comctl32/imagelist: Use proper color format for merged image lists.
[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
3761         lf.lfFaceName[0] = '\0';
3762         lf.lfCharSet = c[i].cs;
3763         lf.lfPitchAndFamily = 0;
3764         if (EnumFontFamiliesEx(hdc, &lf, create_font_proc, (LPARAM)&hfont, 0))
3765         {
3766             skip("TrueType font for charset %u is not installed\n", c[i].cs);
3767             continue;
3768         }
3769
3770         old_hfont = SelectObject(hdc, hfont);
3771
3772         /* expected to ignore superfluous bytes (sigle-byte character) */
3773         ret = GetGlyphOutlineA(hdc, 0x8041, GGO_BITMAP, &gm, 0, NULL, &mat);
3774         ret2 = GetGlyphOutlineA(hdc, 0x41, GGO_BITMAP, &gm2, 0, NULL, &mat);
3775         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
3776
3777         ret = GetGlyphOutlineA(hdc, 0xcc8041, GGO_BITMAP, &gm, 0, NULL, &mat);
3778         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
3779            "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
3780
3781         /* expected to ignore superfluous bytes (double-byte character) */
3782         ret = GetGlyphOutlineA(hdc, c[i].a, GGO_BITMAP, &gm, 0, NULL, &mat);
3783         ret2 = GetGlyphOutlineA(hdc, c[i].a | 0xdead0000, GGO_BITMAP, &gm2, 0, NULL, &mat);
3784         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
3785            "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
3786
3787         /* expected to match wide-char version results */
3788         ret2 = GetGlyphOutlineW(hdc, c[i].w, GGO_BITMAP, &gm2, 0, NULL, &mat);
3789         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
3790
3791         if (EnumFontFamiliesEx(hdc, &lf, create_fixed_pitch_font_proc, (LPARAM)&hfont, 0))
3792         {
3793             skip("Fixed-pitch TrueType font for charset %u is not available\n", c[i].cs);
3794             continue;
3795         }
3796         DeleteObject(SelectObject(hdc, hfont));
3797         if (c[i].a <= 0xff)
3798         {
3799             DeleteObject(SelectObject(hdc, old_hfont));
3800             continue;
3801         }
3802
3803         ret = GetObject(hfont, sizeof lf, &lf);
3804         ok(ret > 0, "GetObject error %u\n", GetLastError());
3805
3806         ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3807         ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
3808         ret = GetGlyphOutlineA(hdc, c[i].a, GGO_METRICS, &gm2, 0, NULL, &mat);
3809         ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
3810         trace("Tests with height=%d,half=%d,full=%d,face=%s,charset=%d\n",
3811               -lf.lfHeight, gm.gmCellIncX, gm2.gmCellIncX, lf.lfFaceName, lf.lfCharSet);
3812         ok(gm2.gmCellIncX == gm.gmCellIncX * 2 || broken(gm2.gmCellIncX == -lf.lfHeight),
3813            "expected %d, got %d (%s:%d)\n",
3814            gm.gmCellIncX * 2, gm2.gmCellIncX, lf.lfFaceName, lf.lfCharSet);
3815
3816         ret = GetGlyphOutlineA(hdc, c[i].a, GGO_METRICS, &gm2, 0, NULL, &rotate_mat);
3817         ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
3818         ok(gm2.gmCellIncY == -lf.lfHeight,
3819            "expected %d, got %d (%s:%d)\n",
3820            -lf.lfHeight, gm2.gmCellIncY, lf.lfFaceName, lf.lfCharSet);
3821
3822         lf.lfItalic = TRUE;
3823         hfont = CreateFontIndirect(&lf);
3824         ok(hfont != NULL, "CreateFontIndirect error %u\n", GetLastError());
3825         DeleteObject(SelectObject(hdc, hfont));
3826         ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3827         ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
3828         ret = GetGlyphOutlineA(hdc, c[i].a, GGO_METRICS, &gm2, 0, NULL, &mat);
3829         ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
3830         ok(gm2.gmCellIncX == gm.gmCellIncX * 2 || broken(gm2.gmCellIncX == -lf.lfHeight),
3831            "expected %d, got %d (%s:%d)\n",
3832            gm.gmCellIncX * 2, gm2.gmCellIncX, lf.lfFaceName, lf.lfCharSet);
3833
3834         lf.lfItalic = FALSE;
3835         lf.lfEscapement = lf.lfOrientation = 2700;
3836         hfont = CreateFontIndirect(&lf);
3837         ok(hfont != NULL, "CreateFontIndirect error %u\n", GetLastError());
3838         DeleteObject(SelectObject(hdc, hfont));
3839         ret = GetGlyphOutlineA(hdc, c[i].a, GGO_METRICS, &gm2, 0, NULL, &mat);
3840         ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
3841         ok(gm2.gmCellIncY == -lf.lfHeight,
3842            "expected %d, got %d (%s:%d)\n",
3843            -lf.lfHeight, gm2.gmCellIncY, lf.lfFaceName, lf.lfCharSet);
3844
3845         hfont = SelectObject(hdc, old_hfont);
3846         DeleteObject(hfont);
3847     }
3848
3849     DeleteDC(hdc);
3850 }
3851
3852 /* bug #9995: there is a limit to the character width that can be specified */
3853 static void test_GetTextMetrics2(const char *fontname, int font_height)
3854 {
3855     HFONT of, hf;
3856     HDC hdc;
3857     TEXTMETRICA tm;
3858     BOOL ret;
3859     int ave_width, height, width, ratio, scale;
3860
3861     if (!is_truetype_font_installed( fontname)) {
3862         skip("%s is not installed\n", fontname);
3863         return;
3864     }
3865     hdc = CreateCompatibleDC(0);
3866     ok( hdc != NULL, "CreateCompatibleDC failed\n");
3867     /* select width = 0 */
3868     hf = CreateFontA(font_height, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3869             DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3870             DEFAULT_QUALITY, VARIABLE_PITCH,
3871             fontname);
3872     ok( hf != NULL, "CreateFontA(%s, %d) failed\n", fontname, font_height);
3873     of = SelectObject( hdc, hf);
3874     ret = GetTextMetricsA( hdc, &tm);
3875     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
3876     height = tm.tmHeight;
3877     ave_width = tm.tmAveCharWidth;
3878     SelectObject( hdc, of);
3879     DeleteObject( hf);
3880
3881     trace("height %d, ave width %d\n", height, ave_width);
3882
3883     for (width = ave_width * 2; /* nothing*/; width += ave_width)
3884     {
3885         hf = CreateFont(height, width, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3886                         DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3887                         DEFAULT_QUALITY, VARIABLE_PITCH, fontname);
3888         ok(hf != 0, "CreateFont failed\n");
3889         of = SelectObject(hdc, hf);
3890         ret = GetTextMetrics(hdc, &tm);
3891         ok(ret, "GetTextMetrics error %u\n", GetLastError());
3892         SelectObject(hdc, of);
3893         DeleteObject(hf);
3894
3895         if (match_off_by_1(tm.tmAveCharWidth, ave_width) || width / height > 200)
3896             break;
3897     }
3898
3899     DeleteDC(hdc);
3900
3901     ratio = width / height;
3902     scale = width / ave_width;
3903
3904     trace("max width/height ratio (%d / %d) %d, max width scale (%d / %d) %d\n",
3905           width, height, ratio, width, ave_width, scale);
3906
3907     ok(ratio >= 90 && ratio <= 110, "expected width/height ratio 90-110, got %d\n", ratio);
3908 }
3909
3910 static void test_CreateFontIndirect(void)
3911 {
3912     LOGFONTA lf, getobj_lf;
3913     int ret, i;
3914     HFONT hfont;
3915     char TestName[][16] = {"Arial", "Arial Bold", "Arial Italic", "Arial Baltic"};
3916
3917     memset(&lf, 0, sizeof(lf));
3918     lf.lfCharSet = ANSI_CHARSET;
3919     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
3920     lf.lfHeight = 16;
3921     lf.lfWidth = 16;
3922     lf.lfQuality = DEFAULT_QUALITY;
3923     lf.lfItalic = FALSE;
3924     lf.lfWeight = FW_DONTCARE;
3925
3926     for (i = 0; i < sizeof(TestName)/sizeof(TestName[0]); i++)
3927     {
3928         lstrcpyA(lf.lfFaceName, TestName[i]);
3929         hfont = CreateFontIndirectA(&lf);
3930         ok(hfont != 0, "CreateFontIndirectA failed\n");
3931         SetLastError(0xdeadbeef);
3932         ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf);
3933         ok(ret, "GetObject failed: %d\n", GetLastError());
3934         ok(lf.lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf.lfItalic, getobj_lf.lfItalic);
3935         ok(lf.lfWeight == getobj_lf.lfWeight ||
3936            broken((SHORT)lf.lfWeight == getobj_lf.lfWeight), /* win9x */
3937            "lfWeight: expect %08x got %08x\n", lf.lfWeight, getobj_lf.lfWeight);
3938         ok(!lstrcmpA(lf.lfFaceName, getobj_lf.lfFaceName) ||
3939            broken(!memcmp(lf.lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
3940            "font names don't match: %s != %s\n", lf.lfFaceName, getobj_lf.lfFaceName);
3941         DeleteObject(hfont);
3942     }
3943 }
3944
3945 static void test_CreateFontIndirectEx(void)
3946 {
3947     ENUMLOGFONTEXDVA lfex;
3948     HFONT hfont;
3949
3950     if (!pCreateFontIndirectExA)
3951     {
3952         win_skip("CreateFontIndirectExA is not available\n");
3953         return;
3954     }
3955
3956     if (!is_truetype_font_installed("Arial"))
3957     {
3958         skip("Arial is not installed\n");
3959         return;
3960     }
3961
3962     SetLastError(0xdeadbeef);
3963     hfont = pCreateFontIndirectExA(NULL);
3964     ok(hfont == NULL, "got %p\n", hfont);
3965     ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
3966
3967     memset(&lfex, 0, sizeof(lfex));
3968     lstrcpyA(lfex.elfEnumLogfontEx.elfLogFont.lfFaceName, "Arial");
3969     hfont = pCreateFontIndirectExA(&lfex);
3970     ok(hfont != 0, "CreateFontIndirectEx failed\n");
3971     if (hfont)
3972         check_font("Arial", &lfex.elfEnumLogfontEx.elfLogFont, hfont);
3973     DeleteObject(hfont);
3974 }
3975
3976 static void free_font(void *font)
3977 {
3978     UnmapViewOfFile(font);
3979 }
3980
3981 static void *load_font(const char *font_name, DWORD *font_size)
3982 {
3983     char file_name[MAX_PATH];
3984     HANDLE file, mapping;
3985     void *font;
3986
3987     if (!GetWindowsDirectory(file_name, sizeof(file_name))) return NULL;
3988     strcat(file_name, "\\fonts\\");
3989     strcat(file_name, font_name);
3990
3991     file = CreateFile(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
3992     if (file == INVALID_HANDLE_VALUE) return NULL;
3993
3994     *font_size = GetFileSize(file, NULL);
3995
3996     mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
3997     if (!mapping)
3998     {
3999         CloseHandle(file);
4000         return NULL;
4001     }
4002
4003     font = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
4004
4005     CloseHandle(file);
4006     CloseHandle(mapping);
4007     return font;
4008 }
4009
4010 static void test_AddFontMemResource(void)
4011 {
4012     void *font;
4013     DWORD font_size, num_fonts;
4014     HANDLE ret;
4015     BOOL bRet;
4016
4017     if (!pAddFontMemResourceEx || !pRemoveFontMemResourceEx)
4018     {
4019         win_skip("AddFontMemResourceEx is not available on this platform\n");
4020         return;
4021     }
4022
4023     font = load_font("sserife.fon", &font_size);
4024     if (!font)
4025     {
4026         skip("Unable to locate and load font sserife.fon\n");
4027         return;
4028     }
4029
4030     SetLastError(0xdeadbeef);
4031     ret = pAddFontMemResourceEx(NULL, 0, NULL, NULL);
4032     ok(!ret, "AddFontMemResourceEx should fail\n");
4033     ok(GetLastError() == ERROR_INVALID_PARAMETER,
4034        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
4035        GetLastError());
4036
4037     SetLastError(0xdeadbeef);
4038     ret = pAddFontMemResourceEx(NULL, 10, NULL, NULL);
4039     ok(!ret, "AddFontMemResourceEx should fail\n");
4040     ok(GetLastError() == ERROR_INVALID_PARAMETER,
4041        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
4042        GetLastError());
4043
4044     SetLastError(0xdeadbeef);
4045     ret = pAddFontMemResourceEx(NULL, 0, NULL, &num_fonts);
4046     ok(!ret, "AddFontMemResourceEx should fail\n");
4047     ok(GetLastError() == ERROR_INVALID_PARAMETER,
4048        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
4049        GetLastError());
4050
4051     SetLastError(0xdeadbeef);
4052     ret = pAddFontMemResourceEx(NULL, 10, NULL, &num_fonts);
4053     ok(!ret, "AddFontMemResourceEx should fail\n");
4054     ok(GetLastError() == ERROR_INVALID_PARAMETER,
4055        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
4056        GetLastError());
4057
4058     SetLastError(0xdeadbeef);
4059     ret = pAddFontMemResourceEx(font, 0, NULL, NULL);
4060     ok(!ret, "AddFontMemResourceEx should fail\n");
4061     ok(GetLastError() == ERROR_INVALID_PARAMETER,
4062        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
4063        GetLastError());
4064
4065     SetLastError(0xdeadbeef);
4066     ret = pAddFontMemResourceEx(font, 10, NULL, NULL);
4067     ok(!ret, "AddFontMemResourceEx should fail\n");
4068     ok(GetLastError() == ERROR_INVALID_PARAMETER,
4069        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
4070        GetLastError());
4071
4072     num_fonts = 0xdeadbeef;
4073     SetLastError(0xdeadbeef);
4074     ret = pAddFontMemResourceEx(font, 0, NULL, &num_fonts);
4075     ok(!ret, "AddFontMemResourceEx should fail\n");
4076     ok(GetLastError() == ERROR_INVALID_PARAMETER,
4077        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
4078        GetLastError());
4079     ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
4080
4081     if (0) /* hangs under windows 2000 */
4082     {
4083         num_fonts = 0xdeadbeef;
4084         SetLastError(0xdeadbeef);
4085         ret = pAddFontMemResourceEx(font, 10, NULL, &num_fonts);
4086         ok(!ret, "AddFontMemResourceEx should fail\n");
4087         ok(GetLastError() == 0xdeadbeef,
4088            "Expected GetLastError() to return 0xdeadbeef, got %u\n",
4089            GetLastError());
4090         ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
4091     }
4092
4093     num_fonts = 0xdeadbeef;
4094     SetLastError(0xdeadbeef);
4095     ret = pAddFontMemResourceEx(font, font_size, NULL, &num_fonts);
4096     ok(ret != 0, "AddFontMemResourceEx error %d\n", GetLastError());
4097     ok(num_fonts != 0xdeadbeef, "number of loaded fonts should not be 0xdeadbeef\n");
4098     ok(num_fonts != 0, "number of loaded fonts should not be 0\n");
4099
4100     free_font(font);
4101
4102     SetLastError(0xdeadbeef);
4103     bRet = pRemoveFontMemResourceEx(ret);
4104     ok(bRet, "RemoveFontMemResourceEx error %d\n", GetLastError());
4105
4106     /* test invalid pointer to number of loaded fonts */
4107     font = load_font("sserife.fon", &font_size);
4108     ok(font != NULL, "Unable to locate and load font sserife.fon\n");
4109
4110     SetLastError(0xdeadbeef);
4111     ret = pAddFontMemResourceEx(font, font_size, NULL, (void *)0xdeadbeef);
4112     ok(!ret, "AddFontMemResourceEx should fail\n");
4113     ok(GetLastError() == 0xdeadbeef,
4114        "Expected GetLastError() to return 0xdeadbeef, got %u\n",
4115        GetLastError());
4116
4117     SetLastError(0xdeadbeef);
4118     ret = pAddFontMemResourceEx(font, font_size, NULL, NULL);
4119     ok(!ret, "AddFontMemResourceEx should fail\n");
4120     ok(GetLastError() == ERROR_INVALID_PARAMETER,
4121        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
4122        GetLastError());
4123
4124     free_font(font);
4125 }
4126
4127 static INT CALLBACK enum_fonts_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
4128 {
4129     LOGFONT *lf;
4130
4131     if (type != TRUETYPE_FONTTYPE) return 1;
4132
4133     ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
4134
4135     lf = (LOGFONT *)lparam;
4136     *lf = *elf;
4137     return 0;
4138 }
4139
4140 static INT CALLBACK enum_all_fonts_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
4141 {
4142     int ret;
4143     LOGFONT *lf;
4144
4145     if (type != TRUETYPE_FONTTYPE) return 1;
4146
4147     lf = (LOGFONT *)lparam;
4148     ret = strcmp(lf->lfFaceName, elf->lfFaceName);
4149     if(ret == 0)
4150     {
4151         ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
4152         *lf = *elf;
4153         return 0;
4154     }
4155     return 1;
4156 }
4157
4158 static INT CALLBACK enum_with_magic_retval_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
4159 {
4160     return lparam;
4161 }
4162
4163 static void test_EnumFonts(void)
4164 {
4165     int ret;
4166     LOGFONT lf;
4167     HDC hdc;
4168
4169     if (!is_truetype_font_installed("Arial"))
4170     {
4171         skip("Arial is not installed\n");
4172         return;
4173     }
4174
4175     /* Windows uses localized font face names, so Arial Bold won't be found */
4176     if (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH)
4177     {
4178         skip("User locale is not English, skipping the test\n");
4179         return;
4180     }
4181
4182     hdc = CreateCompatibleDC(0);
4183
4184     /* check that the enumproc's retval is returned */
4185     ret = EnumFontFamilies(hdc, NULL, enum_with_magic_retval_proc, 0xcafe);
4186     ok(ret == 0xcafe, "got %08x\n", ret);
4187
4188     ret = EnumFontFamilies(hdc, "Arial", enum_fonts_proc, (LPARAM)&lf);
4189     ok(!ret, "font Arial is not enumerated\n");
4190     ret = strcmp(lf.lfFaceName, "Arial");
4191     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
4192     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
4193
4194     lstrcpy(lf.lfFaceName, "Arial");
4195     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
4196     ok(!ret, "font Arial is not enumerated\n");
4197     ret = strcmp(lf.lfFaceName, "Arial");
4198     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
4199     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
4200
4201     ret = EnumFontFamilies(hdc, "Arial Bold", enum_fonts_proc, (LPARAM)&lf);
4202     ok(!ret, "font Arial Bold is not enumerated\n");
4203     ret = strcmp(lf.lfFaceName, "Arial");
4204     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
4205     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
4206
4207     lstrcpy(lf.lfFaceName, "Arial Bold");
4208     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
4209     ok(ret, "font Arial Bold should not be enumerated\n");
4210
4211     ret = EnumFontFamilies(hdc, "Arial Bold Italic", enum_fonts_proc, (LPARAM)&lf);
4212     ok(!ret, "font Arial Bold Italic is not enumerated\n");
4213     ret = strcmp(lf.lfFaceName, "Arial");
4214     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
4215     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
4216
4217     lstrcpy(lf.lfFaceName, "Arial Bold Italic");
4218     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
4219     ok(ret, "font Arial Bold Italic should not be enumerated\n");
4220
4221     ret = EnumFontFamilies(hdc, "Arial Italic Bold", enum_fonts_proc, (LPARAM)&lf);
4222     ok(ret, "font Arial Italic Bold  should not be enumerated\n");
4223
4224     lstrcpy(lf.lfFaceName, "Arial Italic Bold");
4225     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
4226     ok(ret, "font Arial Italic Bold should not be enumerated\n");
4227
4228     DeleteDC(hdc);
4229 }
4230
4231 static INT CALLBACK is_font_installed_fullname_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
4232 {
4233     const ENUMLOGFONT *elf = (const ENUMLOGFONT *)lf;
4234     const char *fullname = (const char *)lParam;
4235
4236     if (!strcmp((const char *)elf->elfFullName, fullname)) return 0;
4237
4238     return 1;
4239 }
4240
4241 static BOOL is_font_installed_fullname(const char *family, const char *fullname)
4242 {
4243     HDC hdc = GetDC(0);
4244     BOOL ret = FALSE;
4245
4246     if(!EnumFontFamiliesA(hdc, family, is_font_installed_fullname_proc, (LPARAM)fullname))
4247         ret = TRUE;
4248
4249     ReleaseDC(0, hdc);
4250     return ret;
4251 }
4252
4253 static void test_fullname(void)
4254 {
4255     static const char *TestName[] = {"Lucida Sans Demibold Roman", "Lucida Sans Italic", "Lucida Sans Regular"};
4256     WCHAR bufW[LF_FULLFACESIZE];
4257     char bufA[LF_FULLFACESIZE];
4258     HFONT hfont, of;
4259     LOGFONTA lf;
4260     HDC hdc;
4261     int i;
4262     DWORD ret;
4263
4264     hdc = CreateCompatibleDC(0);
4265     ok(hdc != NULL, "CreateCompatibleDC failed\n");
4266
4267     memset(&lf, 0, sizeof(lf));
4268     lf.lfCharSet = ANSI_CHARSET;
4269     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
4270     lf.lfHeight = 16;
4271     lf.lfWidth = 16;
4272     lf.lfQuality = DEFAULT_QUALITY;
4273     lf.lfItalic = FALSE;
4274     lf.lfWeight = FW_DONTCARE;
4275
4276     for (i = 0; i < sizeof(TestName) / sizeof(TestName[0]); i++)
4277     {
4278         if (!is_font_installed_fullname("Lucida Sans", TestName[i]))
4279         {
4280             skip("%s is not installed\n", TestName[i]);
4281             continue;
4282         }
4283
4284         lstrcpyA(lf.lfFaceName, TestName[i]);
4285         hfont = CreateFontIndirectA(&lf);
4286         ok(hfont != 0, "CreateFontIndirectA failed\n");
4287
4288         of = SelectObject(hdc, hfont);
4289         bufW[0] = 0;
4290         bufA[0] = 0;
4291         ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FULL_NAME, bufW, sizeof(bufW), TT_MS_LANGID_ENGLISH_UNITED_STATES);
4292         ok(ret, "face full name could not be read\n");
4293         WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, sizeof(bufA), NULL, FALSE);
4294         ok(!lstrcmpA(bufA, TestName[i]), "font full names don't match: %s != %s\n", TestName[i], bufA);
4295         SelectObject(hdc, of);
4296         DeleteObject(hfont);
4297     }
4298     DeleteDC(hdc);
4299 }
4300
4301 static WCHAR *prepend_at(WCHAR *family)
4302 {
4303     if (!family)
4304         return NULL;
4305
4306     memmove(family + 1, family, (lstrlenW(family) + 1) * sizeof(WCHAR));
4307     family[0] = '@';
4308     return family;
4309 }
4310
4311 static void test_fullname2_helper(const char *Family)
4312 {
4313     char *FamilyName, *FaceName, *StyleName, *otmStr;
4314     struct enum_fullname_data efnd;
4315     WCHAR *bufW;
4316     char *bufA;
4317     HFONT hfont, of;
4318     LOGFONTA lf;
4319     HDC hdc;
4320     int i;
4321     DWORD otm_size, ret, buf_size;
4322     OUTLINETEXTMETRICA *otm;
4323     BOOL want_vertical, get_vertical;
4324     want_vertical = ( Family[0] == '@' );
4325
4326     hdc = CreateCompatibleDC(0);
4327     ok(hdc != NULL, "CreateCompatibleDC failed\n");
4328
4329     memset(&lf, 0, sizeof(lf));
4330     lf.lfCharSet = DEFAULT_CHARSET;
4331     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
4332     lf.lfHeight = 16;
4333     lf.lfWidth = 16;
4334     lf.lfQuality = DEFAULT_QUALITY;
4335     lf.lfItalic = FALSE;
4336     lf.lfWeight = FW_DONTCARE;
4337     lstrcpy(lf.lfFaceName, Family);
4338     efnd.total = 0;
4339     EnumFontFamiliesExA(hdc, &lf, enum_fullname_data_proc, (LPARAM)&efnd, 0);
4340     if (efnd.total == 0)
4341         skip("%s is not installed\n", lf.lfFaceName);
4342
4343     for (i = 0; i < efnd.total; i++)
4344     {
4345         FamilyName = (char *)efnd.elf[i].elfLogFont.lfFaceName;
4346         FaceName = (char *)efnd.elf[i].elfFullName;
4347         StyleName = (char *)efnd.elf[i].elfStyle;
4348
4349         trace("Checking font %s:\nFamilyName: %s; FaceName: %s; StyleName: %s\n", Family, FamilyName, FaceName, StyleName);
4350
4351         get_vertical = ( FamilyName[0] == '@' );
4352         ok(get_vertical == want_vertical, "Vertical flags don't match: %s %s\n", Family, FamilyName);
4353
4354         lstrcpyA(lf.lfFaceName, FaceName);
4355         hfont = CreateFontIndirectA(&lf);
4356         ok(hfont != 0, "CreateFontIndirectA failed\n");
4357
4358         of = SelectObject(hdc, hfont);
4359         buf_size = GetFontData(hdc, MS_NAME_TAG, 0, NULL, 0);
4360         ok(buf_size != GDI_ERROR, "no name table found\n");
4361         if (buf_size == GDI_ERROR) continue;
4362
4363         bufW = HeapAlloc(GetProcessHeap(), 0, buf_size);
4364         bufA = HeapAlloc(GetProcessHeap(), 0, buf_size);
4365
4366         otm_size = GetOutlineTextMetricsA(hdc, 0, NULL);
4367         otm = HeapAlloc(GetProcessHeap(), 0, otm_size);
4368         memset(otm, 0, otm_size);
4369         ret = GetOutlineTextMetrics(hdc, otm_size, otm);
4370         ok(ret != 0, "GetOutlineTextMetrics fails!\n");
4371         if (ret == 0) continue;
4372
4373         bufW[0] = 0;
4374         bufA[0] = 0;
4375         ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FONT_FAMILY, bufW, buf_size, GetSystemDefaultLangID());
4376         if (!ret)
4377         {
4378             trace("no localized FONT_FAMILY found.\n");
4379             ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FONT_FAMILY, bufW, buf_size, TT_MS_LANGID_ENGLISH_UNITED_STATES);
4380         }
4381         ok(ret, "FAMILY (family name) could not be read\n");
4382         if (want_vertical) bufW = prepend_at(bufW);
4383         WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
4384         ok(!lstrcmpA(FamilyName, bufA), "font family names don't match: returned %s, expect %s\n", FamilyName, bufA);
4385         otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpFamilyName;
4386         ok(!lstrcmpA(FamilyName, otmStr), "FamilyName %s doesn't match otmpFamilyName %s\n", FamilyName, otmStr);
4387
4388         bufW[0] = 0;
4389         bufA[0] = 0;
4390         ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FULL_NAME, bufW, buf_size, GetSystemDefaultLangID());
4391         if (!ret)
4392         {
4393             trace("no localized FULL_NAME found.\n");
4394             ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FULL_NAME, bufW, buf_size, TT_MS_LANGID_ENGLISH_UNITED_STATES);
4395         }
4396         ok(ret, "FULL_NAME (face name) could not be read\n");
4397         if (want_vertical) bufW = prepend_at(bufW);
4398         WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
4399         ok(!lstrcmpA(FaceName, bufA), "font face names don't match: returned %s, expect %s\n", FaceName, bufA);
4400         otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpFaceName;
4401         ok(!lstrcmpA(FaceName, otmStr), "FaceName %s doesn't match otmpFaceName %s\n", FaceName, otmStr);
4402
4403         bufW[0] = 0;
4404         bufA[0] = 0;
4405         ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FONT_SUBFAMILY, bufW, buf_size, GetSystemDefaultLangID());
4406         if (!ret)
4407         {
4408             trace("no localized FONT_SUBFAMILY found.\n");
4409             ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FONT_SUBFAMILY, bufW, buf_size, TT_MS_LANGID_ENGLISH_UNITED_STATES);
4410         }
4411         ok(ret, "SUBFAMILY (style name) could not be read\n");
4412         WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
4413         ok(!lstrcmpA(StyleName, bufA), "style names don't match: returned %s, expect %s\n", StyleName, bufA);
4414         otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpStyleName;
4415         ok(!lstrcmpA(StyleName, otmStr), "StyleName %s doesn't match otmpStyleName %s\n", StyleName, otmStr);
4416
4417         bufW[0] = 0;
4418         bufA[0] = 0;
4419         ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_UNIQUE_ID, bufW, buf_size, GetSystemDefaultLangID());
4420         if (!ret)
4421         {
4422             trace("no localized UNIQUE_ID found.\n");
4423             ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_UNIQUE_ID, bufW, buf_size, TT_MS_LANGID_ENGLISH_UNITED_STATES);
4424         }
4425         ok(ret, "UNIQUE_ID (full name) could not be read\n");
4426         WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
4427         otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpFullName;
4428         ok(!lstrcmpA(otmStr, bufA), "UNIQUE ID (full name) doesn't match: returned %s, expect %s\n", otmStr, bufA);
4429
4430         SelectObject(hdc, of);
4431         DeleteObject(hfont);
4432
4433         HeapFree(GetProcessHeap(), 0, otm);
4434         HeapFree(GetProcessHeap(), 0, bufW);
4435         HeapFree(GetProcessHeap(), 0, bufA);
4436     }
4437     DeleteDC(hdc);
4438 }
4439
4440 static void test_fullname2(void)
4441 {
4442     test_fullname2_helper("Arial");
4443     test_fullname2_helper("DejaVu Sans");
4444     test_fullname2_helper("Lucida Sans");
4445     test_fullname2_helper("Tahoma");
4446     test_fullname2_helper("Webdings");
4447     test_fullname2_helper("Wingdings");
4448     test_fullname2_helper("SimSun");
4449     test_fullname2_helper("NSimSun");
4450     test_fullname2_helper("MingLiu");
4451     test_fullname2_helper("PMingLiu");
4452     test_fullname2_helper("WenQuanYi Micro Hei");
4453     test_fullname2_helper("MS UI Gothic");
4454     test_fullname2_helper("Ume UI Gothic");
4455     test_fullname2_helper("MS Gothic");
4456     test_fullname2_helper("Ume Gothic");
4457     test_fullname2_helper("MS PGothic");
4458     test_fullname2_helper("Ume P Gothic");
4459     test_fullname2_helper("Gulim");
4460     test_fullname2_helper("Batang");
4461     test_fullname2_helper("UnBatang");
4462     test_fullname2_helper("UnDotum");
4463     test_fullname2_helper("@SimSun");
4464     test_fullname2_helper("@NSimSun");
4465     test_fullname2_helper("@MingLiu");
4466     test_fullname2_helper("@PMingLiu");
4467     test_fullname2_helper("@WenQuanYi Micro Hei");
4468     test_fullname2_helper("@MS UI Gothic");
4469     test_fullname2_helper("@Ume UI Gothic");
4470     test_fullname2_helper("@MS Gothic");
4471     test_fullname2_helper("@Ume Gothic");
4472     test_fullname2_helper("@MS PGothic");
4473     test_fullname2_helper("@Ume P Gothic");
4474     test_fullname2_helper("@Gulim");
4475     test_fullname2_helper("@Batang");
4476     test_fullname2_helper("@UnBatang");
4477     test_fullname2_helper("@UnDotum");
4478
4479 }
4480
4481 static BOOL write_ttf_file(const char *fontname, char *tmp_name)
4482 {
4483     char tmp_path[MAX_PATH];
4484     HRSRC rsrc;
4485     void *rsrc_data;
4486     DWORD rsrc_size;
4487     HANDLE hfile;
4488     BOOL ret;
4489
4490     SetLastError(0xdeadbeef);
4491     rsrc = FindResource(GetModuleHandle(0), fontname, RT_RCDATA);
4492     ok(rsrc != 0, "FindResource error %d\n", GetLastError());
4493     if (!rsrc) return FALSE;
4494     SetLastError(0xdeadbeef);
4495     rsrc_data = LockResource(LoadResource(GetModuleHandle(0), rsrc));
4496     ok(rsrc_data != 0, "LockResource error %d\n", GetLastError());
4497     if (!rsrc_data) return FALSE;
4498     SetLastError(0xdeadbeef);
4499     rsrc_size = SizeofResource(GetModuleHandle(0), rsrc);
4500     ok(rsrc_size != 0, "SizeofResource error %d\n", GetLastError());
4501     if (!rsrc_size) return FALSE;
4502
4503     SetLastError(0xdeadbeef);
4504     ret = GetTempPath(MAX_PATH, tmp_path);
4505     ok(ret, "GetTempPath() error %d\n", GetLastError());
4506     SetLastError(0xdeadbeef);
4507     ret = GetTempFileName(tmp_path, "ttf", 0, tmp_name);
4508     ok(ret, "GetTempFileName() error %d\n", GetLastError());
4509
4510     SetLastError(0xdeadbeef);
4511     hfile = CreateFile(tmp_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
4512     ok(hfile != INVALID_HANDLE_VALUE, "CreateFile() error %d\n", GetLastError());
4513     if (hfile == INVALID_HANDLE_VALUE) return FALSE;
4514
4515     SetLastError(0xdeadbeef);
4516     ret = WriteFile(hfile, rsrc_data, rsrc_size, &rsrc_size, NULL);
4517     ok(ret, "WriteFile() error %d\n", GetLastError());
4518
4519     CloseHandle(hfile);
4520     return ret;
4521 }
4522
4523 static void test_GetGlyphOutline_empty_contour(void)
4524 {
4525     HDC hdc;
4526     LOGFONTA lf;
4527     HFONT hfont, hfont_prev;
4528     TTPOLYGONHEADER *header;
4529     GLYPHMETRICS gm;
4530     char buf[1024];
4531     DWORD ret;
4532
4533     memset(&lf, 0, sizeof(lf));
4534     lf.lfHeight = 72;
4535     lstrcpyA(lf.lfFaceName, "wine_test");
4536
4537     hfont = CreateFontIndirectA(&lf);
4538     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
4539
4540     hdc = GetDC(NULL);
4541
4542     hfont_prev = SelectObject(hdc, hfont);
4543     ok(hfont_prev != NULL, "SelectObject failed\n");
4544
4545     ret = GetGlyphOutlineW(hdc, 0xa8, GGO_NATIVE, &gm, 0, NULL, &mat);
4546     ok(ret == 228, "GetGlyphOutline returned %d, expected 228\n", ret);
4547
4548     header = (TTPOLYGONHEADER*)buf;
4549     ret = GetGlyphOutlineW(hdc, 0xa8, GGO_NATIVE, &gm, sizeof(buf), buf, &mat);
4550     ok(ret == 228, "GetGlyphOutline returned %d, expected 228\n", ret);
4551     ok(header->cb == 36, "header->cb = %d, expected 36\n", header->cb);
4552     ok(header->dwType == TT_POLYGON_TYPE, "header->dwType = %d, expected TT_POLYGON_TYPE\n", header->dwType);
4553     header = (TTPOLYGONHEADER*)((char*)header+header->cb);
4554     ok(header->cb == 96, "header->cb = %d, expected 96\n", header->cb);
4555     header = (TTPOLYGONHEADER*)((char*)header+header->cb);
4556     ok(header->cb == 96, "header->cb = %d, expected 96\n", header->cb);
4557
4558     SelectObject(hdc, hfont_prev);
4559     DeleteObject(hfont);
4560     ReleaseDC(NULL, hdc);
4561 }
4562
4563 static void test_CreateScalableFontResource(void)
4564 {
4565     char ttf_name[MAX_PATH];
4566     char tmp_path[MAX_PATH];
4567     char fot_name[MAX_PATH];
4568     char *file_part;
4569     DWORD ret;
4570     int i;
4571
4572     if (!pAddFontResourceExA || !pRemoveFontResourceExA)
4573     {
4574         win_skip("AddFontResourceExA is not available on this platform\n");
4575         return;
4576     }
4577
4578     if (!write_ttf_file("wine_test.ttf", ttf_name))
4579     {
4580         skip("Failed to create ttf file for testing\n");
4581         return;
4582     }
4583
4584     trace("created %s\n", ttf_name);
4585
4586     ret = is_truetype_font_installed("wine_test");
4587     ok(!ret, "font wine_test should not be enumerated\n");
4588
4589     ret = GetTempPath(MAX_PATH, tmp_path);
4590     ok(ret, "GetTempPath() error %d\n", GetLastError());
4591     ret = GetTempFileName(tmp_path, "fot", 0, fot_name);
4592     ok(ret, "GetTempFileName() error %d\n", GetLastError());
4593
4594     ret = GetFileAttributes(fot_name);
4595     ok(ret != INVALID_FILE_ATTRIBUTES, "file %s does not exist\n", fot_name);
4596
4597     SetLastError(0xdeadbeef);
4598     ret = CreateScalableFontResource(0, fot_name, ttf_name, NULL);
4599     ok(!ret, "CreateScalableFontResource() should fail\n");
4600     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
4601
4602     SetLastError(0xdeadbeef);
4603     ret = CreateScalableFontResource(0, fot_name, ttf_name, "");
4604     ok(!ret, "CreateScalableFontResource() should fail\n");
4605     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
4606
4607     file_part = strrchr(ttf_name, '\\');
4608     SetLastError(0xdeadbeef);
4609     ret = CreateScalableFontResource(0, fot_name, file_part, tmp_path);
4610     ok(!ret, "CreateScalableFontResource() should fail\n");
4611     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
4612
4613     SetLastError(0xdeadbeef);
4614     ret = CreateScalableFontResource(0, fot_name, "random file name", tmp_path);
4615     ok(!ret, "CreateScalableFontResource() should fail\n");
4616     ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
4617
4618     SetLastError(0xdeadbeef);
4619     ret = CreateScalableFontResource(0, fot_name, NULL, ttf_name);
4620     ok(!ret, "CreateScalableFontResource() should fail\n");
4621     ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
4622
4623     ret = DeleteFile(fot_name);
4624     ok(ret, "DeleteFile() error %d\n", GetLastError());
4625
4626     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4627     ok(!ret, "RemoveFontResourceEx() should fail\n");
4628
4629     /* test public font resource */
4630     SetLastError(0xdeadbeef);
4631     ret = CreateScalableFontResource(0, fot_name, ttf_name, NULL);
4632     ok(ret, "CreateScalableFontResource() error %d\n", GetLastError());
4633
4634     ret = is_truetype_font_installed("wine_test");
4635     ok(!ret, "font wine_test should not be enumerated\n");
4636
4637     SetLastError(0xdeadbeef);
4638     ret = pAddFontResourceExA(fot_name, 0, 0);
4639     ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
4640
4641     ret = is_truetype_font_installed("wine_test");
4642     ok(ret, "font wine_test should be enumerated\n");
4643
4644     test_GetGlyphOutline_empty_contour();
4645
4646     ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
4647     ok(!ret, "RemoveFontResourceEx() with not matching flags should fail\n");
4648
4649     SetLastError(0xdeadbeef);
4650     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4651     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
4652
4653     ret = is_truetype_font_installed("wine_test");
4654     ok(!ret, "font wine_test should not be enumerated\n");
4655
4656     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4657     ok(!ret, "RemoveFontResourceEx() should fail\n");
4658
4659     /* test refcounting */
4660     for (i = 0; i < 5; i++)
4661     {
4662         SetLastError(0xdeadbeef);
4663         ret = pAddFontResourceExA(fot_name, 0, 0);
4664         ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
4665     }
4666     for (i = 0; i < 5; i++)
4667     {
4668         SetLastError(0xdeadbeef);
4669         ret = pRemoveFontResourceExA(fot_name, 0, 0);
4670         ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
4671     }
4672     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4673     ok(!ret, "RemoveFontResourceEx() should fail\n");
4674
4675     DeleteFile(fot_name);
4676
4677     /* test hidden font resource */
4678     SetLastError(0xdeadbeef);
4679     ret = CreateScalableFontResource(1, fot_name, ttf_name, NULL);
4680     ok(ret, "CreateScalableFontResource() error %d\n", GetLastError());
4681
4682     ret = is_truetype_font_installed("wine_test");
4683     ok(!ret, "font wine_test should not be enumerated\n");
4684
4685     SetLastError(0xdeadbeef);
4686     ret = pAddFontResourceExA(fot_name, 0, 0);
4687     ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
4688
4689     ret = is_truetype_font_installed("wine_test");
4690     todo_wine
4691     ok(!ret, "font wine_test should not be enumerated\n");
4692
4693     /* XP allows removing a private font added with 0 flags */
4694     SetLastError(0xdeadbeef);
4695     ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
4696     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
4697
4698     ret = is_truetype_font_installed("wine_test");
4699     ok(!ret, "font wine_test should not be enumerated\n");
4700
4701     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4702     ok(!ret, "RemoveFontResourceEx() should fail\n");
4703
4704     DeleteFile(fot_name);
4705     DeleteFile(ttf_name);
4706 }
4707
4708 static void check_vertical_font(const char *name, BOOL *installed, BOOL *selected, GLYPHMETRICS *gm, WORD *gi)
4709 {
4710     LOGFONTA lf;
4711     HFONT hfont, hfont_prev;
4712     HDC hdc;
4713     char facename[100];
4714     DWORD ret;
4715     static const WCHAR str[] = { 0x2025 };
4716
4717     *installed = is_truetype_font_installed(name);
4718
4719     lf.lfHeight = -18;
4720     lf.lfWidth = 0;
4721     lf.lfEscapement = 0;
4722     lf.lfOrientation = 0;
4723     lf.lfWeight = FW_DONTCARE;
4724     lf.lfItalic = 0;
4725     lf.lfUnderline = 0;
4726     lf.lfStrikeOut = 0;
4727     lf.lfCharSet = DEFAULT_CHARSET;
4728     lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
4729     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
4730     lf.lfQuality = DEFAULT_QUALITY;
4731     lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
4732     strcpy(lf.lfFaceName, name);
4733
4734     hfont = CreateFontIndirectA(&lf);
4735     ok(hfont != NULL, "CreateFontIndirectA failed\n");
4736
4737     hdc = GetDC(NULL);
4738
4739     hfont_prev = SelectObject(hdc, hfont);
4740     ok(hfont_prev != NULL, "SelectObject failed\n");
4741
4742     ret = GetTextFaceA(hdc, sizeof facename, facename);
4743     ok(ret, "GetTextFaceA failed\n");
4744     *selected = !strcmp(facename, name);
4745
4746     ret = GetGlyphOutlineW(hdc, 0x2025, GGO_METRICS, gm, 0, NULL, &mat);
4747     ok(ret != GDI_ERROR, "GetGlyphOutlineW failed\n");
4748     if (!*selected)
4749         memset(gm, 0, sizeof *gm);
4750
4751     ret = pGetGlyphIndicesW(hdc, str, 1, gi, 0);
4752     ok(ret != GDI_ERROR, "GetGlyphIndicesW failed\n");
4753
4754     SelectObject(hdc, hfont_prev);
4755     DeleteObject(hfont);
4756     ReleaseDC(NULL, hdc);
4757 }
4758
4759 static void test_vertical_font(void)
4760 {
4761     char ttf_name[MAX_PATH];
4762     int num;
4763     BOOL ret, installed, selected;
4764     GLYPHMETRICS gm;
4765     WORD hgi, vgi;
4766
4767     if (!pAddFontResourceExA || !pRemoveFontResourceExA || !pGetGlyphIndicesW)
4768     {
4769         win_skip("AddFontResourceExA or GetGlyphIndicesW is not available on this platform\n");
4770         return;
4771     }
4772
4773     if (!write_ttf_file("vertical.ttf", ttf_name))
4774     {
4775         skip("Failed to create ttf file for testing\n");
4776         return;
4777     }
4778
4779     num = pAddFontResourceExA(ttf_name, FR_PRIVATE, 0);
4780     ok(num == 2, "AddFontResourceExA should add 2 fonts from vertical.ttf\n");
4781
4782     check_vertical_font("@WineTestVertical", &installed, &selected, &gm, &hgi);
4783     ok(installed, "@WineTestVertical is not installed\n");
4784     ok(selected, "@WineTestVertical is not selected\n");
4785     ok(gm.gmBlackBoxX > gm.gmBlackBoxY,
4786        "gmBlackBoxX(%u) should be greater than gmBlackBoxY(%u) if horizontal\n",
4787        gm.gmBlackBoxX, gm.gmBlackBoxY);
4788
4789     check_vertical_font("@@WineTestVertical", &installed, &selected, &gm, &vgi);
4790     ok(installed, "@@WineTestVertical is not installed\n");
4791     ok(selected, "@@WineTestVertical is not selected\n");
4792     ok(gm.gmBlackBoxX < gm.gmBlackBoxY,
4793        "gmBlackBoxX(%u) should be less than gmBlackBoxY(%u) if vertical\n",
4794        gm.gmBlackBoxX, gm.gmBlackBoxY);
4795
4796     ok(hgi == vgi, "different glyph h:%u v:%u\n", hgi, vgi);
4797
4798     ret = pRemoveFontResourceExA(ttf_name, FR_PRIVATE, 0);
4799     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
4800
4801     DeleteFile(ttf_name);
4802 }
4803
4804 static INT CALLBACK has_vertical_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm,
4805                                            DWORD type, LPARAM lParam)
4806 {
4807     if (lf->lfFaceName[0] == '@') {
4808         return 0;
4809     }
4810     return 1;
4811 }
4812
4813 static void test_east_asian_font_selection(void)
4814 {
4815     HDC hdc;
4816     UINT charset[] = { SHIFTJIS_CHARSET, HANGEUL_CHARSET, JOHAB_CHARSET,
4817                        GB2312_CHARSET, CHINESEBIG5_CHARSET };
4818     size_t i;
4819
4820     hdc = GetDC(NULL);
4821
4822     for (i = 0; i < sizeof(charset)/sizeof(charset[0]); i++)
4823     {
4824         LOGFONTA lf;
4825         HFONT hfont;
4826         char face_name[LF_FACESIZE];
4827         int ret;
4828
4829         memset(&lf, 0, sizeof lf);
4830         lf.lfFaceName[0] = '\0';
4831         lf.lfCharSet = charset[i];
4832
4833         if (EnumFontFamiliesEx(hdc, &lf, has_vertical_font_proc, 0, 0))
4834         {
4835             skip("Vertical font for charset %u is not installed\n", charset[i]);
4836             continue;
4837         }
4838
4839         hfont = CreateFontIndirectA(&lf);
4840         hfont = SelectObject(hdc, hfont);
4841         memset(face_name, 0, sizeof face_name);
4842         ret = GetTextFaceA(hdc, sizeof face_name, face_name);
4843         ok(ret && face_name[0] != '@',
4844            "expected non-vertical face for charset %u, got %s\n", charset[i], face_name);
4845         DeleteObject(SelectObject(hdc, hfont));
4846
4847         memset(&lf, 0, sizeof lf);
4848         strcpy(lf.lfFaceName, "@");
4849         lf.lfCharSet = charset[i];
4850         hfont = CreateFontIndirectA(&lf);
4851         hfont = SelectObject(hdc, hfont);
4852         memset(face_name, 0, sizeof face_name);
4853         ret = GetTextFaceA(hdc, sizeof face_name, face_name);
4854         ok(ret && face_name[0] == '@',
4855            "expected vertical face for charset %u, got %s\n", charset[i], face_name);
4856         DeleteObject(SelectObject(hdc, hfont));
4857     }
4858     ReleaseDC(NULL, hdc);
4859 }
4860
4861 static int get_font_dpi(const LOGFONT *lf)
4862 {
4863     HDC hdc = CreateCompatibleDC(0);
4864     HFONT hfont;
4865     TEXTMETRIC tm;
4866     int ret;
4867
4868     hfont = CreateFontIndirect(lf);
4869     ok(hfont != 0, "CreateFontIndirect failed\n");
4870
4871     SelectObject(hdc, hfont);
4872     ret = GetTextMetrics(hdc, &tm);
4873     ok(ret, "GetTextMetrics failed\n");
4874     ret = tm.tmDigitizedAspectX;
4875
4876     DeleteDC(hdc);
4877     DeleteObject(hfont);
4878
4879     return ret;
4880 }
4881
4882 static void test_stock_fonts(void)
4883 {
4884     static const int font[] =
4885     {
4886         ANSI_FIXED_FONT, ANSI_VAR_FONT, SYSTEM_FONT, DEVICE_DEFAULT_FONT, DEFAULT_GUI_FONT
4887         /* SYSTEM_FIXED_FONT, OEM_FIXED_FONT */
4888     };
4889     static const struct test_data
4890     {
4891         int charset, weight, height, dpi;
4892         const char face_name[LF_FACESIZE];
4893     } td[][11] =
4894     {
4895         { /* ANSI_FIXED_FONT */
4896             { DEFAULT_CHARSET, FW_NORMAL, 12, 96, "Courier" },
4897             { DEFAULT_CHARSET, FW_NORMAL, 12, 120, "Courier" },
4898             { 0 }
4899         },
4900         { /* ANSI_VAR_FONT */
4901             { DEFAULT_CHARSET, FW_NORMAL, 12, 96, "MS Sans Serif" },
4902             { DEFAULT_CHARSET, FW_NORMAL, 12, 120, "MS Sans Serif" },
4903             { 0 }
4904         },
4905         { /* SYSTEM_FONT */
4906             { SHIFTJIS_CHARSET, FW_NORMAL, 18, 96, "System" },
4907             { SHIFTJIS_CHARSET, FW_NORMAL, 22, 120, "System" },
4908             { HANGEUL_CHARSET, FW_NORMAL, 16, 96, "System" },
4909             { HANGEUL_CHARSET, FW_NORMAL, 20, 120, "System" },
4910             { DEFAULT_CHARSET, FW_BOLD, 16, 96, "System" },
4911             { DEFAULT_CHARSET, FW_BOLD, 20, 120, "System" },
4912             { 0 }
4913         },
4914         { /* DEVICE_DEFAULT_FONT */
4915             { SHIFTJIS_CHARSET, FW_NORMAL, 18, 96, "System" },
4916             { SHIFTJIS_CHARSET, FW_NORMAL, 22, 120, "System" },
4917             { HANGEUL_CHARSET, FW_NORMAL, 16, 96, "System" },
4918             { HANGEUL_CHARSET, FW_NORMAL, 20, 120, "System" },
4919             { DEFAULT_CHARSET, FW_BOLD, 16, 96, "System" },
4920             { DEFAULT_CHARSET, FW_BOLD, 20, 120, "System" },
4921             { 0 }
4922         },
4923         { /* DEFAULT_GUI_FONT */
4924             { SHIFTJIS_CHARSET, FW_NORMAL, -12, 96, "?MS UI Gothic" },
4925             { SHIFTJIS_CHARSET, FW_NORMAL, -15, 120, "?MS UI Gothic" },
4926             { HANGEUL_CHARSET, FW_NORMAL, -12, 96, "?Gulim" },
4927             { HANGEUL_CHARSET, FW_NORMAL, -15, 120, "?Gulim" },
4928             { GB2312_CHARSET, FW_NORMAL, -12, 96, "?SimHei" },
4929             { GB2312_CHARSET, FW_NORMAL, -15, 120, "?SimHei" },
4930             { CHINESEBIG5_CHARSET, FW_NORMAL, -12, 96, "?MingLiU" },
4931             { CHINESEBIG5_CHARSET, FW_NORMAL, -15, 120, "?MingLiU" },
4932             { DEFAULT_CHARSET, FW_NORMAL, -11, 96, "MS Shell Dlg" },
4933             { DEFAULT_CHARSET, FW_NORMAL, -13, 120, "MS Shell Dlg" },
4934             { 0 }
4935         }
4936     };
4937     int i, j;
4938
4939     for (i = 0; i < sizeof(font)/sizeof(font[0]); i++)
4940     {
4941         HFONT hfont;
4942         LOGFONT lf;
4943         int ret;
4944
4945         hfont = GetStockObject(font[i]);
4946         ok(hfont != 0, "%d: GetStockObject(%d) failed\n", i, font[i]);
4947
4948         ret = GetObject(hfont, sizeof(lf), &lf);
4949         if (ret != sizeof(lf))
4950         {
4951             /* NT4 */
4952             win_skip("%d: GetObject returned %d instead of sizeof(LOGFONT)\n", i, ret);
4953             continue;
4954         }
4955
4956         for (j = 0; td[i][j].face_name[0] != 0; j++)
4957         {
4958             if (lf.lfCharSet != td[i][j].charset && td[i][j].charset != DEFAULT_CHARSET)
4959             {
4960                 continue;
4961             }
4962
4963             ret = get_font_dpi(&lf);
4964             if (ret != td[i][j].dpi)
4965             {
4966                 trace("%d(%d): font %s %d dpi doesn't match test data %d\n",
4967                       i, j, lf.lfFaceName, ret, td[i][j].dpi);
4968                 continue;
4969             }
4970
4971             ok(td[i][j].weight == lf.lfWeight, "%d(%d): expected lfWeight %d, got %d\n", i, j, td[i][j].weight, lf.lfWeight);
4972             ok(td[i][j].height == lf.lfHeight, "%d(%d): expected lfHeight %d, got %d\n", i, j, td[i][j].height, lf.lfHeight);
4973             if (td[i][j].face_name[0] == '?')
4974             {
4975                 /* Wine doesn't have this font, skip this case for now.
4976                    Actually, the face name is localized on Windows and varies
4977                    dpending on Windows versions (e.g. Japanese NT4 vs win2k). */
4978                 trace("%d(%d): default gui font is %s\n", i, j, lf.lfFaceName);
4979             }
4980             else
4981             {
4982                 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);
4983             }
4984             break;
4985         }
4986     }
4987 }
4988
4989 START_TEST(font)
4990 {
4991     init();
4992
4993     test_stock_fonts();
4994     test_logfont();
4995     test_bitmap_font();
4996     test_outline_font();
4997     test_bitmap_font_metrics();
4998     test_GdiGetCharDimensions();
4999     test_GetCharABCWidths();
5000     test_text_extents();
5001     test_GetGlyphIndices();
5002     test_GetKerningPairs();
5003     test_GetOutlineTextMetrics();
5004     test_SetTextJustification();
5005     test_font_charset();
5006     test_GdiGetCodePage();
5007     test_GetFontUnicodeRanges();
5008     test_nonexistent_font();
5009     test_orientation();
5010     test_height_selection();
5011     test_AddFontMemResource();
5012     test_EnumFonts();
5013
5014     /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
5015      * I'd like to avoid them in this test.
5016      */
5017     test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
5018     test_EnumFontFamilies("Symbol", SYMBOL_CHARSET);
5019     if (is_truetype_font_installed("Arial Black") &&
5020         (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
5021     {
5022         test_EnumFontFamilies("", ANSI_CHARSET);
5023         test_EnumFontFamilies("", SYMBOL_CHARSET);
5024         test_EnumFontFamilies("", DEFAULT_CHARSET);
5025     }
5026     else
5027         skip("Arial Black or Symbol/Wingdings is not installed\n");
5028     test_EnumFontFamiliesEx_default_charset();
5029     test_GetTextMetrics();
5030     test_GdiRealizationInfo();
5031     test_GetTextFace();
5032     test_GetGlyphOutline();
5033     test_GetTextMetrics2("Tahoma", -11);
5034     test_GetTextMetrics2("Tahoma", -55);
5035     test_GetTextMetrics2("Tahoma", -110);
5036     test_GetTextMetrics2("Arial", -11);
5037     test_GetTextMetrics2("Arial", -55);
5038     test_GetTextMetrics2("Arial", -110);
5039     test_CreateFontIndirect();
5040     test_CreateFontIndirectEx();
5041     test_oemcharset();
5042     test_fullname();
5043     test_fullname2();
5044     test_east_asian_font_selection();
5045
5046     /* These tests should be last test until RemoveFontResource
5047      * is properly implemented.
5048      */
5049     test_vertical_font();
5050     test_CreateScalableFontResource();
5051 }