dsound: Always enumerate the default device first.
[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 /* Do not allow more than 1 deviation here */
34 #define match_off_by_1(a, b) (abs((a) - (b)) <= 1)
35
36 #define near_match(a, b) (abs((a) - (b)) <= 6)
37 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
38
39 static LONG  (WINAPI *pGdiGetCharDimensions)(HDC hdc, LPTEXTMETRICW lptm, LONG *height);
40 static DWORD (WINAPI *pGdiGetCodePage)(HDC hdc);
41 static BOOL  (WINAPI *pGetCharABCWidthsI)(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPABC abc);
42 static BOOL  (WINAPI *pGetCharABCWidthsA)(HDC hdc, UINT first, UINT last, LPABC abc);
43 static BOOL  (WINAPI *pGetCharABCWidthsW)(HDC hdc, UINT first, UINT last, LPABC abc);
44 static DWORD (WINAPI *pGetFontUnicodeRanges)(HDC hdc, LPGLYPHSET lpgs);
45 static DWORD (WINAPI *pGetGlyphIndicesA)(HDC hdc, LPCSTR lpstr, INT count, LPWORD pgi, DWORD flags);
46 static DWORD (WINAPI *pGetGlyphIndicesW)(HDC hdc, LPCWSTR lpstr, INT count, LPWORD pgi, DWORD flags);
47 static BOOL  (WINAPI *pGdiRealizationInfo)(HDC hdc, DWORD *);
48 static HFONT (WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDV *);
49 static HANDLE (WINAPI *pAddFontMemResourceEx)(PVOID, DWORD, PVOID, DWORD *);
50 static BOOL  (WINAPI *pRemoveFontMemResourceEx)(HANDLE);
51 static INT   (WINAPI *pAddFontResourceExA)(LPCSTR, DWORD, PVOID);
52 static BOOL  (WINAPI *pRemoveFontResourceExA)(LPCSTR, DWORD, PVOID);
53
54 static HMODULE hgdi32 = 0;
55 static const MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
56
57 static void init(void)
58 {
59     hgdi32 = GetModuleHandleA("gdi32.dll");
60
61     pGdiGetCharDimensions = (void *)GetProcAddress(hgdi32, "GdiGetCharDimensions");
62     pGdiGetCodePage = (void *) GetProcAddress(hgdi32,"GdiGetCodePage");
63     pGetCharABCWidthsI = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsI");
64     pGetCharABCWidthsA = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsA");
65     pGetCharABCWidthsW = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsW");
66     pGetFontUnicodeRanges = (void *)GetProcAddress(hgdi32, "GetFontUnicodeRanges");
67     pGetGlyphIndicesA = (void *)GetProcAddress(hgdi32, "GetGlyphIndicesA");
68     pGetGlyphIndicesW = (void *)GetProcAddress(hgdi32, "GetGlyphIndicesW");
69     pGdiRealizationInfo = (void *)GetProcAddress(hgdi32, "GdiRealizationInfo");
70     pCreateFontIndirectExA = (void *)GetProcAddress(hgdi32, "CreateFontIndirectExA");
71     pAddFontMemResourceEx = (void *)GetProcAddress(hgdi32, "AddFontMemResourceEx");
72     pRemoveFontMemResourceEx = (void *)GetProcAddress(hgdi32, "RemoveFontMemResourceEx");
73     pAddFontResourceExA = (void *)GetProcAddress(hgdi32, "AddFontResourceExA");
74     pRemoveFontResourceExA = (void *)GetProcAddress(hgdi32, "RemoveFontResourceExA");
75 }
76
77 static INT CALLBACK is_truetype_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
78 {
79     if (type != TRUETYPE_FONTTYPE) return 1;
80
81     return 0;
82 }
83
84 static BOOL is_truetype_font_installed(const char *name)
85 {
86     HDC hdc = GetDC(0);
87     BOOL ret = FALSE;
88
89     if (!EnumFontFamiliesA(hdc, name, is_truetype_font_installed_proc, 0))
90         ret = TRUE;
91
92     ReleaseDC(0, hdc);
93     return ret;
94 }
95
96 static INT CALLBACK is_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
97 {
98     return 0;
99 }
100
101 static BOOL is_font_installed(const char *name)
102 {
103     HDC hdc = GetDC(0);
104     BOOL ret = FALSE;
105
106     if(!EnumFontFamiliesA(hdc, name, is_font_installed_proc, 0))
107         ret = TRUE;
108
109     ReleaseDC(0, hdc);
110     return ret;
111 }
112
113 static void check_font(const char* test, const LOGFONTA* lf, HFONT hfont)
114 {
115     LOGFONTA getobj_lf;
116     int ret, minlen = 0;
117
118     if (!hfont)
119         return;
120
121     ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf);
122     /* NT4 tries to be clever and only returns the minimum length */
123     while (lf->lfFaceName[minlen] && minlen < LF_FACESIZE-1)
124         minlen++;
125     minlen += FIELD_OFFSET(LOGFONTA, lfFaceName) + 1;
126     ok(ret == sizeof(LOGFONTA) || ret == minlen, "%s: GetObject returned %d\n", test, ret);
127     ok(lf->lfHeight == getobj_lf.lfHeight ||
128        broken((SHORT)lf->lfHeight == getobj_lf.lfHeight), /* win9x */
129        "lfHeight: expect %08x got %08x\n", lf->lfHeight, getobj_lf.lfHeight);
130     ok(lf->lfWidth == getobj_lf.lfWidth ||
131        broken((SHORT)lf->lfWidth == getobj_lf.lfWidth), /* win9x */
132        "lfWidth: expect %08x got %08x\n", lf->lfWidth, getobj_lf.lfWidth);
133     ok(lf->lfEscapement == getobj_lf.lfEscapement ||
134        broken((SHORT)lf->lfEscapement == getobj_lf.lfEscapement), /* win9x */
135        "lfEscapement: expect %08x got %08x\n", lf->lfEscapement, getobj_lf.lfEscapement);
136     ok(lf->lfOrientation == getobj_lf.lfOrientation ||
137        broken((SHORT)lf->lfOrientation == getobj_lf.lfOrientation), /* win9x */
138        "lfOrientation: expect %08x got %08x\n", lf->lfOrientation, getobj_lf.lfOrientation);
139     ok(lf->lfWeight == getobj_lf.lfWeight ||
140        broken((SHORT)lf->lfWeight == getobj_lf.lfWeight), /* win9x */
141        "lfWeight: expect %08x got %08x\n", lf->lfWeight, getobj_lf.lfWeight);
142     ok(lf->lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf->lfItalic, getobj_lf.lfItalic);
143     ok(lf->lfUnderline == getobj_lf.lfUnderline, "lfUnderline: expect %02x got %02x\n", lf->lfUnderline, getobj_lf.lfUnderline);
144     ok(lf->lfStrikeOut == getobj_lf.lfStrikeOut, "lfStrikeOut: expect %02x got %02x\n", lf->lfStrikeOut, getobj_lf.lfStrikeOut);
145     ok(lf->lfCharSet == getobj_lf.lfCharSet, "lfCharSet: expect %02x got %02x\n", lf->lfCharSet, getobj_lf.lfCharSet);
146     ok(lf->lfOutPrecision == getobj_lf.lfOutPrecision, "lfOutPrecision: expect %02x got %02x\n", lf->lfOutPrecision, getobj_lf.lfOutPrecision);
147     ok(lf->lfClipPrecision == getobj_lf.lfClipPrecision, "lfClipPrecision: expect %02x got %02x\n", lf->lfClipPrecision, getobj_lf.lfClipPrecision);
148     ok(lf->lfQuality == getobj_lf.lfQuality, "lfQuality: expect %02x got %02x\n", lf->lfQuality, getobj_lf.lfQuality);
149     ok(lf->lfPitchAndFamily == getobj_lf.lfPitchAndFamily, "lfPitchAndFamily: expect %02x got %02x\n", lf->lfPitchAndFamily, getobj_lf.lfPitchAndFamily);
150     ok(!lstrcmpA(lf->lfFaceName, getobj_lf.lfFaceName) ||
151        broken(!memcmp(lf->lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
152        "%s: font names don't match: %s != %s\n", test, lf->lfFaceName, getobj_lf.lfFaceName);
153 }
154
155 static HFONT create_font(const char* test, const LOGFONTA* lf)
156 {
157     HFONT hfont = CreateFontIndirectA(lf);
158     ok(hfont != 0, "%s: CreateFontIndirect failed\n", test);
159     if (hfont)
160         check_font(test, lf, hfont);
161     return hfont;
162 }
163
164 static void test_logfont(void)
165 {
166     LOGFONTA lf;
167     HFONT hfont;
168
169     memset(&lf, 0, sizeof lf);
170
171     lf.lfCharSet = ANSI_CHARSET;
172     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
173     lf.lfWeight = FW_DONTCARE;
174     lf.lfHeight = 16;
175     lf.lfWidth = 16;
176     lf.lfQuality = DEFAULT_QUALITY;
177
178     lstrcpyA(lf.lfFaceName, "Arial");
179     hfont = create_font("Arial", &lf);
180     DeleteObject(hfont);
181
182     memset(&lf, 'A', sizeof(lf));
183     hfont = CreateFontIndirectA(&lf);
184     ok(hfont != 0, "CreateFontIndirectA with strange LOGFONT failed\n");
185     
186     lf.lfFaceName[LF_FACESIZE - 1] = 0;
187     check_font("AAA...", &lf, hfont);
188     DeleteObject(hfont);
189 }
190
191 static INT CALLBACK font_enum_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
192 {
193     if (type & RASTER_FONTTYPE)
194     {
195         LOGFONT *lf = (LOGFONT *)lParam;
196         *lf = *elf;
197         return 0; /* stop enumeration */
198     }
199
200     return 1; /* continue enumeration */
201 }
202
203 static void compare_tm(const TEXTMETRICA *tm, const TEXTMETRICA *otm)
204 {
205     ok(tm->tmHeight == otm->tmHeight, "tmHeight %d != %d\n", tm->tmHeight, otm->tmHeight);
206     ok(tm->tmAscent == otm->tmAscent, "tmAscent %d != %d\n", tm->tmAscent, otm->tmAscent);
207     ok(tm->tmDescent == otm->tmDescent, "tmDescent %d != %d\n", tm->tmDescent, otm->tmDescent);
208     ok(tm->tmInternalLeading == otm->tmInternalLeading, "tmInternalLeading %d != %d\n", tm->tmInternalLeading, otm->tmInternalLeading);
209     ok(tm->tmExternalLeading == otm->tmExternalLeading, "tmExternalLeading %d != %d\n", tm->tmExternalLeading, otm->tmExternalLeading);
210     ok(tm->tmAveCharWidth == otm->tmAveCharWidth, "tmAveCharWidth %d != %d\n", tm->tmAveCharWidth, otm->tmAveCharWidth);
211     ok(tm->tmMaxCharWidth == otm->tmMaxCharWidth, "tmMaxCharWidth %d != %d\n", tm->tmMaxCharWidth, otm->tmMaxCharWidth);
212     ok(tm->tmWeight == otm->tmWeight, "tmWeight %d != %d\n", tm->tmWeight, otm->tmWeight);
213     ok(tm->tmOverhang == otm->tmOverhang, "tmOverhang %d != %d\n", tm->tmOverhang, otm->tmOverhang);
214     ok(tm->tmDigitizedAspectX == otm->tmDigitizedAspectX, "tmDigitizedAspectX %d != %d\n", tm->tmDigitizedAspectX, otm->tmDigitizedAspectX);
215     ok(tm->tmDigitizedAspectY == otm->tmDigitizedAspectY, "tmDigitizedAspectY %d != %d\n", tm->tmDigitizedAspectY, otm->tmDigitizedAspectY);
216     ok(tm->tmFirstChar == otm->tmFirstChar, "tmFirstChar %d != %d\n", tm->tmFirstChar, otm->tmFirstChar);
217     ok(tm->tmLastChar == otm->tmLastChar, "tmLastChar %d != %d\n", tm->tmLastChar, otm->tmLastChar);
218     ok(tm->tmDefaultChar == otm->tmDefaultChar, "tmDefaultChar %d != %d\n", tm->tmDefaultChar, otm->tmDefaultChar);
219     ok(tm->tmBreakChar == otm->tmBreakChar, "tmBreakChar %d != %d\n", tm->tmBreakChar, otm->tmBreakChar);
220     ok(tm->tmItalic == otm->tmItalic, "tmItalic %d != %d\n", tm->tmItalic, otm->tmItalic);
221     ok(tm->tmUnderlined == otm->tmUnderlined, "tmUnderlined %d != %d\n", tm->tmUnderlined, otm->tmUnderlined);
222     ok(tm->tmStruckOut == otm->tmStruckOut, "tmStruckOut %d != %d\n", tm->tmStruckOut, otm->tmStruckOut);
223     ok(tm->tmPitchAndFamily == otm->tmPitchAndFamily, "tmPitchAndFamily %d != %d\n", tm->tmPitchAndFamily, otm->tmPitchAndFamily);
224     ok(tm->tmCharSet == otm->tmCharSet, "tmCharSet %d != %d\n", tm->tmCharSet, otm->tmCharSet);
225 }
226
227 static void test_font_metrics(HDC hdc, HFONT hfont, LONG lfHeight,
228                               LONG lfWidth, const char *test_str,
229                               INT test_str_len, const TEXTMETRICA *tm_orig,
230                               const SIZE *size_orig, INT width_of_A_orig,
231                               INT scale_x, INT scale_y)
232 {
233     LOGFONTA lf;
234     OUTLINETEXTMETRIC otm;
235     TEXTMETRICA tm;
236     SIZE size;
237     INT width_of_A, cx, cy;
238     UINT ret;
239
240     if (!hfont)
241         return;
242
243     ok(GetCurrentObject(hdc, OBJ_FONT) == hfont, "hfont should be selected\n");
244
245     GetObjectA(hfont, sizeof(lf), &lf);
246
247     if (GetOutlineTextMetricsA(hdc, 0, NULL))
248     {
249         otm.otmSize = sizeof(otm) / 2;
250         ret = GetOutlineTextMetricsA(hdc, otm.otmSize, &otm);
251         ok(ret == sizeof(otm)/2 /* XP */ ||
252            ret == 1 /* Win9x */, "expected sizeof(otm)/2, got %u\n", ret);
253
254         memset(&otm, 0x1, sizeof(otm));
255         otm.otmSize = sizeof(otm);
256         ret = GetOutlineTextMetricsA(hdc, otm.otmSize, &otm);
257         ok(ret == sizeof(otm) /* XP */ ||
258            ret == 1 /* Win9x */, "expected sizeof(otm), got %u\n", ret);
259
260         memset(&tm, 0x2, sizeof(tm));
261         ret = GetTextMetricsA(hdc, &tm);
262         ok(ret, "GetTextMetricsA failed\n");
263         /* the structure size is aligned */
264         if (memcmp(&tm, &otm.otmTextMetrics, FIELD_OFFSET(TEXTMETRICA, tmCharSet) + 1))
265         {
266             ok(0, "tm != otm\n");
267             compare_tm(&tm, &otm.otmTextMetrics);
268         }
269
270         tm = otm.otmTextMetrics;
271 if (0) /* these metrics are scaled too, but with rounding errors */
272 {
273         ok(otm.otmAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmAscent, tm.tmAscent);
274         ok(otm.otmDescent == -tm.tmDescent, "descent %d != %d\n", otm.otmDescent, -tm.tmDescent);
275 }
276         ok(otm.otmMacAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmMacAscent, tm.tmAscent);
277         ok(otm.otmDescent < 0, "otm.otmDescent should be < 0\n");
278         ok(otm.otmMacDescent < 0, "otm.otmMacDescent should be < 0\n");
279         ok(tm.tmDescent > 0, "tm.tmDescent should be > 0\n");
280         ok(otm.otmMacDescent == -tm.tmDescent, "descent %d != %d\n", otm.otmMacDescent, -tm.tmDescent);
281         ok(otm.otmEMSquare == 2048, "expected 2048, got %d\n", otm.otmEMSquare);
282     }
283     else
284     {
285         ret = GetTextMetricsA(hdc, &tm);
286         ok(ret, "GetTextMetricsA failed\n");
287     }
288
289     cx = tm.tmAveCharWidth / tm_orig->tmAveCharWidth;
290     cy = tm.tmHeight / tm_orig->tmHeight;
291     ok(cx == scale_x && cy == scale_y, "height %d: expected scale_x %d, scale_y %d, got cx %d, cy %d\n",
292        lfHeight, scale_x, scale_y, cx, cy);
293     ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "height %d != %d\n", tm.tmHeight, tm_orig->tmHeight * scale_y);
294     ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "ascent %d != %d\n", tm.tmAscent, tm_orig->tmAscent * scale_y);
295     ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "descent %d != %d\n", tm.tmDescent, tm_orig->tmDescent * scale_y);
296     ok(near_match(tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x), "ave width %d != %d\n", tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x);
297     ok(near_match(tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x), "max width %d != %d\n", tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x);
298
299     ok(lf.lfHeight == lfHeight, "lfHeight %d != %d\n", lf.lfHeight, lfHeight);
300     if (lf.lfHeight)
301     {
302         if (lf.lfWidth)
303             ok(lf.lfWidth == tm.tmAveCharWidth, "lfWidth %d != tm %d\n", lf.lfWidth, tm.tmAveCharWidth);
304     }
305     else
306         ok(lf.lfWidth == lfWidth, "lfWidth %d != %d\n", lf.lfWidth, lfWidth);
307
308     GetTextExtentPoint32A(hdc, test_str, test_str_len, &size);
309
310     ok(near_match(size.cx, size_orig->cx * scale_x), "cx %d != %d\n", size.cx, size_orig->cx * scale_x);
311     ok(size.cy == size_orig->cy * scale_y, "cy %d != %d\n", size.cy, size_orig->cy * scale_y);
312
313     GetCharWidthA(hdc, 'A', 'A', &width_of_A);
314
315     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);
316 }
317
318 /* Test how GDI scales bitmap font metrics */
319 static void test_bitmap_font(void)
320 {
321     static const char test_str[11] = "Test String";
322     HDC hdc;
323     LOGFONTA bitmap_lf;
324     HFONT hfont, old_hfont;
325     TEXTMETRICA tm_orig;
326     SIZE size_orig;
327     INT ret, i, width_orig, height_orig, scale, lfWidth;
328
329     hdc = GetDC(0);
330
331     /* "System" has only 1 pixel size defined, otherwise the test breaks */
332     ret = EnumFontFamiliesA(hdc, "System", font_enum_proc, (LPARAM)&bitmap_lf);
333     if (ret)
334     {
335         ReleaseDC(0, hdc);
336         trace("no bitmap fonts were found, skipping the test\n");
337         return;
338     }
339
340     trace("found bitmap font %s, height %d\n", bitmap_lf.lfFaceName, bitmap_lf.lfHeight);
341
342     height_orig = bitmap_lf.lfHeight;
343     lfWidth = bitmap_lf.lfWidth;
344
345     hfont = create_font("bitmap", &bitmap_lf);
346     old_hfont = SelectObject(hdc, hfont);
347     ok(GetTextMetricsA(hdc, &tm_orig), "GetTextMetricsA failed\n");
348     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
349     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
350     SelectObject(hdc, old_hfont);
351     DeleteObject(hfont);
352
353     bitmap_lf.lfHeight = 0;
354     bitmap_lf.lfWidth = 4;
355     hfont = create_font("bitmap", &bitmap_lf);
356     old_hfont = SelectObject(hdc, hfont);
357     test_font_metrics(hdc, hfont, 0, 4, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, 1);
358     SelectObject(hdc, old_hfont);
359     DeleteObject(hfont);
360
361     bitmap_lf.lfHeight = height_orig;
362     bitmap_lf.lfWidth = lfWidth;
363
364     /* test fractional scaling */
365     for (i = 1; i <= height_orig * 6; i++)
366     {
367         INT nearest_height;
368
369         bitmap_lf.lfHeight = i;
370         hfont = create_font("fractional", &bitmap_lf);
371         scale = (i + height_orig - 1) / height_orig;
372         nearest_height = scale * height_orig;
373         /* Only jump to the next height if the difference <= 25% original height */
374         if (scale > 2 && nearest_height - i > height_orig / 4) scale--;
375         /* The jump between unscaled and doubled is delayed by 1 in winnt+ but not in win9x,
376            so we'll not test this particular height. */
377         else if(scale == 2 && nearest_height - i == (height_orig / 4)) continue;
378         else if(scale == 2 && nearest_height - i > (height_orig / 4 - 1)) scale--;
379         old_hfont = SelectObject(hdc, hfont);
380         test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, scale);
381         SelectObject(hdc, old_hfont);
382         DeleteObject(hfont);
383     }
384
385     /* test integer scaling 3x2 */
386     bitmap_lf.lfHeight = height_orig * 2;
387     bitmap_lf.lfWidth *= 3;
388     hfont = create_font("3x2", &bitmap_lf);
389     old_hfont = SelectObject(hdc, hfont);
390     test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 2);
391     SelectObject(hdc, old_hfont);
392     DeleteObject(hfont);
393
394     /* test integer scaling 3x3 */
395     bitmap_lf.lfHeight = height_orig * 3;
396     bitmap_lf.lfWidth = 0;
397     hfont = create_font("3x3", &bitmap_lf);
398     old_hfont = SelectObject(hdc, hfont);
399     test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 3);
400     SelectObject(hdc, old_hfont);
401     DeleteObject(hfont);
402
403     ReleaseDC(0, hdc);
404 }
405
406 /* Test how GDI scales outline font metrics */
407 static void test_outline_font(void)
408 {
409     static const char test_str[11] = "Test String";
410     HDC hdc, hdc_2;
411     LOGFONTA lf;
412     HFONT hfont, old_hfont, old_hfont_2;
413     OUTLINETEXTMETRICA otm;
414     SIZE size_orig;
415     INT width_orig, height_orig, lfWidth;
416     XFORM xform;
417     GLYPHMETRICS gm;
418     MAT2 mat2 = { {0x8000,0}, {0,0}, {0,0}, {0x8000,0} };
419     POINT pt;
420     INT ret;
421
422     if (!is_truetype_font_installed("Arial"))
423     {
424         skip("Arial is not installed\n");
425         return;
426     }
427
428     hdc = CreateCompatibleDC(0);
429
430     memset(&lf, 0, sizeof(lf));
431     strcpy(lf.lfFaceName, "Arial");
432     lf.lfHeight = 72;
433     hfont = create_font("outline", &lf);
434     old_hfont = SelectObject(hdc, hfont);
435     otm.otmSize = sizeof(otm);
436     ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n");
437     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
438     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
439
440     test_font_metrics(hdc, hfont, lf.lfHeight, otm.otmTextMetrics.tmAveCharWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
441     SelectObject(hdc, old_hfont);
442     DeleteObject(hfont);
443
444     /* font of otmEMSquare height helps to avoid a lot of rounding errors */
445     lf.lfHeight = otm.otmEMSquare;
446     lf.lfHeight = -lf.lfHeight;
447     hfont = create_font("outline", &lf);
448     old_hfont = SelectObject(hdc, hfont);
449     otm.otmSize = sizeof(otm);
450     ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n");
451     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
452     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
453     SelectObject(hdc, old_hfont);
454     DeleteObject(hfont);
455
456     height_orig = otm.otmTextMetrics.tmHeight;
457     lfWidth = otm.otmTextMetrics.tmAveCharWidth;
458
459     /* test integer scaling 3x2 */
460     lf.lfHeight = height_orig * 2;
461     lf.lfWidth = lfWidth * 3;
462     hfont = create_font("3x2", &lf);
463     old_hfont = SelectObject(hdc, hfont);
464     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 2);
465     SelectObject(hdc, old_hfont);
466     DeleteObject(hfont);
467
468     /* test integer scaling 3x3 */
469     lf.lfHeight = height_orig * 3;
470     lf.lfWidth = lfWidth * 3;
471     hfont = create_font("3x3", &lf);
472     old_hfont = SelectObject(hdc, hfont);
473     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 3);
474     SelectObject(hdc, old_hfont);
475     DeleteObject(hfont);
476
477     /* test integer scaling 1x1 */
478     lf.lfHeight = height_orig * 1;
479     lf.lfWidth = lfWidth * 1;
480     hfont = create_font("1x1", &lf);
481     old_hfont = SelectObject(hdc, hfont);
482     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
483     SelectObject(hdc, old_hfont);
484     DeleteObject(hfont);
485
486     /* test integer scaling 1x1 */
487     lf.lfHeight = height_orig;
488     lf.lfWidth = 0;
489     hfont = create_font("1x1", &lf);
490     old_hfont = SelectObject(hdc, hfont);
491     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
492
493     /* with an identity matrix */
494     memset(&gm, 0, sizeof(gm));
495     SetLastError(0xdeadbeef);
496     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
497     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
498     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
499     ok(gm.gmCellIncX == width_orig, "incX %d != %d\n", gm.gmCellIncX, width_orig);
500     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
501     /* with a custom matrix */
502     memset(&gm, 0, sizeof(gm));
503     SetLastError(0xdeadbeef);
504     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
505     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
506     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
507     ok(gm.gmCellIncX == width_orig/2, "incX %d != %d\n", gm.gmCellIncX, width_orig/2);
508     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
509
510     /* Test that changing the DC transformation affects only the font
511      * selected on this DC and doesn't affect the same font selected on
512      * another DC.
513      */
514     hdc_2 = CreateCompatibleDC(0);
515     old_hfont_2 = SelectObject(hdc_2, hfont);
516     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
517
518     SetMapMode(hdc, MM_ANISOTROPIC);
519
520     /* font metrics on another DC should be unchanged */
521     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
522
523     /* test restrictions of compatibility mode GM_COMPATIBLE */
524     /*  part 1: rescaling only X should not change font scaling on screen.
525                 So compressing the X axis by 2 is not done, and this
526                 appears as X scaling of 2 that no one requested. */
527     SetWindowExtEx(hdc, 100, 100, NULL);
528     SetViewportExtEx(hdc, 50, 100, NULL);
529     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 2, 1);
530     /* font metrics on another DC should be unchanged */
531     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
532
533     /*  part 2: rescaling only Y should change font scaling.
534                 As also X is scaled by a factor of 2, but this is not
535                 requested by the DC transformation, we get a scaling factor
536                 of 2 in the X coordinate. */
537     SetViewportExtEx(hdc, 100, 200, NULL);
538     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 2, 1);
539     /* font metrics on another DC should be unchanged */
540     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
541
542     /* restore scaling */
543     SetMapMode(hdc, MM_TEXT);
544
545     /* font metrics on another DC should be unchanged */
546     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
547
548     SelectObject(hdc_2, old_hfont_2);
549     DeleteDC(hdc_2);
550
551     if (!SetGraphicsMode(hdc, GM_ADVANCED))
552     {
553         SelectObject(hdc, old_hfont);
554         DeleteObject(hfont);
555         DeleteDC(hdc);
556         skip("GM_ADVANCED is not supported on this platform\n");
557         return;
558     }
559
560     xform.eM11 = 20.0f;
561     xform.eM12 = 0.0f;
562     xform.eM21 = 0.0f;
563     xform.eM22 = 20.0f;
564     xform.eDx = 0.0f;
565     xform.eDy = 0.0f;
566
567     SetLastError(0xdeadbeef);
568     ret = SetWorldTransform(hdc, &xform);
569     ok(ret, "SetWorldTransform error %u\n", GetLastError());
570
571     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
572
573     /* with an identity matrix */
574     memset(&gm, 0, sizeof(gm));
575     SetLastError(0xdeadbeef);
576     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
577     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
578     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
579     pt.x = width_orig; pt.y = 0;
580     LPtoDP(hdc, &pt, 1);
581     ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x);
582     ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig);
583     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
584     /* with a custom matrix */
585     memset(&gm, 0, sizeof(gm));
586     SetLastError(0xdeadbeef);
587     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
588     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
589     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
590     pt.x = width_orig; pt.y = 0;
591     LPtoDP(hdc, &pt, 1);
592     ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2);
593     ok(near_match(gm.gmCellIncX, 10 * width_orig), "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig);
594     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
595
596     SetLastError(0xdeadbeef);
597     ret = SetMapMode(hdc, MM_LOMETRIC);
598     ok(ret == MM_TEXT, "expected MM_TEXT, got %d, error %u\n", ret, GetLastError());
599
600     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
601
602     /* with an identity matrix */
603     memset(&gm, 0, sizeof(gm));
604     SetLastError(0xdeadbeef);
605     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
606     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
607     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
608     pt.x = width_orig; pt.y = 0;
609     LPtoDP(hdc, &pt, 1);
610     ok(near_match(gm.gmCellIncX, pt.x), "incX %d != %d\n", gm.gmCellIncX, pt.x);
611     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
612     /* with a custom matrix */
613     memset(&gm, 0, sizeof(gm));
614     SetLastError(0xdeadbeef);
615     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
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(near_match(gm.gmCellIncX, (pt.x + 1)/2), "incX %d != %d\n", gm.gmCellIncX, (pt.x + 1)/2);
621     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
622
623     SetLastError(0xdeadbeef);
624     ret = SetMapMode(hdc, MM_TEXT);
625     ok(ret == MM_LOMETRIC, "expected MM_LOMETRIC, got %d, error %u\n", ret, GetLastError());
626
627     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
628
629     /* with an identity matrix */
630     memset(&gm, 0, sizeof(gm));
631     SetLastError(0xdeadbeef);
632     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
633     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
634     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
635     pt.x = width_orig; pt.y = 0;
636     LPtoDP(hdc, &pt, 1);
637     ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x);
638     ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig);
639     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
640     /* with a custom matrix */
641     memset(&gm, 0, sizeof(gm));
642     SetLastError(0xdeadbeef);
643     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
644     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
645     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
646     pt.x = width_orig; pt.y = 0;
647     LPtoDP(hdc, &pt, 1);
648     ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2);
649     ok(gm.gmCellIncX == 10 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig);
650     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
651
652     SelectObject(hdc, old_hfont);
653     DeleteObject(hfont);
654     DeleteDC(hdc);
655 }
656
657 static INT CALLBACK find_font_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
658 {
659     LOGFONT *lf = (LOGFONT *)lParam;
660
661     if (elf->lfHeight == lf->lfHeight && !strcmp(elf->lfFaceName, lf->lfFaceName))
662     {
663         *lf = *elf;
664         return 0; /* stop enumeration */
665     }
666     return 1; /* continue enumeration */
667 }
668
669 static void test_bitmap_font_metrics(void)
670 {
671     static const struct font_data
672     {
673         const char face_name[LF_FACESIZE];
674         int weight, height, ascent, descent, int_leading, ext_leading;
675         int ave_char_width, max_char_width, dpi;
676         BYTE first_char, last_char, def_char, break_char;
677         DWORD ansi_bitfield;
678         WORD skip_lang_id;
679     } fd[] =
680     {
681         { "MS Sans Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
682         { "MS Sans Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
683         { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
684         { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
685         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 16, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 },
686         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN2 },
687         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 16, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
688         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 19, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 },
689         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 24, 96, 0x20, 0xff, 0x81, 0x40, FS_LATIN2 },
690         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 20, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
691         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 24, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 },
692         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 6, 0, 12, 24, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN2 },
693         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 25, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
694         { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 },
695         { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32, 96, 0x20, 0xff, 0x81, 0x40, FS_LATIN2 },
696         { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
697
698         { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
699         { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
700         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
701         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 17, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
702         { "MS Sans Serif", FW_NORMAL, 25, 20, 5, 5, 0, 10, 21, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
703         { "MS Sans Serif", FW_NORMAL, 25, 20, 5, 5, 0, 10, 21, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
704         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 6, 0, 12, 24, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
705         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 24, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
706         { "MS Sans Serif", FW_NORMAL, 36, 29, 7, 6, 0, 15, 30, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
707         { "MS Sans Serif", FW_NORMAL, 36, 29, 7, 6, 0, 15, 30, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
708         { "MS Sans Serif", FW_NORMAL, 46, 37, 9, 6, 0, 20, 40, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
709         { "MS Sans Serif", FW_NORMAL, 46, 37, 9, 6, 0, 20, 40, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
710
711         { "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
712         { "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
713         { "MS Serif", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
714         { "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
715         { "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 12, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
716         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 14, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
717         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 16, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
718         { "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 18, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
719         { "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 19, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
720         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 17, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
721         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 22, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
722         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 23, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
723         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 23, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
724         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 26, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
725         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 27, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
726         { "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 33, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
727         { "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 34, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
728
729         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 14, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_CYRILLIC },
730         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 13, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
731         { "MS Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_CYRILLIC },
732         { "MS Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 15, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
733         { "MS Serif", FW_NORMAL, 23, 18, 5, 3, 0, 10, 21, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_CYRILLIC },
734         { "MS Serif", FW_NORMAL, 23, 18, 5, 3, 0, 10, 19, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
735         { "MS Serif", FW_NORMAL, 27, 21, 6, 4, 0, 12, 23, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
736         { "MS Serif", FW_MEDIUM, 27, 22, 5, 2, 0, 12, 30, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
737         { "MS Serif", FW_NORMAL, 33, 26, 7, 3, 0, 14, 30, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
738         { "MS Serif", FW_MEDIUM, 32, 25, 7, 2, 0, 14, 32, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
739         { "MS Serif", FW_NORMAL, 43, 34, 9, 3, 0, 19, 39, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
740
741         { "Courier", FW_NORMAL, 13, 11, 2, 0, 0, 8, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
742         { "Courier", FW_NORMAL, 16, 13, 3, 0, 0, 9, 9, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
743         { "Courier", FW_NORMAL, 20, 16, 4, 0, 0, 12, 12, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
744
745         { "Courier", FW_NORMAL, 16, 13, 3, 0, 0, 9, 9, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
746         { "Courier", FW_NORMAL, 20, 16, 4, 0, 0, 12, 12, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
747         { "Courier", FW_NORMAL, 25, 20, 5, 0, 0, 15, 15, 120, 0x20, 0xff, 0x40, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
748
749         { "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
750         { "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 15, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
751         { "System", FW_NORMAL, 18, 16, 2, 0, 2, 8, 16, 96, 0, 0, 0, 0, FS_JISJAPAN },
752
753         { "System", FW_BOLD, 20, 16, 4, 4, 0, 9, 14, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
754         { "System", FW_BOLD, 20, 16, 4, 4, 0, 9, 17, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
755
756         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 2, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
757         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
758         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 2, 4, 96, 0, 0, 0, 0, FS_JISJAPAN },
759         { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 3, 4, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1, LANG_ARABIC },
760         { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 2, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
761         { "Small Fonts", FW_NORMAL, 5, 4, 1, 0, 0, 3, 6, 96, 0, 0, 0, 0, FS_JISJAPAN },
762         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 13, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1, LANG_ARABIC },
763         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
764         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 96, 0, 0, 0, 0, FS_ARABIC },
765         { "Small Fonts", FW_NORMAL, 6, 5, 1, 0, 0, 4, 8, 96, 0, 0, 0, 0, FS_JISJAPAN },
766         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 7, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1, LANG_ARABIC },
767         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
768         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 96, 0, 0, 0, 0, FS_ARABIC },
769         { "Small Fonts", FW_NORMAL, 8, 7, 1, 0, 0, 5, 10, 96, 0, 0, 0, 0, FS_JISJAPAN },
770         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2, LANG_ARABIC },
771         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
772         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 4, 9, 96, 0, 0, 0, 0, FS_ARABIC },
773         { "Small Fonts", FW_NORMAL, 10, 8, 2, 0, 0, 6, 12, 96, 0, 0, 0, 0, FS_JISJAPAN },
774         { "Small Fonts", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC, LANG_ARABIC },
775         { "Small Fonts", FW_NORMAL, 11, 9, 2, 2, 0, 4, 10, 96, 0, 0, 0, 0, FS_ARABIC },
776         { "Small Fonts", FW_NORMAL, 11, 9, 2, 0, 0, 7, 14, 96, 0, 0, 0, 0, FS_JISJAPAN },
777
778         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 2, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_JISJAPAN },
779         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 8, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
780         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 5, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_JISJAPAN },
781         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
782         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 7, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_JISJAPAN },
783         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
784         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 9, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
785         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
786         { "Small Fonts", FW_NORMAL, 12, 10, 2, 2, 0, 5, 10, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
787         { "Small Fonts", FW_NORMAL, 12, 10, 2, 2, 0, 6, 10, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
788         { "Small Fonts", FW_NORMAL, 13, 11, 2, 2, 0, 6, 12, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
789         { "Small Fonts", FW_NORMAL, 13, 11, 2, 2, 0, 6, 11, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
790
791         { "Fixedsys", FW_NORMAL, 15, 12, 3, 3, 0, 8, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
792         { "Fixedsys", FW_NORMAL, 16, 12, 4, 3, 0, 8, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
793         { "FixedSys", FW_NORMAL, 18, 16, 2, 0, 0, 8, 16, 96, 0, 0, 0, 0, FS_JISJAPAN },
794
795         /* The 120dpi version still has its dpi marked as 96 */
796         { "Fixedsys", FW_NORMAL, 20, 16, 4, 2, 0, 10, 10, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC }
797
798         /* FIXME: add "Terminal" */
799     };
800     HDC hdc;
801     LOGFONT lf;
802     HFONT hfont, old_hfont;
803     TEXTMETRIC tm;
804     INT ret, i;
805     WORD system_lang_id;
806
807     system_lang_id = PRIMARYLANGID(GetSystemDefaultLangID());
808
809     hdc = CreateCompatibleDC(0);
810     assert(hdc);
811
812     for (i = 0; i < sizeof(fd)/sizeof(fd[0]); i++)
813     {
814         int bit;
815
816         memset(&lf, 0, sizeof(lf));
817
818         lf.lfHeight = fd[i].height;
819         strcpy(lf.lfFaceName, fd[i].face_name);
820
821         for(bit = 0; bit < 32; bit++)
822         {
823             DWORD fs[2];
824             CHARSETINFO csi;
825             BOOL bRet;
826
827             fs[0] = 1L << bit;
828             fs[1] = 0;
829             if((fd[i].ansi_bitfield & fs[0]) == 0) continue;
830             if(!TranslateCharsetInfo( fs, &csi, TCI_SRCFONTSIG )) continue;
831
832             lf.lfCharSet = csi.ciCharset;
833             ret = EnumFontFamiliesEx(hdc, &lf, find_font_proc, (LPARAM)&lf, 0);
834             if (ret) continue;
835
836             hfont = create_font(lf.lfFaceName, &lf);
837             old_hfont = SelectObject(hdc, hfont);
838             bRet = GetTextMetrics(hdc, &tm);
839             ok(bRet, "GetTextMetrics error %d\n", GetLastError());
840             if(fd[i].dpi == tm.tmDigitizedAspectX)
841             {
842                 trace("found font %s, height %d charset %x dpi %d\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet, fd[i].dpi);
843                 if (fd[i].skip_lang_id == 0 || system_lang_id != fd[i].skip_lang_id)
844                 {
845                     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);
846                     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);
847                     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);
848                     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);
849                     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);
850                     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);
851                     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);
852                     ok(tm.tmFirstChar == fd[i].first_char, "%s(%d): tm.tmFirstChar = %02x\n", fd[i].face_name, fd[i].height, tm.tmFirstChar);
853                     ok(tm.tmLastChar == fd[i].last_char, "%s(%d): tm.tmLastChar = %02x\n", fd[i].face_name, fd[i].height, tm.tmLastChar);
854                     ok(tm.tmDefaultChar == fd[i].def_char, "%s(%d): tm.tmDefaultChar = %02x\n", fd[i].face_name, fd[i].height, tm.tmDefaultChar);
855                     ok(tm.tmBreakChar == fd[i].break_char, "%s(%d): tm.tmBreakChar = %02x\n", fd[i].face_name, fd[i].height, tm.tmBreakChar);
856
857                     /* Don't run the max char width test on System/ANSI_CHARSET.  We have extra characters in our font
858                        that make the max width bigger */
859                     if(strcmp(lf.lfFaceName, "System") || lf.lfCharSet != ANSI_CHARSET)
860                         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);
861                 }
862                 else
863                     skip("Skipping font metrics test for system langid 0x%x\n",
864                          system_lang_id);
865             }
866             SelectObject(hdc, old_hfont);
867             DeleteObject(hfont);
868         }
869     }
870
871     DeleteDC(hdc);
872 }
873
874 static void test_GdiGetCharDimensions(void)
875 {
876     HDC hdc;
877     TEXTMETRICW tm;
878     LONG ret;
879     SIZE size;
880     LONG avgwidth, height;
881     static const char szAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
882
883     if (!pGdiGetCharDimensions)
884     {
885         win_skip("GdiGetCharDimensions not available on this platform\n");
886         return;
887     }
888
889     hdc = CreateCompatibleDC(NULL);
890
891     GetTextExtentPoint(hdc, szAlphabet, strlen(szAlphabet), &size);
892     avgwidth = ((size.cx / 26) + 1) / 2;
893
894     ret = pGdiGetCharDimensions(hdc, &tm, &height);
895     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
896     ok(height == tm.tmHeight, "GdiGetCharDimensions should have set height to %d instead of %d\n", tm.tmHeight, height);
897
898     ret = pGdiGetCharDimensions(hdc, &tm, NULL);
899     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
900
901     ret = pGdiGetCharDimensions(hdc, NULL, NULL);
902     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
903
904     height = 0;
905     ret = pGdiGetCharDimensions(hdc, NULL, &height);
906     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
907     ok(height == size.cy, "GdiGetCharDimensions should have set height to %d instead of %d\n", size.cy, height);
908
909     DeleteDC(hdc);
910 }
911
912 static int CALLBACK create_font_proc(const LOGFONT *lpelfe,
913                                      const TEXTMETRIC *lpntme,
914                                      DWORD FontType, LPARAM lParam)
915 {
916     if (FontType & TRUETYPE_FONTTYPE)
917     {
918         HFONT hfont;
919
920         hfont = CreateFontIndirect(lpelfe);
921         if (hfont)
922         {
923             *(HFONT *)lParam = hfont;
924             return 0;
925         }
926     }
927
928     return 1;
929 }
930
931 static void test_GetCharABCWidths(void)
932 {
933     static const WCHAR str[] = {'a',0};
934     BOOL ret;
935     HDC hdc;
936     LOGFONTA lf;
937     HFONT hfont;
938     ABC abc[1];
939     WORD glyphs[1];
940     DWORD nb;
941     static const struct
942     {
943         UINT first;
944         UINT last;
945     } range[] =
946     {
947         {0xff, 0xff},
948         {0x100, 0x100},
949         {0xff, 0x100},
950         {0x1ff, 0xff00},
951         {0xffff, 0xffff},
952         {0x10000, 0x10000},
953         {0xffff, 0x10000},
954         {0xffffff, 0xffffff},
955         {0x1000000, 0x1000000},
956         {0xffffff, 0x1000000},
957         {0xffffffff, 0xffffffff}
958     };
959     static const struct
960     {
961         UINT cs;
962         UINT a;
963         UINT w;
964         BOOL r[sizeof range / sizeof range[0]];
965     } c[] =
966     {
967         {ANSI_CHARSET, 0x30, 0x30, {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}},
968         {SHIFTJIS_CHARSET, 0x82a0, 0x3042, {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}},
969         {HANGEUL_CHARSET, 0x8141, 0xac02, {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}},
970         {JOHAB_CHARSET, 0x8446, 0x3135, {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}},
971         {GB2312_CHARSET, 0x8141, 0x4e04, {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}},
972         {CHINESEBIG5_CHARSET, 0xa142, 0x3001, {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}}
973     };
974     UINT i;
975
976     if (!pGetCharABCWidthsA || !pGetCharABCWidthsW || !pGetCharABCWidthsI)
977     {
978         win_skip("GetCharABCWidthsA/W/I not available on this platform\n");
979         return;
980     }
981
982     memset(&lf, 0, sizeof(lf));
983     strcpy(lf.lfFaceName, "System");
984     lf.lfHeight = 20;
985
986     hfont = CreateFontIndirectA(&lf);
987     hdc = GetDC(0);
988     hfont = SelectObject(hdc, hfont);
989
990     nb = pGetGlyphIndicesW(hdc, str, 1, glyphs, 0);
991     ok(nb == 1, "GetGlyphIndicesW should have returned 1\n");
992
993     ret = pGetCharABCWidthsI(NULL, 0, 1, glyphs, abc);
994     ok(!ret, "GetCharABCWidthsI should have failed\n");
995
996     ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, NULL);
997     ok(!ret, "GetCharABCWidthsI should have failed\n");
998
999     ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, abc);
1000     ok(ret, "GetCharABCWidthsI should have succeeded\n");
1001
1002     ret = pGetCharABCWidthsW(NULL, 'a', 'a', abc);
1003     ok(!ret, "GetCharABCWidthsW should have failed\n");
1004
1005     ret = pGetCharABCWidthsW(hdc, 'a', 'a', NULL);
1006     ok(!ret, "GetCharABCWidthsW should have failed\n");
1007
1008     ret = pGetCharABCWidthsW(hdc, 'a', 'a', abc);
1009     ok(!ret, "GetCharABCWidthsW should have failed\n");
1010
1011     hfont = SelectObject(hdc, hfont);
1012     DeleteObject(hfont);
1013
1014     for (i = 0; i < sizeof c / sizeof c[0]; ++i)
1015     {
1016         ABC a[2], w[2];
1017         ABC full[256];
1018         UINT code = 0x41, j;
1019
1020         lf.lfFaceName[0] = '\0';
1021         lf.lfCharSet = c[i].cs;
1022         lf.lfPitchAndFamily = 0;
1023         if (EnumFontFamiliesEx(hdc, &lf, create_font_proc, (LPARAM)&hfont, 0))
1024         {
1025             skip("TrueType font for charset %u is not installed\n", c[i].cs);
1026             continue;
1027         }
1028
1029         memset(a, 0, sizeof a);
1030         memset(w, 0, sizeof w);
1031         hfont = SelectObject(hdc, hfont);
1032         ok(pGetCharABCWidthsA(hdc, c[i].a, c[i].a + 1, a) &&
1033            pGetCharABCWidthsW(hdc, c[i].w, c[i].w + 1, w) &&
1034            memcmp(a, w, sizeof a) == 0,
1035            "GetCharABCWidthsA and GetCharABCWidthsW should return same widths. charset = %u\n", c[i].cs);
1036
1037         memset(a, 0xbb, sizeof a);
1038         ret = pGetCharABCWidthsA(hdc, code, code, a);
1039         ok(ret, "GetCharABCWidthsA should have succeeded\n");
1040         memset(full, 0xcc, sizeof full);
1041         ret = pGetCharABCWidthsA(hdc, 0x00, code, full);
1042         ok(ret, "GetCharABCWidthsA should have succeeded\n");
1043         ok(memcmp(&a[0], &full[code], sizeof(ABC)) == 0,
1044            "GetCharABCWidthsA info should match. codepage = %u\n", c[i].cs);
1045
1046         for (j = 0; j < sizeof range / sizeof range[0]; ++j)
1047         {
1048             ret = pGetCharABCWidthsA(hdc, range[j].first, range[j].last, full);
1049             ok(ret == c[i].r[j], "GetCharABCWidthsA %x - %x should have %s\n",
1050                range[j].first, range[j].last, c[i].r[j] ? "succeeded" : "failed");
1051         }
1052
1053         hfont = SelectObject(hdc, hfont);
1054         DeleteObject(hfont);
1055     }
1056
1057     ReleaseDC(NULL, hdc);
1058 }
1059
1060 static void test_text_extents(void)
1061 {
1062     static const WCHAR wt[] = {'O','n','e','\n','t','w','o',' ','3',0};
1063     LPINT extents;
1064     INT i, len, fit1, fit2;
1065     LOGFONTA lf;
1066     TEXTMETRICA tm;
1067     HDC hdc;
1068     HFONT hfont;
1069     SIZE sz;
1070     SIZE sz1, sz2;
1071     BOOL ret;
1072
1073     memset(&lf, 0, sizeof(lf));
1074     strcpy(lf.lfFaceName, "Arial");
1075     lf.lfHeight = 20;
1076
1077     hfont = CreateFontIndirectA(&lf);
1078     hdc = GetDC(0);
1079     hfont = SelectObject(hdc, hfont);
1080     GetTextMetricsA(hdc, &tm);
1081     GetTextExtentPointA(hdc, "o", 1, &sz);
1082     ok(sz.cy == tm.tmHeight, "cy %d tmHeight %d\n", sz.cy, tm.tmHeight);
1083
1084     SetLastError(0xdeadbeef);
1085     GetTextExtentExPointW(hdc, wt, 1, 1, &fit1, &fit2, &sz1);
1086     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1087     {
1088         win_skip("Skipping remainder of text extents test on a Win9x platform\n");
1089         hfont = SelectObject(hdc, hfont);
1090         DeleteObject(hfont);
1091         ReleaseDC(0, hdc);
1092         return;
1093     }
1094
1095     len = lstrlenW(wt);
1096     extents = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof extents[0]);
1097     extents[0] = 1;         /* So that the increasing sequence test will fail
1098                                if the extents array is untouched.  */
1099     GetTextExtentExPointW(hdc, wt, len, 32767, &fit1, extents, &sz1);
1100     GetTextExtentPointW(hdc, wt, len, &sz2);
1101     ok(sz1.cy == sz2.cy,
1102        "cy from GetTextExtentExPointW (%d) and GetTextExtentPointW (%d) differ\n", sz1.cy, sz2.cy);
1103     /* Because of the '\n' in the string GetTextExtentExPoint and
1104        GetTextExtentPoint return different widths under Win2k, but
1105        under WinXP they return the same width.  So we don't test that
1106        here. */
1107
1108     for (i = 1; i < len; ++i)
1109         ok(extents[i-1] <= extents[i],
1110            "GetTextExtentExPointW generated a non-increasing sequence of partial extents (at position %d)\n",
1111            i);
1112     ok(extents[len-1] == sz1.cx, "GetTextExtentExPointW extents and size don't match\n");
1113     ok(0 <= fit1 && fit1 <= len, "GetTextExtentExPointW generated illegal value %d for fit\n", fit1);
1114     ok(0 < fit1, "GetTextExtentExPointW says we can't even fit one letter in 32767 logical units\n");
1115     GetTextExtentExPointW(hdc, wt, len, extents[2], &fit2, NULL, &sz2);
1116     ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy, "GetTextExtentExPointW returned different sizes for the same string\n");
1117     ok(fit2 == 3, "GetTextExtentExPointW extents isn't consistent with fit\n");
1118     GetTextExtentExPointW(hdc, wt, len, extents[2]-1, &fit2, NULL, &sz2);
1119     ok(fit2 == 2, "GetTextExtentExPointW extents isn't consistent with fit\n");
1120     GetTextExtentExPointW(hdc, wt, 2, 0, NULL, extents + 2, &sz2);
1121     ok(extents[0] == extents[2] && extents[1] == extents[3],
1122        "GetTextExtentExPointW with lpnFit == NULL returns incorrect results\n");
1123     GetTextExtentExPointW(hdc, wt, 2, 0, NULL, NULL, &sz1);
1124     ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy,
1125        "GetTextExtentExPointW with lpnFit and alpDx both NULL returns incorrect results\n");
1126     HeapFree(GetProcessHeap(), 0, extents);
1127
1128     /* extents functions fail with -ve counts (the interesting case being -1) */
1129     ret = GetTextExtentPointA(hdc, "o", -1, &sz);
1130     ok(ret == FALSE, "got %d\n", ret);
1131     ret = GetTextExtentExPointA(hdc, "o", -1, 0, NULL, NULL, &sz);
1132     ok(ret == FALSE, "got %d\n", ret);
1133     ret = GetTextExtentExPointW(hdc, wt, -1, 0, NULL, NULL, &sz1);
1134     ok(ret == FALSE, "got %d\n", ret);
1135
1136     hfont = SelectObject(hdc, hfont);
1137     DeleteObject(hfont);
1138     ReleaseDC(NULL, hdc);
1139 }
1140
1141 static void test_GetGlyphIndices(void)
1142 {
1143     HDC      hdc;
1144     HFONT    hfont;
1145     DWORD    charcount;
1146     LOGFONTA lf;
1147     DWORD    flags = 0;
1148     WCHAR    testtext[] = {'T','e','s','t',0xffff,0};
1149     WORD     glyphs[(sizeof(testtext)/2)-1];
1150     TEXTMETRIC textm;
1151     HFONT hOldFont;
1152
1153     if (!pGetGlyphIndicesW) {
1154         win_skip("GetGlyphIndicesW not available on platform\n");
1155         return;
1156     }
1157
1158     hdc = GetDC(0);
1159
1160     memset(&lf, 0, sizeof(lf));
1161     strcpy(lf.lfFaceName, "System");
1162     lf.lfHeight = 16;
1163     lf.lfCharSet = ANSI_CHARSET;
1164
1165     hfont = CreateFontIndirectA(&lf);
1166     ok(hfont != 0, "CreateFontIndirectEx failed\n");
1167     ok(GetTextMetrics(hdc, &textm), "GetTextMetric failed\n");
1168     if (textm.tmCharSet == ANSI_CHARSET)
1169     {
1170         flags |= GGI_MARK_NONEXISTING_GLYPHS;
1171         charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1172         ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1173         ok((glyphs[4] == 0x001f || glyphs[4] == 0xffff /* Vista */), "GetGlyphIndicesW should have returned a nonexistent char not %04x\n", glyphs[4]);
1174         flags = 0;
1175         charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1176         ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1177         ok(glyphs[4] == textm.tmDefaultChar, "GetGlyphIndicesW should have returned a %04x not %04x\n",
1178                         textm.tmDefaultChar, glyphs[4]);
1179     }
1180     else
1181         /* FIXME: Write tests for non-ANSI charsets. */
1182         skip("GetGlyphIndices System font tests only for ANSI_CHARSET\n");
1183
1184     if(!is_font_installed("Tahoma"))
1185     {
1186         skip("Tahoma is not installed so skipping this test\n");
1187         return;
1188     }
1189     memset(&lf, 0, sizeof(lf));
1190     strcpy(lf.lfFaceName, "Tahoma");
1191     lf.lfHeight = 20;
1192
1193     hfont = CreateFontIndirectA(&lf);
1194     hOldFont = SelectObject(hdc, hfont);
1195     ok(GetTextMetrics(hdc, &textm), "GetTextMetric failed\n");
1196     flags |= GGI_MARK_NONEXISTING_GLYPHS;
1197     charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1198     ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1199     ok(glyphs[4] == 0xffff, "GetGlyphIndicesW should have returned 0xffff char not %04x\n", glyphs[4]);
1200     flags = 0;
1201     testtext[0] = textm.tmDefaultChar;
1202     charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1203     ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1204     ok(glyphs[0] == 0, "GetGlyphIndicesW for tmDefaultChar should be 0 not %04x\n", glyphs[0]);
1205     ok(glyphs[4] == 0, "GetGlyphIndicesW should have returned 0 not %04x\n", glyphs[4]);
1206     DeleteObject(SelectObject(hdc, hOldFont));
1207 }
1208
1209 static void test_GetKerningPairs(void)
1210 {
1211     static const struct kerning_data
1212     {
1213         const char face_name[LF_FACESIZE];
1214         LONG height;
1215         /* some interesting fields from OUTLINETEXTMETRIC */
1216         LONG tmHeight, tmAscent, tmDescent;
1217         UINT otmEMSquare;
1218         INT  otmAscent;
1219         INT  otmDescent;
1220         UINT otmLineGap;
1221         UINT otmsCapEmHeight;
1222         UINT otmsXHeight;
1223         INT  otmMacAscent;
1224         INT  otmMacDescent;
1225         UINT otmMacLineGap;
1226         UINT otmusMinimumPPEM;
1227         /* small subset of kerning pairs to test */
1228         DWORD total_kern_pairs;
1229         const KERNINGPAIR kern_pair[26];
1230     } kd[] =
1231     {
1232         {"Arial", 12, 12, 9, 3,
1233                   2048, 7, -2, 1, 5, 2, 8, -2, 0, 9,
1234                   26,
1235             {
1236                 {' ','A',-1},{' ','T',0},{' ','Y',0},{'1','1',-1},
1237                 {'A',' ',-1},{'A','T',-1},{'A','V',-1},{'A','W',0},
1238                 {'A','Y',-1},{'A','v',0},{'A','w',0},{'A','y',0},
1239                 {'F',',',-1},{'F','.',-1},{'F','A',-1},{'L',' ',0},
1240                 {'L','T',-1},{'L','V',-1},{'L','W',-1},{'L','Y',-1},
1241                 {915,912,+1},{915,913,-1},{910,912,+1},{910,913,-1},
1242                 {933,970,+1},{933,972,-1}
1243                 }
1244         },
1245         {"Arial", -34, 39, 32, 7,
1246                   2048, 25, -7, 5, 17, 9, 31, -7, 1, 9,
1247                   26,
1248             {
1249                 {' ','A',-2},{' ','T',-1},{' ','Y',-1},{'1','1',-3},
1250                 {'A',' ',-2},{'A','T',-3},{'A','V',-3},{'A','W',-1},
1251                 {'A','Y',-3},{'A','v',-1},{'A','w',-1},{'A','y',-1},
1252                 {'F',',',-4},{'F','.',-4},{'F','A',-2},{'L',' ',-1},
1253                 {'L','T',-3},{'L','V',-3},{'L','W',-3},{'L','Y',-3},
1254                 {915,912,+3},{915,913,-3},{910,912,+3},{910,913,-3},
1255                 {933,970,+2},{933,972,-3}
1256             }
1257         },
1258         { "Arial", 120, 120, 97, 23,
1259                    2048, 79, -23, 16, 54, 27, 98, -23, 4, 9,
1260                    26,
1261             {
1262                 {' ','A',-6},{' ','T',-2},{' ','Y',-2},{'1','1',-8},
1263                 {'A',' ',-6},{'A','T',-8},{'A','V',-8},{'A','W',-4},
1264                 {'A','Y',-8},{'A','v',-2},{'A','w',-2},{'A','y',-2},
1265                 {'F',',',-12},{'F','.',-12},{'F','A',-6},{'L',' ',-4},
1266                 {'L','T',-8},{'L','V',-8},{'L','W',-8},{'L','Y',-8},
1267                 {915,912,+9},{915,913,-10},{910,912,+9},{910,913,-8},
1268                 {933,970,+6},{933,972,-10}
1269             }
1270         },
1271 #if 0 /* this set fails due to +1/-1 errors (rounding bug?), needs investigation. */
1272         { "Arial", 1024 /* usually 1/2 of EM Square */, 1024, 830, 194,
1273                    2048, 668, -193, 137, 459, 229, 830, -194, 30, 9,
1274                    26,
1275             {
1276                 {' ','A',-51},{' ','T',-17},{' ','Y',-17},{'1','1',-68},
1277                 {'A',' ',-51},{'A','T',-68},{'A','V',-68},{'A','W',-34},
1278                 {'A','Y',-68},{'A','v',-17},{'A','w',-17},{'A','y',-17},
1279                 {'F',',',-102},{'F','.',-102},{'F','A',-51},{'L',' ',-34},
1280                 {'L','T',-68},{'L','V',-68},{'L','W',-68},{'L','Y',-68},
1281                 {915,912,+73},{915,913,-84},{910,912,+76},{910,913,-68},
1282                 {933,970,+54},{933,972,-83}
1283             }
1284         }
1285 #endif
1286     };
1287     LOGFONT lf;
1288     HFONT hfont, hfont_old;
1289     KERNINGPAIR *kern_pair;
1290     HDC hdc;
1291     DWORD total_kern_pairs, ret, i, n, matches;
1292
1293     hdc = GetDC(0);
1294
1295     /* GetKerningPairsA maps unicode set of kerning pairs to current code page
1296      * which may render this test unusable, so we're trying to avoid that.
1297      */
1298     SetLastError(0xdeadbeef);
1299     GetKerningPairsW(hdc, 0, NULL);
1300     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1301     {
1302         win_skip("Skipping the GetKerningPairs test on a Win9x platform\n");
1303         ReleaseDC(0, hdc);
1304         return;
1305     }
1306
1307     for (i = 0; i < sizeof(kd)/sizeof(kd[0]); i++)
1308     {
1309         OUTLINETEXTMETRICW otm;
1310         UINT uiRet;
1311
1312         if (!is_font_installed(kd[i].face_name))
1313         {
1314             trace("%s is not installed so skipping this test\n", kd[i].face_name);
1315             continue;
1316         }
1317
1318         trace("testing font %s, height %d\n", kd[i].face_name, kd[i].height);
1319
1320         memset(&lf, 0, sizeof(lf));
1321         strcpy(lf.lfFaceName, kd[i].face_name);
1322         lf.lfHeight = kd[i].height;
1323         hfont = CreateFontIndirect(&lf);
1324         assert(hfont != 0);
1325
1326         hfont_old = SelectObject(hdc, hfont);
1327
1328         SetLastError(0xdeadbeef);
1329         otm.otmSize = sizeof(otm); /* just in case for Win9x compatibility */
1330         uiRet = GetOutlineTextMetricsW(hdc, sizeof(otm), &otm);
1331         ok(uiRet == sizeof(otm), "GetOutlineTextMetricsW error %d\n", GetLastError());
1332
1333         ok(match_off_by_1(kd[i].tmHeight, otm.otmTextMetrics.tmHeight), "expected %d, got %d\n",
1334            kd[i].tmHeight, otm.otmTextMetrics.tmHeight);
1335         ok(match_off_by_1(kd[i].tmAscent, otm.otmTextMetrics.tmAscent), "expected %d, got %d\n",
1336            kd[i].tmAscent, otm.otmTextMetrics.tmAscent);
1337         ok(kd[i].tmDescent == otm.otmTextMetrics.tmDescent, "expected %d, got %d\n",
1338            kd[i].tmDescent, otm.otmTextMetrics.tmDescent);
1339
1340         ok(kd[i].otmEMSquare == otm.otmEMSquare, "expected %u, got %u\n",
1341            kd[i].otmEMSquare, otm.otmEMSquare);
1342         ok(kd[i].otmAscent == otm.otmAscent, "expected %d, got %d\n",
1343            kd[i].otmAscent, otm.otmAscent);
1344         ok(kd[i].otmDescent == otm.otmDescent, "expected %d, got %d\n",
1345            kd[i].otmDescent, otm.otmDescent);
1346         ok(kd[i].otmLineGap == otm.otmLineGap, "expected %u, got %u\n",
1347            kd[i].otmLineGap, otm.otmLineGap);
1348         ok(near_match(kd[i].otmMacDescent, otm.otmMacDescent), "expected %d, got %d\n",
1349            kd[i].otmMacDescent, otm.otmMacDescent);
1350         ok(near_match(kd[i].otmMacAscent, otm.otmMacAscent), "expected %d, got %d\n",
1351            kd[i].otmMacAscent, otm.otmMacAscent);
1352 todo_wine {
1353         ok(kd[i].otmsCapEmHeight == otm.otmsCapEmHeight, "expected %u, got %u\n",
1354            kd[i].otmsCapEmHeight, otm.otmsCapEmHeight);
1355         ok(kd[i].otmsXHeight == otm.otmsXHeight, "expected %u, got %u\n",
1356            kd[i].otmsXHeight, otm.otmsXHeight);
1357         /* FIXME: this one sometimes succeeds due to expected 0, enable it when removing todo */
1358         if (0) ok(kd[i].otmMacLineGap == otm.otmMacLineGap, "expected %u, got %u\n",
1359            kd[i].otmMacLineGap, otm.otmMacLineGap);
1360         ok(kd[i].otmusMinimumPPEM == otm.otmusMinimumPPEM, "expected %u, got %u\n",
1361            kd[i].otmusMinimumPPEM, otm.otmusMinimumPPEM);
1362 }
1363
1364         total_kern_pairs = GetKerningPairsW(hdc, 0, NULL);
1365         trace("total_kern_pairs %u\n", total_kern_pairs);
1366         kern_pair = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pair));
1367
1368         /* Win98 (GetKerningPairsA) and XP behave differently here, the test
1369          * passes on XP.
1370          */
1371         SetLastError(0xdeadbeef);
1372         ret = GetKerningPairsW(hdc, 0, kern_pair);
1373         ok(GetLastError() == ERROR_INVALID_PARAMETER,
1374            "got error %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
1375         ok(ret == 0, "got %u, expected 0\n", ret);
1376
1377         ret = GetKerningPairsW(hdc, 100, NULL);
1378         ok(ret == total_kern_pairs, "got %u, expected %u\n", ret, total_kern_pairs);
1379
1380         ret = GetKerningPairsW(hdc, total_kern_pairs/2, kern_pair);
1381         ok(ret == total_kern_pairs/2, "got %u, expected %u\n", ret, total_kern_pairs/2);
1382
1383         ret = GetKerningPairsW(hdc, total_kern_pairs, kern_pair);
1384         ok(ret == total_kern_pairs, "got %u, expected %u\n", ret, total_kern_pairs);
1385
1386         matches = 0;
1387
1388         for (n = 0; n < ret; n++)
1389         {
1390             DWORD j;
1391             /* Disabled to limit console spam */
1392             if (0 && kern_pair[n].wFirst < 127 && kern_pair[n].wSecond < 127)
1393                 trace("{'%c','%c',%d},\n",
1394                       kern_pair[n].wFirst, kern_pair[n].wSecond, kern_pair[n].iKernAmount);
1395             for (j = 0; j < kd[i].total_kern_pairs; j++)
1396             {
1397                 if (kern_pair[n].wFirst == kd[i].kern_pair[j].wFirst &&
1398                     kern_pair[n].wSecond == kd[i].kern_pair[j].wSecond)
1399                 {
1400                     ok(kern_pair[n].iKernAmount == kd[i].kern_pair[j].iKernAmount,
1401                        "pair %d:%d got %d, expected %d\n",
1402                        kern_pair[n].wFirst, kern_pair[n].wSecond,
1403                        kern_pair[n].iKernAmount, kd[i].kern_pair[j].iKernAmount);
1404                     matches++;
1405                 }
1406             }
1407         }
1408
1409         ok(matches == kd[i].total_kern_pairs, "got matches %u, expected %u\n",
1410            matches, kd[i].total_kern_pairs);
1411
1412         HeapFree(GetProcessHeap(), 0, kern_pair);
1413
1414         SelectObject(hdc, hfont_old);
1415         DeleteObject(hfont);
1416     }
1417
1418     ReleaseDC(0, hdc);
1419 }
1420
1421 static void test_height_selection(void)
1422 {
1423     static const struct font_data
1424     {
1425         const char face_name[LF_FACESIZE];
1426         int requested_height;
1427         int weight, height, ascent, descent, int_leading, ext_leading, dpi;
1428     } fd[] =
1429     {
1430         {"Tahoma", -12, FW_NORMAL, 14, 12, 2, 2, 0, 96 },
1431         {"Tahoma", -24, FW_NORMAL, 29, 24, 5, 5, 0, 96 },
1432         {"Tahoma", -48, FW_NORMAL, 58, 48, 10, 10, 0, 96 },
1433         {"Tahoma", -96, FW_NORMAL, 116, 96, 20, 20, 0, 96 },
1434         {"Tahoma", -192, FW_NORMAL, 232, 192, 40, 40, 0, 96 },
1435         {"Tahoma", 12, FW_NORMAL, 12, 10, 2, 2, 0, 96 },
1436         {"Tahoma", 24, FW_NORMAL, 24, 20, 4, 4, 0, 96 },
1437         {"Tahoma", 48, FW_NORMAL, 48, 40, 8, 8, 0, 96 },
1438         {"Tahoma", 96, FW_NORMAL, 96, 80, 16, 17, 0, 96 },
1439         {"Tahoma", 192, FW_NORMAL, 192, 159, 33, 33, 0, 96 }
1440     };
1441     HDC hdc;
1442     LOGFONT lf;
1443     HFONT hfont, old_hfont;
1444     TEXTMETRIC tm;
1445     INT ret, i;
1446
1447     hdc = CreateCompatibleDC(0);
1448     assert(hdc);
1449
1450     for (i = 0; i < sizeof(fd)/sizeof(fd[0]); i++)
1451     {
1452         if (!is_truetype_font_installed(fd[i].face_name))
1453         {
1454             skip("%s is not installed\n", fd[i].face_name);
1455             continue;
1456         }
1457
1458         memset(&lf, 0, sizeof(lf));
1459         lf.lfHeight = fd[i].requested_height;
1460         lf.lfWeight = fd[i].weight;
1461         strcpy(lf.lfFaceName, fd[i].face_name);
1462
1463         hfont = CreateFontIndirect(&lf);
1464         assert(hfont);
1465
1466         old_hfont = SelectObject(hdc, hfont);
1467         ret = GetTextMetrics(hdc, &tm);
1468         ok(ret, "GetTextMetrics error %d\n", GetLastError());
1469         if(fd[i].dpi == tm.tmDigitizedAspectX)
1470         {
1471             trace("found font %s, height %d charset %x dpi %d\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet, fd[i].dpi);
1472             ok(tm.tmWeight == fd[i].weight, "%s(%d): tm.tmWeight %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmWeight, fd[i].weight);
1473             ok(match_off_by_1(tm.tmHeight, fd[i].height), "%s(%d): tm.tmHeight %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmHeight, fd[i].height);
1474             ok(match_off_by_1(tm.tmAscent, fd[i].ascent), "%s(%d): tm.tmAscent %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmAscent, fd[i].ascent);
1475             ok(match_off_by_1(tm.tmDescent, fd[i].descent), "%s(%d): tm.tmDescent %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmDescent, fd[i].descent);
1476 #if 0 /* FIXME: calculation of tmInternalLeading in Wine doesn't match what Windows does */
1477             ok(tm.tmInternalLeading == fd[i].int_leading, "%s(%d): tm.tmInternalLeading %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmInternalLeading, fd[i].int_leading);
1478 #endif
1479             ok(tm.tmExternalLeading == fd[i].ext_leading, "%s(%d): tm.tmExternalLeading %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmExternalLeading, fd[i].ext_leading);
1480         }
1481
1482         SelectObject(hdc, old_hfont);
1483         DeleteObject(hfont);
1484     }
1485
1486     DeleteDC(hdc);
1487 }
1488
1489 static void test_GetOutlineTextMetrics(void)
1490 {
1491     OUTLINETEXTMETRIC *otm;
1492     LOGFONT lf;
1493     HFONT hfont, hfont_old;
1494     HDC hdc;
1495     DWORD ret, otm_size;
1496     LPSTR unset_ptr;
1497
1498     if (!is_font_installed("Arial"))
1499     {
1500         skip("Arial is not installed\n");
1501         return;
1502     }
1503
1504     hdc = GetDC(0);
1505
1506     memset(&lf, 0, sizeof(lf));
1507     strcpy(lf.lfFaceName, "Arial");
1508     lf.lfHeight = -13;
1509     lf.lfWeight = FW_NORMAL;
1510     lf.lfPitchAndFamily = DEFAULT_PITCH;
1511     lf.lfQuality = PROOF_QUALITY;
1512     hfont = CreateFontIndirect(&lf);
1513     assert(hfont != 0);
1514
1515     hfont_old = SelectObject(hdc, hfont);
1516     otm_size = GetOutlineTextMetrics(hdc, 0, NULL);
1517     trace("otm buffer size %u (0x%x)\n", otm_size, otm_size);
1518
1519     otm = HeapAlloc(GetProcessHeap(), 0, otm_size);
1520
1521     memset(otm, 0xAA, otm_size);
1522     SetLastError(0xdeadbeef);
1523     otm->otmSize = sizeof(*otm); /* just in case for Win9x compatibility */
1524     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1525     ok(ret == 1 /* Win9x */ ||
1526        ret == otm->otmSize /* XP*/,
1527        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1528     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1529     {
1530         ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
1531         ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
1532         ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
1533         ok(otm->otmpFullName == NULL, "expected NULL got %p\n", otm->otmpFullName);
1534     }
1535
1536     memset(otm, 0xAA, otm_size);
1537     SetLastError(0xdeadbeef);
1538     otm->otmSize = otm_size; /* just in case for Win9x compatibility */
1539     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1540     ok(ret == 1 /* Win9x */ ||
1541        ret == otm->otmSize /* XP*/,
1542        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1543     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1544     {
1545         ok(otm->otmpFamilyName != NULL, "expected not NULL got %p\n", otm->otmpFamilyName);
1546         ok(otm->otmpFaceName != NULL, "expected not NULL got %p\n", otm->otmpFaceName);
1547         ok(otm->otmpStyleName != NULL, "expected not NULL got %p\n", otm->otmpStyleName);
1548         ok(otm->otmpFullName != NULL, "expected not NULL got %p\n", otm->otmpFullName);
1549     }
1550
1551     /* ask about truncated data */
1552     memset(otm, 0xAA, otm_size);
1553     memset(&unset_ptr, 0xAA, sizeof(unset_ptr));
1554     SetLastError(0xdeadbeef);
1555     otm->otmSize = sizeof(*otm) - sizeof(LPSTR); /* just in case for Win9x compatibility */
1556     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1557     ok(ret == 1 /* Win9x */ ||
1558        ret == otm->otmSize /* XP*/,
1559        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1560     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1561     {
1562         ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
1563         ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
1564         ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
1565     }
1566     ok(otm->otmpFullName == unset_ptr, "expected %p got %p\n", unset_ptr, otm->otmpFullName);
1567
1568     HeapFree(GetProcessHeap(), 0, otm);
1569
1570     SelectObject(hdc, hfont_old);
1571     DeleteObject(hfont);
1572
1573     ReleaseDC(0, hdc);
1574 }
1575
1576 static void testJustification(HDC hdc, PSTR str, RECT *clientArea)
1577 {
1578     INT         y,
1579                 breakCount,
1580                 justifiedWidth = 0, /* to test GetTextExtentExPointW() */
1581                 areaWidth = clientArea->right - clientArea->left,
1582                 nErrors = 0, e;
1583     BOOL        lastExtent = FALSE;
1584     PSTR        pFirstChar, pLastChar;
1585     SIZE        size;
1586     TEXTMETRICA tm;
1587     struct err
1588     {
1589         char extent[100];
1590         int  GetTextExtentExPointWWidth;
1591     } error[10];
1592
1593     GetTextMetricsA(hdc, &tm);
1594     y = clientArea->top;
1595     do {
1596         breakCount = 0;
1597         while (*str == tm.tmBreakChar) str++; /* skip leading break chars */
1598         pFirstChar = str;
1599
1600         do {
1601             pLastChar = str;
1602
1603             /* if not at the end of the string, ... */
1604             if (*str == '\0') break;
1605             /* ... add the next word to the current extent */
1606             while (*str != '\0' && *str++ != tm.tmBreakChar);
1607             breakCount++;
1608             SetTextJustification(hdc, 0, 0);
1609             GetTextExtentPoint32(hdc, pFirstChar, str - pFirstChar - 1, &size);
1610         } while ((int) size.cx < areaWidth);
1611
1612         /* ignore trailing break chars */
1613         breakCount--;
1614         while (*(pLastChar - 1) == tm.tmBreakChar)
1615         {
1616             pLastChar--;
1617             breakCount--;
1618         }
1619
1620         if (*str == '\0' || breakCount <= 0) pLastChar = str;
1621
1622         SetTextJustification(hdc, 0, 0);
1623         GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
1624
1625         /* do not justify the last extent */
1626         if (*str != '\0' && breakCount > 0)
1627         {
1628             SetTextJustification(hdc, areaWidth - size.cx, breakCount);
1629             GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
1630             justifiedWidth = size.cx;
1631         }
1632         else lastExtent = TRUE;
1633
1634         /* catch errors and report them */
1635         if (!lastExtent && (justifiedWidth != areaWidth))
1636         {
1637             memset(error[nErrors].extent, 0, 100);
1638             memcpy(error[nErrors].extent, pFirstChar, pLastChar - pFirstChar);
1639             error[nErrors].GetTextExtentExPointWWidth = justifiedWidth;
1640             nErrors++;
1641         }
1642
1643         y += size.cy;
1644         str = pLastChar;
1645     } while (*str && y < clientArea->bottom);
1646
1647     for (e = 0; e < nErrors; e++)
1648     {
1649         /* The width returned by GetTextExtentPoint32() is exactly the same
1650            returned by GetTextExtentExPointW() - see dlls/gdi32/font.c */
1651         ok(error[e].GetTextExtentExPointWWidth == areaWidth,
1652             "GetTextExtentPointW() for \"%s\" should have returned a width of %d, not %d.\n",
1653             error[e].extent, areaWidth, error[e].GetTextExtentExPointWWidth);
1654     }
1655 }
1656
1657 static void test_SetTextJustification(void)
1658 {
1659     HDC hdc;
1660     RECT clientArea;
1661     LOGFONTA lf;
1662     HFONT hfont;
1663     HWND hwnd;
1664     static char testText[] =
1665             "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
1666             "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
1667             "enim ad minim veniam, quis nostrud exercitation ullamco laboris "
1668             "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in "
1669             "reprehenderit in voluptate velit esse cillum dolore eu fugiat "
1670             "nulla pariatur. Excepteur sint occaecat cupidatat non proident, "
1671             "sunt in culpa qui officia deserunt mollit anim id est laborum.";
1672
1673     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0, 400,400, 0, 0, 0, NULL);
1674     GetClientRect( hwnd, &clientArea );
1675     hdc = GetDC( hwnd );
1676
1677     memset(&lf, 0, sizeof lf);
1678     lf.lfCharSet = ANSI_CHARSET;
1679     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1680     lf.lfWeight = FW_DONTCARE;
1681     lf.lfHeight = 20;
1682     lf.lfQuality = DEFAULT_QUALITY;
1683     lstrcpyA(lf.lfFaceName, "Times New Roman");
1684     hfont = create_font("Times New Roman", &lf);
1685     SelectObject(hdc, hfont);
1686
1687     testJustification(hdc, testText, &clientArea);
1688
1689     DeleteObject(hfont);
1690     ReleaseDC(hwnd, hdc);
1691     DestroyWindow(hwnd);
1692 }
1693
1694 static BOOL get_glyph_indices(INT charset, UINT code_page, WORD *idx, UINT count, BOOL unicode)
1695 {
1696     HDC hdc;
1697     LOGFONTA lf;
1698     HFONT hfont, hfont_old;
1699     CHARSETINFO csi;
1700     FONTSIGNATURE fs;
1701     INT cs;
1702     DWORD i, ret;
1703     char name[64];
1704
1705     assert(count <= 128);
1706
1707     memset(&lf, 0, sizeof(lf));
1708
1709     lf.lfCharSet = charset;
1710     lf.lfHeight = 10;
1711     lstrcpyA(lf.lfFaceName, "Arial");
1712     SetLastError(0xdeadbeef);
1713     hfont = CreateFontIndirectA(&lf);
1714     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
1715
1716     hdc = GetDC(0);
1717     hfont_old = SelectObject(hdc, hfont);
1718
1719     cs = GetTextCharsetInfo(hdc, &fs, 0);
1720     ok(cs == charset, "expected %d, got %d\n", charset, cs);
1721
1722     SetLastError(0xdeadbeef);
1723     ret = GetTextFaceA(hdc, sizeof(name), name);
1724     ok(ret, "GetTextFaceA error %u\n", GetLastError());
1725
1726     if (charset == SYMBOL_CHARSET)
1727     {
1728         ok(strcmp("Arial", name), "face name should NOT be Arial\n");
1729         ok(fs.fsCsb[0] & (1 << 31), "symbol encoding should be available\n");
1730     }
1731     else
1732     {
1733         ok(!strcmp("Arial", name), "face name should be Arial, not %s\n", name);
1734         ok(!(fs.fsCsb[0] & (1 << 31)), "symbol encoding should NOT be available\n");
1735     }
1736
1737     if (!TranslateCharsetInfo((DWORD *)(INT_PTR)cs, &csi, TCI_SRCCHARSET))
1738     {
1739         trace("Can't find codepage for charset %d\n", cs);
1740         ReleaseDC(0, hdc);
1741         return FALSE;
1742     }
1743     ok(csi.ciACP == code_page, "expected %d, got %d\n", code_page, csi.ciACP);
1744
1745     if (pGdiGetCodePage != NULL && pGdiGetCodePage(hdc) != code_page)
1746     {
1747         skip("Font code page %d, looking for code page %d\n",
1748              pGdiGetCodePage(hdc), code_page);
1749         ReleaseDC(0, hdc);
1750         return FALSE;
1751     }
1752
1753     if (unicode)
1754     {
1755         char ansi_buf[128];
1756         WCHAR unicode_buf[128];
1757
1758         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
1759
1760         MultiByteToWideChar(code_page, 0, ansi_buf, count, unicode_buf, count);
1761
1762         SetLastError(0xdeadbeef);
1763         ret = pGetGlyphIndicesW(hdc, unicode_buf, count, idx, 0);
1764         ok(ret == count, "GetGlyphIndicesW expected %d got %d, error %u\n",
1765            count, ret, GetLastError());
1766     }
1767     else
1768     {
1769         char ansi_buf[128];
1770
1771         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
1772
1773         SetLastError(0xdeadbeef);
1774         ret = pGetGlyphIndicesA(hdc, ansi_buf, count, idx, 0);
1775         ok(ret == count, "GetGlyphIndicesA expected %d got %d, error %u\n",
1776            count, ret, GetLastError());
1777     }
1778
1779     SelectObject(hdc, hfont_old);
1780     DeleteObject(hfont);
1781
1782     ReleaseDC(0, hdc);
1783
1784     return TRUE;
1785 }
1786
1787 static void test_font_charset(void)
1788 {
1789     static struct charset_data
1790     {
1791         INT charset;
1792         UINT code_page;
1793         WORD font_idxA[128], font_idxW[128];
1794     } cd[] =
1795     {
1796         { ANSI_CHARSET, 1252 },
1797         { RUSSIAN_CHARSET, 1251 },
1798         { SYMBOL_CHARSET, CP_SYMBOL } /* keep it as the last one */
1799     };
1800     int i;
1801
1802     if (!pGetGlyphIndicesA || !pGetGlyphIndicesW)
1803     {
1804         win_skip("Skipping the font charset test on a Win9x platform\n");
1805         return;
1806     }
1807
1808     if (!is_font_installed("Arial"))
1809     {
1810         skip("Arial is not installed\n");
1811         return;
1812     }
1813
1814     for (i = 0; i < sizeof(cd)/sizeof(cd[0]); i++)
1815     {
1816         if (cd[i].charset == SYMBOL_CHARSET)
1817         {
1818             if (!is_font_installed("Symbol") && !is_font_installed("Wingdings"))
1819             {
1820                 skip("Symbol or Wingdings is not installed\n");
1821                 break;
1822             }
1823         }
1824         if (get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxA, 128, FALSE) &&
1825             get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxW, 128, TRUE))
1826             ok(!memcmp(cd[i].font_idxA, cd[i].font_idxW, 128*sizeof(WORD)), "%d: indices don't match\n", i);
1827     }
1828
1829     ok(memcmp(cd[0].font_idxW, cd[1].font_idxW, 128*sizeof(WORD)), "0 vs 1: indices shouldn't match\n");
1830     if (i > 2)
1831     {
1832         ok(memcmp(cd[0].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "0 vs 2: indices shouldn't match\n");
1833         ok(memcmp(cd[1].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "1 vs 2: indices shouldn't match\n");
1834     }
1835     else
1836         skip("Symbol or Wingdings is not installed\n");
1837 }
1838
1839 static void test_GetFontUnicodeRanges(void)
1840 {
1841     LOGFONTA lf;
1842     HDC hdc;
1843     HFONT hfont, hfont_old;
1844     DWORD size;
1845     GLYPHSET *gs;
1846     DWORD i;
1847
1848     if (!pGetFontUnicodeRanges)
1849     {
1850         win_skip("GetFontUnicodeRanges not available before W2K\n");
1851         return;
1852     }
1853
1854     memset(&lf, 0, sizeof(lf));
1855     lstrcpyA(lf.lfFaceName, "Arial");
1856     hfont = create_font("Arial", &lf);
1857
1858     hdc = GetDC(0);
1859     hfont_old = SelectObject(hdc, hfont);
1860
1861     size = pGetFontUnicodeRanges(NULL, NULL);
1862     ok(!size, "GetFontUnicodeRanges succeeded unexpectedly\n");
1863
1864     size = pGetFontUnicodeRanges(hdc, NULL);
1865     ok(size, "GetFontUnicodeRanges failed unexpectedly\n");
1866
1867     gs = HeapAlloc(GetProcessHeap(), 0, size);
1868
1869     size = pGetFontUnicodeRanges(hdc, gs);
1870     ok(size, "GetFontUnicodeRanges failed\n");
1871
1872     if (0) /* Disabled to limit console spam */
1873         for (i = 0; i < gs->cRanges; i++)
1874             trace("%03d wcLow %04x cGlyphs %u\n", i, gs->ranges[i].wcLow, gs->ranges[i].cGlyphs);
1875     trace("found %u ranges\n", gs->cRanges);
1876
1877     HeapFree(GetProcessHeap(), 0, gs);
1878
1879     SelectObject(hdc, hfont_old);
1880     DeleteObject(hfont);
1881     ReleaseDC(NULL, hdc);
1882 }
1883
1884 #define MAX_ENUM_FONTS 4096
1885
1886 struct enum_font_data
1887 {
1888     int total;
1889     LOGFONT lf[MAX_ENUM_FONTS];
1890 };
1891
1892 struct enum_font_dataW
1893 {
1894     int total;
1895     LOGFONTW lf[MAX_ENUM_FONTS];
1896 };
1897
1898 static INT CALLBACK arial_enum_proc(const LOGFONT *lf, const TEXTMETRIC *tm, DWORD type, LPARAM lParam)
1899 {
1900     struct enum_font_data *efd = (struct enum_font_data *)lParam;
1901
1902     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
1903
1904     if (type != TRUETYPE_FONTTYPE) return 1;
1905     if (0) /* Disabled to limit console spam */
1906         trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
1907               lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
1908     if (efd->total < MAX_ENUM_FONTS)
1909         efd->lf[efd->total++] = *lf;
1910     else
1911         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
1912
1913     return 1;
1914 }
1915
1916 static INT CALLBACK arial_enum_procw(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
1917 {
1918     struct enum_font_dataW *efd = (struct enum_font_dataW *)lParam;
1919
1920     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
1921
1922     if (type != TRUETYPE_FONTTYPE) return 1;
1923     if (0) /* Disabled to limit console spam */
1924         trace("enumed font %s, charset %d, height %d, weight %d, italic %d\n",
1925               wine_dbgstr_w(lf->lfFaceName), lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
1926     if (efd->total < MAX_ENUM_FONTS)
1927         efd->lf[efd->total++] = *lf;
1928     else
1929         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
1930
1931     return 1;
1932 }
1933
1934 static void get_charset_stats(struct enum_font_data *efd,
1935                               int *ansi_charset, int *symbol_charset,
1936                               int *russian_charset)
1937 {
1938     int i;
1939
1940     *ansi_charset = 0;
1941     *symbol_charset = 0;
1942     *russian_charset = 0;
1943
1944     for (i = 0; i < efd->total; i++)
1945     {
1946         switch (efd->lf[i].lfCharSet)
1947         {
1948         case ANSI_CHARSET:
1949             (*ansi_charset)++;
1950             break;
1951         case SYMBOL_CHARSET:
1952             (*symbol_charset)++;
1953             break;
1954         case RUSSIAN_CHARSET:
1955             (*russian_charset)++;
1956             break;
1957         }
1958     }
1959 }
1960
1961 static void get_charset_statsW(struct enum_font_dataW *efd,
1962                               int *ansi_charset, int *symbol_charset,
1963                               int *russian_charset)
1964 {
1965     int i;
1966
1967     *ansi_charset = 0;
1968     *symbol_charset = 0;
1969     *russian_charset = 0;
1970
1971     for (i = 0; i < efd->total; i++)
1972     {
1973         switch (efd->lf[i].lfCharSet)
1974         {
1975         case ANSI_CHARSET:
1976             (*ansi_charset)++;
1977             break;
1978         case SYMBOL_CHARSET:
1979             (*symbol_charset)++;
1980             break;
1981         case RUSSIAN_CHARSET:
1982             (*russian_charset)++;
1983             break;
1984         }
1985     }
1986 }
1987
1988 static void test_EnumFontFamilies(const char *font_name, INT font_charset)
1989 {
1990     struct enum_font_data efd;
1991     struct enum_font_dataW efdw;
1992     LOGFONT lf;
1993     HDC hdc;
1994     int i, ret, ansi_charset, symbol_charset, russian_charset;
1995
1996     trace("Testing font %s, charset %d\n", *font_name ? font_name : "<empty>", font_charset);
1997
1998     if (*font_name && !is_truetype_font_installed(font_name))
1999     {
2000         skip("%s is not installed\n", font_name);
2001         return;
2002     }
2003
2004     hdc = GetDC(0);
2005
2006     /* Observed behaviour: EnumFontFamilies enumerates aliases like "Arial Cyr"
2007      * while EnumFontFamiliesEx doesn't.
2008      */
2009     if (!*font_name && font_charset == DEFAULT_CHARSET) /* do it only once */
2010     {
2011         /*
2012          * Use EnumFontFamiliesW since win98 crashes when the
2013          *    second parameter is NULL using EnumFontFamilies
2014          */
2015         efdw.total = 0;
2016         SetLastError(0xdeadbeef);
2017         ret = EnumFontFamiliesW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw);
2018         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesW error %u\n", GetLastError());
2019         if(ret)
2020         {
2021             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
2022             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
2023                   ansi_charset, symbol_charset, russian_charset);
2024             ok(efdw.total > 0, "fonts enumerated: NULL\n");
2025             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
2026             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
2027             ok(russian_charset > 0 ||
2028                broken(russian_charset == 0), /* NT4 */
2029                "NULL family should enumerate RUSSIAN_CHARSET\n");
2030         }
2031
2032         efdw.total = 0;
2033         SetLastError(0xdeadbeef);
2034         ret = EnumFontFamiliesExW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw, 0);
2035         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesExW error %u\n", GetLastError());
2036         if(ret)
2037         {
2038             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
2039             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
2040                   ansi_charset, symbol_charset, russian_charset);
2041             ok(efdw.total > 0, "fonts enumerated: NULL\n");
2042             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
2043             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
2044             ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
2045         }
2046     }
2047
2048     efd.total = 0;
2049     SetLastError(0xdeadbeef);
2050     ret = EnumFontFamilies(hdc, font_name, arial_enum_proc, (LPARAM)&efd);
2051     ok(ret, "EnumFontFamilies error %u\n", GetLastError());
2052     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2053     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s\n",
2054           ansi_charset, symbol_charset, russian_charset,
2055           *font_name ? font_name : "<empty>");
2056     if (*font_name)
2057         ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
2058     else
2059         ok(!efd.total, "no fonts should be enumerated for empty font_name\n");
2060     for (i = 0; i < efd.total; i++)
2061     {
2062 /* FIXME: remove completely once Wine is fixed */
2063 if (efd.lf[i].lfCharSet != font_charset)
2064 {
2065 todo_wine
2066     ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2067 }
2068 else
2069         ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2070         ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2071            font_name, efd.lf[i].lfFaceName);
2072     }
2073
2074     memset(&lf, 0, sizeof(lf));
2075     lf.lfCharSet = ANSI_CHARSET;
2076     lstrcpy(lf.lfFaceName, font_name);
2077     efd.total = 0;
2078     SetLastError(0xdeadbeef);
2079     ret = EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2080     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2081     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2082     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s ANSI_CHARSET\n",
2083           ansi_charset, symbol_charset, russian_charset,
2084           *font_name ? font_name : "<empty>");
2085     if (font_charset == SYMBOL_CHARSET)
2086     {
2087         if (*font_name)
2088             ok(efd.total == 0, "no fonts should be enumerated: %s ANSI_CHARSET\n", font_name);
2089         else
2090             ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
2091     }
2092     else
2093     {
2094         ok(efd.total > 0, "no fonts enumerated: %s ANSI_CHARSET\n", font_name);
2095         for (i = 0; i < efd.total; i++)
2096         {
2097             ok(efd.lf[i].lfCharSet == ANSI_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2098             if (*font_name)
2099                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2100                    font_name, efd.lf[i].lfFaceName);
2101         }
2102     }
2103
2104     /* DEFAULT_CHARSET should enumerate all available charsets */
2105     memset(&lf, 0, sizeof(lf));
2106     lf.lfCharSet = DEFAULT_CHARSET;
2107     lstrcpy(lf.lfFaceName, font_name);
2108     efd.total = 0;
2109     SetLastError(0xdeadbeef);
2110     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2111     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2112     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2113     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s DEFAULT_CHARSET\n",
2114           ansi_charset, symbol_charset, russian_charset,
2115           *font_name ? font_name : "<empty>");
2116     ok(efd.total > 0, "no fonts enumerated: %s DEFAULT_CHARSET\n", font_name);
2117     for (i = 0; i < efd.total; i++)
2118     {
2119         if (*font_name)
2120             ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2121                font_name, efd.lf[i].lfFaceName);
2122     }
2123     if (*font_name)
2124     {
2125         switch (font_charset)
2126         {
2127         case ANSI_CHARSET:
2128             ok(ansi_charset > 0,
2129                "ANSI_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
2130             ok(!symbol_charset,
2131                "ANSI_CHARSET should NOT enumerate SYMBOL_CHARSET for %s\n", font_name);
2132             ok(russian_charset > 0,
2133                "ANSI_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
2134             break;
2135         case SYMBOL_CHARSET:
2136             ok(!ansi_charset,
2137                "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", font_name);
2138             ok(symbol_charset,
2139                "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
2140             ok(!russian_charset,
2141                "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", font_name);
2142             break;
2143         case DEFAULT_CHARSET:
2144             ok(ansi_charset > 0,
2145                "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
2146             ok(symbol_charset > 0,
2147                "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
2148             ok(russian_charset > 0,
2149                "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
2150             break;
2151         }
2152     }
2153     else
2154     {
2155         ok(ansi_charset > 0,
2156            "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2157         ok(symbol_charset > 0,
2158            "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2159         ok(russian_charset > 0,
2160            "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2161     }
2162
2163     memset(&lf, 0, sizeof(lf));
2164     lf.lfCharSet = SYMBOL_CHARSET;
2165     lstrcpy(lf.lfFaceName, font_name);
2166     efd.total = 0;
2167     SetLastError(0xdeadbeef);
2168     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2169     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2170     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2171     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s SYMBOL_CHARSET\n",
2172           ansi_charset, symbol_charset, russian_charset,
2173           *font_name ? font_name : "<empty>");
2174     if (*font_name && font_charset == ANSI_CHARSET)
2175         ok(efd.total == 0, "no fonts should be enumerated: %s SYMBOL_CHARSET\n", font_name);
2176     else
2177     {
2178         ok(efd.total > 0, "no fonts enumerated: %s SYMBOL_CHARSET\n", font_name);
2179         for (i = 0; i < efd.total; i++)
2180         {
2181             ok(efd.lf[i].lfCharSet == SYMBOL_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2182             if (*font_name)
2183                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2184                    font_name, efd.lf[i].lfFaceName);
2185         }
2186
2187         ok(!ansi_charset,
2188            "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2189         ok(symbol_charset > 0,
2190            "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2191         ok(!russian_charset,
2192            "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2193     }
2194
2195     ReleaseDC(0, hdc);
2196 }
2197
2198 static INT CALLBACK enum_font_data_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
2199 {
2200     struct enum_font_data *efd = (struct enum_font_data *)lParam;
2201
2202     if (type != TRUETYPE_FONTTYPE) return 1;
2203
2204     if (efd->total < MAX_ENUM_FONTS)
2205         efd->lf[efd->total++] = *lf;
2206     else
2207         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
2208
2209     return 1;
2210 }
2211
2212 static void test_EnumFontFamiliesEx_default_charset(void)
2213 {
2214     struct enum_font_data efd;
2215     LOGFONT gui_font, enum_font;
2216     DWORD ret;
2217     HDC hdc;
2218
2219     ret = GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(gui_font), &gui_font);
2220     ok(ret, "GetObject failed.\n");
2221     if (!ret)
2222         return;
2223
2224     efd.total = 0;
2225
2226     hdc = GetDC(0);
2227     memset(&enum_font, 0, sizeof(enum_font));
2228     lstrcpy(enum_font.lfFaceName, gui_font.lfFaceName);
2229     enum_font.lfCharSet = DEFAULT_CHARSET;
2230     EnumFontFamiliesEx(hdc, &enum_font, enum_font_data_proc, (LPARAM)&efd, 0);
2231     ReleaseDC(0, hdc);
2232
2233     if (efd.total == 0) {
2234         skip("'%s' is not found or not a TrueType font.\n", gui_font.lfFaceName);
2235         return;
2236     }
2237     trace("'%s' has %d charsets.\n", gui_font.lfFaceName, efd.total);
2238
2239     ok(efd.lf[0].lfCharSet == gui_font.lfCharSet,
2240        "(%s) got charset %d expected %d\n",
2241        efd.lf[0].lfFaceName, efd.lf[0].lfCharSet, gui_font.lfCharSet);
2242
2243     return;
2244 }
2245
2246 static void test_negative_width(HDC hdc, const LOGFONTA *lf)
2247 {
2248     HFONT hfont, hfont_prev;
2249     DWORD ret;
2250     GLYPHMETRICS gm1, gm2;
2251     LOGFONTA lf2 = *lf;
2252     WORD idx;
2253
2254     if(!pGetGlyphIndicesA)
2255         return;
2256
2257     /* negative widths are handled just as positive ones */
2258     lf2.lfWidth = -lf->lfWidth;
2259
2260     SetLastError(0xdeadbeef);
2261     hfont = CreateFontIndirectA(lf);
2262     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2263     check_font("original", lf, hfont);
2264
2265     hfont_prev = SelectObject(hdc, hfont);
2266
2267     ret = pGetGlyphIndicesA(hdc, "x", 1, &idx, GGI_MARK_NONEXISTING_GLYPHS);
2268     if (ret == GDI_ERROR || idx == 0xffff)
2269     {
2270         SelectObject(hdc, hfont_prev);
2271         DeleteObject(hfont);
2272         skip("Font %s doesn't contain 'x', skipping the test\n", lf->lfFaceName);
2273         return;
2274     }
2275
2276     /* filling with 0xaa causes false pass under WINEDEBUG=warn+heap */
2277     memset(&gm1, 0xab, sizeof(gm1));
2278     SetLastError(0xdeadbeef);
2279     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm1, 0, NULL, &mat);
2280     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
2281
2282     SelectObject(hdc, hfont_prev);
2283     DeleteObject(hfont);
2284
2285     SetLastError(0xdeadbeef);
2286     hfont = CreateFontIndirectA(&lf2);
2287     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2288     check_font("negative width", &lf2, hfont);
2289
2290     hfont_prev = SelectObject(hdc, hfont);
2291
2292     memset(&gm2, 0xbb, sizeof(gm2));
2293     SetLastError(0xdeadbeef);
2294     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm2, 0, NULL, &mat);
2295     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
2296
2297     SelectObject(hdc, hfont_prev);
2298     DeleteObject(hfont);
2299
2300     ok(gm1.gmBlackBoxX == gm2.gmBlackBoxX &&
2301        gm1.gmBlackBoxY == gm2.gmBlackBoxY &&
2302        gm1.gmptGlyphOrigin.x == gm2.gmptGlyphOrigin.x &&
2303        gm1.gmptGlyphOrigin.y == gm2.gmptGlyphOrigin.y &&
2304        gm1.gmCellIncX == gm2.gmCellIncX &&
2305        gm1.gmCellIncY == gm2.gmCellIncY,
2306        "gm1=%d,%d,%d,%d,%d,%d gm2=%d,%d,%d,%d,%d,%d\n",
2307        gm1.gmBlackBoxX, gm1.gmBlackBoxY, gm1.gmptGlyphOrigin.x,
2308        gm1.gmptGlyphOrigin.y, gm1.gmCellIncX, gm1.gmCellIncY,
2309        gm2.gmBlackBoxX, gm2.gmBlackBoxY, gm2.gmptGlyphOrigin.x,
2310        gm2.gmptGlyphOrigin.y, gm2.gmCellIncX, gm2.gmCellIncY);
2311 }
2312
2313 /* PANOSE is 10 bytes in size, need to pack the structure properly */
2314 #include "pshpack2.h"
2315 typedef struct
2316 {
2317     USHORT version;
2318     SHORT xAvgCharWidth;
2319     USHORT usWeightClass;
2320     USHORT usWidthClass;
2321     SHORT fsType;
2322     SHORT ySubscriptXSize;
2323     SHORT ySubscriptYSize;
2324     SHORT ySubscriptXOffset;
2325     SHORT ySubscriptYOffset;
2326     SHORT ySuperscriptXSize;
2327     SHORT ySuperscriptYSize;
2328     SHORT ySuperscriptXOffset;
2329     SHORT ySuperscriptYOffset;
2330     SHORT yStrikeoutSize;
2331     SHORT yStrikeoutPosition;
2332     SHORT sFamilyClass;
2333     PANOSE panose;
2334     ULONG ulUnicodeRange1;
2335     ULONG ulUnicodeRange2;
2336     ULONG ulUnicodeRange3;
2337     ULONG ulUnicodeRange4;
2338     CHAR achVendID[4];
2339     USHORT fsSelection;
2340     USHORT usFirstCharIndex;
2341     USHORT usLastCharIndex;
2342     /* According to the Apple spec, original version didn't have the below fields,
2343      * version numbers were taken from the OpenType spec.
2344      */
2345     /* version 0 (TrueType 1.5) */
2346     USHORT sTypoAscender;
2347     USHORT sTypoDescender;
2348     USHORT sTypoLineGap;
2349     USHORT usWinAscent;
2350     USHORT usWinDescent;
2351     /* version 1 (TrueType 1.66) */
2352     ULONG ulCodePageRange1;
2353     ULONG ulCodePageRange2;
2354     /* version 2 (OpenType 1.2) */
2355     SHORT sxHeight;
2356     SHORT sCapHeight;
2357     USHORT usDefaultChar;
2358     USHORT usBreakChar;
2359     USHORT usMaxContext;
2360 } TT_OS2_V2;
2361 #include "poppack.h"
2362
2363 #ifdef WORDS_BIGENDIAN
2364 #define GET_BE_WORD(x) (x)
2365 #define GET_BE_DWORD(x) (x)
2366 #else
2367 #define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
2368 #define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
2369 #endif
2370
2371 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
2372                     ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
2373                     ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
2374 #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
2375 #define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
2376 #define MS_NAME_TAG MS_MAKE_TAG('n','a','m','e')
2377
2378 typedef struct
2379 {
2380     USHORT version;
2381     USHORT num_tables;
2382 } cmap_header;
2383
2384 typedef struct
2385 {
2386     USHORT plat_id;
2387     USHORT enc_id;
2388     ULONG offset;
2389 } cmap_encoding_record;
2390
2391 typedef struct
2392 {
2393     USHORT format;
2394     USHORT length;
2395     USHORT language;
2396
2397     BYTE glyph_ids[256];
2398 } cmap_format_0;
2399
2400 typedef struct
2401 {
2402     USHORT format;
2403     USHORT length;
2404     USHORT language;
2405
2406     USHORT seg_countx2;
2407     USHORT search_range;
2408     USHORT entry_selector;
2409     USHORT range_shift;
2410
2411     USHORT end_count[1]; /* this is a variable-sized array of length seg_countx2 / 2 */
2412 /* Then follows:
2413     USHORT pad;
2414     USHORT start_count[seg_countx2 / 2];
2415     USHORT id_delta[seg_countx2 / 2];
2416     USHORT id_range_offset[seg_countx2 / 2];
2417     USHORT glyph_ids[];
2418 */
2419 } cmap_format_4;
2420
2421 typedef struct
2422 {
2423     USHORT end_count;
2424     USHORT start_count;
2425     USHORT id_delta;
2426     USHORT id_range_offset;
2427 } cmap_format_4_seg;
2428
2429 static void expect_ff(const TEXTMETRICA *tmA, const TT_OS2_V2 *os2, WORD family, const char *name)
2430 {
2431     ok((tmA->tmPitchAndFamily & 0xf0) == family ||
2432        broken(PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH),
2433        "%s: expected family %02x got %02x. panose %d-%d-%d-%d-...\n",
2434        name, family, tmA->tmPitchAndFamily, os2->panose.bFamilyType, os2->panose.bSerifStyle,
2435        os2->panose.bWeight, os2->panose.bProportion);
2436 }
2437
2438 static BOOL get_first_last_from_cmap0(void *ptr, DWORD *first, DWORD *last)
2439 {
2440     int i;
2441     cmap_format_0 *cmap = (cmap_format_0*)ptr;
2442
2443     *first = 256;
2444
2445     for(i = 0; i < 256; i++)
2446     {
2447         if(cmap->glyph_ids[i] == 0) continue;
2448         *last = i;
2449         if(*first == 256) *first = i;
2450     }
2451     if(*first == 256) return FALSE;
2452     return TRUE;
2453 }
2454
2455 static void get_seg4(cmap_format_4 *cmap, USHORT seg_num, cmap_format_4_seg *seg)
2456 {
2457     USHORT segs = GET_BE_WORD(cmap->seg_countx2) / 2;
2458     seg->end_count = GET_BE_WORD(cmap->end_count[seg_num]);
2459     seg->start_count = GET_BE_WORD(cmap->end_count[segs + 1 + seg_num]);
2460     seg->id_delta = GET_BE_WORD(cmap->end_count[2 * segs + 1 + seg_num]);
2461     seg->id_range_offset = GET_BE_WORD(cmap->end_count[3 * segs + 1 + seg_num]);
2462 }
2463
2464 static BOOL get_first_last_from_cmap4(void *ptr, DWORD *first, DWORD *last, DWORD limit)
2465 {
2466     int i;
2467     cmap_format_4 *cmap = (cmap_format_4*)ptr;
2468     USHORT seg_count = GET_BE_WORD(cmap->seg_countx2) / 2;
2469     USHORT const *glyph_ids = cmap->end_count + 4 * seg_count + 1;
2470
2471     *first = 0x10000;
2472
2473     for(i = 0; i < seg_count; i++)
2474     {
2475         DWORD code, index;
2476         cmap_format_4_seg seg;
2477
2478         get_seg4(cmap, i, &seg);
2479         for(code = seg.start_count; code <= seg.end_count; code++)
2480         {
2481             if(seg.id_range_offset == 0)
2482                 index = (seg.id_delta + code) & 0xffff;
2483             else
2484             {
2485                 index = seg.id_range_offset / 2
2486                     + code - seg.start_count
2487                     + i - seg_count;
2488
2489                 /* some fonts have broken last segment */
2490                 if ((char *)(glyph_ids + index + 1) < (char *)ptr + limit)
2491                     index = GET_BE_WORD(glyph_ids[index]);
2492                 else
2493                 {
2494                     trace("segment %04x/%04x index %04x points to nowhere\n",
2495                           seg.start_count, seg.end_count, index);
2496                     index = 0;
2497                 }
2498                 if(index) index += seg.id_delta;
2499             }
2500             if(*first == 0x10000)
2501                 *last = *first = code;
2502             else if(index)
2503                 *last = code;
2504         }
2505     }
2506
2507     if(*first == 0x10000) return FALSE;
2508     return TRUE;
2509 }
2510
2511 static void *get_cmap(cmap_header *header, USHORT plat_id, USHORT enc_id)
2512 {
2513     USHORT i;
2514     cmap_encoding_record *record = (cmap_encoding_record *)(header + 1);
2515
2516     for(i = 0; i < GET_BE_WORD(header->num_tables); i++)
2517     {
2518         if(GET_BE_WORD(record->plat_id) == plat_id && GET_BE_WORD(record->enc_id) == enc_id)
2519             return (BYTE *)header + GET_BE_DWORD(record->offset);
2520         record++;
2521     }
2522     return NULL;
2523 }
2524
2525 typedef enum
2526 {
2527     cmap_none,
2528     cmap_ms_unicode,
2529     cmap_ms_symbol
2530 } cmap_type;
2531
2532 static BOOL get_first_last_from_cmap(HDC hdc, DWORD *first, DWORD *last, cmap_type *cmap_type)
2533 {
2534     LONG size, ret;
2535     cmap_header *header;
2536     void *cmap;
2537     BOOL r = FALSE;
2538     WORD format;
2539
2540     size = GetFontData(hdc, MS_CMAP_TAG, 0, NULL, 0);
2541     ok(size != GDI_ERROR, "no cmap table found\n");
2542     if(size == GDI_ERROR) return FALSE;
2543
2544     header = HeapAlloc(GetProcessHeap(), 0, size);
2545     ret = GetFontData(hdc, MS_CMAP_TAG, 0, header, size);
2546     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2547     ok(GET_BE_WORD(header->version) == 0, "got cmap version %d\n", GET_BE_WORD(header->version));
2548
2549     cmap = get_cmap(header, 3, 1);
2550     if(cmap)
2551         *cmap_type = cmap_ms_unicode;
2552     else
2553     {
2554         cmap = get_cmap(header, 3, 0);
2555         if(cmap) *cmap_type = cmap_ms_symbol;
2556     }
2557     if(!cmap)
2558     {
2559         *cmap_type = cmap_none;
2560         goto end;
2561     }
2562
2563     format = GET_BE_WORD(*(WORD *)cmap);
2564     switch(format)
2565     {
2566     case 0:
2567         r = get_first_last_from_cmap0(cmap, first, last);
2568         break;
2569     case 4:
2570         r = get_first_last_from_cmap4(cmap, first, last, size);
2571         break;
2572     default:
2573         trace("unhandled cmap format %d\n", format);
2574         break;
2575     }
2576
2577 end:
2578     HeapFree(GetProcessHeap(), 0, header);
2579     return r;
2580 }
2581
2582 #define TT_PLATFORM_MICROSOFT 3
2583 #define TT_MS_ID_UNICODE_CS 1
2584 #define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409
2585 #define TT_NAME_ID_FULL_NAME 4
2586
2587 static BOOL get_ttf_nametable_entry(HDC hdc, WORD name_id, char *out_buf, SIZE_T out_size)
2588 {
2589     struct sfnt_name_header
2590     {
2591         USHORT format;
2592         USHORT number_of_record;
2593         USHORT storage_offset;
2594     } *header;
2595     struct sfnt_name
2596     {
2597         USHORT platform_id;
2598         USHORT encoding_id;
2599         USHORT language_id;
2600         USHORT name_id;
2601         USHORT length;
2602         USHORT offset;
2603     } *entry;
2604     BOOL r = FALSE;
2605     LONG size, offset, length;
2606     LONG c, ret;
2607     WCHAR *name;
2608     BYTE *data;
2609     USHORT i;
2610
2611     size = GetFontData(hdc, MS_NAME_TAG, 0, NULL, 0);
2612     ok(size != GDI_ERROR, "no name table found\n");
2613     if(size == GDI_ERROR) return FALSE;
2614
2615     data = HeapAlloc(GetProcessHeap(), 0, size);
2616     ret = GetFontData(hdc, MS_NAME_TAG, 0, data, size);
2617     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2618
2619     header = (void *)data;
2620     header->format = GET_BE_WORD(header->format);
2621     header->number_of_record = GET_BE_WORD(header->number_of_record);
2622     header->storage_offset = GET_BE_WORD(header->storage_offset);
2623     if (header->format != 0)
2624     {
2625         trace("got format %u\n", header->format);
2626         goto out;
2627     }
2628     if (header->number_of_record == 0 || sizeof(*header) + header->number_of_record * sizeof(*entry) > size)
2629     {
2630         trace("number records out of range: %d\n", header->number_of_record);
2631         goto out;
2632     }
2633     if (header->storage_offset >= size)
2634     {
2635         trace("storage_offset %u > size %u\n", header->storage_offset, size);
2636         goto out;
2637     }
2638
2639     entry = (void *)&header[1];
2640     for (i = 0; i < header->number_of_record; i++)
2641     {
2642         if (GET_BE_WORD(entry[i].platform_id) != TT_PLATFORM_MICROSOFT ||
2643             GET_BE_WORD(entry[i].encoding_id) != TT_MS_ID_UNICODE_CS ||
2644             GET_BE_WORD(entry[i].language_id) != TT_MS_LANGID_ENGLISH_UNITED_STATES ||
2645             GET_BE_WORD(entry[i].name_id) != name_id)
2646         {
2647             continue;
2648         }
2649
2650         offset = header->storage_offset + GET_BE_WORD(entry[i].offset);
2651         length = GET_BE_WORD(entry[i].length);
2652         if (offset + length > size)
2653         {
2654             trace("entry %d is out of range\n", i);
2655             break;
2656         }
2657         if (length >= out_size)
2658         {
2659             trace("buffer too small for entry %d\n", i);
2660             break;
2661         }
2662
2663         name = (WCHAR *)(data + offset);
2664         for (c = 0; c < length / 2; c++)
2665             out_buf[c] = GET_BE_WORD(name[c]);
2666         out_buf[c] = 0;
2667
2668         r = TRUE;
2669         break;
2670     }
2671
2672 out:
2673     HeapFree(GetProcessHeap(), 0, data);
2674     return r;
2675 }
2676
2677 static void test_text_metrics(const LOGFONTA *lf)
2678 {
2679     HDC hdc;
2680     HFONT hfont, hfont_old;
2681     TEXTMETRICA tmA;
2682     TT_OS2_V2 tt_os2;
2683     LONG size, ret;
2684     const char *font_name = lf->lfFaceName;
2685     DWORD cmap_first = 0, cmap_last = 0;
2686     cmap_type cmap_type;
2687     BOOL sys_lang_non_english;
2688
2689     sys_lang_non_english = PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH;
2690     hdc = GetDC(0);
2691
2692     SetLastError(0xdeadbeef);
2693     hfont = CreateFontIndirectA(lf);
2694     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2695
2696     hfont_old = SelectObject(hdc, hfont);
2697
2698     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
2699     if (size == GDI_ERROR)
2700     {
2701         trace("OS/2 chunk was not found\n");
2702         goto end_of_test;
2703     }
2704     if (size > sizeof(tt_os2))
2705     {
2706         trace("got too large OS/2 chunk of size %u\n", size);
2707         size = sizeof(tt_os2);
2708     }
2709
2710     memset(&tt_os2, 0, sizeof(tt_os2));
2711     ret = GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size);
2712     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2713
2714     SetLastError(0xdeadbeef);
2715     ret = GetTextMetricsA(hdc, &tmA);
2716     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
2717
2718     if(!get_first_last_from_cmap(hdc, &cmap_first, &cmap_last, &cmap_type))
2719     {
2720         skip("Unable to retrieve first and last glyphs from cmap\n");
2721     }
2722     else
2723     {
2724         USHORT expect_first_A, expect_last_A, expect_break_A, expect_default_A;
2725         USHORT expect_first_W, expect_last_W, expect_break_W, expect_default_W;
2726         UINT os2_first_char, os2_last_char, default_char, break_char;
2727         USHORT version;
2728         TEXTMETRICW tmW;
2729
2730         version = GET_BE_WORD(tt_os2.version);
2731
2732         os2_first_char = GET_BE_WORD(tt_os2.usFirstCharIndex);
2733         os2_last_char = GET_BE_WORD(tt_os2.usLastCharIndex);
2734         default_char = GET_BE_WORD(tt_os2.usDefaultChar);
2735         break_char = GET_BE_WORD(tt_os2.usBreakChar);
2736
2737         trace("font %s charset %u: %x-%x (%x-%x) default %x break %x OS/2 version %u vendor %4.4s\n",
2738               font_name, lf->lfCharSet, os2_first_char, os2_last_char, cmap_first, cmap_last,
2739               default_char, break_char, version, (LPCSTR)&tt_os2.achVendID);
2740
2741         if (cmap_type == cmap_ms_symbol || (cmap_first >= 0xf000 && cmap_first < 0xf100))
2742         {
2743             expect_first_W    = 0;
2744             switch(GetACP())
2745             {
2746             case 1257:  /* Baltic */
2747                 expect_last_W = 0xf8fd;
2748                 break;
2749             default:
2750                 expect_last_W = 0xf0ff;
2751             }
2752             expect_break_W    = 0x20;
2753             expect_default_W  = expect_break_W - 1;
2754             expect_first_A    = 0x1e;
2755             expect_last_A     = min(os2_last_char - os2_first_char + 0x20, 0xff);
2756         }
2757         else
2758         {
2759             expect_first_W    = cmap_first;
2760             expect_last_W     = min(cmap_last, os2_last_char);
2761             if(os2_first_char <= 1)
2762                 expect_break_W = os2_first_char + 2;
2763             else if(os2_first_char > 0xff)
2764                 expect_break_W = 0x20;
2765             else
2766                 expect_break_W = os2_first_char;
2767             expect_default_W  = expect_break_W - 1;
2768             expect_first_A    = expect_default_W - 1;
2769             expect_last_A     = min(expect_last_W, 0xff);
2770         }
2771         expect_break_A    = expect_break_W;
2772         expect_default_A  = expect_default_W;
2773
2774         /* Wine currently uses SYMBOL_CHARSET to identify whether the ANSI metrics need special handling */
2775         if(cmap_type != cmap_ms_symbol && tmA.tmCharSet == SYMBOL_CHARSET && expect_first_A != 0x1e)
2776             todo_wine ok(tmA.tmFirstChar == expect_first_A ||
2777                          tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2778                          "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2779         else
2780             ok(tmA.tmFirstChar == expect_first_A ||
2781                tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2782                "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2783         if (pGdiGetCodePage == NULL || ! IsDBCSLeadByteEx(pGdiGetCodePage(hdc), tmA.tmLastChar))
2784             ok(tmA.tmLastChar == expect_last_A ||
2785                tmA.tmLastChar == 0xff /* win9x */,
2786                "A: tmLastChar for %s got %02x expected %02x\n", font_name, tmA.tmLastChar, expect_last_A);
2787         else
2788            skip("tmLastChar is DBCS lead byte\n");
2789         ok(tmA.tmBreakChar == expect_break_A, "A: tmBreakChar for %s got %02x expected %02x\n",
2790            font_name, tmA.tmBreakChar, expect_break_A);
2791         ok(tmA.tmDefaultChar == expect_default_A || broken(sys_lang_non_english),
2792            "A: tmDefaultChar for %s got %02x expected %02x\n",
2793            font_name, tmA.tmDefaultChar, expect_default_A);
2794
2795
2796         SetLastError(0xdeadbeef);
2797         ret = GetTextMetricsW(hdc, &tmW);
2798         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
2799            "GetTextMetricsW error %u\n", GetLastError());
2800         if (ret)
2801         {
2802             /* Wine uses the os2 first char */
2803             if(cmap_first != os2_first_char && cmap_type != cmap_ms_symbol)
2804                 todo_wine ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2805                              font_name, tmW.tmFirstChar, expect_first_W);
2806             else
2807                 ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2808                    font_name, tmW.tmFirstChar, expect_first_W);
2809
2810             /* Wine uses the os2 last char */
2811             if(expect_last_W != os2_last_char && cmap_type != cmap_ms_symbol)
2812                 todo_wine ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2813                              font_name, tmW.tmLastChar, expect_last_W);
2814             else
2815                 ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2816                    font_name, tmW.tmLastChar, expect_last_W);
2817             ok(tmW.tmBreakChar == expect_break_W, "W: tmBreakChar for %s got %02x expected %02x\n",
2818                font_name, tmW.tmBreakChar, expect_break_W);
2819             ok(tmW.tmDefaultChar == expect_default_W || broken(sys_lang_non_english),
2820                "W: tmDefaultChar for %s got %02x expected %02x\n",
2821                font_name, tmW.tmDefaultChar, expect_default_W);
2822
2823             /* Test the aspect ratio while we have tmW */
2824             ret = GetDeviceCaps(hdc, LOGPIXELSX);
2825             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectX %u != %u\n",
2826                tmW.tmDigitizedAspectX, ret);
2827             ret = GetDeviceCaps(hdc, LOGPIXELSY);
2828             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectY %u != %u\n",
2829                tmW.tmDigitizedAspectX, ret);
2830         }
2831     }
2832
2833     /* test FF_ values */
2834     switch(tt_os2.panose.bFamilyType)
2835     {
2836     case PAN_ANY:
2837     case PAN_NO_FIT:
2838     case PAN_FAMILY_TEXT_DISPLAY:
2839     case PAN_FAMILY_PICTORIAL:
2840     default:
2841         if((tmA.tmPitchAndFamily & 1) == 0 || /* fixed */
2842            tt_os2.panose.bProportion == PAN_PROP_MONOSPACED)
2843         {
2844             expect_ff(&tmA, &tt_os2, FF_MODERN, font_name);
2845             break;
2846         }
2847         switch(tt_os2.panose.bSerifStyle)
2848         {
2849         case PAN_ANY:
2850         case PAN_NO_FIT:
2851         default:
2852             expect_ff(&tmA, &tt_os2, FF_DONTCARE, font_name);
2853             break;
2854
2855         case PAN_SERIF_COVE:
2856         case PAN_SERIF_OBTUSE_COVE:
2857         case PAN_SERIF_SQUARE_COVE:
2858         case PAN_SERIF_OBTUSE_SQUARE_COVE:
2859         case PAN_SERIF_SQUARE:
2860         case PAN_SERIF_THIN:
2861         case PAN_SERIF_BONE:
2862         case PAN_SERIF_EXAGGERATED:
2863         case PAN_SERIF_TRIANGLE:
2864             expect_ff(&tmA, &tt_os2, FF_ROMAN, font_name);
2865             break;
2866
2867         case PAN_SERIF_NORMAL_SANS:
2868         case PAN_SERIF_OBTUSE_SANS:
2869         case PAN_SERIF_PERP_SANS:
2870         case PAN_SERIF_FLARED:
2871         case PAN_SERIF_ROUNDED:
2872             expect_ff(&tmA, &tt_os2, FF_SWISS, font_name);
2873             break;
2874         }
2875         break;
2876
2877     case PAN_FAMILY_SCRIPT:
2878         expect_ff(&tmA, &tt_os2, FF_SCRIPT, font_name);
2879         break;
2880
2881     case PAN_FAMILY_DECORATIVE:
2882         expect_ff(&tmA, &tt_os2, FF_DECORATIVE, font_name);
2883         break;
2884     }
2885
2886     test_negative_width(hdc, lf);
2887
2888 end_of_test:
2889     SelectObject(hdc, hfont_old);
2890     DeleteObject(hfont);
2891
2892     ReleaseDC(0, hdc);
2893 }
2894
2895 static INT CALLBACK enum_truetype_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
2896 {
2897     INT *enumed = (INT *)lParam;
2898
2899     if (type == TRUETYPE_FONTTYPE)
2900     {
2901         (*enumed)++;
2902         test_text_metrics(lf);
2903     }
2904     return 1;
2905 }
2906
2907 static void test_GetTextMetrics(void)
2908 {
2909     LOGFONTA lf;
2910     HDC hdc;
2911     INT enumed;
2912
2913     /* Report only once */
2914     if(!pGetGlyphIndicesA)
2915         win_skip("GetGlyphIndicesA is unavailable, negative width will not be checked\n");
2916
2917     hdc = GetDC(0);
2918
2919     memset(&lf, 0, sizeof(lf));
2920     lf.lfCharSet = DEFAULT_CHARSET;
2921     enumed = 0;
2922     EnumFontFamiliesExA(hdc, &lf, enum_truetype_font_proc, (LPARAM)&enumed, 0);
2923     trace("Tested metrics of %d truetype fonts\n", enumed);
2924
2925     ReleaseDC(0, hdc);
2926 }
2927
2928 static void test_nonexistent_font(void)
2929 {
2930     static const struct
2931     {
2932         const char *name;
2933         int charset;
2934     } font_subst[] =
2935     {
2936         { "Times New Roman Baltic", 186 },
2937         { "Times New Roman CE", 238 },
2938         { "Times New Roman CYR", 204 },
2939         { "Times New Roman Greek", 161 },
2940         { "Times New Roman TUR", 162 }
2941     };
2942     LOGFONTA lf;
2943     HDC hdc;
2944     HFONT hfont;
2945     CHARSETINFO csi;
2946     INT cs, expected_cs, i;
2947     char buf[LF_FACESIZE];
2948
2949     if (!is_truetype_font_installed("Arial") ||
2950         !is_truetype_font_installed("Times New Roman"))
2951     {
2952         skip("Arial or Times New Roman not installed\n");
2953         return;
2954     }
2955
2956     expected_cs = GetACP();
2957     if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
2958     {
2959         skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
2960         return;
2961     }
2962     expected_cs = csi.ciCharset;
2963     trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
2964
2965     hdc = GetDC(0);
2966
2967     memset(&lf, 0, sizeof(lf));
2968     lf.lfHeight = 100;
2969     lf.lfWeight = FW_REGULAR;
2970     lf.lfCharSet = ANSI_CHARSET;
2971     lf.lfPitchAndFamily = FF_SWISS;
2972     strcpy(lf.lfFaceName, "Nonexistent font");
2973     hfont = CreateFontIndirectA(&lf);
2974     hfont = SelectObject(hdc, hfont);
2975     GetTextFaceA(hdc, sizeof(buf), buf);
2976     ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
2977     cs = GetTextCharset(hdc);
2978     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2979     DeleteObject(SelectObject(hdc, hfont));
2980
2981     memset(&lf, 0, sizeof(lf));
2982     lf.lfHeight = -13;
2983     lf.lfWeight = FW_DONTCARE;
2984     strcpy(lf.lfFaceName, "Nonexistent font");
2985     hfont = CreateFontIndirectA(&lf);
2986     hfont = SelectObject(hdc, hfont);
2987     GetTextFaceA(hdc, sizeof(buf), buf);
2988 todo_wine /* Wine uses Arial for all substitutions */
2989     ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ ||
2990        !lstrcmpiA(buf, "MS Serif") || /* Win9x */
2991        !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
2992        "Got %s\n", buf);
2993     cs = GetTextCharset(hdc);
2994     ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d\n", expected_cs, cs);
2995     DeleteObject(SelectObject(hdc, hfont));
2996
2997     memset(&lf, 0, sizeof(lf));
2998     lf.lfHeight = -13;
2999     lf.lfWeight = FW_REGULAR;
3000     strcpy(lf.lfFaceName, "Nonexistent font");
3001     hfont = CreateFontIndirectA(&lf);
3002     hfont = SelectObject(hdc, hfont);
3003     GetTextFaceA(hdc, sizeof(buf), buf);
3004     ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
3005        !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "Got %s\n", buf);
3006     cs = GetTextCharset(hdc);
3007     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
3008     DeleteObject(SelectObject(hdc, hfont));
3009
3010     memset(&lf, 0, sizeof(lf));
3011     lf.lfHeight = -13;
3012     lf.lfWeight = FW_DONTCARE;
3013     strcpy(lf.lfFaceName, "Times New Roman");
3014     hfont = CreateFontIndirectA(&lf);
3015     hfont = SelectObject(hdc, hfont);
3016     GetTextFaceA(hdc, sizeof(buf), buf);
3017     ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf);
3018     cs = GetTextCharset(hdc);
3019     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
3020     DeleteObject(SelectObject(hdc, hfont));
3021
3022     for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++)
3023     {
3024         memset(&lf, 0, sizeof(lf));
3025         lf.lfHeight = -13;
3026         lf.lfWeight = FW_REGULAR;
3027         strcpy(lf.lfFaceName, font_subst[i].name);
3028         hfont = CreateFontIndirectA(&lf);
3029         hfont = SelectObject(hdc, hfont);
3030         cs = GetTextCharset(hdc);
3031         if (font_subst[i].charset == expected_cs)
3032         {
3033             ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
3034             GetTextFaceA(hdc, sizeof(buf), buf);
3035             ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf);
3036         }
3037         else
3038         {
3039             ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d for font %s\n", cs, font_subst[i].name);
3040             GetTextFaceA(hdc, sizeof(buf), buf);
3041             ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
3042                !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got %s for font %s\n", buf, font_subst[i].name);
3043         }
3044         DeleteObject(SelectObject(hdc, hfont));
3045
3046         memset(&lf, 0, sizeof(lf));
3047         lf.lfHeight = -13;
3048         lf.lfWeight = FW_DONTCARE;
3049         strcpy(lf.lfFaceName, font_subst[i].name);
3050         hfont = CreateFontIndirectA(&lf);
3051         hfont = SelectObject(hdc, hfont);
3052         GetTextFaceA(hdc, sizeof(buf), buf);
3053         ok(!lstrcmpiA(buf, "Arial") /* Wine */ ||
3054            !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ ||
3055            !lstrcmpiA(buf, "MS Serif") /* Win9x */ ||
3056            !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
3057            "got %s for font %s\n", buf, font_subst[i].name);
3058         cs = GetTextCharset(hdc);
3059         ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
3060         DeleteObject(SelectObject(hdc, hfont));
3061     }
3062
3063     ReleaseDC(0, hdc);
3064 }
3065
3066 static void test_GdiRealizationInfo(void)
3067 {
3068     HDC hdc;
3069     DWORD info[4];
3070     BOOL r;
3071     HFONT hfont, hfont_old;
3072     LOGFONTA lf;
3073
3074     if(!pGdiRealizationInfo)
3075     {
3076         win_skip("GdiRealizationInfo not available\n");
3077         return;
3078     }
3079
3080     hdc = GetDC(0);
3081
3082     memset(info, 0xcc, sizeof(info));
3083     r = pGdiRealizationInfo(hdc, info);
3084     ok(r != 0, "ret 0\n");
3085     ok((info[0] & 0xf) == 1, "info[0] = %x for the system font\n", info[0]);
3086     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
3087
3088     if (!is_truetype_font_installed("Arial"))
3089     {
3090         skip("skipping GdiRealizationInfo with truetype font\n");
3091         goto end;
3092     }
3093
3094     memset(&lf, 0, sizeof(lf));
3095     strcpy(lf.lfFaceName, "Arial");
3096     lf.lfHeight = 20;
3097     lf.lfWeight = FW_NORMAL;
3098     hfont = CreateFontIndirectA(&lf);
3099     hfont_old = SelectObject(hdc, hfont);
3100
3101     memset(info, 0xcc, sizeof(info));
3102     r = pGdiRealizationInfo(hdc, info);
3103     ok(r != 0, "ret 0\n");
3104     ok((info[0] & 0xf) == 3, "info[0] = %x for arial\n", info[0]);
3105     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
3106
3107     DeleteObject(SelectObject(hdc, hfont_old));
3108
3109  end:
3110     ReleaseDC(0, hdc);
3111 }
3112
3113 /* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include
3114    the nul in the count of characters copied when the face name buffer is not
3115    NULL, whereas it does if the buffer is NULL.  Further, the Unicode version
3116    always includes it.  */
3117 static void test_GetTextFace(void)
3118 {
3119     static const char faceA[] = "Tahoma";
3120     static const WCHAR faceW[] = {'T','a','h','o','m','a', 0};
3121     LOGFONTA fA = {0};
3122     LOGFONTW fW = {0};
3123     char bufA[LF_FACESIZE];
3124     WCHAR bufW[LF_FACESIZE];
3125     HFONT f, g;
3126     HDC dc;
3127     int n;
3128
3129     if(!is_font_installed("Tahoma"))
3130     {
3131         skip("Tahoma is not installed so skipping this test\n");
3132         return;
3133     }
3134
3135     /* 'A' case.  */
3136     memcpy(fA.lfFaceName, faceA, sizeof faceA);
3137     f = CreateFontIndirectA(&fA);
3138     ok(f != NULL, "CreateFontIndirectA failed\n");
3139
3140     dc = GetDC(NULL);
3141     g = SelectObject(dc, f);
3142     n = GetTextFaceA(dc, sizeof bufA, bufA);
3143     ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n);
3144     ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n");
3145
3146     /* Play with the count arg.  */
3147     bufA[0] = 'x';
3148     n = GetTextFaceA(dc, 0, bufA);
3149     ok(n == 0, "GetTextFaceA returned %d\n", n);
3150     ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]);
3151
3152     bufA[0] = 'x';
3153     n = GetTextFaceA(dc, 1, bufA);
3154     ok(n == 0, "GetTextFaceA returned %d\n", n);
3155     ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]);
3156
3157     bufA[0] = 'x'; bufA[1] = 'y';
3158     n = GetTextFaceA(dc, 2, bufA);
3159     ok(n == 1, "GetTextFaceA returned %d\n", n);
3160     ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n");
3161
3162     n = GetTextFaceA(dc, 0, NULL);
3163     ok(n == sizeof faceA ||
3164        broken(n == 0), /* win98, winMe */
3165        "GetTextFaceA returned %d\n", n);
3166
3167     DeleteObject(SelectObject(dc, g));
3168     ReleaseDC(NULL, dc);
3169
3170     /* 'W' case.  */
3171     memcpy(fW.lfFaceName, faceW, sizeof faceW);
3172     SetLastError(0xdeadbeef);
3173     f = CreateFontIndirectW(&fW);
3174     if (!f && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
3175     {
3176         win_skip("CreateFontIndirectW is not implemented\n");
3177         return;
3178     }
3179     ok(f != NULL, "CreateFontIndirectW failed\n");
3180
3181     dc = GetDC(NULL);
3182     g = SelectObject(dc, f);
3183     n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW);
3184     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
3185     ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
3186
3187     /* Play with the count arg.  */
3188     bufW[0] = 'x';
3189     n = GetTextFaceW(dc, 0, bufW);
3190     ok(n == 0, "GetTextFaceW returned %d\n", n);
3191     ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]);
3192
3193     bufW[0] = 'x';
3194     n = GetTextFaceW(dc, 1, bufW);
3195     ok(n == 1, "GetTextFaceW returned %d\n", n);
3196     ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]);
3197
3198     bufW[0] = 'x'; bufW[1] = 'y';
3199     n = GetTextFaceW(dc, 2, bufW);
3200     ok(n == 2, "GetTextFaceW returned %d\n", n);
3201     ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n");
3202
3203     n = GetTextFaceW(dc, 0, NULL);
3204     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
3205
3206     DeleteObject(SelectObject(dc, g));
3207     ReleaseDC(NULL, dc);
3208 }
3209
3210 static void test_orientation(void)
3211 {
3212     static const char test_str[11] = "Test String";
3213     HDC hdc;
3214     LOGFONTA lf;
3215     HFONT hfont, old_hfont;
3216     SIZE size;
3217
3218     if (!is_truetype_font_installed("Arial"))
3219     {
3220         skip("Arial is not installed\n");
3221         return;
3222     }
3223
3224     hdc = CreateCompatibleDC(0);
3225     memset(&lf, 0, sizeof(lf));
3226     lstrcpyA(lf.lfFaceName, "Arial");
3227     lf.lfHeight = 72;
3228     lf.lfOrientation = lf.lfEscapement = 900;
3229     hfont = create_font("orientation", &lf);
3230     old_hfont = SelectObject(hdc, hfont);
3231     ok(GetTextExtentExPointA(hdc, test_str, sizeof(test_str), 32767, NULL, NULL, &size), "GetTextExtentExPointA failed\n");
3232     ok(near_match(311, size.cx), "cx should be about 311, got %d\n", size.cx);
3233     ok(near_match(75, size.cy), "cy should be about 75, got %d\n", size.cy);
3234     SelectObject(hdc, old_hfont);
3235     DeleteObject(hfont);
3236     DeleteDC(hdc);
3237 }
3238
3239 static void test_oemcharset(void)
3240 {
3241     HDC hdc;
3242     LOGFONTA lf, clf;
3243     HFONT hfont, old_hfont;
3244     int charset;
3245
3246     hdc = CreateCompatibleDC(0);
3247     ZeroMemory(&lf, sizeof(lf));
3248     lf.lfHeight = 12;
3249     lf.lfCharSet = OEM_CHARSET;
3250     lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
3251     lstrcpyA(lf.lfFaceName, "Terminal");
3252     hfont = CreateFontIndirectA(&lf);
3253     old_hfont = SelectObject(hdc, hfont);
3254     charset = GetTextCharset(hdc);
3255 todo_wine
3256     ok(charset == OEM_CHARSET, "expected %d charset, got %d\n", OEM_CHARSET, charset);
3257     hfont = SelectObject(hdc, old_hfont);
3258     GetObjectA(hfont, sizeof(clf), &clf);
3259     ok(!lstrcmpA(clf.lfFaceName, lf.lfFaceName), "expected %s face name, got %s\n", lf.lfFaceName, clf.lfFaceName);
3260     ok(clf.lfPitchAndFamily == lf.lfPitchAndFamily, "expected %x family, got %x\n", lf.lfPitchAndFamily, clf.lfPitchAndFamily);
3261     ok(clf.lfCharSet == lf.lfCharSet, "expected %d charset, got %d\n", lf.lfCharSet, clf.lfCharSet);
3262     ok(clf.lfHeight == lf.lfHeight, "expected %d height, got %d\n", lf.lfHeight, clf.lfHeight);
3263     DeleteObject(hfont);
3264     DeleteDC(hdc);
3265 }
3266
3267 static void test_GetGlyphOutline(void)
3268 {
3269     HDC hdc;
3270     GLYPHMETRICS gm, gm2;
3271     LOGFONTA lf;
3272     HFONT hfont, old_hfont;
3273     INT ret, ret2;
3274     static const struct
3275     {
3276         UINT cs;
3277         UINT a;
3278         UINT w;
3279     } c[] =
3280     {
3281         {ANSI_CHARSET, 0x30, 0x30},
3282         {SHIFTJIS_CHARSET, 0x82a0, 0x3042},
3283         {HANGEUL_CHARSET, 0x8141, 0xac02},
3284         {JOHAB_CHARSET, 0x8446, 0x3135},
3285         {GB2312_CHARSET, 0x8141, 0x4e04},
3286         {CHINESEBIG5_CHARSET, 0xa142, 0x3001}
3287     };
3288     UINT i;
3289
3290     if (!is_truetype_font_installed("Tahoma"))
3291     {
3292         skip("Tahoma is not installed\n");
3293         return;
3294     }
3295
3296     hdc = CreateCompatibleDC(0);
3297     memset(&lf, 0, sizeof(lf));
3298     lf.lfHeight = 72;
3299     lstrcpyA(lf.lfFaceName, "Tahoma");
3300     SetLastError(0xdeadbeef);
3301     hfont = CreateFontIndirectA(&lf);
3302     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
3303     old_hfont = SelectObject(hdc, hfont);
3304
3305     memset(&gm, 0, sizeof(gm));
3306     SetLastError(0xdeadbeef);
3307     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3308     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
3309
3310     memset(&gm, 0, sizeof(gm));
3311     SetLastError(0xdeadbeef);
3312     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
3313     ok(ret == GDI_ERROR, "GetGlyphOutlineA should fail\n");
3314     ok(GetLastError() == 0xdeadbeef ||
3315        GetLastError() == ERROR_INVALID_PARAMETER, /* win98, winMe */
3316        "expected 0xdeadbeef, got %u\n", GetLastError());
3317
3318     memset(&gm, 0, sizeof(gm));
3319     SetLastError(0xdeadbeef);
3320     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3321     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3322         ok(ret != GDI_ERROR, "GetGlyphOutlineW error %u\n", GetLastError());
3323
3324     memset(&gm, 0, sizeof(gm));
3325     SetLastError(0xdeadbeef);
3326     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
3327     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3328     {
3329        ok(ret == GDI_ERROR, "GetGlyphOutlineW should fail\n");
3330        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
3331     }
3332
3333     /* test for needed buffer size request on space char */
3334     memset(&gm, 0, sizeof(gm));
3335     SetLastError(0xdeadbeef);
3336     ret = GetGlyphOutlineW(hdc, ' ', GGO_NATIVE, &gm, 0, NULL, &mat);
3337     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3338         ok(ret == 0, "GetGlyphOutlineW should return 0 buffer size for space char\n");
3339
3340     /* requesting buffer size for space char + error */
3341     memset(&gm, 0, sizeof(gm));
3342     SetLastError(0xdeadbeef);
3343     ret = GetGlyphOutlineW(0, ' ', GGO_NATIVE, &gm, 0, NULL, NULL);
3344     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3345     {
3346        ok(ret == GDI_ERROR, "GetGlyphOutlineW should return GDI_ERROR\n");
3347        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
3348     }
3349
3350     SelectObject(hdc, old_hfont);
3351     DeleteObject(hfont);
3352
3353     for (i = 0; i < sizeof c / sizeof c[0]; ++i)
3354     {
3355         lf.lfFaceName[0] = '\0';
3356         lf.lfCharSet = c[i].cs;
3357         lf.lfPitchAndFamily = 0;
3358         if (EnumFontFamiliesEx(hdc, &lf, create_font_proc, (LPARAM)&hfont, 0))
3359         {
3360             skip("TrueType font for charset %u is not installed\n", c[i].cs);
3361             continue;
3362         }
3363
3364         old_hfont = SelectObject(hdc, hfont);
3365
3366         /* expected to ignore superfluous bytes (sigle-byte character) */
3367         ret = GetGlyphOutlineA(hdc, 0x8041, GGO_BITMAP, &gm, 0, NULL, &mat);
3368         ret2 = GetGlyphOutlineA(hdc, 0x41, GGO_BITMAP, &gm2, 0, NULL, &mat);
3369         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
3370
3371         ret = GetGlyphOutlineA(hdc, 0xcc8041, GGO_BITMAP, &gm, 0, NULL, &mat);
3372         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
3373            "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
3374
3375         /* expected to ignore superfluous bytes (double-byte character) */
3376         ret = GetGlyphOutlineA(hdc, c[i].a, GGO_BITMAP, &gm, 0, NULL, &mat);
3377         ret2 = GetGlyphOutlineA(hdc, c[i].a | 0xdead0000, GGO_BITMAP, &gm2, 0, NULL, &mat);
3378         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
3379            "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
3380
3381         /* expected to match wide-char version results */
3382         ret2 = GetGlyphOutlineW(hdc, c[i].w, GGO_BITMAP, &gm2, 0, NULL, &mat);
3383         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
3384
3385         hfont = SelectObject(hdc, old_hfont);
3386         DeleteObject(hfont);
3387     }
3388
3389     DeleteDC(hdc);
3390 }
3391
3392 /* bug #9995: there is a limit to the character width that can be specified */
3393 static void test_GetTextMetrics2(const char *fontname, int font_height)
3394 {
3395     HFONT of, hf;
3396     HDC hdc;
3397     TEXTMETRICA tm;
3398     BOOL ret;
3399     int ave_width, height, width, ratio, scale;
3400
3401     if (!is_truetype_font_installed( fontname)) {
3402         skip("%s is not installed\n", fontname);
3403         return;
3404     }
3405     hdc = CreateCompatibleDC(0);
3406     ok( hdc != NULL, "CreateCompatibleDC failed\n");
3407     /* select width = 0 */
3408     hf = CreateFontA(font_height, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3409             DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3410             DEFAULT_QUALITY, VARIABLE_PITCH,
3411             fontname);
3412     ok( hf != NULL, "CreateFontA(%s, %d) failed\n", fontname, font_height);
3413     of = SelectObject( hdc, hf);
3414     ret = GetTextMetricsA( hdc, &tm);
3415     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
3416     height = tm.tmHeight;
3417     ave_width = tm.tmAveCharWidth;
3418     SelectObject( hdc, of);
3419     DeleteObject( hf);
3420
3421     trace("height %d, ave width %d\n", height, ave_width);
3422
3423     for (width = ave_width * 2; /* nothing*/; width += ave_width)
3424     {
3425         hf = CreateFont(height, width, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3426                         DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3427                         DEFAULT_QUALITY, VARIABLE_PITCH, fontname);
3428         ok(hf != 0, "CreateFont failed\n");
3429         of = SelectObject(hdc, hf);
3430         ret = GetTextMetrics(hdc, &tm);
3431         ok(ret, "GetTextMetrics error %u\n", GetLastError());
3432         SelectObject(hdc, of);
3433         DeleteObject(hf);
3434
3435         if (match_off_by_1(tm.tmAveCharWidth, ave_width) || width / height > 200)
3436             break;
3437     }
3438
3439     DeleteDC(hdc);
3440
3441     ratio = width / height;
3442     scale = width / ave_width;
3443
3444     trace("max width/height ratio (%d / %d) %d, max width scale (%d / %d) %d\n",
3445           width, height, ratio, width, ave_width, scale);
3446
3447     ok(ratio >= 90 && ratio <= 110, "expected width/height ratio 90-110, got %d\n", ratio);
3448 }
3449
3450 static void test_CreateFontIndirect(void)
3451 {
3452     LOGFONTA lf, getobj_lf;
3453     int ret, i;
3454     HFONT hfont;
3455     char TestName[][16] = {"Arial", "Arial Bold", "Arial Italic", "Arial Baltic"};
3456
3457     memset(&lf, 0, sizeof(lf));
3458     lf.lfCharSet = ANSI_CHARSET;
3459     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
3460     lf.lfHeight = 16;
3461     lf.lfWidth = 16;
3462     lf.lfQuality = DEFAULT_QUALITY;
3463     lf.lfItalic = FALSE;
3464     lf.lfWeight = FW_DONTCARE;
3465
3466     for (i = 0; i < sizeof(TestName)/sizeof(TestName[0]); i++)
3467     {
3468         lstrcpyA(lf.lfFaceName, TestName[i]);
3469         hfont = CreateFontIndirectA(&lf);
3470         ok(hfont != 0, "CreateFontIndirectA failed\n");
3471         SetLastError(0xdeadbeef);
3472         ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf);
3473         ok(ret, "GetObject failed: %d\n", GetLastError());
3474         ok(lf.lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf.lfItalic, getobj_lf.lfItalic);
3475         ok(lf.lfWeight == getobj_lf.lfWeight ||
3476            broken((SHORT)lf.lfWeight == getobj_lf.lfWeight), /* win9x */
3477            "lfWeight: expect %08x got %08x\n", lf.lfWeight, getobj_lf.lfWeight);
3478         ok(!lstrcmpA(lf.lfFaceName, getobj_lf.lfFaceName) ||
3479            broken(!memcmp(lf.lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
3480            "font names don't match: %s != %s\n", lf.lfFaceName, getobj_lf.lfFaceName);
3481         DeleteObject(hfont);
3482     }
3483 }
3484
3485 static void test_CreateFontIndirectEx(void)
3486 {
3487     ENUMLOGFONTEXDVA lfex;
3488     HFONT hfont;
3489
3490     if (!pCreateFontIndirectExA)
3491     {
3492         win_skip("CreateFontIndirectExA is not available\n");
3493         return;
3494     }
3495
3496     if (!is_truetype_font_installed("Arial"))
3497     {
3498         skip("Arial is not installed\n");
3499         return;
3500     }
3501
3502     SetLastError(0xdeadbeef);
3503     hfont = pCreateFontIndirectExA(NULL);
3504     ok(hfont == NULL, "got %p\n", hfont);
3505     ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
3506
3507     memset(&lfex, 0, sizeof(lfex));
3508     lstrcpyA(lfex.elfEnumLogfontEx.elfLogFont.lfFaceName, "Arial");
3509     hfont = pCreateFontIndirectExA(&lfex);
3510     ok(hfont != 0, "CreateFontIndirectEx failed\n");
3511     if (hfont)
3512         check_font("Arial", &lfex.elfEnumLogfontEx.elfLogFont, hfont);
3513     DeleteObject(hfont);
3514 }
3515
3516 static void free_font(void *font)
3517 {
3518     UnmapViewOfFile(font);
3519 }
3520
3521 static void *load_font(const char *font_name, DWORD *font_size)
3522 {
3523     char file_name[MAX_PATH];
3524     HANDLE file, mapping;
3525     void *font;
3526
3527     if (!GetWindowsDirectory(file_name, sizeof(file_name))) return NULL;
3528     strcat(file_name, "\\fonts\\");
3529     strcat(file_name, font_name);
3530
3531     file = CreateFile(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
3532     if (file == INVALID_HANDLE_VALUE) return NULL;
3533
3534     *font_size = GetFileSize(file, NULL);
3535
3536     mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
3537     if (!mapping)
3538     {
3539         CloseHandle(file);
3540         return NULL;
3541     }
3542
3543     font = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
3544
3545     CloseHandle(file);
3546     CloseHandle(mapping);
3547     return font;
3548 }
3549
3550 static void test_AddFontMemResource(void)
3551 {
3552     void *font;
3553     DWORD font_size, num_fonts;
3554     HANDLE ret;
3555     BOOL bRet;
3556
3557     if (!pAddFontMemResourceEx || !pRemoveFontMemResourceEx)
3558     {
3559         win_skip("AddFontMemResourceEx is not available on this platform\n");
3560         return;
3561     }
3562
3563     font = load_font("sserife.fon", &font_size);
3564     if (!font)
3565     {
3566         skip("Unable to locate and load font sserife.fon\n");
3567         return;
3568     }
3569
3570     SetLastError(0xdeadbeef);
3571     ret = pAddFontMemResourceEx(NULL, 0, NULL, NULL);
3572     ok(!ret, "AddFontMemResourceEx should fail\n");
3573     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3574        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3575        GetLastError());
3576
3577     SetLastError(0xdeadbeef);
3578     ret = pAddFontMemResourceEx(NULL, 10, NULL, NULL);
3579     ok(!ret, "AddFontMemResourceEx should fail\n");
3580     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3581        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3582        GetLastError());
3583
3584     SetLastError(0xdeadbeef);
3585     ret = pAddFontMemResourceEx(NULL, 0, NULL, &num_fonts);
3586     ok(!ret, "AddFontMemResourceEx should fail\n");
3587     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3588        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3589        GetLastError());
3590
3591     SetLastError(0xdeadbeef);
3592     ret = pAddFontMemResourceEx(NULL, 10, NULL, &num_fonts);
3593     ok(!ret, "AddFontMemResourceEx should fail\n");
3594     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3595        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3596        GetLastError());
3597
3598     SetLastError(0xdeadbeef);
3599     ret = pAddFontMemResourceEx(font, 0, NULL, NULL);
3600     ok(!ret, "AddFontMemResourceEx should fail\n");
3601     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3602        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3603        GetLastError());
3604
3605     SetLastError(0xdeadbeef);
3606     ret = pAddFontMemResourceEx(font, 10, NULL, NULL);
3607     ok(!ret, "AddFontMemResourceEx should fail\n");
3608     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3609        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3610        GetLastError());
3611
3612     num_fonts = 0xdeadbeef;
3613     SetLastError(0xdeadbeef);
3614     ret = pAddFontMemResourceEx(font, 0, NULL, &num_fonts);
3615     ok(!ret, "AddFontMemResourceEx should fail\n");
3616     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3617        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3618        GetLastError());
3619     ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
3620
3621     if (0) /* hangs under windows 2000 */
3622     {
3623         num_fonts = 0xdeadbeef;
3624         SetLastError(0xdeadbeef);
3625         ret = pAddFontMemResourceEx(font, 10, NULL, &num_fonts);
3626         ok(!ret, "AddFontMemResourceEx should fail\n");
3627         ok(GetLastError() == 0xdeadbeef,
3628            "Expected GetLastError() to return 0xdeadbeef, got %u\n",
3629            GetLastError());
3630         ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
3631     }
3632
3633     num_fonts = 0xdeadbeef;
3634     SetLastError(0xdeadbeef);
3635     ret = pAddFontMemResourceEx(font, font_size, NULL, &num_fonts);
3636     ok(ret != 0, "AddFontMemResourceEx error %d\n", GetLastError());
3637     ok(num_fonts != 0xdeadbeef, "number of loaded fonts should not be 0xdeadbeef\n");
3638     ok(num_fonts != 0, "number of loaded fonts should not be 0\n");
3639
3640     free_font(font);
3641
3642     SetLastError(0xdeadbeef);
3643     bRet = pRemoveFontMemResourceEx(ret);
3644     ok(bRet, "RemoveFontMemResourceEx error %d\n", GetLastError());
3645
3646     /* test invalid pointer to number of loaded fonts */
3647     font = load_font("sserife.fon", &font_size);
3648     ok(font != NULL, "Unable to locate and load font sserife.fon\n");
3649
3650     SetLastError(0xdeadbeef);
3651     ret = pAddFontMemResourceEx(font, font_size, NULL, (void *)0xdeadbeef);
3652     ok(!ret, "AddFontMemResourceEx should fail\n");
3653     ok(GetLastError() == 0xdeadbeef,
3654        "Expected GetLastError() to return 0xdeadbeef, got %u\n",
3655        GetLastError());
3656
3657     SetLastError(0xdeadbeef);
3658     ret = pAddFontMemResourceEx(font, font_size, NULL, NULL);
3659     ok(!ret, "AddFontMemResourceEx should fail\n");
3660     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3661        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3662        GetLastError());
3663
3664     free_font(font);
3665 }
3666
3667 static INT CALLBACK enum_fonts_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3668 {
3669     LOGFONT *lf;
3670
3671     if (type != TRUETYPE_FONTTYPE) return 1;
3672
3673     ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
3674
3675     lf = (LOGFONT *)lparam;
3676     *lf = *elf;
3677     return 0;
3678 }
3679
3680 static INT CALLBACK enum_all_fonts_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3681 {
3682     int ret;
3683     LOGFONT *lf;
3684
3685     if (type != TRUETYPE_FONTTYPE) return 1;
3686
3687     lf = (LOGFONT *)lparam;
3688     ret = strcmp(lf->lfFaceName, elf->lfFaceName);
3689     if(ret == 0)
3690     {
3691         ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
3692         *lf = *elf;
3693         return 0;
3694     }
3695     return 1;
3696 }
3697
3698 static void test_EnumFonts(void)
3699 {
3700     int ret;
3701     LOGFONT lf;
3702     HDC hdc;
3703
3704     if (!is_truetype_font_installed("Arial"))
3705     {
3706         skip("Arial is not installed\n");
3707         return;
3708     }
3709
3710     /* Windows uses localized font face names, so Arial Bold won't be found */
3711     if (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH)
3712     {
3713         skip("User locale is not English, skipping the test\n");
3714         return;
3715     }
3716
3717     hdc = CreateCompatibleDC(0);
3718
3719     ret = EnumFontFamilies(hdc, "Arial", enum_fonts_proc, (LPARAM)&lf);
3720     ok(!ret, "font Arial is not enumerated\n");
3721     ret = strcmp(lf.lfFaceName, "Arial");
3722     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3723     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
3724
3725     lstrcpy(lf.lfFaceName, "Arial");
3726     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3727     ok(!ret, "font Arial is not enumerated\n");
3728     ret = strcmp(lf.lfFaceName, "Arial");
3729     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3730     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
3731
3732     ret = EnumFontFamilies(hdc, "Arial Bold", enum_fonts_proc, (LPARAM)&lf);
3733     ok(!ret, "font Arial Bold is not enumerated\n");
3734     ret = strcmp(lf.lfFaceName, "Arial");
3735     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3736     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
3737
3738     lstrcpy(lf.lfFaceName, "Arial Bold");
3739     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3740     ok(ret, "font Arial Bold should not be enumerated\n");
3741
3742     ret = EnumFontFamilies(hdc, "Arial Bold Italic", enum_fonts_proc, (LPARAM)&lf);
3743     ok(!ret, "font Arial Bold Italic is not enumerated\n");
3744     ret = strcmp(lf.lfFaceName, "Arial");
3745     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3746     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
3747
3748     lstrcpy(lf.lfFaceName, "Arial Bold Italic");
3749     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3750     ok(ret, "font Arial Bold Italic should not be enumerated\n");
3751
3752     ret = EnumFontFamilies(hdc, "Arial Italic Bold", enum_fonts_proc, (LPARAM)&lf);
3753     ok(ret, "font Arial Italic Bold  should not be enumerated\n");
3754
3755     lstrcpy(lf.lfFaceName, "Arial Italic Bold");
3756     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3757     ok(ret, "font Arial Italic Bold should not be enumerated\n");
3758
3759     DeleteDC(hdc);
3760 }
3761
3762 static INT CALLBACK is_font_installed_fullname_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
3763 {
3764     const ENUMLOGFONT *elf = (const ENUMLOGFONT *)lf;
3765     const char *fullname = (const char *)lParam;
3766
3767     if (!strcmp((const char *)elf->elfFullName, fullname)) return 0;
3768
3769     return 1;
3770 }
3771
3772 static BOOL is_font_installed_fullname(const char *family, const char *fullname)
3773 {
3774     HDC hdc = GetDC(0);
3775     BOOL ret = FALSE;
3776
3777     if(!EnumFontFamiliesA(hdc, family, is_font_installed_fullname_proc, (LPARAM)fullname))
3778         ret = TRUE;
3779
3780     ReleaseDC(0, hdc);
3781     return ret;
3782 }
3783
3784 static void test_fullname(void)
3785 {
3786     static const char *TestName[] = {"Lucida Sans Demibold Roman", "Lucida Sans Italic", "Lucida Sans Regular"};
3787     char buf[LF_FULLFACESIZE];
3788     HFONT hfont, of;
3789     LOGFONTA lf;
3790     HDC hdc;
3791     int i;
3792
3793     hdc = CreateCompatibleDC(0);
3794     ok(hdc != NULL, "CreateCompatibleDC failed\n");
3795
3796     memset(&lf, 0, sizeof(lf));
3797     lf.lfCharSet = ANSI_CHARSET;
3798     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
3799     lf.lfHeight = 16;
3800     lf.lfWidth = 16;
3801     lf.lfQuality = DEFAULT_QUALITY;
3802     lf.lfItalic = FALSE;
3803     lf.lfWeight = FW_DONTCARE;
3804
3805     for (i = 0; i < sizeof(TestName) / sizeof(TestName[0]); i++)
3806     {
3807         if (!is_font_installed_fullname("Lucida Sans", TestName[i]))
3808         {
3809             skip("%s is not installed\n", TestName[i]);
3810             continue;
3811         }
3812
3813         lstrcpyA(lf.lfFaceName, TestName[i]);
3814         hfont = CreateFontIndirectA(&lf);
3815         ok(hfont != 0, "CreateFontIndirectA failed\n");
3816
3817         of = SelectObject(hdc, hfont);
3818         buf[0] = 0;
3819         ok(get_ttf_nametable_entry(hdc, TT_NAME_ID_FULL_NAME, buf, sizeof(buf)),
3820            "face full name could not be read\n");
3821         ok(!lstrcmpA(buf, TestName[i]), "font full names don't match: %s != %s\n", TestName[i], buf);
3822         SelectObject(hdc, of);
3823         DeleteObject(hfont);
3824     }
3825     DeleteDC(hdc);
3826 }
3827
3828 static BOOL write_ttf_file(char *tmp_name)
3829 {
3830     char tmp_path[MAX_PATH];
3831     HRSRC rsrc;
3832     void *rsrc_data;
3833     DWORD rsrc_size;
3834     HANDLE hfile;
3835     BOOL ret;
3836
3837     SetLastError(0xdeadbeef);
3838     rsrc = FindResource(GetModuleHandle(0), "wine_test.ttf", RT_RCDATA);
3839     ok(rsrc != 0, "FindResource error %d\n", GetLastError());
3840     if (!rsrc) return FALSE;
3841     SetLastError(0xdeadbeef);
3842     rsrc_data = LockResource(LoadResource(GetModuleHandle(0), rsrc));
3843     ok(rsrc_data != 0, "LockResource error %d\n", GetLastError());
3844     if (!rsrc_data) return FALSE;
3845     SetLastError(0xdeadbeef);
3846     rsrc_size = SizeofResource(GetModuleHandle(0), rsrc);
3847     ok(rsrc_size != 0, "SizeofResource error %d\n", GetLastError());
3848     if (!rsrc_size) return FALSE;
3849
3850     SetLastError(0xdeadbeef);
3851     ret = GetTempPath(MAX_PATH, tmp_path);
3852     ok(ret, "GetTempPath() error %d\n", GetLastError());
3853     SetLastError(0xdeadbeef);
3854     ret = GetTempFileName(tmp_path, "ttf", 0, tmp_name);
3855     ok(ret, "GetTempFileName() error %d\n", GetLastError());
3856
3857     SetLastError(0xdeadbeef);
3858     hfile = CreateFile(tmp_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
3859     ok(hfile != INVALID_HANDLE_VALUE, "CreateFile() error %d\n", GetLastError());
3860     if (hfile == INVALID_HANDLE_VALUE) return FALSE;
3861
3862     SetLastError(0xdeadbeef);
3863     ret = WriteFile(hfile, rsrc_data, rsrc_size, &rsrc_size, NULL);
3864     ok(ret, "WriteFile() error %d\n", GetLastError());
3865
3866     CloseHandle(hfile);
3867     return ret;
3868 }
3869
3870 static void test_CreateScalableFontResource(void)
3871 {
3872     char ttf_name[MAX_PATH];
3873     char tmp_path[MAX_PATH];
3874     char fot_name[MAX_PATH];
3875     char *file_part;
3876     DWORD ret;
3877
3878     if (!pAddFontResourceExA || !pRemoveFontResourceExA)
3879     {
3880         win_skip("AddFontResourceExA is not available on this platform\n");
3881         return;
3882     }
3883
3884     if (!write_ttf_file(ttf_name))
3885     {
3886         skip("Failed to create ttf file for testing\n");
3887         return;
3888     }
3889
3890     trace("created %s\n", ttf_name);
3891
3892     ret = is_truetype_font_installed("wine_test");
3893     ok(!ret, "font wine_test should not be enumerated\n");
3894
3895     ret = GetTempPath(MAX_PATH, tmp_path);
3896     ok(ret, "GetTempPath() error %d\n", GetLastError());
3897     ret = GetTempFileName(tmp_path, "fot", 0, fot_name);
3898     ok(ret, "GetTempFileName() error %d\n", GetLastError());
3899
3900     ret = GetFileAttributes(fot_name);
3901     ok(ret != INVALID_FILE_ATTRIBUTES, "file %s does not exist\n", fot_name);
3902
3903     SetLastError(0xdeadbeef);
3904     ret = CreateScalableFontResource(0, fot_name, ttf_name, NULL);
3905     ok(!ret, "CreateScalableFontResource() should fail\n");
3906     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
3907
3908     SetLastError(0xdeadbeef);
3909     ret = CreateScalableFontResource(0, fot_name, ttf_name, "");
3910     ok(!ret, "CreateScalableFontResource() should fail\n");
3911     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
3912
3913     file_part = strrchr(ttf_name, '\\');
3914     SetLastError(0xdeadbeef);
3915     ret = CreateScalableFontResource(0, fot_name, file_part, tmp_path);
3916     ok(!ret, "CreateScalableFontResource() should fail\n");
3917     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
3918
3919     SetLastError(0xdeadbeef);
3920     ret = CreateScalableFontResource(0, fot_name, "random file name", tmp_path);
3921     ok(!ret, "CreateScalableFontResource() should fail\n");
3922 todo_wine
3923     ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
3924
3925     SetLastError(0xdeadbeef);
3926     ret = CreateScalableFontResource(0, fot_name, NULL, ttf_name);
3927     ok(!ret, "CreateScalableFontResource() should fail\n");
3928 todo_wine
3929     ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
3930
3931     ret = DeleteFile(fot_name);
3932     ok(ret, "DeleteFile() error %d\n", GetLastError());
3933
3934     ret = pRemoveFontResourceExA(fot_name, 0, 0);
3935 todo_wine
3936     ok(!ret, "RemoveFontResourceEx() should fail\n");
3937
3938     /* FIXME: since CreateScalableFontResource is a stub further testing is impossible */
3939     if (ret) return;
3940
3941     /* test public font resource */
3942     SetLastError(0xdeadbeef);
3943     ret = CreateScalableFontResource(0, fot_name, ttf_name, NULL);
3944     ok(ret, "CreateScalableFontResource() error %d\n", GetLastError());
3945
3946     ret = is_truetype_font_installed("wine_test");
3947     ok(!ret, "font wine_test should not be enumerated\n");
3948
3949     SetLastError(0xdeadbeef);
3950     ret = pAddFontResourceExA(fot_name, 0, 0);
3951     ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
3952
3953     ret = is_truetype_font_installed("wine_test");
3954     ok(ret, "font wine_test should be enumerated\n");
3955
3956     ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
3957     ok(!ret, "RemoveFontResourceEx() with not matching flags should fail\n");
3958
3959     SetLastError(0xdeadbeef);
3960     ret = pRemoveFontResourceExA(fot_name, 0, 0);
3961 todo_wine
3962     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
3963
3964     ret = is_truetype_font_installed("wine_test");
3965 todo_wine
3966     ok(!ret, "font wine_test should not be enumerated\n");
3967
3968     /* FIXME: since RemoveFontResource is a stub correct testing is impossible */
3969     if (ret)
3970     {
3971         /* remove once RemoveFontResource is implemented */
3972         DeleteFile(fot_name);
3973         DeleteFile(ttf_name);
3974         return;
3975     }
3976
3977     ret = pRemoveFontResourceExA(fot_name, 0, 0);
3978     ok(!ret, "RemoveFontResourceEx() should fail\n");
3979
3980     DeleteFile(fot_name);
3981
3982     /* test hidden font resource */
3983     SetLastError(0xdeadbeef);
3984     ret = CreateScalableFontResource(1, fot_name, ttf_name, NULL);
3985     ok(ret, "CreateScalableFontResource() error %d\n", GetLastError());
3986
3987     ret = is_truetype_font_installed("wine_test");
3988     ok(!ret, "font wine_test should not be enumerated\n");
3989
3990     SetLastError(0xdeadbeef);
3991     ret = pAddFontResourceExA(fot_name, 0, 0);
3992     ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
3993
3994     ret = is_truetype_font_installed("wine_test");
3995     ok(!ret, "font wine_test should not be enumerated\n");
3996
3997     /* XP allows removing a private font added with 0 flags */
3998     SetLastError(0xdeadbeef);
3999     ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
4000     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
4001
4002     ret = is_truetype_font_installed("wine_test");
4003     ok(!ret, "font wine_test should not be enumerated\n");
4004
4005     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4006     ok(!ret, "RemoveFontResourceEx() should fail\n");
4007
4008     DeleteFile(fot_name);
4009     DeleteFile(ttf_name);
4010 }
4011
4012 START_TEST(font)
4013 {
4014     init();
4015
4016     test_logfont();
4017     test_bitmap_font();
4018     test_outline_font();
4019     test_bitmap_font_metrics();
4020     test_GdiGetCharDimensions();
4021     test_GetCharABCWidths();
4022     test_text_extents();
4023     test_GetGlyphIndices();
4024     test_GetKerningPairs();
4025     test_GetOutlineTextMetrics();
4026     test_SetTextJustification();
4027     test_font_charset();
4028     test_GetFontUnicodeRanges();
4029     test_nonexistent_font();
4030     test_orientation();
4031     test_height_selection();
4032     test_AddFontMemResource();
4033     test_EnumFonts();
4034
4035     /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
4036      * I'd like to avoid them in this test.
4037      */
4038     test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
4039     test_EnumFontFamilies("Symbol", SYMBOL_CHARSET);
4040     if (is_truetype_font_installed("Arial Black") &&
4041         (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
4042     {
4043         test_EnumFontFamilies("", ANSI_CHARSET);
4044         test_EnumFontFamilies("", SYMBOL_CHARSET);
4045         test_EnumFontFamilies("", DEFAULT_CHARSET);
4046     }
4047     else
4048         skip("Arial Black or Symbol/Wingdings is not installed\n");
4049     test_EnumFontFamiliesEx_default_charset();
4050     test_GetTextMetrics();
4051     test_GdiRealizationInfo();
4052     test_GetTextFace();
4053     test_GetGlyphOutline();
4054     test_GetTextMetrics2("Tahoma", -11);
4055     test_GetTextMetrics2("Tahoma", -55);
4056     test_GetTextMetrics2("Tahoma", -110);
4057     test_GetTextMetrics2("Arial", -11);
4058     test_GetTextMetrics2("Arial", -55);
4059     test_GetTextMetrics2("Arial", -110);
4060     test_CreateFontIndirect();
4061     test_CreateFontIndirectEx();
4062     test_oemcharset();
4063     test_fullname();
4064
4065     /* CreateScalableFontResource should be last test until RemoveFontResource
4066      * is properly implemented.
4067      */
4068     test_CreateScalableFontResource();
4069 }