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