gdi32: Support for hidden flag of CreateScalableFontResource.
[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_GetFontUnicodeRanges(void)
2087 {
2088     LOGFONTA lf;
2089     HDC hdc;
2090     HFONT hfont, hfont_old;
2091     DWORD size;
2092     GLYPHSET *gs;
2093     DWORD i;
2094
2095     if (!pGetFontUnicodeRanges)
2096     {
2097         win_skip("GetFontUnicodeRanges not available before W2K\n");
2098         return;
2099     }
2100
2101     memset(&lf, 0, sizeof(lf));
2102     lstrcpyA(lf.lfFaceName, "Arial");
2103     hfont = create_font("Arial", &lf);
2104
2105     hdc = GetDC(0);
2106     hfont_old = SelectObject(hdc, hfont);
2107
2108     size = pGetFontUnicodeRanges(NULL, NULL);
2109     ok(!size, "GetFontUnicodeRanges succeeded unexpectedly\n");
2110
2111     size = pGetFontUnicodeRanges(hdc, NULL);
2112     ok(size, "GetFontUnicodeRanges failed unexpectedly\n");
2113
2114     gs = HeapAlloc(GetProcessHeap(), 0, size);
2115
2116     size = pGetFontUnicodeRanges(hdc, gs);
2117     ok(size, "GetFontUnicodeRanges failed\n");
2118
2119     if (0) /* Disabled to limit console spam */
2120         for (i = 0; i < gs->cRanges; i++)
2121             trace("%03d wcLow %04x cGlyphs %u\n", i, gs->ranges[i].wcLow, gs->ranges[i].cGlyphs);
2122     trace("found %u ranges\n", gs->cRanges);
2123
2124     HeapFree(GetProcessHeap(), 0, gs);
2125
2126     SelectObject(hdc, hfont_old);
2127     DeleteObject(hfont);
2128     ReleaseDC(NULL, hdc);
2129 }
2130
2131 #define MAX_ENUM_FONTS 4096
2132
2133 struct enum_font_data
2134 {
2135     int total;
2136     LOGFONT lf[MAX_ENUM_FONTS];
2137 };
2138
2139 struct enum_fullname_data
2140 {
2141     int total;
2142     ENUMLOGFONT elf[MAX_ENUM_FONTS];
2143 };
2144
2145 struct enum_font_dataW
2146 {
2147     int total;
2148     LOGFONTW lf[MAX_ENUM_FONTS];
2149 };
2150
2151 static INT CALLBACK arial_enum_proc(const LOGFONT *lf, const TEXTMETRIC *tm, DWORD type, LPARAM lParam)
2152 {
2153     struct enum_font_data *efd = (struct enum_font_data *)lParam;
2154     const NEWTEXTMETRIC *ntm = (const NEWTEXTMETRIC *)tm;
2155
2156     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
2157     ok(lf->lfHeight > 0 && lf->lfHeight < 200, "enumerated font height %d\n", lf->lfHeight);
2158
2159     if (type != TRUETYPE_FONTTYPE) return 1;
2160
2161     ok(ntm->ntmCellHeight + ntm->ntmCellHeight/5 >= ntm->ntmSizeEM, "ntmCellHeight %d should be close to ntmSizeEM %d\n", ntm->ntmCellHeight, ntm->ntmSizeEM);
2162
2163     if (0) /* Disabled to limit console spam */
2164         trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
2165               lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
2166     if (efd->total < MAX_ENUM_FONTS)
2167         efd->lf[efd->total++] = *lf;
2168     else
2169         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
2170
2171     return 1;
2172 }
2173
2174 static INT CALLBACK arial_enum_procw(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
2175 {
2176     struct enum_font_dataW *efd = (struct enum_font_dataW *)lParam;
2177     const NEWTEXTMETRICW *ntm = (const NEWTEXTMETRICW *)tm;
2178
2179     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
2180     ok(lf->lfHeight > 0 && lf->lfHeight < 200, "enumerated font height %d\n", lf->lfHeight);
2181
2182     if (type != TRUETYPE_FONTTYPE) return 1;
2183
2184     ok(ntm->ntmCellHeight + ntm->ntmCellHeight/5 >= ntm->ntmSizeEM, "ntmCellHeight %d should be close to ntmSizeEM %d\n", ntm->ntmCellHeight, ntm->ntmSizeEM);
2185
2186     if (0) /* Disabled to limit console spam */
2187         trace("enumed font %s, charset %d, height %d, weight %d, italic %d\n",
2188               wine_dbgstr_w(lf->lfFaceName), lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
2189     if (efd->total < MAX_ENUM_FONTS)
2190         efd->lf[efd->total++] = *lf;
2191     else
2192         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
2193
2194     return 1;
2195 }
2196
2197 static void get_charset_stats(struct enum_font_data *efd,
2198                               int *ansi_charset, int *symbol_charset,
2199                               int *russian_charset)
2200 {
2201     int i;
2202
2203     *ansi_charset = 0;
2204     *symbol_charset = 0;
2205     *russian_charset = 0;
2206
2207     for (i = 0; i < efd->total; i++)
2208     {
2209         switch (efd->lf[i].lfCharSet)
2210         {
2211         case ANSI_CHARSET:
2212             (*ansi_charset)++;
2213             break;
2214         case SYMBOL_CHARSET:
2215             (*symbol_charset)++;
2216             break;
2217         case RUSSIAN_CHARSET:
2218             (*russian_charset)++;
2219             break;
2220         }
2221     }
2222 }
2223
2224 static void get_charset_statsW(struct enum_font_dataW *efd,
2225                               int *ansi_charset, int *symbol_charset,
2226                               int *russian_charset)
2227 {
2228     int i;
2229
2230     *ansi_charset = 0;
2231     *symbol_charset = 0;
2232     *russian_charset = 0;
2233
2234     for (i = 0; i < efd->total; i++)
2235     {
2236         switch (efd->lf[i].lfCharSet)
2237         {
2238         case ANSI_CHARSET:
2239             (*ansi_charset)++;
2240             break;
2241         case SYMBOL_CHARSET:
2242             (*symbol_charset)++;
2243             break;
2244         case RUSSIAN_CHARSET:
2245             (*russian_charset)++;
2246             break;
2247         }
2248     }
2249 }
2250
2251 static void test_EnumFontFamilies(const char *font_name, INT font_charset)
2252 {
2253     struct enum_font_data efd;
2254     struct enum_font_dataW efdw;
2255     LOGFONT lf;
2256     HDC hdc;
2257     int i, ret, ansi_charset, symbol_charset, russian_charset;
2258
2259     trace("Testing font %s, charset %d\n", *font_name ? font_name : "<empty>", font_charset);
2260
2261     if (*font_name && !is_truetype_font_installed(font_name))
2262     {
2263         skip("%s is not installed\n", font_name);
2264         return;
2265     }
2266
2267     hdc = GetDC(0);
2268
2269     /* Observed behaviour: EnumFontFamilies enumerates aliases like "Arial Cyr"
2270      * while EnumFontFamiliesEx doesn't.
2271      */
2272     if (!*font_name && font_charset == DEFAULT_CHARSET) /* do it only once */
2273     {
2274         /*
2275          * Use EnumFontFamiliesW since win98 crashes when the
2276          *    second parameter is NULL using EnumFontFamilies
2277          */
2278         efdw.total = 0;
2279         SetLastError(0xdeadbeef);
2280         ret = EnumFontFamiliesW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw);
2281         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesW error %u\n", GetLastError());
2282         if(ret)
2283         {
2284             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
2285             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
2286                   ansi_charset, symbol_charset, russian_charset);
2287             ok(efdw.total > 0, "fonts enumerated: NULL\n");
2288             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
2289             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
2290             ok(russian_charset > 0 ||
2291                broken(russian_charset == 0), /* NT4 */
2292                "NULL family should enumerate RUSSIAN_CHARSET\n");
2293         }
2294
2295         efdw.total = 0;
2296         SetLastError(0xdeadbeef);
2297         ret = EnumFontFamiliesExW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw, 0);
2298         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesExW error %u\n", GetLastError());
2299         if(ret)
2300         {
2301             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
2302             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
2303                   ansi_charset, symbol_charset, russian_charset);
2304             ok(efdw.total > 0, "fonts enumerated: NULL\n");
2305             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
2306             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
2307             ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
2308         }
2309     }
2310
2311     efd.total = 0;
2312     SetLastError(0xdeadbeef);
2313     ret = EnumFontFamilies(hdc, font_name, arial_enum_proc, (LPARAM)&efd);
2314     ok(ret, "EnumFontFamilies error %u\n", GetLastError());
2315     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2316     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s\n",
2317           ansi_charset, symbol_charset, russian_charset,
2318           *font_name ? font_name : "<empty>");
2319     if (*font_name)
2320         ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
2321     else
2322         ok(!efd.total, "no fonts should be enumerated for empty font_name\n");
2323     for (i = 0; i < efd.total; i++)
2324     {
2325 /* FIXME: remove completely once Wine is fixed */
2326 if (efd.lf[i].lfCharSet != font_charset)
2327 {
2328 todo_wine
2329     ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2330 }
2331 else
2332         ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2333         ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2334            font_name, efd.lf[i].lfFaceName);
2335     }
2336
2337     memset(&lf, 0, sizeof(lf));
2338     lf.lfCharSet = ANSI_CHARSET;
2339     lstrcpy(lf.lfFaceName, font_name);
2340     efd.total = 0;
2341     SetLastError(0xdeadbeef);
2342     ret = EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2343     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2344     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2345     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s ANSI_CHARSET\n",
2346           ansi_charset, symbol_charset, russian_charset,
2347           *font_name ? font_name : "<empty>");
2348     if (font_charset == SYMBOL_CHARSET)
2349     {
2350         if (*font_name)
2351             ok(efd.total == 0, "no fonts should be enumerated: %s ANSI_CHARSET\n", font_name);
2352         else
2353             ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
2354     }
2355     else
2356     {
2357         ok(efd.total > 0, "no fonts enumerated: %s ANSI_CHARSET\n", font_name);
2358         for (i = 0; i < efd.total; i++)
2359         {
2360             ok(efd.lf[i].lfCharSet == ANSI_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2361             if (*font_name)
2362                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2363                    font_name, efd.lf[i].lfFaceName);
2364         }
2365     }
2366
2367     /* DEFAULT_CHARSET should enumerate all available charsets */
2368     memset(&lf, 0, sizeof(lf));
2369     lf.lfCharSet = DEFAULT_CHARSET;
2370     lstrcpy(lf.lfFaceName, font_name);
2371     efd.total = 0;
2372     SetLastError(0xdeadbeef);
2373     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2374     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2375     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2376     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s DEFAULT_CHARSET\n",
2377           ansi_charset, symbol_charset, russian_charset,
2378           *font_name ? font_name : "<empty>");
2379     ok(efd.total > 0, "no fonts enumerated: %s DEFAULT_CHARSET\n", font_name);
2380     for (i = 0; i < efd.total; i++)
2381     {
2382         if (*font_name)
2383             ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2384                font_name, efd.lf[i].lfFaceName);
2385     }
2386     if (*font_name)
2387     {
2388         switch (font_charset)
2389         {
2390         case ANSI_CHARSET:
2391             ok(ansi_charset > 0,
2392                "ANSI_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
2393             ok(!symbol_charset,
2394                "ANSI_CHARSET should NOT enumerate SYMBOL_CHARSET for %s\n", font_name);
2395             ok(russian_charset > 0,
2396                "ANSI_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
2397             break;
2398         case SYMBOL_CHARSET:
2399             ok(!ansi_charset,
2400                "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", font_name);
2401             ok(symbol_charset,
2402                "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
2403             ok(!russian_charset,
2404                "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", font_name);
2405             break;
2406         case DEFAULT_CHARSET:
2407             ok(ansi_charset > 0,
2408                "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
2409             ok(symbol_charset > 0,
2410                "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
2411             ok(russian_charset > 0,
2412                "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
2413             break;
2414         }
2415     }
2416     else
2417     {
2418         ok(ansi_charset > 0,
2419            "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2420         ok(symbol_charset > 0,
2421            "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2422         ok(russian_charset > 0,
2423            "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2424     }
2425
2426     memset(&lf, 0, sizeof(lf));
2427     lf.lfCharSet = SYMBOL_CHARSET;
2428     lstrcpy(lf.lfFaceName, font_name);
2429     efd.total = 0;
2430     SetLastError(0xdeadbeef);
2431     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2432     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2433     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2434     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s SYMBOL_CHARSET\n",
2435           ansi_charset, symbol_charset, russian_charset,
2436           *font_name ? font_name : "<empty>");
2437     if (*font_name && font_charset == ANSI_CHARSET)
2438         ok(efd.total == 0, "no fonts should be enumerated: %s SYMBOL_CHARSET\n", font_name);
2439     else
2440     {
2441         ok(efd.total > 0, "no fonts enumerated: %s SYMBOL_CHARSET\n", font_name);
2442         for (i = 0; i < efd.total; i++)
2443         {
2444             ok(efd.lf[i].lfCharSet == SYMBOL_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         ok(!ansi_charset,
2451            "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2452         ok(symbol_charset > 0,
2453            "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2454         ok(!russian_charset,
2455            "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2456     }
2457
2458     ReleaseDC(0, hdc);
2459 }
2460
2461 static INT CALLBACK enum_font_data_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
2462 {
2463     struct enum_font_data *efd = (struct enum_font_data *)lParam;
2464
2465     if (type != TRUETYPE_FONTTYPE) return 1;
2466
2467     if (efd->total < MAX_ENUM_FONTS)
2468         efd->lf[efd->total++] = *lf;
2469     else
2470         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
2471
2472     return 1;
2473 }
2474
2475 static INT CALLBACK enum_fullname_data_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
2476 {
2477     struct enum_fullname_data *efnd = (struct enum_fullname_data *)lParam;
2478
2479     if (type != TRUETYPE_FONTTYPE) return 1;
2480
2481     if (efnd->total < MAX_ENUM_FONTS)
2482         efnd->elf[efnd->total++] = *(ENUMLOGFONT*)lf;
2483     else
2484         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
2485
2486     return 1;
2487 }
2488
2489 static void test_EnumFontFamiliesEx_default_charset(void)
2490 {
2491     struct enum_font_data efd;
2492     LOGFONT gui_font, enum_font;
2493     DWORD ret;
2494     HDC hdc;
2495
2496     ret = GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(gui_font), &gui_font);
2497     ok(ret, "GetObject failed.\n");
2498     if (!ret)
2499         return;
2500
2501     efd.total = 0;
2502
2503     hdc = GetDC(0);
2504     memset(&enum_font, 0, sizeof(enum_font));
2505     lstrcpy(enum_font.lfFaceName, gui_font.lfFaceName);
2506     enum_font.lfCharSet = DEFAULT_CHARSET;
2507     EnumFontFamiliesEx(hdc, &enum_font, enum_font_data_proc, (LPARAM)&efd, 0);
2508     ReleaseDC(0, hdc);
2509
2510     if (efd.total == 0) {
2511         skip("'%s' is not found or not a TrueType font.\n", gui_font.lfFaceName);
2512         return;
2513     }
2514     trace("'%s' has %d charsets.\n", gui_font.lfFaceName, efd.total);
2515
2516     ok(efd.lf[0].lfCharSet == gui_font.lfCharSet || broken(system_lang_id == LANG_ARABIC),
2517        "(%s) got charset %d expected %d\n",
2518        efd.lf[0].lfFaceName, efd.lf[0].lfCharSet, gui_font.lfCharSet);
2519
2520     return;
2521 }
2522
2523 static void test_negative_width(HDC hdc, const LOGFONTA *lf)
2524 {
2525     HFONT hfont, hfont_prev;
2526     DWORD ret;
2527     GLYPHMETRICS gm1, gm2;
2528     LOGFONTA lf2 = *lf;
2529     WORD idx;
2530
2531     if(!pGetGlyphIndicesA)
2532         return;
2533
2534     /* negative widths are handled just as positive ones */
2535     lf2.lfWidth = -lf->lfWidth;
2536
2537     SetLastError(0xdeadbeef);
2538     hfont = CreateFontIndirectA(lf);
2539     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2540     check_font("original", lf, hfont);
2541
2542     hfont_prev = SelectObject(hdc, hfont);
2543
2544     ret = pGetGlyphIndicesA(hdc, "x", 1, &idx, GGI_MARK_NONEXISTING_GLYPHS);
2545     if (ret == GDI_ERROR || idx == 0xffff)
2546     {
2547         SelectObject(hdc, hfont_prev);
2548         DeleteObject(hfont);
2549         skip("Font %s doesn't contain 'x', skipping the test\n", lf->lfFaceName);
2550         return;
2551     }
2552
2553     /* filling with 0xaa causes false pass under WINEDEBUG=warn+heap */
2554     memset(&gm1, 0xab, sizeof(gm1));
2555     SetLastError(0xdeadbeef);
2556     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm1, 0, NULL, &mat);
2557     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
2558
2559     SelectObject(hdc, hfont_prev);
2560     DeleteObject(hfont);
2561
2562     SetLastError(0xdeadbeef);
2563     hfont = CreateFontIndirectA(&lf2);
2564     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2565     check_font("negative width", &lf2, hfont);
2566
2567     hfont_prev = SelectObject(hdc, hfont);
2568
2569     memset(&gm2, 0xbb, sizeof(gm2));
2570     SetLastError(0xdeadbeef);
2571     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm2, 0, NULL, &mat);
2572     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
2573
2574     SelectObject(hdc, hfont_prev);
2575     DeleteObject(hfont);
2576
2577     ok(gm1.gmBlackBoxX == gm2.gmBlackBoxX &&
2578        gm1.gmBlackBoxY == gm2.gmBlackBoxY &&
2579        gm1.gmptGlyphOrigin.x == gm2.gmptGlyphOrigin.x &&
2580        gm1.gmptGlyphOrigin.y == gm2.gmptGlyphOrigin.y &&
2581        gm1.gmCellIncX == gm2.gmCellIncX &&
2582        gm1.gmCellIncY == gm2.gmCellIncY,
2583        "gm1=%d,%d,%d,%d,%d,%d gm2=%d,%d,%d,%d,%d,%d\n",
2584        gm1.gmBlackBoxX, gm1.gmBlackBoxY, gm1.gmptGlyphOrigin.x,
2585        gm1.gmptGlyphOrigin.y, gm1.gmCellIncX, gm1.gmCellIncY,
2586        gm2.gmBlackBoxX, gm2.gmBlackBoxY, gm2.gmptGlyphOrigin.x,
2587        gm2.gmptGlyphOrigin.y, gm2.gmCellIncX, gm2.gmCellIncY);
2588 }
2589
2590 /* PANOSE is 10 bytes in size, need to pack the structure properly */
2591 #include "pshpack2.h"
2592 typedef struct
2593 {
2594     USHORT version;
2595     SHORT xAvgCharWidth;
2596     USHORT usWeightClass;
2597     USHORT usWidthClass;
2598     SHORT fsType;
2599     SHORT ySubscriptXSize;
2600     SHORT ySubscriptYSize;
2601     SHORT ySubscriptXOffset;
2602     SHORT ySubscriptYOffset;
2603     SHORT ySuperscriptXSize;
2604     SHORT ySuperscriptYSize;
2605     SHORT ySuperscriptXOffset;
2606     SHORT ySuperscriptYOffset;
2607     SHORT yStrikeoutSize;
2608     SHORT yStrikeoutPosition;
2609     SHORT sFamilyClass;
2610     PANOSE panose;
2611     ULONG ulUnicodeRange1;
2612     ULONG ulUnicodeRange2;
2613     ULONG ulUnicodeRange3;
2614     ULONG ulUnicodeRange4;
2615     CHAR achVendID[4];
2616     USHORT fsSelection;
2617     USHORT usFirstCharIndex;
2618     USHORT usLastCharIndex;
2619     /* According to the Apple spec, original version didn't have the below fields,
2620      * version numbers were taken from the OpenType spec.
2621      */
2622     /* version 0 (TrueType 1.5) */
2623     USHORT sTypoAscender;
2624     USHORT sTypoDescender;
2625     USHORT sTypoLineGap;
2626     USHORT usWinAscent;
2627     USHORT usWinDescent;
2628     /* version 1 (TrueType 1.66) */
2629     ULONG ulCodePageRange1;
2630     ULONG ulCodePageRange2;
2631     /* version 2 (OpenType 1.2) */
2632     SHORT sxHeight;
2633     SHORT sCapHeight;
2634     USHORT usDefaultChar;
2635     USHORT usBreakChar;
2636     USHORT usMaxContext;
2637 } TT_OS2_V2;
2638 #include "poppack.h"
2639
2640 #ifdef WORDS_BIGENDIAN
2641 #define GET_BE_WORD(x) (x)
2642 #define GET_BE_DWORD(x) (x)
2643 #else
2644 #define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
2645 #define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
2646 #endif
2647
2648 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
2649                     ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
2650                     ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
2651 #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
2652 #define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
2653 #define MS_NAME_TAG MS_MAKE_TAG('n','a','m','e')
2654
2655 typedef struct
2656 {
2657     USHORT version;
2658     USHORT num_tables;
2659 } cmap_header;
2660
2661 typedef struct
2662 {
2663     USHORT plat_id;
2664     USHORT enc_id;
2665     ULONG offset;
2666 } cmap_encoding_record;
2667
2668 typedef struct
2669 {
2670     USHORT format;
2671     USHORT length;
2672     USHORT language;
2673
2674     BYTE glyph_ids[256];
2675 } cmap_format_0;
2676
2677 typedef struct
2678 {
2679     USHORT format;
2680     USHORT length;
2681     USHORT language;
2682
2683     USHORT seg_countx2;
2684     USHORT search_range;
2685     USHORT entry_selector;
2686     USHORT range_shift;
2687
2688     USHORT end_count[1]; /* this is a variable-sized array of length seg_countx2 / 2 */
2689 /* Then follows:
2690     USHORT pad;
2691     USHORT start_count[seg_countx2 / 2];
2692     USHORT id_delta[seg_countx2 / 2];
2693     USHORT id_range_offset[seg_countx2 / 2];
2694     USHORT glyph_ids[];
2695 */
2696 } cmap_format_4;
2697
2698 typedef struct
2699 {
2700     USHORT end_count;
2701     USHORT start_count;
2702     USHORT id_delta;
2703     USHORT id_range_offset;
2704 } cmap_format_4_seg;
2705
2706 static void expect_ff(const TEXTMETRICA *tmA, const TT_OS2_V2 *os2, WORD family, const char *name)
2707 {
2708     ok((tmA->tmPitchAndFamily & 0xf0) == family ||
2709        broken(PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH),
2710        "%s: expected family %02x got %02x. panose %d-%d-%d-%d-...\n",
2711        name, family, tmA->tmPitchAndFamily, os2->panose.bFamilyType, os2->panose.bSerifStyle,
2712        os2->panose.bWeight, os2->panose.bProportion);
2713 }
2714
2715 static BOOL get_first_last_from_cmap0(void *ptr, DWORD *first, DWORD *last)
2716 {
2717     int i;
2718     cmap_format_0 *cmap = (cmap_format_0*)ptr;
2719
2720     *first = 256;
2721
2722     for(i = 0; i < 256; i++)
2723     {
2724         if(cmap->glyph_ids[i] == 0) continue;
2725         *last = i;
2726         if(*first == 256) *first = i;
2727     }
2728     if(*first == 256) return FALSE;
2729     return TRUE;
2730 }
2731
2732 static void get_seg4(cmap_format_4 *cmap, USHORT seg_num, cmap_format_4_seg *seg)
2733 {
2734     USHORT segs = GET_BE_WORD(cmap->seg_countx2) / 2;
2735     seg->end_count = GET_BE_WORD(cmap->end_count[seg_num]);
2736     seg->start_count = GET_BE_WORD(cmap->end_count[segs + 1 + seg_num]);
2737     seg->id_delta = GET_BE_WORD(cmap->end_count[2 * segs + 1 + seg_num]);
2738     seg->id_range_offset = GET_BE_WORD(cmap->end_count[3 * segs + 1 + seg_num]);
2739 }
2740
2741 static BOOL get_first_last_from_cmap4(void *ptr, DWORD *first, DWORD *last, DWORD limit)
2742 {
2743     int i;
2744     cmap_format_4 *cmap = (cmap_format_4*)ptr;
2745     USHORT seg_count = GET_BE_WORD(cmap->seg_countx2) / 2;
2746     USHORT const *glyph_ids = cmap->end_count + 4 * seg_count + 1;
2747
2748     *first = 0x10000;
2749
2750     for(i = 0; i < seg_count; i++)
2751     {
2752         DWORD code, index;
2753         cmap_format_4_seg seg;
2754
2755         get_seg4(cmap, i, &seg);
2756         for(code = seg.start_count; code <= seg.end_count; code++)
2757         {
2758             if(seg.id_range_offset == 0)
2759                 index = (seg.id_delta + code) & 0xffff;
2760             else
2761             {
2762                 index = seg.id_range_offset / 2
2763                     + code - seg.start_count
2764                     + i - seg_count;
2765
2766                 /* some fonts have broken last segment */
2767                 if ((char *)(glyph_ids + index + 1) < (char *)ptr + limit)
2768                     index = GET_BE_WORD(glyph_ids[index]);
2769                 else
2770                 {
2771                     trace("segment %04x/%04x index %04x points to nowhere\n",
2772                           seg.start_count, seg.end_count, index);
2773                     index = 0;
2774                 }
2775                 if(index) index += seg.id_delta;
2776             }
2777             if(*first == 0x10000)
2778                 *last = *first = code;
2779             else if(index)
2780                 *last = code;
2781         }
2782     }
2783
2784     if(*first == 0x10000) return FALSE;
2785     return TRUE;
2786 }
2787
2788 static void *get_cmap(cmap_header *header, USHORT plat_id, USHORT enc_id)
2789 {
2790     USHORT i;
2791     cmap_encoding_record *record = (cmap_encoding_record *)(header + 1);
2792
2793     for(i = 0; i < GET_BE_WORD(header->num_tables); i++)
2794     {
2795         if(GET_BE_WORD(record->plat_id) == plat_id && GET_BE_WORD(record->enc_id) == enc_id)
2796             return (BYTE *)header + GET_BE_DWORD(record->offset);
2797         record++;
2798     }
2799     return NULL;
2800 }
2801
2802 typedef enum
2803 {
2804     cmap_none,
2805     cmap_ms_unicode,
2806     cmap_ms_symbol
2807 } cmap_type;
2808
2809 static BOOL get_first_last_from_cmap(HDC hdc, DWORD *first, DWORD *last, cmap_type *cmap_type)
2810 {
2811     LONG size, ret;
2812     cmap_header *header;
2813     void *cmap;
2814     BOOL r = FALSE;
2815     WORD format;
2816
2817     size = GetFontData(hdc, MS_CMAP_TAG, 0, NULL, 0);
2818     ok(size != GDI_ERROR, "no cmap table found\n");
2819     if(size == GDI_ERROR) return FALSE;
2820
2821     header = HeapAlloc(GetProcessHeap(), 0, size);
2822     ret = GetFontData(hdc, MS_CMAP_TAG, 0, header, size);
2823     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2824     ok(GET_BE_WORD(header->version) == 0, "got cmap version %d\n", GET_BE_WORD(header->version));
2825
2826     cmap = get_cmap(header, 3, 1);
2827     if(cmap)
2828         *cmap_type = cmap_ms_unicode;
2829     else
2830     {
2831         cmap = get_cmap(header, 3, 0);
2832         if(cmap) *cmap_type = cmap_ms_symbol;
2833     }
2834     if(!cmap)
2835     {
2836         *cmap_type = cmap_none;
2837         goto end;
2838     }
2839
2840     format = GET_BE_WORD(*(WORD *)cmap);
2841     switch(format)
2842     {
2843     case 0:
2844         r = get_first_last_from_cmap0(cmap, first, last);
2845         break;
2846     case 4:
2847         r = get_first_last_from_cmap4(cmap, first, last, size);
2848         break;
2849     default:
2850         trace("unhandled cmap format %d\n", format);
2851         break;
2852     }
2853
2854 end:
2855     HeapFree(GetProcessHeap(), 0, header);
2856     return r;
2857 }
2858
2859 #define TT_PLATFORM_MICROSOFT 3
2860 #define TT_MS_ID_SYMBOL_CS 0
2861 #define TT_MS_ID_UNICODE_CS 1
2862 #define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409
2863 #define TT_NAME_ID_FONT_FAMILY 1
2864 #define TT_NAME_ID_FONT_SUBFAMILY 2
2865 #define TT_NAME_ID_UNIQUE_ID 3
2866 #define TT_NAME_ID_FULL_NAME 4
2867
2868 static BOOL get_ttf_nametable_entry(HDC hdc, WORD name_id, WCHAR *out_buf, SIZE_T out_size, LCID language_id)
2869 {
2870     struct sfnt_name_header
2871     {
2872         USHORT format;
2873         USHORT number_of_record;
2874         USHORT storage_offset;
2875     } *header;
2876     struct sfnt_name
2877     {
2878         USHORT platform_id;
2879         USHORT encoding_id;
2880         USHORT language_id;
2881         USHORT name_id;
2882         USHORT length;
2883         USHORT offset;
2884     } *entry;
2885     BOOL r = FALSE;
2886     LONG size, offset, length;
2887     LONG c, ret;
2888     WCHAR *name;
2889     BYTE *data;
2890     USHORT i;
2891
2892     size = GetFontData(hdc, MS_NAME_TAG, 0, NULL, 0);
2893     ok(size != GDI_ERROR, "no name table found\n");
2894     if(size == GDI_ERROR) return FALSE;
2895
2896     data = HeapAlloc(GetProcessHeap(), 0, size);
2897     ret = GetFontData(hdc, MS_NAME_TAG, 0, data, size);
2898     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2899
2900     header = (void *)data;
2901     header->format = GET_BE_WORD(header->format);
2902     header->number_of_record = GET_BE_WORD(header->number_of_record);
2903     header->storage_offset = GET_BE_WORD(header->storage_offset);
2904     if (header->format != 0)
2905     {
2906         trace("got format %u\n", header->format);
2907         goto out;
2908     }
2909     if (header->number_of_record == 0 || sizeof(*header) + header->number_of_record * sizeof(*entry) > size)
2910     {
2911         trace("number records out of range: %d\n", header->number_of_record);
2912         goto out;
2913     }
2914     if (header->storage_offset >= size)
2915     {
2916         trace("storage_offset %u > size %u\n", header->storage_offset, size);
2917         goto out;
2918     }
2919
2920     entry = (void *)&header[1];
2921     for (i = 0; i < header->number_of_record; i++)
2922     {
2923         if (GET_BE_WORD(entry[i].platform_id) != TT_PLATFORM_MICROSOFT ||
2924             (GET_BE_WORD(entry[i].encoding_id) != TT_MS_ID_UNICODE_CS && GET_BE_WORD(entry[i].encoding_id) != TT_MS_ID_SYMBOL_CS) ||
2925             GET_BE_WORD(entry[i].language_id) != language_id ||
2926             GET_BE_WORD(entry[i].name_id) != name_id)
2927         {
2928             continue;
2929         }
2930
2931         offset = header->storage_offset + GET_BE_WORD(entry[i].offset);
2932         length = GET_BE_WORD(entry[i].length);
2933         if (offset + length > size)
2934         {
2935             trace("entry %d is out of range\n", i);
2936             break;
2937         }
2938         if (length >= out_size)
2939         {
2940             trace("buffer too small for entry %d\n", i);
2941             break;
2942         }
2943
2944         name = (WCHAR *)(data + offset);
2945         for (c = 0; c < length / 2; c++)
2946             out_buf[c] = GET_BE_WORD(name[c]);
2947         out_buf[c] = 0;
2948
2949         r = TRUE;
2950         break;
2951     }
2952
2953 out:
2954     HeapFree(GetProcessHeap(), 0, data);
2955     return r;
2956 }
2957
2958 static void test_text_metrics(const LOGFONT *lf, const NEWTEXTMETRIC *ntm)
2959 {
2960     HDC hdc;
2961     HFONT hfont, hfont_old;
2962     TEXTMETRICA tmA;
2963     TT_OS2_V2 tt_os2;
2964     LONG size, ret;
2965     const char *font_name = lf->lfFaceName;
2966     DWORD cmap_first = 0, cmap_last = 0;
2967     UINT ascent, descent, cell_height;
2968     cmap_type cmap_type;
2969     BOOL sys_lang_non_english;
2970
2971     sys_lang_non_english = PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH;
2972     hdc = GetDC(0);
2973
2974     SetLastError(0xdeadbeef);
2975     hfont = CreateFontIndirectA(lf);
2976     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2977
2978     hfont_old = SelectObject(hdc, hfont);
2979
2980     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
2981     if (size == GDI_ERROR)
2982     {
2983         trace("OS/2 chunk was not found\n");
2984         goto end_of_test;
2985     }
2986     if (size > sizeof(tt_os2))
2987     {
2988         trace("got too large OS/2 chunk of size %u\n", size);
2989         size = sizeof(tt_os2);
2990     }
2991
2992     memset(&tt_os2, 0, sizeof(tt_os2));
2993     ret = GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size);
2994     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2995
2996     ascent = GET_BE_WORD(tt_os2.usWinAscent);
2997     descent = GET_BE_WORD(tt_os2.usWinDescent);
2998     cell_height = ascent + descent;
2999     ok(ntm->ntmCellHeight == cell_height, "%s: ntmCellHeight %u != %u, os2.usWinAscent/os2.usWinDescent %u/%u\n",
3000        font_name, ntm->ntmCellHeight, cell_height, ascent, descent);
3001
3002     SetLastError(0xdeadbeef);
3003     ret = GetTextMetricsA(hdc, &tmA);
3004     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
3005
3006     if(!get_first_last_from_cmap(hdc, &cmap_first, &cmap_last, &cmap_type))
3007     {
3008         skip("Unable to retrieve first and last glyphs from cmap\n");
3009     }
3010     else
3011     {
3012         USHORT expect_first_A, expect_last_A, expect_break_A, expect_default_A;
3013         USHORT expect_first_W, expect_last_W, expect_break_W, expect_default_W;
3014         UINT os2_first_char, os2_last_char, default_char, break_char;
3015         USHORT version;
3016         TEXTMETRICW tmW;
3017
3018         version = GET_BE_WORD(tt_os2.version);
3019
3020         os2_first_char = GET_BE_WORD(tt_os2.usFirstCharIndex);
3021         os2_last_char = GET_BE_WORD(tt_os2.usLastCharIndex);
3022         default_char = GET_BE_WORD(tt_os2.usDefaultChar);
3023         break_char = GET_BE_WORD(tt_os2.usBreakChar);
3024
3025         trace("font %s charset %u: %x-%x (%x-%x) default %x break %x OS/2 version %u vendor %4.4s\n",
3026               font_name, lf->lfCharSet, os2_first_char, os2_last_char, cmap_first, cmap_last,
3027               default_char, break_char, version, (LPCSTR)&tt_os2.achVendID);
3028
3029         if (cmap_type == cmap_ms_symbol || (cmap_first >= 0xf000 && cmap_first < 0xf100))
3030         {
3031             expect_first_W    = 0;
3032             switch(GetACP())
3033             {
3034             case 1257:  /* Baltic */
3035                 expect_last_W = 0xf8fd;
3036                 break;
3037             default:
3038                 expect_last_W = 0xf0ff;
3039             }
3040             expect_break_W    = 0x20;
3041             expect_default_W  = expect_break_W - 1;
3042             expect_first_A    = 0x1e;
3043             expect_last_A     = min(os2_last_char - os2_first_char + 0x20, 0xff);
3044         }
3045         else
3046         {
3047             expect_first_W    = cmap_first;
3048             expect_last_W     = min(cmap_last, os2_last_char);
3049             if(os2_first_char <= 1)
3050                 expect_break_W = os2_first_char + 2;
3051             else if(os2_first_char > 0xff)
3052                 expect_break_W = 0x20;
3053             else
3054                 expect_break_W = os2_first_char;
3055             expect_default_W  = expect_break_W - 1;
3056             expect_first_A    = expect_default_W - 1;
3057             expect_last_A     = min(expect_last_W, 0xff);
3058         }
3059         expect_break_A    = expect_break_W;
3060         expect_default_A  = expect_default_W;
3061
3062         /* Wine currently uses SYMBOL_CHARSET to identify whether the ANSI metrics need special handling */
3063         if(cmap_type != cmap_ms_symbol && tmA.tmCharSet == SYMBOL_CHARSET && expect_first_A != 0x1e)
3064             todo_wine ok(tmA.tmFirstChar == expect_first_A ||
3065                          tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
3066                          "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
3067         else
3068             ok(tmA.tmFirstChar == expect_first_A ||
3069                tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
3070                "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
3071         if (pGdiGetCodePage == NULL || ! IsDBCSLeadByteEx(pGdiGetCodePage(hdc), tmA.tmLastChar))
3072             ok(tmA.tmLastChar == expect_last_A ||
3073                tmA.tmLastChar == 0xff /* win9x */,
3074                "A: tmLastChar for %s got %02x expected %02x\n", font_name, tmA.tmLastChar, expect_last_A);
3075         else
3076            skip("tmLastChar is DBCS lead byte\n");
3077         ok(tmA.tmBreakChar == expect_break_A, "A: tmBreakChar for %s got %02x expected %02x\n",
3078            font_name, tmA.tmBreakChar, expect_break_A);
3079         ok(tmA.tmDefaultChar == expect_default_A || broken(sys_lang_non_english),
3080            "A: tmDefaultChar for %s got %02x expected %02x\n",
3081            font_name, tmA.tmDefaultChar, expect_default_A);
3082
3083
3084         SetLastError(0xdeadbeef);
3085         ret = GetTextMetricsW(hdc, &tmW);
3086         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
3087            "GetTextMetricsW error %u\n", GetLastError());
3088         if (ret)
3089         {
3090             /* Wine uses the os2 first char */
3091             if(cmap_first != os2_first_char && cmap_type != cmap_ms_symbol)
3092                 todo_wine ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
3093                              font_name, tmW.tmFirstChar, expect_first_W);
3094             else
3095                 ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
3096                    font_name, tmW.tmFirstChar, expect_first_W);
3097
3098             /* Wine uses the os2 last char */
3099             if(expect_last_W != os2_last_char && cmap_type != cmap_ms_symbol)
3100                 todo_wine ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
3101                              font_name, tmW.tmLastChar, expect_last_W);
3102             else
3103                 ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
3104                    font_name, tmW.tmLastChar, expect_last_W);
3105             ok(tmW.tmBreakChar == expect_break_W, "W: tmBreakChar for %s got %02x expected %02x\n",
3106                font_name, tmW.tmBreakChar, expect_break_W);
3107             ok(tmW.tmDefaultChar == expect_default_W || broken(sys_lang_non_english),
3108                "W: tmDefaultChar for %s got %02x expected %02x\n",
3109                font_name, tmW.tmDefaultChar, expect_default_W);
3110
3111             /* Test the aspect ratio while we have tmW */
3112             ret = GetDeviceCaps(hdc, LOGPIXELSX);
3113             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectX %u != %u\n",
3114                tmW.tmDigitizedAspectX, ret);
3115             ret = GetDeviceCaps(hdc, LOGPIXELSY);
3116             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectY %u != %u\n",
3117                tmW.tmDigitizedAspectX, ret);
3118         }
3119     }
3120
3121     /* test FF_ values */
3122     switch(tt_os2.panose.bFamilyType)
3123     {
3124     case PAN_ANY:
3125     case PAN_NO_FIT:
3126     case PAN_FAMILY_TEXT_DISPLAY:
3127     case PAN_FAMILY_PICTORIAL:
3128     default:
3129         if((tmA.tmPitchAndFamily & 1) == 0 || /* fixed */
3130            tt_os2.panose.bProportion == PAN_PROP_MONOSPACED)
3131         {
3132             expect_ff(&tmA, &tt_os2, FF_MODERN, font_name);
3133             break;
3134         }
3135         switch(tt_os2.panose.bSerifStyle)
3136         {
3137         case PAN_ANY:
3138         case PAN_NO_FIT:
3139         default:
3140             expect_ff(&tmA, &tt_os2, FF_DONTCARE, font_name);
3141             break;
3142
3143         case PAN_SERIF_COVE:
3144         case PAN_SERIF_OBTUSE_COVE:
3145         case PAN_SERIF_SQUARE_COVE:
3146         case PAN_SERIF_OBTUSE_SQUARE_COVE:
3147         case PAN_SERIF_SQUARE:
3148         case PAN_SERIF_THIN:
3149         case PAN_SERIF_BONE:
3150         case PAN_SERIF_EXAGGERATED:
3151         case PAN_SERIF_TRIANGLE:
3152             expect_ff(&tmA, &tt_os2, FF_ROMAN, font_name);
3153             break;
3154
3155         case PAN_SERIF_NORMAL_SANS:
3156         case PAN_SERIF_OBTUSE_SANS:
3157         case PAN_SERIF_PERP_SANS:
3158         case PAN_SERIF_FLARED:
3159         case PAN_SERIF_ROUNDED:
3160             expect_ff(&tmA, &tt_os2, FF_SWISS, font_name);
3161             break;
3162         }
3163         break;
3164
3165     case PAN_FAMILY_SCRIPT:
3166         expect_ff(&tmA, &tt_os2, FF_SCRIPT, font_name);
3167         break;
3168
3169     case PAN_FAMILY_DECORATIVE:
3170         expect_ff(&tmA, &tt_os2, FF_DECORATIVE, font_name);
3171         break;
3172     }
3173
3174     test_negative_width(hdc, lf);
3175
3176 end_of_test:
3177     SelectObject(hdc, hfont_old);
3178     DeleteObject(hfont);
3179
3180     ReleaseDC(0, hdc);
3181 }
3182
3183 static INT CALLBACK enum_truetype_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
3184 {
3185     INT *enumed = (INT *)lParam;
3186
3187     if (type == TRUETYPE_FONTTYPE)
3188     {
3189         (*enumed)++;
3190         test_text_metrics(lf, (const NEWTEXTMETRIC *)ntm);
3191     }
3192     return 1;
3193 }
3194
3195 static void test_GetTextMetrics(void)
3196 {
3197     LOGFONTA lf;
3198     HDC hdc;
3199     INT enumed;
3200
3201     /* Report only once */
3202     if(!pGetGlyphIndicesA)
3203         win_skip("GetGlyphIndicesA is unavailable, negative width will not be checked\n");
3204
3205     hdc = GetDC(0);
3206
3207     memset(&lf, 0, sizeof(lf));
3208     lf.lfCharSet = DEFAULT_CHARSET;
3209     enumed = 0;
3210     EnumFontFamiliesExA(hdc, &lf, enum_truetype_font_proc, (LPARAM)&enumed, 0);
3211     trace("Tested metrics of %d truetype fonts\n", enumed);
3212
3213     ReleaseDC(0, hdc);
3214 }
3215
3216 static void test_nonexistent_font(void)
3217 {
3218     static const struct
3219     {
3220         const char *name;
3221         int charset;
3222     } font_subst[] =
3223     {
3224         { "Times New Roman Baltic", 186 },
3225         { "Times New Roman CE", 238 },
3226         { "Times New Roman CYR", 204 },
3227         { "Times New Roman Greek", 161 },
3228         { "Times New Roman TUR", 162 }
3229     };
3230     LOGFONTA lf;
3231     HDC hdc;
3232     HFONT hfont;
3233     CHARSETINFO csi;
3234     INT cs, expected_cs, i;
3235     char buf[LF_FACESIZE];
3236
3237     if (!is_truetype_font_installed("Arial") ||
3238         !is_truetype_font_installed("Times New Roman"))
3239     {
3240         skip("Arial or Times New Roman not installed\n");
3241         return;
3242     }
3243
3244     expected_cs = GetACP();
3245     if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
3246     {
3247         skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
3248         return;
3249     }
3250     expected_cs = csi.ciCharset;
3251     trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
3252
3253     hdc = GetDC(0);
3254
3255     memset(&lf, 0, sizeof(lf));
3256     lf.lfHeight = 100;
3257     lf.lfWeight = FW_REGULAR;
3258     lf.lfCharSet = ANSI_CHARSET;
3259     lf.lfPitchAndFamily = FF_SWISS;
3260     strcpy(lf.lfFaceName, "Nonexistent font");
3261     hfont = CreateFontIndirectA(&lf);
3262     hfont = SelectObject(hdc, hfont);
3263     GetTextFaceA(hdc, sizeof(buf), buf);
3264     ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
3265     cs = GetTextCharset(hdc);
3266     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
3267     DeleteObject(SelectObject(hdc, hfont));
3268
3269     memset(&lf, 0, sizeof(lf));
3270     lf.lfHeight = -13;
3271     lf.lfWeight = FW_DONTCARE;
3272     strcpy(lf.lfFaceName, "Nonexistent font");
3273     hfont = CreateFontIndirectA(&lf);
3274     hfont = SelectObject(hdc, hfont);
3275     GetTextFaceA(hdc, sizeof(buf), buf);
3276 todo_wine /* Wine uses Arial for all substitutions */
3277     ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ ||
3278        !lstrcmpiA(buf, "MS Serif") || /* Win9x */
3279        !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
3280        "Got %s\n", buf);
3281     cs = GetTextCharset(hdc);
3282     ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d\n", expected_cs, cs);
3283     DeleteObject(SelectObject(hdc, hfont));
3284
3285     memset(&lf, 0, sizeof(lf));
3286     lf.lfHeight = -13;
3287     lf.lfWeight = FW_REGULAR;
3288     strcpy(lf.lfFaceName, "Nonexistent font");
3289     hfont = CreateFontIndirectA(&lf);
3290     hfont = SelectObject(hdc, hfont);
3291     GetTextFaceA(hdc, sizeof(buf), buf);
3292     ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
3293        !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "Got %s\n", buf);
3294     cs = GetTextCharset(hdc);
3295     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
3296     DeleteObject(SelectObject(hdc, hfont));
3297
3298     memset(&lf, 0, sizeof(lf));
3299     lf.lfHeight = -13;
3300     lf.lfWeight = FW_DONTCARE;
3301     strcpy(lf.lfFaceName, "Times New Roman");
3302     hfont = CreateFontIndirectA(&lf);
3303     hfont = SelectObject(hdc, hfont);
3304     GetTextFaceA(hdc, sizeof(buf), buf);
3305     ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf);
3306     cs = GetTextCharset(hdc);
3307     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
3308     DeleteObject(SelectObject(hdc, hfont));
3309
3310     for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++)
3311     {
3312         memset(&lf, 0, sizeof(lf));
3313         lf.lfHeight = -13;
3314         lf.lfWeight = FW_REGULAR;
3315         strcpy(lf.lfFaceName, font_subst[i].name);
3316         hfont = CreateFontIndirectA(&lf);
3317         hfont = SelectObject(hdc, hfont);
3318         cs = GetTextCharset(hdc);
3319         if (font_subst[i].charset == expected_cs)
3320         {
3321             ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
3322             GetTextFaceA(hdc, sizeof(buf), buf);
3323             ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf);
3324         }
3325         else
3326         {
3327             ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d for font %s\n", cs, font_subst[i].name);
3328             GetTextFaceA(hdc, sizeof(buf), buf);
3329             ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
3330                !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got %s for font %s\n", buf, font_subst[i].name);
3331         }
3332         DeleteObject(SelectObject(hdc, hfont));
3333
3334         memset(&lf, 0, sizeof(lf));
3335         lf.lfHeight = -13;
3336         lf.lfWeight = FW_DONTCARE;
3337         strcpy(lf.lfFaceName, font_subst[i].name);
3338         hfont = CreateFontIndirectA(&lf);
3339         hfont = SelectObject(hdc, hfont);
3340         GetTextFaceA(hdc, sizeof(buf), buf);
3341         ok(!lstrcmpiA(buf, "Arial") /* Wine */ ||
3342            !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ ||
3343            !lstrcmpiA(buf, "MS Serif") /* Win9x */ ||
3344            !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
3345            "got %s for font %s\n", buf, font_subst[i].name);
3346         cs = GetTextCharset(hdc);
3347         ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
3348         DeleteObject(SelectObject(hdc, hfont));
3349     }
3350
3351     ReleaseDC(0, hdc);
3352 }
3353
3354 static void test_GdiRealizationInfo(void)
3355 {
3356     HDC hdc;
3357     DWORD info[4];
3358     BOOL r;
3359     HFONT hfont, hfont_old;
3360     LOGFONTA lf;
3361
3362     if(!pGdiRealizationInfo)
3363     {
3364         win_skip("GdiRealizationInfo not available\n");
3365         return;
3366     }
3367
3368     hdc = GetDC(0);
3369
3370     memset(info, 0xcc, sizeof(info));
3371     r = pGdiRealizationInfo(hdc, info);
3372     ok(r != 0, "ret 0\n");
3373     ok((info[0] & 0xf) == 1, "info[0] = %x for the system font\n", info[0]);
3374     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
3375
3376     if (!is_truetype_font_installed("Arial"))
3377     {
3378         skip("skipping GdiRealizationInfo with truetype font\n");
3379         goto end;
3380     }
3381
3382     memset(&lf, 0, sizeof(lf));
3383     strcpy(lf.lfFaceName, "Arial");
3384     lf.lfHeight = 20;
3385     lf.lfWeight = FW_NORMAL;
3386     hfont = CreateFontIndirectA(&lf);
3387     hfont_old = SelectObject(hdc, hfont);
3388
3389     memset(info, 0xcc, sizeof(info));
3390     r = pGdiRealizationInfo(hdc, info);
3391     ok(r != 0, "ret 0\n");
3392     ok((info[0] & 0xf) == 3, "info[0] = %x for arial\n", info[0]);
3393     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
3394
3395     DeleteObject(SelectObject(hdc, hfont_old));
3396
3397  end:
3398     ReleaseDC(0, hdc);
3399 }
3400
3401 /* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include
3402    the nul in the count of characters copied when the face name buffer is not
3403    NULL, whereas it does if the buffer is NULL.  Further, the Unicode version
3404    always includes it.  */
3405 static void test_GetTextFace(void)
3406 {
3407     static const char faceA[] = "Tahoma";
3408     static const WCHAR faceW[] = {'T','a','h','o','m','a', 0};
3409     LOGFONTA fA = {0};
3410     LOGFONTW fW = {0};
3411     char bufA[LF_FACESIZE];
3412     WCHAR bufW[LF_FACESIZE];
3413     HFONT f, g;
3414     HDC dc;
3415     int n;
3416
3417     if(!is_font_installed("Tahoma"))
3418     {
3419         skip("Tahoma is not installed so skipping this test\n");
3420         return;
3421     }
3422
3423     /* 'A' case.  */
3424     memcpy(fA.lfFaceName, faceA, sizeof faceA);
3425     f = CreateFontIndirectA(&fA);
3426     ok(f != NULL, "CreateFontIndirectA failed\n");
3427
3428     dc = GetDC(NULL);
3429     g = SelectObject(dc, f);
3430     n = GetTextFaceA(dc, sizeof bufA, bufA);
3431     ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n);
3432     ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n");
3433
3434     /* Play with the count arg.  */
3435     bufA[0] = 'x';
3436     n = GetTextFaceA(dc, 0, bufA);
3437     ok(n == 0, "GetTextFaceA returned %d\n", n);
3438     ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]);
3439
3440     bufA[0] = 'x';
3441     n = GetTextFaceA(dc, 1, bufA);
3442     ok(n == 0, "GetTextFaceA returned %d\n", n);
3443     ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]);
3444
3445     bufA[0] = 'x'; bufA[1] = 'y';
3446     n = GetTextFaceA(dc, 2, bufA);
3447     ok(n == 1, "GetTextFaceA returned %d\n", n);
3448     ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n");
3449
3450     n = GetTextFaceA(dc, 0, NULL);
3451     ok(n == sizeof faceA ||
3452        broken(n == 0), /* win98, winMe */
3453        "GetTextFaceA returned %d\n", n);
3454
3455     DeleteObject(SelectObject(dc, g));
3456     ReleaseDC(NULL, dc);
3457
3458     /* 'W' case.  */
3459     memcpy(fW.lfFaceName, faceW, sizeof faceW);
3460     SetLastError(0xdeadbeef);
3461     f = CreateFontIndirectW(&fW);
3462     if (!f && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
3463     {
3464         win_skip("CreateFontIndirectW is not implemented\n");
3465         return;
3466     }
3467     ok(f != NULL, "CreateFontIndirectW failed\n");
3468
3469     dc = GetDC(NULL);
3470     g = SelectObject(dc, f);
3471     n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW);
3472     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
3473     ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
3474
3475     /* Play with the count arg.  */
3476     bufW[0] = 'x';
3477     n = GetTextFaceW(dc, 0, bufW);
3478     ok(n == 0, "GetTextFaceW returned %d\n", n);
3479     ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]);
3480
3481     bufW[0] = 'x';
3482     n = GetTextFaceW(dc, 1, bufW);
3483     ok(n == 1, "GetTextFaceW returned %d\n", n);
3484     ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]);
3485
3486     bufW[0] = 'x'; bufW[1] = 'y';
3487     n = GetTextFaceW(dc, 2, bufW);
3488     ok(n == 2, "GetTextFaceW returned %d\n", n);
3489     ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n");
3490
3491     n = GetTextFaceW(dc, 0, NULL);
3492     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
3493
3494     DeleteObject(SelectObject(dc, g));
3495     ReleaseDC(NULL, dc);
3496 }
3497
3498 static void test_orientation(void)
3499 {
3500     static const char test_str[11] = "Test String";
3501     HDC hdc;
3502     LOGFONTA lf;
3503     HFONT hfont, old_hfont;
3504     SIZE size;
3505
3506     if (!is_truetype_font_installed("Arial"))
3507     {
3508         skip("Arial is not installed\n");
3509         return;
3510     }
3511
3512     hdc = CreateCompatibleDC(0);
3513     memset(&lf, 0, sizeof(lf));
3514     lstrcpyA(lf.lfFaceName, "Arial");
3515     lf.lfHeight = 72;
3516     lf.lfOrientation = lf.lfEscapement = 900;
3517     hfont = create_font("orientation", &lf);
3518     old_hfont = SelectObject(hdc, hfont);
3519     ok(GetTextExtentExPointA(hdc, test_str, sizeof(test_str), 32767, NULL, NULL, &size), "GetTextExtentExPointA failed\n");
3520     ok(near_match(311, size.cx), "cx should be about 311, got %d\n", size.cx);
3521     ok(near_match(75, size.cy), "cy should be about 75, got %d\n", size.cy);
3522     SelectObject(hdc, old_hfont);
3523     DeleteObject(hfont);
3524     DeleteDC(hdc);
3525 }
3526
3527 static void test_oemcharset(void)
3528 {
3529     HDC hdc;
3530     LOGFONTA lf, clf;
3531     HFONT hfont, old_hfont;
3532     int charset;
3533
3534     hdc = CreateCompatibleDC(0);
3535     ZeroMemory(&lf, sizeof(lf));
3536     lf.lfHeight = 12;
3537     lf.lfCharSet = OEM_CHARSET;
3538     lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
3539     lstrcpyA(lf.lfFaceName, "Terminal");
3540     hfont = CreateFontIndirectA(&lf);
3541     old_hfont = SelectObject(hdc, hfont);
3542     charset = GetTextCharset(hdc);
3543 todo_wine
3544     ok(charset == OEM_CHARSET, "expected %d charset, got %d\n", OEM_CHARSET, charset);
3545     hfont = SelectObject(hdc, old_hfont);
3546     GetObjectA(hfont, sizeof(clf), &clf);
3547     ok(!lstrcmpA(clf.lfFaceName, lf.lfFaceName), "expected %s face name, got %s\n", lf.lfFaceName, clf.lfFaceName);
3548     ok(clf.lfPitchAndFamily == lf.lfPitchAndFamily, "expected %x family, got %x\n", lf.lfPitchAndFamily, clf.lfPitchAndFamily);
3549     ok(clf.lfCharSet == lf.lfCharSet, "expected %d charset, got %d\n", lf.lfCharSet, clf.lfCharSet);
3550     ok(clf.lfHeight == lf.lfHeight, "expected %d height, got %d\n", lf.lfHeight, clf.lfHeight);
3551     DeleteObject(hfont);
3552     DeleteDC(hdc);
3553 }
3554
3555 static void test_GetGlyphOutline(void)
3556 {
3557     HDC hdc;
3558     GLYPHMETRICS gm, gm2;
3559     LOGFONTA lf;
3560     HFONT hfont, old_hfont;
3561     INT ret, ret2;
3562     static const struct
3563     {
3564         UINT cs;
3565         UINT a;
3566         UINT w;
3567     } c[] =
3568     {
3569         {ANSI_CHARSET, 0x30, 0x30},
3570         {SHIFTJIS_CHARSET, 0x82a0, 0x3042},
3571         {HANGEUL_CHARSET, 0x8141, 0xac02},
3572         {JOHAB_CHARSET, 0x8446, 0x3135},
3573         {GB2312_CHARSET, 0x8141, 0x4e04},
3574         {CHINESEBIG5_CHARSET, 0xa142, 0x3001}
3575     };
3576     UINT i;
3577
3578     if (!is_truetype_font_installed("Tahoma"))
3579     {
3580         skip("Tahoma is not installed\n");
3581         return;
3582     }
3583
3584     hdc = CreateCompatibleDC(0);
3585     memset(&lf, 0, sizeof(lf));
3586     lf.lfHeight = 72;
3587     lstrcpyA(lf.lfFaceName, "Tahoma");
3588     SetLastError(0xdeadbeef);
3589     hfont = CreateFontIndirectA(&lf);
3590     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
3591     old_hfont = SelectObject(hdc, hfont);
3592
3593     memset(&gm, 0, sizeof(gm));
3594     SetLastError(0xdeadbeef);
3595     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3596     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
3597
3598     memset(&gm, 0, sizeof(gm));
3599     SetLastError(0xdeadbeef);
3600     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
3601     ok(ret == GDI_ERROR, "GetGlyphOutlineA should fail\n");
3602     ok(GetLastError() == 0xdeadbeef ||
3603        GetLastError() == ERROR_INVALID_PARAMETER, /* win98, winMe */
3604        "expected 0xdeadbeef, got %u\n", GetLastError());
3605
3606     memset(&gm, 0, sizeof(gm));
3607     SetLastError(0xdeadbeef);
3608     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3609     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3610         ok(ret != GDI_ERROR, "GetGlyphOutlineW error %u\n", GetLastError());
3611
3612     memset(&gm, 0, sizeof(gm));
3613     SetLastError(0xdeadbeef);
3614     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
3615     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3616     {
3617        ok(ret == GDI_ERROR, "GetGlyphOutlineW should fail\n");
3618        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
3619     }
3620
3621     /* test for needed buffer size request on space char */
3622     memset(&gm, 0, sizeof(gm));
3623     SetLastError(0xdeadbeef);
3624     ret = GetGlyphOutlineW(hdc, ' ', GGO_NATIVE, &gm, 0, NULL, &mat);
3625     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3626         ok(ret == 0, "GetGlyphOutlineW should return 0 buffer size for space char\n");
3627
3628     /* requesting buffer size for space char + error */
3629     memset(&gm, 0, sizeof(gm));
3630     SetLastError(0xdeadbeef);
3631     ret = GetGlyphOutlineW(0, ' ', GGO_NATIVE, &gm, 0, NULL, NULL);
3632     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3633     {
3634        ok(ret == GDI_ERROR, "GetGlyphOutlineW should return GDI_ERROR\n");
3635        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
3636     }
3637
3638     SelectObject(hdc, old_hfont);
3639     DeleteObject(hfont);
3640
3641     for (i = 0; i < sizeof c / sizeof c[0]; ++i)
3642     {
3643         lf.lfFaceName[0] = '\0';
3644         lf.lfCharSet = c[i].cs;
3645         lf.lfPitchAndFamily = 0;
3646         if (EnumFontFamiliesEx(hdc, &lf, create_font_proc, (LPARAM)&hfont, 0))
3647         {
3648             skip("TrueType font for charset %u is not installed\n", c[i].cs);
3649             continue;
3650         }
3651
3652         old_hfont = SelectObject(hdc, hfont);
3653
3654         /* expected to ignore superfluous bytes (sigle-byte character) */
3655         ret = GetGlyphOutlineA(hdc, 0x8041, GGO_BITMAP, &gm, 0, NULL, &mat);
3656         ret2 = GetGlyphOutlineA(hdc, 0x41, GGO_BITMAP, &gm2, 0, NULL, &mat);
3657         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
3658
3659         ret = GetGlyphOutlineA(hdc, 0xcc8041, GGO_BITMAP, &gm, 0, NULL, &mat);
3660         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
3661            "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
3662
3663         /* expected to ignore superfluous bytes (double-byte character) */
3664         ret = GetGlyphOutlineA(hdc, c[i].a, GGO_BITMAP, &gm, 0, NULL, &mat);
3665         ret2 = GetGlyphOutlineA(hdc, c[i].a | 0xdead0000, GGO_BITMAP, &gm2, 0, NULL, &mat);
3666         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
3667            "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
3668
3669         /* expected to match wide-char version results */
3670         ret2 = GetGlyphOutlineW(hdc, c[i].w, GGO_BITMAP, &gm2, 0, NULL, &mat);
3671         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
3672
3673         hfont = SelectObject(hdc, old_hfont);
3674         DeleteObject(hfont);
3675     }
3676
3677     DeleteDC(hdc);
3678 }
3679
3680 /* bug #9995: there is a limit to the character width that can be specified */
3681 static void test_GetTextMetrics2(const char *fontname, int font_height)
3682 {
3683     HFONT of, hf;
3684     HDC hdc;
3685     TEXTMETRICA tm;
3686     BOOL ret;
3687     int ave_width, height, width, ratio, scale;
3688
3689     if (!is_truetype_font_installed( fontname)) {
3690         skip("%s is not installed\n", fontname);
3691         return;
3692     }
3693     hdc = CreateCompatibleDC(0);
3694     ok( hdc != NULL, "CreateCompatibleDC failed\n");
3695     /* select width = 0 */
3696     hf = CreateFontA(font_height, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3697             DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3698             DEFAULT_QUALITY, VARIABLE_PITCH,
3699             fontname);
3700     ok( hf != NULL, "CreateFontA(%s, %d) failed\n", fontname, font_height);
3701     of = SelectObject( hdc, hf);
3702     ret = GetTextMetricsA( hdc, &tm);
3703     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
3704     height = tm.tmHeight;
3705     ave_width = tm.tmAveCharWidth;
3706     SelectObject( hdc, of);
3707     DeleteObject( hf);
3708
3709     trace("height %d, ave width %d\n", height, ave_width);
3710
3711     for (width = ave_width * 2; /* nothing*/; width += ave_width)
3712     {
3713         hf = CreateFont(height, width, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3714                         DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3715                         DEFAULT_QUALITY, VARIABLE_PITCH, fontname);
3716         ok(hf != 0, "CreateFont failed\n");
3717         of = SelectObject(hdc, hf);
3718         ret = GetTextMetrics(hdc, &tm);
3719         ok(ret, "GetTextMetrics error %u\n", GetLastError());
3720         SelectObject(hdc, of);
3721         DeleteObject(hf);
3722
3723         if (match_off_by_1(tm.tmAveCharWidth, ave_width) || width / height > 200)
3724             break;
3725     }
3726
3727     DeleteDC(hdc);
3728
3729     ratio = width / height;
3730     scale = width / ave_width;
3731
3732     trace("max width/height ratio (%d / %d) %d, max width scale (%d / %d) %d\n",
3733           width, height, ratio, width, ave_width, scale);
3734
3735     ok(ratio >= 90 && ratio <= 110, "expected width/height ratio 90-110, got %d\n", ratio);
3736 }
3737
3738 static void test_CreateFontIndirect(void)
3739 {
3740     LOGFONTA lf, getobj_lf;
3741     int ret, i;
3742     HFONT hfont;
3743     char TestName[][16] = {"Arial", "Arial Bold", "Arial Italic", "Arial Baltic"};
3744
3745     memset(&lf, 0, sizeof(lf));
3746     lf.lfCharSet = ANSI_CHARSET;
3747     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
3748     lf.lfHeight = 16;
3749     lf.lfWidth = 16;
3750     lf.lfQuality = DEFAULT_QUALITY;
3751     lf.lfItalic = FALSE;
3752     lf.lfWeight = FW_DONTCARE;
3753
3754     for (i = 0; i < sizeof(TestName)/sizeof(TestName[0]); i++)
3755     {
3756         lstrcpyA(lf.lfFaceName, TestName[i]);
3757         hfont = CreateFontIndirectA(&lf);
3758         ok(hfont != 0, "CreateFontIndirectA failed\n");
3759         SetLastError(0xdeadbeef);
3760         ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf);
3761         ok(ret, "GetObject failed: %d\n", GetLastError());
3762         ok(lf.lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf.lfItalic, getobj_lf.lfItalic);
3763         ok(lf.lfWeight == getobj_lf.lfWeight ||
3764            broken((SHORT)lf.lfWeight == getobj_lf.lfWeight), /* win9x */
3765            "lfWeight: expect %08x got %08x\n", lf.lfWeight, getobj_lf.lfWeight);
3766         ok(!lstrcmpA(lf.lfFaceName, getobj_lf.lfFaceName) ||
3767            broken(!memcmp(lf.lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
3768            "font names don't match: %s != %s\n", lf.lfFaceName, getobj_lf.lfFaceName);
3769         DeleteObject(hfont);
3770     }
3771 }
3772
3773 static void test_CreateFontIndirectEx(void)
3774 {
3775     ENUMLOGFONTEXDVA lfex;
3776     HFONT hfont;
3777
3778     if (!pCreateFontIndirectExA)
3779     {
3780         win_skip("CreateFontIndirectExA is not available\n");
3781         return;
3782     }
3783
3784     if (!is_truetype_font_installed("Arial"))
3785     {
3786         skip("Arial is not installed\n");
3787         return;
3788     }
3789
3790     SetLastError(0xdeadbeef);
3791     hfont = pCreateFontIndirectExA(NULL);
3792     ok(hfont == NULL, "got %p\n", hfont);
3793     ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
3794
3795     memset(&lfex, 0, sizeof(lfex));
3796     lstrcpyA(lfex.elfEnumLogfontEx.elfLogFont.lfFaceName, "Arial");
3797     hfont = pCreateFontIndirectExA(&lfex);
3798     ok(hfont != 0, "CreateFontIndirectEx failed\n");
3799     if (hfont)
3800         check_font("Arial", &lfex.elfEnumLogfontEx.elfLogFont, hfont);
3801     DeleteObject(hfont);
3802 }
3803
3804 static void free_font(void *font)
3805 {
3806     UnmapViewOfFile(font);
3807 }
3808
3809 static void *load_font(const char *font_name, DWORD *font_size)
3810 {
3811     char file_name[MAX_PATH];
3812     HANDLE file, mapping;
3813     void *font;
3814
3815     if (!GetWindowsDirectory(file_name, sizeof(file_name))) return NULL;
3816     strcat(file_name, "\\fonts\\");
3817     strcat(file_name, font_name);
3818
3819     file = CreateFile(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
3820     if (file == INVALID_HANDLE_VALUE) return NULL;
3821
3822     *font_size = GetFileSize(file, NULL);
3823
3824     mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
3825     if (!mapping)
3826     {
3827         CloseHandle(file);
3828         return NULL;
3829     }
3830
3831     font = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
3832
3833     CloseHandle(file);
3834     CloseHandle(mapping);
3835     return font;
3836 }
3837
3838 static void test_AddFontMemResource(void)
3839 {
3840     void *font;
3841     DWORD font_size, num_fonts;
3842     HANDLE ret;
3843     BOOL bRet;
3844
3845     if (!pAddFontMemResourceEx || !pRemoveFontMemResourceEx)
3846     {
3847         win_skip("AddFontMemResourceEx is not available on this platform\n");
3848         return;
3849     }
3850
3851     font = load_font("sserife.fon", &font_size);
3852     if (!font)
3853     {
3854         skip("Unable to locate and load font sserife.fon\n");
3855         return;
3856     }
3857
3858     SetLastError(0xdeadbeef);
3859     ret = pAddFontMemResourceEx(NULL, 0, NULL, NULL);
3860     ok(!ret, "AddFontMemResourceEx should fail\n");
3861     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3862        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3863        GetLastError());
3864
3865     SetLastError(0xdeadbeef);
3866     ret = pAddFontMemResourceEx(NULL, 10, NULL, NULL);
3867     ok(!ret, "AddFontMemResourceEx should fail\n");
3868     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3869        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3870        GetLastError());
3871
3872     SetLastError(0xdeadbeef);
3873     ret = pAddFontMemResourceEx(NULL, 0, NULL, &num_fonts);
3874     ok(!ret, "AddFontMemResourceEx should fail\n");
3875     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3876        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3877        GetLastError());
3878
3879     SetLastError(0xdeadbeef);
3880     ret = pAddFontMemResourceEx(NULL, 10, NULL, &num_fonts);
3881     ok(!ret, "AddFontMemResourceEx should fail\n");
3882     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3883        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3884        GetLastError());
3885
3886     SetLastError(0xdeadbeef);
3887     ret = pAddFontMemResourceEx(font, 0, NULL, NULL);
3888     ok(!ret, "AddFontMemResourceEx should fail\n");
3889     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3890        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3891        GetLastError());
3892
3893     SetLastError(0xdeadbeef);
3894     ret = pAddFontMemResourceEx(font, 10, NULL, NULL);
3895     ok(!ret, "AddFontMemResourceEx should fail\n");
3896     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3897        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3898        GetLastError());
3899
3900     num_fonts = 0xdeadbeef;
3901     SetLastError(0xdeadbeef);
3902     ret = pAddFontMemResourceEx(font, 0, NULL, &num_fonts);
3903     ok(!ret, "AddFontMemResourceEx should fail\n");
3904     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3905        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3906        GetLastError());
3907     ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
3908
3909     if (0) /* hangs under windows 2000 */
3910     {
3911         num_fonts = 0xdeadbeef;
3912         SetLastError(0xdeadbeef);
3913         ret = pAddFontMemResourceEx(font, 10, NULL, &num_fonts);
3914         ok(!ret, "AddFontMemResourceEx should fail\n");
3915         ok(GetLastError() == 0xdeadbeef,
3916            "Expected GetLastError() to return 0xdeadbeef, got %u\n",
3917            GetLastError());
3918         ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
3919     }
3920
3921     num_fonts = 0xdeadbeef;
3922     SetLastError(0xdeadbeef);
3923     ret = pAddFontMemResourceEx(font, font_size, NULL, &num_fonts);
3924     ok(ret != 0, "AddFontMemResourceEx error %d\n", GetLastError());
3925     ok(num_fonts != 0xdeadbeef, "number of loaded fonts should not be 0xdeadbeef\n");
3926     ok(num_fonts != 0, "number of loaded fonts should not be 0\n");
3927
3928     free_font(font);
3929
3930     SetLastError(0xdeadbeef);
3931     bRet = pRemoveFontMemResourceEx(ret);
3932     ok(bRet, "RemoveFontMemResourceEx error %d\n", GetLastError());
3933
3934     /* test invalid pointer to number of loaded fonts */
3935     font = load_font("sserife.fon", &font_size);
3936     ok(font != NULL, "Unable to locate and load font sserife.fon\n");
3937
3938     SetLastError(0xdeadbeef);
3939     ret = pAddFontMemResourceEx(font, font_size, NULL, (void *)0xdeadbeef);
3940     ok(!ret, "AddFontMemResourceEx should fail\n");
3941     ok(GetLastError() == 0xdeadbeef,
3942        "Expected GetLastError() to return 0xdeadbeef, got %u\n",
3943        GetLastError());
3944
3945     SetLastError(0xdeadbeef);
3946     ret = pAddFontMemResourceEx(font, font_size, NULL, NULL);
3947     ok(!ret, "AddFontMemResourceEx should fail\n");
3948     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3949        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3950        GetLastError());
3951
3952     free_font(font);
3953 }
3954
3955 static INT CALLBACK enum_fonts_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3956 {
3957     LOGFONT *lf;
3958
3959     if (type != TRUETYPE_FONTTYPE) return 1;
3960
3961     ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
3962
3963     lf = (LOGFONT *)lparam;
3964     *lf = *elf;
3965     return 0;
3966 }
3967
3968 static INT CALLBACK enum_all_fonts_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3969 {
3970     int ret;
3971     LOGFONT *lf;
3972
3973     if (type != TRUETYPE_FONTTYPE) return 1;
3974
3975     lf = (LOGFONT *)lparam;
3976     ret = strcmp(lf->lfFaceName, elf->lfFaceName);
3977     if(ret == 0)
3978     {
3979         ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
3980         *lf = *elf;
3981         return 0;
3982     }
3983     return 1;
3984 }
3985
3986 static INT CALLBACK enum_with_magic_retval_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3987 {
3988     return lparam;
3989 }
3990
3991 static void test_EnumFonts(void)
3992 {
3993     int ret;
3994     LOGFONT lf;
3995     HDC hdc;
3996
3997     if (!is_truetype_font_installed("Arial"))
3998     {
3999         skip("Arial is not installed\n");
4000         return;
4001     }
4002
4003     /* Windows uses localized font face names, so Arial Bold won't be found */
4004     if (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH)
4005     {
4006         skip("User locale is not English, skipping the test\n");
4007         return;
4008     }
4009
4010     hdc = CreateCompatibleDC(0);
4011
4012     /* check that the enumproc's retval is returned */
4013     ret = EnumFontFamilies(hdc, NULL, enum_with_magic_retval_proc, 0xcafe);
4014     ok(ret == 0xcafe, "got %08x\n", ret);
4015
4016     ret = EnumFontFamilies(hdc, "Arial", enum_fonts_proc, (LPARAM)&lf);
4017     ok(!ret, "font Arial is not enumerated\n");
4018     ret = strcmp(lf.lfFaceName, "Arial");
4019     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
4020     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
4021
4022     lstrcpy(lf.lfFaceName, "Arial");
4023     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
4024     ok(!ret, "font Arial is not enumerated\n");
4025     ret = strcmp(lf.lfFaceName, "Arial");
4026     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
4027     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
4028
4029     ret = EnumFontFamilies(hdc, "Arial Bold", enum_fonts_proc, (LPARAM)&lf);
4030     ok(!ret, "font Arial Bold is not enumerated\n");
4031     ret = strcmp(lf.lfFaceName, "Arial");
4032     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
4033     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
4034
4035     lstrcpy(lf.lfFaceName, "Arial Bold");
4036     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
4037     ok(ret, "font Arial Bold should not be enumerated\n");
4038
4039     ret = EnumFontFamilies(hdc, "Arial Bold Italic", enum_fonts_proc, (LPARAM)&lf);
4040     ok(!ret, "font Arial Bold Italic is not enumerated\n");
4041     ret = strcmp(lf.lfFaceName, "Arial");
4042     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
4043     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
4044
4045     lstrcpy(lf.lfFaceName, "Arial Bold Italic");
4046     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
4047     ok(ret, "font Arial Bold Italic should not be enumerated\n");
4048
4049     ret = EnumFontFamilies(hdc, "Arial Italic Bold", enum_fonts_proc, (LPARAM)&lf);
4050     ok(ret, "font Arial Italic Bold  should not be enumerated\n");
4051
4052     lstrcpy(lf.lfFaceName, "Arial Italic Bold");
4053     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
4054     ok(ret, "font Arial Italic Bold should not be enumerated\n");
4055
4056     DeleteDC(hdc);
4057 }
4058
4059 static INT CALLBACK is_font_installed_fullname_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
4060 {
4061     const ENUMLOGFONT *elf = (const ENUMLOGFONT *)lf;
4062     const char *fullname = (const char *)lParam;
4063
4064     if (!strcmp((const char *)elf->elfFullName, fullname)) return 0;
4065
4066     return 1;
4067 }
4068
4069 static BOOL is_font_installed_fullname(const char *family, const char *fullname)
4070 {
4071     HDC hdc = GetDC(0);
4072     BOOL ret = FALSE;
4073
4074     if(!EnumFontFamiliesA(hdc, family, is_font_installed_fullname_proc, (LPARAM)fullname))
4075         ret = TRUE;
4076
4077     ReleaseDC(0, hdc);
4078     return ret;
4079 }
4080
4081 static void test_fullname(void)
4082 {
4083     static const char *TestName[] = {"Lucida Sans Demibold Roman", "Lucida Sans Italic", "Lucida Sans Regular"};
4084     WCHAR bufW[LF_FULLFACESIZE];
4085     char bufA[LF_FULLFACESIZE];
4086     HFONT hfont, of;
4087     LOGFONTA lf;
4088     HDC hdc;
4089     int i;
4090     DWORD ret;
4091
4092     hdc = CreateCompatibleDC(0);
4093     ok(hdc != NULL, "CreateCompatibleDC failed\n");
4094
4095     memset(&lf, 0, sizeof(lf));
4096     lf.lfCharSet = ANSI_CHARSET;
4097     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
4098     lf.lfHeight = 16;
4099     lf.lfWidth = 16;
4100     lf.lfQuality = DEFAULT_QUALITY;
4101     lf.lfItalic = FALSE;
4102     lf.lfWeight = FW_DONTCARE;
4103
4104     for (i = 0; i < sizeof(TestName) / sizeof(TestName[0]); i++)
4105     {
4106         if (!is_font_installed_fullname("Lucida Sans", TestName[i]))
4107         {
4108             skip("%s is not installed\n", TestName[i]);
4109             continue;
4110         }
4111
4112         lstrcpyA(lf.lfFaceName, TestName[i]);
4113         hfont = CreateFontIndirectA(&lf);
4114         ok(hfont != 0, "CreateFontIndirectA failed\n");
4115
4116         of = SelectObject(hdc, hfont);
4117         bufW[0] = 0;
4118         bufA[0] = 0;
4119         ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FULL_NAME, bufW, sizeof(bufW), TT_MS_LANGID_ENGLISH_UNITED_STATES);
4120         ok(ret, "face full name could not be read\n");
4121         WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, sizeof(bufA), NULL, FALSE);
4122         ok(!lstrcmpA(bufA, TestName[i]), "font full names don't match: %s != %s\n", TestName[i], bufA);
4123         SelectObject(hdc, of);
4124         DeleteObject(hfont);
4125     }
4126     DeleteDC(hdc);
4127 }
4128
4129 static WCHAR *prepend_at(WCHAR *family)
4130 {
4131     if (!family)
4132         return NULL;
4133
4134     memmove(family + 1, family, (lstrlenW(family) + 1) * sizeof(WCHAR));
4135     family[0] = '@';
4136     return family;
4137 }
4138
4139 static void test_fullname2_helper(const char *Family)
4140 {
4141     char *FamilyName, *FaceName, *StyleName, *otmStr;
4142     struct enum_fullname_data efnd;
4143     WCHAR *bufW;
4144     char *bufA;
4145     HFONT hfont, of;
4146     LOGFONTA lf;
4147     HDC hdc;
4148     int i;
4149     DWORD otm_size, ret, buf_size;
4150     OUTLINETEXTMETRICA *otm;
4151     BOOL want_vertical, get_vertical;
4152     want_vertical = ( Family[0] == '@' );
4153
4154     hdc = CreateCompatibleDC(0);
4155     ok(hdc != NULL, "CreateCompatibleDC failed\n");
4156
4157     memset(&lf, 0, sizeof(lf));
4158     lf.lfCharSet = DEFAULT_CHARSET;
4159     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
4160     lf.lfHeight = 16;
4161     lf.lfWidth = 16;
4162     lf.lfQuality = DEFAULT_QUALITY;
4163     lf.lfItalic = FALSE;
4164     lf.lfWeight = FW_DONTCARE;
4165     lstrcpy(lf.lfFaceName, Family);
4166     efnd.total = 0;
4167     EnumFontFamiliesExA(hdc, &lf, enum_fullname_data_proc, (LPARAM)&efnd, 0);
4168     if (efnd.total == 0)
4169         skip("%s is not installed\n", lf.lfFaceName);
4170
4171     for (i = 0; i < efnd.total; i++)
4172     {
4173         FamilyName = (char *)efnd.elf[i].elfLogFont.lfFaceName;
4174         FaceName = (char *)efnd.elf[i].elfFullName;
4175         StyleName = (char *)efnd.elf[i].elfStyle;
4176
4177         trace("Checking font %s:\nFamilyName: %s; FaceName: %s; StyleName: %s\n", Family, FamilyName, FaceName, StyleName);
4178
4179         get_vertical = ( FamilyName[0] == '@' );
4180         ok(get_vertical == want_vertical, "Vertical flags don't match: %s %s\n", Family, FamilyName);
4181
4182         lstrcpyA(lf.lfFaceName, FaceName);
4183         hfont = CreateFontIndirectA(&lf);
4184         ok(hfont != 0, "CreateFontIndirectA failed\n");
4185
4186         of = SelectObject(hdc, hfont);
4187         buf_size = GetFontData(hdc, MS_NAME_TAG, 0, NULL, 0);
4188         ok(buf_size != GDI_ERROR, "no name table found\n");
4189         if (buf_size == GDI_ERROR) continue;
4190
4191         bufW = HeapAlloc(GetProcessHeap(), 0, buf_size);
4192         bufA = HeapAlloc(GetProcessHeap(), 0, buf_size);
4193
4194         otm_size = GetOutlineTextMetricsA(hdc, 0, NULL);
4195         otm = HeapAlloc(GetProcessHeap(), 0, otm_size);
4196         memset(otm, 0, otm_size);
4197         ret = GetOutlineTextMetrics(hdc, otm_size, otm);
4198         ok(ret != 0, "GetOutlineTextMetrics fails!\n");
4199         if (ret == 0) continue;
4200
4201         bufW[0] = 0;
4202         bufA[0] = 0;
4203         ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FONT_FAMILY, bufW, buf_size, GetSystemDefaultLangID());
4204         if (!ret)
4205         {
4206             trace("no localized FONT_FAMILY found.\n");
4207             ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FONT_FAMILY, bufW, buf_size, TT_MS_LANGID_ENGLISH_UNITED_STATES);
4208         }
4209         ok(ret, "FAMILY (family name) could not be read\n");
4210         if (want_vertical) bufW = prepend_at(bufW);
4211         WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
4212         ok(!lstrcmpA(FamilyName, bufA), "font family names don't match: returned %s, expect %s\n", FamilyName, bufA);
4213         otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpFamilyName;
4214         ok(!lstrcmpA(FamilyName, otmStr), "FamilyName %s doesn't match otmpFamilyName %s\n", FamilyName, otmStr);
4215
4216         bufW[0] = 0;
4217         bufA[0] = 0;
4218         ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FULL_NAME, bufW, buf_size, GetSystemDefaultLangID());
4219         if (!ret)
4220         {
4221             trace("no localized FULL_NAME found.\n");
4222             ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FULL_NAME, bufW, buf_size, TT_MS_LANGID_ENGLISH_UNITED_STATES);
4223         }
4224         ok(ret, "FULL_NAME (face name) could not be read\n");
4225         if (want_vertical) bufW = prepend_at(bufW);
4226         WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
4227         ok(!lstrcmpA(FaceName, bufA), "font face names don't match: returned %s, expect %s\n", FaceName, bufA);
4228         otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpFaceName;
4229         ok(!lstrcmpA(FaceName, otmStr), "FaceName %s doesn't match otmpFaceName %s\n", FaceName, otmStr);
4230
4231         bufW[0] = 0;
4232         bufA[0] = 0;
4233         ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FONT_SUBFAMILY, bufW, buf_size, GetSystemDefaultLangID());
4234         if (!ret)
4235         {
4236             trace("no localized FONT_SUBFAMILY found.\n");
4237             ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FONT_SUBFAMILY, bufW, buf_size, TT_MS_LANGID_ENGLISH_UNITED_STATES);
4238         }
4239         ok(ret, "SUBFAMILY (style name) could not be read\n");
4240         WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
4241         ok(!lstrcmpA(StyleName, bufA), "style names don't match: returned %s, expect %s\n", StyleName, bufA);
4242         otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpStyleName;
4243         ok(!lstrcmpA(StyleName, otmStr), "StyleName %s doesn't match otmpStyleName %s\n", StyleName, otmStr);
4244
4245         bufW[0] = 0;
4246         bufA[0] = 0;
4247         ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_UNIQUE_ID, bufW, buf_size, GetSystemDefaultLangID());
4248         if (!ret)
4249         {
4250             trace("no localized UNIQUE_ID found.\n");
4251             ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_UNIQUE_ID, bufW, buf_size, TT_MS_LANGID_ENGLISH_UNITED_STATES);
4252         }
4253         ok(ret, "UNIQUE_ID (full name) could not be read\n");
4254         WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
4255         otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpFullName;
4256         ok(!lstrcmpA(otmStr, bufA), "UNIQUE ID (full name) doesn't match: returned %s, expect %s\n", otmStr, bufA);
4257
4258         SelectObject(hdc, of);
4259         DeleteObject(hfont);
4260
4261         HeapFree(GetProcessHeap(), 0, otm);
4262         HeapFree(GetProcessHeap(), 0, bufW);
4263         HeapFree(GetProcessHeap(), 0, bufA);
4264     }
4265     DeleteDC(hdc);
4266 }
4267
4268 static void test_fullname2(void)
4269 {
4270     test_fullname2_helper("Arial");
4271     test_fullname2_helper("DejaVu Sans");
4272     test_fullname2_helper("Lucida Sans");
4273     test_fullname2_helper("Tahoma");
4274     test_fullname2_helper("Webdings");
4275     test_fullname2_helper("Wingdings");
4276     test_fullname2_helper("SimSun");
4277     test_fullname2_helper("NSimSun");
4278     test_fullname2_helper("MingLiu");
4279     test_fullname2_helper("PMingLiu");
4280     test_fullname2_helper("WenQuanYi Micro Hei");
4281     test_fullname2_helper("MS UI Gothic");
4282     test_fullname2_helper("Ume UI Gothic");
4283     test_fullname2_helper("MS Gothic");
4284     test_fullname2_helper("Ume Gothic");
4285     test_fullname2_helper("MS PGothic");
4286     test_fullname2_helper("Ume P Gothic");
4287     test_fullname2_helper("Gulim");
4288     test_fullname2_helper("Batang");
4289     test_fullname2_helper("UnBatang");
4290     test_fullname2_helper("UnDotum");
4291     test_fullname2_helper("@SimSun");
4292     test_fullname2_helper("@NSimSun");
4293     test_fullname2_helper("@MingLiu");
4294     test_fullname2_helper("@PMingLiu");
4295     test_fullname2_helper("@WenQuanYi Micro Hei");
4296     test_fullname2_helper("@MS UI Gothic");
4297     test_fullname2_helper("@Ume UI Gothic");
4298     test_fullname2_helper("@MS Gothic");
4299     test_fullname2_helper("@Ume Gothic");
4300     test_fullname2_helper("@MS PGothic");
4301     test_fullname2_helper("@Ume P Gothic");
4302     test_fullname2_helper("@Gulim");
4303     test_fullname2_helper("@Batang");
4304     test_fullname2_helper("@UnBatang");
4305     test_fullname2_helper("@UnDotum");
4306
4307 }
4308
4309 static BOOL write_ttf_file(const char *fontname, char *tmp_name)
4310 {
4311     char tmp_path[MAX_PATH];
4312     HRSRC rsrc;
4313     void *rsrc_data;
4314     DWORD rsrc_size;
4315     HANDLE hfile;
4316     BOOL ret;
4317
4318     SetLastError(0xdeadbeef);
4319     rsrc = FindResource(GetModuleHandle(0), fontname, RT_RCDATA);
4320     ok(rsrc != 0, "FindResource error %d\n", GetLastError());
4321     if (!rsrc) return FALSE;
4322     SetLastError(0xdeadbeef);
4323     rsrc_data = LockResource(LoadResource(GetModuleHandle(0), rsrc));
4324     ok(rsrc_data != 0, "LockResource error %d\n", GetLastError());
4325     if (!rsrc_data) return FALSE;
4326     SetLastError(0xdeadbeef);
4327     rsrc_size = SizeofResource(GetModuleHandle(0), rsrc);
4328     ok(rsrc_size != 0, "SizeofResource error %d\n", GetLastError());
4329     if (!rsrc_size) return FALSE;
4330
4331     SetLastError(0xdeadbeef);
4332     ret = GetTempPath(MAX_PATH, tmp_path);
4333     ok(ret, "GetTempPath() error %d\n", GetLastError());
4334     SetLastError(0xdeadbeef);
4335     ret = GetTempFileName(tmp_path, "ttf", 0, tmp_name);
4336     ok(ret, "GetTempFileName() error %d\n", GetLastError());
4337
4338     SetLastError(0xdeadbeef);
4339     hfile = CreateFile(tmp_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
4340     ok(hfile != INVALID_HANDLE_VALUE, "CreateFile() error %d\n", GetLastError());
4341     if (hfile == INVALID_HANDLE_VALUE) return FALSE;
4342
4343     SetLastError(0xdeadbeef);
4344     ret = WriteFile(hfile, rsrc_data, rsrc_size, &rsrc_size, NULL);
4345     ok(ret, "WriteFile() error %d\n", GetLastError());
4346
4347     CloseHandle(hfile);
4348     return ret;
4349 }
4350
4351 static void test_GetGlyphOutline_empty_contour(void)
4352 {
4353     HDC hdc;
4354     LOGFONTA lf;
4355     HFONT hfont, hfont_prev;
4356     TTPOLYGONHEADER *header;
4357     GLYPHMETRICS gm;
4358     char buf[1024];
4359     DWORD ret;
4360
4361     memset(&lf, 0, sizeof(lf));
4362     lf.lfHeight = 72;
4363     lstrcpyA(lf.lfFaceName, "wine_test");
4364
4365     hfont = CreateFontIndirectA(&lf);
4366     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
4367
4368     hdc = GetDC(NULL);
4369
4370     hfont_prev = SelectObject(hdc, hfont);
4371     ok(hfont_prev != NULL, "SelectObject failed\n");
4372
4373     ret = GetGlyphOutlineW(hdc, 0xa8, GGO_NATIVE, &gm, 0, NULL, &mat);
4374     ok(ret == 228, "GetGlyphOutline returned %d, expected 228\n", ret);
4375
4376     header = (TTPOLYGONHEADER*)buf;
4377     ret = GetGlyphOutlineW(hdc, 0xa8, GGO_NATIVE, &gm, sizeof(buf), buf, &mat);
4378     ok(ret == 228, "GetGlyphOutline returned %d, expected 228\n", ret);
4379     ok(header->cb == 36, "header->cb = %d, expected 36\n", header->cb);
4380     ok(header->dwType == TT_POLYGON_TYPE, "header->dwType = %d, expected TT_POLYGON_TYPE\n", header->dwType);
4381     header = (TTPOLYGONHEADER*)((char*)header+header->cb);
4382     ok(header->cb == 96, "header->cb = %d, expected 96\n", header->cb);
4383     header = (TTPOLYGONHEADER*)((char*)header+header->cb);
4384     ok(header->cb == 96, "header->cb = %d, expected 96\n", header->cb);
4385
4386     SelectObject(hdc, hfont_prev);
4387     DeleteObject(hfont);
4388     ReleaseDC(NULL, hdc);
4389 }
4390
4391 static void test_CreateScalableFontResource(void)
4392 {
4393     char ttf_name[MAX_PATH];
4394     char tmp_path[MAX_PATH];
4395     char fot_name[MAX_PATH];
4396     char *file_part;
4397     DWORD ret;
4398
4399     if (!pAddFontResourceExA || !pRemoveFontResourceExA)
4400     {
4401         win_skip("AddFontResourceExA is not available on this platform\n");
4402         return;
4403     }
4404
4405     if (!write_ttf_file("wine_test.ttf", ttf_name))
4406     {
4407         skip("Failed to create ttf file for testing\n");
4408         return;
4409     }
4410
4411     trace("created %s\n", ttf_name);
4412
4413     ret = is_truetype_font_installed("wine_test");
4414     ok(!ret, "font wine_test should not be enumerated\n");
4415
4416     ret = GetTempPath(MAX_PATH, tmp_path);
4417     ok(ret, "GetTempPath() error %d\n", GetLastError());
4418     ret = GetTempFileName(tmp_path, "fot", 0, fot_name);
4419     ok(ret, "GetTempFileName() error %d\n", GetLastError());
4420
4421     ret = GetFileAttributes(fot_name);
4422     ok(ret != INVALID_FILE_ATTRIBUTES, "file %s does not exist\n", fot_name);
4423
4424     SetLastError(0xdeadbeef);
4425     ret = CreateScalableFontResource(0, fot_name, ttf_name, NULL);
4426     ok(!ret, "CreateScalableFontResource() should fail\n");
4427     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
4428
4429     SetLastError(0xdeadbeef);
4430     ret = CreateScalableFontResource(0, fot_name, ttf_name, "");
4431     ok(!ret, "CreateScalableFontResource() should fail\n");
4432     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
4433
4434     file_part = strrchr(ttf_name, '\\');
4435     SetLastError(0xdeadbeef);
4436     ret = CreateScalableFontResource(0, fot_name, file_part, tmp_path);
4437     ok(!ret, "CreateScalableFontResource() should fail\n");
4438     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
4439
4440     SetLastError(0xdeadbeef);
4441     ret = CreateScalableFontResource(0, fot_name, "random file name", tmp_path);
4442     ok(!ret, "CreateScalableFontResource() should fail\n");
4443     ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
4444
4445     SetLastError(0xdeadbeef);
4446     ret = CreateScalableFontResource(0, fot_name, NULL, ttf_name);
4447     ok(!ret, "CreateScalableFontResource() should fail\n");
4448     ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
4449
4450     ret = DeleteFile(fot_name);
4451     ok(ret, "DeleteFile() error %d\n", GetLastError());
4452
4453     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4454     ok(!ret, "RemoveFontResourceEx() should fail\n");
4455
4456     /* test public font resource */
4457     SetLastError(0xdeadbeef);
4458     ret = CreateScalableFontResource(0, fot_name, ttf_name, NULL);
4459     ok(ret, "CreateScalableFontResource() error %d\n", GetLastError());
4460
4461     ret = is_truetype_font_installed("wine_test");
4462     ok(!ret, "font wine_test should not be enumerated\n");
4463
4464     SetLastError(0xdeadbeef);
4465     ret = pAddFontResourceExA(fot_name, 0, 0);
4466     ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
4467
4468     ret = is_truetype_font_installed("wine_test");
4469     ok(ret, "font wine_test should be enumerated\n");
4470
4471     test_GetGlyphOutline_empty_contour();
4472
4473     ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
4474     ok(!ret, "RemoveFontResourceEx() with not matching flags should fail\n");
4475
4476     SetLastError(0xdeadbeef);
4477     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4478     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
4479
4480     ret = is_truetype_font_installed("wine_test");
4481     ok(!ret, "font wine_test should not be enumerated\n");
4482
4483     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4484     ok(!ret, "RemoveFontResourceEx() should fail\n");
4485
4486     DeleteFile(fot_name);
4487
4488     /* test hidden font resource */
4489     SetLastError(0xdeadbeef);
4490     ret = CreateScalableFontResource(1, fot_name, ttf_name, NULL);
4491     ok(ret, "CreateScalableFontResource() error %d\n", GetLastError());
4492
4493     ret = is_truetype_font_installed("wine_test");
4494     ok(!ret, "font wine_test should not be enumerated\n");
4495
4496     SetLastError(0xdeadbeef);
4497     ret = pAddFontResourceExA(fot_name, 0, 0);
4498     ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
4499
4500     ret = is_truetype_font_installed("wine_test");
4501     todo_wine
4502     ok(!ret, "font wine_test should not be enumerated\n");
4503
4504     /* XP allows removing a private font added with 0 flags */
4505     SetLastError(0xdeadbeef);
4506     ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
4507     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
4508
4509     ret = is_truetype_font_installed("wine_test");
4510     ok(!ret, "font wine_test should not be enumerated\n");
4511
4512     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4513     ok(!ret, "RemoveFontResourceEx() should fail\n");
4514
4515     DeleteFile(fot_name);
4516     DeleteFile(ttf_name);
4517 }
4518
4519 static void check_vertical_font(const char *name, BOOL *installed, BOOL *selected, GLYPHMETRICS *gm, WORD *gi)
4520 {
4521     LOGFONTA lf;
4522     HFONT hfont, hfont_prev;
4523     HDC hdc;
4524     char facename[100];
4525     DWORD ret;
4526     static const WCHAR str[] = { 0x2025 };
4527
4528     *installed = is_truetype_font_installed(name);
4529
4530     lf.lfHeight = -18;
4531     lf.lfWidth = 0;
4532     lf.lfEscapement = 0;
4533     lf.lfOrientation = 0;
4534     lf.lfWeight = FW_DONTCARE;
4535     lf.lfItalic = 0;
4536     lf.lfUnderline = 0;
4537     lf.lfStrikeOut = 0;
4538     lf.lfCharSet = DEFAULT_CHARSET;
4539     lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
4540     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
4541     lf.lfQuality = DEFAULT_QUALITY;
4542     lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
4543     strcpy(lf.lfFaceName, name);
4544
4545     hfont = CreateFontIndirectA(&lf);
4546     ok(hfont != NULL, "CreateFontIndirectA failed\n");
4547
4548     hdc = GetDC(NULL);
4549
4550     hfont_prev = SelectObject(hdc, hfont);
4551     ok(hfont_prev != NULL, "SelectObject failed\n");
4552
4553     ret = GetTextFaceA(hdc, sizeof facename, facename);
4554     ok(ret, "GetTextFaceA failed\n");
4555     *selected = !strcmp(facename, name);
4556
4557     ret = GetGlyphOutlineW(hdc, 0x2025, GGO_METRICS, gm, 0, NULL, &mat);
4558     ok(ret != GDI_ERROR, "GetGlyphOutlineW failed\n");
4559     if (!*selected)
4560         memset(gm, 0, sizeof *gm);
4561
4562     ret = pGetGlyphIndicesW(hdc, str, 1, gi, 0);
4563     ok(ret != GDI_ERROR, "GetGlyphIndicesW failed\n");
4564
4565     SelectObject(hdc, hfont_prev);
4566     DeleteObject(hfont);
4567     ReleaseDC(NULL, hdc);
4568 }
4569
4570 static void test_vertical_font(void)
4571 {
4572     char ttf_name[MAX_PATH];
4573     int num;
4574     BOOL ret, installed, selected;
4575     GLYPHMETRICS gm;
4576     WORD hgi, vgi;
4577
4578     if (!pAddFontResourceExA || !pRemoveFontResourceExA || !pGetGlyphIndicesW)
4579     {
4580         win_skip("AddFontResourceExA or GetGlyphIndicesW is not available on this platform\n");
4581         return;
4582     }
4583
4584     if (!write_ttf_file("vertical.ttf", ttf_name))
4585     {
4586         skip("Failed to create ttf file for testing\n");
4587         return;
4588     }
4589
4590     num = pAddFontResourceExA(ttf_name, FR_PRIVATE, 0);
4591     ok(num == 2, "AddFontResourceExA should add 2 fonts from vertical.ttf\n");
4592
4593     check_vertical_font("@WineTestVertical", &installed, &selected, &gm, &hgi);
4594     ok(installed, "@WineTestVertical is not installed\n");
4595     ok(selected, "@WineTestVertical is not selected\n");
4596     ok(gm.gmBlackBoxX > gm.gmBlackBoxY,
4597        "gmBlackBoxX(%u) should be greater than gmBlackBoxY(%u) if horizontal\n",
4598        gm.gmBlackBoxX, gm.gmBlackBoxY);
4599
4600     check_vertical_font("@@WineTestVertical", &installed, &selected, &gm, &vgi);
4601     ok(installed, "@@WineTestVertical is not installed\n");
4602     ok(selected, "@@WineTestVertical is not selected\n");
4603     ok(gm.gmBlackBoxX < gm.gmBlackBoxY,
4604        "gmBlackBoxX(%u) should be less than gmBlackBoxY(%u) if vertical\n",
4605        gm.gmBlackBoxX, gm.gmBlackBoxY);
4606
4607     ok(hgi == vgi, "different glyph h:%u v:%u\n", hgi, vgi);
4608
4609     ret = pRemoveFontResourceExA(ttf_name, FR_PRIVATE, 0);
4610     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
4611
4612     DeleteFile(ttf_name);
4613 }
4614
4615 static INT CALLBACK has_vertical_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm,
4616                                            DWORD type, LPARAM lParam)
4617 {
4618     if (lf->lfFaceName[0] == '@') {
4619         return 0;
4620     }
4621     return 1;
4622 }
4623
4624 static void test_east_asian_font_selection(void)
4625 {
4626     HDC hdc;
4627     UINT charset[] = { SHIFTJIS_CHARSET, HANGEUL_CHARSET, JOHAB_CHARSET,
4628                        GB2312_CHARSET, CHINESEBIG5_CHARSET };
4629     size_t i;
4630
4631     hdc = GetDC(NULL);
4632
4633     for (i = 0; i < sizeof(charset)/sizeof(charset[0]); i++)
4634     {
4635         LOGFONTA lf;
4636         HFONT hfont;
4637         char face_name[LF_FACESIZE];
4638         int ret;
4639
4640         memset(&lf, 0, sizeof lf);
4641         lf.lfFaceName[0] = '\0';
4642         lf.lfCharSet = charset[i];
4643
4644         if (EnumFontFamiliesEx(hdc, &lf, has_vertical_font_proc, 0, 0))
4645         {
4646             skip("Vertical font for charset %u is not installed\n", charset[i]);
4647             continue;
4648         }
4649
4650         hfont = CreateFontIndirectA(&lf);
4651         hfont = SelectObject(hdc, hfont);
4652         memset(face_name, 0, sizeof face_name);
4653         ret = GetTextFaceA(hdc, sizeof face_name, face_name);
4654         ok(ret && face_name[0] != '@',
4655            "expected non-vertical face for charset %u, got %s\n", charset[i], face_name);
4656         DeleteObject(SelectObject(hdc, hfont));
4657
4658         memset(&lf, 0, sizeof lf);
4659         strcpy(lf.lfFaceName, "@");
4660         lf.lfCharSet = charset[i];
4661         hfont = CreateFontIndirectA(&lf);
4662         hfont = SelectObject(hdc, hfont);
4663         memset(face_name, 0, sizeof face_name);
4664         ret = GetTextFaceA(hdc, sizeof face_name, face_name);
4665         ok(ret && face_name[0] == '@',
4666            "expected vertical face for charset %u, got %s\n", charset[i], face_name);
4667         DeleteObject(SelectObject(hdc, hfont));
4668     }
4669     ReleaseDC(NULL, hdc);
4670 }
4671
4672 static int get_font_dpi(const LOGFONT *lf)
4673 {
4674     HDC hdc = CreateCompatibleDC(0);
4675     HFONT hfont;
4676     TEXTMETRIC tm;
4677     int ret;
4678
4679     hfont = CreateFontIndirect(lf);
4680     ok(hfont != 0, "CreateFontIndirect failed\n");
4681
4682     SelectObject(hdc, hfont);
4683     ret = GetTextMetrics(hdc, &tm);
4684     ok(ret, "GetTextMetrics failed\n");
4685     ret = tm.tmDigitizedAspectX;
4686
4687     DeleteDC(hdc);
4688     DeleteObject(hfont);
4689
4690     return ret;
4691 }
4692
4693 static void test_stock_fonts(void)
4694 {
4695     static const int font[] =
4696     {
4697         ANSI_FIXED_FONT, ANSI_VAR_FONT, SYSTEM_FONT, DEVICE_DEFAULT_FONT, DEFAULT_GUI_FONT
4698         /* SYSTEM_FIXED_FONT, OEM_FIXED_FONT */
4699     };
4700     static const struct test_data
4701     {
4702         int charset, weight, height, dpi;
4703         const char face_name[LF_FACESIZE];
4704     } td[][11] =
4705     {
4706         { /* ANSI_FIXED_FONT */
4707             { DEFAULT_CHARSET, FW_NORMAL, 12, 96, "Courier" },
4708             { DEFAULT_CHARSET, FW_NORMAL, 12, 120, "Courier" },
4709             { 0 }
4710         },
4711         { /* ANSI_VAR_FONT */
4712             { DEFAULT_CHARSET, FW_NORMAL, 12, 96, "MS Sans Serif" },
4713             { DEFAULT_CHARSET, FW_NORMAL, 12, 120, "MS Sans Serif" },
4714             { 0 }
4715         },
4716         { /* SYSTEM_FONT */
4717             { SHIFTJIS_CHARSET, FW_NORMAL, 18, 96, "System" },
4718             { SHIFTJIS_CHARSET, FW_NORMAL, 22, 120, "System" },
4719             { HANGEUL_CHARSET, FW_NORMAL, 16, 96, "System" },
4720             { HANGEUL_CHARSET, FW_NORMAL, 20, 120, "System" },
4721             { DEFAULT_CHARSET, FW_BOLD, 16, 96, "System" },
4722             { DEFAULT_CHARSET, FW_BOLD, 20, 120, "System" },
4723             { 0 }
4724         },
4725         { /* DEVICE_DEFAULT_FONT */
4726             { SHIFTJIS_CHARSET, FW_NORMAL, 18, 96, "System" },
4727             { SHIFTJIS_CHARSET, FW_NORMAL, 22, 120, "System" },
4728             { HANGEUL_CHARSET, FW_NORMAL, 16, 96, "System" },
4729             { HANGEUL_CHARSET, FW_NORMAL, 20, 120, "System" },
4730             { DEFAULT_CHARSET, FW_BOLD, 16, 96, "System" },
4731             { DEFAULT_CHARSET, FW_BOLD, 20, 120, "System" },
4732             { 0 }
4733         },
4734         { /* DEFAULT_GUI_FONT */
4735             { SHIFTJIS_CHARSET, FW_NORMAL, -12, 96, "?MS UI Gothic" },
4736             { SHIFTJIS_CHARSET, FW_NORMAL, -15, 120, "?MS UI Gothic" },
4737             { HANGEUL_CHARSET, FW_NORMAL, -12, 96, "?Gulim" },
4738             { HANGEUL_CHARSET, FW_NORMAL, -15, 120, "?Gulim" },
4739             { GB2312_CHARSET, FW_NORMAL, -12, 96, "?SimHei" },
4740             { GB2312_CHARSET, FW_NORMAL, -15, 120, "?SimHei" },
4741             { CHINESEBIG5_CHARSET, FW_NORMAL, -12, 96, "?MingLiU" },
4742             { CHINESEBIG5_CHARSET, FW_NORMAL, -15, 120, "?MingLiU" },
4743             { DEFAULT_CHARSET, FW_NORMAL, -11, 96, "MS Shell Dlg" },
4744             { DEFAULT_CHARSET, FW_NORMAL, -13, 120, "MS Shell Dlg" },
4745             { 0 }
4746         }
4747     };
4748     int i, j;
4749
4750     for (i = 0; i < sizeof(font)/sizeof(font[0]); i++)
4751     {
4752         HFONT hfont;
4753         LOGFONT lf;
4754         int ret;
4755
4756         hfont = GetStockObject(font[i]);
4757         ok(hfont != 0, "%d: GetStockObject(%d) failed\n", i, font[i]);
4758
4759         ret = GetObject(hfont, sizeof(lf), &lf);
4760         if (ret != sizeof(lf))
4761         {
4762             /* NT4 */
4763             win_skip("%d: GetObject returned %d instead of sizeof(LOGFONT)\n", i, ret);
4764             continue;
4765         }
4766
4767         for (j = 0; td[i][j].face_name[0] != 0; j++)
4768         {
4769             if (lf.lfCharSet != td[i][j].charset && td[i][j].charset != DEFAULT_CHARSET)
4770             {
4771                 continue;
4772             }
4773
4774             ret = get_font_dpi(&lf);
4775             if (ret != td[i][j].dpi)
4776             {
4777                 trace("%d(%d): font %s %d dpi doesn't match test data %d\n",
4778                       i, j, lf.lfFaceName, ret, td[i][j].dpi);
4779                 continue;
4780             }
4781
4782             ok(td[i][j].weight == lf.lfWeight, "%d(%d): expected lfWeight %d, got %d\n", i, j, td[i][j].weight, lf.lfWeight);
4783             ok(td[i][j].height == lf.lfHeight, "%d(%d): expected lfHeight %d, got %d\n", i, j, td[i][j].height, lf.lfHeight);
4784             if (td[i][j].face_name[0] == '?')
4785             {
4786                 /* Wine doesn't have this font, skip this case for now.
4787                    Actually, the face name is localized on Windows and varies
4788                    dpending on Windows versions (e.g. Japanese NT4 vs win2k). */
4789                 trace("%d(%d): default gui font is %s\n", i, j, lf.lfFaceName);
4790             }
4791             else
4792             {
4793                 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);
4794             }
4795             break;
4796         }
4797     }
4798 }
4799
4800 START_TEST(font)
4801 {
4802     init();
4803
4804     test_stock_fonts();
4805     test_logfont();
4806     test_bitmap_font();
4807     test_outline_font();
4808     test_bitmap_font_metrics();
4809     test_GdiGetCharDimensions();
4810     test_GetCharABCWidths();
4811     test_text_extents();
4812     test_GetGlyphIndices();
4813     test_GetKerningPairs();
4814     test_GetOutlineTextMetrics();
4815     test_SetTextJustification();
4816     test_font_charset();
4817     test_GetFontUnicodeRanges();
4818     test_nonexistent_font();
4819     test_orientation();
4820     test_height_selection();
4821     test_AddFontMemResource();
4822     test_EnumFonts();
4823
4824     /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
4825      * I'd like to avoid them in this test.
4826      */
4827     test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
4828     test_EnumFontFamilies("Symbol", SYMBOL_CHARSET);
4829     if (is_truetype_font_installed("Arial Black") &&
4830         (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
4831     {
4832         test_EnumFontFamilies("", ANSI_CHARSET);
4833         test_EnumFontFamilies("", SYMBOL_CHARSET);
4834         test_EnumFontFamilies("", DEFAULT_CHARSET);
4835     }
4836     else
4837         skip("Arial Black or Symbol/Wingdings is not installed\n");
4838     test_EnumFontFamiliesEx_default_charset();
4839     test_GetTextMetrics();
4840     test_GdiRealizationInfo();
4841     test_GetTextFace();
4842     test_GetGlyphOutline();
4843     test_GetTextMetrics2("Tahoma", -11);
4844     test_GetTextMetrics2("Tahoma", -55);
4845     test_GetTextMetrics2("Tahoma", -110);
4846     test_GetTextMetrics2("Arial", -11);
4847     test_GetTextMetrics2("Arial", -55);
4848     test_GetTextMetrics2("Arial", -110);
4849     test_CreateFontIndirect();
4850     test_CreateFontIndirectEx();
4851     test_oemcharset();
4852     test_fullname();
4853     test_fullname2();
4854     test_east_asian_font_selection();
4855
4856     /* These tests should be last test until RemoveFontResource
4857      * is properly implemented.
4858      */
4859     test_vertical_font();
4860     test_CreateScalableFontResource();
4861 }