d3d10: Add argument check to ID3D10Effect::GetTechniqueByName().
[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         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         /* catch errors and report them */
1403         if (!lastExtent && (justifiedWidth != areaWidth))
1404         {
1405             memset(error[nErrors].extent, 0, 100);
1406             memcpy(error[nErrors].extent, pFirstChar, pLastChar - pFirstChar);
1407             error[nErrors].GetTextExtentExPointWWidth = justifiedWidth;
1408             nErrors++;
1409         }
1410
1411         y += size.cy;
1412         str = pLastChar;
1413     } while (*str && y < clientArea->bottom);
1414
1415     for (e = 0; e < nErrors; e++)
1416     {
1417         /* The width returned by GetTextExtentPoint32() is exactly the same
1418            returned by GetTextExtentExPointW() - see dlls/gdi32/font.c */
1419         ok(error[e].GetTextExtentExPointWWidth == areaWidth,
1420             "GetTextExtentPointW() for \"%s\" should have returned a width of %d, not %d.\n",
1421             error[e].extent, areaWidth, error[e].GetTextExtentExPointWWidth);
1422     }
1423 }
1424
1425 static void test_SetTextJustification(void)
1426 {
1427     HDC hdc;
1428     RECT clientArea;
1429     LOGFONTA lf;
1430     HFONT hfont;
1431     HWND hwnd;
1432     static char testText[] =
1433             "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
1434             "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
1435             "enim ad minim veniam, quis nostrud exercitation ullamco laboris "
1436             "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in "
1437             "reprehenderit in voluptate velit esse cillum dolore eu fugiat "
1438             "nulla pariatur. Excepteur sint occaecat cupidatat non proident, "
1439             "sunt in culpa qui officia deserunt mollit anim id est laborum.";
1440
1441     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0, 400,400, 0, 0, 0, NULL);
1442     GetClientRect( hwnd, &clientArea );
1443     hdc = GetDC( hwnd );
1444
1445     memset(&lf, 0, sizeof lf);
1446     lf.lfCharSet = ANSI_CHARSET;
1447     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1448     lf.lfWeight = FW_DONTCARE;
1449     lf.lfHeight = 20;
1450     lf.lfQuality = DEFAULT_QUALITY;
1451     lstrcpyA(lf.lfFaceName, "Times New Roman");
1452     hfont = create_font("Times New Roman", &lf);
1453     SelectObject(hdc, hfont);
1454
1455     testJustification(hdc, testText, &clientArea);
1456
1457     DeleteObject(hfont);
1458     ReleaseDC(hwnd, hdc);
1459     DestroyWindow(hwnd);
1460 }
1461
1462 static BOOL get_glyph_indices(INT charset, UINT code_page, WORD *idx, UINT count, BOOL unicode)
1463 {
1464     HDC hdc;
1465     LOGFONTA lf;
1466     HFONT hfont, hfont_old;
1467     CHARSETINFO csi;
1468     FONTSIGNATURE fs;
1469     INT cs;
1470     DWORD i, ret;
1471     char name[64];
1472
1473     assert(count <= 128);
1474
1475     memset(&lf, 0, sizeof(lf));
1476
1477     lf.lfCharSet = charset;
1478     lf.lfHeight = 10;
1479     lstrcpyA(lf.lfFaceName, "Arial");
1480     SetLastError(0xdeadbeef);
1481     hfont = CreateFontIndirectA(&lf);
1482     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
1483
1484     hdc = GetDC(0);
1485     hfont_old = SelectObject(hdc, hfont);
1486
1487     cs = GetTextCharsetInfo(hdc, &fs, 0);
1488     ok(cs == charset, "expected %d, got %d\n", charset, cs);
1489
1490     SetLastError(0xdeadbeef);
1491     ret = GetTextFaceA(hdc, sizeof(name), name);
1492     ok(ret, "GetTextFaceA error %u\n", GetLastError());
1493
1494     if (charset == SYMBOL_CHARSET)
1495     {
1496         ok(strcmp("Arial", name), "face name should NOT be Arial\n");
1497         ok(fs.fsCsb[0] & (1 << 31), "symbol encoding should be available\n");
1498     }
1499     else
1500     {
1501         ok(!strcmp("Arial", name), "face name should be Arial, not %s\n", name);
1502         ok(!(fs.fsCsb[0] & (1 << 31)), "symbol encoding should NOT be available\n");
1503     }
1504
1505     if (!TranslateCharsetInfo((DWORD *)(INT_PTR)cs, &csi, TCI_SRCCHARSET))
1506     {
1507         trace("Can't find codepage for charset %d\n", cs);
1508         ReleaseDC(0, hdc);
1509         return FALSE;
1510     }
1511     ok(csi.ciACP == code_page, "expected %d, got %d\n", code_page, csi.ciACP);
1512
1513     if (unicode)
1514     {
1515         char ansi_buf[128];
1516         WCHAR unicode_buf[128];
1517
1518         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
1519
1520         MultiByteToWideChar(code_page, 0, ansi_buf, count, unicode_buf, count);
1521
1522         SetLastError(0xdeadbeef);
1523         ret = pGetGlyphIndicesW(hdc, unicode_buf, count, idx, 0);
1524         ok(ret == count, "GetGlyphIndicesW error %u\n", GetLastError());
1525     }
1526     else
1527     {
1528         char ansi_buf[128];
1529
1530         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
1531
1532         SetLastError(0xdeadbeef);
1533         ret = pGetGlyphIndicesA(hdc, ansi_buf, count, idx, 0);
1534         ok(ret == count, "GetGlyphIndicesA error %u\n", GetLastError());
1535     }
1536
1537     SelectObject(hdc, hfont_old);
1538     DeleteObject(hfont);
1539
1540     ReleaseDC(0, hdc);
1541
1542     return TRUE;
1543 }
1544
1545 static void test_font_charset(void)
1546 {
1547     static struct charset_data
1548     {
1549         INT charset;
1550         UINT code_page;
1551         WORD font_idxA[128], font_idxW[128];
1552     } cd[] =
1553     {
1554         { ANSI_CHARSET, 1252 },
1555         { RUSSIAN_CHARSET, 1251 },
1556         { SYMBOL_CHARSET, CP_SYMBOL } /* keep it as the last one */
1557     };
1558     int i;
1559
1560     if (!pGetGlyphIndicesA || !pGetGlyphIndicesW)
1561     {
1562         win_skip("Skipping the font charset test on a Win9x platform\n");
1563         return;
1564     }
1565
1566     if (!is_font_installed("Arial"))
1567     {
1568         skip("Arial is not installed\n");
1569         return;
1570     }
1571
1572     for (i = 0; i < sizeof(cd)/sizeof(cd[0]); i++)
1573     {
1574         if (cd[i].charset == SYMBOL_CHARSET)
1575         {
1576             if (!is_font_installed("Symbol") && !is_font_installed("Wingdings"))
1577             {
1578                 skip("Symbol or Wingdings is not installed\n");
1579                 break;
1580             }
1581         }
1582         get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxA, 128, FALSE);
1583         get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxW, 128, TRUE);
1584         ok(!memcmp(cd[i].font_idxA, cd[i].font_idxW, 128*sizeof(WORD)), "%d: indices don't match\n", i);
1585     }
1586
1587     ok(memcmp(cd[0].font_idxW, cd[1].font_idxW, 128*sizeof(WORD)), "0 vs 1: indices shouldn't match\n");
1588     if (i > 2)
1589     {
1590         ok(memcmp(cd[0].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "0 vs 2: indices shouldn't match\n");
1591         ok(memcmp(cd[1].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "1 vs 2: indices shouldn't match\n");
1592     }
1593     else
1594         skip("Symbol or Wingdings is not installed\n");
1595 }
1596
1597 static void test_GetFontUnicodeRanges(void)
1598 {
1599     LOGFONTA lf;
1600     HDC hdc;
1601     HFONT hfont, hfont_old;
1602     DWORD size;
1603     GLYPHSET *gs;
1604
1605     if (!pGetFontUnicodeRanges)
1606     {
1607         win_skip("GetFontUnicodeRanges not available before W2K\n");
1608         return;
1609     }
1610
1611     memset(&lf, 0, sizeof(lf));
1612     lstrcpyA(lf.lfFaceName, "Arial");
1613     hfont = create_font("Arial", &lf);
1614
1615     hdc = GetDC(0);
1616     hfont_old = SelectObject(hdc, hfont);
1617
1618     size = pGetFontUnicodeRanges(NULL, NULL);
1619     ok(!size, "GetFontUnicodeRanges succeeded unexpectedly\n");
1620
1621     size = pGetFontUnicodeRanges(hdc, NULL);
1622     ok(size, "GetFontUnicodeRanges failed unexpectedly\n");
1623
1624     gs = HeapAlloc(GetProcessHeap(), 0, size);
1625
1626     size = pGetFontUnicodeRanges(hdc, gs);
1627     ok(size, "GetFontUnicodeRanges failed\n");
1628 #if 0
1629     for (i = 0; i < gs->cRanges; i++)
1630         trace("%03d wcLow %04x cGlyphs %u\n", i, gs->ranges[i].wcLow, gs->ranges[i].cGlyphs);
1631 #endif
1632     trace("found %u ranges\n", gs->cRanges);
1633
1634     HeapFree(GetProcessHeap(), 0, gs);
1635
1636     SelectObject(hdc, hfont_old);
1637     DeleteObject(hfont);
1638     ReleaseDC(NULL, hdc);
1639 }
1640
1641 #define MAX_ENUM_FONTS 4096
1642
1643 struct enum_font_data
1644 {
1645     int total;
1646     LOGFONT lf[MAX_ENUM_FONTS];
1647 };
1648
1649 struct enum_font_dataW
1650 {
1651     int total;
1652     LOGFONTW lf[MAX_ENUM_FONTS];
1653 };
1654
1655 static INT CALLBACK arial_enum_proc(const LOGFONT *lf, const TEXTMETRIC *tm, DWORD type, LPARAM lParam)
1656 {
1657     struct enum_font_data *efd = (struct enum_font_data *)lParam;
1658
1659     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
1660
1661     if (type != TRUETYPE_FONTTYPE) return 1;
1662 #if 0
1663     trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
1664           lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
1665 #endif
1666     if (efd->total < MAX_ENUM_FONTS)
1667         efd->lf[efd->total++] = *lf;
1668     else
1669         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
1670
1671     return 1;
1672 }
1673
1674 static INT CALLBACK arial_enum_procw(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
1675 {
1676     struct enum_font_dataW *efd = (struct enum_font_dataW *)lParam;
1677
1678     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
1679
1680     if (type != TRUETYPE_FONTTYPE) return 1;
1681 #if 0
1682     trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
1683           lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
1684 #endif
1685     if (efd->total < MAX_ENUM_FONTS)
1686         efd->lf[efd->total++] = *lf;
1687     else
1688         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
1689
1690     return 1;
1691 }
1692
1693 static void get_charset_stats(struct enum_font_data *efd,
1694                               int *ansi_charset, int *symbol_charset,
1695                               int *russian_charset)
1696 {
1697     int i;
1698
1699     *ansi_charset = 0;
1700     *symbol_charset = 0;
1701     *russian_charset = 0;
1702
1703     for (i = 0; i < efd->total; i++)
1704     {
1705         switch (efd->lf[i].lfCharSet)
1706         {
1707         case ANSI_CHARSET:
1708             (*ansi_charset)++;
1709             break;
1710         case SYMBOL_CHARSET:
1711             (*symbol_charset)++;
1712             break;
1713         case RUSSIAN_CHARSET:
1714             (*russian_charset)++;
1715             break;
1716         }
1717     }
1718 }
1719
1720 static void get_charset_statsW(struct enum_font_dataW *efd,
1721                               int *ansi_charset, int *symbol_charset,
1722                               int *russian_charset)
1723 {
1724     int i;
1725
1726     *ansi_charset = 0;
1727     *symbol_charset = 0;
1728     *russian_charset = 0;
1729
1730     for (i = 0; i < efd->total; i++)
1731     {
1732         switch (efd->lf[i].lfCharSet)
1733         {
1734         case ANSI_CHARSET:
1735             (*ansi_charset)++;
1736             break;
1737         case SYMBOL_CHARSET:
1738             (*symbol_charset)++;
1739             break;
1740         case RUSSIAN_CHARSET:
1741             (*russian_charset)++;
1742             break;
1743         }
1744     }
1745 }
1746
1747 static void test_EnumFontFamilies(const char *font_name, INT font_charset)
1748 {
1749     struct enum_font_data efd;
1750     struct enum_font_dataW efdw;
1751     LOGFONT lf;
1752     HDC hdc;
1753     int i, ret, ansi_charset, symbol_charset, russian_charset;
1754
1755     trace("Testing font %s, charset %d\n", *font_name ? font_name : "<empty>", font_charset);
1756
1757     if (*font_name && !is_truetype_font_installed(font_name))
1758     {
1759         skip("%s is not installed\n", font_name);
1760         return;
1761     }
1762
1763     hdc = GetDC(0);
1764
1765     /* Observed behaviour: EnumFontFamilies enumerates aliases like "Arial Cyr"
1766      * while EnumFontFamiliesEx doesn't.
1767      */
1768     if (!*font_name && font_charset == DEFAULT_CHARSET) /* do it only once */
1769     {
1770         /*
1771          * Use EnumFontFamiliesW since win98 crashes when the
1772          *    second parameter is NULL using EnumFontFamilies
1773          */
1774         efdw.total = 0;
1775         SetLastError(0xdeadbeef);
1776         ret = EnumFontFamiliesW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw);
1777         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesW error %u\n", GetLastError());
1778         if(ret)
1779         {
1780             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
1781             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
1782                   ansi_charset, symbol_charset, russian_charset);
1783             ok(efdw.total > 0, "fonts enumerated: NULL\n");
1784             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
1785             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
1786             ok(russian_charset > 0 ||
1787                broken(russian_charset == 0), /* NT4 */
1788                "NULL family should enumerate RUSSIAN_CHARSET\n");
1789         }
1790
1791         efdw.total = 0;
1792         SetLastError(0xdeadbeef);
1793         ret = EnumFontFamiliesExW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw, 0);
1794         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesExW error %u\n", GetLastError());
1795         if(ret)
1796         {
1797             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
1798             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
1799                   ansi_charset, symbol_charset, russian_charset);
1800             ok(efdw.total > 0, "fonts enumerated: NULL\n");
1801             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
1802             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
1803             ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
1804         }
1805     }
1806
1807     efd.total = 0;
1808     SetLastError(0xdeadbeef);
1809     ret = EnumFontFamilies(hdc, font_name, arial_enum_proc, (LPARAM)&efd);
1810     ok(ret, "EnumFontFamilies error %u\n", GetLastError());
1811     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1812     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s\n",
1813           ansi_charset, symbol_charset, russian_charset,
1814           *font_name ? font_name : "<empty>");
1815     if (*font_name)
1816         ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
1817     else
1818         ok(!efd.total, "no fonts should be enumerated for empty font_name\n");
1819     for (i = 0; i < efd.total; i++)
1820     {
1821 /* FIXME: remove completely once Wine is fixed */
1822 if (efd.lf[i].lfCharSet != font_charset)
1823 {
1824 todo_wine
1825     ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1826 }
1827 else
1828         ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1829         ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1830            font_name, efd.lf[i].lfFaceName);
1831     }
1832
1833     memset(&lf, 0, sizeof(lf));
1834     lf.lfCharSet = ANSI_CHARSET;
1835     lstrcpy(lf.lfFaceName, font_name);
1836     efd.total = 0;
1837     SetLastError(0xdeadbeef);
1838     ret = EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
1839     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
1840     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1841     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s ANSI_CHARSET\n",
1842           ansi_charset, symbol_charset, russian_charset,
1843           *font_name ? font_name : "<empty>");
1844     if (font_charset == SYMBOL_CHARSET)
1845     {
1846         if (*font_name)
1847             ok(efd.total == 0, "no fonts should be enumerated: %s ANSI_CHARSET\n", font_name);
1848         else
1849             ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
1850     }
1851     else
1852     {
1853         ok(efd.total > 0, "no fonts enumerated: %s ANSI_CHARSET\n", font_name);
1854         for (i = 0; i < efd.total; i++)
1855         {
1856             ok(efd.lf[i].lfCharSet == ANSI_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1857             if (*font_name)
1858                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1859                    font_name, efd.lf[i].lfFaceName);
1860         }
1861     }
1862
1863     /* DEFAULT_CHARSET should enumerate all available charsets */
1864     memset(&lf, 0, sizeof(lf));
1865     lf.lfCharSet = DEFAULT_CHARSET;
1866     lstrcpy(lf.lfFaceName, font_name);
1867     efd.total = 0;
1868     SetLastError(0xdeadbeef);
1869     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
1870     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
1871     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1872     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s DEFAULT_CHARSET\n",
1873           ansi_charset, symbol_charset, russian_charset,
1874           *font_name ? font_name : "<empty>");
1875     ok(efd.total > 0, "no fonts enumerated: %s DEFAULT_CHARSET\n", font_name);
1876     for (i = 0; i < efd.total; i++)
1877     {
1878         if (*font_name)
1879             ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1880                font_name, efd.lf[i].lfFaceName);
1881     }
1882     if (*font_name)
1883     {
1884         switch (font_charset)
1885         {
1886         case ANSI_CHARSET:
1887             ok(ansi_charset > 0,
1888                "ANSI_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
1889             ok(!symbol_charset,
1890                "ANSI_CHARSET should NOT enumerate SYMBOL_CHARSET for %s\n", font_name);
1891             ok(russian_charset > 0,
1892                "ANSI_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
1893             break;
1894         case SYMBOL_CHARSET:
1895             ok(!ansi_charset,
1896                "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", font_name);
1897             ok(symbol_charset,
1898                "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
1899             ok(!russian_charset,
1900                "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", font_name);
1901             break;
1902         case DEFAULT_CHARSET:
1903             ok(ansi_charset > 0,
1904                "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
1905             ok(symbol_charset > 0,
1906                "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
1907             ok(russian_charset > 0,
1908                "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
1909             break;
1910         }
1911     }
1912     else
1913     {
1914         ok(ansi_charset > 0,
1915            "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1916         ok(symbol_charset > 0,
1917            "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1918         ok(russian_charset > 0,
1919            "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1920     }
1921
1922     memset(&lf, 0, sizeof(lf));
1923     lf.lfCharSet = SYMBOL_CHARSET;
1924     lstrcpy(lf.lfFaceName, font_name);
1925     efd.total = 0;
1926     SetLastError(0xdeadbeef);
1927     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
1928     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
1929     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1930     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s SYMBOL_CHARSET\n",
1931           ansi_charset, symbol_charset, russian_charset,
1932           *font_name ? font_name : "<empty>");
1933     if (*font_name && font_charset == ANSI_CHARSET)
1934         ok(efd.total == 0, "no fonts should be enumerated: %s SYMBOL_CHARSET\n", font_name);
1935     else
1936     {
1937         ok(efd.total > 0, "no fonts enumerated: %s SYMBOL_CHARSET\n", font_name);
1938         for (i = 0; i < efd.total; i++)
1939         {
1940             ok(efd.lf[i].lfCharSet == SYMBOL_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1941             if (*font_name)
1942                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1943                    font_name, efd.lf[i].lfFaceName);
1944         }
1945
1946         ok(!ansi_charset,
1947            "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1948         ok(symbol_charset > 0,
1949            "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1950         ok(!russian_charset,
1951            "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1952     }
1953
1954     ReleaseDC(0, hdc);
1955 }
1956
1957 static void test_negative_width(HDC hdc, const LOGFONTA *lf)
1958 {
1959     HFONT hfont, hfont_prev;
1960     DWORD ret;
1961     GLYPHMETRICS gm1, gm2;
1962     LOGFONTA lf2 = *lf;
1963     WORD idx;
1964     MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
1965
1966     if(!pGetGlyphIndicesA)
1967         return;
1968
1969     /* negative widths are handled just as positive ones */
1970     lf2.lfWidth = -lf->lfWidth;
1971
1972     SetLastError(0xdeadbeef);
1973     hfont = CreateFontIndirectA(lf);
1974     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
1975     check_font("original", lf, hfont);
1976
1977     hfont_prev = SelectObject(hdc, hfont);
1978
1979     ret = pGetGlyphIndicesA(hdc, "x", 1, &idx, GGI_MARK_NONEXISTING_GLYPHS);
1980     if (ret == GDI_ERROR || idx == 0xffff)
1981     {
1982         SelectObject(hdc, hfont_prev);
1983         DeleteObject(hfont);
1984         skip("Font %s doesn't contain 'x', skipping the test\n", lf->lfFaceName);
1985         return;
1986     }
1987
1988     /* filling with 0xaa causes false pass under WINEDEBUG=warn+heap */
1989     memset(&gm1, 0xab, sizeof(gm1));
1990     SetLastError(0xdeadbeef);
1991     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm1, 0, NULL, &mat);
1992     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
1993
1994     SelectObject(hdc, hfont_prev);
1995     DeleteObject(hfont);
1996
1997     SetLastError(0xdeadbeef);
1998     hfont = CreateFontIndirectA(&lf2);
1999     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2000     check_font("negative width", &lf2, hfont);
2001
2002     hfont_prev = SelectObject(hdc, hfont);
2003
2004     memset(&gm2, 0xbb, sizeof(gm2));
2005     SetLastError(0xdeadbeef);
2006     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm2, 0, NULL, &mat);
2007     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
2008
2009     SelectObject(hdc, hfont_prev);
2010     DeleteObject(hfont);
2011
2012     ok(gm1.gmBlackBoxX == gm2.gmBlackBoxX &&
2013        gm1.gmBlackBoxY == gm2.gmBlackBoxY &&
2014        gm1.gmptGlyphOrigin.x == gm2.gmptGlyphOrigin.x &&
2015        gm1.gmptGlyphOrigin.y == gm2.gmptGlyphOrigin.y &&
2016        gm1.gmCellIncX == gm2.gmCellIncX &&
2017        gm1.gmCellIncY == gm2.gmCellIncY,
2018        "gm1=%d,%d,%d,%d,%d,%d gm2=%d,%d,%d,%d,%d,%d\n",
2019        gm1.gmBlackBoxX, gm1.gmBlackBoxY, gm1.gmptGlyphOrigin.x,
2020        gm1.gmptGlyphOrigin.y, gm1.gmCellIncX, gm1.gmCellIncY,
2021        gm2.gmBlackBoxX, gm2.gmBlackBoxY, gm2.gmptGlyphOrigin.x,
2022        gm2.gmptGlyphOrigin.y, gm2.gmCellIncX, gm2.gmCellIncY);
2023 }
2024
2025 /* PANOSE is 10 bytes in size, need to pack the structure properly */
2026 #include "pshpack2.h"
2027 typedef struct
2028 {
2029     USHORT version;
2030     SHORT xAvgCharWidth;
2031     USHORT usWeightClass;
2032     USHORT usWidthClass;
2033     SHORT fsType;
2034     SHORT ySubscriptXSize;
2035     SHORT ySubscriptYSize;
2036     SHORT ySubscriptXOffset;
2037     SHORT ySubscriptYOffset;
2038     SHORT ySuperscriptXSize;
2039     SHORT ySuperscriptYSize;
2040     SHORT ySuperscriptXOffset;
2041     SHORT ySuperscriptYOffset;
2042     SHORT yStrikeoutSize;
2043     SHORT yStrikeoutPosition;
2044     SHORT sFamilyClass;
2045     PANOSE panose;
2046     ULONG ulUnicodeRange1;
2047     ULONG ulUnicodeRange2;
2048     ULONG ulUnicodeRange3;
2049     ULONG ulUnicodeRange4;
2050     CHAR achVendID[4];
2051     USHORT fsSelection;
2052     USHORT usFirstCharIndex;
2053     USHORT usLastCharIndex;
2054     /* According to the Apple spec, original version didn't have the below fields,
2055      * version numbers were taked from the OpenType spec.
2056      */
2057     /* version 0 (TrueType 1.5) */
2058     USHORT sTypoAscender;
2059     USHORT sTypoDescender;
2060     USHORT sTypoLineGap;
2061     USHORT usWinAscent;
2062     USHORT usWinDescent;
2063     /* version 1 (TrueType 1.66) */
2064     ULONG ulCodePageRange1;
2065     ULONG ulCodePageRange2;
2066     /* version 2 (OpenType 1.2) */
2067     SHORT sxHeight;
2068     SHORT sCapHeight;
2069     USHORT usDefaultChar;
2070     USHORT usBreakChar;
2071     USHORT usMaxContext;
2072 } TT_OS2_V2;
2073 #include "poppack.h"
2074
2075 #ifdef WORDS_BIGENDIAN
2076 #define GET_BE_WORD(x) (x)
2077 #define GET_BE_DWORD(x) (x)
2078 #else
2079 #define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
2080 #define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
2081 #endif
2082
2083 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
2084                     ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
2085                     ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
2086 #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
2087 #define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
2088
2089 typedef struct
2090 {
2091     USHORT version;
2092     USHORT num_tables;
2093 } cmap_header;
2094
2095 typedef struct
2096 {
2097     USHORT plat_id;
2098     USHORT enc_id;
2099     ULONG offset;
2100 } cmap_encoding_record;
2101
2102 typedef struct
2103 {
2104     USHORT format;
2105     USHORT length;
2106     USHORT language;
2107
2108     BYTE glyph_ids[256];
2109 } cmap_format_0;
2110
2111 typedef struct
2112 {
2113     USHORT format;
2114     USHORT length;
2115     USHORT language;
2116
2117     USHORT seg_countx2;
2118     USHORT search_range;
2119     USHORT entry_selector;
2120     USHORT range_shift;
2121
2122     USHORT end_count[1]; /* this is a variable-sized array of length seg_countx2 / 2 */
2123 /* Then follows:
2124     USHORT pad;
2125     USHORT start_count[seg_countx2 / 2];
2126     USHORT id_delta[seg_countx2 / 2];
2127     USHORT id_range_offset[seg_countx2 / 2];
2128     USHORT glyph_ids[];
2129 */
2130 } cmap_format_4;
2131
2132 typedef struct
2133 {
2134     USHORT end_count;
2135     USHORT start_count;
2136     USHORT id_delta;
2137     USHORT id_range_offset;
2138 } cmap_format_4_seg;
2139
2140 static void expect_ff(const TEXTMETRICA *tmA, const TT_OS2_V2 *os2, WORD family, const char *name)
2141 {
2142     ok((tmA->tmPitchAndFamily & 0xf0) == family, "%s: expected family %02x got %02x. panose %d-%d-%d-%d-...\n",
2143        name, family, tmA->tmPitchAndFamily, os2->panose.bFamilyType, os2->panose.bSerifStyle,
2144        os2->panose.bWeight, os2->panose.bProportion);
2145 }
2146
2147 static BOOL get_first_last_from_cmap0(void *ptr, DWORD *first, DWORD *last)
2148 {
2149     int i;
2150     cmap_format_0 *cmap = (cmap_format_0*)ptr;
2151
2152     *first = 256;
2153
2154     for(i = 0; i < 256; i++)
2155     {
2156         if(cmap->glyph_ids[i] == 0) continue;
2157         *last = i;
2158         if(*first == 256) *first = i;
2159     }
2160     if(*first == 256) return FALSE;
2161     return TRUE;
2162 }
2163
2164 static void get_seg4(cmap_format_4 *cmap, USHORT seg_num, cmap_format_4_seg *seg)
2165 {
2166     USHORT segs = GET_BE_WORD(cmap->seg_countx2) / 2;
2167     seg->end_count = GET_BE_WORD(cmap->end_count[seg_num]);
2168     seg->start_count = GET_BE_WORD(cmap->end_count[segs + 1 + seg_num]);
2169     seg->id_delta = GET_BE_WORD(cmap->end_count[2 * segs + 1 + seg_num]);
2170     seg->id_range_offset = GET_BE_WORD(cmap->end_count[3 * segs + 1 + seg_num]);
2171 }
2172
2173 static BOOL get_first_last_from_cmap4(void *ptr, DWORD *first, DWORD *last, DWORD limit)
2174 {
2175     int i;
2176     cmap_format_4 *cmap = (cmap_format_4*)ptr;
2177     USHORT seg_count = GET_BE_WORD(cmap->seg_countx2) / 2;
2178     USHORT const *glyph_ids = cmap->end_count + 4 * seg_count + 1;
2179
2180     *first = 0x10000;
2181
2182     for(i = 0; i < seg_count; i++)
2183     {
2184         DWORD code, index;
2185         cmap_format_4_seg seg;
2186
2187         get_seg4(cmap, i, &seg);
2188         for(code = seg.start_count; code <= seg.end_count; code++)
2189         {
2190             if(seg.id_range_offset == 0)
2191                 index = (seg.id_delta + code) & 0xffff;
2192             else
2193             {
2194                 index = seg.id_range_offset / 2
2195                     + code - seg.start_count
2196                     + i - seg_count;
2197
2198                 /* some fonts have broken last segment */
2199                 if ((char *)(glyph_ids + index + sizeof(*glyph_ids)) < (char *)ptr + limit)
2200                     index = GET_BE_WORD(glyph_ids[index]);
2201                 else
2202                 {
2203                     trace("segment %04x/%04x index %04x points to nowhere\n",
2204                           seg.start_count, seg.end_count, index);
2205                     index = 0;
2206                 }
2207                 if(index) index += seg.id_delta;
2208             }
2209             if(*first == 0x10000)
2210                 *last = *first = code;
2211             else if(index)
2212                 *last = code;
2213         }
2214     }
2215
2216     if(*first == 0x10000) return FALSE;
2217     return TRUE;
2218 }
2219
2220 static void *get_cmap(cmap_header *header, USHORT plat_id, USHORT enc_id)
2221 {
2222     USHORT i;
2223     cmap_encoding_record *record = (cmap_encoding_record *)(header + 1);
2224
2225     for(i = 0; i < GET_BE_WORD(header->num_tables); i++)
2226     {
2227         if(GET_BE_WORD(record->plat_id) == plat_id && GET_BE_WORD(record->enc_id) == enc_id)
2228             return (BYTE *)header + GET_BE_DWORD(record->offset);
2229         record++;
2230     }
2231     return NULL;
2232 }
2233
2234 typedef enum
2235 {
2236     cmap_none,
2237     cmap_ms_unicode,
2238     cmap_ms_symbol
2239 } cmap_type;
2240
2241 static BOOL get_first_last_from_cmap(HDC hdc, DWORD *first, DWORD *last, cmap_type *cmap_type)
2242 {
2243     LONG size, ret;
2244     cmap_header *header;
2245     void *cmap;
2246     BOOL r = FALSE;
2247     WORD format;
2248
2249     size = GetFontData(hdc, MS_CMAP_TAG, 0, NULL, 0);
2250     ok(size != GDI_ERROR, "no cmap table found\n");
2251     if(size == GDI_ERROR) return FALSE;
2252
2253     header = HeapAlloc(GetProcessHeap(), 0, size);
2254     ret = GetFontData(hdc, MS_CMAP_TAG, 0, header, size);
2255     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2256     ok(GET_BE_WORD(header->version) == 0, "got cmap version %d\n", GET_BE_WORD(header->version));
2257
2258     cmap = get_cmap(header, 3, 1);
2259     if(cmap)
2260         *cmap_type = cmap_ms_unicode;
2261     else
2262     {
2263         cmap = get_cmap(header, 3, 0);
2264         if(cmap) *cmap_type = cmap_ms_symbol;
2265     }
2266     if(!cmap)
2267     {
2268         *cmap_type = cmap_none;
2269         goto end;
2270     }
2271
2272     format = GET_BE_WORD(*(WORD *)cmap);
2273     switch(format)
2274     {
2275     case 0:
2276         r = get_first_last_from_cmap0(cmap, first, last);
2277         break;
2278     case 4:
2279         r = get_first_last_from_cmap4(cmap, first, last, size);
2280         break;
2281     default:
2282         trace("unhandled cmap format %d\n", format);
2283         break;
2284     }
2285
2286 end:
2287     HeapFree(GetProcessHeap(), 0, header);
2288     return r;
2289 }
2290
2291 static void test_text_metrics(const LOGFONTA *lf)
2292 {
2293     HDC hdc;
2294     HFONT hfont, hfont_old;
2295     TEXTMETRICA tmA;
2296     TT_OS2_V2 tt_os2;
2297     LONG size, ret;
2298     const char *font_name = lf->lfFaceName;
2299     DWORD cmap_first = 0, cmap_last = 0;
2300     cmap_type cmap_type;
2301
2302     hdc = GetDC(0);
2303
2304     SetLastError(0xdeadbeef);
2305     hfont = CreateFontIndirectA(lf);
2306     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2307
2308     hfont_old = SelectObject(hdc, hfont);
2309
2310     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
2311     if (size == GDI_ERROR)
2312     {
2313         trace("OS/2 chunk was not found\n");
2314         goto end_of_test;
2315     }
2316     if (size > sizeof(tt_os2))
2317     {
2318         trace("got too large OS/2 chunk of size %u\n", size);
2319         size = sizeof(tt_os2);
2320     }
2321
2322     memset(&tt_os2, 0, sizeof(tt_os2));
2323     ret = GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size);
2324     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2325
2326     SetLastError(0xdeadbeef);
2327     ret = GetTextMetricsA(hdc, &tmA);
2328     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
2329
2330     if(!get_first_last_from_cmap(hdc, &cmap_first, &cmap_last, &cmap_type))
2331     {
2332         skip("Unable to retrieve first and last glyphs from cmap\n");
2333     }
2334     else
2335     {
2336         USHORT expect_first_A, expect_last_A, expect_break_A, expect_default_A;
2337         USHORT expect_first_W, expect_last_W, expect_break_W, expect_default_W;
2338         UINT os2_first_char, os2_last_char, default_char, break_char;
2339         USHORT version;
2340         TEXTMETRICW tmW;
2341
2342         version = GET_BE_WORD(tt_os2.version);
2343
2344         os2_first_char = GET_BE_WORD(tt_os2.usFirstCharIndex);
2345         os2_last_char = GET_BE_WORD(tt_os2.usLastCharIndex);
2346         default_char = GET_BE_WORD(tt_os2.usDefaultChar);
2347         break_char = GET_BE_WORD(tt_os2.usBreakChar);
2348
2349         trace("font %s charset %u: %x-%x (%x-%x) default %x break %x OS/2 version %u vendor %4.4s\n",
2350               font_name, lf->lfCharSet, os2_first_char, os2_last_char, cmap_first, cmap_last,
2351               default_char, break_char, version, (LPCSTR)&tt_os2.achVendID);
2352
2353         if (cmap_type == cmap_ms_symbol || (cmap_first >= 0xf000 && cmap_first < 0xf100))
2354         {
2355             expect_first_W    = 0;
2356             switch(GetACP())
2357             {
2358             case 1257:  /* Baltic */
2359                 expect_last_W = 0xf8fd;
2360                 break;
2361             default:
2362                 expect_last_W = 0xf0ff;
2363             }
2364             expect_break_W    = 0x20;
2365             expect_default_W  = expect_break_W - 1;
2366             expect_first_A    = 0x1e;
2367             expect_last_A     = min(os2_last_char - os2_first_char + 0x20, 0xff);
2368         }
2369         else
2370         {
2371             expect_first_W    = cmap_first;
2372             expect_last_W     = min(cmap_last, os2_last_char);
2373             if(os2_first_char <= 1)
2374                 expect_break_W = os2_first_char + 2;
2375             else if(os2_first_char > 0xff)
2376                 expect_break_W = 0x20;
2377             else
2378                 expect_break_W = os2_first_char;
2379             expect_default_W  = expect_break_W - 1;
2380             expect_first_A    = expect_default_W - 1;
2381             expect_last_A     = min(expect_last_W, 0xff);
2382         }
2383         expect_break_A    = expect_break_W;
2384         expect_default_A  = expect_default_W;
2385
2386         /* Wine currently uses SYMBOL_CHARSET to identify whether the ANSI metrics need special handling */
2387         if(cmap_type != cmap_ms_symbol && tmA.tmCharSet == SYMBOL_CHARSET && expect_first_A != 0x1e)
2388             todo_wine ok(tmA.tmFirstChar == expect_first_A ||
2389                          tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2390                          "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2391         else
2392             ok(tmA.tmFirstChar == expect_first_A ||
2393                tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2394                "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2395         ok(tmA.tmLastChar == expect_last_A ||
2396            tmA.tmLastChar == 0xff /* win9x */,
2397            "A: tmLastChar for %s got %02x expected %02x\n", font_name, tmA.tmLastChar, expect_last_A);
2398         ok(tmA.tmBreakChar == expect_break_A, "A: tmBreakChar for %s got %02x expected %02x\n",
2399            font_name, tmA.tmBreakChar, expect_break_A);
2400         ok(tmA.tmDefaultChar == expect_default_A, "A: tmDefaultChar for %s got %02x expected %02x\n",
2401            font_name, tmA.tmDefaultChar, expect_default_A);
2402
2403
2404         SetLastError(0xdeadbeef);
2405         ret = GetTextMetricsW(hdc, &tmW);
2406         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
2407            "GetTextMetricsW error %u\n", GetLastError());
2408         if (ret)
2409         {
2410             /* Wine uses the os2 first char */
2411             if(cmap_first != os2_first_char && cmap_type != cmap_ms_symbol)
2412                 todo_wine ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2413                              font_name, tmW.tmFirstChar, expect_first_W);
2414             else
2415                 ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2416                    font_name, tmW.tmFirstChar, expect_first_W);
2417
2418             /* Wine uses the os2 last char */
2419             if(expect_last_W != os2_last_char && cmap_type != cmap_ms_symbol)
2420                 todo_wine ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2421                              font_name, tmW.tmLastChar, expect_last_W);
2422             else
2423                 ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2424                    font_name, tmW.tmLastChar, expect_last_W);
2425             ok(tmW.tmBreakChar == expect_break_W, "W: tmBreakChar for %s got %02x expected %02x\n",
2426                font_name, tmW.tmBreakChar, expect_break_W);
2427             ok(tmW.tmDefaultChar == expect_default_W, "W: tmDefaultChar for %s got %02x expected %02x\n",
2428                font_name, tmW.tmDefaultChar, expect_default_W);
2429
2430             /* Test the aspect ratio while we have tmW */
2431             ret = GetDeviceCaps(hdc, LOGPIXELSX);
2432             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectX %u != %u\n",
2433                tmW.tmDigitizedAspectX, ret);
2434             ret = GetDeviceCaps(hdc, LOGPIXELSY);
2435             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectY %u != %u\n",
2436                tmW.tmDigitizedAspectX, ret);
2437         }
2438     }
2439
2440     /* test FF_ values */
2441     switch(tt_os2.panose.bFamilyType)
2442     {
2443     case PAN_ANY:
2444     case PAN_NO_FIT:
2445     case PAN_FAMILY_TEXT_DISPLAY:
2446     case PAN_FAMILY_PICTORIAL:
2447     default:
2448         if((tmA.tmPitchAndFamily & 1) == 0 || /* fixed */
2449            tt_os2.panose.bProportion == PAN_PROP_MONOSPACED)
2450         {
2451             expect_ff(&tmA, &tt_os2, FF_MODERN, font_name);
2452             break;
2453         }
2454         switch(tt_os2.panose.bSerifStyle)
2455         {
2456         case PAN_ANY:
2457         case PAN_NO_FIT:
2458         default:
2459             expect_ff(&tmA, &tt_os2, FF_DONTCARE, font_name);
2460             break;
2461
2462         case PAN_SERIF_COVE:
2463         case PAN_SERIF_OBTUSE_COVE:
2464         case PAN_SERIF_SQUARE_COVE:
2465         case PAN_SERIF_OBTUSE_SQUARE_COVE:
2466         case PAN_SERIF_SQUARE:
2467         case PAN_SERIF_THIN:
2468         case PAN_SERIF_BONE:
2469         case PAN_SERIF_EXAGGERATED:
2470         case PAN_SERIF_TRIANGLE:
2471             expect_ff(&tmA, &tt_os2, FF_ROMAN, font_name);
2472             break;
2473
2474         case PAN_SERIF_NORMAL_SANS:
2475         case PAN_SERIF_OBTUSE_SANS:
2476         case PAN_SERIF_PERP_SANS:
2477         case PAN_SERIF_FLARED:
2478         case PAN_SERIF_ROUNDED:
2479             expect_ff(&tmA, &tt_os2, FF_SWISS, font_name);
2480             break;
2481         }
2482         break;
2483
2484     case PAN_FAMILY_SCRIPT:
2485         expect_ff(&tmA, &tt_os2, FF_SCRIPT, font_name);
2486         break;
2487
2488     case PAN_FAMILY_DECORATIVE:
2489         expect_ff(&tmA, &tt_os2, FF_DECORATIVE, font_name);
2490         break;
2491     }
2492
2493     test_negative_width(hdc, lf);
2494
2495 end_of_test:
2496     SelectObject(hdc, hfont_old);
2497     DeleteObject(hfont);
2498
2499     ReleaseDC(0, hdc);
2500 }
2501
2502 static INT CALLBACK enum_truetype_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
2503 {
2504     INT *enumed = (INT *)lParam;
2505
2506     if (type == TRUETYPE_FONTTYPE)
2507     {
2508         (*enumed)++;
2509         test_text_metrics(lf);
2510     }
2511     return 1;
2512 }
2513
2514 static void test_GetTextMetrics(void)
2515 {
2516     LOGFONTA lf;
2517     HDC hdc;
2518     INT enumed;
2519
2520     /* Report only once */
2521     if(!pGetGlyphIndicesA)
2522         win_skip("GetGlyphIndicesA is unavailable, negative width will not be checked\n");
2523
2524     hdc = GetDC(0);
2525
2526     memset(&lf, 0, sizeof(lf));
2527     lf.lfCharSet = DEFAULT_CHARSET;
2528     enumed = 0;
2529     EnumFontFamiliesExA(hdc, &lf, enum_truetype_font_proc, (LPARAM)&enumed, 0);
2530     trace("Tested metrics of %d truetype fonts\n", enumed);
2531
2532     ReleaseDC(0, hdc);
2533 }
2534
2535 static void test_nonexistent_font(void)
2536 {
2537     static const struct
2538     {
2539         const char *name;
2540         int charset;
2541     } font_subst[] =
2542     {
2543         { "Times New Roman Baltic", 186 },
2544         { "Times New Roman CE", 238 },
2545         { "Times New Roman CYR", 204 },
2546         { "Times New Roman Greek", 161 },
2547         { "Times New Roman TUR", 162 }
2548     };
2549     LOGFONTA lf;
2550     HDC hdc;
2551     HFONT hfont;
2552     CHARSETINFO csi;
2553     INT cs, expected_cs, i;
2554     char buf[LF_FACESIZE];
2555
2556     if (!is_truetype_font_installed("Arial") ||
2557         !is_truetype_font_installed("Times New Roman"))
2558     {
2559         skip("Arial or Times New Roman not installed\n");
2560         return;
2561     }
2562
2563     expected_cs = GetACP();
2564     if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
2565     {
2566         skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
2567         return;
2568     }
2569     expected_cs = csi.ciCharset;
2570     trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
2571
2572     hdc = GetDC(0);
2573
2574     memset(&lf, 0, sizeof(lf));
2575     lf.lfHeight = 100;
2576     lf.lfWeight = FW_REGULAR;
2577     lf.lfCharSet = ANSI_CHARSET;
2578     lf.lfPitchAndFamily = FF_SWISS;
2579     strcpy(lf.lfFaceName, "Nonexistent font");
2580     hfont = CreateFontIndirectA(&lf);
2581     hfont = SelectObject(hdc, hfont);
2582     GetTextFaceA(hdc, sizeof(buf), buf);
2583     ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
2584     cs = GetTextCharset(hdc);
2585     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2586     DeleteObject(SelectObject(hdc, hfont));
2587
2588     memset(&lf, 0, sizeof(lf));
2589     lf.lfHeight = -13;
2590     lf.lfWeight = FW_DONTCARE;
2591     strcpy(lf.lfFaceName, "Nonexistent font");
2592     hfont = CreateFontIndirectA(&lf);
2593     hfont = SelectObject(hdc, hfont);
2594     GetTextFaceA(hdc, sizeof(buf), buf);
2595 todo_wine /* Wine uses Arial for all substitutions */
2596     ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ ||
2597        !lstrcmpiA(buf, "MS Serif") || /* Win9x */
2598        !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
2599        "Got %s\n", buf);
2600     cs = GetTextCharset(hdc);
2601     ok(cs == expected_cs, "expected %d, got %d\n", expected_cs, cs);
2602     DeleteObject(SelectObject(hdc, hfont));
2603
2604     memset(&lf, 0, sizeof(lf));
2605     lf.lfHeight = -13;
2606     lf.lfWeight = FW_REGULAR;
2607     strcpy(lf.lfFaceName, "Nonexistent font");
2608     hfont = CreateFontIndirectA(&lf);
2609     hfont = SelectObject(hdc, hfont);
2610     GetTextFaceA(hdc, sizeof(buf), buf);
2611     ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
2612        !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "Got %s\n", buf);
2613     cs = GetTextCharset(hdc);
2614     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2615     DeleteObject(SelectObject(hdc, hfont));
2616
2617     memset(&lf, 0, sizeof(lf));
2618     lf.lfHeight = -13;
2619     lf.lfWeight = FW_DONTCARE;
2620     strcpy(lf.lfFaceName, "Times New Roman");
2621     hfont = CreateFontIndirectA(&lf);
2622     hfont = SelectObject(hdc, hfont);
2623     GetTextFaceA(hdc, sizeof(buf), buf);
2624     ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf);
2625     cs = GetTextCharset(hdc);
2626     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2627     DeleteObject(SelectObject(hdc, hfont));
2628
2629     for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++)
2630     {
2631         memset(&lf, 0, sizeof(lf));
2632         lf.lfHeight = -13;
2633         lf.lfWeight = FW_REGULAR;
2634         strcpy(lf.lfFaceName, font_subst[i].name);
2635         hfont = CreateFontIndirectA(&lf);
2636         hfont = SelectObject(hdc, hfont);
2637         cs = GetTextCharset(hdc);
2638         if (font_subst[i].charset == expected_cs)
2639         {
2640             ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
2641             GetTextFaceA(hdc, sizeof(buf), buf);
2642             ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf);
2643         }
2644         else
2645         {
2646             ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d for font %s\n", cs, font_subst[i].name);
2647             GetTextFaceA(hdc, sizeof(buf), buf);
2648             ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
2649                !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got %s for font %s\n", buf, font_subst[i].name);
2650         }
2651         DeleteObject(SelectObject(hdc, hfont));
2652
2653         memset(&lf, 0, sizeof(lf));
2654         lf.lfHeight = -13;
2655         lf.lfWeight = FW_DONTCARE;
2656         strcpy(lf.lfFaceName, font_subst[i].name);
2657         hfont = CreateFontIndirectA(&lf);
2658         hfont = SelectObject(hdc, hfont);
2659         GetTextFaceA(hdc, sizeof(buf), buf);
2660         ok(!lstrcmpiA(buf, "Arial") /* Wine */ ||
2661            !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ ||
2662            !lstrcmpiA(buf, "MS Serif") /* Win9x */ ||
2663            !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
2664            "got %s for font %s\n", buf, font_subst[i].name);
2665         cs = GetTextCharset(hdc);
2666         ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
2667         DeleteObject(SelectObject(hdc, hfont));
2668     }
2669
2670     ReleaseDC(0, hdc);
2671 }
2672
2673 static void test_GdiRealizationInfo(void)
2674 {
2675     HDC hdc;
2676     DWORD info[4];
2677     BOOL r;
2678     HFONT hfont, hfont_old;
2679     LOGFONTA lf;
2680
2681     if(!pGdiRealizationInfo)
2682     {
2683         win_skip("GdiRealizationInfo not available\n");
2684         return;
2685     }
2686
2687     hdc = GetDC(0);
2688
2689     memset(info, 0xcc, sizeof(info));
2690     r = pGdiRealizationInfo(hdc, info);
2691     ok(r != 0, "ret 0\n");
2692     ok((info[0] & 0xf) == 1, "info[0] = %x for the system font\n", info[0]);
2693     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
2694
2695     if (!is_truetype_font_installed("Arial"))
2696     {
2697         skip("skipping GdiRealizationInfo with truetype font\n");
2698         goto end;
2699     }
2700
2701     memset(&lf, 0, sizeof(lf));
2702     strcpy(lf.lfFaceName, "Arial");
2703     lf.lfHeight = 20;
2704     lf.lfWeight = FW_NORMAL;
2705     hfont = CreateFontIndirectA(&lf);
2706     hfont_old = SelectObject(hdc, hfont);
2707
2708     memset(info, 0xcc, sizeof(info));
2709     r = pGdiRealizationInfo(hdc, info);
2710     ok(r != 0, "ret 0\n");
2711     ok((info[0] & 0xf) == 3, "info[0] = %x for arial\n", info[0]);
2712     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
2713
2714     DeleteObject(SelectObject(hdc, hfont_old));
2715
2716  end:
2717     ReleaseDC(0, hdc);
2718 }
2719
2720 /* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include
2721    the nul in the count of characters copied when the face name buffer is not
2722    NULL, whereas it does if the buffer is NULL.  Further, the Unicode version
2723    always includes it.  */
2724 static void test_GetTextFace(void)
2725 {
2726     static const char faceA[] = "Tahoma";
2727     static const WCHAR faceW[] = {'T','a','h','o','m','a', 0};
2728     LOGFONTA fA = {0};
2729     LOGFONTW fW = {0};
2730     char bufA[LF_FACESIZE];
2731     WCHAR bufW[LF_FACESIZE];
2732     HFONT f, g;
2733     HDC dc;
2734     int n;
2735
2736     if(!is_font_installed("Tahoma"))
2737     {
2738         skip("Tahoma is not installed so skipping this test\n");
2739         return;
2740     }
2741
2742     /* 'A' case.  */
2743     memcpy(fA.lfFaceName, faceA, sizeof faceA);
2744     f = CreateFontIndirectA(&fA);
2745     ok(f != NULL, "CreateFontIndirectA failed\n");
2746
2747     dc = GetDC(NULL);
2748     g = SelectObject(dc, f);
2749     n = GetTextFaceA(dc, sizeof bufA, bufA);
2750     ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n);
2751     ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n");
2752
2753     /* Play with the count arg.  */
2754     bufA[0] = 'x';
2755     n = GetTextFaceA(dc, 0, bufA);
2756     ok(n == 0, "GetTextFaceA returned %d\n", n);
2757     ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]);
2758
2759     bufA[0] = 'x';
2760     n = GetTextFaceA(dc, 1, bufA);
2761     ok(n == 0, "GetTextFaceA returned %d\n", n);
2762     ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]);
2763
2764     bufA[0] = 'x'; bufA[1] = 'y';
2765     n = GetTextFaceA(dc, 2, bufA);
2766     ok(n == 1, "GetTextFaceA returned %d\n", n);
2767     ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n");
2768
2769     n = GetTextFaceA(dc, 0, NULL);
2770     ok(n == sizeof faceA ||
2771        broken(n == 0), /* win98, winMe */
2772        "GetTextFaceA returned %d\n", n);
2773
2774     DeleteObject(SelectObject(dc, g));
2775     ReleaseDC(NULL, dc);
2776
2777     /* 'W' case.  */
2778     memcpy(fW.lfFaceName, faceW, sizeof faceW);
2779     SetLastError(0xdeadbeef);
2780     f = CreateFontIndirectW(&fW);
2781     if (!f && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2782     {
2783         win_skip("CreateFontIndirectW is not implemented\n");
2784         return;
2785     }
2786     ok(f != NULL, "CreateFontIndirectW failed\n");
2787
2788     dc = GetDC(NULL);
2789     g = SelectObject(dc, f);
2790     n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW);
2791     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
2792     ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
2793
2794     /* Play with the count arg.  */
2795     bufW[0] = 'x';
2796     n = GetTextFaceW(dc, 0, bufW);
2797     ok(n == 0, "GetTextFaceW returned %d\n", n);
2798     ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]);
2799
2800     bufW[0] = 'x';
2801     n = GetTextFaceW(dc, 1, bufW);
2802     ok(n == 1, "GetTextFaceW returned %d\n", n);
2803     ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]);
2804
2805     bufW[0] = 'x'; bufW[1] = 'y';
2806     n = GetTextFaceW(dc, 2, bufW);
2807     ok(n == 2, "GetTextFaceW returned %d\n", n);
2808     ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n");
2809
2810     n = GetTextFaceW(dc, 0, NULL);
2811     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
2812
2813     DeleteObject(SelectObject(dc, g));
2814     ReleaseDC(NULL, dc);
2815 }
2816
2817 static void test_orientation(void)
2818 {
2819     static const char test_str[11] = "Test String";
2820     HDC hdc;
2821     LOGFONTA lf;
2822     HFONT hfont, old_hfont;
2823     SIZE size;
2824
2825     if (!is_truetype_font_installed("Arial"))
2826     {
2827         skip("Arial is not installed\n");
2828         return;
2829     }
2830
2831     hdc = CreateCompatibleDC(0);
2832     memset(&lf, 0, sizeof(lf));
2833     lstrcpyA(lf.lfFaceName, "Arial");
2834     lf.lfHeight = 72;
2835     lf.lfOrientation = lf.lfEscapement = 900;
2836     hfont = create_font("orientation", &lf);
2837     old_hfont = SelectObject(hdc, hfont);
2838     ok(GetTextExtentExPointA(hdc, test_str, sizeof(test_str), 32767, NULL, NULL, &size), "GetTextExtentExPointA failed\n");
2839     ok(near_match(311, size.cx), "cx should be about 311, got %d\n", size.cx);
2840     ok(near_match(75, size.cy), "cy should be about 75, got %d\n", size.cy);
2841     SelectObject(hdc, old_hfont);
2842     DeleteObject(hfont);
2843     DeleteDC(hdc);
2844 }
2845
2846 static void test_oemcharset(void)
2847 {
2848     HDC hdc;
2849     LOGFONTA lf, clf;
2850     HFONT hfont, old_hfont;
2851     int charset;
2852
2853     hdc = CreateCompatibleDC(0);
2854     ZeroMemory(&lf, sizeof(lf));
2855     lf.lfHeight = 12;
2856     lf.lfCharSet = OEM_CHARSET;
2857     lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
2858     lstrcpyA(lf.lfFaceName, "Terminal");
2859     hfont = CreateFontIndirectA(&lf);
2860     old_hfont = SelectObject(hdc, hfont);
2861     charset = GetTextCharset(hdc);
2862 todo_wine
2863     ok(charset == OEM_CHARSET, "expected %d charset, got %d\n", OEM_CHARSET, charset);
2864     hfont = SelectObject(hdc, old_hfont);
2865     GetObjectA(hfont, sizeof(clf), &clf);
2866     ok(!lstrcmpA(clf.lfFaceName, lf.lfFaceName), "expected %s face name, got %s\n", lf.lfFaceName, clf.lfFaceName);
2867     ok(clf.lfPitchAndFamily == lf.lfPitchAndFamily, "expected %x family, got %x\n", lf.lfPitchAndFamily, clf.lfPitchAndFamily);
2868     ok(clf.lfCharSet == lf.lfCharSet, "expected %d charset, got %d\n", lf.lfCharSet, clf.lfCharSet);
2869     ok(clf.lfHeight == lf.lfHeight, "expected %d height, got %d\n", lf.lfHeight, clf.lfHeight);
2870     DeleteObject(hfont);
2871     DeleteDC(hdc);
2872 }
2873
2874 static void test_GetGlyphOutline(void)
2875 {
2876     MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
2877     HDC hdc;
2878     GLYPHMETRICS gm;
2879     LOGFONTA lf;
2880     HFONT hfont, old_hfont;
2881     INT ret;
2882
2883     if (!is_truetype_font_installed("Tahoma"))
2884     {
2885         skip("Tahoma is not installed\n");
2886         return;
2887     }
2888
2889     hdc = CreateCompatibleDC(0);
2890     memset(&lf, 0, sizeof(lf));
2891     lf.lfHeight = 72;
2892     lstrcpyA(lf.lfFaceName, "Tahoma");
2893     SetLastError(0xdeadbeef);
2894     hfont = CreateFontIndirectA(&lf);
2895     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
2896     old_hfont = SelectObject(hdc, hfont);
2897
2898     memset(&gm, 0, sizeof(gm));
2899     SetLastError(0xdeadbeef);
2900     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
2901     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
2902
2903     memset(&gm, 0, sizeof(gm));
2904     SetLastError(0xdeadbeef);
2905     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
2906     ok(ret == GDI_ERROR, "GetGlyphOutlineA should fail\n");
2907     ok(GetLastError() == 0xdeadbeef ||
2908        GetLastError() == ERROR_INVALID_PARAMETER, /* win98, winMe */
2909        "expected 0xdeadbeef, got %u\n", GetLastError());
2910
2911     memset(&gm, 0, sizeof(gm));
2912     SetLastError(0xdeadbeef);
2913     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
2914     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
2915         ok(ret != GDI_ERROR, "GetGlyphOutlineW error %u\n", GetLastError());
2916
2917     memset(&gm, 0, sizeof(gm));
2918     SetLastError(0xdeadbeef);
2919     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
2920     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
2921     {
2922        ok(ret == GDI_ERROR, "GetGlyphOutlineW should fail\n");
2923        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
2924     }
2925
2926     /* test for needed buffer size request on space char */
2927     memset(&gm, 0, sizeof(gm));
2928     SetLastError(0xdeadbeef);
2929     ret = GetGlyphOutlineW(hdc, ' ', GGO_NATIVE, &gm, 0, NULL, &mat);
2930     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
2931         ok(ret == 0, "GetGlyphOutlineW should return 0 buffer size for space char\n");
2932
2933     /* requesting buffer size for space char + error */
2934     memset(&gm, 0, sizeof(gm));
2935     SetLastError(0xdeadbeef);
2936     ret = GetGlyphOutlineW(0, ' ', GGO_NATIVE, &gm, 0, NULL, NULL);
2937     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
2938     {
2939        ok(ret == GDI_ERROR, "GetGlyphOutlineW should return GDI_ERROR\n");
2940        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
2941     }
2942
2943     SelectObject(hdc, old_hfont);
2944     DeleteObject(hfont);
2945     DeleteDC(hdc);
2946 }
2947
2948 /* bug #9995: there is a limit to the character width that can be specified */
2949 static void test_GetTextMetrics2(const char *fontname, int font_height)
2950 {
2951     HFONT of, hf;
2952     HDC hdc;
2953     TEXTMETRICA tm;
2954     BOOL ret;
2955     int ave_width, height, width, ratio, scale;
2956
2957     if (!is_truetype_font_installed( fontname)) {
2958         skip("%s is not installed\n", fontname);
2959         return;
2960     }
2961     hdc = CreateCompatibleDC(0);
2962     ok( hdc != NULL, "CreateCompatibleDC failed\n");
2963     /* select width = 0 */
2964     hf = CreateFontA(font_height, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
2965             DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
2966             DEFAULT_QUALITY, VARIABLE_PITCH,
2967             fontname);
2968     ok( hf != NULL, "CreateFontA failed\n");
2969     of = SelectObject( hdc, hf);
2970     ret = GetTextMetricsA( hdc, &tm);
2971     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
2972     height = tm.tmHeight;
2973     ave_width = tm.tmAveCharWidth;
2974     SelectObject( hdc, of);
2975     DeleteObject( hf);
2976
2977     trace("height %d, ave width %d\n", height, ave_width);
2978
2979     for (width = ave_width * 2; /* nothing*/; width += ave_width)
2980     {
2981         hf = CreateFont(height, width, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
2982                         DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
2983                         DEFAULT_QUALITY, VARIABLE_PITCH, fontname);
2984         ok(hf != 0, "CreateFont failed\n");
2985         of = SelectObject(hdc, hf);
2986         ret = GetTextMetrics(hdc, &tm);
2987         ok(ret, "GetTextMetrics error %u\n", GetLastError());
2988         SelectObject(hdc, of);
2989         DeleteObject(hf);
2990
2991         if (tm.tmAveCharWidth == ave_width || width / height > 200)
2992             break;
2993     }
2994
2995     DeleteDC(hdc);
2996
2997     ratio = width / height;
2998     scale = width / ave_width;
2999
3000     trace("max width/height ratio (%d / %d) %d, max width scale (%d / %d) %d\n",
3001           width, height, ratio, width, ave_width, scale);
3002
3003     ok(ratio >= 90 && ratio <= 110, "expected width/height ratio 90-110, got %d\n", ratio);
3004 }
3005
3006 static void test_CreateFontIndirect(void)
3007 {
3008     LOGFONTA lf, getobj_lf;
3009     int ret, i;
3010     HFONT hfont;
3011     char TestName[][16] = {"Arial", "Arial Bold", "Arial Italic", "Arial Baltic"};
3012
3013     memset(&lf, 0, sizeof(lf));
3014     lf.lfCharSet = ANSI_CHARSET;
3015     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
3016     lf.lfHeight = 16;
3017     lf.lfWidth = 16;
3018     lf.lfQuality = DEFAULT_QUALITY;
3019     lf.lfItalic = FALSE;
3020     lf.lfWeight = FW_DONTCARE;
3021
3022     for (i = 0; i < sizeof(TestName)/sizeof(TestName[0]); i++)
3023     {
3024         lstrcpyA(lf.lfFaceName, TestName[i]);
3025         hfont = CreateFontIndirectA(&lf);
3026         ok(hfont != 0, "CreateFontIndirectA failed\n");
3027         ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf);
3028         ok(lf.lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf.lfItalic, getobj_lf.lfItalic);
3029         ok(lf.lfWeight == getobj_lf.lfWeight ||
3030            broken((SHORT)lf.lfWeight == getobj_lf.lfWeight), /* win9x */
3031            "lfWeight: expect %08x got %08x\n", lf.lfWeight, getobj_lf.lfWeight);
3032         ok(!lstrcmpA(lf.lfFaceName, getobj_lf.lfFaceName) ||
3033            broken(!memcmp(lf.lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
3034            "font names don't match: %s != %s\n", lf.lfFaceName, getobj_lf.lfFaceName);
3035         DeleteObject(hfont);
3036     }
3037 }
3038
3039 START_TEST(font)
3040 {
3041     init();
3042     test_logfont();
3043     test_bitmap_font();
3044     test_outline_font();
3045     test_bitmap_font_metrics();
3046     test_GdiGetCharDimensions();
3047     test_GetCharABCWidths();
3048     test_text_extents();
3049     test_GetGlyphIndices();
3050     test_GetKerningPairs();
3051     test_GetOutlineTextMetrics();
3052     test_SetTextJustification();
3053     test_font_charset();
3054     test_GetFontUnicodeRanges();
3055     test_nonexistent_font();
3056     test_orientation();
3057
3058     /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
3059      * I'd like to avoid them in this test.
3060      */
3061     test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
3062     test_EnumFontFamilies("Symbol", SYMBOL_CHARSET);
3063     if (is_truetype_font_installed("Arial Black") &&
3064         (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
3065     {
3066         test_EnumFontFamilies("", ANSI_CHARSET);
3067         test_EnumFontFamilies("", SYMBOL_CHARSET);
3068         test_EnumFontFamilies("", DEFAULT_CHARSET);
3069     }
3070     else
3071         skip("Arial Black or Symbol/Wingdings is not installed\n");
3072     test_GetTextMetrics();
3073     test_GdiRealizationInfo();
3074     test_GetTextFace();
3075     test_GetGlyphOutline();
3076     test_GetTextMetrics2("Tahoma", -11);
3077     test_GetTextMetrics2("Tahoma", -55);
3078     test_GetTextMetrics2("Tahoma", -110);
3079     test_GetTextMetrics2("Arial", -11);
3080     test_GetTextMetrics2("Arial", -55);
3081     test_GetTextMetrics2("Arial", -110);
3082     test_CreateFontIndirect();
3083     test_oemcharset();
3084 }