gdi32/tests: Add some tests for the behavior of a printer DC.
[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     /* max_extent = 0 succeeds and returns zero */
1137     fit1 = fit2 = -215;
1138     ret = GetTextExtentExPointA(hdc, NULL, 0, 0, &fit1, NULL, &sz);
1139     ok(ret == TRUE ||
1140        broken(ret == FALSE), /* NT4, 2k */
1141        "got %d\n", ret);
1142     ok(fit1 == 0 ||
1143        broken(fit1 == -215), /* NT4, 2k */
1144        "fit = %d\n", fit1);
1145     ret = GetTextExtentExPointW(hdc, NULL, 0, 0, &fit2, NULL, &sz1);
1146     ok(ret == TRUE, "got %d\n", ret);
1147     ok(fit2 == 0, "fit = %d\n", fit2);
1148
1149     /* max_extent = -1 is interpreted as a very large width that will
1150      * definitely fit our three characters */
1151     fit1 = fit2 = -215;
1152     ret = GetTextExtentExPointA(hdc, "One", 3, -1, &fit1, NULL, &sz);
1153     ok(ret == TRUE, "got %d\n", ret);
1154     todo_wine ok(fit1 == 3, "fit = %d\n", fit1);
1155     ret = GetTextExtentExPointW(hdc, wt, 3, -1, &fit2, NULL, &sz);
1156     ok(ret == TRUE, "got %d\n", ret);
1157     todo_wine ok(fit2 == 3, "fit = %d\n", fit2);
1158
1159     /* max_extent = -2 is interpreted similarly, but the Ansi version
1160      * rejects it while the Unicode one accepts it */
1161     fit1 = fit2 = -215;
1162     ret = GetTextExtentExPointA(hdc, "One", 3, -2, &fit1, NULL, &sz);
1163     todo_wine ok(ret == FALSE, "got %d\n", ret);
1164     todo_wine ok(fit1 == -215, "fit = %d\n", fit1);
1165     ret = GetTextExtentExPointW(hdc, wt, 3, -2, &fit2, NULL, &sz);
1166     ok(ret == TRUE, "got %d\n", ret);
1167     todo_wine ok(fit2 == 3, "fit = %d\n", fit2);
1168
1169     hfont = SelectObject(hdc, hfont);
1170     DeleteObject(hfont);
1171     ReleaseDC(NULL, hdc);
1172 }
1173
1174 static void test_GetGlyphIndices(void)
1175 {
1176     HDC      hdc;
1177     HFONT    hfont;
1178     DWORD    charcount;
1179     LOGFONTA lf;
1180     DWORD    flags = 0;
1181     WCHAR    testtext[] = {'T','e','s','t',0xffff,0};
1182     WORD     glyphs[(sizeof(testtext)/2)-1];
1183     TEXTMETRIC textm;
1184     HFONT hOldFont;
1185
1186     if (!pGetGlyphIndicesW) {
1187         win_skip("GetGlyphIndicesW not available on platform\n");
1188         return;
1189     }
1190
1191     hdc = GetDC(0);
1192
1193     memset(&lf, 0, sizeof(lf));
1194     strcpy(lf.lfFaceName, "System");
1195     lf.lfHeight = 16;
1196     lf.lfCharSet = ANSI_CHARSET;
1197
1198     hfont = CreateFontIndirectA(&lf);
1199     ok(hfont != 0, "CreateFontIndirectEx failed\n");
1200     ok(GetTextMetrics(hdc, &textm), "GetTextMetric failed\n");
1201     if (textm.tmCharSet == ANSI_CHARSET)
1202     {
1203         flags |= GGI_MARK_NONEXISTING_GLYPHS;
1204         charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1205         ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1206         ok((glyphs[4] == 0x001f || glyphs[4] == 0xffff /* Vista */), "GetGlyphIndicesW should have returned a nonexistent char not %04x\n", glyphs[4]);
1207         flags = 0;
1208         charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1209         ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1210         ok(glyphs[4] == textm.tmDefaultChar, "GetGlyphIndicesW should have returned a %04x not %04x\n",
1211                         textm.tmDefaultChar, glyphs[4]);
1212     }
1213     else
1214         /* FIXME: Write tests for non-ANSI charsets. */
1215         skip("GetGlyphIndices System font tests only for ANSI_CHARSET\n");
1216
1217     if(!is_font_installed("Tahoma"))
1218     {
1219         skip("Tahoma is not installed so skipping this test\n");
1220         return;
1221     }
1222     memset(&lf, 0, sizeof(lf));
1223     strcpy(lf.lfFaceName, "Tahoma");
1224     lf.lfHeight = 20;
1225
1226     hfont = CreateFontIndirectA(&lf);
1227     hOldFont = SelectObject(hdc, hfont);
1228     ok(GetTextMetrics(hdc, &textm), "GetTextMetric failed\n");
1229     flags |= GGI_MARK_NONEXISTING_GLYPHS;
1230     charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1231     ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1232     ok(glyphs[4] == 0xffff, "GetGlyphIndicesW should have returned 0xffff char not %04x\n", glyphs[4]);
1233     flags = 0;
1234     testtext[0] = textm.tmDefaultChar;
1235     charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1236     ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1237     ok(glyphs[0] == 0, "GetGlyphIndicesW for tmDefaultChar should be 0 not %04x\n", glyphs[0]);
1238     ok(glyphs[4] == 0, "GetGlyphIndicesW should have returned 0 not %04x\n", glyphs[4]);
1239     DeleteObject(SelectObject(hdc, hOldFont));
1240 }
1241
1242 static void test_GetKerningPairs(void)
1243 {
1244     static const struct kerning_data
1245     {
1246         const char face_name[LF_FACESIZE];
1247         LONG height;
1248         /* some interesting fields from OUTLINETEXTMETRIC */
1249         LONG tmHeight, tmAscent, tmDescent;
1250         UINT otmEMSquare;
1251         INT  otmAscent;
1252         INT  otmDescent;
1253         UINT otmLineGap;
1254         UINT otmsCapEmHeight;
1255         UINT otmsXHeight;
1256         INT  otmMacAscent;
1257         INT  otmMacDescent;
1258         UINT otmMacLineGap;
1259         UINT otmusMinimumPPEM;
1260         /* small subset of kerning pairs to test */
1261         DWORD total_kern_pairs;
1262         const KERNINGPAIR kern_pair[26];
1263     } kd[] =
1264     {
1265         {"Arial", 12, 12, 9, 3,
1266                   2048, 7, -2, 1, 5, 2, 8, -2, 0, 9,
1267                   26,
1268             {
1269                 {' ','A',-1},{' ','T',0},{' ','Y',0},{'1','1',-1},
1270                 {'A',' ',-1},{'A','T',-1},{'A','V',-1},{'A','W',0},
1271                 {'A','Y',-1},{'A','v',0},{'A','w',0},{'A','y',0},
1272                 {'F',',',-1},{'F','.',-1},{'F','A',-1},{'L',' ',0},
1273                 {'L','T',-1},{'L','V',-1},{'L','W',-1},{'L','Y',-1},
1274                 {915,912,+1},{915,913,-1},{910,912,+1},{910,913,-1},
1275                 {933,970,+1},{933,972,-1}
1276                 }
1277         },
1278         {"Arial", -34, 39, 32, 7,
1279                   2048, 25, -7, 5, 17, 9, 31, -7, 1, 9,
1280                   26,
1281             {
1282                 {' ','A',-2},{' ','T',-1},{' ','Y',-1},{'1','1',-3},
1283                 {'A',' ',-2},{'A','T',-3},{'A','V',-3},{'A','W',-1},
1284                 {'A','Y',-3},{'A','v',-1},{'A','w',-1},{'A','y',-1},
1285                 {'F',',',-4},{'F','.',-4},{'F','A',-2},{'L',' ',-1},
1286                 {'L','T',-3},{'L','V',-3},{'L','W',-3},{'L','Y',-3},
1287                 {915,912,+3},{915,913,-3},{910,912,+3},{910,913,-3},
1288                 {933,970,+2},{933,972,-3}
1289             }
1290         },
1291         { "Arial", 120, 120, 97, 23,
1292                    2048, 79, -23, 16, 54, 27, 98, -23, 4, 9,
1293                    26,
1294             {
1295                 {' ','A',-6},{' ','T',-2},{' ','Y',-2},{'1','1',-8},
1296                 {'A',' ',-6},{'A','T',-8},{'A','V',-8},{'A','W',-4},
1297                 {'A','Y',-8},{'A','v',-2},{'A','w',-2},{'A','y',-2},
1298                 {'F',',',-12},{'F','.',-12},{'F','A',-6},{'L',' ',-4},
1299                 {'L','T',-8},{'L','V',-8},{'L','W',-8},{'L','Y',-8},
1300                 {915,912,+9},{915,913,-10},{910,912,+9},{910,913,-8},
1301                 {933,970,+6},{933,972,-10}
1302             }
1303         },
1304 #if 0 /* this set fails due to +1/-1 errors (rounding bug?), needs investigation. */
1305         { "Arial", 1024 /* usually 1/2 of EM Square */, 1024, 830, 194,
1306                    2048, 668, -193, 137, 459, 229, 830, -194, 30, 9,
1307                    26,
1308             {
1309                 {' ','A',-51},{' ','T',-17},{' ','Y',-17},{'1','1',-68},
1310                 {'A',' ',-51},{'A','T',-68},{'A','V',-68},{'A','W',-34},
1311                 {'A','Y',-68},{'A','v',-17},{'A','w',-17},{'A','y',-17},
1312                 {'F',',',-102},{'F','.',-102},{'F','A',-51},{'L',' ',-34},
1313                 {'L','T',-68},{'L','V',-68},{'L','W',-68},{'L','Y',-68},
1314                 {915,912,+73},{915,913,-84},{910,912,+76},{910,913,-68},
1315                 {933,970,+54},{933,972,-83}
1316             }
1317         }
1318 #endif
1319     };
1320     LOGFONT lf;
1321     HFONT hfont, hfont_old;
1322     KERNINGPAIR *kern_pair;
1323     HDC hdc;
1324     DWORD total_kern_pairs, ret, i, n, matches;
1325
1326     hdc = GetDC(0);
1327
1328     /* GetKerningPairsA maps unicode set of kerning pairs to current code page
1329      * which may render this test unusable, so we're trying to avoid that.
1330      */
1331     SetLastError(0xdeadbeef);
1332     GetKerningPairsW(hdc, 0, NULL);
1333     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1334     {
1335         win_skip("Skipping the GetKerningPairs test on a Win9x platform\n");
1336         ReleaseDC(0, hdc);
1337         return;
1338     }
1339
1340     for (i = 0; i < sizeof(kd)/sizeof(kd[0]); i++)
1341     {
1342         OUTLINETEXTMETRICW otm;
1343         UINT uiRet;
1344
1345         if (!is_font_installed(kd[i].face_name))
1346         {
1347             trace("%s is not installed so skipping this test\n", kd[i].face_name);
1348             continue;
1349         }
1350
1351         trace("testing font %s, height %d\n", kd[i].face_name, kd[i].height);
1352
1353         memset(&lf, 0, sizeof(lf));
1354         strcpy(lf.lfFaceName, kd[i].face_name);
1355         lf.lfHeight = kd[i].height;
1356         hfont = CreateFontIndirect(&lf);
1357         assert(hfont != 0);
1358
1359         hfont_old = SelectObject(hdc, hfont);
1360
1361         SetLastError(0xdeadbeef);
1362         otm.otmSize = sizeof(otm); /* just in case for Win9x compatibility */
1363         uiRet = GetOutlineTextMetricsW(hdc, sizeof(otm), &otm);
1364         ok(uiRet == sizeof(otm), "GetOutlineTextMetricsW error %d\n", GetLastError());
1365
1366         ok(match_off_by_1(kd[i].tmHeight, otm.otmTextMetrics.tmHeight), "expected %d, got %d\n",
1367            kd[i].tmHeight, otm.otmTextMetrics.tmHeight);
1368         ok(match_off_by_1(kd[i].tmAscent, otm.otmTextMetrics.tmAscent), "expected %d, got %d\n",
1369            kd[i].tmAscent, otm.otmTextMetrics.tmAscent);
1370         ok(kd[i].tmDescent == otm.otmTextMetrics.tmDescent, "expected %d, got %d\n",
1371            kd[i].tmDescent, otm.otmTextMetrics.tmDescent);
1372
1373         ok(kd[i].otmEMSquare == otm.otmEMSquare, "expected %u, got %u\n",
1374            kd[i].otmEMSquare, otm.otmEMSquare);
1375         ok(kd[i].otmAscent == otm.otmAscent, "expected %d, got %d\n",
1376            kd[i].otmAscent, otm.otmAscent);
1377         ok(kd[i].otmDescent == otm.otmDescent, "expected %d, got %d\n",
1378            kd[i].otmDescent, otm.otmDescent);
1379         ok(kd[i].otmLineGap == otm.otmLineGap, "expected %u, got %u\n",
1380            kd[i].otmLineGap, otm.otmLineGap);
1381         ok(near_match(kd[i].otmMacDescent, otm.otmMacDescent), "expected %d, got %d\n",
1382            kd[i].otmMacDescent, otm.otmMacDescent);
1383         ok(near_match(kd[i].otmMacAscent, otm.otmMacAscent), "expected %d, got %d\n",
1384            kd[i].otmMacAscent, otm.otmMacAscent);
1385 todo_wine {
1386         ok(kd[i].otmsCapEmHeight == otm.otmsCapEmHeight, "expected %u, got %u\n",
1387            kd[i].otmsCapEmHeight, otm.otmsCapEmHeight);
1388         ok(kd[i].otmsXHeight == otm.otmsXHeight, "expected %u, got %u\n",
1389            kd[i].otmsXHeight, otm.otmsXHeight);
1390         /* FIXME: this one sometimes succeeds due to expected 0, enable it when removing todo */
1391         if (0) ok(kd[i].otmMacLineGap == otm.otmMacLineGap, "expected %u, got %u\n",
1392            kd[i].otmMacLineGap, otm.otmMacLineGap);
1393         ok(kd[i].otmusMinimumPPEM == otm.otmusMinimumPPEM, "expected %u, got %u\n",
1394            kd[i].otmusMinimumPPEM, otm.otmusMinimumPPEM);
1395 }
1396
1397         total_kern_pairs = GetKerningPairsW(hdc, 0, NULL);
1398         trace("total_kern_pairs %u\n", total_kern_pairs);
1399         kern_pair = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pair));
1400
1401         /* Win98 (GetKerningPairsA) and XP behave differently here, the test
1402          * passes on XP.
1403          */
1404         SetLastError(0xdeadbeef);
1405         ret = GetKerningPairsW(hdc, 0, kern_pair);
1406         ok(GetLastError() == ERROR_INVALID_PARAMETER,
1407            "got error %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
1408         ok(ret == 0, "got %u, expected 0\n", ret);
1409
1410         ret = GetKerningPairsW(hdc, 100, NULL);
1411         ok(ret == total_kern_pairs, "got %u, expected %u\n", ret, total_kern_pairs);
1412
1413         ret = GetKerningPairsW(hdc, total_kern_pairs/2, kern_pair);
1414         ok(ret == total_kern_pairs/2, "got %u, expected %u\n", ret, total_kern_pairs/2);
1415
1416         ret = GetKerningPairsW(hdc, total_kern_pairs, kern_pair);
1417         ok(ret == total_kern_pairs, "got %u, expected %u\n", ret, total_kern_pairs);
1418
1419         matches = 0;
1420
1421         for (n = 0; n < ret; n++)
1422         {
1423             DWORD j;
1424             /* Disabled to limit console spam */
1425             if (0 && kern_pair[n].wFirst < 127 && kern_pair[n].wSecond < 127)
1426                 trace("{'%c','%c',%d},\n",
1427                       kern_pair[n].wFirst, kern_pair[n].wSecond, kern_pair[n].iKernAmount);
1428             for (j = 0; j < kd[i].total_kern_pairs; j++)
1429             {
1430                 if (kern_pair[n].wFirst == kd[i].kern_pair[j].wFirst &&
1431                     kern_pair[n].wSecond == kd[i].kern_pair[j].wSecond)
1432                 {
1433                     ok(kern_pair[n].iKernAmount == kd[i].kern_pair[j].iKernAmount,
1434                        "pair %d:%d got %d, expected %d\n",
1435                        kern_pair[n].wFirst, kern_pair[n].wSecond,
1436                        kern_pair[n].iKernAmount, kd[i].kern_pair[j].iKernAmount);
1437                     matches++;
1438                 }
1439             }
1440         }
1441
1442         ok(matches == kd[i].total_kern_pairs, "got matches %u, expected %u\n",
1443            matches, kd[i].total_kern_pairs);
1444
1445         HeapFree(GetProcessHeap(), 0, kern_pair);
1446
1447         SelectObject(hdc, hfont_old);
1448         DeleteObject(hfont);
1449     }
1450
1451     ReleaseDC(0, hdc);
1452 }
1453
1454 static void test_height_selection(void)
1455 {
1456     static const struct font_data
1457     {
1458         const char face_name[LF_FACESIZE];
1459         int requested_height;
1460         int weight, height, ascent, descent, int_leading, ext_leading, dpi;
1461     } fd[] =
1462     {
1463         {"Tahoma", -12, FW_NORMAL, 14, 12, 2, 2, 0, 96 },
1464         {"Tahoma", -24, FW_NORMAL, 29, 24, 5, 5, 0, 96 },
1465         {"Tahoma", -48, FW_NORMAL, 58, 48, 10, 10, 0, 96 },
1466         {"Tahoma", -96, FW_NORMAL, 116, 96, 20, 20, 0, 96 },
1467         {"Tahoma", -192, FW_NORMAL, 232, 192, 40, 40, 0, 96 },
1468         {"Tahoma", 12, FW_NORMAL, 12, 10, 2, 2, 0, 96 },
1469         {"Tahoma", 24, FW_NORMAL, 24, 20, 4, 4, 0, 96 },
1470         {"Tahoma", 48, FW_NORMAL, 48, 40, 8, 8, 0, 96 },
1471         {"Tahoma", 96, FW_NORMAL, 96, 80, 16, 17, 0, 96 },
1472         {"Tahoma", 192, FW_NORMAL, 192, 159, 33, 33, 0, 96 }
1473     };
1474     HDC hdc;
1475     LOGFONT lf;
1476     HFONT hfont, old_hfont;
1477     TEXTMETRIC tm;
1478     INT ret, i;
1479
1480     hdc = CreateCompatibleDC(0);
1481     assert(hdc);
1482
1483     for (i = 0; i < sizeof(fd)/sizeof(fd[0]); i++)
1484     {
1485         if (!is_truetype_font_installed(fd[i].face_name))
1486         {
1487             skip("%s is not installed\n", fd[i].face_name);
1488             continue;
1489         }
1490
1491         memset(&lf, 0, sizeof(lf));
1492         lf.lfHeight = fd[i].requested_height;
1493         lf.lfWeight = fd[i].weight;
1494         strcpy(lf.lfFaceName, fd[i].face_name);
1495
1496         hfont = CreateFontIndirect(&lf);
1497         assert(hfont);
1498
1499         old_hfont = SelectObject(hdc, hfont);
1500         ret = GetTextMetrics(hdc, &tm);
1501         ok(ret, "GetTextMetrics error %d\n", GetLastError());
1502         if(fd[i].dpi == tm.tmDigitizedAspectX)
1503         {
1504             trace("found font %s, height %d charset %x dpi %d\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet, fd[i].dpi);
1505             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);
1506             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);
1507             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);
1508             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);
1509 #if 0 /* FIXME: calculation of tmInternalLeading in Wine doesn't match what Windows does */
1510             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);
1511 #endif
1512             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);
1513         }
1514
1515         SelectObject(hdc, old_hfont);
1516         DeleteObject(hfont);
1517     }
1518
1519     DeleteDC(hdc);
1520 }
1521
1522 static void test_GetOutlineTextMetrics(void)
1523 {
1524     OUTLINETEXTMETRIC *otm;
1525     LOGFONT lf;
1526     HFONT hfont, hfont_old;
1527     HDC hdc;
1528     DWORD ret, otm_size;
1529     LPSTR unset_ptr;
1530
1531     if (!is_font_installed("Arial"))
1532     {
1533         skip("Arial is not installed\n");
1534         return;
1535     }
1536
1537     hdc = GetDC(0);
1538
1539     memset(&lf, 0, sizeof(lf));
1540     strcpy(lf.lfFaceName, "Arial");
1541     lf.lfHeight = -13;
1542     lf.lfWeight = FW_NORMAL;
1543     lf.lfPitchAndFamily = DEFAULT_PITCH;
1544     lf.lfQuality = PROOF_QUALITY;
1545     hfont = CreateFontIndirect(&lf);
1546     assert(hfont != 0);
1547
1548     hfont_old = SelectObject(hdc, hfont);
1549     otm_size = GetOutlineTextMetrics(hdc, 0, NULL);
1550     trace("otm buffer size %u (0x%x)\n", otm_size, otm_size);
1551
1552     otm = HeapAlloc(GetProcessHeap(), 0, otm_size);
1553
1554     memset(otm, 0xAA, otm_size);
1555     SetLastError(0xdeadbeef);
1556     otm->otmSize = sizeof(*otm); /* just in case for Win9x compatibility */
1557     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1558     ok(ret == 1 /* Win9x */ ||
1559        ret == otm->otmSize /* XP*/,
1560        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1561     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1562     {
1563         ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
1564         ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
1565         ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
1566         ok(otm->otmpFullName == NULL, "expected NULL got %p\n", otm->otmpFullName);
1567     }
1568
1569     memset(otm, 0xAA, otm_size);
1570     SetLastError(0xdeadbeef);
1571     otm->otmSize = otm_size; /* just in case for Win9x compatibility */
1572     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1573     ok(ret == 1 /* Win9x */ ||
1574        ret == otm->otmSize /* XP*/,
1575        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1576     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1577     {
1578         ok(otm->otmpFamilyName != NULL, "expected not NULL got %p\n", otm->otmpFamilyName);
1579         ok(otm->otmpFaceName != NULL, "expected not NULL got %p\n", otm->otmpFaceName);
1580         ok(otm->otmpStyleName != NULL, "expected not NULL got %p\n", otm->otmpStyleName);
1581         ok(otm->otmpFullName != NULL, "expected not NULL got %p\n", otm->otmpFullName);
1582     }
1583
1584     /* ask about truncated data */
1585     memset(otm, 0xAA, otm_size);
1586     memset(&unset_ptr, 0xAA, sizeof(unset_ptr));
1587     SetLastError(0xdeadbeef);
1588     otm->otmSize = sizeof(*otm) - sizeof(LPSTR); /* just in case for Win9x compatibility */
1589     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1590     ok(ret == 1 /* Win9x */ ||
1591        ret == otm->otmSize /* XP*/,
1592        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1593     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1594     {
1595         ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
1596         ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
1597         ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
1598     }
1599     ok(otm->otmpFullName == unset_ptr, "expected %p got %p\n", unset_ptr, otm->otmpFullName);
1600
1601     HeapFree(GetProcessHeap(), 0, otm);
1602
1603     SelectObject(hdc, hfont_old);
1604     DeleteObject(hfont);
1605
1606     ReleaseDC(0, hdc);
1607 }
1608
1609 static void testJustification(HDC hdc, PSTR str, RECT *clientArea)
1610 {
1611     INT         y,
1612                 breakCount,
1613                 justifiedWidth = 0, /* to test GetTextExtentExPointW() */
1614                 areaWidth = clientArea->right - clientArea->left,
1615                 nErrors = 0, e;
1616     BOOL        lastExtent = FALSE;
1617     PSTR        pFirstChar, pLastChar;
1618     SIZE        size;
1619     TEXTMETRICA tm;
1620     struct err
1621     {
1622         char extent[100];
1623         int  GetTextExtentExPointWWidth;
1624     } error[10];
1625
1626     GetTextMetricsA(hdc, &tm);
1627     y = clientArea->top;
1628     do {
1629         breakCount = 0;
1630         while (*str == tm.tmBreakChar) str++; /* skip leading break chars */
1631         pFirstChar = str;
1632
1633         do {
1634             pLastChar = str;
1635
1636             /* if not at the end of the string, ... */
1637             if (*str == '\0') break;
1638             /* ... add the next word to the current extent */
1639             while (*str != '\0' && *str++ != tm.tmBreakChar);
1640             breakCount++;
1641             SetTextJustification(hdc, 0, 0);
1642             GetTextExtentPoint32(hdc, pFirstChar, str - pFirstChar - 1, &size);
1643         } while ((int) size.cx < areaWidth);
1644
1645         /* ignore trailing break chars */
1646         breakCount--;
1647         while (*(pLastChar - 1) == tm.tmBreakChar)
1648         {
1649             pLastChar--;
1650             breakCount--;
1651         }
1652
1653         if (*str == '\0' || breakCount <= 0) pLastChar = str;
1654
1655         SetTextJustification(hdc, 0, 0);
1656         GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
1657
1658         /* do not justify the last extent */
1659         if (*str != '\0' && breakCount > 0)
1660         {
1661             SetTextJustification(hdc, areaWidth - size.cx, breakCount);
1662             GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
1663             justifiedWidth = size.cx;
1664         }
1665         else lastExtent = TRUE;
1666
1667         /* catch errors and report them */
1668         if (!lastExtent && (justifiedWidth != areaWidth))
1669         {
1670             memset(error[nErrors].extent, 0, 100);
1671             memcpy(error[nErrors].extent, pFirstChar, pLastChar - pFirstChar);
1672             error[nErrors].GetTextExtentExPointWWidth = justifiedWidth;
1673             nErrors++;
1674         }
1675
1676         y += size.cy;
1677         str = pLastChar;
1678     } while (*str && y < clientArea->bottom);
1679
1680     for (e = 0; e < nErrors; e++)
1681     {
1682         /* The width returned by GetTextExtentPoint32() is exactly the same
1683            returned by GetTextExtentExPointW() - see dlls/gdi32/font.c */
1684         ok(error[e].GetTextExtentExPointWWidth == areaWidth,
1685             "GetTextExtentPointW() for \"%s\" should have returned a width of %d, not %d.\n",
1686             error[e].extent, areaWidth, error[e].GetTextExtentExPointWWidth);
1687     }
1688 }
1689
1690 static void test_SetTextJustification(void)
1691 {
1692     HDC hdc;
1693     RECT clientArea;
1694     LOGFONTA lf;
1695     HFONT hfont;
1696     HWND hwnd;
1697     static char testText[] =
1698             "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
1699             "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
1700             "enim ad minim veniam, quis nostrud exercitation ullamco laboris "
1701             "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in "
1702             "reprehenderit in voluptate velit esse cillum dolore eu fugiat "
1703             "nulla pariatur. Excepteur sint occaecat cupidatat non proident, "
1704             "sunt in culpa qui officia deserunt mollit anim id est laborum.";
1705
1706     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0, 400,400, 0, 0, 0, NULL);
1707     GetClientRect( hwnd, &clientArea );
1708     hdc = GetDC( hwnd );
1709
1710     memset(&lf, 0, sizeof lf);
1711     lf.lfCharSet = ANSI_CHARSET;
1712     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1713     lf.lfWeight = FW_DONTCARE;
1714     lf.lfHeight = 20;
1715     lf.lfQuality = DEFAULT_QUALITY;
1716     lstrcpyA(lf.lfFaceName, "Times New Roman");
1717     hfont = create_font("Times New Roman", &lf);
1718     SelectObject(hdc, hfont);
1719
1720     testJustification(hdc, testText, &clientArea);
1721
1722     DeleteObject(hfont);
1723     ReleaseDC(hwnd, hdc);
1724     DestroyWindow(hwnd);
1725 }
1726
1727 static BOOL get_glyph_indices(INT charset, UINT code_page, WORD *idx, UINT count, BOOL unicode)
1728 {
1729     HDC hdc;
1730     LOGFONTA lf;
1731     HFONT hfont, hfont_old;
1732     CHARSETINFO csi;
1733     FONTSIGNATURE fs;
1734     INT cs;
1735     DWORD i, ret;
1736     char name[64];
1737
1738     assert(count <= 128);
1739
1740     memset(&lf, 0, sizeof(lf));
1741
1742     lf.lfCharSet = charset;
1743     lf.lfHeight = 10;
1744     lstrcpyA(lf.lfFaceName, "Arial");
1745     SetLastError(0xdeadbeef);
1746     hfont = CreateFontIndirectA(&lf);
1747     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
1748
1749     hdc = GetDC(0);
1750     hfont_old = SelectObject(hdc, hfont);
1751
1752     cs = GetTextCharsetInfo(hdc, &fs, 0);
1753     ok(cs == charset, "expected %d, got %d\n", charset, cs);
1754
1755     SetLastError(0xdeadbeef);
1756     ret = GetTextFaceA(hdc, sizeof(name), name);
1757     ok(ret, "GetTextFaceA error %u\n", GetLastError());
1758
1759     if (charset == SYMBOL_CHARSET)
1760     {
1761         ok(strcmp("Arial", name), "face name should NOT be Arial\n");
1762         ok(fs.fsCsb[0] & (1 << 31), "symbol encoding should be available\n");
1763     }
1764     else
1765     {
1766         ok(!strcmp("Arial", name), "face name should be Arial, not %s\n", name);
1767         ok(!(fs.fsCsb[0] & (1 << 31)), "symbol encoding should NOT be available\n");
1768     }
1769
1770     if (!TranslateCharsetInfo((DWORD *)(INT_PTR)cs, &csi, TCI_SRCCHARSET))
1771     {
1772         trace("Can't find codepage for charset %d\n", cs);
1773         ReleaseDC(0, hdc);
1774         return FALSE;
1775     }
1776     ok(csi.ciACP == code_page, "expected %d, got %d\n", code_page, csi.ciACP);
1777
1778     if (pGdiGetCodePage != NULL && pGdiGetCodePage(hdc) != code_page)
1779     {
1780         skip("Font code page %d, looking for code page %d\n",
1781              pGdiGetCodePage(hdc), code_page);
1782         ReleaseDC(0, hdc);
1783         return FALSE;
1784     }
1785
1786     if (unicode)
1787     {
1788         char ansi_buf[128];
1789         WCHAR unicode_buf[128];
1790
1791         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
1792
1793         MultiByteToWideChar(code_page, 0, ansi_buf, count, unicode_buf, count);
1794
1795         SetLastError(0xdeadbeef);
1796         ret = pGetGlyphIndicesW(hdc, unicode_buf, count, idx, 0);
1797         ok(ret == count, "GetGlyphIndicesW expected %d got %d, error %u\n",
1798            count, ret, GetLastError());
1799     }
1800     else
1801     {
1802         char ansi_buf[128];
1803
1804         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
1805
1806         SetLastError(0xdeadbeef);
1807         ret = pGetGlyphIndicesA(hdc, ansi_buf, count, idx, 0);
1808         ok(ret == count, "GetGlyphIndicesA expected %d got %d, error %u\n",
1809            count, ret, GetLastError());
1810     }
1811
1812     SelectObject(hdc, hfont_old);
1813     DeleteObject(hfont);
1814
1815     ReleaseDC(0, hdc);
1816
1817     return TRUE;
1818 }
1819
1820 static void test_font_charset(void)
1821 {
1822     static struct charset_data
1823     {
1824         INT charset;
1825         UINT code_page;
1826         WORD font_idxA[128], font_idxW[128];
1827     } cd[] =
1828     {
1829         { ANSI_CHARSET, 1252 },
1830         { RUSSIAN_CHARSET, 1251 },
1831         { SYMBOL_CHARSET, CP_SYMBOL } /* keep it as the last one */
1832     };
1833     int i;
1834
1835     if (!pGetGlyphIndicesA || !pGetGlyphIndicesW)
1836     {
1837         win_skip("Skipping the font charset test on a Win9x platform\n");
1838         return;
1839     }
1840
1841     if (!is_font_installed("Arial"))
1842     {
1843         skip("Arial is not installed\n");
1844         return;
1845     }
1846
1847     for (i = 0; i < sizeof(cd)/sizeof(cd[0]); i++)
1848     {
1849         if (cd[i].charset == SYMBOL_CHARSET)
1850         {
1851             if (!is_font_installed("Symbol") && !is_font_installed("Wingdings"))
1852             {
1853                 skip("Symbol or Wingdings is not installed\n");
1854                 break;
1855             }
1856         }
1857         if (get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxA, 128, FALSE) &&
1858             get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxW, 128, TRUE))
1859             ok(!memcmp(cd[i].font_idxA, cd[i].font_idxW, 128*sizeof(WORD)), "%d: indices don't match\n", i);
1860     }
1861
1862     ok(memcmp(cd[0].font_idxW, cd[1].font_idxW, 128*sizeof(WORD)), "0 vs 1: indices shouldn't match\n");
1863     if (i > 2)
1864     {
1865         ok(memcmp(cd[0].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "0 vs 2: indices shouldn't match\n");
1866         ok(memcmp(cd[1].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "1 vs 2: indices shouldn't match\n");
1867     }
1868     else
1869         skip("Symbol or Wingdings is not installed\n");
1870 }
1871
1872 static void test_GetFontUnicodeRanges(void)
1873 {
1874     LOGFONTA lf;
1875     HDC hdc;
1876     HFONT hfont, hfont_old;
1877     DWORD size;
1878     GLYPHSET *gs;
1879     DWORD i;
1880
1881     if (!pGetFontUnicodeRanges)
1882     {
1883         win_skip("GetFontUnicodeRanges not available before W2K\n");
1884         return;
1885     }
1886
1887     memset(&lf, 0, sizeof(lf));
1888     lstrcpyA(lf.lfFaceName, "Arial");
1889     hfont = create_font("Arial", &lf);
1890
1891     hdc = GetDC(0);
1892     hfont_old = SelectObject(hdc, hfont);
1893
1894     size = pGetFontUnicodeRanges(NULL, NULL);
1895     ok(!size, "GetFontUnicodeRanges succeeded unexpectedly\n");
1896
1897     size = pGetFontUnicodeRanges(hdc, NULL);
1898     ok(size, "GetFontUnicodeRanges failed unexpectedly\n");
1899
1900     gs = HeapAlloc(GetProcessHeap(), 0, size);
1901
1902     size = pGetFontUnicodeRanges(hdc, gs);
1903     ok(size, "GetFontUnicodeRanges failed\n");
1904
1905     if (0) /* Disabled to limit console spam */
1906         for (i = 0; i < gs->cRanges; i++)
1907             trace("%03d wcLow %04x cGlyphs %u\n", i, gs->ranges[i].wcLow, gs->ranges[i].cGlyphs);
1908     trace("found %u ranges\n", gs->cRanges);
1909
1910     HeapFree(GetProcessHeap(), 0, gs);
1911
1912     SelectObject(hdc, hfont_old);
1913     DeleteObject(hfont);
1914     ReleaseDC(NULL, hdc);
1915 }
1916
1917 #define MAX_ENUM_FONTS 4096
1918
1919 struct enum_font_data
1920 {
1921     int total;
1922     LOGFONT lf[MAX_ENUM_FONTS];
1923 };
1924
1925 struct enum_font_dataW
1926 {
1927     int total;
1928     LOGFONTW lf[MAX_ENUM_FONTS];
1929 };
1930
1931 static INT CALLBACK arial_enum_proc(const LOGFONT *lf, const TEXTMETRIC *tm, DWORD type, LPARAM lParam)
1932 {
1933     struct enum_font_data *efd = (struct enum_font_data *)lParam;
1934
1935     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
1936
1937     if (type != TRUETYPE_FONTTYPE) return 1;
1938     if (0) /* Disabled to limit console spam */
1939         trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
1940               lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
1941     if (efd->total < MAX_ENUM_FONTS)
1942         efd->lf[efd->total++] = *lf;
1943     else
1944         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
1945
1946     return 1;
1947 }
1948
1949 static INT CALLBACK arial_enum_procw(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
1950 {
1951     struct enum_font_dataW *efd = (struct enum_font_dataW *)lParam;
1952
1953     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
1954
1955     if (type != TRUETYPE_FONTTYPE) return 1;
1956     if (0) /* Disabled to limit console spam */
1957         trace("enumed font %s, charset %d, height %d, weight %d, italic %d\n",
1958               wine_dbgstr_w(lf->lfFaceName), lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
1959     if (efd->total < MAX_ENUM_FONTS)
1960         efd->lf[efd->total++] = *lf;
1961     else
1962         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
1963
1964     return 1;
1965 }
1966
1967 static void get_charset_stats(struct enum_font_data *efd,
1968                               int *ansi_charset, int *symbol_charset,
1969                               int *russian_charset)
1970 {
1971     int i;
1972
1973     *ansi_charset = 0;
1974     *symbol_charset = 0;
1975     *russian_charset = 0;
1976
1977     for (i = 0; i < efd->total; i++)
1978     {
1979         switch (efd->lf[i].lfCharSet)
1980         {
1981         case ANSI_CHARSET:
1982             (*ansi_charset)++;
1983             break;
1984         case SYMBOL_CHARSET:
1985             (*symbol_charset)++;
1986             break;
1987         case RUSSIAN_CHARSET:
1988             (*russian_charset)++;
1989             break;
1990         }
1991     }
1992 }
1993
1994 static void get_charset_statsW(struct enum_font_dataW *efd,
1995                               int *ansi_charset, int *symbol_charset,
1996                               int *russian_charset)
1997 {
1998     int i;
1999
2000     *ansi_charset = 0;
2001     *symbol_charset = 0;
2002     *russian_charset = 0;
2003
2004     for (i = 0; i < efd->total; i++)
2005     {
2006         switch (efd->lf[i].lfCharSet)
2007         {
2008         case ANSI_CHARSET:
2009             (*ansi_charset)++;
2010             break;
2011         case SYMBOL_CHARSET:
2012             (*symbol_charset)++;
2013             break;
2014         case RUSSIAN_CHARSET:
2015             (*russian_charset)++;
2016             break;
2017         }
2018     }
2019 }
2020
2021 static void test_EnumFontFamilies(const char *font_name, INT font_charset)
2022 {
2023     struct enum_font_data efd;
2024     struct enum_font_dataW efdw;
2025     LOGFONT lf;
2026     HDC hdc;
2027     int i, ret, ansi_charset, symbol_charset, russian_charset;
2028
2029     trace("Testing font %s, charset %d\n", *font_name ? font_name : "<empty>", font_charset);
2030
2031     if (*font_name && !is_truetype_font_installed(font_name))
2032     {
2033         skip("%s is not installed\n", font_name);
2034         return;
2035     }
2036
2037     hdc = GetDC(0);
2038
2039     /* Observed behaviour: EnumFontFamilies enumerates aliases like "Arial Cyr"
2040      * while EnumFontFamiliesEx doesn't.
2041      */
2042     if (!*font_name && font_charset == DEFAULT_CHARSET) /* do it only once */
2043     {
2044         /*
2045          * Use EnumFontFamiliesW since win98 crashes when the
2046          *    second parameter is NULL using EnumFontFamilies
2047          */
2048         efdw.total = 0;
2049         SetLastError(0xdeadbeef);
2050         ret = EnumFontFamiliesW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw);
2051         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesW error %u\n", GetLastError());
2052         if(ret)
2053         {
2054             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
2055             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
2056                   ansi_charset, symbol_charset, russian_charset);
2057             ok(efdw.total > 0, "fonts enumerated: NULL\n");
2058             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
2059             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
2060             ok(russian_charset > 0 ||
2061                broken(russian_charset == 0), /* NT4 */
2062                "NULL family should enumerate RUSSIAN_CHARSET\n");
2063         }
2064
2065         efdw.total = 0;
2066         SetLastError(0xdeadbeef);
2067         ret = EnumFontFamiliesExW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw, 0);
2068         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesExW error %u\n", GetLastError());
2069         if(ret)
2070         {
2071             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
2072             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
2073                   ansi_charset, symbol_charset, russian_charset);
2074             ok(efdw.total > 0, "fonts enumerated: NULL\n");
2075             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
2076             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
2077             ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
2078         }
2079     }
2080
2081     efd.total = 0;
2082     SetLastError(0xdeadbeef);
2083     ret = EnumFontFamilies(hdc, font_name, arial_enum_proc, (LPARAM)&efd);
2084     ok(ret, "EnumFontFamilies error %u\n", GetLastError());
2085     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2086     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s\n",
2087           ansi_charset, symbol_charset, russian_charset,
2088           *font_name ? font_name : "<empty>");
2089     if (*font_name)
2090         ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
2091     else
2092         ok(!efd.total, "no fonts should be enumerated for empty font_name\n");
2093     for (i = 0; i < efd.total; i++)
2094     {
2095 /* FIXME: remove completely once Wine is fixed */
2096 if (efd.lf[i].lfCharSet != font_charset)
2097 {
2098 todo_wine
2099     ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2100 }
2101 else
2102         ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2103         ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2104            font_name, efd.lf[i].lfFaceName);
2105     }
2106
2107     memset(&lf, 0, sizeof(lf));
2108     lf.lfCharSet = ANSI_CHARSET;
2109     lstrcpy(lf.lfFaceName, font_name);
2110     efd.total = 0;
2111     SetLastError(0xdeadbeef);
2112     ret = EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2113     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2114     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2115     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s ANSI_CHARSET\n",
2116           ansi_charset, symbol_charset, russian_charset,
2117           *font_name ? font_name : "<empty>");
2118     if (font_charset == SYMBOL_CHARSET)
2119     {
2120         if (*font_name)
2121             ok(efd.total == 0, "no fonts should be enumerated: %s ANSI_CHARSET\n", font_name);
2122         else
2123             ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
2124     }
2125     else
2126     {
2127         ok(efd.total > 0, "no fonts enumerated: %s ANSI_CHARSET\n", font_name);
2128         for (i = 0; i < efd.total; i++)
2129         {
2130             ok(efd.lf[i].lfCharSet == ANSI_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2131             if (*font_name)
2132                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2133                    font_name, efd.lf[i].lfFaceName);
2134         }
2135     }
2136
2137     /* DEFAULT_CHARSET should enumerate all available charsets */
2138     memset(&lf, 0, sizeof(lf));
2139     lf.lfCharSet = DEFAULT_CHARSET;
2140     lstrcpy(lf.lfFaceName, font_name);
2141     efd.total = 0;
2142     SetLastError(0xdeadbeef);
2143     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2144     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2145     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2146     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s DEFAULT_CHARSET\n",
2147           ansi_charset, symbol_charset, russian_charset,
2148           *font_name ? font_name : "<empty>");
2149     ok(efd.total > 0, "no fonts enumerated: %s DEFAULT_CHARSET\n", font_name);
2150     for (i = 0; i < efd.total; i++)
2151     {
2152         if (*font_name)
2153             ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2154                font_name, efd.lf[i].lfFaceName);
2155     }
2156     if (*font_name)
2157     {
2158         switch (font_charset)
2159         {
2160         case ANSI_CHARSET:
2161             ok(ansi_charset > 0,
2162                "ANSI_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
2163             ok(!symbol_charset,
2164                "ANSI_CHARSET should NOT enumerate SYMBOL_CHARSET for %s\n", font_name);
2165             ok(russian_charset > 0,
2166                "ANSI_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
2167             break;
2168         case SYMBOL_CHARSET:
2169             ok(!ansi_charset,
2170                "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", font_name);
2171             ok(symbol_charset,
2172                "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
2173             ok(!russian_charset,
2174                "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", font_name);
2175             break;
2176         case DEFAULT_CHARSET:
2177             ok(ansi_charset > 0,
2178                "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
2179             ok(symbol_charset > 0,
2180                "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
2181             ok(russian_charset > 0,
2182                "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
2183             break;
2184         }
2185     }
2186     else
2187     {
2188         ok(ansi_charset > 0,
2189            "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2190         ok(symbol_charset > 0,
2191            "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2192         ok(russian_charset > 0,
2193            "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2194     }
2195
2196     memset(&lf, 0, sizeof(lf));
2197     lf.lfCharSet = SYMBOL_CHARSET;
2198     lstrcpy(lf.lfFaceName, font_name);
2199     efd.total = 0;
2200     SetLastError(0xdeadbeef);
2201     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2202     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2203     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2204     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s SYMBOL_CHARSET\n",
2205           ansi_charset, symbol_charset, russian_charset,
2206           *font_name ? font_name : "<empty>");
2207     if (*font_name && font_charset == ANSI_CHARSET)
2208         ok(efd.total == 0, "no fonts should be enumerated: %s SYMBOL_CHARSET\n", font_name);
2209     else
2210     {
2211         ok(efd.total > 0, "no fonts enumerated: %s SYMBOL_CHARSET\n", font_name);
2212         for (i = 0; i < efd.total; i++)
2213         {
2214             ok(efd.lf[i].lfCharSet == SYMBOL_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2215             if (*font_name)
2216                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2217                    font_name, efd.lf[i].lfFaceName);
2218         }
2219
2220         ok(!ansi_charset,
2221            "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2222         ok(symbol_charset > 0,
2223            "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2224         ok(!russian_charset,
2225            "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2226     }
2227
2228     ReleaseDC(0, hdc);
2229 }
2230
2231 static INT CALLBACK enum_font_data_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
2232 {
2233     struct enum_font_data *efd = (struct enum_font_data *)lParam;
2234
2235     if (type != TRUETYPE_FONTTYPE) return 1;
2236
2237     if (efd->total < MAX_ENUM_FONTS)
2238         efd->lf[efd->total++] = *lf;
2239     else
2240         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
2241
2242     return 1;
2243 }
2244
2245 static void test_EnumFontFamiliesEx_default_charset(void)
2246 {
2247     struct enum_font_data efd;
2248     LOGFONT gui_font, enum_font;
2249     DWORD ret;
2250     HDC hdc;
2251
2252     ret = GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(gui_font), &gui_font);
2253     ok(ret, "GetObject failed.\n");
2254     if (!ret)
2255         return;
2256
2257     efd.total = 0;
2258
2259     hdc = GetDC(0);
2260     memset(&enum_font, 0, sizeof(enum_font));
2261     lstrcpy(enum_font.lfFaceName, gui_font.lfFaceName);
2262     enum_font.lfCharSet = DEFAULT_CHARSET;
2263     EnumFontFamiliesEx(hdc, &enum_font, enum_font_data_proc, (LPARAM)&efd, 0);
2264     ReleaseDC(0, hdc);
2265
2266     if (efd.total == 0) {
2267         skip("'%s' is not found or not a TrueType font.\n", gui_font.lfFaceName);
2268         return;
2269     }
2270     trace("'%s' has %d charsets.\n", gui_font.lfFaceName, efd.total);
2271
2272     ok(efd.lf[0].lfCharSet == gui_font.lfCharSet,
2273        "(%s) got charset %d expected %d\n",
2274        efd.lf[0].lfFaceName, efd.lf[0].lfCharSet, gui_font.lfCharSet);
2275
2276     return;
2277 }
2278
2279 static void test_negative_width(HDC hdc, const LOGFONTA *lf)
2280 {
2281     HFONT hfont, hfont_prev;
2282     DWORD ret;
2283     GLYPHMETRICS gm1, gm2;
2284     LOGFONTA lf2 = *lf;
2285     WORD idx;
2286
2287     if(!pGetGlyphIndicesA)
2288         return;
2289
2290     /* negative widths are handled just as positive ones */
2291     lf2.lfWidth = -lf->lfWidth;
2292
2293     SetLastError(0xdeadbeef);
2294     hfont = CreateFontIndirectA(lf);
2295     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2296     check_font("original", lf, hfont);
2297
2298     hfont_prev = SelectObject(hdc, hfont);
2299
2300     ret = pGetGlyphIndicesA(hdc, "x", 1, &idx, GGI_MARK_NONEXISTING_GLYPHS);
2301     if (ret == GDI_ERROR || idx == 0xffff)
2302     {
2303         SelectObject(hdc, hfont_prev);
2304         DeleteObject(hfont);
2305         skip("Font %s doesn't contain 'x', skipping the test\n", lf->lfFaceName);
2306         return;
2307     }
2308
2309     /* filling with 0xaa causes false pass under WINEDEBUG=warn+heap */
2310     memset(&gm1, 0xab, sizeof(gm1));
2311     SetLastError(0xdeadbeef);
2312     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm1, 0, NULL, &mat);
2313     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
2314
2315     SelectObject(hdc, hfont_prev);
2316     DeleteObject(hfont);
2317
2318     SetLastError(0xdeadbeef);
2319     hfont = CreateFontIndirectA(&lf2);
2320     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2321     check_font("negative width", &lf2, hfont);
2322
2323     hfont_prev = SelectObject(hdc, hfont);
2324
2325     memset(&gm2, 0xbb, sizeof(gm2));
2326     SetLastError(0xdeadbeef);
2327     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm2, 0, NULL, &mat);
2328     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
2329
2330     SelectObject(hdc, hfont_prev);
2331     DeleteObject(hfont);
2332
2333     ok(gm1.gmBlackBoxX == gm2.gmBlackBoxX &&
2334        gm1.gmBlackBoxY == gm2.gmBlackBoxY &&
2335        gm1.gmptGlyphOrigin.x == gm2.gmptGlyphOrigin.x &&
2336        gm1.gmptGlyphOrigin.y == gm2.gmptGlyphOrigin.y &&
2337        gm1.gmCellIncX == gm2.gmCellIncX &&
2338        gm1.gmCellIncY == gm2.gmCellIncY,
2339        "gm1=%d,%d,%d,%d,%d,%d gm2=%d,%d,%d,%d,%d,%d\n",
2340        gm1.gmBlackBoxX, gm1.gmBlackBoxY, gm1.gmptGlyphOrigin.x,
2341        gm1.gmptGlyphOrigin.y, gm1.gmCellIncX, gm1.gmCellIncY,
2342        gm2.gmBlackBoxX, gm2.gmBlackBoxY, gm2.gmptGlyphOrigin.x,
2343        gm2.gmptGlyphOrigin.y, gm2.gmCellIncX, gm2.gmCellIncY);
2344 }
2345
2346 /* PANOSE is 10 bytes in size, need to pack the structure properly */
2347 #include "pshpack2.h"
2348 typedef struct
2349 {
2350     USHORT version;
2351     SHORT xAvgCharWidth;
2352     USHORT usWeightClass;
2353     USHORT usWidthClass;
2354     SHORT fsType;
2355     SHORT ySubscriptXSize;
2356     SHORT ySubscriptYSize;
2357     SHORT ySubscriptXOffset;
2358     SHORT ySubscriptYOffset;
2359     SHORT ySuperscriptXSize;
2360     SHORT ySuperscriptYSize;
2361     SHORT ySuperscriptXOffset;
2362     SHORT ySuperscriptYOffset;
2363     SHORT yStrikeoutSize;
2364     SHORT yStrikeoutPosition;
2365     SHORT sFamilyClass;
2366     PANOSE panose;
2367     ULONG ulUnicodeRange1;
2368     ULONG ulUnicodeRange2;
2369     ULONG ulUnicodeRange3;
2370     ULONG ulUnicodeRange4;
2371     CHAR achVendID[4];
2372     USHORT fsSelection;
2373     USHORT usFirstCharIndex;
2374     USHORT usLastCharIndex;
2375     /* According to the Apple spec, original version didn't have the below fields,
2376      * version numbers were taken from the OpenType spec.
2377      */
2378     /* version 0 (TrueType 1.5) */
2379     USHORT sTypoAscender;
2380     USHORT sTypoDescender;
2381     USHORT sTypoLineGap;
2382     USHORT usWinAscent;
2383     USHORT usWinDescent;
2384     /* version 1 (TrueType 1.66) */
2385     ULONG ulCodePageRange1;
2386     ULONG ulCodePageRange2;
2387     /* version 2 (OpenType 1.2) */
2388     SHORT sxHeight;
2389     SHORT sCapHeight;
2390     USHORT usDefaultChar;
2391     USHORT usBreakChar;
2392     USHORT usMaxContext;
2393 } TT_OS2_V2;
2394 #include "poppack.h"
2395
2396 #ifdef WORDS_BIGENDIAN
2397 #define GET_BE_WORD(x) (x)
2398 #define GET_BE_DWORD(x) (x)
2399 #else
2400 #define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
2401 #define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
2402 #endif
2403
2404 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
2405                     ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
2406                     ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
2407 #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
2408 #define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
2409 #define MS_NAME_TAG MS_MAKE_TAG('n','a','m','e')
2410
2411 typedef struct
2412 {
2413     USHORT version;
2414     USHORT num_tables;
2415 } cmap_header;
2416
2417 typedef struct
2418 {
2419     USHORT plat_id;
2420     USHORT enc_id;
2421     ULONG offset;
2422 } cmap_encoding_record;
2423
2424 typedef struct
2425 {
2426     USHORT format;
2427     USHORT length;
2428     USHORT language;
2429
2430     BYTE glyph_ids[256];
2431 } cmap_format_0;
2432
2433 typedef struct
2434 {
2435     USHORT format;
2436     USHORT length;
2437     USHORT language;
2438
2439     USHORT seg_countx2;
2440     USHORT search_range;
2441     USHORT entry_selector;
2442     USHORT range_shift;
2443
2444     USHORT end_count[1]; /* this is a variable-sized array of length seg_countx2 / 2 */
2445 /* Then follows:
2446     USHORT pad;
2447     USHORT start_count[seg_countx2 / 2];
2448     USHORT id_delta[seg_countx2 / 2];
2449     USHORT id_range_offset[seg_countx2 / 2];
2450     USHORT glyph_ids[];
2451 */
2452 } cmap_format_4;
2453
2454 typedef struct
2455 {
2456     USHORT end_count;
2457     USHORT start_count;
2458     USHORT id_delta;
2459     USHORT id_range_offset;
2460 } cmap_format_4_seg;
2461
2462 static void expect_ff(const TEXTMETRICA *tmA, const TT_OS2_V2 *os2, WORD family, const char *name)
2463 {
2464     ok((tmA->tmPitchAndFamily & 0xf0) == family ||
2465        broken(PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH),
2466        "%s: expected family %02x got %02x. panose %d-%d-%d-%d-...\n",
2467        name, family, tmA->tmPitchAndFamily, os2->panose.bFamilyType, os2->panose.bSerifStyle,
2468        os2->panose.bWeight, os2->panose.bProportion);
2469 }
2470
2471 static BOOL get_first_last_from_cmap0(void *ptr, DWORD *first, DWORD *last)
2472 {
2473     int i;
2474     cmap_format_0 *cmap = (cmap_format_0*)ptr;
2475
2476     *first = 256;
2477
2478     for(i = 0; i < 256; i++)
2479     {
2480         if(cmap->glyph_ids[i] == 0) continue;
2481         *last = i;
2482         if(*first == 256) *first = i;
2483     }
2484     if(*first == 256) return FALSE;
2485     return TRUE;
2486 }
2487
2488 static void get_seg4(cmap_format_4 *cmap, USHORT seg_num, cmap_format_4_seg *seg)
2489 {
2490     USHORT segs = GET_BE_WORD(cmap->seg_countx2) / 2;
2491     seg->end_count = GET_BE_WORD(cmap->end_count[seg_num]);
2492     seg->start_count = GET_BE_WORD(cmap->end_count[segs + 1 + seg_num]);
2493     seg->id_delta = GET_BE_WORD(cmap->end_count[2 * segs + 1 + seg_num]);
2494     seg->id_range_offset = GET_BE_WORD(cmap->end_count[3 * segs + 1 + seg_num]);
2495 }
2496
2497 static BOOL get_first_last_from_cmap4(void *ptr, DWORD *first, DWORD *last, DWORD limit)
2498 {
2499     int i;
2500     cmap_format_4 *cmap = (cmap_format_4*)ptr;
2501     USHORT seg_count = GET_BE_WORD(cmap->seg_countx2) / 2;
2502     USHORT const *glyph_ids = cmap->end_count + 4 * seg_count + 1;
2503
2504     *first = 0x10000;
2505
2506     for(i = 0; i < seg_count; i++)
2507     {
2508         DWORD code, index;
2509         cmap_format_4_seg seg;
2510
2511         get_seg4(cmap, i, &seg);
2512         for(code = seg.start_count; code <= seg.end_count; code++)
2513         {
2514             if(seg.id_range_offset == 0)
2515                 index = (seg.id_delta + code) & 0xffff;
2516             else
2517             {
2518                 index = seg.id_range_offset / 2
2519                     + code - seg.start_count
2520                     + i - seg_count;
2521
2522                 /* some fonts have broken last segment */
2523                 if ((char *)(glyph_ids + index + 1) < (char *)ptr + limit)
2524                     index = GET_BE_WORD(glyph_ids[index]);
2525                 else
2526                 {
2527                     trace("segment %04x/%04x index %04x points to nowhere\n",
2528                           seg.start_count, seg.end_count, index);
2529                     index = 0;
2530                 }
2531                 if(index) index += seg.id_delta;
2532             }
2533             if(*first == 0x10000)
2534                 *last = *first = code;
2535             else if(index)
2536                 *last = code;
2537         }
2538     }
2539
2540     if(*first == 0x10000) return FALSE;
2541     return TRUE;
2542 }
2543
2544 static void *get_cmap(cmap_header *header, USHORT plat_id, USHORT enc_id)
2545 {
2546     USHORT i;
2547     cmap_encoding_record *record = (cmap_encoding_record *)(header + 1);
2548
2549     for(i = 0; i < GET_BE_WORD(header->num_tables); i++)
2550     {
2551         if(GET_BE_WORD(record->plat_id) == plat_id && GET_BE_WORD(record->enc_id) == enc_id)
2552             return (BYTE *)header + GET_BE_DWORD(record->offset);
2553         record++;
2554     }
2555     return NULL;
2556 }
2557
2558 typedef enum
2559 {
2560     cmap_none,
2561     cmap_ms_unicode,
2562     cmap_ms_symbol
2563 } cmap_type;
2564
2565 static BOOL get_first_last_from_cmap(HDC hdc, DWORD *first, DWORD *last, cmap_type *cmap_type)
2566 {
2567     LONG size, ret;
2568     cmap_header *header;
2569     void *cmap;
2570     BOOL r = FALSE;
2571     WORD format;
2572
2573     size = GetFontData(hdc, MS_CMAP_TAG, 0, NULL, 0);
2574     ok(size != GDI_ERROR, "no cmap table found\n");
2575     if(size == GDI_ERROR) return FALSE;
2576
2577     header = HeapAlloc(GetProcessHeap(), 0, size);
2578     ret = GetFontData(hdc, MS_CMAP_TAG, 0, header, size);
2579     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2580     ok(GET_BE_WORD(header->version) == 0, "got cmap version %d\n", GET_BE_WORD(header->version));
2581
2582     cmap = get_cmap(header, 3, 1);
2583     if(cmap)
2584         *cmap_type = cmap_ms_unicode;
2585     else
2586     {
2587         cmap = get_cmap(header, 3, 0);
2588         if(cmap) *cmap_type = cmap_ms_symbol;
2589     }
2590     if(!cmap)
2591     {
2592         *cmap_type = cmap_none;
2593         goto end;
2594     }
2595
2596     format = GET_BE_WORD(*(WORD *)cmap);
2597     switch(format)
2598     {
2599     case 0:
2600         r = get_first_last_from_cmap0(cmap, first, last);
2601         break;
2602     case 4:
2603         r = get_first_last_from_cmap4(cmap, first, last, size);
2604         break;
2605     default:
2606         trace("unhandled cmap format %d\n", format);
2607         break;
2608     }
2609
2610 end:
2611     HeapFree(GetProcessHeap(), 0, header);
2612     return r;
2613 }
2614
2615 #define TT_PLATFORM_MICROSOFT 3
2616 #define TT_MS_ID_UNICODE_CS 1
2617 #define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409
2618 #define TT_NAME_ID_FULL_NAME 4
2619
2620 static BOOL get_ttf_nametable_entry(HDC hdc, WORD name_id, char *out_buf, SIZE_T out_size)
2621 {
2622     struct sfnt_name_header
2623     {
2624         USHORT format;
2625         USHORT number_of_record;
2626         USHORT storage_offset;
2627     } *header;
2628     struct sfnt_name
2629     {
2630         USHORT platform_id;
2631         USHORT encoding_id;
2632         USHORT language_id;
2633         USHORT name_id;
2634         USHORT length;
2635         USHORT offset;
2636     } *entry;
2637     BOOL r = FALSE;
2638     LONG size, offset, length;
2639     LONG c, ret;
2640     WCHAR *name;
2641     BYTE *data;
2642     USHORT i;
2643
2644     size = GetFontData(hdc, MS_NAME_TAG, 0, NULL, 0);
2645     ok(size != GDI_ERROR, "no name table found\n");
2646     if(size == GDI_ERROR) return FALSE;
2647
2648     data = HeapAlloc(GetProcessHeap(), 0, size);
2649     ret = GetFontData(hdc, MS_NAME_TAG, 0, data, size);
2650     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2651
2652     header = (void *)data;
2653     header->format = GET_BE_WORD(header->format);
2654     header->number_of_record = GET_BE_WORD(header->number_of_record);
2655     header->storage_offset = GET_BE_WORD(header->storage_offset);
2656     if (header->format != 0)
2657     {
2658         trace("got format %u\n", header->format);
2659         goto out;
2660     }
2661     if (header->number_of_record == 0 || sizeof(*header) + header->number_of_record * sizeof(*entry) > size)
2662     {
2663         trace("number records out of range: %d\n", header->number_of_record);
2664         goto out;
2665     }
2666     if (header->storage_offset >= size)
2667     {
2668         trace("storage_offset %u > size %u\n", header->storage_offset, size);
2669         goto out;
2670     }
2671
2672     entry = (void *)&header[1];
2673     for (i = 0; i < header->number_of_record; i++)
2674     {
2675         if (GET_BE_WORD(entry[i].platform_id) != TT_PLATFORM_MICROSOFT ||
2676             GET_BE_WORD(entry[i].encoding_id) != TT_MS_ID_UNICODE_CS ||
2677             GET_BE_WORD(entry[i].language_id) != TT_MS_LANGID_ENGLISH_UNITED_STATES ||
2678             GET_BE_WORD(entry[i].name_id) != name_id)
2679         {
2680             continue;
2681         }
2682
2683         offset = header->storage_offset + GET_BE_WORD(entry[i].offset);
2684         length = GET_BE_WORD(entry[i].length);
2685         if (offset + length > size)
2686         {
2687             trace("entry %d is out of range\n", i);
2688             break;
2689         }
2690         if (length >= out_size)
2691         {
2692             trace("buffer too small for entry %d\n", i);
2693             break;
2694         }
2695
2696         name = (WCHAR *)(data + offset);
2697         for (c = 0; c < length / 2; c++)
2698             out_buf[c] = GET_BE_WORD(name[c]);
2699         out_buf[c] = 0;
2700
2701         r = TRUE;
2702         break;
2703     }
2704
2705 out:
2706     HeapFree(GetProcessHeap(), 0, data);
2707     return r;
2708 }
2709
2710 static void test_text_metrics(const LOGFONTA *lf)
2711 {
2712     HDC hdc;
2713     HFONT hfont, hfont_old;
2714     TEXTMETRICA tmA;
2715     TT_OS2_V2 tt_os2;
2716     LONG size, ret;
2717     const char *font_name = lf->lfFaceName;
2718     DWORD cmap_first = 0, cmap_last = 0;
2719     cmap_type cmap_type;
2720     BOOL sys_lang_non_english;
2721
2722     sys_lang_non_english = PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH;
2723     hdc = GetDC(0);
2724
2725     SetLastError(0xdeadbeef);
2726     hfont = CreateFontIndirectA(lf);
2727     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2728
2729     hfont_old = SelectObject(hdc, hfont);
2730
2731     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
2732     if (size == GDI_ERROR)
2733     {
2734         trace("OS/2 chunk was not found\n");
2735         goto end_of_test;
2736     }
2737     if (size > sizeof(tt_os2))
2738     {
2739         trace("got too large OS/2 chunk of size %u\n", size);
2740         size = sizeof(tt_os2);
2741     }
2742
2743     memset(&tt_os2, 0, sizeof(tt_os2));
2744     ret = GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size);
2745     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2746
2747     SetLastError(0xdeadbeef);
2748     ret = GetTextMetricsA(hdc, &tmA);
2749     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
2750
2751     if(!get_first_last_from_cmap(hdc, &cmap_first, &cmap_last, &cmap_type))
2752     {
2753         skip("Unable to retrieve first and last glyphs from cmap\n");
2754     }
2755     else
2756     {
2757         USHORT expect_first_A, expect_last_A, expect_break_A, expect_default_A;
2758         USHORT expect_first_W, expect_last_W, expect_break_W, expect_default_W;
2759         UINT os2_first_char, os2_last_char, default_char, break_char;
2760         USHORT version;
2761         TEXTMETRICW tmW;
2762
2763         version = GET_BE_WORD(tt_os2.version);
2764
2765         os2_first_char = GET_BE_WORD(tt_os2.usFirstCharIndex);
2766         os2_last_char = GET_BE_WORD(tt_os2.usLastCharIndex);
2767         default_char = GET_BE_WORD(tt_os2.usDefaultChar);
2768         break_char = GET_BE_WORD(tt_os2.usBreakChar);
2769
2770         trace("font %s charset %u: %x-%x (%x-%x) default %x break %x OS/2 version %u vendor %4.4s\n",
2771               font_name, lf->lfCharSet, os2_first_char, os2_last_char, cmap_first, cmap_last,
2772               default_char, break_char, version, (LPCSTR)&tt_os2.achVendID);
2773
2774         if (cmap_type == cmap_ms_symbol || (cmap_first >= 0xf000 && cmap_first < 0xf100))
2775         {
2776             expect_first_W    = 0;
2777             switch(GetACP())
2778             {
2779             case 1257:  /* Baltic */
2780                 expect_last_W = 0xf8fd;
2781                 break;
2782             default:
2783                 expect_last_W = 0xf0ff;
2784             }
2785             expect_break_W    = 0x20;
2786             expect_default_W  = expect_break_W - 1;
2787             expect_first_A    = 0x1e;
2788             expect_last_A     = min(os2_last_char - os2_first_char + 0x20, 0xff);
2789         }
2790         else
2791         {
2792             expect_first_W    = cmap_first;
2793             expect_last_W     = min(cmap_last, os2_last_char);
2794             if(os2_first_char <= 1)
2795                 expect_break_W = os2_first_char + 2;
2796             else if(os2_first_char > 0xff)
2797                 expect_break_W = 0x20;
2798             else
2799                 expect_break_W = os2_first_char;
2800             expect_default_W  = expect_break_W - 1;
2801             expect_first_A    = expect_default_W - 1;
2802             expect_last_A     = min(expect_last_W, 0xff);
2803         }
2804         expect_break_A    = expect_break_W;
2805         expect_default_A  = expect_default_W;
2806
2807         /* Wine currently uses SYMBOL_CHARSET to identify whether the ANSI metrics need special handling */
2808         if(cmap_type != cmap_ms_symbol && tmA.tmCharSet == SYMBOL_CHARSET && expect_first_A != 0x1e)
2809             todo_wine ok(tmA.tmFirstChar == expect_first_A ||
2810                          tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2811                          "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2812         else
2813             ok(tmA.tmFirstChar == expect_first_A ||
2814                tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2815                "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2816         if (pGdiGetCodePage == NULL || ! IsDBCSLeadByteEx(pGdiGetCodePage(hdc), tmA.tmLastChar))
2817             ok(tmA.tmLastChar == expect_last_A ||
2818                tmA.tmLastChar == 0xff /* win9x */,
2819                "A: tmLastChar for %s got %02x expected %02x\n", font_name, tmA.tmLastChar, expect_last_A);
2820         else
2821            skip("tmLastChar is DBCS lead byte\n");
2822         ok(tmA.tmBreakChar == expect_break_A, "A: tmBreakChar for %s got %02x expected %02x\n",
2823            font_name, tmA.tmBreakChar, expect_break_A);
2824         ok(tmA.tmDefaultChar == expect_default_A || broken(sys_lang_non_english),
2825            "A: tmDefaultChar for %s got %02x expected %02x\n",
2826            font_name, tmA.tmDefaultChar, expect_default_A);
2827
2828
2829         SetLastError(0xdeadbeef);
2830         ret = GetTextMetricsW(hdc, &tmW);
2831         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
2832            "GetTextMetricsW error %u\n", GetLastError());
2833         if (ret)
2834         {
2835             /* Wine uses the os2 first char */
2836             if(cmap_first != os2_first_char && cmap_type != cmap_ms_symbol)
2837                 todo_wine ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2838                              font_name, tmW.tmFirstChar, expect_first_W);
2839             else
2840                 ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2841                    font_name, tmW.tmFirstChar, expect_first_W);
2842
2843             /* Wine uses the os2 last char */
2844             if(expect_last_W != os2_last_char && cmap_type != cmap_ms_symbol)
2845                 todo_wine ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2846                              font_name, tmW.tmLastChar, expect_last_W);
2847             else
2848                 ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2849                    font_name, tmW.tmLastChar, expect_last_W);
2850             ok(tmW.tmBreakChar == expect_break_W, "W: tmBreakChar for %s got %02x expected %02x\n",
2851                font_name, tmW.tmBreakChar, expect_break_W);
2852             ok(tmW.tmDefaultChar == expect_default_W || broken(sys_lang_non_english),
2853                "W: tmDefaultChar for %s got %02x expected %02x\n",
2854                font_name, tmW.tmDefaultChar, expect_default_W);
2855
2856             /* Test the aspect ratio while we have tmW */
2857             ret = GetDeviceCaps(hdc, LOGPIXELSX);
2858             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectX %u != %u\n",
2859                tmW.tmDigitizedAspectX, ret);
2860             ret = GetDeviceCaps(hdc, LOGPIXELSY);
2861             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectY %u != %u\n",
2862                tmW.tmDigitizedAspectX, ret);
2863         }
2864     }
2865
2866     /* test FF_ values */
2867     switch(tt_os2.panose.bFamilyType)
2868     {
2869     case PAN_ANY:
2870     case PAN_NO_FIT:
2871     case PAN_FAMILY_TEXT_DISPLAY:
2872     case PAN_FAMILY_PICTORIAL:
2873     default:
2874         if((tmA.tmPitchAndFamily & 1) == 0 || /* fixed */
2875            tt_os2.panose.bProportion == PAN_PROP_MONOSPACED)
2876         {
2877             expect_ff(&tmA, &tt_os2, FF_MODERN, font_name);
2878             break;
2879         }
2880         switch(tt_os2.panose.bSerifStyle)
2881         {
2882         case PAN_ANY:
2883         case PAN_NO_FIT:
2884         default:
2885             expect_ff(&tmA, &tt_os2, FF_DONTCARE, font_name);
2886             break;
2887
2888         case PAN_SERIF_COVE:
2889         case PAN_SERIF_OBTUSE_COVE:
2890         case PAN_SERIF_SQUARE_COVE:
2891         case PAN_SERIF_OBTUSE_SQUARE_COVE:
2892         case PAN_SERIF_SQUARE:
2893         case PAN_SERIF_THIN:
2894         case PAN_SERIF_BONE:
2895         case PAN_SERIF_EXAGGERATED:
2896         case PAN_SERIF_TRIANGLE:
2897             expect_ff(&tmA, &tt_os2, FF_ROMAN, font_name);
2898             break;
2899
2900         case PAN_SERIF_NORMAL_SANS:
2901         case PAN_SERIF_OBTUSE_SANS:
2902         case PAN_SERIF_PERP_SANS:
2903         case PAN_SERIF_FLARED:
2904         case PAN_SERIF_ROUNDED:
2905             expect_ff(&tmA, &tt_os2, FF_SWISS, font_name);
2906             break;
2907         }
2908         break;
2909
2910     case PAN_FAMILY_SCRIPT:
2911         expect_ff(&tmA, &tt_os2, FF_SCRIPT, font_name);
2912         break;
2913
2914     case PAN_FAMILY_DECORATIVE:
2915         expect_ff(&tmA, &tt_os2, FF_DECORATIVE, font_name);
2916         break;
2917     }
2918
2919     test_negative_width(hdc, lf);
2920
2921 end_of_test:
2922     SelectObject(hdc, hfont_old);
2923     DeleteObject(hfont);
2924
2925     ReleaseDC(0, hdc);
2926 }
2927
2928 static INT CALLBACK enum_truetype_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
2929 {
2930     INT *enumed = (INT *)lParam;
2931
2932     if (type == TRUETYPE_FONTTYPE)
2933     {
2934         (*enumed)++;
2935         test_text_metrics(lf);
2936     }
2937     return 1;
2938 }
2939
2940 static void test_GetTextMetrics(void)
2941 {
2942     LOGFONTA lf;
2943     HDC hdc;
2944     INT enumed;
2945
2946     /* Report only once */
2947     if(!pGetGlyphIndicesA)
2948         win_skip("GetGlyphIndicesA is unavailable, negative width will not be checked\n");
2949
2950     hdc = GetDC(0);
2951
2952     memset(&lf, 0, sizeof(lf));
2953     lf.lfCharSet = DEFAULT_CHARSET;
2954     enumed = 0;
2955     EnumFontFamiliesExA(hdc, &lf, enum_truetype_font_proc, (LPARAM)&enumed, 0);
2956     trace("Tested metrics of %d truetype fonts\n", enumed);
2957
2958     ReleaseDC(0, hdc);
2959 }
2960
2961 static void test_nonexistent_font(void)
2962 {
2963     static const struct
2964     {
2965         const char *name;
2966         int charset;
2967     } font_subst[] =
2968     {
2969         { "Times New Roman Baltic", 186 },
2970         { "Times New Roman CE", 238 },
2971         { "Times New Roman CYR", 204 },
2972         { "Times New Roman Greek", 161 },
2973         { "Times New Roman TUR", 162 }
2974     };
2975     LOGFONTA lf;
2976     HDC hdc;
2977     HFONT hfont;
2978     CHARSETINFO csi;
2979     INT cs, expected_cs, i;
2980     char buf[LF_FACESIZE];
2981
2982     if (!is_truetype_font_installed("Arial") ||
2983         !is_truetype_font_installed("Times New Roman"))
2984     {
2985         skip("Arial or Times New Roman not installed\n");
2986         return;
2987     }
2988
2989     expected_cs = GetACP();
2990     if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
2991     {
2992         skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
2993         return;
2994     }
2995     expected_cs = csi.ciCharset;
2996     trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
2997
2998     hdc = GetDC(0);
2999
3000     memset(&lf, 0, sizeof(lf));
3001     lf.lfHeight = 100;
3002     lf.lfWeight = FW_REGULAR;
3003     lf.lfCharSet = ANSI_CHARSET;
3004     lf.lfPitchAndFamily = FF_SWISS;
3005     strcpy(lf.lfFaceName, "Nonexistent font");
3006     hfont = CreateFontIndirectA(&lf);
3007     hfont = SelectObject(hdc, hfont);
3008     GetTextFaceA(hdc, sizeof(buf), buf);
3009     ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
3010     cs = GetTextCharset(hdc);
3011     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
3012     DeleteObject(SelectObject(hdc, hfont));
3013
3014     memset(&lf, 0, sizeof(lf));
3015     lf.lfHeight = -13;
3016     lf.lfWeight = FW_DONTCARE;
3017     strcpy(lf.lfFaceName, "Nonexistent font");
3018     hfont = CreateFontIndirectA(&lf);
3019     hfont = SelectObject(hdc, hfont);
3020     GetTextFaceA(hdc, sizeof(buf), buf);
3021 todo_wine /* Wine uses Arial for all substitutions */
3022     ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ ||
3023        !lstrcmpiA(buf, "MS Serif") || /* Win9x */
3024        !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
3025        "Got %s\n", buf);
3026     cs = GetTextCharset(hdc);
3027     ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d\n", expected_cs, cs);
3028     DeleteObject(SelectObject(hdc, hfont));
3029
3030     memset(&lf, 0, sizeof(lf));
3031     lf.lfHeight = -13;
3032     lf.lfWeight = FW_REGULAR;
3033     strcpy(lf.lfFaceName, "Nonexistent font");
3034     hfont = CreateFontIndirectA(&lf);
3035     hfont = SelectObject(hdc, hfont);
3036     GetTextFaceA(hdc, sizeof(buf), buf);
3037     ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
3038        !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "Got %s\n", buf);
3039     cs = GetTextCharset(hdc);
3040     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
3041     DeleteObject(SelectObject(hdc, hfont));
3042
3043     memset(&lf, 0, sizeof(lf));
3044     lf.lfHeight = -13;
3045     lf.lfWeight = FW_DONTCARE;
3046     strcpy(lf.lfFaceName, "Times New Roman");
3047     hfont = CreateFontIndirectA(&lf);
3048     hfont = SelectObject(hdc, hfont);
3049     GetTextFaceA(hdc, sizeof(buf), buf);
3050     ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf);
3051     cs = GetTextCharset(hdc);
3052     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
3053     DeleteObject(SelectObject(hdc, hfont));
3054
3055     for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++)
3056     {
3057         memset(&lf, 0, sizeof(lf));
3058         lf.lfHeight = -13;
3059         lf.lfWeight = FW_REGULAR;
3060         strcpy(lf.lfFaceName, font_subst[i].name);
3061         hfont = CreateFontIndirectA(&lf);
3062         hfont = SelectObject(hdc, hfont);
3063         cs = GetTextCharset(hdc);
3064         if (font_subst[i].charset == expected_cs)
3065         {
3066             ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
3067             GetTextFaceA(hdc, sizeof(buf), buf);
3068             ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf);
3069         }
3070         else
3071         {
3072             ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d for font %s\n", cs, font_subst[i].name);
3073             GetTextFaceA(hdc, sizeof(buf), buf);
3074             ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
3075                !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got %s for font %s\n", buf, font_subst[i].name);
3076         }
3077         DeleteObject(SelectObject(hdc, hfont));
3078
3079         memset(&lf, 0, sizeof(lf));
3080         lf.lfHeight = -13;
3081         lf.lfWeight = FW_DONTCARE;
3082         strcpy(lf.lfFaceName, font_subst[i].name);
3083         hfont = CreateFontIndirectA(&lf);
3084         hfont = SelectObject(hdc, hfont);
3085         GetTextFaceA(hdc, sizeof(buf), buf);
3086         ok(!lstrcmpiA(buf, "Arial") /* Wine */ ||
3087            !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ ||
3088            !lstrcmpiA(buf, "MS Serif") /* Win9x */ ||
3089            !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
3090            "got %s for font %s\n", buf, font_subst[i].name);
3091         cs = GetTextCharset(hdc);
3092         ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
3093         DeleteObject(SelectObject(hdc, hfont));
3094     }
3095
3096     ReleaseDC(0, hdc);
3097 }
3098
3099 static void test_GdiRealizationInfo(void)
3100 {
3101     HDC hdc;
3102     DWORD info[4];
3103     BOOL r;
3104     HFONT hfont, hfont_old;
3105     LOGFONTA lf;
3106
3107     if(!pGdiRealizationInfo)
3108     {
3109         win_skip("GdiRealizationInfo not available\n");
3110         return;
3111     }
3112
3113     hdc = GetDC(0);
3114
3115     memset(info, 0xcc, sizeof(info));
3116     r = pGdiRealizationInfo(hdc, info);
3117     ok(r != 0, "ret 0\n");
3118     ok((info[0] & 0xf) == 1, "info[0] = %x for the system font\n", info[0]);
3119     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
3120
3121     if (!is_truetype_font_installed("Arial"))
3122     {
3123         skip("skipping GdiRealizationInfo with truetype font\n");
3124         goto end;
3125     }
3126
3127     memset(&lf, 0, sizeof(lf));
3128     strcpy(lf.lfFaceName, "Arial");
3129     lf.lfHeight = 20;
3130     lf.lfWeight = FW_NORMAL;
3131     hfont = CreateFontIndirectA(&lf);
3132     hfont_old = SelectObject(hdc, hfont);
3133
3134     memset(info, 0xcc, sizeof(info));
3135     r = pGdiRealizationInfo(hdc, info);
3136     ok(r != 0, "ret 0\n");
3137     ok((info[0] & 0xf) == 3, "info[0] = %x for arial\n", info[0]);
3138     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
3139
3140     DeleteObject(SelectObject(hdc, hfont_old));
3141
3142  end:
3143     ReleaseDC(0, hdc);
3144 }
3145
3146 /* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include
3147    the nul in the count of characters copied when the face name buffer is not
3148    NULL, whereas it does if the buffer is NULL.  Further, the Unicode version
3149    always includes it.  */
3150 static void test_GetTextFace(void)
3151 {
3152     static const char faceA[] = "Tahoma";
3153     static const WCHAR faceW[] = {'T','a','h','o','m','a', 0};
3154     LOGFONTA fA = {0};
3155     LOGFONTW fW = {0};
3156     char bufA[LF_FACESIZE];
3157     WCHAR bufW[LF_FACESIZE];
3158     HFONT f, g;
3159     HDC dc;
3160     int n;
3161
3162     if(!is_font_installed("Tahoma"))
3163     {
3164         skip("Tahoma is not installed so skipping this test\n");
3165         return;
3166     }
3167
3168     /* 'A' case.  */
3169     memcpy(fA.lfFaceName, faceA, sizeof faceA);
3170     f = CreateFontIndirectA(&fA);
3171     ok(f != NULL, "CreateFontIndirectA failed\n");
3172
3173     dc = GetDC(NULL);
3174     g = SelectObject(dc, f);
3175     n = GetTextFaceA(dc, sizeof bufA, bufA);
3176     ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n);
3177     ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n");
3178
3179     /* Play with the count arg.  */
3180     bufA[0] = 'x';
3181     n = GetTextFaceA(dc, 0, bufA);
3182     ok(n == 0, "GetTextFaceA returned %d\n", n);
3183     ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]);
3184
3185     bufA[0] = 'x';
3186     n = GetTextFaceA(dc, 1, bufA);
3187     ok(n == 0, "GetTextFaceA returned %d\n", n);
3188     ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]);
3189
3190     bufA[0] = 'x'; bufA[1] = 'y';
3191     n = GetTextFaceA(dc, 2, bufA);
3192     ok(n == 1, "GetTextFaceA returned %d\n", n);
3193     ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n");
3194
3195     n = GetTextFaceA(dc, 0, NULL);
3196     ok(n == sizeof faceA ||
3197        broken(n == 0), /* win98, winMe */
3198        "GetTextFaceA returned %d\n", n);
3199
3200     DeleteObject(SelectObject(dc, g));
3201     ReleaseDC(NULL, dc);
3202
3203     /* 'W' case.  */
3204     memcpy(fW.lfFaceName, faceW, sizeof faceW);
3205     SetLastError(0xdeadbeef);
3206     f = CreateFontIndirectW(&fW);
3207     if (!f && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
3208     {
3209         win_skip("CreateFontIndirectW is not implemented\n");
3210         return;
3211     }
3212     ok(f != NULL, "CreateFontIndirectW failed\n");
3213
3214     dc = GetDC(NULL);
3215     g = SelectObject(dc, f);
3216     n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW);
3217     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
3218     ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
3219
3220     /* Play with the count arg.  */
3221     bufW[0] = 'x';
3222     n = GetTextFaceW(dc, 0, bufW);
3223     ok(n == 0, "GetTextFaceW returned %d\n", n);
3224     ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]);
3225
3226     bufW[0] = 'x';
3227     n = GetTextFaceW(dc, 1, bufW);
3228     ok(n == 1, "GetTextFaceW returned %d\n", n);
3229     ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]);
3230
3231     bufW[0] = 'x'; bufW[1] = 'y';
3232     n = GetTextFaceW(dc, 2, bufW);
3233     ok(n == 2, "GetTextFaceW returned %d\n", n);
3234     ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n");
3235
3236     n = GetTextFaceW(dc, 0, NULL);
3237     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
3238
3239     DeleteObject(SelectObject(dc, g));
3240     ReleaseDC(NULL, dc);
3241 }
3242
3243 static void test_orientation(void)
3244 {
3245     static const char test_str[11] = "Test String";
3246     HDC hdc;
3247     LOGFONTA lf;
3248     HFONT hfont, old_hfont;
3249     SIZE size;
3250
3251     if (!is_truetype_font_installed("Arial"))
3252     {
3253         skip("Arial is not installed\n");
3254         return;
3255     }
3256
3257     hdc = CreateCompatibleDC(0);
3258     memset(&lf, 0, sizeof(lf));
3259     lstrcpyA(lf.lfFaceName, "Arial");
3260     lf.lfHeight = 72;
3261     lf.lfOrientation = lf.lfEscapement = 900;
3262     hfont = create_font("orientation", &lf);
3263     old_hfont = SelectObject(hdc, hfont);
3264     ok(GetTextExtentExPointA(hdc, test_str, sizeof(test_str), 32767, NULL, NULL, &size), "GetTextExtentExPointA failed\n");
3265     ok(near_match(311, size.cx), "cx should be about 311, got %d\n", size.cx);
3266     ok(near_match(75, size.cy), "cy should be about 75, got %d\n", size.cy);
3267     SelectObject(hdc, old_hfont);
3268     DeleteObject(hfont);
3269     DeleteDC(hdc);
3270 }
3271
3272 static void test_oemcharset(void)
3273 {
3274     HDC hdc;
3275     LOGFONTA lf, clf;
3276     HFONT hfont, old_hfont;
3277     int charset;
3278
3279     hdc = CreateCompatibleDC(0);
3280     ZeroMemory(&lf, sizeof(lf));
3281     lf.lfHeight = 12;
3282     lf.lfCharSet = OEM_CHARSET;
3283     lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
3284     lstrcpyA(lf.lfFaceName, "Terminal");
3285     hfont = CreateFontIndirectA(&lf);
3286     old_hfont = SelectObject(hdc, hfont);
3287     charset = GetTextCharset(hdc);
3288 todo_wine
3289     ok(charset == OEM_CHARSET, "expected %d charset, got %d\n", OEM_CHARSET, charset);
3290     hfont = SelectObject(hdc, old_hfont);
3291     GetObjectA(hfont, sizeof(clf), &clf);
3292     ok(!lstrcmpA(clf.lfFaceName, lf.lfFaceName), "expected %s face name, got %s\n", lf.lfFaceName, clf.lfFaceName);
3293     ok(clf.lfPitchAndFamily == lf.lfPitchAndFamily, "expected %x family, got %x\n", lf.lfPitchAndFamily, clf.lfPitchAndFamily);
3294     ok(clf.lfCharSet == lf.lfCharSet, "expected %d charset, got %d\n", lf.lfCharSet, clf.lfCharSet);
3295     ok(clf.lfHeight == lf.lfHeight, "expected %d height, got %d\n", lf.lfHeight, clf.lfHeight);
3296     DeleteObject(hfont);
3297     DeleteDC(hdc);
3298 }
3299
3300 static void test_GetGlyphOutline(void)
3301 {
3302     HDC hdc;
3303     GLYPHMETRICS gm, gm2;
3304     LOGFONTA lf;
3305     HFONT hfont, old_hfont;
3306     INT ret, ret2;
3307     static const struct
3308     {
3309         UINT cs;
3310         UINT a;
3311         UINT w;
3312     } c[] =
3313     {
3314         {ANSI_CHARSET, 0x30, 0x30},
3315         {SHIFTJIS_CHARSET, 0x82a0, 0x3042},
3316         {HANGEUL_CHARSET, 0x8141, 0xac02},
3317         {JOHAB_CHARSET, 0x8446, 0x3135},
3318         {GB2312_CHARSET, 0x8141, 0x4e04},
3319         {CHINESEBIG5_CHARSET, 0xa142, 0x3001}
3320     };
3321     UINT i;
3322
3323     if (!is_truetype_font_installed("Tahoma"))
3324     {
3325         skip("Tahoma is not installed\n");
3326         return;
3327     }
3328
3329     hdc = CreateCompatibleDC(0);
3330     memset(&lf, 0, sizeof(lf));
3331     lf.lfHeight = 72;
3332     lstrcpyA(lf.lfFaceName, "Tahoma");
3333     SetLastError(0xdeadbeef);
3334     hfont = CreateFontIndirectA(&lf);
3335     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
3336     old_hfont = SelectObject(hdc, hfont);
3337
3338     memset(&gm, 0, sizeof(gm));
3339     SetLastError(0xdeadbeef);
3340     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3341     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
3342
3343     memset(&gm, 0, sizeof(gm));
3344     SetLastError(0xdeadbeef);
3345     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
3346     ok(ret == GDI_ERROR, "GetGlyphOutlineA should fail\n");
3347     ok(GetLastError() == 0xdeadbeef ||
3348        GetLastError() == ERROR_INVALID_PARAMETER, /* win98, winMe */
3349        "expected 0xdeadbeef, got %u\n", GetLastError());
3350
3351     memset(&gm, 0, sizeof(gm));
3352     SetLastError(0xdeadbeef);
3353     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3354     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3355         ok(ret != GDI_ERROR, "GetGlyphOutlineW error %u\n", GetLastError());
3356
3357     memset(&gm, 0, sizeof(gm));
3358     SetLastError(0xdeadbeef);
3359     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
3360     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3361     {
3362        ok(ret == GDI_ERROR, "GetGlyphOutlineW should fail\n");
3363        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
3364     }
3365
3366     /* test for needed buffer size request on space char */
3367     memset(&gm, 0, sizeof(gm));
3368     SetLastError(0xdeadbeef);
3369     ret = GetGlyphOutlineW(hdc, ' ', GGO_NATIVE, &gm, 0, NULL, &mat);
3370     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3371         ok(ret == 0, "GetGlyphOutlineW should return 0 buffer size for space char\n");
3372
3373     /* requesting buffer size for space char + error */
3374     memset(&gm, 0, sizeof(gm));
3375     SetLastError(0xdeadbeef);
3376     ret = GetGlyphOutlineW(0, ' ', GGO_NATIVE, &gm, 0, NULL, NULL);
3377     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3378     {
3379        ok(ret == GDI_ERROR, "GetGlyphOutlineW should return GDI_ERROR\n");
3380        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
3381     }
3382
3383     SelectObject(hdc, old_hfont);
3384     DeleteObject(hfont);
3385
3386     for (i = 0; i < sizeof c / sizeof c[0]; ++i)
3387     {
3388         lf.lfFaceName[0] = '\0';
3389         lf.lfCharSet = c[i].cs;
3390         lf.lfPitchAndFamily = 0;
3391         if (EnumFontFamiliesEx(hdc, &lf, create_font_proc, (LPARAM)&hfont, 0))
3392         {
3393             skip("TrueType font for charset %u is not installed\n", c[i].cs);
3394             continue;
3395         }
3396
3397         old_hfont = SelectObject(hdc, hfont);
3398
3399         /* expected to ignore superfluous bytes (sigle-byte character) */
3400         ret = GetGlyphOutlineA(hdc, 0x8041, GGO_BITMAP, &gm, 0, NULL, &mat);
3401         ret2 = GetGlyphOutlineA(hdc, 0x41, GGO_BITMAP, &gm2, 0, NULL, &mat);
3402         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
3403
3404         ret = GetGlyphOutlineA(hdc, 0xcc8041, GGO_BITMAP, &gm, 0, NULL, &mat);
3405         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
3406            "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
3407
3408         /* expected to ignore superfluous bytes (double-byte character) */
3409         ret = GetGlyphOutlineA(hdc, c[i].a, GGO_BITMAP, &gm, 0, NULL, &mat);
3410         ret2 = GetGlyphOutlineA(hdc, c[i].a | 0xdead0000, GGO_BITMAP, &gm2, 0, NULL, &mat);
3411         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
3412            "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
3413
3414         /* expected to match wide-char version results */
3415         ret2 = GetGlyphOutlineW(hdc, c[i].w, GGO_BITMAP, &gm2, 0, NULL, &mat);
3416         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
3417
3418         hfont = SelectObject(hdc, old_hfont);
3419         DeleteObject(hfont);
3420     }
3421
3422     DeleteDC(hdc);
3423 }
3424
3425 /* bug #9995: there is a limit to the character width that can be specified */
3426 static void test_GetTextMetrics2(const char *fontname, int font_height)
3427 {
3428     HFONT of, hf;
3429     HDC hdc;
3430     TEXTMETRICA tm;
3431     BOOL ret;
3432     int ave_width, height, width, ratio, scale;
3433
3434     if (!is_truetype_font_installed( fontname)) {
3435         skip("%s is not installed\n", fontname);
3436         return;
3437     }
3438     hdc = CreateCompatibleDC(0);
3439     ok( hdc != NULL, "CreateCompatibleDC failed\n");
3440     /* select width = 0 */
3441     hf = CreateFontA(font_height, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3442             DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3443             DEFAULT_QUALITY, VARIABLE_PITCH,
3444             fontname);
3445     ok( hf != NULL, "CreateFontA(%s, %d) failed\n", fontname, font_height);
3446     of = SelectObject( hdc, hf);
3447     ret = GetTextMetricsA( hdc, &tm);
3448     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
3449     height = tm.tmHeight;
3450     ave_width = tm.tmAveCharWidth;
3451     SelectObject( hdc, of);
3452     DeleteObject( hf);
3453
3454     trace("height %d, ave width %d\n", height, ave_width);
3455
3456     for (width = ave_width * 2; /* nothing*/; width += ave_width)
3457     {
3458         hf = CreateFont(height, width, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3459                         DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3460                         DEFAULT_QUALITY, VARIABLE_PITCH, fontname);
3461         ok(hf != 0, "CreateFont failed\n");
3462         of = SelectObject(hdc, hf);
3463         ret = GetTextMetrics(hdc, &tm);
3464         ok(ret, "GetTextMetrics error %u\n", GetLastError());
3465         SelectObject(hdc, of);
3466         DeleteObject(hf);
3467
3468         if (match_off_by_1(tm.tmAveCharWidth, ave_width) || width / height > 200)
3469             break;
3470     }
3471
3472     DeleteDC(hdc);
3473
3474     ratio = width / height;
3475     scale = width / ave_width;
3476
3477     trace("max width/height ratio (%d / %d) %d, max width scale (%d / %d) %d\n",
3478           width, height, ratio, width, ave_width, scale);
3479
3480     ok(ratio >= 90 && ratio <= 110, "expected width/height ratio 90-110, got %d\n", ratio);
3481 }
3482
3483 static void test_CreateFontIndirect(void)
3484 {
3485     LOGFONTA lf, getobj_lf;
3486     int ret, i;
3487     HFONT hfont;
3488     char TestName[][16] = {"Arial", "Arial Bold", "Arial Italic", "Arial Baltic"};
3489
3490     memset(&lf, 0, sizeof(lf));
3491     lf.lfCharSet = ANSI_CHARSET;
3492     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
3493     lf.lfHeight = 16;
3494     lf.lfWidth = 16;
3495     lf.lfQuality = DEFAULT_QUALITY;
3496     lf.lfItalic = FALSE;
3497     lf.lfWeight = FW_DONTCARE;
3498
3499     for (i = 0; i < sizeof(TestName)/sizeof(TestName[0]); i++)
3500     {
3501         lstrcpyA(lf.lfFaceName, TestName[i]);
3502         hfont = CreateFontIndirectA(&lf);
3503         ok(hfont != 0, "CreateFontIndirectA failed\n");
3504         SetLastError(0xdeadbeef);
3505         ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf);
3506         ok(ret, "GetObject failed: %d\n", GetLastError());
3507         ok(lf.lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf.lfItalic, getobj_lf.lfItalic);
3508         ok(lf.lfWeight == getobj_lf.lfWeight ||
3509            broken((SHORT)lf.lfWeight == getobj_lf.lfWeight), /* win9x */
3510            "lfWeight: expect %08x got %08x\n", lf.lfWeight, getobj_lf.lfWeight);
3511         ok(!lstrcmpA(lf.lfFaceName, getobj_lf.lfFaceName) ||
3512            broken(!memcmp(lf.lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
3513            "font names don't match: %s != %s\n", lf.lfFaceName, getobj_lf.lfFaceName);
3514         DeleteObject(hfont);
3515     }
3516 }
3517
3518 static void test_CreateFontIndirectEx(void)
3519 {
3520     ENUMLOGFONTEXDVA lfex;
3521     HFONT hfont;
3522
3523     if (!pCreateFontIndirectExA)
3524     {
3525         win_skip("CreateFontIndirectExA is not available\n");
3526         return;
3527     }
3528
3529     if (!is_truetype_font_installed("Arial"))
3530     {
3531         skip("Arial is not installed\n");
3532         return;
3533     }
3534
3535     SetLastError(0xdeadbeef);
3536     hfont = pCreateFontIndirectExA(NULL);
3537     ok(hfont == NULL, "got %p\n", hfont);
3538     ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
3539
3540     memset(&lfex, 0, sizeof(lfex));
3541     lstrcpyA(lfex.elfEnumLogfontEx.elfLogFont.lfFaceName, "Arial");
3542     hfont = pCreateFontIndirectExA(&lfex);
3543     ok(hfont != 0, "CreateFontIndirectEx failed\n");
3544     if (hfont)
3545         check_font("Arial", &lfex.elfEnumLogfontEx.elfLogFont, hfont);
3546     DeleteObject(hfont);
3547 }
3548
3549 static void free_font(void *font)
3550 {
3551     UnmapViewOfFile(font);
3552 }
3553
3554 static void *load_font(const char *font_name, DWORD *font_size)
3555 {
3556     char file_name[MAX_PATH];
3557     HANDLE file, mapping;
3558     void *font;
3559
3560     if (!GetWindowsDirectory(file_name, sizeof(file_name))) return NULL;
3561     strcat(file_name, "\\fonts\\");
3562     strcat(file_name, font_name);
3563
3564     file = CreateFile(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
3565     if (file == INVALID_HANDLE_VALUE) return NULL;
3566
3567     *font_size = GetFileSize(file, NULL);
3568
3569     mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
3570     if (!mapping)
3571     {
3572         CloseHandle(file);
3573         return NULL;
3574     }
3575
3576     font = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
3577
3578     CloseHandle(file);
3579     CloseHandle(mapping);
3580     return font;
3581 }
3582
3583 static void test_AddFontMemResource(void)
3584 {
3585     void *font;
3586     DWORD font_size, num_fonts;
3587     HANDLE ret;
3588     BOOL bRet;
3589
3590     if (!pAddFontMemResourceEx || !pRemoveFontMemResourceEx)
3591     {
3592         win_skip("AddFontMemResourceEx is not available on this platform\n");
3593         return;
3594     }
3595
3596     font = load_font("sserife.fon", &font_size);
3597     if (!font)
3598     {
3599         skip("Unable to locate and load font sserife.fon\n");
3600         return;
3601     }
3602
3603     SetLastError(0xdeadbeef);
3604     ret = pAddFontMemResourceEx(NULL, 0, NULL, NULL);
3605     ok(!ret, "AddFontMemResourceEx should fail\n");
3606     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3607        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3608        GetLastError());
3609
3610     SetLastError(0xdeadbeef);
3611     ret = pAddFontMemResourceEx(NULL, 10, NULL, NULL);
3612     ok(!ret, "AddFontMemResourceEx should fail\n");
3613     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3614        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3615        GetLastError());
3616
3617     SetLastError(0xdeadbeef);
3618     ret = pAddFontMemResourceEx(NULL, 0, NULL, &num_fonts);
3619     ok(!ret, "AddFontMemResourceEx should fail\n");
3620     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3621        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3622        GetLastError());
3623
3624     SetLastError(0xdeadbeef);
3625     ret = pAddFontMemResourceEx(NULL, 10, NULL, &num_fonts);
3626     ok(!ret, "AddFontMemResourceEx should fail\n");
3627     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3628        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3629        GetLastError());
3630
3631     SetLastError(0xdeadbeef);
3632     ret = pAddFontMemResourceEx(font, 0, NULL, NULL);
3633     ok(!ret, "AddFontMemResourceEx should fail\n");
3634     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3635        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3636        GetLastError());
3637
3638     SetLastError(0xdeadbeef);
3639     ret = pAddFontMemResourceEx(font, 10, NULL, NULL);
3640     ok(!ret, "AddFontMemResourceEx should fail\n");
3641     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3642        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3643        GetLastError());
3644
3645     num_fonts = 0xdeadbeef;
3646     SetLastError(0xdeadbeef);
3647     ret = pAddFontMemResourceEx(font, 0, NULL, &num_fonts);
3648     ok(!ret, "AddFontMemResourceEx should fail\n");
3649     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3650        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3651        GetLastError());
3652     ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
3653
3654     if (0) /* hangs under windows 2000 */
3655     {
3656         num_fonts = 0xdeadbeef;
3657         SetLastError(0xdeadbeef);
3658         ret = pAddFontMemResourceEx(font, 10, NULL, &num_fonts);
3659         ok(!ret, "AddFontMemResourceEx should fail\n");
3660         ok(GetLastError() == 0xdeadbeef,
3661            "Expected GetLastError() to return 0xdeadbeef, got %u\n",
3662            GetLastError());
3663         ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
3664     }
3665
3666     num_fonts = 0xdeadbeef;
3667     SetLastError(0xdeadbeef);
3668     ret = pAddFontMemResourceEx(font, font_size, NULL, &num_fonts);
3669     ok(ret != 0, "AddFontMemResourceEx error %d\n", GetLastError());
3670     ok(num_fonts != 0xdeadbeef, "number of loaded fonts should not be 0xdeadbeef\n");
3671     ok(num_fonts != 0, "number of loaded fonts should not be 0\n");
3672
3673     free_font(font);
3674
3675     SetLastError(0xdeadbeef);
3676     bRet = pRemoveFontMemResourceEx(ret);
3677     ok(bRet, "RemoveFontMemResourceEx error %d\n", GetLastError());
3678
3679     /* test invalid pointer to number of loaded fonts */
3680     font = load_font("sserife.fon", &font_size);
3681     ok(font != NULL, "Unable to locate and load font sserife.fon\n");
3682
3683     SetLastError(0xdeadbeef);
3684     ret = pAddFontMemResourceEx(font, font_size, NULL, (void *)0xdeadbeef);
3685     ok(!ret, "AddFontMemResourceEx should fail\n");
3686     ok(GetLastError() == 0xdeadbeef,
3687        "Expected GetLastError() to return 0xdeadbeef, got %u\n",
3688        GetLastError());
3689
3690     SetLastError(0xdeadbeef);
3691     ret = pAddFontMemResourceEx(font, font_size, NULL, NULL);
3692     ok(!ret, "AddFontMemResourceEx should fail\n");
3693     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3694        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3695        GetLastError());
3696
3697     free_font(font);
3698 }
3699
3700 static INT CALLBACK enum_fonts_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3701 {
3702     LOGFONT *lf;
3703
3704     if (type != TRUETYPE_FONTTYPE) return 1;
3705
3706     ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
3707
3708     lf = (LOGFONT *)lparam;
3709     *lf = *elf;
3710     return 0;
3711 }
3712
3713 static INT CALLBACK enum_all_fonts_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3714 {
3715     int ret;
3716     LOGFONT *lf;
3717
3718     if (type != TRUETYPE_FONTTYPE) return 1;
3719
3720     lf = (LOGFONT *)lparam;
3721     ret = strcmp(lf->lfFaceName, elf->lfFaceName);
3722     if(ret == 0)
3723     {
3724         ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
3725         *lf = *elf;
3726         return 0;
3727     }
3728     return 1;
3729 }
3730
3731 static void test_EnumFonts(void)
3732 {
3733     int ret;
3734     LOGFONT lf;
3735     HDC hdc;
3736
3737     if (!is_truetype_font_installed("Arial"))
3738     {
3739         skip("Arial is not installed\n");
3740         return;
3741     }
3742
3743     /* Windows uses localized font face names, so Arial Bold won't be found */
3744     if (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH)
3745     {
3746         skip("User locale is not English, skipping the test\n");
3747         return;
3748     }
3749
3750     hdc = CreateCompatibleDC(0);
3751
3752     ret = EnumFontFamilies(hdc, "Arial", enum_fonts_proc, (LPARAM)&lf);
3753     ok(!ret, "font Arial is not enumerated\n");
3754     ret = strcmp(lf.lfFaceName, "Arial");
3755     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3756     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
3757
3758     lstrcpy(lf.lfFaceName, "Arial");
3759     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3760     ok(!ret, "font Arial is not enumerated\n");
3761     ret = strcmp(lf.lfFaceName, "Arial");
3762     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3763     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
3764
3765     ret = EnumFontFamilies(hdc, "Arial Bold", enum_fonts_proc, (LPARAM)&lf);
3766     ok(!ret, "font Arial Bold is not enumerated\n");
3767     ret = strcmp(lf.lfFaceName, "Arial");
3768     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3769     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
3770
3771     lstrcpy(lf.lfFaceName, "Arial Bold");
3772     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3773     ok(ret, "font Arial Bold should not be enumerated\n");
3774
3775     ret = EnumFontFamilies(hdc, "Arial Bold Italic", enum_fonts_proc, (LPARAM)&lf);
3776     ok(!ret, "font Arial Bold Italic is not enumerated\n");
3777     ret = strcmp(lf.lfFaceName, "Arial");
3778     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3779     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
3780
3781     lstrcpy(lf.lfFaceName, "Arial Bold Italic");
3782     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3783     ok(ret, "font Arial Bold Italic should not be enumerated\n");
3784
3785     ret = EnumFontFamilies(hdc, "Arial Italic Bold", enum_fonts_proc, (LPARAM)&lf);
3786     ok(ret, "font Arial Italic Bold  should not be enumerated\n");
3787
3788     lstrcpy(lf.lfFaceName, "Arial Italic Bold");
3789     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3790     ok(ret, "font Arial Italic Bold should not be enumerated\n");
3791
3792     DeleteDC(hdc);
3793 }
3794
3795 static INT CALLBACK is_font_installed_fullname_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
3796 {
3797     const ENUMLOGFONT *elf = (const ENUMLOGFONT *)lf;
3798     const char *fullname = (const char *)lParam;
3799
3800     if (!strcmp((const char *)elf->elfFullName, fullname)) return 0;
3801
3802     return 1;
3803 }
3804
3805 static BOOL is_font_installed_fullname(const char *family, const char *fullname)
3806 {
3807     HDC hdc = GetDC(0);
3808     BOOL ret = FALSE;
3809
3810     if(!EnumFontFamiliesA(hdc, family, is_font_installed_fullname_proc, (LPARAM)fullname))
3811         ret = TRUE;
3812
3813     ReleaseDC(0, hdc);
3814     return ret;
3815 }
3816
3817 static void test_fullname(void)
3818 {
3819     static const char *TestName[] = {"Lucida Sans Demibold Roman", "Lucida Sans Italic", "Lucida Sans Regular"};
3820     char buf[LF_FULLFACESIZE];
3821     HFONT hfont, of;
3822     LOGFONTA lf;
3823     HDC hdc;
3824     int i;
3825
3826     hdc = CreateCompatibleDC(0);
3827     ok(hdc != NULL, "CreateCompatibleDC failed\n");
3828
3829     memset(&lf, 0, sizeof(lf));
3830     lf.lfCharSet = ANSI_CHARSET;
3831     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
3832     lf.lfHeight = 16;
3833     lf.lfWidth = 16;
3834     lf.lfQuality = DEFAULT_QUALITY;
3835     lf.lfItalic = FALSE;
3836     lf.lfWeight = FW_DONTCARE;
3837
3838     for (i = 0; i < sizeof(TestName) / sizeof(TestName[0]); i++)
3839     {
3840         if (!is_font_installed_fullname("Lucida Sans", TestName[i]))
3841         {
3842             skip("%s is not installed\n", TestName[i]);
3843             continue;
3844         }
3845
3846         lstrcpyA(lf.lfFaceName, TestName[i]);
3847         hfont = CreateFontIndirectA(&lf);
3848         ok(hfont != 0, "CreateFontIndirectA failed\n");
3849
3850         of = SelectObject(hdc, hfont);
3851         buf[0] = 0;
3852         ok(get_ttf_nametable_entry(hdc, TT_NAME_ID_FULL_NAME, buf, sizeof(buf)),
3853            "face full name could not be read\n");
3854         ok(!lstrcmpA(buf, TestName[i]), "font full names don't match: %s != %s\n", TestName[i], buf);
3855         SelectObject(hdc, of);
3856         DeleteObject(hfont);
3857     }
3858     DeleteDC(hdc);
3859 }
3860
3861 static BOOL write_ttf_file(char *tmp_name)
3862 {
3863     char tmp_path[MAX_PATH];
3864     HRSRC rsrc;
3865     void *rsrc_data;
3866     DWORD rsrc_size;
3867     HANDLE hfile;
3868     BOOL ret;
3869
3870     SetLastError(0xdeadbeef);
3871     rsrc = FindResource(GetModuleHandle(0), "wine_test.ttf", RT_RCDATA);
3872     ok(rsrc != 0, "FindResource error %d\n", GetLastError());
3873     if (!rsrc) return FALSE;
3874     SetLastError(0xdeadbeef);
3875     rsrc_data = LockResource(LoadResource(GetModuleHandle(0), rsrc));
3876     ok(rsrc_data != 0, "LockResource error %d\n", GetLastError());
3877     if (!rsrc_data) return FALSE;
3878     SetLastError(0xdeadbeef);
3879     rsrc_size = SizeofResource(GetModuleHandle(0), rsrc);
3880     ok(rsrc_size != 0, "SizeofResource error %d\n", GetLastError());
3881     if (!rsrc_size) return FALSE;
3882
3883     SetLastError(0xdeadbeef);
3884     ret = GetTempPath(MAX_PATH, tmp_path);
3885     ok(ret, "GetTempPath() error %d\n", GetLastError());
3886     SetLastError(0xdeadbeef);
3887     ret = GetTempFileName(tmp_path, "ttf", 0, tmp_name);
3888     ok(ret, "GetTempFileName() error %d\n", GetLastError());
3889
3890     SetLastError(0xdeadbeef);
3891     hfile = CreateFile(tmp_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
3892     ok(hfile != INVALID_HANDLE_VALUE, "CreateFile() error %d\n", GetLastError());
3893     if (hfile == INVALID_HANDLE_VALUE) return FALSE;
3894
3895     SetLastError(0xdeadbeef);
3896     ret = WriteFile(hfile, rsrc_data, rsrc_size, &rsrc_size, NULL);
3897     ok(ret, "WriteFile() error %d\n", GetLastError());
3898
3899     CloseHandle(hfile);
3900     return ret;
3901 }
3902
3903 static void test_CreateScalableFontResource(void)
3904 {
3905     char ttf_name[MAX_PATH];
3906     char tmp_path[MAX_PATH];
3907     char fot_name[MAX_PATH];
3908     char *file_part;
3909     DWORD ret;
3910
3911     if (!pAddFontResourceExA || !pRemoveFontResourceExA)
3912     {
3913         win_skip("AddFontResourceExA is not available on this platform\n");
3914         return;
3915     }
3916
3917     if (!write_ttf_file(ttf_name))
3918     {
3919         skip("Failed to create ttf file for testing\n");
3920         return;
3921     }
3922
3923     trace("created %s\n", ttf_name);
3924
3925     ret = is_truetype_font_installed("wine_test");
3926     ok(!ret, "font wine_test should not be enumerated\n");
3927
3928     ret = GetTempPath(MAX_PATH, tmp_path);
3929     ok(ret, "GetTempPath() error %d\n", GetLastError());
3930     ret = GetTempFileName(tmp_path, "fot", 0, fot_name);
3931     ok(ret, "GetTempFileName() error %d\n", GetLastError());
3932
3933     ret = GetFileAttributes(fot_name);
3934     ok(ret != INVALID_FILE_ATTRIBUTES, "file %s does not exist\n", fot_name);
3935
3936     SetLastError(0xdeadbeef);
3937     ret = CreateScalableFontResource(0, fot_name, ttf_name, NULL);
3938     ok(!ret, "CreateScalableFontResource() should fail\n");
3939     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
3940
3941     SetLastError(0xdeadbeef);
3942     ret = CreateScalableFontResource(0, fot_name, ttf_name, "");
3943     ok(!ret, "CreateScalableFontResource() should fail\n");
3944     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
3945
3946     file_part = strrchr(ttf_name, '\\');
3947     SetLastError(0xdeadbeef);
3948     ret = CreateScalableFontResource(0, fot_name, file_part, tmp_path);
3949     ok(!ret, "CreateScalableFontResource() should fail\n");
3950     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
3951
3952     SetLastError(0xdeadbeef);
3953     ret = CreateScalableFontResource(0, fot_name, "random file name", tmp_path);
3954     ok(!ret, "CreateScalableFontResource() should fail\n");
3955 todo_wine
3956     ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
3957
3958     SetLastError(0xdeadbeef);
3959     ret = CreateScalableFontResource(0, fot_name, NULL, ttf_name);
3960     ok(!ret, "CreateScalableFontResource() should fail\n");
3961 todo_wine
3962     ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
3963
3964     ret = DeleteFile(fot_name);
3965     ok(ret, "DeleteFile() error %d\n", GetLastError());
3966
3967     ret = pRemoveFontResourceExA(fot_name, 0, 0);
3968 todo_wine
3969     ok(!ret, "RemoveFontResourceEx() should fail\n");
3970
3971     /* FIXME: since CreateScalableFontResource is a stub further testing is impossible */
3972     if (ret) return;
3973
3974     /* test public font resource */
3975     SetLastError(0xdeadbeef);
3976     ret = CreateScalableFontResource(0, fot_name, ttf_name, NULL);
3977     ok(ret, "CreateScalableFontResource() error %d\n", GetLastError());
3978
3979     ret = is_truetype_font_installed("wine_test");
3980     ok(!ret, "font wine_test should not be enumerated\n");
3981
3982     SetLastError(0xdeadbeef);
3983     ret = pAddFontResourceExA(fot_name, 0, 0);
3984     ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
3985
3986     ret = is_truetype_font_installed("wine_test");
3987     ok(ret, "font wine_test should be enumerated\n");
3988
3989     ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
3990     ok(!ret, "RemoveFontResourceEx() with not matching flags should fail\n");
3991
3992     SetLastError(0xdeadbeef);
3993     ret = pRemoveFontResourceExA(fot_name, 0, 0);
3994 todo_wine
3995     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
3996
3997     ret = is_truetype_font_installed("wine_test");
3998 todo_wine
3999     ok(!ret, "font wine_test should not be enumerated\n");
4000
4001     /* FIXME: since RemoveFontResource is a stub correct testing is impossible */
4002     if (ret)
4003     {
4004         /* remove once RemoveFontResource is implemented */
4005         DeleteFile(fot_name);
4006         DeleteFile(ttf_name);
4007         return;
4008     }
4009
4010     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4011     ok(!ret, "RemoveFontResourceEx() should fail\n");
4012
4013     DeleteFile(fot_name);
4014
4015     /* test hidden font resource */
4016     SetLastError(0xdeadbeef);
4017     ret = CreateScalableFontResource(1, fot_name, ttf_name, NULL);
4018     ok(ret, "CreateScalableFontResource() error %d\n", GetLastError());
4019
4020     ret = is_truetype_font_installed("wine_test");
4021     ok(!ret, "font wine_test should not be enumerated\n");
4022
4023     SetLastError(0xdeadbeef);
4024     ret = pAddFontResourceExA(fot_name, 0, 0);
4025     ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
4026
4027     ret = is_truetype_font_installed("wine_test");
4028     ok(!ret, "font wine_test should not be enumerated\n");
4029
4030     /* XP allows removing a private font added with 0 flags */
4031     SetLastError(0xdeadbeef);
4032     ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
4033     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
4034
4035     ret = is_truetype_font_installed("wine_test");
4036     ok(!ret, "font wine_test should not be enumerated\n");
4037
4038     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4039     ok(!ret, "RemoveFontResourceEx() should fail\n");
4040
4041     DeleteFile(fot_name);
4042     DeleteFile(ttf_name);
4043 }
4044
4045 START_TEST(font)
4046 {
4047     init();
4048
4049     test_logfont();
4050     test_bitmap_font();
4051     test_outline_font();
4052     test_bitmap_font_metrics();
4053     test_GdiGetCharDimensions();
4054     test_GetCharABCWidths();
4055     test_text_extents();
4056     test_GetGlyphIndices();
4057     test_GetKerningPairs();
4058     test_GetOutlineTextMetrics();
4059     test_SetTextJustification();
4060     test_font_charset();
4061     test_GetFontUnicodeRanges();
4062     test_nonexistent_font();
4063     test_orientation();
4064     test_height_selection();
4065     test_AddFontMemResource();
4066     test_EnumFonts();
4067
4068     /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
4069      * I'd like to avoid them in this test.
4070      */
4071     test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
4072     test_EnumFontFamilies("Symbol", SYMBOL_CHARSET);
4073     if (is_truetype_font_installed("Arial Black") &&
4074         (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
4075     {
4076         test_EnumFontFamilies("", ANSI_CHARSET);
4077         test_EnumFontFamilies("", SYMBOL_CHARSET);
4078         test_EnumFontFamilies("", DEFAULT_CHARSET);
4079     }
4080     else
4081         skip("Arial Black or Symbol/Wingdings is not installed\n");
4082     test_EnumFontFamiliesEx_default_charset();
4083     test_GetTextMetrics();
4084     test_GdiRealizationInfo();
4085     test_GetTextFace();
4086     test_GetGlyphOutline();
4087     test_GetTextMetrics2("Tahoma", -11);
4088     test_GetTextMetrics2("Tahoma", -55);
4089     test_GetTextMetrics2("Tahoma", -110);
4090     test_GetTextMetrics2("Arial", -11);
4091     test_GetTextMetrics2("Arial", -55);
4092     test_GetTextMetrics2("Arial", -110);
4093     test_CreateFontIndirect();
4094     test_CreateFontIndirectEx();
4095     test_oemcharset();
4096     test_fullname();
4097
4098     /* CreateScalableFontResource should be last test until RemoveFontResource
4099      * is properly implemented.
4100      */
4101     test_CreateScalableFontResource();
4102 }