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/heap.h"
32 #include "wine/test.h"
33 
34 static inline BOOL match_off_by_n(int a, int b, unsigned int n)
35 {
36     return abs(a - b) <= n;
37 }
38 #define match_off_by_1(a, b, exact) match_off_by_n((a), (b), (exact) ? 0 : 1)
39 #define near_match(a, b) match_off_by_n((a), (b), 6)
40 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
41 
42 static LONG  (WINAPI *pGdiGetCharDimensions)(HDC hdc, LPTEXTMETRICW lptm, LONG *height);
43 static DWORD (WINAPI *pGdiGetCodePage)(HDC hdc);
44 static BOOL  (WINAPI *pGetCharABCWidthsI)(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPABC abc);
45 static BOOL  (WINAPI *pGetCharABCWidthsA)(HDC hdc, UINT first, UINT last, LPABC abc);
46 static BOOL  (WINAPI *pGetCharABCWidthsW)(HDC hdc, UINT first, UINT last, LPABC abc);
47 static BOOL  (WINAPI *pGetCharABCWidthsFloatW)(HDC hdc, UINT first, UINT last, LPABCFLOAT abc);
48 static BOOL  (WINAPI *pGetCharWidth32A)(HDC hdc, UINT first, UINT last, LPINT buffer);
49 static BOOL  (WINAPI *pGetCharWidth32W)(HDC hdc, UINT first, UINT last, LPINT buffer);
50 static DWORD (WINAPI *pGetFontUnicodeRanges)(HDC hdc, LPGLYPHSET lpgs);
51 static DWORD (WINAPI *pGetGlyphIndicesA)(HDC hdc, LPCSTR lpstr, INT count, LPWORD pgi, DWORD flags);
52 static DWORD (WINAPI *pGetGlyphIndicesW)(HDC hdc, LPCWSTR lpstr, INT count, LPWORD pgi, DWORD flags);
53 static BOOL  (WINAPI *pGetTextExtentExPointI)(HDC hdc, const WORD *indices, INT count, INT max_ext,
54                                               LPINT nfit, LPINT dxs, LPSIZE size );
55 static BOOL  (WINAPI *pGdiRealizationInfo)(HDC hdc, DWORD *);
56 static HFONT (WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *);
57 static HANDLE (WINAPI *pAddFontMemResourceEx)(PVOID, DWORD, PVOID, DWORD *);
58 static BOOL  (WINAPI *pRemoveFontMemResourceEx)(HANDLE);
59 static INT   (WINAPI *pAddFontResourceExA)(LPCSTR, DWORD, PVOID);
60 static BOOL  (WINAPI *pRemoveFontResourceExA)(LPCSTR, DWORD, PVOID);
61 static BOOL  (WINAPI *pGetFontRealizationInfo)(HDC hdc, DWORD *);
62 static BOOL  (WINAPI *pGetFontFileInfo)(DWORD, DWORD, void *, DWORD, DWORD *);
63 static BOOL  (WINAPI *pGetFontFileData)(DWORD, DWORD, ULONGLONG, void *, DWORD);
64 
65 static HMODULE hgdi32 = 0;
66 static const MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
67 static WORD system_lang_id;
68 
69 #ifdef WORDS_BIGENDIAN
70 #define GET_BE_WORD(x) (x)
71 #define GET_BE_DWORD(x) (x)
72 #else
73 #define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
74 #define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
75 #endif
76 
77 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
78                     ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
79                     ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
80 #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
81 #define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
82 #define MS_NAME_TAG MS_MAKE_TAG('n','a','m','e')
83 
84 static void init(void)
85 {
86     hgdi32 = GetModuleHandleA("gdi32.dll");
87 
88     pGdiGetCharDimensions = (void *)GetProcAddress(hgdi32, "GdiGetCharDimensions");
89     pGdiGetCodePage = (void *) GetProcAddress(hgdi32,"GdiGetCodePage");
90     pGetCharABCWidthsI = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsI");
91     pGetCharABCWidthsA = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsA");
92     pGetCharABCWidthsW = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsW");
93     pGetCharABCWidthsFloatW = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsFloatW");
94     pGetCharWidth32A = (void *)GetProcAddress(hgdi32, "GetCharWidth32A");
95     pGetCharWidth32W = (void *)GetProcAddress(hgdi32, "GetCharWidth32W");
96     pGetFontUnicodeRanges = (void *)GetProcAddress(hgdi32, "GetFontUnicodeRanges");
97     pGetGlyphIndicesA = (void *)GetProcAddress(hgdi32, "GetGlyphIndicesA");
98     pGetGlyphIndicesW = (void *)GetProcAddress(hgdi32, "GetGlyphIndicesW");
99     pGetTextExtentExPointI = (void *)GetProcAddress(hgdi32, "GetTextExtentExPointI");
100     pGdiRealizationInfo = (void *)GetProcAddress(hgdi32, "GdiRealizationInfo");
101     pCreateFontIndirectExA = (void *)GetProcAddress(hgdi32, "CreateFontIndirectExA");
102     pAddFontMemResourceEx = (void *)GetProcAddress(hgdi32, "AddFontMemResourceEx");
103     pRemoveFontMemResourceEx = (void *)GetProcAddress(hgdi32, "RemoveFontMemResourceEx");
104     pAddFontResourceExA = (void *)GetProcAddress(hgdi32, "AddFontResourceExA");
105     pRemoveFontResourceExA = (void *)GetProcAddress(hgdi32, "RemoveFontResourceExA");
106     pGetFontRealizationInfo = (void *)GetProcAddress(hgdi32, "GetFontRealizationInfo");
107     pGetFontFileInfo = (void *)GetProcAddress(hgdi32, "GetFontFileInfo");
108     pGetFontFileData = (void *)GetProcAddress(hgdi32, "GetFontFileData");
109 
110     system_lang_id = PRIMARYLANGID(GetSystemDefaultLangID());
111 }
112 
113 static INT CALLBACK is_truetype_font_installed_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
114 {
115     if (type != TRUETYPE_FONTTYPE) return 1;
116 
117     return 0;
118 }
119 
120 static BOOL is_truetype_font_installed(const char *name)
121 {
122     HDC hdc = GetDC(0);
123     BOOL ret = FALSE;
124 
125     if (!EnumFontFamiliesA(hdc, name, is_truetype_font_installed_proc, 0))
126         ret = TRUE;
127 
128     ReleaseDC(0, hdc);
129     return ret;
130 }
131 
132 static INT CALLBACK is_font_installed_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
133 {
134     return 0;
135 }
136 
137 static BOOL is_font_installed(const char *name)
138 {
139     HDC hdc = GetDC(0);
140     BOOL ret = FALSE;
141 
142     if(!EnumFontFamiliesA(hdc, name, is_font_installed_proc, 0))
143         ret = TRUE;
144 
145     ReleaseDC(0, hdc);
146     return ret;
147 }
148 
149 static void *get_res_data(const char *fontname, DWORD *rsrc_size)
150 {
151     HRSRC rsrc;
152     void *rsrc_data;
153 
154     rsrc = FindResourceA(GetModuleHandleA(NULL), fontname, (LPCSTR)RT_RCDATA);
155     if (!rsrc) return NULL;
156 
157     rsrc_data = LockResource(LoadResource(GetModuleHandleA(NULL), rsrc));
158     if (!rsrc_data) return NULL;
159 
160     *rsrc_size = SizeofResource(GetModuleHandleA(NULL), rsrc);
161     if (!*rsrc_size) return NULL;
162 
163     return rsrc_data;
164 }
165 
166 static BOOL write_tmp_file( const void *data, DWORD *size, char *tmp_name )
167 {
168     char tmp_path[MAX_PATH];
169     HANDLE hfile;
170     BOOL ret;
171 
172     GetTempPathA(MAX_PATH, tmp_path);
173     GetTempFileNameA(tmp_path, "ttf", 0, tmp_name);
174 
175     hfile = CreateFileA(tmp_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
176     if (hfile == INVALID_HANDLE_VALUE) return FALSE;
177 
178     ret = WriteFile(hfile, data, *size, size, NULL);
179 
180     CloseHandle(hfile);
181     return ret;
182 }
183 
184 static BOOL write_ttf_file(const char *fontname, char *tmp_name)
185 {
186     void *rsrc_data;
187     DWORD rsrc_size;
188 
189     rsrc_data = get_res_data( fontname, &rsrc_size );
190     if (!rsrc_data) return FALSE;
191 
192     return write_tmp_file( rsrc_data, &rsrc_size, tmp_name );
193 }
194 
195 static void check_font(const char* test, const LOGFONTA* lf, HFONT hfont)
196 {
197     LOGFONTA getobj_lf;
198     int ret, minlen = 0;
199 
200     if (!hfont)
201         return;
202 
203     ret = GetObjectA(hfont, sizeof(getobj_lf), &getobj_lf);
204     /* NT4 tries to be clever and only returns the minimum length */
205     while (lf->lfFaceName[minlen] && minlen < LF_FACESIZE-1)
206         minlen++;
207     minlen += FIELD_OFFSET(LOGFONTA, lfFaceName) + 1;
208     ok(ret == sizeof(LOGFONTA) || ret == minlen, "%s: GetObject returned %d\n", test, ret);
209     ok(lf->lfHeight == getobj_lf.lfHeight ||
210        broken((SHORT)lf->lfHeight == getobj_lf.lfHeight), /* win9x */
211        "lfHeight: expect %08x got %08x\n", lf->lfHeight, getobj_lf.lfHeight);
212     ok(lf->lfWidth == getobj_lf.lfWidth ||
213        broken((SHORT)lf->lfWidth == getobj_lf.lfWidth), /* win9x */
214        "lfWidth: expect %08x got %08x\n", lf->lfWidth, getobj_lf.lfWidth);
215     ok(lf->lfEscapement == getobj_lf.lfEscapement ||
216        broken((SHORT)lf->lfEscapement == getobj_lf.lfEscapement), /* win9x */
217        "lfEscapement: expect %08x got %08x\n", lf->lfEscapement, getobj_lf.lfEscapement);
218     ok(lf->lfOrientation == getobj_lf.lfOrientation ||
219        broken((SHORT)lf->lfOrientation == getobj_lf.lfOrientation), /* win9x */
220        "lfOrientation: expect %08x got %08x\n", lf->lfOrientation, getobj_lf.lfOrientation);
221     ok(lf->lfWeight == getobj_lf.lfWeight ||
222        broken((SHORT)lf->lfWeight == getobj_lf.lfWeight), /* win9x */
223        "lfWeight: expect %08x got %08x\n", lf->lfWeight, getobj_lf.lfWeight);
224     ok(lf->lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf->lfItalic, getobj_lf.lfItalic);
225     ok(lf->lfUnderline == getobj_lf.lfUnderline, "lfUnderline: expect %02x got %02x\n", lf->lfUnderline, getobj_lf.lfUnderline);
226     ok(lf->lfStrikeOut == getobj_lf.lfStrikeOut, "lfStrikeOut: expect %02x got %02x\n", lf->lfStrikeOut, getobj_lf.lfStrikeOut);
227     ok(lf->lfCharSet == getobj_lf.lfCharSet, "lfCharSet: expect %02x got %02x\n", lf->lfCharSet, getobj_lf.lfCharSet);
228     ok(lf->lfOutPrecision == getobj_lf.lfOutPrecision, "lfOutPrecision: expect %02x got %02x\n", lf->lfOutPrecision, getobj_lf.lfOutPrecision);
229     ok(lf->lfClipPrecision == getobj_lf.lfClipPrecision, "lfClipPrecision: expect %02x got %02x\n", lf->lfClipPrecision, getobj_lf.lfClipPrecision);
230     ok(lf->lfQuality == getobj_lf.lfQuality, "lfQuality: expect %02x got %02x\n", lf->lfQuality, getobj_lf.lfQuality);
231     ok(lf->lfPitchAndFamily == getobj_lf.lfPitchAndFamily, "lfPitchAndFamily: expect %02x got %02x\n", lf->lfPitchAndFamily, getobj_lf.lfPitchAndFamily);
232     ok(!lstrcmpA(lf->lfFaceName, getobj_lf.lfFaceName) ||
233        broken(!memcmp(lf->lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
234        "%s: font names don't match: %s != %s\n", test, lf->lfFaceName, getobj_lf.lfFaceName);
235 }
236 
237 static HFONT create_font(const char* test, const LOGFONTA* lf)
238 {
239     HFONT hfont = CreateFontIndirectA(lf);
240     ok(hfont != 0, "%s: CreateFontIndirect failed\n", test);
241     if (hfont)
242         check_font(test, lf, hfont);
243     return hfont;
244 }
245 
246 static void test_logfont(void)
247 {
248     LOGFONTA lf;
249     HFONT hfont;
250 
251     memset(&lf, 0, sizeof lf);
252 
253     lf.lfCharSet = ANSI_CHARSET;
254     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
255     lf.lfWeight = FW_DONTCARE;
256     lf.lfHeight = 16;
257     lf.lfWidth = 16;
258     lf.lfQuality = DEFAULT_QUALITY;
259 
260     lstrcpyA(lf.lfFaceName, "Arial");
261     hfont = create_font("Arial", &lf);
262     DeleteObject(hfont);
263 
264     memset(&lf, 'A', sizeof(lf));
265     hfont = CreateFontIndirectA(&lf);
266     ok(hfont != 0, "CreateFontIndirectA with strange LOGFONT failed\n");
267 
268     lf.lfFaceName[LF_FACESIZE - 1] = 0;
269     check_font("AAA...", &lf, hfont);
270     DeleteObject(hfont);
271 }
272 
273 static INT CALLBACK font_enum_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
274 {
275     if (type & RASTER_FONTTYPE)
276     {
277 	LOGFONTA *lf = (LOGFONTA *)lParam;
278 	*lf = *elf;
279 	return 0; /* stop enumeration */
280     }
281 
282     return 1; /* continue enumeration */
283 }
284 
285 static void compare_tm(const TEXTMETRICA *tm, const TEXTMETRICA *otm)
286 {
287     ok(tm->tmHeight == otm->tmHeight, "tmHeight %d != %d\n", tm->tmHeight, otm->tmHeight);
288     ok(tm->tmAscent == otm->tmAscent, "tmAscent %d != %d\n", tm->tmAscent, otm->tmAscent);
289     ok(tm->tmDescent == otm->tmDescent, "tmDescent %d != %d\n", tm->tmDescent, otm->tmDescent);
290     ok(tm->tmInternalLeading == otm->tmInternalLeading, "tmInternalLeading %d != %d\n", tm->tmInternalLeading, otm->tmInternalLeading);
291     ok(tm->tmExternalLeading == otm->tmExternalLeading, "tmExternalLeading %d != %d\n", tm->tmExternalLeading, otm->tmExternalLeading);
292     ok(tm->tmAveCharWidth == otm->tmAveCharWidth, "tmAveCharWidth %d != %d\n", tm->tmAveCharWidth, otm->tmAveCharWidth);
293     ok(tm->tmMaxCharWidth == otm->tmMaxCharWidth, "tmMaxCharWidth %d != %d\n", tm->tmMaxCharWidth, otm->tmMaxCharWidth);
294     ok(tm->tmWeight == otm->tmWeight, "tmWeight %d != %d\n", tm->tmWeight, otm->tmWeight);
295     ok(tm->tmOverhang == otm->tmOverhang, "tmOverhang %d != %d\n", tm->tmOverhang, otm->tmOverhang);
296     ok(tm->tmDigitizedAspectX == otm->tmDigitizedAspectX, "tmDigitizedAspectX %d != %d\n", tm->tmDigitizedAspectX, otm->tmDigitizedAspectX);
297     ok(tm->tmDigitizedAspectY == otm->tmDigitizedAspectY, "tmDigitizedAspectY %d != %d\n", tm->tmDigitizedAspectY, otm->tmDigitizedAspectY);
298     ok(tm->tmFirstChar == otm->tmFirstChar, "tmFirstChar %d != %d\n", tm->tmFirstChar, otm->tmFirstChar);
299     ok(tm->tmLastChar == otm->tmLastChar, "tmLastChar %d != %d\n", tm->tmLastChar, otm->tmLastChar);
300     ok(tm->tmDefaultChar == otm->tmDefaultChar, "tmDefaultChar %d != %d\n", tm->tmDefaultChar, otm->tmDefaultChar);
301     ok(tm->tmBreakChar == otm->tmBreakChar, "tmBreakChar %d != %d\n", tm->tmBreakChar, otm->tmBreakChar);
302     ok(tm->tmItalic == otm->tmItalic, "tmItalic %d != %d\n", tm->tmItalic, otm->tmItalic);
303     ok(tm->tmUnderlined == otm->tmUnderlined, "tmUnderlined %d != %d\n", tm->tmUnderlined, otm->tmUnderlined);
304     ok(tm->tmStruckOut == otm->tmStruckOut, "tmStruckOut %d != %d\n", tm->tmStruckOut, otm->tmStruckOut);
305     ok(tm->tmPitchAndFamily == otm->tmPitchAndFamily, "tmPitchAndFamily %d != %d\n", tm->tmPitchAndFamily, otm->tmPitchAndFamily);
306     ok(tm->tmCharSet == otm->tmCharSet, "tmCharSet %d != %d\n", tm->tmCharSet, otm->tmCharSet);
307 }
308 
309 static void test_font_metrics(HDC hdc, HFONT hfont, LONG lfHeight,
310                               LONG lfWidth, const char *test_str,
311 			      INT test_str_len, const TEXTMETRICA *tm_orig,
312 			      const SIZE *size_orig, INT width_of_A_orig,
313 			      INT scale_x, INT scale_y)
314 {
315     LOGFONTA lf;
316     OUTLINETEXTMETRICA otm;
317     TEXTMETRICA tm;
318     SIZE size;
319     INT width_of_A, cx, cy;
320     UINT ret;
321 
322     if (!hfont)
323         return;
324 
325     ok(GetCurrentObject(hdc, OBJ_FONT) == hfont, "hfont should be selected\n");
326 
327     GetObjectA(hfont, sizeof(lf), &lf);
328 
329     if (GetOutlineTextMetricsA(hdc, 0, NULL))
330     {
331         otm.otmSize = sizeof(otm) / 2;
332         ret = GetOutlineTextMetricsA(hdc, otm.otmSize, &otm);
333         ok(ret == sizeof(otm)/2 /* XP */ ||
334            ret == 1 /* Win9x */, "expected sizeof(otm)/2, got %u\n", ret);
335 
336         memset(&otm, 0x1, sizeof(otm));
337         otm.otmSize = sizeof(otm);
338         ret = GetOutlineTextMetricsA(hdc, otm.otmSize, &otm);
339         ok(ret == sizeof(otm) /* XP */ ||
340            ret == 1 /* Win9x */, "expected sizeof(otm), got %u\n", ret);
341 
342         memset(&tm, 0x2, sizeof(tm));
343         ret = GetTextMetricsA(hdc, &tm);
344         ok(ret, "GetTextMetricsA failed\n");
345         /* the structure size is aligned */
346         if (memcmp(&tm, &otm.otmTextMetrics, FIELD_OFFSET(TEXTMETRICA, tmCharSet) + 1))
347         {
348             ok(0, "tm != otm\n");
349             compare_tm(&tm, &otm.otmTextMetrics);
350         }
351 
352         tm = otm.otmTextMetrics;
353 if (0) /* these metrics are scaled too, but with rounding errors */
354 {
355         ok(otm.otmAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmAscent, tm.tmAscent);
356         ok(otm.otmDescent == -tm.tmDescent, "descent %d != %d\n", otm.otmDescent, -tm.tmDescent);
357 }
358         ok(otm.otmMacAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmMacAscent, tm.tmAscent);
359         ok(otm.otmDescent < 0, "otm.otmDescent should be < 0\n");
360         ok(otm.otmMacDescent < 0, "otm.otmMacDescent should be < 0\n");
361         ok(tm.tmDescent > 0, "tm.tmDescent should be > 0\n");
362         ok(otm.otmMacDescent == -tm.tmDescent, "descent %d != %d\n", otm.otmMacDescent, -tm.tmDescent);
363         ok(otm.otmEMSquare == 2048, "expected 2048, got %d\n", otm.otmEMSquare);
364     }
365     else
366     {
367         ret = GetTextMetricsA(hdc, &tm);
368         ok(ret, "GetTextMetricsA failed\n");
369     }
370 
371     cx = tm.tmAveCharWidth / tm_orig->tmAveCharWidth;
372     cy = tm.tmHeight / tm_orig->tmHeight;
373     ok(cx == scale_x && cy == scale_y, "height %d: expected scale_x %d, scale_y %d, got cx %d, cy %d\n",
374        lfHeight, scale_x, scale_y, cx, cy);
375     ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "height %d != %d\n", tm.tmHeight, tm_orig->tmHeight * scale_y);
376     ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "ascent %d != %d\n", tm.tmAscent, tm_orig->tmAscent * scale_y);
377     ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "descent %d != %d\n", tm.tmDescent, tm_orig->tmDescent * scale_y);
378     ok(near_match(tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x), "ave width %d != %d\n", tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x);
379     ok(near_match(tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x), "max width %d != %d\n", tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x);
380 
381     ok(lf.lfHeight == lfHeight, "lfHeight %d != %d\n", lf.lfHeight, lfHeight);
382     if (lf.lfHeight)
383     {
384         if (lf.lfWidth)
385             ok(lf.lfWidth == tm.tmAveCharWidth, "lfWidth %d != tm %d\n", lf.lfWidth, tm.tmAveCharWidth);
386     }
387     else
388         ok(lf.lfWidth == lfWidth, "lfWidth %d != %d\n", lf.lfWidth, lfWidth);
389 
390     GetTextExtentPoint32A(hdc, test_str, test_str_len, &size);
391 
392     ok(near_match(size.cx, size_orig->cx * scale_x), "cx %d != %d\n", size.cx, size_orig->cx * scale_x);
393     ok(size.cy == size_orig->cy * scale_y, "cy %d != %d\n", size.cy, size_orig->cy * scale_y);
394 
395     GetCharWidthA(hdc, 'A', 'A', &width_of_A);
396 
397     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);
398 }
399 
400 /* Test how GDI scales bitmap font metrics */
401 static void test_bitmap_font(void)
402 {
403     static const char test_str[11] = "Test String";
404     HDC hdc;
405     LOGFONTA bitmap_lf;
406     HFONT hfont, old_hfont;
407     TEXTMETRICA tm_orig;
408     SIZE size_orig;
409     INT ret, i, width_orig, height_orig, scale, lfWidth;
410 
411     hdc = CreateCompatibleDC(0);
412 
413     /* "System" has only 1 pixel size defined, otherwise the test breaks */
414     ret = EnumFontFamiliesA(hdc, "System", font_enum_proc, (LPARAM)&bitmap_lf);
415     if (ret)
416     {
417 	ReleaseDC(0, hdc);
418 	trace("no bitmap fonts were found, skipping the test\n");
419 	return;
420     }
421 
422     trace("found bitmap font %s, height %d\n", bitmap_lf.lfFaceName, bitmap_lf.lfHeight);
423 
424     height_orig = bitmap_lf.lfHeight;
425     lfWidth = bitmap_lf.lfWidth;
426 
427     hfont = create_font("bitmap", &bitmap_lf);
428     old_hfont = SelectObject(hdc, hfont);
429     ok(GetTextMetricsA(hdc, &tm_orig), "GetTextMetricsA failed\n");
430     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
431     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
432     SelectObject(hdc, old_hfont);
433     DeleteObject(hfont);
434 
435     bitmap_lf.lfHeight = 0;
436     bitmap_lf.lfWidth = 4;
437     hfont = create_font("bitmap", &bitmap_lf);
438     old_hfont = SelectObject(hdc, hfont);
439     test_font_metrics(hdc, hfont, 0, 4, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, 1);
440     SelectObject(hdc, old_hfont);
441     DeleteObject(hfont);
442 
443     bitmap_lf.lfHeight = height_orig;
444     bitmap_lf.lfWidth = lfWidth;
445 
446     /* test fractional scaling */
447     for (i = 1; i <= height_orig * 6; i++)
448     {
449         INT nearest_height;
450 
451         bitmap_lf.lfHeight = i;
452 	hfont = create_font("fractional", &bitmap_lf);
453         scale = (i + height_orig - 1) / height_orig;
454         nearest_height = scale * height_orig;
455         /* Only jump to the next height if the difference <= 25% original height */
456         if (scale > 2 && nearest_height - i > height_orig / 4) scale--;
457         /* The jump between unscaled and doubled is delayed by 1 in winnt+ but not in win9x,
458            so we'll not test this particular height. */
459         else if(scale == 2 && nearest_height - i == (height_orig / 4)) continue;
460         else if(scale == 2 && nearest_height - i > (height_orig / 4 - 1)) scale--;
461         old_hfont = SelectObject(hdc, hfont);
462         test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, scale);
463         SelectObject(hdc, old_hfont);
464         DeleteObject(hfont);
465     }
466 
467     /* test integer scaling 3x2 */
468     bitmap_lf.lfHeight = height_orig * 2;
469     bitmap_lf.lfWidth *= 3;
470     hfont = create_font("3x2", &bitmap_lf);
471     old_hfont = SelectObject(hdc, hfont);
472     test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 2);
473     SelectObject(hdc, old_hfont);
474     DeleteObject(hfont);
475 
476     /* test integer scaling 3x3 */
477     bitmap_lf.lfHeight = height_orig * 3;
478     bitmap_lf.lfWidth = 0;
479     hfont = create_font("3x3", &bitmap_lf);
480     old_hfont = SelectObject(hdc, hfont);
481     test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 3);
482     SelectObject(hdc, old_hfont);
483     DeleteObject(hfont);
484 
485     DeleteDC(hdc);
486 }
487 
488 /* Test how GDI scales outline font metrics */
489 static void test_outline_font(void)
490 {
491     static const char test_str[11] = "Test String";
492     HDC hdc, hdc_2;
493     LOGFONTA lf;
494     HFONT hfont, old_hfont, old_hfont_2;
495     OUTLINETEXTMETRICA otm;
496     SIZE size_orig;
497     INT width_orig, height_orig, lfWidth;
498     XFORM xform;
499     GLYPHMETRICS gm;
500     MAT2 mat2 = { {0x8000,0}, {0,0}, {0,0}, {0x8000,0} };
501     POINT pt;
502     INT ret;
503 
504     if (!is_truetype_font_installed("Arial"))
505     {
506         skip("Arial is not installed\n");
507         return;
508     }
509 
510     hdc = CreateCompatibleDC(0);
511 
512     memset(&lf, 0, sizeof(lf));
513     strcpy(lf.lfFaceName, "Arial");
514     lf.lfHeight = 72;
515     hfont = create_font("outline", &lf);
516     old_hfont = SelectObject(hdc, hfont);
517     otm.otmSize = sizeof(otm);
518     ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n");
519     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
520     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
521 
522     test_font_metrics(hdc, hfont, lf.lfHeight, otm.otmTextMetrics.tmAveCharWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
523     SelectObject(hdc, old_hfont);
524     DeleteObject(hfont);
525 
526     /* font of otmEMSquare height helps to avoid a lot of rounding errors */
527     lf.lfHeight = otm.otmEMSquare;
528     lf.lfHeight = -lf.lfHeight;
529     hfont = create_font("outline", &lf);
530     old_hfont = SelectObject(hdc, hfont);
531     otm.otmSize = sizeof(otm);
532     ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n");
533     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
534     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
535     SelectObject(hdc, old_hfont);
536     DeleteObject(hfont);
537 
538     height_orig = otm.otmTextMetrics.tmHeight;
539     lfWidth = otm.otmTextMetrics.tmAveCharWidth;
540 
541     /* test integer scaling 3x2 */
542     lf.lfHeight = height_orig * 2;
543     lf.lfWidth = lfWidth * 3;
544     hfont = create_font("3x2", &lf);
545     old_hfont = SelectObject(hdc, hfont);
546     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 2);
547     SelectObject(hdc, old_hfont);
548     DeleteObject(hfont);
549 
550     /* test integer scaling 3x3 */
551     lf.lfHeight = height_orig * 3;
552     lf.lfWidth = lfWidth * 3;
553     hfont = create_font("3x3", &lf);
554     old_hfont = SelectObject(hdc, hfont);
555     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 3);
556     SelectObject(hdc, old_hfont);
557     DeleteObject(hfont);
558 
559     /* test integer scaling 1x1 */
560     lf.lfHeight = height_orig * 1;
561     lf.lfWidth = lfWidth * 1;
562     hfont = create_font("1x1", &lf);
563     old_hfont = SelectObject(hdc, hfont);
564     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
565     SelectObject(hdc, old_hfont);
566     DeleteObject(hfont);
567 
568     /* test integer scaling 1x1 */
569     lf.lfHeight = height_orig;
570     lf.lfWidth = 0;
571     hfont = create_font("1x1", &lf);
572     old_hfont = SelectObject(hdc, hfont);
573     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
574 
575     /* with an identity matrix */
576     memset(&gm, 0, sizeof(gm));
577     SetLastError(0xdeadbeef);
578     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
579     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
580     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
581     ok(gm.gmCellIncX == width_orig, "incX %d != %d\n", gm.gmCellIncX, width_orig);
582     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
583     /* with a custom matrix */
584     memset(&gm, 0, sizeof(gm));
585     SetLastError(0xdeadbeef);
586     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
587     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
588     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
589     ok(gm.gmCellIncX == width_orig/2, "incX %d != %d\n", gm.gmCellIncX, width_orig/2);
590     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
591 
592     /* Test that changing the DC transformation affects only the font
593      * selected on this DC and doesn't affect the same font selected on
594      * another DC.
595      */
596     hdc_2 = CreateCompatibleDC(0);
597     old_hfont_2 = SelectObject(hdc_2, hfont);
598     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
599 
600     SetMapMode(hdc, MM_ANISOTROPIC);
601 
602     /* font metrics on another DC should be unchanged */
603     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
604 
605     /* test restrictions of compatibility mode GM_COMPATIBLE */
606     /*  part 1: rescaling only X should not change font scaling on screen.
607                 So compressing the X axis by 2 is not done, and this
608                 appears as X scaling of 2 that no one requested. */
609     SetWindowExtEx(hdc, 100, 100, NULL);
610     SetViewportExtEx(hdc, 50, 100, NULL);
611     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 2, 1);
612     /* font metrics on another DC should be unchanged */
613     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
614 
615     /*  part 2: rescaling only Y should change font scaling.
616                 As also X is scaled by a factor of 2, but this is not
617                 requested by the DC transformation, we get a scaling factor
618                 of 2 in the X coordinate. */
619     SetViewportExtEx(hdc, 100, 200, NULL);
620     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 2, 1);
621     /* font metrics on another DC should be unchanged */
622     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
623 
624     /* restore scaling */
625     SetMapMode(hdc, MM_TEXT);
626 
627     /* font metrics on another DC should be unchanged */
628     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
629 
630     SelectObject(hdc_2, old_hfont_2);
631     DeleteDC(hdc_2);
632 
633     if (!SetGraphicsMode(hdc, GM_ADVANCED))
634     {
635         SelectObject(hdc, old_hfont);
636         DeleteObject(hfont);
637         DeleteDC(hdc);
638         skip("GM_ADVANCED is not supported on this platform\n");
639         return;
640     }
641 
642     xform.eM11 = 20.0f;
643     xform.eM12 = 0.0f;
644     xform.eM21 = 0.0f;
645     xform.eM22 = 20.0f;
646     xform.eDx = 0.0f;
647     xform.eDy = 0.0f;
648 
649     SetLastError(0xdeadbeef);
650     ret = SetWorldTransform(hdc, &xform);
651     ok(ret, "SetWorldTransform error %u\n", GetLastError());
652 
653     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
654 
655     /* with an identity matrix */
656     memset(&gm, 0, sizeof(gm));
657     SetLastError(0xdeadbeef);
658     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
659     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
660     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
661     pt.x = width_orig; pt.y = 0;
662     LPtoDP(hdc, &pt, 1);
663     ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x);
664     ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig);
665     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
666     /* with a custom matrix */
667     memset(&gm, 0, sizeof(gm));
668     SetLastError(0xdeadbeef);
669     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
670     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
671     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
672     pt.x = width_orig; pt.y = 0;
673     LPtoDP(hdc, &pt, 1);
674     ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2);
675     ok(near_match(gm.gmCellIncX, 10 * width_orig), "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig);
676     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
677 
678     SetLastError(0xdeadbeef);
679     ret = SetMapMode(hdc, MM_LOMETRIC);
680     ok(ret == MM_TEXT, "expected MM_TEXT, got %d, error %u\n", ret, GetLastError());
681 
682     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
683 
684     /* with an identity matrix */
685     memset(&gm, 0, sizeof(gm));
686     SetLastError(0xdeadbeef);
687     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
688     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
689     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
690     pt.x = width_orig; pt.y = 0;
691     LPtoDP(hdc, &pt, 1);
692     ok(near_match(gm.gmCellIncX, pt.x), "incX %d != %d\n", gm.gmCellIncX, pt.x);
693     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
694     /* with a custom matrix */
695     memset(&gm, 0, sizeof(gm));
696     SetLastError(0xdeadbeef);
697     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
698     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
699     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
700     pt.x = width_orig; pt.y = 0;
701     LPtoDP(hdc, &pt, 1);
702     ok(near_match(gm.gmCellIncX, (pt.x + 1)/2), "incX %d != %d\n", gm.gmCellIncX, (pt.x + 1)/2);
703     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
704 
705     SetLastError(0xdeadbeef);
706     ret = SetMapMode(hdc, MM_TEXT);
707     ok(ret == MM_LOMETRIC, "expected MM_LOMETRIC, got %d, error %u\n", ret, GetLastError());
708 
709     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
710 
711     /* with an identity matrix */
712     memset(&gm, 0, sizeof(gm));
713     SetLastError(0xdeadbeef);
714     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
715     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
716     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
717     pt.x = width_orig; pt.y = 0;
718     LPtoDP(hdc, &pt, 1);
719     ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x);
720     ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig);
721     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
722     /* with a custom matrix */
723     memset(&gm, 0, sizeof(gm));
724     SetLastError(0xdeadbeef);
725     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
726     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
727     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
728     pt.x = width_orig; pt.y = 0;
729     LPtoDP(hdc, &pt, 1);
730     ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2);
731     ok(gm.gmCellIncX == 10 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig);
732     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
733 
734     SelectObject(hdc, old_hfont);
735     DeleteObject(hfont);
736     DeleteDC(hdc);
737 }
738 
739 static INT CALLBACK find_font_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
740 {
741     LOGFONTA *lf = (LOGFONTA *)lParam;
742 
743     if (elf->lfHeight == lf->lfHeight && !strcmp(elf->lfFaceName, lf->lfFaceName))
744     {
745         *lf = *elf;
746         return 0; /* stop enumeration */
747     }
748     return 1; /* continue enumeration */
749 }
750 
751 static BOOL is_CJK(void)
752 {
753     return (system_lang_id == LANG_CHINESE || system_lang_id == LANG_JAPANESE || system_lang_id == LANG_KOREAN);
754 }
755 
756 #define FH_SCALE 0x80000000
757 static void test_bitmap_font_metrics(void)
758 {
759     static const WORD skip_rtl[] = {LANG_ARABIC, LANG_HEBREW, 0};
760     static const struct font_data
761     {
762         const char face_name[LF_FACESIZE];
763         int weight, height, ascent, descent, int_leading, ext_leading;
764         int ave_char_width, max_char_width, dpi;
765         BYTE first_char, last_char, def_char, break_char;
766         DWORD ansi_bitfield;
767         const WORD *skip_lang_id;
768         int scaled_height;
769     } fd[] =
770     {
771         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 6, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, skip_rtl, 13 },
772         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 6, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 13 },
773         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 8, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, skip_rtl, 13 },
774         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 8, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 13 },
775         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 10, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, skip_rtl, 13 },
776         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 10, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 13 },
777         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 14, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, skip_rtl, 13 },
778         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 14, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 13 },
779         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 18, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, skip_rtl, 16 },
780         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 18, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
781 
782         { "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 },
783         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 6, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
784         { "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 },
785         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 8, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
786         { "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 },
787         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 10, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
788         { "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 },
789         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 14, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
790         { "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 },
791         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 18, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
792 
793         { "MS Sans Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
794         { "MS Sans Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
795         { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
796         { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
797         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 16, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 },
798         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN2 },
799         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 16, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
800         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 19, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 },
801         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 24, 96, 0x20, 0xff, 0x81, 0x40, FS_LATIN2 },
802         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 20, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
803         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 24, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 },
804         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 6, 0, 12, 24, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN2 },
805         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 25, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
806         { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 },
807         { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32, 96, 0x20, 0xff, 0x81, 0x40, FS_LATIN2 },
808         { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
809 
810         { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
811         { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
812         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
813         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 17, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
814         { "MS Sans Serif", FW_NORMAL, 25, 20, 5, 5, 0, 10, 21, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
815         { "MS Sans Serif", FW_NORMAL, 25, 20, 5, 5, 0, 10, 21, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
816         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 6, 0, 12, 24, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
817         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 24, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
818         { "MS Sans Serif", FW_NORMAL, 36, 29, 7, 6, 0, 15, 30, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
819         { "MS Sans Serif", FW_NORMAL, 36, 29, 7, 6, 0, 15, 30, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
820         { "MS Sans Serif", FW_NORMAL, 46, 37, 9, 6, 0, 20, 40, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
821         { "MS Sans Serif", FW_NORMAL, 46, 37, 9, 6, 0, 20, 40, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
822 
823         { "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
824         { "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
825         { "MS Serif", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
826         { "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
827         { "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 12, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
828         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 14, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
829         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 16, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
830         { "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 18, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
831         { "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 19, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
832         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 17, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
833         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 22, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
834         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 23, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
835         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 23, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
836         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 26, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
837         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 27, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
838         { "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 33, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
839         { "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 34, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
840 
841         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 14, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_CYRILLIC },
842         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 13, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
843         { "MS Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_CYRILLIC },
844         { "MS Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 15, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
845         { "MS Serif", FW_NORMAL, 23, 18, 5, 3, 0, 10, 21, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_CYRILLIC },
846         { "MS Serif", FW_NORMAL, 23, 18, 5, 3, 0, 10, 19, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
847         { "MS Serif", FW_NORMAL, 27, 21, 6, 4, 0, 12, 23, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
848         { "MS Serif", FW_MEDIUM, 27, 22, 5, 2, 0, 12, 30, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
849         { "MS Serif", FW_NORMAL, 33, 26, 7, 3, 0, 14, 30, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
850         { "MS Serif", FW_MEDIUM, 32, 25, 7, 2, 0, 14, 32, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
851         { "MS Serif", FW_NORMAL, 43, 34, 9, 3, 0, 19, 39, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
852 
853         { "Courier", FW_NORMAL, 13, 11, 2, 0, 0, 8, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
854         { "Courier", FW_NORMAL, 16, 13, 3, 0, 0, 9, 9, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
855         { "Courier", FW_NORMAL, 20, 16, 4, 0, 0, 12, 12, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
856 
857         { "Courier", FW_NORMAL, 16, 13, 3, 0, 0, 9, 9, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
858         { "Courier", FW_NORMAL, 20, 16, 4, 0, 0, 12, 12, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
859         { "Courier", FW_NORMAL, 25, 20, 5, 0, 0, 15, 15, 120, 0x20, 0xff, 0x40, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
860 
861         { "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
862         { "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 15, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
863         { "System", FW_NORMAL, 18, 16, 2, 0, 2, 8, 16, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
864 
865         { "System", FW_BOLD, 20, 16, 4, 4, 0, 9, 14, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
866         { "System", FW_BOLD, 20, 16, 4, 4, 0, 9, 17, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
867 
868         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 2, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
869         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
870         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 2, 4, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
871         { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 3, 4, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1, skip_rtl},
872         { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 2, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
873         { "Small Fonts", FW_NORMAL, 5, 4, 1, 0, 0, 3, 6, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
874         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 13, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1, skip_rtl},
875         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
876         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 96, 0x00, 0xff, 0x60, 0x00, FS_ARABIC },
877         { "Small Fonts", FW_NORMAL, 6, 5, 1, 0, 0, 4, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
878         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 7, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1, skip_rtl},
879         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
880         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 96, 0x00, 0xff, 0x60, 0x00, FS_ARABIC },
881         { "Small Fonts", FW_NORMAL, 8, 7, 1, 0, 0, 5, 10, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
882         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2, skip_rtl},
883         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
884         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 4, 9, 96, 0x00, 0xff, 0x60, 0x00, FS_ARABIC },
885         { "Small Fonts", FW_NORMAL, 10, 8, 2, 0, 0, 6, 12, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
886         { "Small Fonts", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC, skip_rtl},
887         { "Small Fonts", FW_NORMAL, 11, 9, 2, 2, 0, 4, 10, 96, 0x00, 0xff, 0x60, 0x00, FS_ARABIC },
888         { "Small Fonts", FW_NORMAL, 11, 9, 2, 0, 0, 7, 14, 96, 0x20, 0xff, 0x80, 0x20, FS_JISJAPAN },
889 
890         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 2, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_JISJAPAN },
891         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 8, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
892         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 5, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_JISJAPAN },
893         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
894         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 7, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_JISJAPAN },
895         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
896         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 9, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
897         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
898         { "Small Fonts", FW_NORMAL, 12, 10, 2, 2, 0, 5, 10, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
899         { "Small Fonts", FW_NORMAL, 12, 10, 2, 2, 0, 6, 10, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
900         { "Small Fonts", FW_NORMAL, 13, 11, 2, 2, 0, 6, 12, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
901         { "Small Fonts", FW_NORMAL, 13, 11, 2, 2, 0, 6, 11, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
902 
903         { "Fixedsys", FW_NORMAL, 15, 12, 3, 3, 0, 8, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
904         { "Fixedsys", FW_NORMAL, 16, 12, 4, 3, 0, 8, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
905         { "FixedSys", FW_NORMAL, 18, 16, 2, 0, 0, 8, 16, 96, 0x20, 0xff, 0xa0, 0x20, FS_JISJAPAN },
906 
907         { "Fixedsys", FW_NORMAL, 20, 16, 4, 2, 0, 10, 10, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC }
908 
909         /* FIXME: add "Terminal" */
910     };
911     static const int font_log_pixels[] = { 96, 120 };
912     HDC hdc;
913     LOGFONTA lf;
914     HFONT hfont, old_hfont;
915     TEXTMETRICA tm;
916     INT ret, i, expected_cs, screen_log_pixels, diff, font_res;
917     char face_name[LF_FACESIZE];
918     CHARSETINFO csi;
919 
920     trace("system language id %04x\n", system_lang_id);
921 
922     expected_cs = GetACP();
923     if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
924     {
925         skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
926         return;
927     }
928     expected_cs = csi.ciCharset;
929     trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
930 
931     hdc = CreateCompatibleDC(0);
932     ok(hdc != NULL, "failed to create hdc\n");
933 
934     trace("logpixelsX %d, logpixelsY %d\n", GetDeviceCaps(hdc, LOGPIXELSX),
935           GetDeviceCaps(hdc, LOGPIXELSY));
936 
937     screen_log_pixels = GetDeviceCaps(hdc, LOGPIXELSY);
938     diff = 32768;
939     font_res = 0;
940     for (i = 0; i < sizeof(font_log_pixels)/sizeof(font_log_pixels[0]); i++)
941     {
942         int new_diff = abs(font_log_pixels[i] - screen_log_pixels);
943         if (new_diff < diff)
944         {
945             diff = new_diff;
946             font_res = font_log_pixels[i];
947         }
948     }
949     trace("best font resolution is %d\n", font_res);
950 
951     for (i = 0; i < sizeof(fd)/sizeof(fd[0]); i++)
952     {
953         int bit, height;
954 
955         memset(&lf, 0, sizeof(lf));
956 
957         height = fd[i].height & ~FH_SCALE;
958         lf.lfHeight = height;
959         strcpy(lf.lfFaceName, fd[i].face_name);
960 
961         for(bit = 0; bit < 32; bit++)
962         {
963             GLYPHMETRICS gm;
964             DWORD fs[2];
965             BOOL bRet;
966 
967             fs[0] = 1L << bit;
968             fs[1] = 0;
969             if((fd[i].ansi_bitfield & fs[0]) == 0) continue;
970             if(!TranslateCharsetInfo( fs, &csi, TCI_SRCFONTSIG )) continue;
971 
972             lf.lfCharSet = csi.ciCharset;
973             ret = EnumFontFamiliesExA(hdc, &lf, find_font_proc, (LPARAM)&lf, 0);
974             if (fd[i].height & FH_SCALE)
975                 ok(ret, "scaled font height %d should not be enumerated\n", height);
976             else
977             {
978                 if (font_res == fd[i].dpi && lf.lfCharSet == expected_cs)
979                 {
980                     todo_wine_if (ret) /* FIXME: Remove once Wine is fixed */
981                         ok(!ret, "%s height %d charset %d dpi %d should be enumerated\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet, fd[i].dpi);
982                 }
983             }
984             if (ret && !(fd[i].height & FH_SCALE))
985                 continue;
986 
987             hfont = create_font(lf.lfFaceName, &lf);
988             old_hfont = SelectObject(hdc, hfont);
989 
990             SetLastError(0xdeadbeef);
991             ret = GetTextFaceA(hdc, sizeof(face_name), face_name);
992             ok(ret, "GetTextFace error %u\n", GetLastError());
993 
994             if (strcmp(face_name, fd[i].face_name) != 0)
995             {
996                 ok(ret != ANSI_CHARSET, "font charset should not be ANSI_CHARSET\n");
997                 ok(ret != expected_cs, "font charset %d should not be %d\n", ret, expected_cs);
998                 SelectObject(hdc, old_hfont);
999                 DeleteObject(hfont);
1000                 continue;
1001             }
1002 
1003             memset(&gm, 0, sizeof(gm));
1004             SetLastError(0xdeadbeef);
1005             ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
1006             todo_wine {
1007             ok(ret == GDI_ERROR, "GetGlyphOutline should fail for a bitmap font\n");
1008             ok(GetLastError() == ERROR_CAN_NOT_COMPLETE, "expected ERROR_CAN_NOT_COMPLETE, got %u\n", GetLastError());
1009             }
1010 
1011             bRet = GetTextMetricsA(hdc, &tm);
1012             ok(bRet, "GetTextMetrics error %d\n", GetLastError());
1013 
1014             SetLastError(0xdeadbeef);
1015             ret = GetTextCharset(hdc);
1016             if (is_CJK() && lf.lfCharSet == ANSI_CHARSET)
1017                 ok(ret == ANSI_CHARSET, "got charset %d, expected ANSI_CHARSETd\n", ret);
1018             else
1019                 ok(ret == expected_cs, "got charset %d, expected %d\n", ret, expected_cs);
1020 
1021             trace("created %s, height %d charset %x dpi %d\n", face_name, tm.tmHeight, tm.tmCharSet, tm.tmDigitizedAspectX);
1022             trace("expected %s, height %d scaled_height %d, dpi %d\n", fd[i].face_name, height, fd[i].scaled_height, fd[i].dpi);
1023 
1024             if(fd[i].dpi == tm.tmDigitizedAspectX)
1025             {
1026                 int skipme = 0;
1027                 trace("matched %s, height %d charset %x dpi %d\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet, fd[i].dpi);
1028                 if (fd[i].skip_lang_id)
1029                 {
1030                     int si = 0;
1031                     skipme = 0;
1032                     while(!skipme && fd[i].skip_lang_id[si])
1033                         if (fd[i].skip_lang_id[si++] == system_lang_id)
1034                             skipme = 1;
1035                 }
1036                 if (!skipme)
1037                 {
1038                     ok(tm.tmWeight == fd[i].weight, "%s(%d): tm.tmWeight %d != %d\n", fd[i].face_name, height, tm.tmWeight, fd[i].weight);
1039                     if (fd[i].height & FH_SCALE)
1040                         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);
1041                     else
1042                         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);
1043                     ok(tm.tmAscent == fd[i].ascent, "%s(%d): tm.tmAscent %d != %d\n", fd[i].face_name, height, tm.tmAscent, fd[i].ascent);
1044                     ok(tm.tmDescent == fd[i].descent, "%s(%d): tm.tmDescent %d != %d\n", fd[i].face_name, height, tm.tmDescent, fd[i].descent);
1045                     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);
1046                     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);
1047                     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);
1048                     ok(tm.tmFirstChar == fd[i].first_char, "%s(%d): tm.tmFirstChar = %02x\n", fd[i].face_name, height, tm.tmFirstChar);
1049                     ok(tm.tmLastChar == fd[i].last_char, "%s(%d): tm.tmLastChar = %02x\n", fd[i].face_name, height, tm.tmLastChar);
1050                     /* Substitutions like MS Sans Serif,0=MS Sans Serif,204
1051                        make default char test fail */
1052                     if (tm.tmCharSet == lf.lfCharSet)
1053                         ok(tm.tmDefaultChar == fd[i].def_char, "%s(%d): tm.tmDefaultChar = %02x\n", fd[i].face_name, height, tm.tmDefaultChar);
1054                     ok(tm.tmBreakChar == fd[i].break_char, "%s(%d): tm.tmBreakChar = %02x\n", fd[i].face_name, height, tm.tmBreakChar);
1055                     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);
1056 
1057                     /* Don't run the max char width test on System/ANSI_CHARSET.  We have extra characters in our font
1058                        that make the max width bigger */
1059                     if ((strcmp(lf.lfFaceName, "System") || lf.lfCharSet != ANSI_CHARSET) && tm.tmDigitizedAspectX == 96)
1060                         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);
1061                 }
1062                 else
1063                     skip("Skipping font metrics test for system langid 0x%x\n",
1064                          system_lang_id);
1065             }
1066             SelectObject(hdc, old_hfont);
1067             DeleteObject(hfont);
1068         }
1069     }
1070 
1071     DeleteDC(hdc);
1072 }
1073 
1074 static void test_GdiGetCharDimensions(void)
1075 {
1076     HDC hdc;
1077     TEXTMETRICW tm;
1078     LONG ret;
1079     SIZE size;
1080     LONG avgwidth, height;
1081     static const char szAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1082 
1083     if (!pGdiGetCharDimensions)
1084     {
1085         win_skip("GdiGetCharDimensions not available on this platform\n");
1086         return;
1087     }
1088 
1089     hdc = CreateCompatibleDC(NULL);
1090 
1091     GetTextExtentPointA(hdc, szAlphabet, strlen(szAlphabet), &size);
1092     avgwidth = ((size.cx / 26) + 1) / 2;
1093 
1094     ret = pGdiGetCharDimensions(hdc, &tm, &height);
1095     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
1096     ok(height == tm.tmHeight, "GdiGetCharDimensions should have set height to %d instead of %d\n", tm.tmHeight, height);
1097 
1098     ret = pGdiGetCharDimensions(hdc, &tm, NULL);
1099     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
1100 
1101     ret = pGdiGetCharDimensions(hdc, NULL, NULL);
1102     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
1103 
1104     height = 0;
1105     ret = pGdiGetCharDimensions(hdc, NULL, &height);
1106     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
1107     ok(height == size.cy, "GdiGetCharDimensions should have set height to %d instead of %d\n", size.cy, height);
1108 
1109     DeleteDC(hdc);
1110 }
1111 
1112 static int CALLBACK create_font_proc(const LOGFONTA *lpelfe,
1113                                      const TEXTMETRICA *lpntme,
1114                                      DWORD FontType, LPARAM lParam)
1115 {
1116     if (FontType & TRUETYPE_FONTTYPE)
1117     {
1118         HFONT hfont;
1119 
1120         hfont = CreateFontIndirectA(lpelfe);
1121         if (hfont)
1122         {
1123             *(HFONT *)lParam = hfont;
1124             return 0;
1125         }
1126     }
1127 
1128     return 1;
1129 }
1130 
1131 static void ABCWidths_helper(const char* description, HDC hdc, WORD *glyphs, const ABC *base_abci, const ABC *base_abcw, const ABCFLOAT *base_abcf)
1132 {
1133     ABC abc[1];
1134     ABCFLOAT abcf[1];
1135     BOOL ret = FALSE;
1136 
1137     ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, abc);
1138     ok(ret, "%s: GetCharABCWidthsI should have succeeded\n", description);
1139     ok ((INT)abc->abcB > 0, "%s: abcB should be positive\n", description);
1140     ok(abc->abcA * base_abci->abcA >= 0, "%s: abcA's sign should be unchanged\n", description);
1141     ok(abc->abcC * base_abci->abcC >= 0, "%s: abcC's sign should be unchanged\n", description);
1142 
1143     ret = pGetCharABCWidthsW(hdc, 'i', 'i', abc);
1144     ok(ret, "%s: GetCharABCWidthsW should have succeeded\n", description);
1145     ok ((INT)abc->abcB > 0, "%s: abcB should be positive\n", description);
1146     ok(abc->abcA * base_abcw->abcA >= 0, "%s: abcA's sign should be unchanged\n", description);
1147     ok(abc->abcC * base_abcw->abcC >= 0, "%s: abcC's sign should be unchanged\n", description);
1148 
1149     ret = pGetCharABCWidthsFloatW(hdc, 'i', 'i', abcf);
1150     ok(ret, "%s: GetCharABCWidthsFloatW should have succeeded\n", description);
1151     ok (abcf->abcfB > 0.0, "%s: abcfB should be positive\n", description);
1152     ok(abcf->abcfA * base_abcf->abcfA >= 0.0, "%s: abcfA's sign should be unchanged\n", description);
1153     ok(abcf->abcfC * base_abcf->abcfC >= 0.0, "%s: abcfC's sign should be unchanged\n", description);
1154 }
1155 
1156 static void test_GetCharABCWidths(void)
1157 {
1158     static const WCHAR str[] = {'i',0};
1159     BOOL ret;
1160     HDC hdc;
1161     LOGFONTA lf;
1162     HFONT hfont;
1163     ABC abc[1];
1164     ABC abcw[1];
1165     ABCFLOAT abcf[1];
1166     WORD glyphs[1];
1167     DWORD nb;
1168     HWND hwnd;
1169     static const struct
1170     {
1171         UINT first;
1172         UINT last;
1173     } range[] =
1174     {
1175         {0xff, 0xff},
1176         {0x100, 0x100},
1177         {0xff, 0x100},
1178         {0x1ff, 0xff00},
1179         {0xffff, 0xffff},
1180         {0x10000, 0x10000},
1181         {0xffff, 0x10000},
1182         {0xffffff, 0xffffff},
1183         {0x1000000, 0x1000000},
1184         {0xffffff, 0x1000000},
1185         {0xffffffff, 0xffffffff},
1186         {0x00, 0xff}
1187     };
1188     static const struct
1189     {
1190         UINT cs;
1191         UINT a;
1192         UINT w;
1193         BOOL r[sizeof range / sizeof range[0]];
1194     } c[] =
1195     {
1196         {ANSI_CHARSET, 0x30, 0x30,
1197          {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE}},
1198         {SHIFTJIS_CHARSET, 0x82a0, 0x3042,
1199          {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE}},
1200         {HANGEUL_CHARSET, 0x8141, 0xac02,
1201          {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE}},
1202         {GB2312_CHARSET, 0x8141, 0x4e04,
1203          {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE}},
1204         {CHINESEBIG5_CHARSET, 0xa142, 0x3001,
1205          {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE}}
1206     };
1207     UINT i;
1208 
1209     if (!pGetCharABCWidthsA || !pGetCharABCWidthsW || !pGetCharABCWidthsFloatW || !pGetCharABCWidthsI)
1210     {
1211         win_skip("GetCharABCWidthsA/W/I not available on this platform\n");
1212         return;
1213     }
1214 
1215     memset(&lf, 0, sizeof(lf));
1216     strcpy(lf.lfFaceName, "System");
1217     lf.lfHeight = 20;
1218 
1219     hfont = CreateFontIndirectA(&lf);
1220     hdc = GetDC(0);
1221     hfont = SelectObject(hdc, hfont);
1222 
1223     nb = pGetGlyphIndicesW(hdc, str, 1, glyphs, 0);
1224     ok(nb == 1, "GetGlyphIndicesW should have returned 1\n");
1225 
1226     ret = pGetCharABCWidthsI(NULL, 0, 1, glyphs, abc);
1227     ok(!ret, "GetCharABCWidthsI should have failed\n");
1228 
1229     ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, NULL);
1230     ok(!ret, "GetCharABCWidthsI should have failed\n");
1231 
1232     ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, abc);
1233     ok(ret, "GetCharABCWidthsI should have succeeded\n");
1234 
1235     ret = pGetCharABCWidthsW(NULL, 'a', 'a', abc);
1236     ok(!ret, "GetCharABCWidthsW should have failed\n");
1237 
1238     ret = pGetCharABCWidthsW(hdc, 'a', 'a', NULL);
1239     ok(!ret, "GetCharABCWidthsW should have failed\n");
1240 
1241     ret = pGetCharABCWidthsW(hdc, 'a', 'a', abc);
1242     ok(!ret, "GetCharABCWidthsW should have failed\n");
1243 
1244     ret = pGetCharABCWidthsFloatW(NULL, 'a', 'a', abcf);
1245     ok(!ret, "GetCharABCWidthsFloatW should have failed\n");
1246 
1247     ret = pGetCharABCWidthsFloatW(hdc, 'a', 'a', NULL);
1248     ok(!ret, "GetCharABCWidthsFloatW should have failed\n");
1249 
1250     ret = pGetCharABCWidthsFloatW(hdc, 'a', 'a', abcf);
1251     ok(ret, "GetCharABCWidthsFloatW should have succeeded\n");
1252 
1253     hfont = SelectObject(hdc, hfont);
1254     DeleteObject(hfont);
1255 
1256     for (i = 0; i < sizeof c / sizeof c[0]; ++i)
1257     {
1258         ABC a[2], w[2];
1259         ABC full[256];
1260         UINT code = 0x41, j;
1261 
1262         lf.lfFaceName[0] = '\0';
1263         lf.lfCharSet = c[i].cs;
1264         lf.lfPitchAndFamily = 0;
1265         if (EnumFontFamiliesExA(hdc, &lf, create_font_proc, (LPARAM)&hfont, 0))
1266         {
1267             skip("TrueType font for charset %u is not installed\n", c[i].cs);
1268             continue;
1269         }
1270 
1271         memset(a, 0, sizeof a);
1272         memset(w, 0, sizeof w);
1273         hfont = SelectObject(hdc, hfont);
1274         ok(pGetCharABCWidthsA(hdc, c[i].a, c[i].a + 1, a) &&
1275            pGetCharABCWidthsW(hdc, c[i].w, c[i].w + 1, w) &&
1276            memcmp(a, w, sizeof a) == 0,
1277            "GetCharABCWidthsA and GetCharABCWidthsW should return same widths. charset = %u\n", c[i].cs);
1278 
1279         memset(a, 0xbb, sizeof a);
1280         ret = pGetCharABCWidthsA(hdc, code, code, a);
1281         ok(ret, "GetCharABCWidthsA should have succeeded\n");
1282         memset(full, 0xcc, sizeof full);
1283         ret = pGetCharABCWidthsA(hdc, 0x00, code, full);
1284         ok(ret, "GetCharABCWidthsA should have succeeded\n");
1285         ok(memcmp(&a[0], &full[code], sizeof(ABC)) == 0,
1286            "GetCharABCWidthsA info should match. codepage = %u\n", c[i].cs);
1287 
1288         for (j = 0; j < sizeof range / sizeof range[0]; ++j)
1289         {
1290             memset(full, 0xdd, sizeof full);
1291             ret = pGetCharABCWidthsA(hdc, range[j].first, range[j].last, full);
1292             ok(ret == c[i].r[j], "GetCharABCWidthsA %x - %x should have %s\n",
1293                range[j].first, range[j].last, c[i].r[j] ? "succeeded" : "failed");
1294             if (ret)
1295             {
1296                 UINT last = range[j].last - range[j].first;
1297                 ret = pGetCharABCWidthsA(hdc, range[j].last, range[j].last, a);
1298                 ok(ret && memcmp(&full[last], &a[0], sizeof(ABC)) == 0,
1299                    "GetCharABCWidthsA %x should match. codepage = %u\n",
1300                    range[j].last, c[i].cs);
1301             }
1302         }
1303 
1304         hfont = SelectObject(hdc, hfont);
1305         DeleteObject(hfont);
1306     }
1307 
1308     memset(&lf, 0, sizeof(lf));
1309     strcpy(lf.lfFaceName, "Tahoma");
1310     lf.lfHeight = 200;
1311     hfont = CreateFontIndirectA(&lf);
1312 
1313     /* test empty glyph's metrics */
1314     hfont = SelectObject(hdc, hfont);
1315     ret = pGetCharABCWidthsFloatW(hdc, ' ', ' ', abcf);
1316     ok(ret, "GetCharABCWidthsFloatW should have succeeded\n");
1317     ok(abcf[0].abcfB == 1.0, "got %f\n", abcf[0].abcfB);
1318     ret = pGetCharABCWidthsW(hdc, ' ', ' ', abcw);
1319     ok(ret, "GetCharABCWidthsW should have succeeded\n");
1320     ok(abcw[0].abcB == 1, "got %u\n", abcw[0].abcB);
1321 
1322     /* 1) prepare unrotated font metrics */
1323     ret = pGetCharABCWidthsW(hdc, 'a', 'a', abcw);
1324     ok(ret, "GetCharABCWidthsW should have succeeded\n");
1325     DeleteObject(SelectObject(hdc, hfont));
1326 
1327     /* 2) get rotated font metrics */
1328     lf.lfEscapement = lf.lfOrientation = 900;
1329     hfont = CreateFontIndirectA(&lf);
1330     hfont = SelectObject(hdc, hfont);
1331     ret = pGetCharABCWidthsW(hdc, 'a', 'a', abc);
1332     ok(ret, "GetCharABCWidthsW should have succeeded\n");
1333 
1334     /* 3) compare ABC results */
1335     ok(match_off_by_1(abcw[0].abcA, abc[0].abcA, FALSE),
1336        "got %d, expected %d (A)\n", abc[0].abcA, abcw[0].abcA);
1337     ok(match_off_by_1(abcw[0].abcB, abc[0].abcB, FALSE),
1338        "got %d, expected %d (B)\n", abc[0].abcB, abcw[0].abcB);
1339     ok(match_off_by_1(abcw[0].abcC, abc[0].abcC, FALSE),
1340        "got %d, expected %d (C)\n", abc[0].abcC, abcw[0].abcC);
1341 
1342     DeleteObject(SelectObject(hdc, hfont));
1343 
1344     /* test abcA == gmptGlyphOrigin.x && abcB == gmBlackBoxX
1345        in various widths. */
1346     for (i = 1; i <= 2; i++)
1347     {
1348         UINT j;
1349         UINT code;
1350 
1351         memset(&lf, 0, sizeof(lf));
1352         lf.lfHeight = 20;
1353         switch(i)
1354         {
1355         case 1:
1356             strcpy(lf.lfFaceName, "Tahoma");
1357             code = 'a';
1358             break;
1359         case 2:
1360             strcpy(lf.lfFaceName, "Times New Roman");
1361             lf.lfItalic = TRUE;
1362             code = 'f';
1363             break;
1364         }
1365         if (!is_truetype_font_installed(lf.lfFaceName))
1366         {
1367             skip("%s is not installed\n", lf.lfFaceName);
1368             continue;
1369         }
1370         for (j = 1; j <= 80; j++)
1371         {
1372             GLYPHMETRICS gm;
1373 
1374             lf.lfWidth = j;
1375             hfont = CreateFontIndirectA(&lf);
1376             hfont = SelectObject(hdc, hfont);
1377 
1378             nb = GetGlyphOutlineA(hdc, code, GGO_METRICS, &gm, 0, NULL, &mat);
1379             ok(nb, "GetGlyphOutlineA should have succeeded at width %d\n", i);
1380 
1381             ret = GetCharABCWidthsA(hdc, code, code, abc);
1382             ok(ret, "GetCharABCWidthsA should have succeeded at width %d\n", i);
1383 
1384             ok(abc[0].abcA == gm.gmptGlyphOrigin.x,
1385                "abcA(%d) and gmptGlyphOrigin.x(%d) values are different at width %d\n",
1386                abc[0].abcA, gm.gmptGlyphOrigin.x, i);
1387             ok(abc[0].abcB == gm.gmBlackBoxX,
1388                "abcB(%d) and gmBlackBoxX(%d) values are different at width %d\n",
1389                abc[0].abcB, gm.gmBlackBoxX, i);
1390             DeleteObject(SelectObject(hdc, hfont));
1391         }
1392     }
1393     ReleaseDC(NULL, hdc);
1394 
1395     trace("ABC sign test for a variety of transforms:\n");
1396     memset(&lf, 0, sizeof(lf));
1397     strcpy(lf.lfFaceName, "Tahoma");
1398     lf.lfHeight = 20;
1399     hfont = CreateFontIndirectA(&lf);
1400     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
1401                            0, 0, 0, NULL);
1402     hdc = GetDC(hwnd);
1403     SetMapMode(hdc, MM_ANISOTROPIC);
1404     SelectObject(hdc, hfont);
1405 
1406     nb = pGetGlyphIndicesW(hdc, str, 1, glyphs, 0);
1407     ok(nb == 1, "GetGlyphIndicesW should have returned 1\n");
1408 
1409     ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, abc);
1410     ok(ret, "GetCharABCWidthsI should have succeeded\n");
1411     ret = pGetCharABCWidthsW(hdc, 'i', 'i', abcw);
1412     ok(ret, "GetCharABCWidthsW should have succeeded\n");
1413     ret = pGetCharABCWidthsFloatW(hdc, 'i', 'i', abcf);
1414     ok(ret, "GetCharABCWidthsFloatW should have succeeded\n");
1415 
1416     ABCWidths_helper("LTR", hdc, glyphs, abc, abcw, abcf);
1417     SetWindowExtEx(hdc, -1, -1, NULL);
1418     SetGraphicsMode(hdc, GM_COMPATIBLE);
1419     ABCWidths_helper("LTR -1 compatible", hdc, glyphs, abc, abcw, abcf);
1420     SetGraphicsMode(hdc, GM_ADVANCED);
1421     ABCWidths_helper("LTR -1 advanced", hdc, glyphs, abc, abcw, abcf);
1422     SetWindowExtEx(hdc, 1, 1, NULL);
1423     SetGraphicsMode(hdc, GM_COMPATIBLE);
1424     ABCWidths_helper("LTR 1 compatible", hdc, glyphs, abc, abcw, abcf);
1425     SetGraphicsMode(hdc, GM_ADVANCED);
1426     ABCWidths_helper("LTR 1 advanced", hdc, glyphs, abc, abcw, abcf);
1427 
1428     ReleaseDC(hwnd, hdc);
1429     DestroyWindow(hwnd);
1430 
1431     trace("RTL layout\n");
1432     hwnd = CreateWindowExA(WS_EX_LAYOUTRTL, "static", "", WS_POPUP, 0,0,100,100,
1433                            0, 0, 0, NULL);
1434     hdc = GetDC(hwnd);
1435     SetMapMode(hdc, MM_ANISOTROPIC);
1436     SelectObject(hdc, hfont);
1437 
1438     ABCWidths_helper("RTL", hdc, glyphs, abc, abcw, abcf);
1439     SetWindowExtEx(hdc, -1, -1, NULL);
1440     SetGraphicsMode(hdc, GM_COMPATIBLE);
1441     ABCWidths_helper("RTL -1 compatible", hdc, glyphs, abc, abcw, abcf);
1442     SetGraphicsMode(hdc, GM_ADVANCED);
1443     ABCWidths_helper("RTL -1 advanced", hdc, glyphs, abc, abcw, abcf);
1444     SetWindowExtEx(hdc, 1, 1, NULL);
1445     SetGraphicsMode(hdc, GM_COMPATIBLE);
1446     ABCWidths_helper("RTL 1 compatible", hdc, glyphs, abc, abcw, abcf);
1447     SetGraphicsMode(hdc, GM_ADVANCED);
1448     ABCWidths_helper("RTL 1 advanced", hdc, glyphs, abc, abcw, abcf);
1449 
1450     ReleaseDC(hwnd, hdc);
1451     DestroyWindow(hwnd);
1452     DeleteObject(hfont);
1453 }
1454 
1455 static void test_text_extents(void)
1456 {
1457     static const WCHAR wt[] = {'O','n','e','\n','t','w','o',' ','3',0};
1458     static const WCHAR emptyW[] = {0};
1459     LPINT extents;
1460     INT i, len, fit1, fit2, extents2[3];
1461     LOGFONTA lf;
1462     TEXTMETRICA tm;
1463     HDC hdc;
1464     HFONT hfont;
1465     SIZE sz;
1466     SIZE sz1, sz2;
1467     BOOL ret;
1468 
1469     memset(&lf, 0, sizeof(lf));
1470     strcpy(lf.lfFaceName, "Arial");
1471     lf.lfHeight = 20;
1472 
1473     hfont = CreateFontIndirectA(&lf);
1474     hdc = GetDC(0);
1475     hfont = SelectObject(hdc, hfont);
1476     GetTextMetricsA(hdc, &tm);
1477     ret = GetTextExtentPointA(hdc, "o", 1, &sz);
1478     ok(ret, "got %d\n", ret);
1479     ok(sz.cy == tm.tmHeight, "cy %d tmHeight %d\n", sz.cy, tm.tmHeight);
1480 
1481     memset(&sz, 0xcc, sizeof(sz));
1482     ret = GetTextExtentPointA(hdc, "o", 0, &sz);
1483     ok(ret, "got %d\n", ret);
1484     ok(sz.cx == 0 && sz.cy == 0, "cx %d, cy %d\n", sz.cx, sz.cy);
1485 
1486     memset(&sz, 0xcc, sizeof(sz));
1487     ret = GetTextExtentPointA(hdc, "", 0, &sz);
1488     ok(ret, "got %d\n", ret);
1489     ok(sz.cx == 0 && sz.cy == 0, "cx %d, cy %d\n", sz.cx, sz.cy);
1490 
1491     SetLastError(0xdeadbeef);
1492     GetTextExtentExPointW(hdc, wt, 1, 1, &fit1, &fit2, &sz1);
1493     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1494     {
1495         win_skip("Skipping remainder of text extents test on a Win9x platform\n");
1496         hfont = SelectObject(hdc, hfont);
1497         DeleteObject(hfont);
1498         ReleaseDC(0, hdc);
1499         return;
1500     }
1501 
1502     memset(&sz, 0xcc, sizeof(sz));
1503     ret = GetTextExtentPointW(hdc, wt, 0, &sz);
1504     ok(ret, "got %d\n", ret);
1505     ok(sz.cx == 0 && sz.cy == 0, "cx %d, cy %d\n", sz.cx, sz.cy);
1506 
1507     memset(&sz, 0xcc, sizeof(sz));
1508     ret = GetTextExtentPointW(hdc, emptyW, 0, &sz);
1509     ok(ret, "got %d\n", ret);
1510     ok(sz.cx == 0 && sz.cy == 0, "cx %d, cy %d\n", sz.cx, sz.cy);
1511 
1512     len = lstrlenW(wt);
1513     extents = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof extents[0]);
1514     extents[0] = 1;         /* So that the increasing sequence test will fail
1515                                if the extents array is untouched.  */
1516     GetTextExtentExPointW(hdc, wt, len, 32767, &fit1, extents, &sz1);
1517     GetTextExtentPointW(hdc, wt, len, &sz2);
1518     ok(sz1.cy == sz2.cy,
1519        "cy from GetTextExtentExPointW (%d) and GetTextExtentPointW (%d) differ\n", sz1.cy, sz2.cy);
1520     /* Because of the '\n' in the string GetTextExtentExPoint and
1521        GetTextExtentPoint return different widths under Win2k, but
1522        under WinXP they return the same width.  So we don't test that
1523        here. */
1524 
1525     for (i = 1; i < len; ++i)
1526         ok(extents[i-1] <= extents[i],
1527            "GetTextExtentExPointW generated a non-increasing sequence of partial extents (at position %d)\n",
1528            i);
1529     ok(extents[len-1] == sz1.cx, "GetTextExtentExPointW extents and size don't match\n");
1530     ok(0 <= fit1 && fit1 <= len, "GetTextExtentExPointW generated illegal value %d for fit\n", fit1);
1531     ok(0 < fit1, "GetTextExtentExPointW says we can't even fit one letter in 32767 logical units\n");
1532     GetTextExtentExPointW(hdc, wt, len, extents[2], &fit2, NULL, &sz2);
1533     ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy, "GetTextExtentExPointW returned different sizes for the same string\n");
1534     ok(fit2 == 3, "GetTextExtentExPointW extents isn't consistent with fit\n");
1535     GetTextExtentExPointW(hdc, wt, len, extents[2]-1, &fit2, NULL, &sz2);
1536     ok(fit2 == 2, "GetTextExtentExPointW extents isn't consistent with fit\n");
1537     GetTextExtentExPointW(hdc, wt, 2, 0, NULL, extents + 2, &sz2);
1538     ok(extents[0] == extents[2] && extents[1] == extents[3],
1539        "GetTextExtentExPointW with lpnFit == NULL returns incorrect results\n");
1540     GetTextExtentExPointW(hdc, wt, 2, 0, NULL, NULL, &sz1);
1541     ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy,
1542        "GetTextExtentExPointW with lpnFit and alpDx both NULL returns incorrect results\n");
1543 
1544     /* extents functions fail with -ve counts (the interesting case being -1) */
1545     ret = GetTextExtentPointA(hdc, "o", -1, &sz);
1546     ok(ret == FALSE, "got %d\n", ret);
1547     ret = GetTextExtentExPointA(hdc, "o", -1, 0, NULL, NULL, &sz);
1548     ok(ret == FALSE, "got %d\n", ret);
1549     ret = GetTextExtentExPointW(hdc, wt, -1, 0, NULL, NULL, &sz1);
1550     ok(ret == FALSE, "got %d\n", ret);
1551 
1552     /* max_extent = 0 succeeds and returns zero */
1553     fit1 = fit2 = -215;
1554     ret = GetTextExtentExPointA(hdc, NULL, 0, 0, &fit1, NULL, &sz);
1555     ok(ret == TRUE ||
1556        broken(ret == FALSE), /* NT4, 2k */
1557        "got %d\n", ret);
1558     ok(fit1 == 0 ||
1559        broken(fit1 == -215), /* NT4, 2k */
1560        "fit = %d\n", fit1);
1561     ret = GetTextExtentExPointW(hdc, NULL, 0, 0, &fit2, NULL, &sz1);
1562     ok(ret == TRUE, "got %d\n", ret);
1563     ok(fit2 == 0, "fit = %d\n", fit2);
1564 
1565     /* max_extent = -1 is interpreted as a very large width that will
1566      * definitely fit our three characters */
1567     fit1 = fit2 = -215;
1568     ret = GetTextExtentExPointA(hdc, "One", 3, -1, &fit1, NULL, &sz);
1569     ok(ret == TRUE, "got %d\n", ret);
1570     ok(fit1 == 3, "fit = %d\n", fit1);
1571     ret = GetTextExtentExPointW(hdc, wt, 3, -1, &fit2, NULL, &sz);
1572     ok(ret == TRUE, "got %d\n", ret);
1573     ok(fit2 == 3, "fit = %d\n", fit2);
1574 
1575     /* max_extent = -2 is interpreted similarly, but the Ansi version
1576      * rejects it while the Unicode one accepts it */
1577     fit1 = fit2 = -215;
1578     ret = GetTextExtentExPointA(hdc, "One", 3, -2, &fit1, NULL, &sz);
1579     ok(ret == FALSE, "got %d\n", ret);
1580     ok(fit1 == -215, "fit = %d\n", fit1);
1581     ret = GetTextExtentExPointW(hdc, wt, 3, -2, &fit2, NULL, &sz);
1582     ok(ret == TRUE, "got %d\n", ret);
1583     ok(fit2 == 3, "fit = %d\n", fit2);
1584 
1585     hfont = SelectObject(hdc, hfont);
1586     DeleteObject(hfont);
1587 
1588     /* non-MM_TEXT mapping mode */
1589     lf.lfHeight = 2000;
1590     hfont = CreateFontIndirectA(&lf);
1591     hfont = SelectObject(hdc, hfont);
1592 
1593     SetMapMode( hdc, MM_HIMETRIC );
1594     ret = GetTextExtentExPointW(hdc, wt, 3, 0, NULL, extents, &sz);
1595     ok(ret, "got %d\n", ret);
1596     ok(sz.cx == extents[2], "got %d vs %d\n", sz.cx, extents[2]);
1597 
1598     ret = GetTextExtentExPointW(hdc, wt, 3, extents[1], &fit1, extents2, &sz2);
1599     ok(ret, "got %d\n", ret);
1600     ok(fit1 == 2, "got %d\n", fit1);
1601     ok(sz2.cx == sz.cx, "got %d vs %d\n", sz2.cx, sz.cx);
1602     for(i = 0; i < 2; i++)
1603         ok(extents2[i] == extents[i], "%d: %d, %d\n", i, extents2[i], extents[i]);
1604 
1605     hfont = SelectObject(hdc, hfont);
1606     DeleteObject(hfont);
1607     HeapFree(GetProcessHeap(), 0, extents);
1608     ReleaseDC(NULL, hdc);
1609 }
1610 
1611 static void test_GetGlyphIndices(void)
1612 {
1613     HDC      hdc;
1614     HFONT    hfont;
1615     DWORD    charcount;
1616     LOGFONTA lf;
1617     DWORD    flags = 0;
1618     WCHAR    testtext[] = {'T','e','s','t',0xffff,0};
1619     WORD     glyphs[(sizeof(testtext)/2)-1];
1620     TEXTMETRICA textm;
1621     HFONT hOldFont;
1622 
1623     if (!pGetGlyphIndicesW) {
1624         win_skip("GetGlyphIndicesW not available on platform\n");
1625         return;
1626     }
1627 
1628     hdc = GetDC(0);
1629 
1630     memset(&lf, 0, sizeof(lf));
1631     strcpy(lf.lfFaceName, "System");
1632     lf.lfHeight = 16;
1633     lf.lfCharSet = ANSI_CHARSET;
1634 
1635     hfont = CreateFontIndirectA(&lf);
1636     ok(hfont != 0, "CreateFontIndirectEx failed\n");
1637     ok(GetTextMetricsA(hdc, &textm), "GetTextMetric failed\n");
1638     if (textm.tmCharSet == ANSI_CHARSET)
1639     {
1640         flags |= GGI_MARK_NONEXISTING_GLYPHS;
1641         charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1642         ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1643         ok((glyphs[4] == 0x001f || glyphs[4] == 0xffff /* Vista */), "GetGlyphIndicesW should have returned a nonexistent char not %04x\n", glyphs[4]);
1644         flags = 0;
1645         charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1646         ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1647         ok(glyphs[4] == textm.tmDefaultChar, "GetGlyphIndicesW should have returned a %04x not %04x\n",
1648                         textm.tmDefaultChar, glyphs[4]);
1649     }
1650     else
1651         /* FIXME: Write tests for non-ANSI charsets. */
1652         skip("GetGlyphIndices System font tests only for ANSI_CHARSET\n");
1653 
1654     if(!is_font_installed("Tahoma"))
1655     {
1656         skip("Tahoma is not installed so skipping this test\n");
1657         return;
1658     }
1659     memset(&lf, 0, sizeof(lf));
1660     strcpy(lf.lfFaceName, "Tahoma");
1661     lf.lfHeight = 20;
1662 
1663     hfont = CreateFontIndirectA(&lf);
1664     hOldFont = SelectObject(hdc, hfont);
1665     ok(GetTextMetricsA(hdc, &textm), "GetTextMetric failed\n");
1666     flags |= GGI_MARK_NONEXISTING_GLYPHS;
1667     charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1668     ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1669     ok(glyphs[4] == 0xffff, "GetGlyphIndicesW should have returned 0xffff char not %04x\n", glyphs[4]);
1670     flags = 0;
1671     testtext[0] = textm.tmDefaultChar;
1672     charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1673     ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1674     ok(glyphs[0] == 0, "GetGlyphIndicesW for tmDefaultChar should be 0 not %04x\n", glyphs[0]);
1675     ok(glyphs[4] == 0, "GetGlyphIndicesW should have returned 0 not %04x\n", glyphs[4]);
1676     DeleteObject(SelectObject(hdc, hOldFont));
1677 }
1678 
1679 static void test_GetKerningPairs(void)
1680 {
1681     static const struct kerning_data
1682     {
1683         const char face_name[LF_FACESIZE];
1684         LONG height;
1685         /* some interesting fields from OUTLINETEXTMETRIC */
1686         LONG tmHeight, tmAscent, tmDescent;
1687         UINT otmEMSquare;
1688         INT  otmAscent;
1689         INT  otmDescent;
1690         UINT otmLineGap;
1691         UINT otmsCapEmHeight;
1692         UINT otmsXHeight;
1693         INT  otmMacAscent;
1694         INT  otmMacDescent;
1695         UINT otmMacLineGap;
1696         UINT otmusMinimumPPEM;
1697         /* small subset of kerning pairs to test */
1698         DWORD total_kern_pairs;
1699         const KERNINGPAIR kern_pair[26];
1700     } kd[] =
1701     {
1702         {"Arial", 12, 12, 9, 3,
1703                   2048, 7, -2, 1, 5, 2, 8, -2, 0, 9,
1704                   26,
1705             {
1706                 {' ','A',-1},{' ','T',0},{' ','Y',0},{'1','1',-1},
1707                 {'A',' ',-1},{'A','T',-1},{'A','V',-1},{'A','W',0},
1708                 {'A','Y',-1},{'A','v',0},{'A','w',0},{'A','y',0},
1709                 {'F',',',-1},{'F','.',-1},{'F','A',-1},{'L',' ',0},
1710                 {'L','T',-1},{'L','V',-1},{'L','W',-1},{'L','Y',-1},
1711                 {915,912,+1},{915,913,-1},{910,912,+1},{910,913,-1},
1712                 {933,970,+1},{933,972,-1}
1713                 }
1714         },
1715         {"Arial", -34, 39, 32, 7,
1716                   2048, 25, -7, 5, 17, 9, 31, -7, 1, 9,
1717                   26,
1718             {
1719                 {' ','A',-2},{' ','T',-1},{' ','Y',-1},{'1','1',-3},
1720                 {'A',' ',-2},{'A','T',-3},{'A','V',-3},{'A','W',-1},
1721                 {'A','Y',-3},{'A','v',-1},{'A','w',-1},{'A','y',-1},
1722                 {'F',',',-4},{'F','.',-4},{'F','A',-2},{'L',' ',-1},
1723                 {'L','T',-3},{'L','V',-3},{'L','W',-3},{'L','Y',-3},
1724                 {915,912,+3},{915,913,-3},{910,912,+3},{910,913,-3},
1725                 {933,970,+2},{933,972,-3}
1726             }
1727         },
1728         { "Arial", 120, 120, 97, 23,
1729                    2048, 79, -23, 16, 54, 27, 98, -23, 4, 9,
1730                    26,
1731             {
1732                 {' ','A',-6},{' ','T',-2},{' ','Y',-2},{'1','1',-8},
1733                 {'A',' ',-6},{'A','T',-8},{'A','V',-8},{'A','W',-4},
1734                 {'A','Y',-8},{'A','v',-2},{'A','w',-2},{'A','y',-2},
1735                 {'F',',',-12},{'F','.',-12},{'F','A',-6},{'L',' ',-4},
1736                 {'L','T',-8},{'L','V',-8},{'L','W',-8},{'L','Y',-8},
1737                 {915,912,+9},{915,913,-10},{910,912,+9},{910,913,-8},
1738                 {933,970,+6},{933,972,-10}
1739             }
1740         },
1741 #if 0 /* this set fails due to +1/-1 errors (rounding bug?), needs investigation. */
1742         { "Arial", 1024 /* usually 1/2 of EM Square */, 1024, 830, 194,
1743                    2048, 668, -193, 137, 459, 229, 830, -194, 30, 9,
1744                    26,
1745             {
1746                 {' ','A',-51},{' ','T',-17},{' ','Y',-17},{'1','1',-68},
1747                 {'A',' ',-51},{'A','T',-68},{'A','V',-68},{'A','W',-34},
1748                 {'A','Y',-68},{'A','v',-17},{'A','w',-17},{'A','y',-17},
1749                 {'F',',',-102},{'F','.',-102},{'F','A',-51},{'L',' ',-34},
1750                 {'L','T',-68},{'L','V',-68},{'L','W',-68},{'L','Y',-68},
1751                 {915,912,+73},{915,913,-84},{910,912,+76},{910,913,-68},
1752                 {933,970,+54},{933,972,-83}
1753             }
1754         }
1755 #endif
1756     };
1757     LOGFONTA lf;
1758     HFONT hfont, hfont_old;
1759     KERNINGPAIR *kern_pair;
1760     HDC hdc;
1761     DWORD total_kern_pairs, ret, i, n, matches;
1762 
1763     hdc = GetDC(0);
1764 
1765     /* GetKerningPairsA maps unicode set of kerning pairs to current code page
1766      * which may render this test unusable, so we're trying to avoid that.
1767      */
1768     SetLastError(0xdeadbeef);
1769     GetKerningPairsW(hdc, 0, NULL);
1770     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1771     {
1772         win_skip("Skipping the GetKerningPairs test on a Win9x platform\n");
1773         ReleaseDC(0, hdc);
1774         return;
1775     }
1776 
1777     for (i = 0; i < sizeof(kd)/sizeof(kd[0]); i++)
1778     {
1779         OUTLINETEXTMETRICW otm;
1780         UINT uiRet;
1781 
1782         if (!is_font_installed(kd[i].face_name))
1783         {
1784             trace("%s is not installed so skipping this test\n", kd[i].face_name);
1785             continue;
1786         }
1787 
1788         trace("testing font %s, height %d\n", kd[i].face_name, kd[i].height);
1789 
1790         memset(&lf, 0, sizeof(lf));
1791         strcpy(lf.lfFaceName, kd[i].face_name);
1792         lf.lfHeight = kd[i].height;
1793         hfont = CreateFontIndirectA(&lf);
1794         ok(hfont != NULL, "failed to create a font, name %s\n", kd[i].face_name);
1795 
1796         hfont_old = SelectObject(hdc, hfont);
1797 
1798         SetLastError(0xdeadbeef);
1799         otm.otmSize = sizeof(otm); /* just in case for Win9x compatibility */
1800         uiRet = GetOutlineTextMetricsW(hdc, sizeof(otm), &otm);
1801         ok(uiRet == sizeof(otm), "GetOutlineTextMetricsW error %d\n", GetLastError());
1802 
1803         ok(match_off_by_1(kd[i].tmHeight, otm.otmTextMetrics.tmHeight, FALSE), "expected %d, got %d\n",
1804            kd[i].tmHeight, otm.otmTextMetrics.tmHeight);
1805         ok(match_off_by_1(kd[i].tmAscent, otm.otmTextMetrics.tmAscent, FALSE), "expected %d, got %d\n",
1806            kd[i].tmAscent, otm.otmTextMetrics.tmAscent);
1807         ok(kd[i].tmDescent == otm.otmTextMetrics.tmDescent, "expected %d, got %d\n",
1808            kd[i].tmDescent, otm.otmTextMetrics.tmDescent);
1809 
1810         ok(kd[i].otmEMSquare == otm.otmEMSquare, "expected %u, got %u\n",
1811            kd[i].otmEMSquare, otm.otmEMSquare);
1812         ok(kd[i].otmAscent == otm.otmAscent, "expected %d, got %d\n",
1813            kd[i].otmAscent, otm.otmAscent);
1814         ok(kd[i].otmDescent == otm.otmDescent, "expected %d, got %d\n",
1815            kd[i].otmDescent, otm.otmDescent);
1816         ok(kd[i].otmLineGap == otm.otmLineGap, "expected %u, got %u\n",
1817            kd[i].otmLineGap, otm.otmLineGap);
1818         ok(near_match(kd[i].otmMacDescent, otm.otmMacDescent), "expected %d, got %d\n",
1819            kd[i].otmMacDescent, otm.otmMacDescent);
1820         ok(near_match(kd[i].otmMacAscent, otm.otmMacAscent), "expected %d, got %d\n",
1821            kd[i].otmMacAscent, otm.otmMacAscent);
1822 todo_wine
1823         ok(kd[i].otmsCapEmHeight == otm.otmsCapEmHeight, "expected %u, got %u\n",
1824            kd[i].otmsCapEmHeight, otm.otmsCapEmHeight);
1825 todo_wine
1826         ok(kd[i].otmsXHeight == otm.otmsXHeight, "expected %u, got %u\n",
1827            kd[i].otmsXHeight, otm.otmsXHeight);
1828         ok(kd[i].otmMacLineGap == otm.otmMacLineGap, "expected %u, got %u\n",
1829            kd[i].otmMacLineGap, otm.otmMacLineGap);
1830 todo_wine
1831         ok(kd[i].otmusMinimumPPEM == otm.otmusMinimumPPEM, "expected %u, got %u\n",
1832            kd[i].otmusMinimumPPEM, otm.otmusMinimumPPEM);
1833 
1834         total_kern_pairs = GetKerningPairsW(hdc, 0, NULL);
1835         trace("total_kern_pairs %u\n", total_kern_pairs);
1836         kern_pair = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pair));
1837 
1838         /* Win98 (GetKerningPairsA) and XP behave differently here, the test
1839          * passes on XP.
1840          */
1841         SetLastError(0xdeadbeef);
1842         ret = GetKerningPairsW(hdc, 0, kern_pair);
1843         ok(GetLastError() == ERROR_INVALID_PARAMETER,
1844            "got error %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
1845         ok(ret == 0, "got %u, expected 0\n", ret);
1846 
1847         ret = GetKerningPairsW(hdc, 100, NULL);
1848         ok(ret == total_kern_pairs, "got %u, expected %u\n", ret, total_kern_pairs);
1849 
1850         ret = GetKerningPairsW(hdc, total_kern_pairs/2, kern_pair);
1851         ok(ret == total_kern_pairs/2, "got %u, expected %u\n", ret, total_kern_pairs/2);
1852 
1853         ret = GetKerningPairsW(hdc, total_kern_pairs, kern_pair);
1854         ok(ret == total_kern_pairs, "got %u, expected %u\n", ret, total_kern_pairs);
1855 
1856         matches = 0;
1857 
1858         for (n = 0; n < ret; n++)
1859         {
1860             DWORD j;
1861             /* Disabled to limit console spam */
1862             if (0 && kern_pair[n].wFirst < 127 && kern_pair[n].wSecond < 127)
1863                 trace("{'%c','%c',%d},\n",
1864                       kern_pair[n].wFirst, kern_pair[n].wSecond, kern_pair[n].iKernAmount);
1865             for (j = 0; j < kd[i].total_kern_pairs; j++)
1866             {
1867                 if (kern_pair[n].wFirst == kd[i].kern_pair[j].wFirst &&
1868                     kern_pair[n].wSecond == kd[i].kern_pair[j].wSecond)
1869                 {
1870                     ok(kern_pair[n].iKernAmount == kd[i].kern_pair[j].iKernAmount,
1871                        "pair %d:%d got %d, expected %d\n",
1872                        kern_pair[n].wFirst, kern_pair[n].wSecond,
1873                        kern_pair[n].iKernAmount, kd[i].kern_pair[j].iKernAmount);
1874                     matches++;
1875                 }
1876             }
1877         }
1878 
1879         ok(matches == kd[i].total_kern_pairs, "got matches %u, expected %u\n",
1880            matches, kd[i].total_kern_pairs);
1881 
1882         HeapFree(GetProcessHeap(), 0, kern_pair);
1883 
1884         SelectObject(hdc, hfont_old);
1885         DeleteObject(hfont);
1886     }
1887 
1888     ReleaseDC(0, hdc);
1889 }
1890 
1891 struct font_data
1892 {
1893     const char face_name[LF_FACESIZE];
1894     int requested_height;
1895     int weight, height, ascent, descent, int_leading, ext_leading, dpi;
1896     BOOL exact;
1897 };
1898 
1899 static void test_height( HDC hdc, const struct font_data *fd )
1900 {
1901     LOGFONTA lf;
1902     HFONT hfont, old_hfont;
1903     TEXTMETRICA tm;
1904     INT ret, i;
1905 
1906     for (i = 0; fd[i].face_name[0]; i++)
1907     {
1908         if (!is_truetype_font_installed(fd[i].face_name))
1909         {
1910             skip("%s is not installed\n", fd[i].face_name);
1911             continue;
1912         }
1913 
1914         memset(&lf, 0, sizeof(lf));
1915         lf.lfHeight = fd[i].requested_height;
1916         lf.lfWeight = fd[i].weight;
1917         strcpy(lf.lfFaceName, fd[i].face_name);
1918 
1919         hfont = CreateFontIndirectA(&lf);
1920         ok(hfont != NULL, "failed to create a font, name %s\n", fd[i].face_name);
1921 
1922         old_hfont = SelectObject(hdc, hfont);
1923         ret = GetTextMetricsA(hdc, &tm);
1924         ok(ret, "GetTextMetrics error %d\n", GetLastError());
1925         if(fd[i].dpi == tm.tmDigitizedAspectX)
1926         {
1927             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);
1928             ok(match_off_by_1(tm.tmHeight, fd[i].height, fd[i].exact), "%s(%d): tm.tmHeight %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmHeight, fd[i].height);
1929             ok(match_off_by_1(tm.tmAscent, fd[i].ascent, fd[i].exact), "%s(%d): tm.tmAscent %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmAscent, fd[i].ascent);
1930             ok(match_off_by_1(tm.tmDescent, fd[i].descent, fd[i].exact), "%s(%d): tm.tmDescent %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmDescent, fd[i].descent);
1931             ok(match_off_by_1(tm.tmInternalLeading, fd[i].int_leading, fd[i].exact), "%s(%d): tm.tmInternalLeading %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmInternalLeading, fd[i].int_leading);
1932             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);
1933         }
1934 
1935         SelectObject(hdc, old_hfont);
1936         /* force GDI to use new font, otherwise Windows leaks the font reference */
1937         GetTextMetricsA(hdc, &tm);
1938         DeleteObject(hfont);
1939     }
1940 }
1941 
1942 static void *find_ttf_table( void *ttf, DWORD size, DWORD tag )
1943 {
1944     WORD i, num_tables = GET_BE_WORD(*((WORD *)ttf + 2));
1945     DWORD *table = (DWORD *)ttf + 3;
1946 
1947     for (i = 0; i < num_tables; i++)
1948     {
1949         if (table[0] == tag)
1950             return (BYTE *)ttf + GET_BE_DWORD(table[2]);
1951         table += 4;
1952     }
1953     return NULL;
1954 }
1955 
1956 static void test_height_selection_vdmx( HDC hdc )
1957 {
1958     static const struct font_data charset_0[] = /* doesn't use VDMX */
1959     {
1960         { "wine_vdmx", 10, FW_NORMAL, 10, 8, 2, 2, 0, 96, TRUE },
1961         { "wine_vdmx", 11, FW_NORMAL, 11, 9, 2, 2, 0, 96, TRUE },
1962         { "wine_vdmx", 12, FW_NORMAL, 12, 10, 2, 2, 0, 96, TRUE },
1963         { "wine_vdmx", 13, FW_NORMAL, 13, 11, 2, 2, 0, 96, TRUE },
1964         { "wine_vdmx", 14, FW_NORMAL, 14, 12, 2, 2, 0, 96, TRUE },
1965         { "wine_vdmx", 15, FW_NORMAL, 15, 12, 3, 3, 0, 96, FALSE },
1966         { "wine_vdmx", 16, FW_NORMAL, 16, 13, 3, 3, 0, 96, TRUE },
1967         { "wine_vdmx", 17, FW_NORMAL, 17, 14, 3, 3, 0, 96, TRUE },
1968         { "wine_vdmx", 18, FW_NORMAL, 18, 15, 3, 3, 0, 96, TRUE },
1969         { "wine_vdmx", 19, FW_NORMAL, 19, 16, 3, 3, 0, 96, TRUE },
1970         { "wine_vdmx", 20, FW_NORMAL, 20, 17, 3, 4, 0, 96, FALSE },
1971         { "wine_vdmx", 21, FW_NORMAL, 21, 17, 4, 4, 0, 96, TRUE },
1972         { "wine_vdmx", 22, FW_NORMAL, 22, 18, 4, 4, 0, 96, TRUE },
1973         { "wine_vdmx", 23, FW_NORMAL, 23, 19, 4, 4, 0, 96, TRUE },
1974         { "wine_vdmx", 24, FW_NORMAL, 24, 20, 4, 4, 0, 96, TRUE },
1975         { "wine_vdmx", 25, FW_NORMAL, 25, 21, 4, 4, 0, 96, TRUE },
1976         { "wine_vdmx", 26, FW_NORMAL, 26, 22, 4, 5, 0, 96, FALSE },
1977         { "wine_vdmx", 27, FW_NORMAL, 27, 22, 5, 5, 0, 96, TRUE },
1978         { "wine_vdmx", 28, FW_NORMAL, 28, 23, 5, 5, 0, 96, TRUE },
1979         { "wine_vdmx", 29, FW_NORMAL, 29, 24, 5, 5, 0, 96, TRUE },
1980         { "wine_vdmx", 30, FW_NORMAL, 30, 25, 5, 5, 0, 96, TRUE },
1981         { "wine_vdmx", 31, FW_NORMAL, 31, 26, 5, 5, 0, 96, TRUE },
1982         { "wine_vdmx", 32, FW_NORMAL, 32, 27, 5, 6, 0, 96, FALSE },
1983         { "wine_vdmx", 48, FW_NORMAL, 48, 40, 8, 8, 0, 96, TRUE },
1984         { "wine_vdmx", 64, FW_NORMAL, 64, 53, 11, 11, 0, 96, TRUE },
1985         { "wine_vdmx", 96, FW_NORMAL, 96, 80, 16, 17, 0, 96, FALSE },
1986         { "wine_vdmx", -10, FW_NORMAL, 12, 10, 2, 2, 0, 96, TRUE },
1987         { "wine_vdmx", -11, FW_NORMAL, 13, 11, 2, 2, 0, 96, TRUE },
1988         { "wine_vdmx", -12, FW_NORMAL, 14, 12, 2, 2, 0, 96, TRUE },
1989         { "wine_vdmx", -13, FW_NORMAL, 16, 13, 3, 3, 0, 96, TRUE },
1990         { "wine_vdmx", -14, FW_NORMAL, 17, 14, 3, 3, 0, 96, TRUE },
1991         { "wine_vdmx", -15, FW_NORMAL, 18, 15, 3, 3, 0, 96, TRUE },
1992         { "wine_vdmx", -16, FW_NORMAL, 19, 16, 3, 3, 0, 96, TRUE },
1993         { "wine_vdmx", -17, FW_NORMAL, 21, 17, 4, 4, 0, 96, TRUE },
1994         { "wine_vdmx", -18, FW_NORMAL, 22, 18, 4, 4, 0, 96, TRUE },
1995         { "wine_vdmx", -19, FW_NORMAL, 23, 19, 4, 4, 0, 96, TRUE },
1996         { "wine_vdmx", -20, FW_NORMAL, 24, 20, 4, 4, 0, 96, TRUE },
1997         { "wine_vdmx", -21, FW_NORMAL, 25, 21, 4, 4, 0, 96, TRUE },
1998         { "wine_vdmx", -22, FW_NORMAL, 27, 22, 5, 5, 0, 96, TRUE },
1999         { "wine_vdmx", -23, FW_NORMAL, 28, 23, 5, 5, 0, 96, TRUE },
2000         { "wine_vdmx", -24, FW_NORMAL, 29, 24, 5, 5, 0, 96, TRUE },
2001         { "wine_vdmx", -25, FW_NORMAL, 30, 25, 5, 5, 0, 96, TRUE },
2002         { "wine_vdmx", -26, FW_NORMAL, 31, 26, 5, 5, 0, 96, TRUE },
2003         { "wine_vdmx", -27, FW_NORMAL, 33, 27, 6, 6, 0, 96, TRUE },
2004         { "wine_vdmx", -28, FW_NORMAL, 34, 28, 6, 6, 0, 96, TRUE },
2005         { "wine_vdmx", -29, FW_NORMAL, 35, 29, 6, 6, 0, 96, TRUE },
2006         { "wine_vdmx", -30, FW_NORMAL, 36, 30, 6, 6, 0, 96, TRUE },
2007         { "wine_vdmx", -31, FW_NORMAL, 37, 31, 6, 6, 0, 96, TRUE },
2008         { "wine_vdmx", -32, FW_NORMAL, 39, 32, 7, 7, 0, 96, TRUE },
2009         { "wine_vdmx", -48, FW_NORMAL, 58, 48, 10, 10, 0, 96, TRUE },
2010         { "wine_vdmx", -64, FW_NORMAL, 77, 64, 13, 13, 0, 96, TRUE },
2011         { "wine_vdmx", -96, FW_NORMAL, 116, 96, 20, 20, 0, 96, TRUE },
2012         { "", 0, 0, 0, 0, 0, 0, 0, 0, 0 }
2013     };
2014 
2015     static const struct font_data charset_1[] = /* Uses VDMX */
2016     {
2017         { "wine_vdmx", 10, FW_NORMAL, 10, 8, 2, 2, 0, 96, TRUE },
2018         { "wine_vdmx", 11, FW_NORMAL, 11, 9, 2, 2, 0, 96, TRUE },
2019         { "wine_vdmx", 12, FW_NORMAL, 12, 10, 2, 2, 0, 96, TRUE },
2020         { "wine_vdmx", 13, FW_NORMAL, 13, 11, 2, 2, 0, 96, TRUE },
2021         { "wine_vdmx", 14, FW_NORMAL, 13, 11, 2, 2, 0, 96, TRUE },
2022         { "wine_vdmx", 15, FW_NORMAL, 13, 11, 2, 2, 0, 96, TRUE },
2023         { "wine_vdmx", 16, FW_NORMAL, 16, 13, 3, 4, 0, 96, TRUE },
2024         { "wine_vdmx", 17, FW_NORMAL, 16, 13, 3, 3, 0, 96, TRUE },
2025         { "wine_vdmx", 18, FW_NORMAL, 16, 13, 3, 3, 0, 96, TRUE },
2026         { "wine_vdmx", 19, FW_NORMAL, 19, 15, 4, 5, 0, 96, TRUE },
2027         { "wine_vdmx", 20, FW_NORMAL, 20, 16, 4, 5, 0, 96, TRUE },
2028         { "wine_vdmx", 21, FW_NORMAL, 21, 17, 4, 5, 0, 96, TRUE },
2029         { "wine_vdmx", 22, FW_NORMAL, 22, 18, 4, 5, 0, 96, TRUE },
2030         { "wine_vdmx", 23, FW_NORMAL, 23, 19, 4, 5, 0, 96, TRUE },
2031         { "wine_vdmx", 24, FW_NORMAL, 23, 19, 4, 5, 0, 96, TRUE },
2032         { "wine_vdmx", 25, FW_NORMAL, 25, 21, 4, 6, 0, 96, TRUE },
2033         { "wine_vdmx", 26, FW_NORMAL, 26, 22, 4, 6, 0, 96, TRUE },
2034         { "wine_vdmx", 27, FW_NORMAL, 27, 23, 4, 6, 0, 96, TRUE },
2035         { "wine_vdmx", 28, FW_NORMAL, 27, 23, 4, 5, 0, 96, TRUE },
2036         { "wine_vdmx", 29, FW_NORMAL, 29, 24, 5, 6, 0, 96, TRUE },
2037         { "wine_vdmx", 30, FW_NORMAL, 29, 24, 5, 6, 0, 96, TRUE },
2038         { "wine_vdmx", 31, FW_NORMAL, 29, 24, 5, 6, 0, 96, TRUE },
2039         { "wine_vdmx", 32, FW_NORMAL, 32, 26, 6, 8, 0, 96, TRUE },
2040         { "wine_vdmx", 48, FW_NORMAL, 48, 40, 8, 10, 0, 96, TRUE },
2041         { "wine_vdmx", 64, FW_NORMAL, 64, 54, 10, 13, 0, 96, TRUE },
2042         { "wine_vdmx", 96, FW_NORMAL, 95, 79, 16, 18, 0, 96, TRUE },
2043         { "wine_vdmx", -10, FW_NORMAL, 12, 10, 2, 2, 0, 96, TRUE },
2044         { "wine_vdmx", -11, FW_NORMAL, 13, 11, 2, 2, 0, 96, TRUE },
2045         { "wine_vdmx", -12, FW_NORMAL, 16, 13, 3, 4, 0, 96, TRUE },
2046         { "wine_vdmx", -13, FW_NORMAL, 16, 13, 3, 3, 0, 96, TRUE },
2047         { "wine_vdmx", -14, FW_NORMAL, 19, 15, 4, 5, 0, 96, TRUE },
2048         { "wine_vdmx", -15, FW_NORMAL, 20, 16, 4, 5, 0, 96, TRUE },
2049         { "wine_vdmx", -16, FW_NORMAL, 21, 17, 4, 5, 0, 96, TRUE },
2050         { "wine_vdmx", -17, FW_NORMAL, 22, 18, 4, 5, 0, 96, TRUE },
2051         { "wine_vdmx", -18, FW_NORMAL, 23, 19, 4, 5, 0, 96, TRUE },
2052         { "wine_vdmx", -19, FW_NORMAL, 25, 21, 4, 6, 0, 96, TRUE },
2053         { "wine_vdmx", -20, FW_NORMAL, 26, 22, 4, 6, 0, 96, TRUE },
2054         { "wine_vdmx", -21, FW_NORMAL, 27, 23, 4, 6, 0, 96, TRUE },
2055         { "wine_vdmx", -22, FW_NORMAL, 27, 23, 4, 5, 0, 96, TRUE },
2056         { "wine_vdmx", -23, FW_NORMAL, 29, 24, 5, 6, 0, 96, TRUE },
2057         { "wine_vdmx", -24, FW_NORMAL, 32, 26, 6, 8, 0, 96, TRUE },
2058         { "wine_vdmx", -25, FW_NORMAL, 32, 26, 6, 7, 0, 96, TRUE },
2059         { "wine_vdmx", -26, FW_NORMAL, 33, 27, 6, 7, 0, 96, TRUE },
2060         { "wine_vdmx", -27, FW_NORMAL, 35, 29, 6, 8, 0, 96, TRUE },
2061         { "wine_vdmx", -28, FW_NORMAL, 36, 30, 6, 8, 0, 96, TRUE },
2062         { "wine_vdmx", -29, FW_NORMAL, 36, 30, 6, 7, 0, 96, TRUE },
2063         { "wine_vdmx", -30, FW_NORMAL, 38, 32, 6, 8, 0, 96, TRUE },
2064         { "wine_vdmx", -31, FW_NORMAL, 39, 33, 6, 8, 0, 96, TRUE },
2065         { "wine_vdmx", -32, FW_NORMAL, 40, 33, 7, 8, 0, 96, TRUE },
2066         { "wine_vdmx", -48, FW_NORMAL, 60, 50, 10, 12, 0, 96, TRUE },
2067         { "wine_vdmx", -64, FW_NORMAL, 81, 67, 14, 17, 0, 96, TRUE },
2068         { "wine_vdmx", -96, FW_NORMAL, 119, 99, 20, 23, 0, 96, TRUE },
2069         { "", 0, 0, 0, 0, 0, 0, 0, 0, 0 }
2070     };
2071 
2072     static const struct vdmx_data
2073     {
2074         WORD version;
2075         BYTE bCharSet;
2076         const struct font_data *fd;
2077     } data[] =
2078     {
2079         { 0, 0, charset_0 },
2080         { 0, 1, charset_1 },
2081         { 1, 0, charset_0 },
2082         { 1, 1, charset_1 }
2083     };
2084     int i;
2085     DWORD size, num;
2086     WORD *vdmx_header;
2087     BYTE *ratio_rec;
2088     char ttf_name[MAX_PATH];
2089     void *res, *copy;
2090     BOOL ret;
2091 
2092     if (!pAddFontResourceExA)
2093     {
2094         win_skip("AddFontResourceExA unavailable\n");
2095         return;
2096     }
2097 
2098     for (i = 0; i < sizeof(data) / sizeof(data[0]); i++)
2099     {
2100         res = get_res_data( "wine_vdmx.ttf", &size );
2101 
2102         copy = HeapAlloc( GetProcessHeap(), 0, size );
2103         memcpy( copy, res, size );
2104         vdmx_header = find_ttf_table( copy, size, MS_MAKE_TAG('V','D','M','X') );
2105         vdmx_header[0] = GET_BE_WORD( data[i].version );
2106         ok( GET_BE_WORD( vdmx_header[1] ) == 1, "got %04x\n", GET_BE_WORD( vdmx_header[1] ) );
2107         ok( GET_BE_WORD( vdmx_header[2] ) == 1, "got %04x\n", GET_BE_WORD( vdmx_header[2] ) );
2108         ratio_rec = (BYTE *)&vdmx_header[3];
2109         ratio_rec[0] = data[i].bCharSet;
2110 
2111         write_tmp_file( copy, &size, ttf_name );
2112         HeapFree( GetProcessHeap(), 0, copy );
2113 
2114         ok( !is_truetype_font_installed("wine_vdmx"), "Already installed\n" );
2115         num = pAddFontResourceExA( ttf_name, FR_PRIVATE, 0 );
2116         if (!num) win_skip("Unable to add ttf font resource\n");
2117         else
2118         {
2119             ok( is_truetype_font_installed("wine_vdmx"), "Not installed\n" );
2120             test_height( hdc, data[i].fd );
2121             pRemoveFontResourceExA( ttf_name, FR_PRIVATE, 0 );
2122         }
2123         ret = DeleteFileA( ttf_name );
2124         ok(ret || broken(!ret && GetLastError() == ERROR_ACCESS_DENIED),
2125            "DeleteFile error %d\n", GetLastError());
2126     }
2127 }
2128 
2129 static void test_height_selection(void)
2130 {
2131     static const struct font_data tahoma[] =
2132     {
2133         {"Tahoma", -12, FW_NORMAL, 14, 12, 2, 2, 0, 96, TRUE },
2134         {"Tahoma", -24, FW_NORMAL, 29, 24, 5, 5, 0, 96, TRUE },
2135         {"Tahoma", -48, FW_NORMAL, 58, 48, 10, 10, 0, 96, TRUE },
2136         {"Tahoma", -96, FW_NORMAL, 116, 96, 20, 20, 0, 96, TRUE },
2137         {"Tahoma", -192, FW_NORMAL, 232, 192, 40, 40, 0, 96, TRUE },
2138         {"Tahoma", 12, FW_NORMAL, 12, 10, 2, 2, 0, 96, TRUE },
2139         {"Tahoma", 24, FW_NORMAL, 24, 20, 4, 4, 0, 96, TRUE },
2140         {"Tahoma", 48, FW_NORMAL, 48, 40, 8, 8, 0, 96, TRUE },
2141         {"Tahoma", 96, FW_NORMAL, 96, 80, 16, 17, 0, 96, FALSE },
2142         {"Tahoma", 192, FW_NORMAL, 192, 159, 33, 33, 0, 96, TRUE },
2143         {"", 0, 0, 0, 0, 0, 0, 0, 0, 0 }
2144     };
2145     HDC hdc = CreateCompatibleDC(0);
2146     ok(hdc != NULL, "failed to create hdc\n");
2147 
2148     test_height( hdc, tahoma );
2149     test_height_selection_vdmx( hdc );
2150 
2151     DeleteDC(hdc);
2152 }
2153 
2154 static UINT get_font_fsselection(LOGFONTA *lf)
2155 {
2156     OUTLINETEXTMETRICA *otm;
2157     HFONT hfont, hfont_old;
2158     DWORD ret, otm_size;
2159     UINT fsSelection;
2160     HDC hdc;
2161 
2162     hdc = GetDC(0);
2163     hfont = CreateFontIndirectA(lf);
2164     ok(hfont != NULL, "failed to create a font\n");
2165 
2166     hfont_old = SelectObject(hdc, hfont);
2167 
2168     otm_size = GetOutlineTextMetricsA(hdc, 0, NULL);
2169     otm = HeapAlloc(GetProcessHeap(), 0, otm_size);
2170     otm->otmSize = sizeof(*otm);
2171     ret = GetOutlineTextMetricsA(hdc, otm->otmSize, otm);
2172     ok(ret == otm->otmSize, "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
2173     fsSelection = otm->otmfsSelection;
2174     HeapFree(GetProcessHeap(), 0, otm);
2175     SelectObject(hdc, hfont_old);
2176     DeleteObject(hfont);
2177     ReleaseDC(0, hdc);
2178 
2179     return fsSelection;
2180 }
2181 
2182 static void test_GetOutlineTextMetrics(void)
2183 {
2184     OUTLINETEXTMETRICA *otm;
2185     LOGFONTA lf;
2186     HFONT hfont, hfont_old;
2187     HDC hdc;
2188     DWORD ret, otm_size;
2189     LPSTR unset_ptr;
2190     UINT fsSelection;
2191 
2192     /* check fsSelection field with bold simulation */
2193     memset(&lf, 0, sizeof(lf));
2194     strcpy(lf.lfFaceName, "Wingdings");
2195     lf.lfCharSet = SYMBOL_CHARSET;
2196 
2197     /* regular face */
2198     fsSelection = get_font_fsselection(&lf);
2199     ok((fsSelection & (1 << 5)) == 0, "got 0x%x\n", fsSelection);
2200 
2201     /* face with bold simulation */
2202     lf.lfWeight = FW_BOLD;
2203     fsSelection = get_font_fsselection(&lf);
2204     ok((fsSelection & (1 << 5)) != 0, "got 0x%x\n", fsSelection);
2205 
2206     /* check fsSelection field with oblique simulation */
2207     memset(&lf, 0, sizeof(lf));
2208     strcpy(lf.lfFaceName, "Tahoma");
2209     lf.lfHeight = -13;
2210     lf.lfWeight = FW_NORMAL;
2211     lf.lfPitchAndFamily = DEFAULT_PITCH;
2212     lf.lfQuality = PROOF_QUALITY;
2213 
2214     /* regular face */
2215     fsSelection = get_font_fsselection(&lf);
2216     ok((fsSelection & 1) == 0, "got 0x%x\n", fsSelection);
2217 
2218     lf.lfItalic = 1;
2219     /* face with oblique simulation */
2220     fsSelection = get_font_fsselection(&lf);
2221     ok((fsSelection & 1) == 1, "got 0x%x\n", fsSelection);
2222 
2223     if (!is_font_installed("Arial"))
2224     {
2225         skip("Arial is not installed\n");
2226         return;
2227     }
2228 
2229     hdc = GetDC(0);
2230 
2231     memset(&lf, 0, sizeof(lf));
2232     strcpy(lf.lfFaceName, "Arial");
2233     lf.lfHeight = -13;
2234     lf.lfWeight = FW_NORMAL;
2235     lf.lfPitchAndFamily = DEFAULT_PITCH;
2236     lf.lfQuality = PROOF_QUALITY;
2237     hfont = CreateFontIndirectA(&lf);
2238     ok(hfont != NULL, "failed to create a font\n");
2239 
2240     hfont_old = SelectObject(hdc, hfont);
2241     otm_size = GetOutlineTextMetricsA(hdc, 0, NULL);
2242     trace("otm buffer size %u (0x%x)\n", otm_size, otm_size);
2243 
2244     otm = HeapAlloc(GetProcessHeap(), 0, otm_size);
2245 
2246     memset(otm, 0xAA, otm_size);
2247     SetLastError(0xdeadbeef);
2248     otm->otmSize = sizeof(*otm); /* just in case for Win9x compatibility */
2249     ret = GetOutlineTextMetricsA(hdc, otm->otmSize, otm);
2250     ok(ret == 1 /* Win9x */ ||
2251        ret == otm->otmSize /* XP*/,
2252        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
2253     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
2254     {
2255         ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
2256         ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
2257         ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
2258         ok(otm->otmpFullName == NULL, "expected NULL got %p\n", otm->otmpFullName);
2259     }
2260 
2261     memset(otm, 0xAA, otm_size);
2262     SetLastError(0xdeadbeef);
2263     otm->otmSize = otm_size; /* just in case for Win9x compatibility */
2264     ret = GetOutlineTextMetricsA(hdc, otm->otmSize, otm);
2265     ok(ret == 1 /* Win9x */ ||
2266        ret == otm->otmSize /* XP*/,
2267        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
2268     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
2269     {
2270         ok(otm->otmpFamilyName != NULL, "expected not NULL got %p\n", otm->otmpFamilyName);
2271         ok(otm->otmpFaceName != NULL, "expected not NULL got %p\n", otm->otmpFaceName);
2272         ok(otm->otmpStyleName != NULL, "expected not NULL got %p\n", otm->otmpStyleName);
2273         ok(otm->otmpFullName != NULL, "expected not NULL got %p\n", otm->otmpFullName);
2274     }
2275 
2276     /* ask about truncated data */
2277     memset(otm, 0xAA, otm_size);
2278     memset(&unset_ptr, 0xAA, sizeof(unset_ptr));
2279     SetLastError(0xdeadbeef);
2280     otm->otmSize = sizeof(*otm) - sizeof(LPSTR); /* just in case for Win9x compatibility */
2281     ret = GetOutlineTextMetricsA(hdc, otm->otmSize, otm);
2282     ok(ret == 1 /* Win9x */ ||
2283        ret == otm->otmSize /* XP*/,
2284        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
2285     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
2286     {
2287         ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
2288         ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
2289         ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
2290     }
2291     ok(otm->otmpFullName == unset_ptr, "expected %p got %p\n", unset_ptr, otm->otmpFullName);
2292 
2293     /* check handling of NULL pointer */
2294     SetLastError(0xdeadbeef);
2295     ret = GetOutlineTextMetricsA(hdc, otm_size, NULL);
2296     ok(ret == otm_size, "expected %u, got %u, error %d\n", otm_size, ret, GetLastError());
2297 
2298     HeapFree(GetProcessHeap(), 0, otm);
2299 
2300     SelectObject(hdc, hfont_old);
2301     DeleteObject(hfont);
2302 
2303     ReleaseDC(0, hdc);
2304 }
2305 
2306 static void testJustification(HDC hdc, PCSTR str, RECT *clientArea)
2307 {
2308     INT         y,
2309                 breakCount,
2310                 areaWidth = clientArea->right - clientArea->left,
2311                 nErrors = 0, e;
2312     const char *pFirstChar, *pLastChar;
2313     SIZE        size;
2314     TEXTMETRICA tm;
2315     struct err
2316     {
2317         const char *start;
2318         int  len;
2319         int  GetTextExtentExPointWWidth;
2320     } error[20];
2321 
2322     GetTextMetricsA(hdc, &tm);
2323     y = clientArea->top;
2324     do {
2325         breakCount = 0;
2326         while (*str == tm.tmBreakChar) str++; /* skip leading break chars */
2327         pFirstChar = str;
2328 
2329         do {
2330             pLastChar = str;
2331 
2332             /* if not at the end of the string, ... */
2333             if (*str == '\0') break;
2334             /* ... add the next word to the current extent */
2335             while (*str != '\0' && *str++ != tm.tmBreakChar);
2336             breakCount++;
2337             SetTextJustification(hdc, 0, 0);
2338             GetTextExtentPoint32A(hdc, pFirstChar, str - pFirstChar - 1, &size);
2339         } while ((int) size.cx < areaWidth);
2340 
2341         /* ignore trailing break chars */
2342         breakCount--;
2343         while (*(pLastChar - 1) == tm.tmBreakChar)
2344         {
2345             pLastChar--;
2346             breakCount--;
2347         }
2348 
2349         if (*str == '\0' || breakCount <= 0) pLastChar = str;
2350 
2351         SetTextJustification(hdc, 0, 0);
2352         GetTextExtentPoint32A(hdc, pFirstChar, pLastChar - pFirstChar, &size);
2353 
2354         /* do not justify the last extent */
2355         if (*str != '\0' && breakCount > 0)
2356         {
2357             SetTextJustification(hdc, areaWidth - size.cx, breakCount);
2358             GetTextExtentPoint32A(hdc, pFirstChar, pLastChar - pFirstChar, &size);
2359             if (size.cx != areaWidth && nErrors < sizeof(error)/sizeof(error[0]) - 1)
2360             {
2361                 error[nErrors].start = pFirstChar;
2362                 error[nErrors].len = pLastChar - pFirstChar;
2363                 error[nErrors].GetTextExtentExPointWWidth = size.cx;
2364                 nErrors++;
2365             }
2366         }
2367 
2368         y += size.cy;
2369         str = pLastChar;
2370     } while (*str && y < clientArea->bottom);
2371 
2372     for (e = 0; e < nErrors; e++)
2373     {
2374         /* The width returned by GetTextExtentPoint32() is exactly the same
2375            returned by GetTextExtentExPointW() - see dlls/gdi32/font.c */
2376         ok(error[e].GetTextExtentExPointWWidth == areaWidth,
2377             "GetTextExtentPointW() for \"%.*s\" should have returned a width of %d, not %d.\n",
2378            error[e].len, error[e].start, areaWidth, error[e].GetTextExtentExPointWWidth);
2379     }
2380 }
2381 
2382 static void test_SetTextJustification(void)
2383 {
2384     HDC hdc;
2385     RECT clientArea;
2386     LOGFONTA lf;
2387     HFONT hfont;
2388     HWND hwnd;
2389     SIZE size, expect;
2390     int i;
2391     WORD indices[2];
2392     static const char testText[] =
2393             "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
2394             "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
2395             "enim ad minim veniam, quis nostrud exercitation ullamco laboris "
2396             "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in "
2397             "reprehenderit in voluptate velit esse cillum dolore eu fugiat "
2398             "nulla pariatur. Excepteur sint occaecat cupidatat non proident, "
2399             "sunt in culpa qui officia deserunt mollit anim id est laborum.";
2400 
2401     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0, 400,400, 0, 0, 0, NULL);
2402     GetClientRect( hwnd, &clientArea );
2403     hdc = GetDC( hwnd );
2404 
2405     if (!is_font_installed("Times New Roman"))
2406     {
2407         skip("Times New Roman is not installed\n");
2408         return;
2409     }
2410 
2411     memset(&lf, 0, sizeof lf);
2412     lf.lfCharSet = ANSI_CHARSET;
2413     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
2414     lf.lfWeight = FW_DONTCARE;
2415     lf.lfHeight = 20;
2416     lf.lfQuality = DEFAULT_QUALITY;
2417     lstrcpyA(lf.lfFaceName, "Times New Roman");
2418     hfont = create_font("Times New Roman", &lf);
2419     SelectObject(hdc, hfont);
2420 
2421     testJustification(hdc, testText, &clientArea);
2422 
2423     if (!pGetGlyphIndicesA || !pGetTextExtentExPointI) goto done;
2424     pGetGlyphIndicesA( hdc, "A ", 2, indices, 0 );
2425 
2426     SetTextJustification(hdc, 0, 0);
2427     GetTextExtentPoint32A(hdc, " ", 1, &expect);
2428     GetTextExtentPoint32A(hdc, "   ", 3, &size);
2429     ok( size.cx == 3 * expect.cx, "wrong size %d/%d\n", size.cx, expect.cx );
2430     SetTextJustification(hdc, 4, 1);
2431     GetTextExtentPoint32A(hdc, " ", 1, &size);
2432     ok( size.cx == expect.cx + 4, "wrong size %d/%d\n", size.cx, expect.cx );
2433     SetTextJustification(hdc, 9, 2);
2434     GetTextExtentPoint32A(hdc, "  ", 2, &size);
2435     ok( size.cx == 2 * expect.cx + 9, "wrong size %d/%d\n", size.cx, expect.cx );
2436     SetTextJustification(hdc, 7, 3);
2437     GetTextExtentPoint32A(hdc, "   ", 3, &size);
2438     ok( size.cx == 3 * expect.cx + 7, "wrong size %d/%d\n", size.cx, expect.cx );
2439     SetTextJustification(hdc, 7, 3);
2440     SetTextCharacterExtra(hdc, 2 );
2441     GetTextExtentPoint32A(hdc, "   ", 3, &size);
2442     ok( size.cx == 3 * (expect.cx + 2) + 7, "wrong size %d/%d\n", size.cx, expect.cx );
2443     SetTextJustification(hdc, 0, 0);
2444     SetTextCharacterExtra(hdc, 0);
2445     size.cx = size.cy = 1234;
2446     GetTextExtentPoint32A(hdc, " ", 0, &size);
2447     ok( size.cx == 0 && size.cy == 0, "wrong size %d,%d\n", size.cx, size.cy );
2448     pGetTextExtentExPointI(hdc, indices, 2, -1, NULL, NULL, &expect);
2449     SetTextJustification(hdc, 5, 1);
2450     pGetTextExtentExPointI(hdc, indices, 2, -1, NULL, NULL, &size);
2451     ok( size.cx == expect.cx + 5, "wrong size %d/%d\n", size.cx, expect.cx );
2452     SetTextJustification(hdc, 0, 0);
2453 
2454     SetMapMode( hdc, MM_ANISOTROPIC );
2455     SetWindowExtEx( hdc, 2, 2, NULL );
2456     GetClientRect( hwnd, &clientArea );
2457     DPtoLP( hdc, (POINT *)&clientArea, 2 );
2458     testJustification(hdc, testText, &clientArea);
2459 
2460     GetTextExtentPoint32A(hdc, "A", 1, &expect);
2461     for (i = 0; i < 10; i++)
2462     {
2463         SetTextCharacterExtra(hdc, i);
2464         GetTextExtentPoint32A(hdc, "A", 1, &size);
2465         ok( size.cx == expect.cx + i, "wrong size %d/%d+%d\n", size.cx, expect.cx, i );
2466     }
2467     SetTextCharacterExtra(hdc, 0);
2468     pGetTextExtentExPointI(hdc, indices, 1, -1, NULL, NULL, &expect);
2469     for (i = 0; i < 10; i++)
2470     {
2471         SetTextCharacterExtra(hdc, i);
2472         pGetTextExtentExPointI(hdc, indices, 1, -1, NULL, NULL, &size);
2473         ok( size.cx == expect.cx + i, "wrong size %d/%d+%d\n", size.cx, expect.cx, i );
2474     }
2475     SetTextCharacterExtra(hdc, 0);
2476 
2477     SetViewportExtEx( hdc, 3, 3, NULL );
2478     GetClientRect( hwnd, &clientArea );
2479     DPtoLP( hdc, (POINT *)&clientArea, 2 );
2480     testJustification(hdc, testText, &clientArea);
2481 
2482     GetTextExtentPoint32A(hdc, "A", 1, &expect);
2483     for (i = 0; i < 10; i++)
2484     {
2485         SetTextCharacterExtra(hdc, i);
2486         GetTextExtentPoint32A(hdc, "A", 1, &size);
2487         ok( size.cx == expect.cx + i, "wrong size %d/%d+%d\n", size.cx, expect.cx, i );
2488     }
2489 
2490 done:
2491     DeleteObject(hfont);
2492     ReleaseDC(hwnd, hdc);
2493     DestroyWindow(hwnd);
2494 }
2495 
2496 static BOOL get_glyph_indices(INT charset, UINT code_page, WORD *idx, UINT count, BOOL unicode)
2497 {
2498     HDC hdc;
2499     LOGFONTA lf;
2500     HFONT hfont, hfont_old;
2501     CHARSETINFO csi;
2502     FONTSIGNATURE fs;
2503     INT cs;
2504     DWORD i, ret;
2505     char name[64];
2506 
2507     assert(count <= 128);
2508 
2509     memset(&lf, 0, sizeof(lf));
2510 
2511     lf.lfCharSet = charset;
2512     lf.lfHeight = 10;
2513     lstrcpyA(lf.lfFaceName, "Arial");
2514     SetLastError(0xdeadbeef);
2515     hfont = CreateFontIndirectA(&lf);
2516     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
2517 
2518     hdc = GetDC(0);
2519     hfont_old = SelectObject(hdc, hfont);
2520 
2521     cs = GetTextCharsetInfo(hdc, &fs, 0);
2522     ok(cs == charset, "expected %d, got %d\n", charset, cs);
2523 
2524     SetLastError(0xdeadbeef);
2525     ret = GetTextFaceA(hdc, sizeof(name), name);
2526     ok(ret, "GetTextFaceA error %u\n", GetLastError());
2527 
2528     if (charset == SYMBOL_CHARSET)
2529     {
2530         ok(strcmp("Arial", name), "face name should NOT be Arial\n");
2531         ok(fs.fsCsb[0] & (1u << 31), "symbol encoding should be available\n");
2532     }
2533     else
2534     {
2535         ok(!strcmp("Arial", name), "face name should be Arial, not %s\n", name);
2536         ok(!(fs.fsCsb[0] & (1u << 31)), "symbol encoding should NOT be available\n");
2537     }
2538 
2539     if (!TranslateCharsetInfo((DWORD *)(INT_PTR)cs, &csi, TCI_SRCCHARSET))
2540     {
2541         trace("Can't find codepage for charset %d\n", cs);
2542         ReleaseDC(0, hdc);
2543         return FALSE;
2544     }
2545     ok(csi.ciACP == code_page, "expected %d, got %d\n", code_page, csi.ciACP);
2546 
2547     if (pGdiGetCodePage != NULL && pGdiGetCodePage(hdc) != code_page)
2548     {
2549         skip("Font code page %d, looking for code page %d\n",
2550              pGdiGetCodePage(hdc), code_page);
2551         ReleaseDC(0, hdc);
2552         return FALSE;
2553     }
2554 
2555     if (unicode)
2556     {
2557         char ansi_buf[128];
2558         WCHAR unicode_buf[128];
2559 
2560         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
2561 
2562         MultiByteToWideChar(code_page, 0, ansi_buf, count, unicode_buf, count);
2563 
2564         SetLastError(0xdeadbeef);
2565         ret = pGetGlyphIndicesW(hdc, unicode_buf, count, idx, 0);
2566         ok(ret == count, "GetGlyphIndicesW expected %d got %d, error %u\n",
2567            count, ret, GetLastError());
2568     }
2569     else
2570     {
2571         char ansi_buf[128];
2572 
2573         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
2574 
2575         SetLastError(0xdeadbeef);
2576         ret = pGetGlyphIndicesA(hdc, ansi_buf, count, idx, 0);
2577         ok(ret == count, "GetGlyphIndicesA expected %d got %d, error %u\n",
2578            count, ret, GetLastError());
2579     }
2580 
2581     SelectObject(hdc, hfont_old);
2582     DeleteObject(hfont);
2583 
2584     ReleaseDC(0, hdc);
2585 
2586     return TRUE;
2587 }
2588 
2589 static void test_font_charset(void)
2590 {
2591     static struct charset_data
2592     {
2593         INT charset;
2594         UINT code_page;
2595         WORD font_idxA[128], font_idxW[128];
2596     } cd[] =
2597     {
2598         { ANSI_CHARSET, 1252 },
2599         { RUSSIAN_CHARSET, 1251 },
2600         { SYMBOL_CHARSET, CP_SYMBOL } /* keep it as the last one */
2601     };
2602     int i;
2603 
2604     if (!pGetGlyphIndicesA || !pGetGlyphIndicesW)
2605     {
2606         win_skip("Skipping the font charset test on a Win9x platform\n");
2607         return;
2608     }
2609 
2610     if (!is_font_installed("Arial"))
2611     {
2612         skip("Arial is not installed\n");
2613         return;
2614     }
2615 
2616     for (i = 0; i < sizeof(cd)/sizeof(cd[0]); i++)
2617     {
2618         if (cd[i].charset == SYMBOL_CHARSET)
2619         {
2620             if (!is_font_installed("Symbol") && !is_font_installed("Wingdings"))
2621             {
2622                 skip("Symbol or Wingdings is not installed\n");
2623                 break;
2624             }
2625         }
2626         if (get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxA, 128, FALSE) &&
2627             get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxW, 128, TRUE))
2628             ok(!memcmp(cd[i].font_idxA, cd[i].font_idxW, 128*sizeof(WORD)), "%d: indices don't match\n", i);
2629     }
2630 
2631     ok(memcmp(cd[0].font_idxW, cd[1].font_idxW, 128*sizeof(WORD)), "0 vs 1: indices shouldn't match\n");
2632     if (i > 2)
2633     {
2634         ok(memcmp(cd[0].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "0 vs 2: indices shouldn't match\n");
2635         ok(memcmp(cd[1].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "1 vs 2: indices shouldn't match\n");
2636     }
2637     else
2638         skip("Symbol or Wingdings is not installed\n");
2639 }
2640 
2641 static void test_GdiGetCodePage(void)
2642 {
2643     static const struct _matching_data
2644     {
2645         UINT   current_codepage;
2646         LPCSTR lfFaceName;
2647         UCHAR  lfCharSet;
2648         UINT   expected_codepage;
2649     } matching_data[] = {
2650         {1251, "Arial", ANSI_CHARSET, 1252},
2651         {1251, "Tahoma", ANSI_CHARSET, 1252},
2652 
2653         {1252, "Arial", ANSI_CHARSET, 1252},
2654         {1252, "Tahoma", ANSI_CHARSET, 1252},
2655 
2656         {1253, "Arial", ANSI_CHARSET, 1252},
2657         {1253, "Tahoma", ANSI_CHARSET, 1252},
2658 
2659         { 932, "Arial", ANSI_CHARSET, 1252}, /* Japanese Windows returns 1252, not 932 */
2660         { 932, "Tahoma", ANSI_CHARSET, 1252},
2661         { 932, "MS UI Gothic", ANSI_CHARSET, 1252},
2662 
2663         { 936, "Arial", ANSI_CHARSET, 936},
2664         { 936, "Tahoma", ANSI_CHARSET, 936},
2665         { 936, "Simsun", ANSI_CHARSET, 936},
2666 
2667         { 949, "Arial", ANSI_CHARSET, 949},
2668         { 949, "Tahoma", ANSI_CHARSET, 949},
2669         { 949, "Gulim",  ANSI_CHARSET, 949},
2670 
2671         { 950, "Arial", ANSI_CHARSET, 950},
2672         { 950, "Tahoma", ANSI_CHARSET, 950},
2673         { 950, "PMingLiU", ANSI_CHARSET, 950},
2674     };
2675     HDC         hdc;
2676     LOGFONTA    lf;
2677     HFONT       hfont;
2678     UINT        charset, acp;
2679     DWORD       codepage;
2680     int         i;
2681 
2682     if (!pGdiGetCodePage)
2683     {
2684         skip("GdiGetCodePage not available on this platform\n");
2685         return;
2686     }
2687 
2688     acp = GetACP();
2689 
2690     for (i = 0; i < sizeof(matching_data) / sizeof(struct _matching_data); i++)
2691     {
2692         /* only test data matched current locale codepage */
2693         if (matching_data[i].current_codepage != acp)
2694             continue;
2695 
2696         if (!is_font_installed(matching_data[i].lfFaceName))
2697         {
2698             skip("%s is not installed\n", matching_data[i].lfFaceName);
2699             continue;
2700         }
2701 
2702         hdc = GetDC(0);
2703 
2704         memset(&lf, 0, sizeof(lf));
2705         lf.lfHeight = -16;
2706         lf.lfCharSet = matching_data[i].lfCharSet;
2707         lstrcpyA(lf.lfFaceName, matching_data[i].lfFaceName);
2708         hfont = CreateFontIndirectA(&lf);
2709         ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
2710 
2711         hfont = SelectObject(hdc, hfont);
2712         charset = GetTextCharset(hdc);
2713         codepage = pGdiGetCodePage(hdc);
2714         trace("acp=%d, lfFaceName=%s, lfCharSet=%d, GetTextCharset=%d, GdiGetCodePage=%d, expected codepage=%d\n",
2715               acp, lf.lfFaceName, lf.lfCharSet, charset, codepage, matching_data[i].expected_codepage);
2716         ok(codepage == matching_data[i].expected_codepage,
2717            "GdiGetCodePage should have returned %d, got %d\n", matching_data[i].expected_codepage, codepage);
2718 
2719         hfont = SelectObject(hdc, hfont);
2720         DeleteObject(hfont);
2721 
2722         /* CLIP_DFA_DISABLE turns off the font association */
2723         lf.lfClipPrecision = CLIP_DFA_DISABLE;
2724         hfont = CreateFontIndirectA(&lf);
2725         ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
2726 
2727         hfont = SelectObject(hdc, hfont);
2728         charset = GetTextCharset(hdc);
2729         codepage = pGdiGetCodePage(hdc);
2730         trace("acp=%d, lfFaceName=%s, lfCharSet=%d, GetTextCharset=%d, GdiGetCodePage=%d\n",
2731               acp, lf.lfFaceName, lf.lfCharSet, charset, codepage);
2732         ok(codepage == 1252, "GdiGetCodePage returned %d\n", codepage);
2733 
2734         hfont = SelectObject(hdc, hfont);
2735         DeleteObject(hfont);
2736 
2737         ReleaseDC(NULL, hdc);
2738     }
2739 }
2740 
2741 static void test_GetFontUnicodeRanges(void)
2742 {
2743     LOGFONTA lf;
2744     HDC hdc;
2745     HFONT hfont, hfont_old;
2746     DWORD size;
2747     GLYPHSET *gs;
2748     DWORD i;
2749 
2750     if (!pGetFontUnicodeRanges)
2751     {
2752         win_skip("GetFontUnicodeRanges not available before W2K\n");
2753         return;
2754     }
2755 
2756     memset(&lf, 0, sizeof(lf));
2757     lstrcpyA(lf.lfFaceName, "Arial");
2758     hfont = create_font("Arial", &lf);
2759 
2760     hdc = GetDC(0);
2761     hfont_old = SelectObject(hdc, hfont);
2762 
2763     size = pGetFontUnicodeRanges(NULL, NULL);
2764     ok(!size, "GetFontUnicodeRanges succeeded unexpectedly\n");
2765 
2766     size = pGetFontUnicodeRanges(hdc, NULL);
2767     ok(size, "GetFontUnicodeRanges failed unexpectedly\n");
2768 
2769     gs = HeapAlloc(GetProcessHeap(), 0, size);
2770 
2771     size = pGetFontUnicodeRanges(hdc, gs);
2772     ok(size, "GetFontUnicodeRanges failed\n");
2773 
2774     if (0) /* Disabled to limit console spam */
2775         for (i = 0; i < gs->cRanges; i++)
2776             trace("%03d wcLow %04x cGlyphs %u\n", i, gs->ranges[i].wcLow, gs->ranges[i].cGlyphs);
2777     trace("found %u ranges\n", gs->cRanges);
2778 
2779     HeapFree(GetProcessHeap(), 0, gs);
2780 
2781     SelectObject(hdc, hfont_old);
2782     DeleteObject(hfont);
2783     ReleaseDC(NULL, hdc);
2784 }
2785 
2786 struct enum_font_data
2787 {
2788     int total, size;
2789     LOGFONTA *lf;
2790 };
2791 
2792 struct enum_fullname_data
2793 {
2794     int total, size;
2795     ENUMLOGFONTA *elf;
2796 };
2797 
2798 struct enum_font_dataW
2799 {
2800     int total, size;
2801     LOGFONTW *lf;
2802 };
2803 
2804 static INT CALLBACK arial_enum_proc(const LOGFONTA *lf, const TEXTMETRICA *tm, DWORD type, LPARAM lParam)
2805 {
2806     struct enum_font_data *efd = (struct enum_font_data *)lParam;
2807     const NEWTEXTMETRICA *ntm = (const NEWTEXTMETRICA *)tm;
2808 
2809     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
2810     ok(lf->lfHeight > 0 && lf->lfHeight < 200, "enumerated font height %d\n", lf->lfHeight);
2811 
2812     if (type != TRUETYPE_FONTTYPE) return 1;
2813 
2814     ok(ntm->ntmCellHeight + ntm->ntmCellHeight/5 >= ntm->ntmSizeEM, "ntmCellHeight %d should be close to ntmSizeEM %d\n", ntm->ntmCellHeight, ntm->ntmSizeEM);
2815 
2816     if (0) /* Disabled to limit console spam */
2817         trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
2818               lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
2819     if (efd->total >= efd->size)
2820     {
2821         efd->size = max( (efd->total + 1) * 2, 256 );
2822         efd->lf = heap_realloc( efd->lf, efd->size * sizeof(*efd->lf) );
2823         if (!efd->lf) return 0;
2824     }
2825     efd->lf[efd->total++] = *lf;
2826 
2827     return 1;
2828 }
2829 
2830 static INT CALLBACK arial_enum_procw(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
2831 {
2832     struct enum_font_dataW *efd = (struct enum_font_dataW *)lParam;
2833     const NEWTEXTMETRICW *ntm = (const NEWTEXTMETRICW *)tm;
2834 
2835     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
2836     ok(lf->lfHeight > 0 && lf->lfHeight < 200, "enumerated font height %d\n", lf->lfHeight);
2837 
2838     if (type != TRUETYPE_FONTTYPE) return 1;
2839 
2840     ok(ntm->ntmCellHeight + ntm->ntmCellHeight/5 >= ntm->ntmSizeEM, "ntmCellHeight %d should be close to ntmSizeEM %d\n", ntm->ntmCellHeight, ntm->ntmSizeEM);
2841 
2842     if (0) /* Disabled to limit console spam */
2843         trace("enumed font %s, charset %d, height %d, weight %d, italic %d\n",
2844               wine_dbgstr_w(lf->lfFaceName), lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
2845     if (efd->total >= efd->size)
2846     {
2847         efd->size = max( (efd->total + 1) * 2, 256 );
2848         efd->lf = heap_realloc( efd->lf, efd->size * sizeof(*efd->lf) );
2849         if (!efd->lf) return 0;
2850     }
2851     efd->lf[efd->total++] = *lf;
2852 
2853     return 1;
2854 }
2855 
2856 static void get_charset_stats(struct enum_font_data *efd,
2857                               int *ansi_charset, int *symbol_charset,
2858                               int *russian_charset)
2859 {
2860     int i;
2861 
2862     *ansi_charset = 0;
2863     *symbol_charset = 0;
2864     *russian_charset = 0;
2865 
2866     for (i = 0; i < efd->total; i++)
2867     {
2868         switch (efd->lf[i].lfCharSet)
2869         {
2870         case ANSI_CHARSET:
2871             (*ansi_charset)++;
2872             break;
2873         case SYMBOL_CHARSET:
2874             (*symbol_charset)++;
2875             break;
2876         case RUSSIAN_CHARSET:
2877             (*russian_charset)++;
2878             break;
2879         }
2880     }
2881 }
2882 
2883 static void get_charset_statsW(struct enum_font_dataW *efd,
2884                               int *ansi_charset, int *symbol_charset,
2885                               int *russian_charset)
2886 {
2887     int i;
2888 
2889     *ansi_charset = 0;
2890     *symbol_charset = 0;
2891     *russian_charset = 0;
2892 
2893     for (i = 0; i < efd->total; i++)
2894     {
2895         switch (efd->lf[i].lfCharSet)
2896         {
2897         case ANSI_CHARSET:
2898             (*ansi_charset)++;
2899             break;
2900         case SYMBOL_CHARSET:
2901             (*symbol_charset)++;
2902             break;
2903         case RUSSIAN_CHARSET:
2904             (*russian_charset)++;
2905             break;
2906         }
2907     }
2908 }
2909 
2910 static void test_EnumFontFamilies(const char *font_name, INT font_charset)
2911 {
2912     struct enum_font_data efd;
2913     struct enum_font_dataW efdw;
2914     LOGFONTA lf;
2915     HDC hdc;
2916     int i, ret, ansi_charset, symbol_charset, russian_charset;
2917 
2918     trace("Testing font %s, charset %d\n", *font_name ? font_name : "<empty>", font_charset);
2919 
2920     if (*font_name && !is_truetype_font_installed(font_name))
2921     {
2922         skip("%s is not installed\n", font_name);
2923         return;
2924     }
2925     memset( &efd, 0, sizeof(efd) );
2926     memset( &efdw, 0, sizeof(efdw) );
2927 
2928     hdc = GetDC(0);
2929 
2930     /* Observed behaviour: EnumFontFamilies enumerates aliases like "Arial Cyr"
2931      * while EnumFontFamiliesEx doesn't.
2932      */
2933     if (!*font_name && font_charset == DEFAULT_CHARSET) /* do it only once */
2934     {
2935         /*
2936          * Use EnumFontFamiliesW since win98 crashes when the
2937          *    second parameter is NULL using EnumFontFamilies
2938          */
2939         efdw.total = 0;
2940         SetLastError(0xdeadbeef);
2941         ret = EnumFontFamiliesW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw);
2942         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesW error %u\n", GetLastError());
2943         if(ret)
2944         {
2945             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
2946             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
2947                   ansi_charset, symbol_charset, russian_charset);
2948             ok(efdw.total > 0, "fonts enumerated: NULL\n");
2949             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
2950             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
2951             ok(russian_charset > 0 ||
2952                broken(russian_charset == 0), /* NT4 */
2953                "NULL family should enumerate RUSSIAN_CHARSET\n");
2954         }
2955 
2956         efdw.total = 0;
2957         SetLastError(0xdeadbeef);
2958         ret = EnumFontFamiliesExW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw, 0);
2959         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesExW error %u\n", GetLastError());
2960         if(ret)
2961         {
2962             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
2963             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
2964                   ansi_charset, symbol_charset, russian_charset);
2965             ok(efdw.total > 0, "fonts enumerated: NULL\n");
2966             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
2967             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
2968             ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
2969         }
2970     }
2971 
2972     efd.total = 0;
2973     SetLastError(0xdeadbeef);
2974     ret = EnumFontFamiliesA(hdc, font_name, arial_enum_proc, (LPARAM)&efd);
2975     ok(ret, "EnumFontFamilies error %u\n", GetLastError());
2976     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2977     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s\n",
2978           ansi_charset, symbol_charset, russian_charset,
2979           *font_name ? font_name : "<empty>");
2980     if (*font_name)
2981         ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
2982     else
2983         ok(!efd.total, "no fonts should be enumerated for empty font_name\n");
2984     for (i = 0; i < efd.total; i++)
2985     {
2986         /* FIXME: remove completely once Wine is fixed */
2987         todo_wine_if(efd.lf[i].lfCharSet != font_charset)
2988         ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2989         ok(!strcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2990            font_name, efd.lf[i].lfFaceName);
2991     }
2992 
2993     memset(&lf, 0, sizeof(lf));
2994     lf.lfCharSet = ANSI_CHARSET;
2995     strcpy(lf.lfFaceName, font_name);
2996     efd.total = 0;
2997     SetLastError(0xdeadbeef);
2998     ret = EnumFontFamiliesExA(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2999     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
3000     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
3001     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s ANSI_CHARSET\n",
3002           ansi_charset, symbol_charset, russian_charset,
3003           *font_name ? font_name : "<empty>");
3004     if (font_charset == SYMBOL_CHARSET)
3005     {
3006         if (*font_name)
3007             ok(efd.total == 0, "no fonts should be enumerated: %s ANSI_CHARSET\n", font_name);
3008         else
3009             ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
3010     }
3011     else
3012     {
3013         ok(efd.total > 0, "no fonts enumerated: %s ANSI_CHARSET\n", font_name);
3014         for (i = 0; i < efd.total; i++)
3015         {
3016             ok(efd.lf[i].lfCharSet == ANSI_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
3017             if (*font_name)
3018                 ok(!strcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
3019                    font_name, efd.lf[i].lfFaceName);
3020         }
3021     }
3022 
3023     /* DEFAULT_CHARSET should enumerate all available charsets */
3024     memset(&lf, 0, sizeof(lf));
3025     lf.lfCharSet = DEFAULT_CHARSET;
3026     strcpy(lf.lfFaceName, font_name);
3027     efd.total = 0;
3028     SetLastError(0xdeadbeef);
3029     EnumFontFamiliesExA(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
3030     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
3031     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
3032     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s DEFAULT_CHARSET\n",
3033           ansi_charset, symbol_charset, russian_charset,
3034           *font_name ? font_name : "<empty>");
3035     ok(efd.total > 0, "no fonts enumerated: %s DEFAULT_CHARSET\n", font_name);
3036     for (i = 0; i < efd.total; i++)
3037     {
3038         if (*font_name)
3039             ok(!strcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
3040                font_name, efd.lf[i].lfFaceName);
3041     }
3042     if (*font_name)
3043     {
3044         switch (font_charset)
3045         {
3046         case ANSI_CHARSET:
3047             ok(ansi_charset > 0,
3048                "ANSI_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
3049             ok(!symbol_charset,
3050                "ANSI_CHARSET should NOT enumerate SYMBOL_CHARSET for %s\n", font_name);
3051             ok(russian_charset > 0,
3052                "ANSI_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
3053             break;
3054         case SYMBOL_CHARSET:
3055             ok(!ansi_charset,
3056                "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", font_name);
3057             ok(symbol_charset,
3058                "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
3059             ok(!russian_charset,
3060                "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", font_name);
3061             break;
3062         case DEFAULT_CHARSET:
3063             ok(ansi_charset > 0,
3064                "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
3065             ok(symbol_charset > 0,
3066                "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
3067             ok(russian_charset > 0,
3068                "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
3069             break;
3070         }
3071     }
3072     else
3073     {
3074         ok(ansi_charset > 0,
3075            "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
3076         ok(symbol_charset > 0,
3077            "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
3078         ok(russian_charset > 0,
3079            "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
3080     }
3081 
3082     memset(&lf, 0, sizeof(lf));
3083     lf.lfCharSet = SYMBOL_CHARSET;
3084     strcpy(lf.lfFaceName, font_name);
3085     efd.total = 0;
3086     SetLastError(0xdeadbeef);
3087     EnumFontFamiliesExA(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
3088     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
3089     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
3090     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s SYMBOL_CHARSET\n",
3091           ansi_charset, symbol_charset, russian_charset,
3092           *font_name ? font_name : "<empty>");
3093     if (*font_name && font_charset == ANSI_CHARSET)
3094         ok(efd.total == 0, "no fonts should be enumerated: %s SYMBOL_CHARSET\n", font_name);
3095     else
3096     {
3097         ok(efd.total > 0, "no fonts enumerated: %s SYMBOL_CHARSET\n", font_name);
3098         for (i = 0; i < efd.total; i++)
3099         {
3100             ok(efd.lf[i].lfCharSet == SYMBOL_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
3101             if (*font_name)
3102                 ok(!strcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
3103                    font_name, efd.lf[i].lfFaceName);
3104         }
3105 
3106         ok(!ansi_charset,
3107            "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
3108         ok(symbol_charset > 0,
3109            "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
3110         ok(!russian_charset,
3111            "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
3112     }
3113 
3114     ReleaseDC(0, hdc);
3115 
3116     heap_free( efd.lf );
3117     heap_free( efdw.lf );
3118 }
3119 
3120 static INT CALLBACK enum_multi_charset_font_proc(const LOGFONTA *lf, const TEXTMETRICA *tm, DWORD type, LPARAM lParam)
3121 {
3122     const NEWTEXTMETRICEXA *ntm = (const NEWTEXTMETRICEXA *)tm;
3123     LOGFONTA *target = (LOGFONTA *)lParam;
3124     const DWORD valid_bits = 0x003f01ff;
3125     CHARSETINFO csi;
3126     DWORD fs;
3127 
3128     if (type != TRUETYPE_FONTTYPE) return TRUE;
3129 
3130     if (TranslateCharsetInfo(ULongToPtr(target->lfCharSet), &csi, TCI_SRCCHARSET)) {
3131         fs = ntm->ntmFontSig.fsCsb[0] & valid_bits;
3132         if ((fs & csi.fs.fsCsb[0]) && (fs & ~csi.fs.fsCsb[0]) && (fs & FS_LATIN1)) {
3133             *target = *lf;
3134             return FALSE;
3135         }
3136     }
3137 
3138     return TRUE;
3139 }
3140 
3141 static INT CALLBACK enum_font_data_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
3142 {
3143     struct enum_font_data *efd = (struct enum_font_data *)lParam;
3144 
3145     if (type != TRUETYPE_FONTTYPE) return 1;
3146 
3147     if (efd->total >= efd->size)
3148     {
3149         efd->size = max( (efd->total + 1) * 2, 256 );
3150         efd->lf = heap_realloc( efd->lf, efd->size * sizeof(*efd->lf) );
3151         if (!efd->lf) return 0;
3152     }
3153     efd->lf[efd->total++] = *lf;
3154 
3155     return 1;
3156 }
3157 
3158 static INT CALLBACK enum_fullname_data_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
3159 {
3160     struct enum_fullname_data *efnd = (struct enum_fullname_data *)lParam;
3161 
3162     if (type != TRUETYPE_FONTTYPE) return 1;
3163 
3164     if (efnd->total >= efnd->size)
3165     {
3166         efnd->size = max( (efnd->total + 1) * 2, 256 );
3167         efnd->elf = heap_realloc( efnd->elf, efnd->size * sizeof(*efnd->elf) );
3168         if (!efnd->elf) return 0;
3169     }
3170     efnd->elf[efnd->total++] = *(ENUMLOGFONTA *)lf;
3171 
3172     return 1;
3173 }
3174 
3175 static void test_EnumFontFamiliesEx_default_charset(void)
3176 {
3177     struct enum_font_data efd;
3178     LOGFONTA target, enum_font;
3179     UINT acp;
3180     HDC hdc;
3181     CHARSETINFO csi;
3182 
3183     acp = GetACP();
3184     if (!TranslateCharsetInfo(ULongToPtr(acp), &csi, TCI_SRCCODEPAGE)) {
3185         skip("TranslateCharsetInfo failed for code page %u.\n", acp);
3186         return;
3187     }
3188 
3189     hdc = GetDC(0);
3190     memset(&enum_font, 0, sizeof(enum_font));
3191     enum_font.lfCharSet = csi.ciCharset;
3192     target.lfFaceName[0] = '\0';
3193     target.lfCharSet = csi.ciCharset;
3194     EnumFontFamiliesExA(hdc, &enum_font, enum_multi_charset_font_proc, (LPARAM)&target, 0);
3195     if (target.lfFaceName[0] == '\0') {
3196         skip("suitable font isn't found for charset %d.\n", enum_font.lfCharSet);
3197         return;
3198     }
3199     if (acp == 874 || acp == 1255 || acp == 1256) {
3200         /* these codepage use complex script, expecting ANSI_CHARSET here. */
3201         target.lfCharSet = ANSI_CHARSET;
3202     }
3203 
3204     memset(&efd, 0, sizeof(efd));
3205     memset(&enum_font, 0, sizeof(enum_font));
3206     strcpy(enum_font.lfFaceName, target.lfFaceName);
3207     enum_font.lfCharSet = DEFAULT_CHARSET;
3208     EnumFontFamiliesExA(hdc, &enum_font, enum_font_data_proc, (LPARAM)&efd, 0);
3209     ReleaseDC(0, hdc);
3210 
3211     trace("'%s' has %d charsets.\n", target.lfFaceName, efd.total);
3212     if (efd.total < 2)
3213         ok(0, "EnumFontFamilies is broken. Expected >= 2, got %d.\n", efd.total);
3214     else
3215         ok(efd.lf[0].lfCharSet == target.lfCharSet,
3216            "(%s) got charset %d expected %d\n",
3217            efd.lf[0].lfFaceName, efd.lf[0].lfCharSet, target.lfCharSet);
3218 
3219     heap_free(efd.lf);
3220     return;
3221 }
3222 
3223 static void test_negative_width(HDC hdc, const LOGFONTA *lf)
3224 {
3225     HFONT hfont, hfont_prev;
3226     DWORD ret;
3227     GLYPHMETRICS gm1, gm2;
3228     LOGFONTA lf2 = *lf;
3229     WORD idx;
3230 
3231     if(!pGetGlyphIndicesA)
3232         return;
3233 
3234     /* negative widths are handled just as positive ones */
3235     lf2.lfWidth = -lf->lfWidth;
3236 
3237     SetLastError(0xdeadbeef);
3238     hfont = CreateFontIndirectA(lf);
3239     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
3240     check_font("original", lf, hfont);
3241 
3242     hfont_prev = SelectObject(hdc, hfont);
3243 
3244     ret = pGetGlyphIndicesA(hdc, "x", 1, &idx, GGI_MARK_NONEXISTING_GLYPHS);
3245     if (ret == GDI_ERROR || idx == 0xffff)
3246     {
3247         SelectObject(hdc, hfont_prev);
3248         DeleteObject(hfont);
3249         skip("Font %s doesn't contain 'x', skipping the test\n", lf->lfFaceName);
3250         return;
3251     }
3252 
3253     /* filling with 0xaa causes false pass under WINEDEBUG=warn+heap */
3254     memset(&gm1, 0xab, sizeof(gm1));
3255     SetLastError(0xdeadbeef);
3256     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm1, 0, NULL, &mat);
3257     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
3258 
3259     SelectObject(hdc, hfont_prev);
3260     DeleteObject(hfont);
3261 
3262     SetLastError(0xdeadbeef);
3263     hfont = CreateFontIndirectA(&lf2);
3264     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
3265     check_font("negative width", &lf2, hfont);
3266 
3267     hfont_prev = SelectObject(hdc, hfont);
3268 
3269     memset(&gm2, 0xbb, sizeof(gm2));
3270     SetLastError(0xdeadbeef);
3271     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm2, 0, NULL, &mat);
3272     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
3273 
3274     SelectObject(hdc, hfont_prev);
3275     DeleteObject(hfont);
3276 
3277     ok(gm1.gmBlackBoxX == gm2.gmBlackBoxX &&
3278        gm1.gmBlackBoxY == gm2.gmBlackBoxY &&
3279        gm1.gmptGlyphOrigin.x == gm2.gmptGlyphOrigin.x &&
3280        gm1.gmptGlyphOrigin.y == gm2.gmptGlyphOrigin.y &&
3281        gm1.gmCellIncX == gm2.gmCellIncX &&
3282        gm1.gmCellIncY == gm2.gmCellIncY,
3283        "gm1=%d,%d,%d,%d,%d,%d gm2=%d,%d,%d,%d,%d,%d\n",
3284        gm1.gmBlackBoxX, gm1.gmBlackBoxY, gm1.gmptGlyphOrigin.x,
3285        gm1.gmptGlyphOrigin.y, gm1.gmCellIncX, gm1.gmCellIncY,
3286        gm2.gmBlackBoxX, gm2.gmBlackBoxY, gm2.gmptGlyphOrigin.x,
3287        gm2.gmptGlyphOrigin.y, gm2.gmCellIncX, gm2.gmCellIncY);
3288 }
3289 
3290 /* PANOSE is 10 bytes in size, need to pack the structure properly */
3291 #include "pshpack2.h"
3292 typedef struct
3293 {
3294     USHORT version;
3295     SHORT xAvgCharWidth;
3296     USHORT usWeightClass;
3297     USHORT usWidthClass;
3298     SHORT fsType;
3299     SHORT ySubscriptXSize;
3300     SHORT ySubscriptYSize;
3301     SHORT ySubscriptXOffset;
3302     SHORT ySubscriptYOffset;
3303     SHORT ySuperscriptXSize;
3304     SHORT ySuperscriptYSize;
3305     SHORT ySuperscriptXOffset;
3306     SHORT ySuperscriptYOffset;
3307     SHORT yStrikeoutSize;
3308     SHORT yStrikeoutPosition;
3309     SHORT sFamilyClass;
3310     PANOSE panose;
3311     ULONG ulUnicodeRange1;
3312     ULONG ulUnicodeRange2;
3313     ULONG ulUnicodeRange3;
3314     ULONG ulUnicodeRange4;
3315     CHAR achVendID[4];
3316     USHORT fsSelection;
3317     USHORT usFirstCharIndex;
3318     USHORT usLastCharIndex;
3319     /* According to the Apple spec, original version didn't have the below fields,
3320      * version numbers were taken from the OpenType spec.
3321      */
3322     /* version 0 (TrueType 1.5) */
3323     USHORT sTypoAscender;
3324     USHORT sTypoDescender;
3325     USHORT sTypoLineGap;
3326     USHORT usWinAscent;
3327     USHORT usWinDescent;
3328     /* version 1 (TrueType 1.66) */
3329     ULONG ulCodePageRange1;
3330     ULONG ulCodePageRange2;
3331     /* version 2 (OpenType 1.2) */
3332     SHORT sxHeight;
3333     SHORT sCapHeight;
3334     USHORT usDefaultChar;
3335     USHORT usBreakChar;
3336     USHORT usMaxContext;
3337     /* version 4 (OpenType 1.6) */
3338     USHORT usLowerOpticalPointSize;
3339     USHORT usUpperOpticalPointSize;
3340 } TT_OS2_V4;
3341 #include "poppack.h"
3342 
3343 #define TT_OS2_V0_SIZE (FIELD_OFFSET(TT_OS2_V4, ulCodePageRange1))
3344 
3345 typedef struct
3346 {
3347     USHORT version;
3348     USHORT num_tables;
3349 } cmap_header;
3350 
3351 typedef struct
3352 {
3353     USHORT plat_id;
3354     USHORT enc_id;
3355     ULONG offset;
3356 } cmap_encoding_record;
3357 
3358 typedef struct
3359 {
3360     USHORT format;
3361     USHORT length;
3362     USHORT language;
3363 
3364     BYTE glyph_ids[256];
3365 } cmap_format_0;
3366 
3367 typedef struct
3368 {
3369     USHORT format;
3370     USHORT length;
3371     USHORT language;
3372 
3373     USHORT seg_countx2;
3374     USHORT search_range;
3375     USHORT entry_selector;
3376     USHORT range_shift;
3377 
3378     USHORT end_count[1]; /* this is a variable-sized array of length seg_countx2 / 2 */
3379 /* Then follows:
3380     USHORT pad;
3381     USHORT start_count[seg_countx2 / 2];
3382     USHORT id_delta[seg_countx2 / 2];
3383     USHORT id_range_offset[seg_countx2 / 2];
3384     USHORT glyph_ids[];
3385 */
3386 } cmap_format_4;
3387 
3388 typedef struct
3389 {
3390     USHORT end_count;
3391     USHORT start_count;
3392     USHORT id_delta;
3393     USHORT id_range_offset;
3394 } cmap_format_4_seg;
3395 
3396 static void expect_ff(const TEXTMETRICA *tmA, const TT_OS2_V4 *os2, WORD family, const char *name)
3397 {
3398     ok((tmA->tmPitchAndFamily & 0xf0) == family ||
3399        broken(PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH),
3400        "%s: expected family %02x got %02x. panose %d-%d-%d-%d-...\n",
3401        name, family, tmA->tmPitchAndFamily, os2->panose.bFamilyType, os2->panose.bSerifStyle,
3402        os2->panose.bWeight, os2->panose.bProportion);
3403 }
3404 
3405 static BOOL get_first_last_from_cmap0(void *ptr, DWORD *first, DWORD *last)
3406 {
3407     int i;
3408     cmap_format_0 *cmap = (cmap_format_0*)ptr;
3409 
3410     *first = 256;
3411 
3412     for(i = 0; i < 256; i++)
3413     {
3414         if(cmap->glyph_ids[i] == 0) continue;
3415         *last = i;
3416         if(*first == 256) *first = i;
3417     }
3418     if(*first == 256) return FALSE;
3419     return TRUE;
3420 }
3421 
3422 static void get_seg4(cmap_format_4 *cmap, USHORT seg_num, cmap_format_4_seg *seg)
3423 {
3424     USHORT segs = GET_BE_WORD(cmap->seg_countx2) / 2;
3425     seg->end_count = GET_BE_WORD(cmap->end_count[seg_num]);
3426     seg->start_count = GET_BE_WORD(cmap->end_count[segs + 1 + seg_num]);
3427     seg->id_delta = GET_BE_WORD(cmap->end_count[2 * segs + 1 + seg_num]);
3428     seg->id_range_offset = GET_BE_WORD(cmap->end_count[3 * segs + 1 + seg_num]);
3429 }
3430 
3431 static BOOL get_first_last_from_cmap4(void *ptr, DWORD *first, DWORD *last, DWORD limit)
3432 {
3433     int i;
3434     cmap_format_4 *cmap = (cmap_format_4*)ptr;
3435     USHORT seg_count = GET_BE_WORD(cmap->seg_countx2) / 2;
3436 
3437     *first = 0x10000;
3438 
3439     for(i = 0; i < seg_count; i++)
3440     {
3441         cmap_format_4_seg seg;
3442 
3443         get_seg4(cmap, i, &seg);
3444 
3445         if(seg.start_count > 0xfffe) break;
3446 
3447         if(*first == 0x10000) *first = seg.start_count;
3448 
3449         *last = min(seg.end_count, 0xfffe);
3450     }
3451 
3452     if(*first == 0x10000) return FALSE;
3453     return TRUE;
3454 }
3455 
3456 static void *get_cmap(cmap_header *header, USHORT plat_id, USHORT enc_id)
3457 {
3458     USHORT i;
3459     cmap_encoding_record *record = (cmap_encoding_record *)(header + 1);
3460 
3461     for(i = 0; i < GET_BE_WORD(header->num_tables); i++)
3462     {
3463         if(GET_BE_WORD(record->plat_id) == plat_id && GET_BE_WORD(record->enc_id) == enc_id)
3464             return (BYTE *)header + GET_BE_DWORD(record->offset);
3465         record++;
3466     }
3467     return NULL;
3468 }
3469 
3470 typedef enum
3471 {
3472     cmap_none,
3473     cmap_ms_unicode,
3474     cmap_ms_symbol
3475 } cmap_type;
3476 
3477 static BOOL get_first_last_from_cmap(HDC hdc, DWORD *first, DWORD *last, cmap_type *cmap_type)
3478 {
3479     LONG size, ret;
3480     cmap_header *header;
3481     void *cmap;
3482     BOOL r = FALSE;
3483     WORD format;
3484 
3485     size = GetFontData(hdc, MS_CMAP_TAG, 0, NULL, 0);
3486     ok(size != GDI_ERROR, "no cmap table found\n");
3487     if(size == GDI_ERROR) return FALSE;
3488 
3489     header = HeapAlloc(GetProcessHeap(), 0, size);
3490     ret = GetFontData(hdc, MS_CMAP_TAG, 0, header, size);
3491     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
3492     ok(GET_BE_WORD(header->version) == 0, "got cmap version %d\n", GET_BE_WORD(header->version));
3493 
3494     cmap = get_cmap(header, 3, 1);
3495     if(cmap)
3496         *cmap_type = cmap_ms_unicode;
3497     else
3498     {
3499         cmap = get_cmap(header, 3, 0);
3500         if(cmap) *cmap_type = cmap_ms_symbol;
3501     }
3502     if(!cmap)
3503     {
3504         *cmap_type = cmap_none;
3505         goto end;
3506     }
3507 
3508     format = GET_BE_WORD(*(WORD *)cmap);
3509     switch(format)
3510     {
3511     case 0:
3512         r = get_first_last_from_cmap0(cmap, first, last);
3513         break;
3514     case 4:
3515         r = get_first_last_from_cmap4(cmap, first, last, size);
3516         break;
3517     default:
3518         trace("unhandled cmap format %d\n", format);
3519         break;
3520     }
3521 
3522 end:
3523     HeapFree(GetProcessHeap(), 0, header);
3524     return r;
3525 }
3526 
3527 #define TT_PLATFORM_APPLE_UNICODE 0
3528 #define TT_PLATFORM_MACINTOSH 1
3529 #define TT_PLATFORM_MICROSOFT 3
3530 #define TT_APPLE_ID_DEFAULT 0
3531 #define TT_APPLE_ID_ISO_10646 2
3532 #define TT_APPLE_ID_UNICODE_2_0 3
3533 #define TT_MS_ID_SYMBOL_CS 0
3534 #define TT_MS_ID_UNICODE_CS 1
3535 #define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409
3536 #define TT_NAME_ID_FONT_FAMILY 1
3537 #define TT_NAME_ID_FONT_SUBFAMILY 2
3538 #define TT_NAME_ID_UNIQUE_ID 3
3539 #define TT_NAME_ID_FULL_NAME 4
3540 #define TT_MAC_ID_SIMPLIFIED_CHINESE    25
3541 
3542 typedef struct sfnt_name
3543 {
3544     USHORT platform_id;
3545     USHORT encoding_id;
3546     USHORT language_id;
3547     USHORT name_id;
3548     USHORT length;
3549     USHORT offset;
3550 } sfnt_name;
3551 
3552 static const LANGID mac_langid_table[] =
3553 {
3554     MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT),                /* TT_MAC_LANGID_ENGLISH */
3555     MAKELANGID(LANG_FRENCH,SUBLANG_DEFAULT),                 /* TT_MAC_LANGID_FRENCH */
3556     MAKELANGID(LANG_GERMAN,SUBLANG_DEFAULT),                 /* TT_MAC_LANGID_GERMAN */
3557     MAKELANGID(LANG_ITALIAN,SUBLANG_DEFAULT),                /* TT_MAC_LANGID_ITALIAN */
3558     MAKELANGID(LANG_DUTCH,SUBLANG_DEFAULT),                  /* TT_MAC_LANGID_DUTCH */
3559     MAKELANGID(LANG_SWEDISH,SUBLANG_DEFAULT),                /* TT_MAC_LANGID_SWEDISH */
3560     MAKELANGID(LANG_SPANISH,SUBLANG_DEFAULT),                /* TT_MAC_LANGID_SPANISH */
3561     MAKELANGID(LANG_DANISH,SUBLANG_DEFAULT),                 /* TT_MAC_LANGID_DANISH */
3562     MAKELANGID(LANG_PORTUGUESE,SUBLANG_DEFAULT),             /* TT_MAC_LANGID_PORTUGUESE */
3563     MAKELANGID(LANG_NORWEGIAN,SUBLANG_DEFAULT),              /* TT_MAC_LANGID_NORWEGIAN */
3564     MAKELANGID(LANG_HEBREW,SUBLANG_DEFAULT),                 /* TT_MAC_LANGID_HEBREW */
3565     MAKELANGID(LANG_JAPANESE,SUBLANG_DEFAULT),               /* TT_MAC_LANGID_JAPANESE */
3566     MAKELANGID(LANG_ARABIC,SUBLANG_DEFAULT),                 /* TT_MAC_LANGID_ARABIC */
3567     MAKELANGID(LANG_FINNISH,SUBLANG_DEFAULT),                /* TT_MAC_LANGID_FINNISH */
3568     MAKELANGID(LANG_GREEK,SUBLANG_DEFAULT),                  /* TT_MAC_LANGID_GREEK */
3569     MAKELANGID(LANG_ICELANDIC,SUBLANG_DEFAULT),              /* TT_MAC_LANGID_ICELANDIC */
3570     MAKELANGID(LANG_MALTESE,SUBLANG_DEFAULT),                /* TT_MAC_LANGID_MALTESE */
3571     MAKELANGID(LANG_TURKISH,SUBLANG_DEFAULT),                /* TT_MAC_LANGID_TURKISH */
3572     MAKELANGID(LANG_CROATIAN,SUBLANG_DEFAULT),               /* TT_MAC_LANGID_CROATIAN */
3573     MAKELANGID(LANG_CHINESE_TRADITIONAL,SUBLANG_DEFAULT),    /* TT_MAC_LANGID_CHINESE_TRADITIONAL */
3574     MAKELANGID(LANG_URDU,SUBLANG_DEFAULT),                   /* TT_MAC_LANGID_URDU */
3575     MAKELANGID(LANG_HINDI,SUBLANG_DEFAULT),                  /* TT_MAC_LANGID_HINDI */
3576     MAKELANGID(LANG_THAI,SUBLANG_DEFAULT),                   /* TT_MAC_LANGID_THAI */
3577     MAKELANGID(LANG_KOREAN,SUBLANG_DEFAULT),                 /* TT_MAC_LANGID_KOREAN */
3578     MAKELANGID(LANG_LITHUANIAN,SUBLANG_DEFAULT),             /* TT_MAC_LANGID_LITHUANIAN */
3579     MAKELANGID(LANG_POLISH,SUBLANG_DEFAULT),                 /* TT_MAC_LANGID_POLISH */
3580     MAKELANGID(LANG_HUNGARIAN,SUBLANG_DEFAULT),              /* TT_MAC_LANGID_HUNGARIAN */
3581     MAKELANGID(LANG_ESTONIAN,SUBLANG_DEFAULT),               /* TT_MAC_LANGID_ESTONIAN */
3582     MAKELANGID(LANG_LATVIAN,SUBLANG_DEFAULT),                /* TT_MAC_LANGID_LETTISH */
3583     MAKELANGID(LANG_SAMI,SUBLANG_DEFAULT),                   /* TT_MAC_LANGID_SAAMISK */
3584     MAKELANGID(LANG_FAEROESE,SUBLANG_DEFAULT),               /* TT_MAC_LANGID_FAEROESE */
3585     MAKELANGID(LANG_FARSI,SUBLANG_DEFAULT),                  /* TT_MAC_LANGID_FARSI */
3586     MAKELANGID(LANG_RUSSIAN,SUBLANG_DEFAULT),                /* TT_MAC_LANGID_RUSSIAN */
3587     MAKELANGID(LANG_CHINESE_SIMPLIFIED,SUBLANG_DEFAULT),     /* TT_MAC_LANGID_CHINESE_SIMPLIFIED */
3588     MAKELANGID(LANG_DUTCH,SUBLANG_DUTCH_BELGIAN),            /* TT_MAC_LANGID_FLEMISH */
3589     MAKELANGID(LANG_IRISH,SUBLANG_DEFAULT),                  /* TT_MAC_LANGID_IRISH */
3590     MAKELANGID(LANG_ALBANIAN,SUBLANG_DEFAULT),               /* TT_MAC_LANGID_ALBANIAN */
3591     MAKELANGID(LANG_ROMANIAN,SUBLANG_DEFAULT),               /* TT_MAC_LANGID_ROMANIAN */
3592     MAKELANGID(LANG_CZECH,SUBLANG_DEFAULT),                  /* TT_MAC_LANGID_CZECH */
3593     MAKELANGID(LANG_SLOVAK,SUBLANG_DEFAULT),                 /* TT_MAC_LANGID_SLOVAK */
3594     MAKELANGID(LANG_SLOVENIAN,SUBLANG_DEFAULT),              /* TT_MAC_LANGID_SLOVENIAN */
3595     0,                                                       /* TT_MAC_LANGID_YIDDISH */
3596     MAKELANGID(LANG_SERBIAN,SUBLANG_DEFAULT),                /* TT_MAC_LANGID_SERBIAN */
3597     MAKELANGID(LANG_MACEDONIAN,SUBLANG_DEFAULT),             /* TT_MAC_LANGID_MACEDONIAN */
3598     MAKELANGID(LANG_BULGARIAN,SUBLANG_DEFAULT),              /* TT_MAC_LANGID_BULGARIAN */
3599     MAKELANGID(LANG_UKRAINIAN,SUBLANG_DEFAULT),              /* TT_MAC_LANGID_UKRAINIAN */
3600     MAKELANGID(LANG_BELARUSIAN,SUBLANG_DEFAULT),             /* TT_MAC_LANGID_BYELORUSSIAN */
3601     MAKELANGID(LANG_UZBEK,SUBLANG_DEFAULT),                  /* TT_MAC_LANGID_UZBEK */
3602     MAKELANGID(LANG_KAZAK,SUBLANG_DEFAULT),                  /* TT_MAC_LANGID_KAZAKH */
3603     MAKELANGID(LANG_AZERI,SUBLANG_AZERI_CYRILLIC),           /* TT_MAC_LANGID_AZERBAIJANI */
3604     0,                                                       /* TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT */
3605     MAKELANGID(LANG_ARMENIAN,SUBLANG_DEFAULT),               /* TT_MAC_LANGID_ARMENIAN */
3606     MAKELANGID(LANG_GEORGIAN,SUBLANG_DEFAULT),               /* TT_MAC_LANGID_GEORGIAN */
3607     0,                                                       /* TT_MAC_LANGID_MOLDAVIAN */
3608     MAKELANGID(LANG_KYRGYZ,SUBLANG_DEFAULT),                 /* TT_MAC_LANGID_KIRGHIZ */
3609     MAKELANGID(LANG_TAJIK,SUBLANG_DEFAULT),                  /* TT_MAC_LANGID_TAJIKI */
3610     MAKELANGID(LANG_TURKMEN,SUBLANG_DEFAULT),                /* TT_MAC_LANGID_TURKMEN */
3611     MAKELANGID(LANG_MONGOLIAN,SUBLANG_DEFAULT),              /* TT_MAC_LANGID_MONGOLIAN */
3612     MAKELANGID(LANG_MONGOLIAN,SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA), /* TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT */
3613     MAKELANGID(LANG_PASHTO,SUBLANG_DEFAULT),                 /* TT_MAC_LANGID_PASHTO */
3614     0,                                                       /* TT_MAC_LANGID_KURDISH */
3615     MAKELANGID(LANG_KASHMIRI,SUBLANG_DEFAULT),               /* TT_MAC_LANGID_KASHMIRI */
3616     MAKELANGID(LANG_SINDHI,SUBLANG_DEFAULT),                 /* TT_MAC_LANGID_SINDHI */
3617     MAKELANGID(LANG_TIBETAN,SUBLANG_DEFAULT),                /* TT_MAC_LANGID_TIBETAN */
3618     MAKELANGID(LANG_NEPALI,SUBLANG_DEFAULT),                 /* TT_MAC_LANGID_NEPALI */
3619     MAKELANGID(LANG_SANSKRIT,SUBLANG_DEFAULT),               /* TT_MAC_LANGID_SANSKRIT */
3620     MAKELANGID(LANG_MARATHI,SUBLANG_DEFAULT),                /* TT_MAC_LANGID_MARATHI */
3621     MAKELANGID(LANG_BENGALI,SUBLANG_DEFAULT),                /* TT_MAC_LANGID_BENGALI */
3622     MAKELANGID(LANG_ASSAMESE,SUBLANG_DEFAULT),               /* TT_MAC_LANGID_ASSAMESE */
3623     MAKELANGID(LANG_GUJARATI,SUBLANG_DEFAULT),               /* TT_MAC_LANGID_GUJARATI */
3624     MAKELANGID(LANG_PUNJABI,SUBLANG_DEFAULT),                /* TT_MAC_LANGID_PUNJABI */
3625     MAKELANGID(LANG_ORIYA,SUBLANG_DEFAULT),                  /* TT_MAC_LANGID_ORIYA */
3626     MAKELANGID(LANG_MALAYALAM,SUBLANG_DEFAULT),              /* TT_MAC_LANGID_MALAYALAM */
3627     MAKELANGID(LANG_KANNADA,SUBLANG_DEFAULT),                /* TT_MAC_LANGID_KANNADA */
3628     MAKELANGID(LANG_TAMIL,SUBLANG_DEFAULT),                  /* TT_MAC_LANGID_TAMIL */
3629     MAKELANGID(LANG_TELUGU,SUBLANG_DEFAULT),                 /* TT_MAC_LANGID_TELUGU */
3630     MAKELANGID(LANG_SINHALESE,SUBLANG_DEFAULT),              /* TT_MAC_LANGID_SINHALESE */
3631     0,                                                       /* TT_MAC_LANGID_BURMESE */
3632     MAKELANGID(LANG_KHMER,SUBLANG_DEFAULT),                  /* TT_MAC_LANGID_KHMER */
3633     MAKELANGID(LANG_LAO,SUBLANG_DEFAULT),                    /* TT_MAC_LANGID_LAO */
3634     MAKELANGID(LANG_VIETNAMESE,SUBLANG_DEFAULT),             /* TT_MAC_LANGID_VIETNAMESE */
3635     MAKELANGID(LANG_INDONESIAN,SUBLANG_DEFAULT),             /* TT_MAC_LANGID_INDONESIAN */
3636     0,                                                       /* TT_MAC_LANGID_TAGALOG */
3637     MAKELANGID(LANG_MALAY,SUBLANG_DEFAULT),                  /* TT_MAC_LANGID_MALAY_ROMAN_SCRIPT */
3638     0,                                                       /* TT_MAC_LANGID_MALAY_ARABIC_SCRIPT */
3639     MAKELANGID(LANG_AMHARIC,SUBLANG_DEFAULT),                /* TT_MAC_LANGID_AMHARIC */
3640     MAKELANGID(LANG_TIGRIGNA,SUBLANG_DEFAULT),               /* TT_MAC_LANGID_TIGRINYA */
3641     0,                                                       /* TT_MAC_LANGID_GALLA */
3642     0,                                                       /* TT_MAC_LANGID_SOMALI */
3643     MAKELANGID(LANG_SWAHILI,SUBLANG_DEFAULT),                /* TT_MAC_LANGID_SWAHILI */
3644     0,                                                       /* TT_MAC_LANGID_RUANDA */
3645     0,                                                       /* TT_MAC_LANGID_RUNDI */
3646     0,                                                       /* TT_MAC_LANGID_CHEWA */
3647     MAKELANGID(LANG_MALAGASY,SUBLANG_DEFAULT),               /* TT_MAC_LANGID_MALAGASY */
3648     MAKELANGID(LANG_ESPERANTO,SUBLANG_DEFAULT),              /* TT_MAC_LANGID_ESPERANTO */
3649     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,       /* 95-111 */
3650     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,          /* 112-127 */
3651     MAKELANGID(LANG_WELSH,SUBLANG_DEFAULT),                  /* TT_MAC_LANGID_WELSH */
3652     MAKELANGID(LANG_BASQUE,SUBLANG_DEFAULT),                 /* TT_MAC_LANGID_BASQUE */
3653     MAKELANGID(LANG_CATALAN,SUBLANG_DEFAULT),                /* TT_MAC_LANGID_CATALAN */
3654     0,                                                       /* TT_MAC_LANGID_LATIN */
3655     MAKELANGID(LANG_QUECHUA,SUBLANG_DEFAULT),                /* TT_MAC_LANGID_QUECHUA */
3656     0,                                                       /* TT_MAC_LANGID_GUARANI */
3657     0,                                                       /* TT_MAC_LANGID_AYMARA */
3658     MAKELANGID(LANG_TATAR,SUBLANG_DEFAULT),                  /* TT_MAC_LANGID_TATAR */
3659     MAKELANGID(LANG_UIGHUR,SUBLANG_DEFAULT),                 /* TT_MAC_LANGID_UIGHUR */
3660     0,                                                       /* TT_MAC_LANGID_DZONGKHA */
3661     0,                                                       /* TT_MAC_LANGID_JAVANESE */
3662     0,                                                       /* TT_MAC_LANGID_SUNDANESE */
3663     MAKELANGID(LANG_GALICIAN,SUBLANG_DEFAULT),               /* TT_MAC_LANGID_GALICIAN */
3664     MAKELANGID(LANG_AFRIKAANS,SUBLANG_DEFAULT),              /* TT_MAC_LANGID_AFRIKAANS */
3665     MAKELANGID(LANG_BRETON,SUBLANG_DEFAULT),                 /* TT_MAC_LANGID_BRETON */
3666     MAKELANGID(LANG_INUKTITUT,SUBLANG_DEFAULT),              /* TT_MAC_LANGID_INUKTITUT */
3667     MAKELANGID(LANG_SCOTTISH_GAELIC,SUBLANG_DEFAULT),        /* TT_MAC_LANGID_SCOTTISH_GAELIC */
3668     MAKELANGID(LANG_MANX_GAELIC,SUBLANG_DEFAULT),            /* TT_MAC_LANGID_MANX_GAELIC */
3669     MAKELANGID(LANG_IRISH,SUBLANG_IRISH_IRELAND),            /* TT_MAC_LANGID_IRISH_GAELIC */
3670     0,                                                       /* TT_MAC_LANGID_TONGAN */
3671     0,                                                       /* TT_MAC_LANGID_GREEK_POLYTONIC */
3672     MAKELANGID(LANG_GREENLANDIC,SUBLANG_DEFAULT),            /* TT_MAC_LANGID_GREELANDIC */
3673     MAKELANGID(LANG_AZERI,SUBLANG_AZERI_LATIN),              /* TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT */
3674 };
3675 
3676 static inline WORD get_mac_code_page( const sfnt_name *name )
3677 {
3678     if (GET_BE_WORD(name->encoding_id) == TT_MAC_ID_SIMPLIFIED_CHINESE) return 10008;  /* special case */
3679     return 10000 + GET_BE_WORD(name->encoding_id);
3680 }
3681 
3682 static int match_name_table_language( const sfnt_name *name, LANGID lang )
3683 {
3684     LANGID name_lang;
3685     int res = 0;
3686 
3687     switch (GET_BE_WORD(name->platform_id))
3688     {
3689     case TT_PLATFORM_MICROSOFT:
3690         res += 5;  /* prefer the Microsoft name */
3691         switch (GET_BE_WORD(name->encoding_id))
3692         {
3693         case TT_MS_ID_UNICODE_CS:
3694         case TT_MS_ID_SYMBOL_CS:
3695             name_lang = GET_BE_WORD(name->language_id);
3696             break;
3697         default:
3698             return 0;
3699         }
3700         break;
3701     case TT_PLATFORM_MACINTOSH:
3702         if (!IsValidCodePage( get_mac_code_page( name ))) return 0;
3703         if (GET_BE_WORD(name->language_id) >= sizeof(mac_langid_table)/sizeof(mac_langid_table[0])) return 0;
3704         name_lang = mac_langid_table[GET_BE_WORD(name->language_id)];
3705         break;
3706     case TT_PLATFORM_APPLE_UNICODE:
3707         res += 2;  /* prefer Unicode encodings */
3708         switch (GET_BE_WORD(name->encoding_id))
3709         {
3710         case TT_APPLE_ID_DEFAULT:
3711         case TT_APPLE_ID_ISO_10646:
3712         case TT_APPLE_ID_UNICODE_2_0:
3713             if (GET_BE_WORD(name->language_id) >= sizeof(mac_langid_table)/sizeof(mac_langid_table[0])) return 0;
3714             name_lang = mac_langid_table[GET_BE_WORD(name->language_id)];
3715             break;
3716         default:
3717             return 0;
3718         }
3719         break;
3720     default:
3721         return 0;
3722     }
3723     if (name_lang == lang) res += 30;
3724     else if (PRIMARYLANGID( name_lang ) == PRIMARYLANGID( lang )) res += 20;
3725     else if (name_lang == MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT )) res += 10;
3726     return res;
3727 }
3728 
3729 static BOOL get_ttf_nametable_entry(HDC hdc, WORD name_id, WCHAR *out_buf, SIZE_T out_size, LCID language_id)
3730 {
3731     struct sfnt_name_header
3732     {
3733         USHORT format;
3734         USHORT number_of_record;
3735         USHORT storage_offset;
3736     } *header;
3737     sfnt_name *entry;
3738     BOOL r = FALSE;
3739     LONG size, offset, length;
3740     LONG c, ret;
3741     WCHAR *name;
3742     BYTE *data;
3743     USHORT i;
3744     int res, best_lang = 0, best_index = -1;
3745 
3746     size = GetFontData(hdc, MS_NAME_TAG, 0, NULL, 0);
3747     ok(size != GDI_ERROR, "no name table found\n");
3748     if(size == GDI_ERROR) return FALSE;
3749 
3750     data = HeapAlloc(GetProcessHeap(), 0, size);
3751     ret = GetFontData(hdc, MS_NAME_TAG, 0, data, size);
3752     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
3753 
3754     header = (void *)data;
3755     header->format = GET_BE_WORD(header->format);
3756     header->number_of_record = GET_BE_WORD(header->number_of_record);
3757     header->storage_offset = GET_BE_WORD(header->storage_offset);
3758     if (header->format != 0)
3759     {
3760         trace("got format %u\n", header->format);
3761         goto out;
3762     }
3763     if (header->number_of_record == 0 || sizeof(*header) + header->number_of_record * sizeof(*entry) > size)
3764     {
3765         trace("number records out of range: %d\n", header->number_of_record);
3766         goto out;
3767     }
3768     if (header->storage_offset >= size)
3769     {
3770         trace("storage_offset %u > size %u\n", header->storage_offset, size);
3771         goto out;
3772     }
3773 
3774     entry = (void *)&header[1];
3775     for (i = 0; i < header->number_of_record; i++)
3776     {
3777         if (GET_BE_WORD(entry[i].name_id) != name_id) continue;
3778         res = match_name_table_language( &entry[i], language_id);
3779         if (res > best_lang)
3780         {
3781             best_lang = res;
3782             best_index = i;
3783         }
3784     }
3785 
3786     offset = header->storage_offset + GET_BE_WORD(entry[best_index].offset);
3787     length = GET_BE_WORD(entry[best_index].length);
3788     if (offset + length > size)
3789     {
3790         trace("entry %d is out of range\n", best_index);
3791         goto out;
3792     }
3793     if (length >= out_size)
3794     {
3795         trace("buffer too small for entry %d\n", best_index);
3796         goto out;
3797     }
3798 
3799     name = (WCHAR *)(data + offset);
3800     for (c = 0; c < length / 2; c++)
3801         out_buf[c] = GET_BE_WORD(name[c]);
3802     out_buf[c] = 0;
3803 
3804     r = TRUE;
3805 
3806 out:
3807     HeapFree(GetProcessHeap(), 0, data);
3808     return r;
3809 }
3810 
3811 static void test_text_metrics(const LOGFONTA *lf, const NEWTEXTMETRICA *ntm)
3812 {
3813     HDC hdc;
3814     HFONT hfont, hfont_old;
3815     TEXTMETRICA tmA;
3816     TT_OS2_V4 tt_os2;
3817     LONG size, ret;
3818     const char *font_name = lf->lfFaceName;
3819     DWORD cmap_first = 0, cmap_last = 0;
3820     UINT ascent, descent, cell_height;
3821     cmap_type cmap_type;
3822     BOOL sys_lang_non_english;
3823 
3824     sys_lang_non_english = PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH;
3825     hdc = GetDC(0);
3826 
3827     SetLastError(0xdeadbeef);
3828     hfont = CreateFontIndirectA(lf);
3829     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
3830 
3831     hfont_old = SelectObject(hdc, hfont);
3832 
3833     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
3834     if (size == GDI_ERROR)
3835     {
3836         trace("OS/2 chunk was not found\n");
3837         goto end_of_test;
3838     }
3839     if (size > sizeof(tt_os2))
3840     {
3841         trace("got too large OS/2 chunk of size %u\n", size);
3842         size = sizeof(tt_os2);
3843     }
3844 
3845     memset(&tt_os2, 0, sizeof(tt_os2));
3846     ret = GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size);
3847     ok(ret >= TT_OS2_V0_SIZE && ret <= size, "GetFontData should return size from [%u,%u] not %u\n", TT_OS2_V0_SIZE,
3848         size, ret);
3849 
3850     SetLastError(0xdeadbeef);
3851     ret = GetTextMetricsA(hdc, &tmA);
3852     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
3853 
3854     if(!get_first_last_from_cmap(hdc, &cmap_first, &cmap_last, &cmap_type))
3855     {
3856         skip("%s is not a Windows font, OS/2 metrics may be invalid.\n",font_name);
3857     }
3858     else
3859     {
3860         USHORT expect_first_A, expect_last_A, expect_break_A, expect_default_A;
3861         USHORT expect_first_W, expect_last_W, expect_break_W, expect_default_W;
3862         UINT os2_first_char, os2_last_char, default_char, break_char;
3863         USHORT version;
3864         TEXTMETRICW tmW;
3865 
3866         ascent = GET_BE_WORD(tt_os2.usWinAscent);
3867         descent = abs((SHORT)GET_BE_WORD(tt_os2.usWinDescent));
3868         cell_height = ascent + descent;
3869         ok(ntm->ntmCellHeight == cell_height, "%s: ntmCellHeight %u != %u, os2.usWinAscent/os2.usWinDescent %u/%u\n",
3870            font_name, ntm->ntmCellHeight, cell_height, ascent, descent);
3871 
3872         version = GET_BE_WORD(tt_os2.version);
3873 
3874         os2_first_char = GET_BE_WORD(tt_os2.usFirstCharIndex);
3875         os2_last_char = GET_BE_WORD(tt_os2.usLastCharIndex);
3876         default_char = GET_BE_WORD(tt_os2.usDefaultChar);
3877         break_char = GET_BE_WORD(tt_os2.usBreakChar);
3878 
3879         if (winetest_debug > 1)
3880             trace("font %s charset %u: %x-%x (%x-%x) default %x break %x OS/2 version %u vendor %4.4s\n",
3881                   font_name, lf->lfCharSet, os2_first_char, os2_last_char, cmap_first, cmap_last,
3882                   default_char, break_char, version, (LPCSTR)&tt_os2.achVendID);
3883 
3884         if (cmap_type == cmap_ms_symbol || (cmap_first >= 0xf000 && cmap_first < 0xf100))
3885         {
3886             expect_first_W    = 0;
3887             switch(GetACP())
3888             {
3889             case 1255:  /* Hebrew */
3890                 expect_last_W = 0xf896;
3891                 break;
3892             case 1257:  /* Baltic */
3893                 expect_last_W = 0xf8fd;
3894                 break;
3895             default:
3896                 expect_last_W = 0xf0ff;
3897             }
3898             expect_break_W    = 0x20;
3899             expect_default_W  = expect_break_W - 1;
3900             expect_first_A    = 0x1e;
3901             expect_last_A     = min(os2_last_char - os2_first_char + 0x20, 0xff);
3902         }
3903         else
3904         {
3905             expect_first_W    = cmap_first;
3906             expect_last_W     = cmap_last;
3907             if(os2_first_char <= 1)
3908                 expect_break_W = os2_first_char + 2;
3909             else if(os2_first_char > 0xff)
3910                 expect_break_W = 0x20;
3911             else
3912                 expect_break_W = os2_first_char;
3913             expect_default_W  = expect_break_W - 1;
3914             expect_first_A    = expect_default_W - 1;
3915             expect_last_A     = min(expect_last_W, 0xff);
3916         }
3917         expect_break_A    = expect_break_W;
3918         expect_default_A  = expect_default_W;
3919 
3920         /* Wine currently uses SYMBOL_CHARSET to identify whether the ANSI metrics need special handling */
3921         todo_wine_if(cmap_type != cmap_ms_symbol && tmA.tmCharSet == SYMBOL_CHARSET && expect_first_A != 0x1e)
3922             ok(tmA.tmFirstChar == expect_first_A ||
3923                tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
3924                "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
3925         if (pGdiGetCodePage == NULL || ! IsDBCSLeadByteEx(pGdiGetCodePage(hdc), tmA.tmLastChar))
3926             ok(tmA.tmLastChar == expect_last_A ||
3927                tmA.tmLastChar == 0xff /* win9x */,
3928                "A: tmLastChar for %s got %02x expected %02x\n", font_name, tmA.tmLastChar, expect_last_A);
3929         else
3930            skip("tmLastChar is DBCS lead byte\n");
3931         ok(tmA.tmBreakChar == expect_break_A, "A: tmBreakChar for %s got %02x expected %02x\n",
3932            font_name, tmA.tmBreakChar, expect_break_A);
3933         ok(tmA.tmDefaultChar == expect_default_A || broken(sys_lang_non_english),
3934            "A: tmDefaultChar for %s got %02x expected %02x\n",
3935            font_name, tmA.tmDefaultChar, expect_default_A);
3936 
3937 
3938         SetLastError(0xdeadbeef);
3939         ret = GetTextMetricsW(hdc, &tmW);
3940         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
3941            "GetTextMetricsW error %u\n", GetLastError());
3942         if (ret)
3943         {
3944             /* Wine uses the os2 first char */
3945             todo_wine_if(cmap_first != os2_first_char && cmap_type != cmap_ms_symbol)
3946                 ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
3947                    font_name, tmW.tmFirstChar, expect_first_W);
3948 
3949             /* Wine uses the os2 last char */
3950             todo_wine_if(expect_last_W != os2_last_char && cmap_type != cmap_ms_symbol)
3951                 ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
3952                    font_name, tmW.tmLastChar, expect_last_W);
3953             ok(tmW.tmBreakChar == expect_break_W, "W: tmBreakChar for %s got %02x expected %02x\n",
3954                font_name, tmW.tmBreakChar, expect_break_W);
3955             ok(tmW.tmDefaultChar == expect_default_W || broken(sys_lang_non_english),
3956                "W: tmDefaultChar for %s got %02x expected %02x\n",
3957                font_name, tmW.tmDefaultChar, expect_default_W);
3958 
3959             /* Test the aspect ratio while we have tmW */
3960             ret = GetDeviceCaps(hdc, LOGPIXELSX);
3961             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectX %u != %u\n",
3962                tmW.tmDigitizedAspectX, ret);
3963             ret = GetDeviceCaps(hdc, LOGPIXELSY);
3964             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectY %u != %u\n",
3965                tmW.tmDigitizedAspectX, ret);
3966         }
3967     }
3968 
3969     /* test FF_ values */
3970     switch(tt_os2.panose.bFamilyType)
3971     {
3972     case PAN_ANY:
3973     case PAN_NO_FIT:
3974     case PAN_FAMILY_TEXT_DISPLAY:
3975     case PAN_FAMILY_PICTORIAL:
3976     default:
3977         if((tmA.tmPitchAndFamily & 1) == 0 || /* fixed */
3978            tt_os2.panose.bProportion == PAN_PROP_MONOSPACED)
3979         {
3980             expect_ff(&tmA, &tt_os2, FF_MODERN, font_name);
3981             break;
3982         }
3983         switch(tt_os2.panose.bSerifStyle)
3984         {
3985         case PAN_ANY:
3986         case PAN_NO_FIT:
3987         default:
3988             expect_ff(&tmA, &tt_os2, FF_DONTCARE, font_name);
3989             break;
3990 
3991         case PAN_SERIF_COVE:
3992         case PAN_SERIF_OBTUSE_COVE:
3993         case PAN_SERIF_SQUARE_COVE:
3994         case PAN_SERIF_OBTUSE_SQUARE_COVE:
3995         case PAN_SERIF_SQUARE:
3996         case PAN_SERIF_THIN:
3997         case PAN_SERIF_BONE:
3998         case PAN_SERIF_EXAGGERATED:
3999         case PAN_SERIF_TRIANGLE:
4000             expect_ff(&tmA, &tt_os2, FF_ROMAN, font_name);
4001             break;
4002 
4003         case PAN_SERIF_NORMAL_SANS:
4004         case PAN_SERIF_OBTUSE_SANS:
4005         case PAN_SERIF_PERP_SANS:
4006         case PAN_SERIF_FLARED:
4007         case PAN_SERIF_ROUNDED:
4008             expect_ff(&tmA, &tt_os2, FF_SWISS, font_name);
4009             break;
4010         }
4011         break;
4012 
4013     case PAN_FAMILY_SCRIPT:
4014         expect_ff(&tmA, &tt_os2, FF_SCRIPT, font_name);
4015         break;
4016 
4017     case PAN_FAMILY_DECORATIVE:
4018         expect_ff(&tmA, &tt_os2, FF_DECORATIVE, font_name);
4019         break;
4020     }
4021 
4022     test_negative_width(hdc, lf);
4023 
4024 end_of_test:
4025     SelectObject(hdc, hfont_old);
4026     DeleteObject(hfont);
4027 
4028     ReleaseDC(0, hdc);
4029 }
4030 
4031 static INT CALLBACK enum_truetype_font_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
4032 {
4033     INT *enumed = (INT *)lParam;
4034 
4035     if (type == TRUETYPE_FONTTYPE)
4036     {
4037         (*enumed)++;
4038         test_text_metrics(lf, (const NEWTEXTMETRICA *)ntm);
4039     }
4040     return 1;
4041 }
4042 
4043 static void test_GetTextMetrics(void)
4044 {
4045     LOGFONTA lf;
4046     HDC hdc;
4047     INT enumed;
4048 
4049     /* Report only once */
4050     if(!pGetGlyphIndicesA)
4051         win_skip("GetGlyphIndicesA is unavailable, negative width will not be checked\n");
4052 
4053     hdc = GetDC(0);
4054 
4055     memset(&lf, 0, sizeof(lf));
4056     lf.lfCharSet = DEFAULT_CHARSET;
4057     enumed = 0;
4058     EnumFontFamiliesExA(hdc, &lf, enum_truetype_font_proc, (LPARAM)&enumed, 0);
4059     trace("Tested metrics of %d truetype fonts\n", enumed);
4060 
4061     ReleaseDC(0, hdc);
4062 }
4063 
4064 static void test_nonexistent_font(void)
4065 {
4066     static const struct
4067     {
4068         const char *name;
4069         int charset;
4070     } font_subst[] =
4071     {
4072         { "Times New Roman Baltic", 186 },
4073         { "Times New Roman CE", 238 },
4074         { "Times New Roman CYR", 204 },
4075         { "Times New Roman Greek", 161 },
4076         { "Times New Roman TUR", 162 }
4077     };
4078     static const struct
4079     {
4080         const char *name;
4081         int charset;
4082     } shell_subst[] =
4083     {
4084         { "MS Shell Dlg", 186 },
4085         { "MS Shell Dlg", 238 },
4086         { "MS Shell Dlg", 204 },
4087         { "MS Shell Dlg", 161 },
4088         { "MS Shell Dlg", 162 }
4089     };
4090     LOGFONTA lf;
4091     HDC hdc;
4092     HFONT hfont;
4093     CHARSETINFO csi;
4094     INT cs, expected_cs, i, ret;
4095     char buf[LF_FACESIZE];
4096 
4097     expected_cs = GetACP();
4098     if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
4099     {
4100         skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
4101         return;
4102     }
4103     expected_cs = csi.ciCharset;
4104     trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
4105 
4106     hdc = CreateCompatibleDC(0);
4107 
4108     for (i = 0; i < sizeof(shell_subst)/sizeof(shell_subst[0]); i++)
4109     {
4110         ret = is_font_installed(shell_subst[i].name);
4111         ok(ret || broken(!ret) /* win2000 */, "%s should be enumerated\n", shell_subst[i].name);
4112         ret = is_truetype_font_installed(shell_subst[i].name);
4113         ok(ret || broken(!ret) /* win2000 */, "%s should be enumerated\n", shell_subst[i].name);
4114 
4115         memset(&lf, 0, sizeof(lf));
4116         lf.lfHeight = -13;
4117         lf.lfWeight = FW_REGULAR;
4118         strcpy(lf.lfFaceName, shell_subst[i].name);
4119         hfont = CreateFontIndirectA(&lf);
4120         hfont = SelectObject(hdc, hfont);
4121         GetTextFaceA(hdc, sizeof(buf), buf);
4122         ok(!lstrcmpiA(buf, shell_subst[i].name), "expected %s, got %s\n", shell_subst[i].name, buf);
4123         cs = GetTextCharset(hdc);
4124         ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d for font %s\n", cs, shell_subst[i].name);
4125 
4126         DeleteObject(SelectObject(hdc, hfont));
4127 
4128         memset(&lf, 0, sizeof(lf));
4129         lf.lfHeight = -13;
4130         lf.lfWeight = FW_DONTCARE;
4131         strcpy(lf.lfFaceName, shell_subst[i].name);
4132         hfont = CreateFontIndirectA(&lf);
4133         hfont = SelectObject(hdc, hfont);
4134         GetTextFaceA(hdc, sizeof(buf), buf);
4135         ok(!lstrcmpiA(buf, shell_subst[i].name), "expected %s, got %s\n", shell_subst[i].name, buf);
4136         cs = GetTextCharset(hdc);
4137         ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d for font %s\n", expected_cs, cs, shell_subst[i].name);
4138         DeleteObject(SelectObject(hdc, hfont));
4139     }
4140 
4141     if (!is_truetype_font_installed("Arial") ||
4142         !is_truetype_font_installed("Times New Roman"))
4143     {
4144         DeleteDC(hdc);
4145         skip("Arial or Times New Roman not installed\n");
4146         return;
4147     }
4148 
4149     memset(&lf, 0, sizeof(lf));
4150     lf.lfHeight = 100;
4151     lf.lfWeight = FW_REGULAR;
4152     lf.lfCharSet = ANSI_CHARSET;
4153     lf.lfPitchAndFamily = FF_SWISS;
4154     strcpy(lf.lfFaceName, "Nonexistent font");
4155     hfont = CreateFontIndirectA(&lf);
4156     hfont = SelectObject(hdc, hfont);
4157     GetTextFaceA(hdc, sizeof(buf), buf);
4158     ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
4159     cs = GetTextCharset(hdc);
4160     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
4161     DeleteObject(SelectObject(hdc, hfont));
4162 
4163     memset(&lf, 0, sizeof(lf));
4164     lf.lfHeight = -13;
4165     lf.lfWeight = FW_DONTCARE;
4166     strcpy(lf.lfFaceName, "Nonexistent font");
4167     hfont = CreateFontIndirectA(&lf);
4168     hfont = SelectObject(hdc, hfont);
4169     GetTextFaceA(hdc, sizeof(buf), buf);
4170 todo_wine /* Wine uses Arial for all substitutions */
4171     ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ ||
4172        !lstrcmpiA(buf, "MS Serif") || /* Win9x */
4173        !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
4174        "Got %s\n", buf);
4175     cs = GetTextCharset(hdc);
4176     ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d\n", expected_cs, cs);
4177     DeleteObject(SelectObject(hdc, hfont));
4178 
4179     memset(&lf, 0, sizeof(lf));
4180     lf.lfHeight = -13;
4181     lf.lfWeight = FW_REGULAR;
4182     strcpy(lf.lfFaceName, "Nonexistent font");
4183     hfont = CreateFontIndirectA(&lf);
4184     hfont = SelectObject(hdc, hfont);
4185     GetTextFaceA(hdc, sizeof(buf), buf);
4186     ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
4187        !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "Got %s\n", buf);
4188     cs = GetTextCharset(hdc);
4189     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
4190     DeleteObject(SelectObject(hdc, hfont));
4191 
4192     memset(&lf, 0, sizeof(lf));
4193     lf.lfHeight = -13;
4194     lf.lfWeight = FW_DONTCARE;
4195     strcpy(lf.lfFaceName, "Times New Roman");
4196     hfont = CreateFontIndirectA(&lf);
4197     hfont = SelectObject(hdc, hfont);
4198     GetTextFaceA(hdc, sizeof(buf), buf);
4199     ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf);
4200     cs = GetTextCharset(hdc);
4201     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
4202     DeleteObject(SelectObject(hdc, hfont));
4203 
4204     for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++)
4205     {
4206         ret = is_font_installed(font_subst[i].name);
4207 todo_wine
4208         ok(ret || broken(!ret && !i) /* win2000 doesn't have Times New Roman Baltic substitution */,
4209            "%s should be enumerated\n", font_subst[i].name);
4210         ret = is_truetype_font_installed(font_subst[i].name);
4211 todo_wine
4212         ok(ret || broken(!ret && !i) /* win2000 doesn't have Times New Roman Baltic substitution */,
4213            "%s should be enumerated\n", font_subst[i].name);
4214 
4215         memset(&lf, 0, sizeof(lf));
4216         lf.lfHeight = -13;
4217         lf.lfWeight = FW_REGULAR;
4218         strcpy(lf.lfFaceName, font_subst[i].name);
4219         hfont = CreateFontIndirectA(&lf);
4220         hfont = SelectObject(hdc, hfont);
4221         cs = GetTextCharset(hdc);
4222         if (font_subst[i].charset == expected_cs)
4223         {
4224             ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
4225             GetTextFaceA(hdc, sizeof(buf), buf);
4226             ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf);
4227         }
4228         else
4229         {
4230             ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d for font %s\n", cs, font_subst[i].name);
4231             GetTextFaceA(hdc, sizeof(buf), buf);
4232             ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
4233                !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got %s for font %s\n", buf, font_subst[i].name);
4234         }
4235         DeleteObject(SelectObject(hdc, hfont));
4236 
4237         memset(&lf, 0, sizeof(lf));
4238         lf.lfHeight = -13;
4239         lf.lfWeight = FW_DONTCARE;
4240         strcpy(lf.lfFaceName, font_subst[i].name);
4241         hfont = CreateFontIndirectA(&lf);
4242         hfont = SelectObject(hdc, hfont);
4243         GetTextFaceA(hdc, sizeof(buf), buf);
4244         ok(!lstrcmpiA(buf, "Arial") /* Wine */ ||
4245            !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ ||
4246            !lstrcmpiA(buf, "MS Serif") /* Win9x */ ||
4247            !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
4248            "got %s for font %s\n", buf, font_subst[i].name);
4249         cs = GetTextCharset(hdc);
4250         ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
4251         DeleteObject(SelectObject(hdc, hfont));
4252     }
4253 
4254     DeleteDC(hdc);
4255 }
4256 
4257 static void test_RealizationInfo(void)
4258 {
4259     struct font_realization_info {
4260         DWORD size;
4261         DWORD flags;
4262         DWORD cache_num;
4263         DWORD instance_id;
4264         DWORD unk;
4265         WORD  face_index;
4266         WORD  simulations;
4267     };
4268 
4269     struct realization_info_t
4270     {
4271         DWORD flags;
4272         DWORD cache_num;
4273         DWORD instance_id;
4274     };
4275 
4276     HDC hdc;
4277     DWORD info[4], info2[10];
4278     BOOL r, have_file = FALSE;
4279     HFONT hfont, hfont_old;
4280     LOGFONTA lf;
4281     DWORD needed, read;
4282     HANDLE h;
4283     BYTE file[16], data[14];
4284     struct file_info
4285     {
4286         FILETIME time;
4287         LARGE_INTEGER size;
4288         WCHAR path[MAX_PATH];
4289     } file_info;
4290     FILETIME time;
4291     LARGE_INTEGER size;
4292 
4293     if(!pGdiRealizationInfo)
4294     {
4295         win_skip("GdiRealizationInfo not available\n");
4296         return;
4297     }
4298 
4299     hdc = GetDC(0);
4300 
4301     memset(info, 0xcc, sizeof(info));
4302     r = pGdiRealizationInfo(hdc, info);
4303     ok(r != 0, "ret 0\n");
4304     ok((info[0] & 0xf) == 1, "info[0] = %x for the system font\n", info[0]);
4305     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
4306 
4307     if (!is_truetype_font_installed("Tahoma"))
4308     {
4309         skip("skipping GdiRealizationInfo with truetype font\n");
4310         goto end;
4311     }
4312 
4313     memset(&lf, 0, sizeof(lf));
4314     strcpy(lf.lfFaceName, "Tahoma");
4315     lf.lfHeight = 20;
4316     lf.lfWeight = FW_BOLD;
4317     lf.lfItalic = 1;
4318     hfont = CreateFontIndirectA(&lf);
4319     hfont_old = SelectObject(hdc, hfont);
4320 
4321     memset(info, 0xcc, sizeof(info));
4322     r = pGdiRealizationInfo(hdc, info);
4323     ok(r != 0, "ret 0\n");
4324     ok((info[0] & 0xf) == 3, "info[0] = %x for arial\n", info[0]);
4325     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
4326 
4327     if (pGetFontRealizationInfo)
4328     {
4329         struct font_realization_info *fri = (struct font_realization_info*)info2;
4330         struct realization_info_t *ri = (struct realization_info_t*)info;
4331 
4332         /* The first DWORD represents a struct size. On a
4333            newly rebooted system setting this to < 16 results
4334            in GetFontRealizationInfo failing.  However there
4335            appears to be some caching going on which results
4336            in calls after a successful call also succeeding even
4337            if the size < 16.  This means we can't reliably test
4338            this behaviour. */
4339 
4340         memset(info2, 0xcc, sizeof(info2));
4341         info2[0] = 16;
4342         r = pGetFontRealizationInfo(hdc, info2);
4343         ok(r != 0, "ret 0\n");
4344         /* We may get the '24' version here if that has been previously
4345            requested. */
4346         ok(fri->size == 16 || fri->size == 24, "got %d\n", info2[0]);
4347         ok(fri->flags == ri->flags, "flags mismatch\n");
4348         ok(fri->cache_num == ri->cache_num, "cache_num mismatch\n");
4349         ok(fri->instance_id == ri->instance_id, "instance id mismatch\n");
4350         ok(info2[6] == 0xcccccccc, "got wrong dword 6, 0x%08x\n", info2[6]);
4351 
4352         memset(info2, 0xcc, sizeof(info2));
4353         info2[0] = 28;
4354         r = pGetFontRealizationInfo(hdc, info2);
4355         ok(r == FALSE, "got %d\n", r);
4356 
4357         memset(info2, 0xcc, sizeof(info2));
4358         info2[0] = 24;
4359         r = pGetFontRealizationInfo(hdc, info2);
4360         ok(r != 0, "ret 0\n");
4361         ok(fri->size == 24, "got %d\n", fri->size);
4362         ok(fri->flags == ri->flags, "flags mismatch\n");
4363         ok(fri->cache_num == ri->cache_num, "cache_num mismatch\n");
4364         ok(fri->instance_id == ri->instance_id, "instance id mismatch\n");
4365         ok(fri->simulations == 0x2, "got simulations flags 0x%04x\n", fri->simulations);
4366         ok(fri->face_index == 0, "got wrong face index %u\n", fri->face_index);
4367         ok(info2[6] == 0xcccccccc, "structure longer than 6 dwords\n");
4368 
4369         /* Test GetFontFileInfo() */
4370         /* invalid font id */
4371         SetLastError(0xdeadbeef);
4372         r = pGetFontFileInfo(0xabababab, 0, &file_info, sizeof(file_info), &needed);
4373         ok(r == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "ret %d gle %d\n", r, GetLastError());
4374 
4375         needed = 0;
4376         r = pGetFontFileInfo(fri->instance_id, 0, &file_info, sizeof(file_info), &needed);
4377         ok(r != 0 || GetLastError() == ERROR_NOACCESS, "ret %d gle %d\n", r, GetLastError());
4378 
4379         if (r)
4380         {
4381             ok(needed > 0 && needed < sizeof(file_info), "got needed size %u\n", needed);
4382 
4383             h = CreateFileW(file_info.path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
4384             ok(h != INVALID_HANDLE_VALUE, "Unable to open file %d\n", GetLastError());
4385 
4386             GetFileTime(h, NULL, NULL, &time);
4387             ok(!CompareFileTime(&file_info.time, &time), "time mismatch\n");
4388             GetFileSizeEx(h, &size);
4389             ok(file_info.size.QuadPart == size.QuadPart, "size mismatch\n");
4390 
4391             /* Read first 16 bytes from the file */
4392             ReadFile(h, file, sizeof(file), &read, NULL);
4393             CloseHandle(h);
4394             have_file = TRUE;
4395 
4396             /* shorter buffer */
4397             SetLastError(0xdeadbeef);
4398             r = pGetFontFileInfo(fri->instance_id, 0, &file_info, needed - 1, &needed);
4399             ok(r == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "ret %d gle %d\n", r, GetLastError());
4400         }
4401 
4402     if (pGetFontFileData) {
4403         /* Get bytes 2 - 16 using GetFontFileData */
4404         r = pGetFontFileData(fri->instance_id, 0, 2, data, sizeof(data));
4405         ok(r != 0, "ret 0 gle %d\n", GetLastError());
4406 
4407         if (have_file)
4408             ok(!memcmp(data, file + 2, sizeof(data)), "mismatch\n");
4409         else
4410             win_skip("GetFontFileInfo() failed, skipping\n");
4411     }
4412     }
4413 
4414     DeleteObject(SelectObject(hdc, hfont_old));
4415 
4416  end:
4417     ReleaseDC(0, hdc);
4418 }
4419 
4420 /* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include
4421    the nul in the count of characters copied when the face name buffer is not
4422    NULL, whereas it does if the buffer is NULL.  Further, the Unicode version
4423    always includes it.  */
4424 static void test_GetTextFace(void)
4425 {
4426     static const char faceA[] = "Tahoma";
4427     static const WCHAR faceW[] = {'T','a','h','o','m','a', 0};
4428     LOGFONTA fA = {0};
4429     LOGFONTW fW = {0};
4430     char bufA[LF_FACESIZE];
4431     WCHAR bufW[LF_FACESIZE];
4432     HFONT f, g;
4433     HDC dc;
4434     int n;
4435 
4436     if(!is_font_installed("Tahoma"))
4437     {
4438         skip("Tahoma is not installed so skipping this test\n");
4439         return;
4440     }
4441 
4442     /* 'A' case.  */
4443     memcpy(fA.lfFaceName, faceA, sizeof faceA);
4444     f = CreateFontIndirectA(&fA);
4445     ok(f != NULL, "CreateFontIndirectA failed\n");
4446 
4447     dc = GetDC(NULL);
4448     g = SelectObject(dc, f);
4449     n = GetTextFaceA(dc, sizeof bufA, bufA);
4450     ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n);
4451     ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n");
4452 
4453     /* Play with the count arg.  */
4454     bufA[0] = 'x';
4455     n = GetTextFaceA(dc, 0, bufA);
4456     ok(n == 0, "GetTextFaceA returned %d\n", n);
4457     ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]);
4458 
4459     bufA[0] = 'x';
4460     n = GetTextFaceA(dc, 1, bufA);
4461     ok(n == 0, "GetTextFaceA returned %d\n", n);
4462     ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]);
4463 
4464     bufA[0] = 'x'; bufA[1] = 'y';
4465     n = GetTextFaceA(dc, 2, bufA);
4466     ok(n == 1, "GetTextFaceA returned %d\n", n);
4467     ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n");
4468 
4469     n = GetTextFaceA(dc, 0, NULL);
4470     ok(n == sizeof faceA ||
4471        broken(n == 0), /* win98, winMe */
4472        "GetTextFaceA returned %d\n", n);
4473 
4474     DeleteObject(SelectObject(dc, g));
4475     ReleaseDC(NULL, dc);
4476 
4477     /* 'W' case.  */
4478     memcpy(fW.lfFaceName, faceW, sizeof faceW);
4479     SetLastError(0xdeadbeef);
4480     f = CreateFontIndirectW(&fW);
4481     if (!f && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
4482     {
4483         win_skip("CreateFontIndirectW is not implemented\n");
4484         return;
4485     }
4486     ok(f != NULL, "CreateFontIndirectW failed\n");
4487 
4488     dc = GetDC(NULL);
4489     g = SelectObject(dc, f);
4490     n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW);
4491     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
4492     ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
4493 
4494     /* Play with the count arg.  */
4495     bufW[0] = 'x';
4496     n = GetTextFaceW(dc, 0, bufW);
4497     ok(n == 0, "GetTextFaceW returned %d\n", n);
4498     ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]);
4499 
4500     bufW[0] = 'x';
4501     n = GetTextFaceW(dc, 1, bufW);
4502     ok(n == 1, "GetTextFaceW returned %d\n", n);
4503     ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]);
4504 
4505     bufW[0] = 'x'; bufW[1] = 'y';
4506     n = GetTextFaceW(dc, 2, bufW);
4507     ok(n == 2, "GetTextFaceW returned %d\n", n);
4508     ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n");
4509 
4510     n = GetTextFaceW(dc, 0, NULL);
4511     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
4512 
4513     DeleteObject(SelectObject(dc, g));
4514     ReleaseDC(NULL, dc);
4515 }
4516 
4517 static void test_orientation(void)
4518 {
4519     static const char test_str[11] = "Test String";
4520     HDC hdc;
4521     LOGFONTA lf;
4522     HFONT hfont, old_hfont;
4523     SIZE size;
4524 
4525     if (!is_truetype_font_installed("Arial"))
4526     {
4527         skip("Arial is not installed\n");
4528         return;
4529     }
4530 
4531     hdc = CreateCompatibleDC(0);
4532     memset(&lf, 0, sizeof(lf));
4533     lstrcpyA(lf.lfFaceName, "Arial");
4534     lf.lfHeight = 72;
4535     lf.lfOrientation = lf.lfEscapement = 900;
4536     hfont = create_font("orientation", &lf);
4537     old_hfont = SelectObject(hdc, hfont);
4538     ok(GetTextExtentExPointA(hdc, test_str, sizeof(test_str), 32767, NULL, NULL, &size), "GetTextExtentExPointA failed\n");
4539     ok(near_match(311, size.cx), "cx should be about 311, got %d\n", size.cx);
4540     ok(near_match(75, size.cy), "cy should be about 75, got %d\n", size.cy);
4541     SelectObject(hdc, old_hfont);
4542     DeleteObject(hfont);
4543     DeleteDC(hdc);
4544 }
4545 
4546 static void test_oemcharset(void)
4547 {
4548     HDC hdc;
4549     LOGFONTA lf, clf;
4550     HFONT hfont, old_hfont;
4551     int charset;
4552 
4553     hdc = CreateCompatibleDC(0);
4554     ZeroMemory(&lf, sizeof(lf));
4555     lf.lfHeight = 12;
4556     lf.lfCharSet = OEM_CHARSET;
4557     lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
4558     lstrcpyA(lf.lfFaceName, "Terminal");
4559     hfont = CreateFontIndirectA(&lf);
4560     old_hfont = SelectObject(hdc, hfont);
4561     charset = GetTextCharset(hdc);
4562 todo_wine
4563     ok(charset == OEM_CHARSET, "expected %d charset, got %d\n", OEM_CHARSET, charset);
4564     hfont = SelectObject(hdc, old_hfont);
4565     GetObjectA(hfont, sizeof(clf), &clf);
4566     ok(!lstrcmpA(clf.lfFaceName, lf.lfFaceName), "expected %s face name, got %s\n", lf.lfFaceName, clf.lfFaceName);
4567     ok(clf.lfPitchAndFamily == lf.lfPitchAndFamily, "expected %x family, got %x\n", lf.lfPitchAndFamily, clf.lfPitchAndFamily);
4568     ok(clf.lfCharSet == lf.lfCharSet, "expected %d charset, got %d\n", lf.lfCharSet, clf.lfCharSet);
4569     ok(clf.lfHeight == lf.lfHeight, "expected %d height, got %d\n", lf.lfHeight, clf.lfHeight);
4570     DeleteObject(hfont);
4571     DeleteDC(hdc);
4572 }
4573 
4574 static int CALLBACK create_fixed_pitch_font_proc(const LOGFONTA *lpelfe,
4575                                                  const TEXTMETRICA *lpntme,
4576                                                  DWORD FontType, LPARAM lParam)
4577 {
4578     const NEWTEXTMETRICEXA *lpntmex = (const NEWTEXTMETRICEXA *)lpntme;
4579     CHARSETINFO csi;
4580     LOGFONTA lf = *lpelfe;
4581     HFONT hfont;
4582     DWORD found_subset;
4583 
4584     /* skip bitmap, proportional or vertical font */
4585     if ((FontType & TRUETYPE_FONTTYPE) == 0 ||
4586         (lf.lfPitchAndFamily & 0xf) != FIXED_PITCH ||
4587         lf.lfFaceName[0] == '@')
4588         return 1;
4589 
4590     /* skip linked font */
4591     if (!TranslateCharsetInfo((DWORD*)(INT_PTR)lpelfe->lfCharSet, &csi, TCI_SRCCHARSET) ||
4592         (lpntmex->ntmFontSig.fsCsb[0] & csi.fs.fsCsb[0]) == 0)
4593         return 1;
4594 
4595     /* skip linked font, like SimSun-ExtB */
4596     switch (lpelfe->lfCharSet) {
4597     case SHIFTJIS_CHARSET:
4598         found_subset = lpntmex->ntmFontSig.fsUsb[1] & (1 << 17); /* Hiragana */
4599         break;
4600     case GB2312_CHARSET:
4601     case CHINESEBIG5_CHARSET:
4602         found_subset = lpntmex->ntmFontSig.fsUsb[1] & (1 << 16); /* CJK Symbols And Punctuation */
4603         break;
4604     case HANGEUL_CHARSET:
4605         found_subset = lpntmex->ntmFontSig.fsUsb[1] & (1 << 24); /* Hangul Syllables */
4606         break;
4607     default:
4608         found_subset = lpntmex->ntmFontSig.fsUsb[0] & (1 <<  0); /* Basic Latin */
4609         break;
4610     }
4611     if (!found_subset)
4612         return 1;
4613 
4614     /* test with an odd height */
4615     lf.lfHeight = -19;
4616     lf.lfWidth = 0;
4617     hfont = CreateFontIndirectA(&lf);
4618     if (hfont)
4619     {
4620         *(HFONT *)lParam = hfont;
4621         return 0;
4622     }
4623     return 1;
4624 }
4625 
4626 static void test_GetGlyphOutline(void)
4627 {
4628     HDC hdc;
4629     GLYPHMETRICS gm, gm2;
4630     LOGFONTA lf;
4631     HFONT hfont, old_hfont;
4632     INT ret, ret2;
4633     const UINT fmt[] = { GGO_METRICS, GGO_BITMAP, GGO_GRAY2_BITMAP,
4634                          GGO_GRAY4_BITMAP, GGO_GRAY8_BITMAP };
4635     static const struct
4636     {
4637         UINT cs;
4638         UINT a;
4639         UINT w;
4640     } c[] =
4641     {
4642         {ANSI_CHARSET, 0x30, 0x30},
4643         {SHIFTJIS_CHARSET, 0x82a0, 0x3042},
4644         {HANGEUL_CHARSET, 0x8141, 0xac02},
4645         {GB2312_CHARSET, 0x8141, 0x4e04},
4646         {CHINESEBIG5_CHARSET, 0xa142, 0x3001}
4647     };
4648     UINT i;
4649 
4650     if (!is_truetype_font_installed("Tahoma"))
4651     {
4652         skip("Tahoma is not installed\n");
4653         return;
4654     }
4655 
4656     hdc = CreateCompatibleDC(0);
4657     memset(&lf, 0, sizeof(lf));
4658     lf.lfHeight = 72;
4659     lstrcpyA(lf.lfFaceName, "Tahoma");
4660     SetLastError(0xdeadbeef);
4661     hfont = CreateFontIndirectA(&lf);
4662     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
4663     old_hfont = SelectObject(hdc, hfont);
4664 
4665     memset(&gm, 0, sizeof(gm));
4666     SetLastError(0xdeadbeef);
4667     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
4668     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
4669 
4670     memset(&gm, 0, sizeof(gm));
4671     SetLastError(0xdeadbeef);
4672     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
4673     ok(ret == GDI_ERROR, "GetGlyphOutlineA should fail\n");
4674     ok(GetLastError() == 0xdeadbeef ||
4675        GetLastError() == ERROR_INVALID_PARAMETER, /* win98, winMe */
4676        "expected 0xdeadbeef, got %u\n", GetLastError());
4677 
4678     memset(&gm, 0, sizeof(gm));
4679     SetLastError(0xdeadbeef);
4680     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
4681     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
4682         ok(ret != GDI_ERROR, "GetGlyphOutlineW error %u\n", GetLastError());
4683 
4684     memset(&gm, 0, sizeof(gm));
4685     SetLastError(0xdeadbeef);
4686     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
4687     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
4688     {
4689        ok(ret == GDI_ERROR, "GetGlyphOutlineW should fail\n");
4690        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
4691     }
4692 
4693     /* test for needed buffer size request on space char */
4694     memset(&gm, 0, sizeof(gm));
4695     SetLastError(0xdeadbeef);
4696     ret = GetGlyphOutlineW(hdc, ' ', GGO_NATIVE, &gm, 0, NULL, &mat);
4697     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
4698     {
4699         ok(ret == 0, "GetGlyphOutlineW should return 0 buffer size for space char\n");
4700         ok(gm.gmBlackBoxX == 1, "Expected 1, got %u\n", gm.gmBlackBoxX);
4701         ok(gm.gmBlackBoxY == 1, "Expected 1, got %u\n", gm.gmBlackBoxY);
4702     }
4703 
4704     /* requesting buffer size for space char + error */
4705     memset(&gm, 0, sizeof(gm));
4706     SetLastError(0xdeadbeef);
4707     ret = GetGlyphOutlineW(0, ' ', GGO_NATIVE, &gm, 0, NULL, NULL);
4708     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
4709     {
4710        ok(ret == GDI_ERROR, "GetGlyphOutlineW should return GDI_ERROR\n");
4711        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
4712        ok(gm.gmBlackBoxX == 0, "Expected 0, got %u\n", gm.gmBlackBoxX);
4713        ok(gm.gmBlackBoxY == 0, "Expected 0, got %u\n", gm.gmBlackBoxY);
4714     }
4715 
4716     /* test GetGlyphOutline with a buffer too small */
4717     SetLastError(0xdeadbeef);
4718     ret = GetGlyphOutlineA(hdc, 'A', GGO_NATIVE, &gm, sizeof(i), &i, &mat);
4719     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
4720         ok(ret == GDI_ERROR, "GetGlyphOutlineW should return an error when the buffer size is too small.\n");
4721 
4722     for (i = 0; i < sizeof(fmt) / sizeof(fmt[0]); ++i)
4723     {
4724         DWORD dummy;
4725 
4726         memset(&gm, 0xab, sizeof(gm));
4727         SetLastError(0xdeadbeef);
4728         ret = GetGlyphOutlineW(hdc, ' ', fmt[i], &gm, 0, NULL, &mat);
4729         if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
4730         {
4731             if (fmt[i] == GGO_METRICS)
4732                 ok(ret != GDI_ERROR, "%2d:GetGlyphOutlineW should succeed, got %d\n", fmt[i], ret);
4733             else
4734                 ok(ret == 0, "%2d:GetGlyphOutlineW should return 0, got %d\n", fmt[i], ret);
4735             ok(gm.gmBlackBoxX == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxX);
4736             ok(gm.gmBlackBoxY == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxY);
4737         }
4738 
4739         memset(&gm, 0xab, sizeof(gm));
4740         SetLastError(0xdeadbeef);
4741         ret = GetGlyphOutlineW(hdc, ' ', fmt[i], &gm, 0, &dummy, &mat);
4742         if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
4743         {
4744             if (fmt[i] == GGO_METRICS)
4745                 ok(ret != GDI_ERROR, "%2d:GetGlyphOutlineW should succeed, got %d\n", fmt[i], ret);
4746             else
4747                 ok(ret == 0, "%2d:GetGlyphOutlineW should return 0, got %d\n", fmt[i], ret);
4748             ok(gm.gmBlackBoxX == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxX);
4749             ok(gm.gmBlackBoxY == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxY);
4750         }
4751 
4752         memset(&gm, 0xab, sizeof(gm));
4753         SetLastError(0xdeadbeef);
4754         ret = GetGlyphOutlineW(hdc, ' ', fmt[i], &gm, sizeof(dummy), NULL, &mat);
4755         if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
4756         {
4757             if (fmt[i] == GGO_METRICS)
4758                 ok(ret != GDI_ERROR, "%2d:GetGlyphOutlineW should succeed, got %d\n", fmt[i], ret);
4759             else
4760                 ok(ret == 0, "%2d:GetGlyphOutlineW should return 0, got %d\n", fmt[i], ret);
4761             ok(gm.gmBlackBoxX == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxX);
4762             ok(gm.gmBlackBoxY == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxY);
4763         }
4764 
4765         memset(&gm, 0xab, sizeof(gm));
4766         SetLastError(0xdeadbeef);
4767         ret = GetGlyphOutlineW(hdc, ' ', fmt[i], &gm, sizeof(dummy), &dummy, &mat);
4768         if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
4769         {
4770             if (fmt[i] == GGO_METRICS) {
4771                 ok(ret != GDI_ERROR, "%2d:GetGlyphOutlineW should succeed, got %d\n", fmt[i], ret);
4772                 ok(gm.gmBlackBoxX == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxX);
4773                 ok(gm.gmBlackBoxY == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxY);
4774             }
4775             else
4776             {
4777                 ok(ret == GDI_ERROR, "%2d:GetGlyphOutlineW should return GDI_ERROR, got %d\n", fmt[i], ret);
4778                 memset(&gm2, 0xab, sizeof(gm2));
4779                 ok(memcmp(&gm, &gm2, sizeof(GLYPHMETRICS)) == 0,
4780                    "%2d:GLYPHMETRICS shouldn't be touched on error\n", fmt[i]);
4781             }
4782         }
4783     }
4784 
4785     SelectObject(hdc, old_hfont);
4786     DeleteObject(hfont);
4787 
4788     for (i = 0; i < sizeof c / sizeof c[0]; ++i)
4789     {
4790         static const MAT2 rotate_mat = {{0, 0}, {0, -1}, {0, 1}, {0, 0}};
4791         TEXTMETRICA tm;
4792 
4793         lf.lfFaceName[0] = '\0';
4794         lf.lfCharSet = c[i].cs;
4795         lf.lfPitchAndFamily = 0;
4796         if (EnumFontFamiliesExA(hdc, &lf, create_font_proc, (LPARAM)&hfont, 0))
4797         {
4798             skip("TrueType font for charset %u is not installed\n", c[i].cs);
4799             continue;
4800         }
4801 
4802         old_hfont = SelectObject(hdc, hfont);
4803 
4804         /* expected to ignore superfluous bytes (sigle-byte character) */
4805         ret = GetGlyphOutlineA(hdc, 0x8041, GGO_BITMAP, &gm, 0, NULL, &mat);
4806         ret2 = GetGlyphOutlineA(hdc, 0x41, GGO_BITMAP, &gm2, 0, NULL, &mat);
4807         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
4808 
4809         ret = GetGlyphOutlineA(hdc, 0xcc8041, GGO_BITMAP, &gm, 0, NULL, &mat);
4810         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
4811            "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
4812 
4813         /* expected to ignore superfluous bytes (double-byte character) */
4814         ret = GetGlyphOutlineA(hdc, c[i].a, GGO_BITMAP, &gm, 0, NULL, &mat);
4815         ret2 = GetGlyphOutlineA(hdc, c[i].a | 0xdead0000, GGO_BITMAP, &gm2, 0, NULL, &mat);
4816         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
4817            "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
4818 
4819         /* expected to match wide-char version results */
4820         ret2 = GetGlyphOutlineW(hdc, c[i].w, GGO_BITMAP, &gm2, 0, NULL, &mat);
4821         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
4822 
4823         if (EnumFontFamiliesExA(hdc, &lf, create_fixed_pitch_font_proc, (LPARAM)&hfont, 0))
4824         {
4825             skip("Fixed-pitch TrueType font for charset %u is not available\n", c[i].cs);
4826             continue;
4827         }
4828         DeleteObject(SelectObject(hdc, hfont));
4829         if (c[i].a <= 0xff)
4830         {
4831             DeleteObject(SelectObject(hdc, old_hfont));
4832             continue;
4833         }
4834 
4835         ret = GetObjectA(hfont, sizeof lf, &lf);
4836         ok(ret > 0, "GetObject error %u\n", GetLastError());
4837 
4838         ret = GetTextMetricsA(hdc, &tm);
4839         ok(ret, "GetTextMetrics error %u\n", GetLastError());
4840         ret = GetGlyphOutlineA(hdc, c[i].a, GGO_METRICS, &gm2, 0, NULL, &mat);
4841         ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
4842         trace("Tests with height=%d,avg=%d,full=%d,face=%s,charset=%d\n",
4843               -lf.lfHeight, tm.tmAveCharWidth, gm2.gmCellIncX, lf.lfFaceName, lf.lfCharSet);
4844         ok(gm2.gmCellIncX == tm.tmAveCharWidth * 2 || broken(gm2.gmCellIncX == -lf.lfHeight),
4845            "expected %d, got %d (%s:%d)\n",
4846            tm.tmAveCharWidth * 2, gm2.gmCellIncX, lf.lfFaceName, lf.lfCharSet);
4847 
4848         ret = GetGlyphOutlineA(hdc, c[i].a, GGO_METRICS, &gm2, 0, NULL, &rotate_mat);
4849         ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
4850         ok(gm2.gmCellIncY == -lf.lfHeight,
4851            "expected %d, got %d (%s:%d)\n",
4852            -lf.lfHeight, gm2.gmCellIncY, lf.lfFaceName, lf.lfCharSet);
4853 
4854         lf.lfItalic = TRUE;
4855         hfont = CreateFontIndirectA(&lf);
4856         ok(hfont != NULL, "CreateFontIndirect error %u\n", GetLastError());
4857         DeleteObject(SelectObject(hdc, hfont));
4858         ret = GetTextMetricsA(hdc, &tm);
4859         ok(ret, "GetTextMetrics error %u\n", GetLastError());
4860         ret = GetGlyphOutlineA(hdc, c[i].a, GGO_METRICS, &gm2, 0, NULL, &mat);
4861         ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
4862         ok(gm2.gmCellIncX == tm.tmAveCharWidth * 2 || broken(gm2.gmCellIncX == -lf.lfHeight),
4863            "expected %d, got %d (%s:%d)\n",
4864            tm.tmAveCharWidth * 2, gm2.gmCellIncX, lf.lfFaceName, lf.lfCharSet);
4865 
4866         lf.lfItalic = FALSE;
4867         lf.lfEscapement = lf.lfOrientation = 2700;
4868         hfont = CreateFontIndirectA(&lf);
4869         ok(hfont != NULL, "CreateFontIndirect error %u\n", GetLastError());
4870         DeleteObject(SelectObject(hdc, hfont));
4871         ret = GetGlyphOutlineA(hdc, c[i].a, GGO_METRICS, &gm2, 0, NULL, &mat);
4872         ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
4873         ok(gm2.gmCellIncY == -lf.lfHeight,
4874            "expected %d, got %d (%s:%d)\n",
4875            -lf.lfHeight, gm2.gmCellIncY, lf.lfFaceName, lf.lfCharSet);
4876 
4877         hfont = SelectObject(hdc, old_hfont);
4878         DeleteObject(hfont);
4879     }
4880 
4881     DeleteDC(hdc);
4882 }
4883 
4884 /* bug #9995: there is a limit to the character width that can be specified */
4885 static void test_GetTextMetrics2(const char *fontname, int font_height)
4886 {
4887     HFONT of, hf;
4888     HDC hdc;
4889     TEXTMETRICA tm;
4890     BOOL ret;
4891     int ave_width, height, width, ratio, scale;
4892 
4893     if (!is_truetype_font_installed( fontname)) {
4894         skip("%s is not installed\n", fontname);
4895         return;
4896     }
4897     hdc = CreateCompatibleDC(0);
4898     ok( hdc != NULL, "CreateCompatibleDC failed\n");
4899     /* select width = 0 */
4900     hf = CreateFontA(font_height, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
4901             DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
4902             DEFAULT_QUALITY, VARIABLE_PITCH,
4903             fontname);
4904     ok( hf != NULL, "CreateFontA(%s, %d) failed\n", fontname, font_height);
4905     of = SelectObject( hdc, hf);
4906     ret = GetTextMetricsA( hdc, &tm);
4907     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
4908     height = tm.tmHeight;
4909     ave_width = tm.tmAveCharWidth;
4910     SelectObject( hdc, of);
4911     DeleteObject( hf);
4912 
4913     trace("height %d, ave width %d\n", height, ave_width);
4914 
4915     for (width = ave_width * 2; /* nothing*/; width += ave_width)
4916     {
4917         hf = CreateFontA(height, width, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
4918                         DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
4919                         DEFAULT_QUALITY, VARIABLE_PITCH, fontname);
4920         ok(hf != 0, "CreateFont failed\n");
4921         of = SelectObject(hdc, hf);
4922         ret = GetTextMetricsA(hdc, &tm);
4923         ok(ret, "GetTextMetrics error %u\n", GetLastError());
4924         SelectObject(hdc, of);
4925         DeleteObject(hf);
4926 
4927         if (match_off_by_1(tm.tmAveCharWidth, ave_width, FALSE) || width / height > 200)
4928             break;
4929     }
4930 
4931     DeleteDC(hdc);
4932 
4933     ratio = width / height;
4934     scale = width / ave_width;
4935 
4936     trace("max width/height ratio (%d / %d) %d, max width scale (%d / %d) %d\n",
4937           width, height, ratio, width, ave_width, scale);
4938 
4939     ok(ratio >= 90 && ratio <= 110, "expected width/height ratio 90-110, got %d\n", ratio);
4940 }
4941 
4942 static void test_GetCharacterPlacement(void)
4943 {
4944     GCP_RESULTSA result;
4945     DWORD size, size2;
4946     WCHAR glyphs[20];
4947     HDC hdc;
4948 
4949     hdc = CreateCompatibleDC(0);
4950     ok(!!hdc, "CreateCompatibleDC failed\n");
4951 
4952     memset(&result, 0, sizeof(result));
4953     result.lStructSize = sizeof(result);
4954     result.lpGlyphs = glyphs;
4955     result.nGlyphs  = 20;
4956 
4957     size = GetCharacterPlacementA(hdc, "Wine Test", 9, 0, &result, 0);
4958     ok(size, "GetCharacterPlacementA failed!\n");
4959 
4960     size2 = GetCharacterPlacementA(hdc, "Wine Test", 9, 0, NULL, 0);
4961     ok(size2, "GetCharacterPlacementA failed!\n");
4962     ok(size == size2, "GetCharacterPlacementA returned different result: %u vs %u\n", size2, size);
4963 
4964     size2 = GetCharacterPlacementA(hdc, "Wine Test", 9, 1024, NULL, GCP_REORDER);
4965     ok(size2, "GetCharacterPlacementA failed!\n");
4966     ok(size == size2, "GetCharacterPlacementA returned different result: %u vs %u\n", size2, size);
4967 
4968     size = GetCharacterPlacementA(hdc, "Wine Test", 9, 1024, &result, GCP_REORDER);
4969     ok(size, "GetCharacterPlacementA failed!\n");
4970     ok(size == size2, "GetCharacterPlacementA returned different result: %u vs %u\n", size2, size);
4971 }
4972 
4973 static void test_CreateFontIndirect(void)
4974 {
4975     LOGFONTA lf, getobj_lf;
4976     int ret, i;
4977     HFONT hfont;
4978     char TestName[][16] = {"Arial", "Arial Bold", "Arial Italic", "Arial Baltic"};
4979 
4980     memset(&lf, 0, sizeof(lf));
4981     lf.lfCharSet = ANSI_CHARSET;
4982     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
4983     lf.lfHeight = 16;
4984     lf.lfWidth = 16;
4985     lf.lfQuality = DEFAULT_QUALITY;
4986     lf.lfItalic = FALSE;
4987     lf.lfWeight = FW_DONTCARE;
4988 
4989     for (i = 0; i < sizeof(TestName)/sizeof(TestName[0]); i++)
4990     {
4991         lstrcpyA(lf.lfFaceName, TestName[i]);
4992         hfont = CreateFontIndirectA(&lf);
4993         ok(hfont != 0, "CreateFontIndirectA failed\n");
4994         SetLastError(0xdeadbeef);
4995         ret = GetObjectA(hfont, sizeof(getobj_lf), &getobj_lf);
4996         ok(ret, "GetObject failed: %d\n", GetLastError());
4997         ok(lf.lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf.lfItalic, getobj_lf.lfItalic);
4998         ok(lf.lfWeight == getobj_lf.lfWeight ||
4999            broken((SHORT)lf.lfWeight == getobj_lf.lfWeight), /* win9x */
5000            "lfWeight: expect %08x got %08x\n", lf.lfWeight, getobj_lf.lfWeight);
5001         ok(!lstrcmpA(lf.lfFaceName, getobj_lf.lfFaceName) ||
5002            broken(!memcmp(lf.lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
5003            "font names don't match: %s != %s\n", lf.lfFaceName, getobj_lf.lfFaceName);
5004         DeleteObject(hfont);
5005     }
5006 }
5007 
5008 static void test_CreateFontIndirectEx(void)
5009 {
5010     ENUMLOGFONTEXDVA lfex;
5011     HFONT hfont;
5012 
5013     if (!pCreateFontIndirectExA)
5014     {
5015         win_skip("CreateFontIndirectExA is not available\n");
5016         return;
5017     }
5018 
5019     if (!is_truetype_font_installed("Arial"))
5020     {
5021         skip("Arial is not installed\n");
5022         return;
5023     }
5024 
5025     SetLastError(0xdeadbeef);
5026     hfont = pCreateFontIndirectExA(NULL);
5027     ok(hfont == NULL, "got %p\n", hfont);
5028     ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
5029 
5030     memset(&lfex, 0, sizeof(lfex));
5031     lstrcpyA(lfex.elfEnumLogfontEx.elfLogFont.lfFaceName, "Arial");
5032     hfont = pCreateFontIndirectExA(&lfex);
5033     ok(hfont != 0, "CreateFontIndirectEx failed\n");
5034     if (hfont)
5035         check_font("Arial", &lfex.elfEnumLogfontEx.elfLogFont, hfont);
5036     DeleteObject(hfont);
5037 }
5038 
5039 static void free_font(void *font)
5040 {
5041     UnmapViewOfFile(font);
5042 }
5043 
5044 static void *load_font(const char *font_name, DWORD *font_size)
5045 {
5046     char file_name[MAX_PATH];
5047     HANDLE file, mapping;
5048     void *font;
5049 
5050     if (!GetWindowsDirectoryA(file_name, sizeof(file_name))) return NULL;
5051     strcat(file_name, "\\fonts\\");
5052     strcat(file_name, font_name);
5053 
5054     file = CreateFileA(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
5055     if (file == INVALID_HANDLE_VALUE) return NULL;
5056 
5057     *font_size = GetFileSize(file, NULL);
5058 
5059     mapping = CreateFileMappingA(file, NULL, PAGE_READONLY, 0, 0, NULL);
5060     if (!mapping)
5061     {
5062         CloseHandle(file);
5063         return NULL;
5064     }
5065 
5066     font = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
5067 
5068     CloseHandle(file);
5069     CloseHandle(mapping);
5070     return font;
5071 }
5072 
5073 static void test_AddFontMemResource(void)
5074 {
5075     void *font;
5076     DWORD font_size, num_fonts;
5077     HANDLE ret;
5078     BOOL bRet;
5079 
5080     if (!pAddFontMemResourceEx || !pRemoveFontMemResourceEx)
5081     {
5082         win_skip("AddFontMemResourceEx is not available on this platform\n");
5083         return;
5084     }
5085 
5086     font = load_font("sserife.fon", &font_size);
5087     if (!font)
5088     {
5089         skip("Unable to locate and load font sserife.fon\n");
5090         return;
5091     }
5092 
5093     SetLastError(0xdeadbeef);
5094     ret = pAddFontMemResourceEx(NULL, 0, NULL, NULL);
5095     ok(!ret, "AddFontMemResourceEx should fail\n");
5096     ok(GetLastError() == ERROR_INVALID_PARAMETER,
5097        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
5098        GetLastError());
5099 
5100     SetLastError(0xdeadbeef);
5101     ret = pAddFontMemResourceEx(NULL, 10, NULL, NULL);
5102     ok(!ret, "AddFontMemResourceEx should fail\n");
5103     ok(GetLastError() == ERROR_INVALID_PARAMETER,
5104        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
5105        GetLastError());
5106 
5107     SetLastError(0xdeadbeef);
5108     ret = pAddFontMemResourceEx(NULL, 0, NULL, &num_fonts);
5109     ok(!ret, "AddFontMemResourceEx should fail\n");
5110     ok(GetLastError() == ERROR_INVALID_PARAMETER,
5111        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
5112        GetLastError());
5113 
5114     SetLastError(0xdeadbeef);
5115     ret = pAddFontMemResourceEx(NULL, 10, NULL, &num_fonts);
5116     ok(!ret, "AddFontMemResourceEx should fail\n");
5117     ok(GetLastError() == ERROR_INVALID_PARAMETER,
5118        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
5119        GetLastError());
5120 
5121     SetLastError(0xdeadbeef);
5122     ret = pAddFontMemResourceEx(font, 0, NULL, NULL);
5123     ok(!ret, "AddFontMemResourceEx should fail\n");
5124     ok(GetLastError() == ERROR_INVALID_PARAMETER,
5125        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
5126        GetLastError());
5127 
5128     SetLastError(0xdeadbeef);
5129     ret = pAddFontMemResourceEx(font, 10, NULL, NULL);
5130     ok(!ret, "AddFontMemResourceEx should fail\n");
5131     ok(GetLastError() == ERROR_INVALID_PARAMETER,
5132        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
5133        GetLastError());
5134 
5135     num_fonts = 0xdeadbeef;
5136     SetLastError(0xdeadbeef);
5137     ret = pAddFontMemResourceEx(font, 0, NULL, &num_fonts);
5138     ok(!ret, "AddFontMemResourceEx should fail\n");
5139     ok(GetLastError() == ERROR_INVALID_PARAMETER,
5140        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
5141        GetLastError());
5142     ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
5143 
5144     if (0) /* hangs under windows 2000 */
5145     {
5146         num_fonts = 0xdeadbeef;
5147         SetLastError(0xdeadbeef);
5148         ret = pAddFontMemResourceEx(font, 10, NULL, &num_fonts);
5149         ok(!ret, "AddFontMemResourceEx should fail\n");
5150         ok(GetLastError() == 0xdeadbeef,
5151            "Expected GetLastError() to return 0xdeadbeef, got %u\n",
5152            GetLastError());
5153         ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
5154     }
5155 
5156     num_fonts = 0xdeadbeef;
5157     SetLastError(0xdeadbeef);
5158     ret = pAddFontMemResourceEx(font, font_size, NULL, &num_fonts);
5159     ok(ret != 0, "AddFontMemResourceEx error %d\n", GetLastError());
5160     ok(num_fonts != 0xdeadbeef, "number of loaded fonts should not be 0xdeadbeef\n");
5161     ok(num_fonts != 0, "number of loaded fonts should not be 0\n");
5162 
5163     free_font(font);
5164 
5165     SetLastError(0xdeadbeef);
5166     bRet = pRemoveFontMemResourceEx(ret);
5167     ok(bRet, "RemoveFontMemResourceEx error %d\n", GetLastError());
5168 
5169     /* test invalid pointer to number of loaded fonts */
5170     font = load_font("sserife.fon", &font_size);
5171     ok(font != NULL, "Unable to locate and load font sserife.fon\n");
5172 
5173     SetLastError(0xdeadbeef);
5174     ret = pAddFontMemResourceEx(font, font_size, NULL, (void *)0xdeadbeef);
5175     ok(!ret, "AddFontMemResourceEx should fail\n");
5176     ok(GetLastError() == 0xdeadbeef,
5177        "Expected GetLastError() to return 0xdeadbeef, got %u\n",
5178        GetLastError());
5179 
5180     SetLastError(0xdeadbeef);
5181     ret = pAddFontMemResourceEx(font, font_size, NULL, NULL);
5182     ok(!ret, "AddFontMemResourceEx should fail\n");
5183     ok(GetLastError() == ERROR_INVALID_PARAMETER,
5184        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
5185        GetLastError());
5186 
5187     free_font(font);
5188 }
5189 
5190 static INT CALLBACK enum_fonts_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lparam)
5191 {
5192     LOGFONTA *lf;
5193 
5194     if (type != TRUETYPE_FONTTYPE) return 1;
5195 
5196     ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
5197 
5198     lf = (LOGFONTA *)lparam;
5199     *lf = *elf;
5200     return 0;
5201 }
5202 
5203 static INT CALLBACK enum_all_fonts_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lparam)
5204 {
5205     int ret;
5206     LOGFONTA *lf;
5207 
5208     if (type != TRUETYPE_FONTTYPE) return 1;
5209 
5210     lf = (LOGFONTA *)lparam;
5211     ret = strcmp(lf->lfFaceName, elf->lfFaceName);
5212     if(ret == 0)
5213     {
5214         ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
5215         *lf = *elf;
5216         return 0;
5217     }
5218     return 1;
5219 }
5220 
5221 static INT CALLBACK enum_with_magic_retval_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lparam)
5222 {
5223     return lparam;
5224 }
5225 
5226 static void test_EnumFonts(void)
5227 {
5228     int ret;
5229     LOGFONTA lf;
5230     HDC hdc;
5231 
5232     if (!is_truetype_font_installed("Arial"))
5233     {
5234         skip("Arial is not installed\n");
5235         return;
5236     }
5237 
5238     /* Windows uses localized font face names, so Arial Bold won't be found */
5239     if (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH)
5240     {
5241         skip("User locale is not English, skipping the test\n");
5242         return;
5243     }
5244 
5245     hdc = CreateCompatibleDC(0);
5246 
5247     /* check that the enumproc's retval is returned */
5248     ret = EnumFontFamiliesA(hdc, NULL, enum_with_magic_retval_proc, 0xcafe);
5249     ok(ret == 0xcafe, "got %08x\n", ret);
5250 
5251     ret = EnumFontFamiliesA(hdc, "Arial", enum_fonts_proc, (LPARAM)&lf);
5252     ok(!ret, "font Arial is not enumerated\n");
5253     ret = strcmp(lf.lfFaceName, "Arial");
5254     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
5255     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
5256 
5257     strcpy(lf.lfFaceName, "Arial");
5258     ret = EnumFontFamiliesA(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
5259     ok(!ret, "font Arial is not enumerated\n");
5260     ret = strcmp(lf.lfFaceName, "Arial");
5261     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
5262     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
5263 
5264     ret = EnumFontFamiliesA(hdc, "Arial Bold", enum_fonts_proc, (LPARAM)&lf);
5265     ok(!ret, "font Arial Bold is not enumerated\n");
5266     ret = strcmp(lf.lfFaceName, "Arial");
5267     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
5268     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
5269 
5270     strcpy(lf.lfFaceName, "Arial Bold");
5271     ret = EnumFontFamiliesA(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
5272     ok(ret, "font Arial Bold should not be enumerated\n");
5273 
5274     ret = EnumFontFamiliesA(hdc, "Arial Bold Italic", enum_fonts_proc, (LPARAM)&lf);
5275     ok(!ret, "font Arial Bold Italic is not enumerated\n");
5276     ret = strcmp(lf.lfFaceName, "Arial");
5277     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
5278     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
5279 
5280     strcpy(lf.lfFaceName, "Arial Bold Italic");
5281     ret = EnumFontFamiliesA(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
5282     ok(ret, "font Arial Bold Italic should not be enumerated\n");
5283 
5284     ret = EnumFontFamiliesA(hdc, "Arial Italic Bold", enum_fonts_proc, (LPARAM)&lf);
5285     ok(ret, "font Arial Italic Bold  should not be enumerated\n");
5286 
5287     strcpy(lf.lfFaceName, "Arial Italic Bold");
5288     ret = EnumFontFamiliesA(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
5289     ok(ret, "font Arial Italic Bold should not be enumerated\n");
5290 
5291     DeleteDC(hdc);
5292 }
5293 
5294 static INT CALLBACK enum_ms_shell_dlg_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
5295 {
5296     struct enum_fullname_data *efnd = (struct enum_fullname_data *)lParam;
5297 
5298 if (0) /* Disabled to limit console spam */
5299     trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
5300           lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
5301 
5302     if (type != TRUETYPE_FONTTYPE) return 1;
5303     if (strcmp(lf->lfFaceName, "MS Shell Dlg") != 0) return 1;
5304 
5305     if (efnd->total >= efnd->size)
5306     {
5307         efnd->size = max( (efnd->total + 1) * 2, 256 );
5308         efnd->elf = heap_realloc( efnd->elf, efnd->size * sizeof(*efnd->elf) );
5309         if (!efnd->elf) return 0;
5310     }
5311     efnd->elf[efnd->total++] = *(ENUMLOGFONTA *)lf;
5312     return 0;
5313 }
5314 
5315 static INT CALLBACK enum_ms_shell_dlg2_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
5316 {
5317     struct enum_fullname_data *efnd = (struct enum_fullname_data *)lParam;
5318 
5319 if (0) /* Disabled to limit console spam */
5320     trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
5321           lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
5322 
5323     if (type != TRUETYPE_FONTTYPE) return 1;
5324     if (strcmp(lf->lfFaceName, "MS Shell Dlg 2") != 0) return 1;
5325 
5326     if (efnd->total >= efnd->size)
5327     {
5328         efnd->size = max( (efnd->total + 1) * 2, 256 );
5329         efnd->elf = heap_realloc( efnd->elf, efnd->size * sizeof(*efnd->elf) );
5330         if (!efnd->elf) return 0;
5331     }
5332     efnd->elf[efnd->total++] = *(ENUMLOGFONTA *)lf;
5333     return 0;
5334 }
5335 
5336 static void test_EnumFonts_subst(void)
5337 {
5338     int ret;
5339     LOGFONTA lf;
5340     HDC hdc;
5341     struct enum_fullname_data efnd;
5342 
5343     ret = is_font_installed("MS Shell Dlg");
5344     ok(ret, "MS Shell Dlg should be enumerated\n");
5345     ret = is_truetype_font_installed("MS Shell Dlg");
5346     ok(ret, "MS Shell Dlg should be enumerated as a TrueType font\n");
5347 
5348     ret = is_font_installed("MS Shell Dlg 2");
5349     ok(ret, "MS Shell Dlg 2 should be enumerated\n");
5350     ret = is_truetype_font_installed("MS Shell Dlg 2");
5351     ok(ret, "MS Shell Dlg 2 should be enumerated as a TrueType font\n");
5352 
5353     hdc = CreateCompatibleDC(0);
5354 
5355     memset(&efnd, 0, sizeof(efnd));
5356     ret = EnumFontFamiliesExA(hdc, NULL, enum_ms_shell_dlg_proc, (LPARAM)&efnd, 0);
5357     ok(ret, "MS Shell Dlg should not be enumerated\n");
5358     ok(!efnd.total, "MS Shell Dlg should not be enumerated\n");
5359 
5360     memset(&lf, 0, sizeof(lf));
5361     lf.lfCharSet = DEFAULT_CHARSET;
5362 
5363     efnd.total = 0;
5364     strcpy(lf.lfFaceName, "MS Shell Dlg");
5365     ret = EnumFontFamiliesExA(hdc, &lf, enum_ms_shell_dlg_proc, (LPARAM)&efnd, 0);
5366     ok(!ret, "MS Shell Dlg should be enumerated\n");
5367     ok(efnd.total > 0, "MS Shell Dlg should be enumerated\n");
5368     if (efnd.total)
5369     {
5370         ret = strcmp((const char *)efnd.elf[0].elfLogFont.lfFaceName, "MS Shell Dlg");
5371         ok(!ret, "expected MS Shell Dlg, got %s\n", efnd.elf[0].elfLogFont.lfFaceName);
5372         ret = strcmp((const char *)efnd.elf[0].elfFullName, "MS Shell Dlg");
5373         ok(ret, "did not expect MS Shell Dlg\n");
5374     }
5375 
5376     efnd.total = 0;
5377     ret = EnumFontFamiliesExA(hdc, NULL, enum_ms_shell_dlg2_proc, (LPARAM)&efnd, 0);
5378     ok(ret, "MS Shell Dlg 2 should not be enumerated\n");
5379     ok(!efnd.total, "MS Shell Dlg 2 should not be enumerated\n");
5380 
5381     efnd.total = 0;
5382     strcpy(lf.lfFaceName, "MS Shell Dlg 2");
5383     ret = EnumFontFamiliesExA(hdc, &lf, enum_ms_shell_dlg2_proc, (LPARAM)&efnd, 0);
5384     ok(!ret, "MS Shell Dlg 2 should be enumerated\n");
5385     ok(efnd.total > 0, "MS Shell Dlg 2 should be enumerated\n");
5386     if (efnd.total)
5387     {
5388         ret = strcmp((const char *)efnd.elf[0].elfLogFont.lfFaceName, "MS Shell Dlg 2");
5389         ok(!ret, "expected MS Shell Dlg 2, got %s\n", efnd.elf[0].elfLogFont.lfFaceName);
5390         ret = strcmp((const char *)efnd.elf[0].elfFullName, "MS Shell Dlg 2");
5391         ok(ret, "did not expect MS Shell Dlg 2\n");
5392     }
5393 
5394     heap_free(efnd.elf);
5395     DeleteDC(hdc);
5396 }
5397 
5398 static INT CALLBACK is_font_installed_fullname_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
5399 {
5400     const ENUMLOGFONTA *elf = (const ENUMLOGFONTA *)lf;
5401     const char *fullname = (const char *)lParam;
5402 
5403     if (!strcmp((const char *)elf->elfFullName, fullname)) return 0;
5404 
5405     return 1;
5406 }
5407 
5408 static BOOL is_font_installed_fullname(const char *family, const char *fullname)
5409 {
5410     HDC hdc = GetDC(0);
5411     BOOL ret = FALSE;
5412 
5413     if(!EnumFontFamiliesA(hdc, family, is_font_installed_fullname_proc, (LPARAM)fullname))
5414         ret = TRUE;
5415 
5416     ReleaseDC(0, hdc);
5417     return ret;
5418 }
5419 
5420 static void test_fullname(void)
5421 {
5422     static const char *TestName[] = {"Lucida Sans Demibold Roman", "Lucida Sans Italic", "Lucida Sans Regular"};
5423     WCHAR bufW[LF_FULLFACESIZE];
5424     char bufA[LF_FULLFACESIZE];
5425     HFONT hfont, of;
5426     LOGFONTA lf;
5427     HDC hdc;
5428     int i;
5429     DWORD ret;
5430 
5431     hdc = CreateCompatibleDC(0);
5432     ok(hdc != NULL, "CreateCompatibleDC failed\n");
5433 
5434     memset(&lf, 0, sizeof(lf));
5435     lf.lfCharSet = ANSI_CHARSET;
5436     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
5437     lf.lfHeight = 16;
5438     lf.lfWidth = 16;
5439     lf.lfQuality = DEFAULT_QUALITY;
5440     lf.lfItalic = FALSE;
5441     lf.lfWeight = FW_DONTCARE;
5442 
5443     for (i = 0; i < sizeof(TestName) / sizeof(TestName[0]); i++)
5444     {
5445         if (!is_font_installed_fullname("Lucida Sans", TestName[i]))
5446         {
5447             skip("%s is not installed\n", TestName[i]);
5448             continue;
5449         }
5450 
5451         lstrcpyA(lf.lfFaceName, TestName[i]);
5452         hfont = CreateFontIndirectA(&lf);
5453         ok(hfont != 0, "CreateFontIndirectA failed\n");
5454 
5455         of = SelectObject(hdc, hfont);
5456         bufW[0] = 0;
5457         bufA[0] = 0;
5458         ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FULL_NAME, bufW, sizeof(bufW), TT_MS_LANGID_ENGLISH_UNITED_STATES);
5459         ok(ret, "face full name could not be read\n");
5460         WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, sizeof(bufA), NULL, FALSE);
5461         ok(!lstrcmpA(bufA, TestName[i]), "font full names don't match: %s != %s\n", TestName[i], bufA);
5462         SelectObject(hdc, of);
5463         DeleteObject(hfont);
5464     }
5465     DeleteDC(hdc);
5466 }
5467 
5468 static WCHAR *prepend_at(WCHAR *family)
5469 {
5470     if (!family)
5471         return NULL;
5472 
5473     memmove(family + 1, family, (lstrlenW(family) + 1) * sizeof(WCHAR));
5474     family[0] = '@';
5475     return family;
5476 }
5477 
5478 static void test_fullname2_helper(const char *Family)
5479 {
5480     char *FamilyName, *FaceName, *StyleName, *otmStr;
5481     struct enum_fullname_data efnd;
5482     WCHAR *bufW;
5483     char *bufA;
5484     HFONT hfont, of;
5485     LOGFONTA lf;
5486     HDC hdc;
5487     int i;
5488     DWORD otm_size, ret, buf_size;
5489     OUTLINETEXTMETRICA *otm;
5490     BOOL want_vertical, get_vertical;
5491     want_vertical = ( Family[0] == '@' );
5492 
5493     hdc = CreateCompatibleDC(0);
5494     ok(hdc != NULL, "CreateCompatibleDC failed\n");
5495 
5496     memset(&lf, 0, sizeof(lf));
5497     lf.lfCharSet = DEFAULT_CHARSET;
5498     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
5499     lf.lfHeight = 16;
5500     lf.lfWidth = 16;
5501     lf.lfQuality = DEFAULT_QUALITY;
5502     lf.lfItalic = FALSE;
5503     lf.lfWeight = FW_DONTCARE;
5504     strcpy(lf.lfFaceName, Family);
5505     memset(&efnd, 0, sizeof(efnd));
5506     EnumFontFamiliesExA(hdc, &lf, enum_fullname_data_proc, (LPARAM)&efnd, 0);
5507     if (efnd.total == 0)
5508         skip("%s is not installed\n", lf.lfFaceName);
5509 
5510     for (i = 0; i < efnd.total; i++)
5511     {
5512         FamilyName = (char *)efnd.elf[i].elfLogFont.lfFaceName;
5513         FaceName = (char *)efnd.elf[i].elfFullName;
5514         StyleName = (char *)efnd.elf[i].elfStyle;
5515 
5516         get_vertical = ( FamilyName[0] == '@' );
5517         ok(get_vertical == want_vertical, "Vertical flags don't match: %s %s\n", Family, FamilyName);
5518 
5519         lstrcpyA(lf.lfFaceName, FaceName);
5520         hfont = CreateFontIndirectA(&lf);
5521         ok(hfont != 0, "CreateFontIndirectA failed\n");
5522 
5523         of = SelectObject(hdc, hfont);
5524         buf_size = GetFontData(hdc, MS_NAME_TAG, 0, NULL, 0);
5525         ok(buf_size != GDI_ERROR, "no name table found\n");
5526         if (buf_size == GDI_ERROR) continue;
5527 
5528         bufW = HeapAlloc(GetProcessHeap(), 0, buf_size);
5529         bufA = HeapAlloc(GetProcessHeap(), 0, buf_size);
5530 
5531         otm_size = GetOutlineTextMetricsA(hdc, 0, NULL);
5532         otm = HeapAlloc(GetProcessHeap(), 0, otm_size);
5533         memset(otm, 0, otm_size);
5534         ret = GetOutlineTextMetricsA(hdc, otm_size, otm);
5535         ok(ret != 0, "GetOutlineTextMetrics fails!\n");
5536         if (ret == 0) continue;
5537 
5538         bufW[0] = 0;
5539         bufA[0] = 0;
5540         ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FONT_FAMILY, bufW, buf_size, GetSystemDefaultLangID());
5541         if (!ret) ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FONT_FAMILY, bufW, buf_size, TT_MS_LANGID_ENGLISH_UNITED_STATES);
5542         ok(ret, "%s: FAMILY (family name) could not be read\n", FamilyName);
5543         if (want_vertical) bufW = prepend_at(bufW);
5544         WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
5545         ok(!lstrcmpA(FamilyName, bufA), "font family names don't match: returned %s, expect %s\n", FamilyName, bufA);
5546         otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpFamilyName;
5547         ok(!lstrcmpA(FamilyName, otmStr), "FamilyName %s doesn't match otmpFamilyName %s\n", FamilyName, otmStr);
5548 
5549         bufW[0] = 0;
5550         bufA[0] = 0;
5551         ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FULL_NAME, bufW, buf_size, GetSystemDefaultLangID());
5552         if (!ret) ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FULL_NAME, bufW, buf_size, TT_MS_LANGID_ENGLISH_UNITED_STATES);
5553         ok(ret, "FULL_NAME (face name) could not be read\n");
5554         if (want_vertical) bufW = prepend_at(bufW);
5555         WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
5556         ok(!lstrcmpA(FaceName, bufA), "%s: font face names don't match: returned %s, expect %s\n", FamilyName, FaceName, bufA);
5557         otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpFaceName;
5558         ok(!lstrcmpA(FaceName, otmStr), "%s: FaceName %s doesn't match otmpFaceName %s\n", FamilyName, FaceName, otmStr);
5559 
5560         bufW[0] = 0;
5561         bufA[0] = 0;
5562         ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FONT_SUBFAMILY, bufW, buf_size, GetSystemDefaultLangID());
5563         if (!ret) ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FONT_SUBFAMILY, bufW, buf_size, TT_MS_LANGID_ENGLISH_UNITED_STATES);
5564         ok(ret, "%s: SUBFAMILY (style name) could not be read\n", FamilyName);
5565         WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
5566         ok(!lstrcmpA(StyleName, bufA), "%s: style names don't match: returned %s, expect %s\n", FamilyName, StyleName, bufA);
5567         otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpStyleName;
5568         ok(!lstrcmpA(StyleName, otmStr), "%s: StyleName %s doesn't match otmpStyleName %s\n", FamilyName, StyleName, otmStr);
5569 
5570         bufW[0] = 0;
5571         bufA[0] = 0;
5572         ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_UNIQUE_ID, bufW, buf_size, GetSystemDefaultLangID());
5573         if (!ret) ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_UNIQUE_ID, bufW, buf_size, TT_MS_LANGID_ENGLISH_UNITED_STATES);
5574         ok(ret, "%s: UNIQUE_ID (full name) could not be read\n", FamilyName);
5575         WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
5576         otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpFullName;
5577         ok(!lstrcmpA(otmStr, bufA), "%s: UNIQUE ID (full name) doesn't match: returned %s, expect %s\n", FamilyName, otmStr, bufA);
5578 
5579         SelectObject(hdc, of);
5580         DeleteObject(hfont);
5581 
5582         HeapFree(GetProcessHeap(), 0, otm);
5583         HeapFree(GetProcessHeap(), 0, bufW);
5584         HeapFree(GetProcessHeap(), 0, bufA);
5585     }
5586     heap_free(efnd.elf);
5587     DeleteDC(hdc);
5588 }
5589 
5590 static void test_fullname2(void)
5591 {
5592     test_fullname2_helper("Arial");
5593     test_fullname2_helper("Lucida Sans");
5594     test_fullname2_helper("Tahoma");
5595     test_fullname2_helper("Webdings");
5596     test_fullname2_helper("Wingdings");
5597     test_fullname2_helper("SimSun");
5598     test_fullname2_helper("NSimSun");
5599     test_fullname2_helper("MingLiu");
5600     test_fullname2_helper("PMingLiu");
5601     test_fullname2_helper("WenQuanYi Micro Hei");
5602     test_fullname2_helper("MS UI Gothic");
5603     test_fullname2_helper("Ume UI Gothic");
5604     test_fullname2_helper("MS Gothic");
5605     test_fullname2_helper("Ume Gothic");
5606     test_fullname2_helper("MS PGothic");
5607     test_fullname2_helper("Ume P Gothic");
5608     test_fullname2_helper("Gulim");
5609     test_fullname2_helper("Batang");
5610     test_fullname2_helper("UnBatang");
5611     test_fullname2_helper("UnDotum");
5612     test_fullname2_helper("@SimSun");
5613     test_fullname2_helper("@NSimSun");
5614     test_fullname2_helper("@MingLiu");
5615     test_fullname2_helper("@PMingLiu");
5616     test_fullname2_helper("@WenQuanYi Micro Hei");
5617     test_fullname2_helper("@MS UI Gothic");
5618     test_fullname2_helper("@Ume UI Gothic");
5619     test_fullname2_helper("@MS Gothic");
5620     test_fullname2_helper("@Ume Gothic");
5621     test_fullname2_helper("@MS PGothic");
5622     test_fullname2_helper("@Ume P Gothic");
5623     test_fullname2_helper("@Gulim");
5624     test_fullname2_helper("@Batang");
5625     test_fullname2_helper("@UnBatang");
5626     test_fullname2_helper("@UnDotum");
5627 
5628 }
5629 
5630 static void test_GetGlyphOutline_empty_contour(void)
5631 {
5632     HDC hdc;
5633     LOGFONTA lf;
5634     HFONT hfont, hfont_prev;
5635     TTPOLYGONHEADER *header;
5636     GLYPHMETRICS gm;
5637     char buf[1024];
5638     DWORD ret;
5639 
5640     memset(&lf, 0, sizeof(lf));
5641     lf.lfHeight = 72;
5642     lstrcpyA(lf.lfFaceName, "wine_test");
5643 
5644     hfont = CreateFontIndirectA(&lf);
5645     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
5646 
5647     hdc = GetDC(NULL);
5648 
5649     hfont_prev = SelectObject(hdc, hfont);
5650     ok(hfont_prev != NULL, "SelectObject failed\n");
5651 
5652     ret = GetGlyphOutlineW(hdc, 0xa8, GGO_NATIVE, &gm, 0, NULL, &mat);
5653     ok(ret == 228, "GetGlyphOutline returned %d, expected 228\n", ret);
5654 
5655     header = (TTPOLYGONHEADER*)buf;
5656     ret = GetGlyphOutlineW(hdc, 0xa8, GGO_NATIVE, &gm, sizeof(buf), buf, &mat);
5657     ok(ret == 228, "GetGlyphOutline returned %d, expected 228\n", ret);
5658     ok(header->cb == 36, "header->cb = %d, expected 36\n", header->cb);
5659     ok(header->dwType == TT_POLYGON_TYPE, "header->dwType = %d, expected TT_POLYGON_TYPE\n", header->dwType);
5660     header = (TTPOLYGONHEADER*)((char*)header+header->cb);
5661     ok(header->cb == 96, "header->cb = %d, expected 96\n", header->cb);
5662     header = (TTPOLYGONHEADER*)((char*)header+header->cb);
5663     ok(header->cb == 96, "header->cb = %d, expected 96\n", header->cb);
5664 
5665     SelectObject(hdc, hfont_prev);
5666     DeleteObject(hfont);
5667     ReleaseDC(NULL, hdc);
5668 }
5669 
5670 static void test_GetGlyphOutline_metric_clipping(void)
5671 {
5672     HDC hdc;
5673     LOGFONTA lf;
5674     HFONT hfont, hfont_prev;
5675     GLYPHMETRICS gm;
5676     TEXTMETRICA tm;
5677     TEXTMETRICW tmW;
5678     DWORD ret;
5679 
5680     memset(&lf, 0, sizeof(lf));
5681     lf.lfHeight = 72;
5682     lstrcpyA(lf.lfFaceName, "wine_test");
5683 
5684     SetLastError(0xdeadbeef);
5685     hfont = CreateFontIndirectA(&lf);
5686     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
5687 
5688     hdc = GetDC(NULL);
5689 
5690     hfont_prev = SelectObject(hdc, hfont);
5691     ok(hfont_prev != NULL, "SelectObject failed\n");
5692 
5693     SetLastError(0xdeadbeef);
5694     ret = GetTextMetricsA(hdc, &tm);
5695     ok(ret, "GetTextMetrics error %u\n", GetLastError());
5696 
5697     GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
5698     ok(gm.gmptGlyphOrigin.y <= tm.tmAscent,
5699         "Glyph top(%d) exceeds ascent(%d)\n",
5700         gm.gmptGlyphOrigin.y, tm.tmAscent);
5701     GetGlyphOutlineA(hdc, 'D', GGO_METRICS, &gm, 0, NULL, &mat);
5702     ok(gm.gmptGlyphOrigin.y - gm.gmBlackBoxY >= -tm.tmDescent,
5703         "Glyph bottom(%d) exceeds descent(%d)\n",
5704         gm.gmptGlyphOrigin.y - gm.gmBlackBoxY, -tm.tmDescent);
5705 
5706     /* Test tmLastChar - wine_test has code points fffb-fffe mapped to glyph 0 */
5707     GetTextMetricsW(hdc, &tmW);
5708 todo_wine
5709     ok( tmW.tmLastChar == 0xfffe, "got %04x\n", tmW.tmLastChar);
5710 
5711     SelectObject(hdc, hfont_prev);
5712     DeleteObject(hfont);
5713     ReleaseDC(NULL, hdc);
5714 }
5715 
5716 static void test_fstype_fixup(void)
5717 {
5718     HDC hdc;
5719     LOGFONTA lf;
5720     HFONT hfont, hfont_prev;
5721     DWORD ret;
5722     OUTLINETEXTMETRICA *otm;
5723     DWORD otm_size;
5724 
5725     memset(&lf, 0, sizeof(lf));
5726     lf.lfHeight = 72;
5727     lstrcpyA(lf.lfFaceName, "wine_test");
5728 
5729     SetLastError(0xdeadbeef);
5730     hfont = CreateFontIndirectA(&lf);
5731     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
5732 
5733     hdc = GetDC(NULL);
5734 
5735     hfont_prev = SelectObject(hdc, hfont);
5736     ok(hfont_prev != NULL, "SelectObject failed\n");
5737 
5738     otm_size = GetOutlineTextMetricsA(hdc, 0, NULL);
5739     otm = HeapAlloc(GetProcessHeap(), 0, otm_size);
5740     otm->otmSize = sizeof(*otm);
5741     ret = GetOutlineTextMetricsA(hdc, otm->otmSize, otm);
5742     ok(ret == otm->otmSize, "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
5743 
5744     /* Test font has fsType set to 0x7fff, test that reserved bits are filtered out,
5745        valid bits are 1, 2, 3, 8, 9. */
5746     ok((otm->otmfsType & ~0x30e) == 0, "fsType %#x\n", otm->otmfsType);
5747 
5748     HeapFree(GetProcessHeap(), 0, otm);
5749 
5750     SelectObject(hdc, hfont_prev);
5751     DeleteObject(hfont);
5752     ReleaseDC(NULL, hdc);
5753 }
5754 
5755 static void test_CreateScalableFontResource(void)
5756 {
5757     char ttf_name[MAX_PATH];
5758     char tmp_path[MAX_PATH];
5759     char fot_name[MAX_PATH];
5760     char *file_part;
5761     DWORD ret;
5762     int i;
5763 
5764     if (!pAddFontResourceExA || !pRemoveFontResourceExA)
5765     {
5766         win_skip("AddFontResourceExA is not available on this platform\n");
5767         return;
5768     }
5769 
5770     if (!write_ttf_file("wine_test.ttf", ttf_name))
5771     {
5772         skip("Failed to create ttf file for testing\n");
5773         return;
5774     }
5775 
5776     trace("created %s\n", ttf_name);
5777 
5778     ret = is_truetype_font_installed("wine_test");
5779     ok(!ret, "font wine_test should not be enumerated\n");
5780 
5781     ret = GetTempPathA(MAX_PATH, tmp_path);
5782     ok(ret, "GetTempPath() error %d\n", GetLastError());
5783     ret = GetTempFileNameA(tmp_path, "fot", 0, fot_name);
5784     ok(ret, "GetTempFileName() error %d\n", GetLastError());
5785 
5786     ret = GetFileAttributesA(fot_name);
5787     ok(ret != INVALID_FILE_ATTRIBUTES, "file %s does not exist\n", fot_name);
5788 
5789     SetLastError(0xdeadbeef);
5790     ret = CreateScalableFontResourceA(0, fot_name, ttf_name, NULL);
5791     ok(!ret, "CreateScalableFontResource() should fail\n");
5792     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
5793 
5794     SetLastError(0xdeadbeef);
5795     ret = CreateScalableFontResourceA(0, fot_name, ttf_name, "");
5796     ok(!ret, "CreateScalableFontResource() should fail\n");
5797     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
5798 
5799     file_part = strrchr(ttf_name, '\\');
5800     SetLastError(0xdeadbeef);
5801     ret = CreateScalableFontResourceA(0, fot_name, file_part, tmp_path);
5802     ok(!ret, "CreateScalableFontResource() should fail\n");
5803     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
5804 
5805     SetLastError(0xdeadbeef);
5806     ret = CreateScalableFontResourceA(0, fot_name, "random file name", tmp_path);
5807     ok(!ret, "CreateScalableFontResource() should fail\n");
5808     ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
5809 
5810     SetLastError(0xdeadbeef);
5811     ret = CreateScalableFontResourceA(0, fot_name, NULL, ttf_name);
5812     ok(!ret, "CreateScalableFontResource() should fail\n");
5813     ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
5814 
5815     ret = DeleteFileA(fot_name);
5816     ok(ret, "DeleteFile() error %d\n", GetLastError());
5817 
5818     ret = pRemoveFontResourceExA(fot_name, 0, 0);
5819     ok(!ret, "RemoveFontResourceEx() should fail\n");
5820 
5821     /* test public font resource */
5822     SetLastError(0xdeadbeef);
5823     ret = CreateScalableFontResourceA(0, fot_name, ttf_name, NULL);
5824     ok(ret, "CreateScalableFontResource() error %d\n", GetLastError());
5825 
5826     ret = is_truetype_font_installed("wine_test");
5827     ok(!ret, "font wine_test should not be enumerated\n");
5828 
5829     SetLastError(0xdeadbeef);
5830     ret = pAddFontResourceExA(fot_name, 0, 0);
5831     ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
5832 
5833     ret = is_truetype_font_installed("wine_test");
5834     ok(ret, "font wine_test should be enumerated\n");
5835 
5836     test_GetGlyphOutline_empty_contour();
5837     test_GetGlyphOutline_metric_clipping();
5838     test_fstype_fixup();
5839 
5840     ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
5841     ok(!ret, "RemoveFontResourceEx() with not matching flags should fail\n");
5842 
5843     SetLastError(0xdeadbeef);
5844     ret = pRemoveFontResourceExA(fot_name, 0, 0);
5845     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
5846 
5847     ret = is_truetype_font_installed("wine_test");
5848     ok(!ret, "font wine_test should not be enumerated\n");
5849 
5850     ret = pRemoveFontResourceExA(fot_name, 0, 0);
5851     ok(!ret, "RemoveFontResourceEx() should fail\n");
5852 
5853     /* test refcounting */
5854     for (i = 0; i < 5; i++)
5855     {
5856         SetLastError(0xdeadbeef);
5857         ret = pAddFontResourceExA(fot_name, 0, 0);
5858         ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
5859     }
5860     for (i = 0; i < 5; i++)
5861     {
5862         SetLastError(0xdeadbeef);
5863         ret = pRemoveFontResourceExA(fot_name, 0, 0);
5864         ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
5865     }
5866     ret = pRemoveFontResourceExA(fot_name, 0, 0);
5867     ok(!ret, "RemoveFontResourceEx() should fail\n");
5868 
5869     DeleteFileA(fot_name);
5870 
5871     /* test hidden font resource */
5872     SetLastError(0xdeadbeef);
5873     ret = CreateScalableFontResourceA(1, fot_name, ttf_name, NULL);
5874     ok(ret, "CreateScalableFontResource() error %d\n", GetLastError());
5875 
5876     ret = is_truetype_font_installed("wine_test");
5877     ok(!ret, "font wine_test should not be enumerated\n");
5878 
5879     SetLastError(0xdeadbeef);
5880     ret = pAddFontResourceExA(fot_name, 0, 0);
5881     ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
5882 
5883     ret = is_truetype_font_installed("wine_test");
5884     todo_wine
5885     ok(!ret, "font wine_test should not be enumerated\n");
5886 
5887     /* XP allows removing a private font added with 0 flags */
5888     SetLastError(0xdeadbeef);
5889     ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
5890     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
5891 
5892     ret = is_truetype_font_installed("wine_test");
5893     ok(!ret, "font wine_test should not be enumerated\n");
5894 
5895     ret = pRemoveFontResourceExA(fot_name, 0, 0);
5896     ok(!ret, "RemoveFontResourceEx() should fail\n");
5897 
5898     DeleteFileA(fot_name);
5899     DeleteFileA(ttf_name);
5900 }
5901 
5902 static void check_vertical_font(const char *name, BOOL *installed, BOOL *selected, GLYPHMETRICS *gm, WORD *gi)
5903 {
5904     LOGFONTA lf;
5905     HFONT hfont, hfont_prev;
5906     HDC hdc;
5907     char facename[100];
5908     DWORD ret;
5909     static const WCHAR str[] = { 0x2025 };
5910 
5911     *installed = is_truetype_font_installed(name);
5912 
5913     lf.lfHeight = -18;
5914     lf.lfWidth = 0;
5915     lf.lfEscapement = 0;
5916     lf.lfOrientation = 0;
5917     lf.lfWeight = FW_DONTCARE;
5918     lf.lfItalic = 0;
5919     lf.lfUnderline = 0;
5920     lf.lfStrikeOut = 0;
5921     lf.lfCharSet = DEFAULT_CHARSET;
5922     lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
5923     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
5924     lf.lfQuality = DEFAULT_QUALITY;
5925     lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
5926     strcpy(lf.lfFaceName, name);
5927 
5928     hfont = CreateFontIndirectA(&lf);
5929     ok(hfont != NULL, "CreateFontIndirectA failed\n");
5930 
5931     hdc = GetDC(NULL);
5932 
5933     hfont_prev = SelectObject(hdc, hfont);
5934     ok(hfont_prev != NULL, "SelectObject failed\n");
5935 
5936     ret = GetTextFaceA(hdc, sizeof facename, facename);
5937     ok(ret, "GetTextFaceA failed\n");
5938     *selected = !strcmp(facename, name);
5939 
5940     ret = GetGlyphOutlineW(hdc, 0x2025, GGO_METRICS, gm, 0, NULL, &mat);
5941     ok(ret != GDI_ERROR, "GetGlyphOutlineW failed\n");
5942     if (!*selected)
5943         memset(gm, 0, sizeof *gm);
5944 
5945     ret = pGetGlyphIndicesW(hdc, str, 1, gi, 0);
5946     ok(ret != GDI_ERROR, "GetGlyphIndicesW failed\n");
5947 
5948     SelectObject(hdc, hfont_prev);
5949     DeleteObject(hfont);
5950     ReleaseDC(NULL, hdc);
5951 }
5952 
5953 static void check_vertical_metrics(const char *face)
5954 {
5955     LOGFONTA lf;
5956     HFONT hfont, hfont_prev;
5957     HDC hdc;
5958     DWORD ret;
5959     GLYPHMETRICS rgm, vgm;
5960     const UINT code = 0x5EAD, height = 1000;
5961     WORD idx;
5962     ABC abc, vabc;
5963     OUTLINETEXTMETRICA otm;
5964     USHORT numOfLongVerMetrics;
5965 
5966     hdc = GetDC(NULL);
5967 
5968     memset(&lf, 0, sizeof(lf));
5969     strcpy(lf.lfFaceName, face);
5970     lf.lfHeight = -height;
5971     lf.lfCharSet = DEFAULT_CHARSET;
5972     lf.lfEscapement = lf.lfOrientation = 900;
5973     hfont = CreateFontIndirectA(&lf);
5974     hfont_prev = SelectObject(hdc, hfont);
5975     ret = GetGlyphOutlineW(hdc, code, GGO_METRICS, &rgm, 0, NULL, &mat);
5976     ok(ret != GDI_ERROR, "GetGlyphOutlineW failed\n");
5977     ret = GetCharABCWidthsW(hdc, code, code, &abc);
5978     ok(ret, "GetCharABCWidthsW failed\n");
5979     DeleteObject(SelectObject(hdc, hfont_prev));
5980 
5981     memset(&lf, 0, sizeof(lf));
5982     strcpy(lf.lfFaceName, "@");
5983     strcat(lf.lfFaceName, face);
5984     lf.lfHeight = -height;
5985     lf.lfCharSet = DEFAULT_CHARSET;
5986     hfont = CreateFontIndirectA(&lf);
5987     hfont_prev = SelectObject(hdc, hfont);
5988     ret = GetGlyphOutlineW(hdc, code, GGO_METRICS, &vgm, 0, NULL, &mat);
5989     ok(ret != GDI_ERROR, "GetGlyphOutlineW failed\n");
5990     ret = GetCharABCWidthsW(hdc, code, code, &vabc);
5991     ok(ret, "GetCharABCWidthsW failed\n");
5992     ok(vabc.abcA == vgm.gmptGlyphOrigin.x, "expected %d, got %d\n",
5993        vabc.abcA, vgm.gmptGlyphOrigin.x);
5994     ok(vabc.abcB == vgm.gmBlackBoxX, "expected %d, got %d\n",
5995        vabc.abcB, vgm.gmBlackBoxX);
5996     ok(vabc.abcA + vabc.abcB + vabc.abcC == vgm.gmCellIncX,
5997        "expected %d, got %d\n",
5998        vabc.abcA + vabc.abcB + vabc.abcC, vgm.gmCellIncX);
5999 
6000     memset(&otm, 0, sizeof(otm));
6001     otm.otmSize = sizeof(otm);
6002     ret = GetOutlineTextMetricsA(hdc, sizeof(otm), &otm);
6003     ok(ret != 0, "GetOutlineTextMetricsA failed\n");
6004 
6005     if (GetFontData(hdc, MS_MAKE_TAG('v','h','e','a'), sizeof(SHORT) * 17,
6006                     &numOfLongVerMetrics, sizeof(numOfLongVerMetrics)) != GDI_ERROR) {
6007         int offset;
6008         SHORT topSideBearing;
6009 
6010         if (!pGetGlyphIndicesW) {
6011             win_skip("GetGlyphIndices is not available on this platform\n");
6012         }
6013         else {
6014             ret = pGetGlyphIndicesW(hdc, (LPCWSTR)&code, 1, &idx, 0);
6015             ok(ret != 0, "GetGlyphIndicesW failed\n");
6016             numOfLongVerMetrics = GET_BE_WORD(numOfLongVerMetrics);
6017             if (numOfLongVerMetrics > idx)
6018                 offset = idx * 2 + 1;
6019             else
6020                 offset = numOfLongVerMetrics * 2 + (idx - numOfLongVerMetrics);
6021             ret = GetFontData(hdc, MS_MAKE_TAG('v','m','t','x'), offset * sizeof(SHORT),
6022                               &topSideBearing, sizeof(SHORT));
6023             ok(ret != GDI_ERROR, "GetFontData(vmtx) failed\n");
6024             topSideBearing = GET_BE_WORD(topSideBearing);
6025             ok(match_off_by_1(vgm.gmptGlyphOrigin.x,
6026                               MulDiv(topSideBearing, height, otm.otmEMSquare), FALSE),
6027                "expected %d, got %d\n",
6028                MulDiv(topSideBearing, height, otm.otmEMSquare), vgm.gmptGlyphOrigin.x);
6029         }
6030     }
6031     else
6032     {
6033         ok(vgm.gmptGlyphOrigin.x == rgm.gmptGlyphOrigin.x + vgm.gmCellIncX + otm.otmDescent,
6034            "got %d, expected rgm.origin.x(%d) + vgm.cellIncX(%d) + descent(%d)\n",
6035            vgm.gmptGlyphOrigin.x, rgm.gmptGlyphOrigin.x, vgm.gmCellIncX, otm.otmDescent);
6036     }
6037 
6038     ok(vgm.gmptGlyphOrigin.y == abc.abcA + abc.abcB + otm.otmDescent ||
6039        broken(vgm.gmptGlyphOrigin.y == abc.abcA + abc.abcB - otm.otmTextMetrics.tmDescent) /* win2k */,
6040        "got %d, expected abcA(%d) + abcB(%u) + descent(%d)\n",
6041        (INT)vgm.gmptGlyphOrigin.y, abc.abcA, abc.abcB, otm.otmDescent);
6042 
6043     DeleteObject(SelectObject(hdc, hfont_prev));
6044     ReleaseDC(NULL, hdc);
6045 }
6046 
6047 static void test_vertical_font(void)
6048 {
6049     char ttf_name[MAX_PATH];
6050     int num, i;
6051     BOOL ret, installed, selected;
6052     GLYPHMETRICS gm;
6053     WORD hgi, vgi;
6054     const char* face_list[] = {
6055         "@WineTestVertical", /* has vmtx table */
6056         "@Ume Gothic",       /* doesn't have vmtx table */
6057         "@MS UI Gothic",     /* has vmtx table, available on native */
6058     };
6059 
6060     if (!pAddFontResourceExA || !pRemoveFontResourceExA || !pGetGlyphIndicesW)
6061     {
6062         win_skip("AddFontResourceExA or GetGlyphIndicesW is not available on this platform\n");
6063         return;
6064     }
6065 
6066     if (!write_ttf_file("vertical.ttf", ttf_name))
6067     {
6068         skip("Failed to create ttf file for testing\n");
6069         return;
6070     }
6071 
6072     num = pAddFontResourceExA(ttf_name, FR_PRIVATE, 0);
6073     ok(num == 2, "AddFontResourceExA should add 2 fonts from vertical.ttf\n");
6074 
6075     check_vertical_font("WineTestVertical", &installed, &selected, &gm, &hgi);
6076     ok(installed, "WineTestVertical is not installed\n");
6077     ok(selected, "WineTestVertical is not selected\n");
6078     ok(gm.gmBlackBoxX > gm.gmBlackBoxY,
6079        "gmBlackBoxX(%u) should be greater than gmBlackBoxY(%u) if horizontal\n",
6080        gm.gmBlackBoxX, gm.gmBlackBoxY);
6081 
6082     check_vertical_font("@WineTestVertical", &installed, &selected, &gm, &vgi);
6083     ok(installed, "@WineTestVertical is not installed\n");
6084     ok(selected, "@WineTestVertical is not selected\n");
6085     ok(gm.gmBlackBoxX > gm.gmBlackBoxY,
6086        "gmBlackBoxX(%u) should be less than gmBlackBoxY(%u) if vertical\n",
6087        gm.gmBlackBoxX, gm.gmBlackBoxY);
6088 
6089     ok(hgi != vgi, "same glyph h:%u v:%u\n", hgi, vgi);
6090 
6091     for (i = 0; i < sizeof(face_list)/sizeof(face_list[0]); i++) {
6092         const char* face = face_list[i];
6093         if (!is_truetype_font_installed(face)) {
6094             skip("%s is not installed\n", face);
6095             continue;
6096         }
6097         trace("Testing %s...\n", face);
6098         check_vertical_metrics(&face[1]);
6099     }
6100 
6101     ret = pRemoveFontResourceExA(ttf_name, FR_PRIVATE, 0);
6102     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
6103 
6104     DeleteFileA(ttf_name);
6105 }
6106 
6107 static INT CALLBACK has_vertical_font_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm,
6108                                            DWORD type, LPARAM lParam)
6109 {
6110     if (lf->lfFaceName[0] == '@') {
6111         return 0;
6112     }
6113     return 1;
6114 }
6115 
6116 static void test_east_asian_font_selection(void)
6117 {
6118     HDC hdc;
6119     UINT charset[] = { SHIFTJIS_CHARSET, HANGEUL_CHARSET, JOHAB_CHARSET,
6120                        GB2312_CHARSET, CHINESEBIG5_CHARSET };
6121     size_t i;
6122 
6123     hdc = GetDC(NULL);
6124 
6125     for (i = 0; i < sizeof(charset)/sizeof(charset[0]); i++)
6126     {
6127         LOGFONTA lf;
6128         HFONT hfont;
6129         char face_name[LF_FACESIZE];
6130         int ret;
6131 
6132         memset(&lf, 0, sizeof lf);
6133         lf.lfFaceName[0] = '\0';
6134         lf.lfCharSet = charset[i];
6135 
6136         if (EnumFontFamiliesExA(hdc, &lf, has_vertical_font_proc, 0, 0))
6137         {
6138             skip("Vertical font for charset %u is not installed\n", charset[i]);
6139             continue;
6140         }
6141 
6142         hfont = CreateFontIndirectA(&lf);
6143         hfont = SelectObject(hdc, hfont);
6144         memset(face_name, 0, sizeof face_name);
6145         ret = GetTextFaceA(hdc, sizeof face_name, face_name);
6146         ok(ret && face_name[0] != '@',
6147            "expected non-vertical face for charset %u, got %s\n", charset[i], face_name);
6148         DeleteObject(SelectObject(hdc, hfont));
6149 
6150         memset(&lf, 0, sizeof lf);
6151         strcpy(lf.lfFaceName, "@");
6152         lf.lfCharSet = charset[i];
6153         hfont = CreateFontIndirectA(&lf);
6154         hfont = SelectObject(hdc, hfont);
6155         memset(face_name, 0, sizeof face_name);
6156         ret = GetTextFaceA(hdc, sizeof face_name, face_name);
6157         ok(ret && face_name[0] == '@',
6158            "expected vertical face for charset %u, got %s\n", charset[i], face_name);
6159         DeleteObject(SelectObject(hdc, hfont));
6160     }
6161     ReleaseDC(NULL, hdc);
6162 }
6163 
6164 static int get_font_dpi(const LOGFONTA *lf, int *height)
6165 {
6166     HDC hdc = CreateCompatibleDC(0);
6167     HFONT hfont;
6168     TEXTMETRICA tm;
6169     int ret;
6170 
6171     hfont = CreateFontIndirectA(lf);
6172     ok(hfont != 0, "CreateFontIndirect failed\n");
6173 
6174     SelectObject(hdc, hfont);
6175     ret = GetTextMetricsA(hdc, &tm);
6176     ok(ret, "GetTextMetrics failed\n");
6177     ret = tm.tmDigitizedAspectX;
6178     if (height) *height = tm.tmHeight;
6179 
6180     DeleteDC(hdc);
6181     DeleteObject(hfont);
6182 
6183     return ret;
6184 }
6185 
6186 static void test_stock_fonts(void)
6187 {
6188     static const int font[] =
6189     {
6190         ANSI_FIXED_FONT, ANSI_VAR_FONT, SYSTEM_FONT, DEVICE_DEFAULT_FONT, DEFAULT_GUI_FONT
6191         /* SYSTEM_FIXED_FONT, OEM_FIXED_FONT */
6192     };
6193     static const struct test_data
6194     {
6195         int charset, weight, height, height_pixels, dpi;
6196         const char face_name[LF_FACESIZE];
6197         WORD lang_id;
6198     } td[][12] =
6199     {
6200         { /* ANSI_FIXED_FONT */
6201             { ANSI_CHARSET, FW_NORMAL, 12, 12, 96, "Courier", LANG_ARABIC },
6202             { ANSI_CHARSET, FW_NORMAL, 12, 12, 96, "Courier", LANG_HEBREW},
6203             { DEFAULT_CHARSET, FW_NORMAL, 12, 13, 96, "Courier" },
6204             { DEFAULT_CHARSET, FW_NORMAL, 12, 13, 120, "Courier" },
6205             { 0 }
6206         },
6207         { /* ANSI_VAR_FONT */
6208             { DEFAULT_CHARSET, FW_NORMAL, 12, 13, 96, "MS Sans Serif" },
6209             { DEFAULT_CHARSET, FW_NORMAL, 12, 13, 120, "MS Sans Serif" },
6210             { 0 }
6211         },
6212         { /* SYSTEM_FONT */
6213             { SHIFTJIS_CHARSET, FW_NORMAL, 18, 18, 96, "System" },
6214             { SHIFTJIS_CHARSET, FW_NORMAL, 22, 22, 120, "System" },
6215             { HANGEUL_CHARSET, FW_NORMAL, 16, 16, 96, "System" },
6216             { HANGEUL_CHARSET, FW_NORMAL, 20, 20, 120, "System" },
6217             { DEFAULT_CHARSET, FW_BOLD, 16, 16, 96, "System" },
6218             { DEFAULT_CHARSET, FW_BOLD, 20, 20, 120, "System" },
6219             { 0 }
6220         },
6221         { /* DEVICE_DEFAULT_FONT */
6222             { SHIFTJIS_CHARSET, FW_NORMAL, 18, 18, 96, "System" },
6223             { SHIFTJIS_CHARSET, FW_NORMAL, 22, 22, 120, "System" },
6224             { HANGEUL_CHARSET, FW_NORMAL, 16, 16, 96, "System" },
6225             { HANGEUL_CHARSET, FW_NORMAL, 20, 20, 120, "System" },
6226             { DEFAULT_CHARSET, FW_BOLD, 16, 16, 96, "System" },
6227             { DEFAULT_CHARSET, FW_BOLD, 20, 20, 120, "System" },
6228             { 0 }
6229         },
6230         { /* DEFAULT_GUI_FONT */
6231             { SHIFTJIS_CHARSET, FW_NORMAL, -11, 13, 96, "MS Shell Dlg" },
6232             { SHIFTJIS_CHARSET, FW_NORMAL, -12, 15, 96, "?MS UI Gothic" },
6233             { SHIFTJIS_CHARSET, FW_NORMAL, -15, 18, 120, "?MS UI Gothic" },
6234             { HANGEUL_CHARSET, FW_NORMAL, -12, 15, 96, "?Gulim" },
6235             { HANGEUL_CHARSET, FW_NORMAL, -15, 18, 120, "?Gulim" },
6236             { GB2312_CHARSET, FW_NORMAL, -12, 15, 96, "?SimHei" },
6237             { GB2312_CHARSET, FW_NORMAL, -15, 18, 120, "?SimHei" },
6238             { CHINESEBIG5_CHARSET, FW_NORMAL, -12, 15, 96, "?MingLiU" },
6239             { CHINESEBIG5_CHARSET, FW_NORMAL, -15, 18, 120, "?MingLiU" },
6240             { DEFAULT_CHARSET, FW_NORMAL, -11, 13, 96, "MS Shell Dlg" },
6241             { DEFAULT_CHARSET, FW_NORMAL, -13, 16, 120, "MS Shell Dlg" },
6242             { 0 }
6243         }
6244     };
6245     int i, j;
6246 
6247     for (i = 0; i < sizeof(font)/sizeof(font[0]); i++)
6248     {
6249         HFONT hfont;
6250         LOGFONTA lf;
6251         int ret, height;
6252 
6253         hfont = GetStockObject(font[i]);
6254         ok(hfont != 0, "%d: GetStockObject(%d) failed\n", i, font[i]);
6255 
6256         ret = GetObjectA(hfont, sizeof(lf), &lf);
6257         if (ret != sizeof(lf))
6258         {
6259             /* NT4 */
6260             win_skip("%d: GetObject returned %d instead of sizeof(LOGFONT)\n", i, ret);
6261             continue;
6262         }
6263 
6264         for (j = 0; td[i][j].face_name[0] != 0; j++)
6265         {
6266             if ((lf.lfCharSet != td[i][j].charset && td[i][j].charset != DEFAULT_CHARSET) ||
6267                 (system_lang_id != td[i][j].lang_id && td[i][j].lang_id != LANG_NEUTRAL) ||
6268                 (td[i][j].face_name[0] != '?' && strcmp(lf.lfFaceName, td[i][j].face_name)))
6269             {
6270                 continue;
6271             }
6272 
6273             ret = get_font_dpi(&lf, &height);
6274             if (ret != td[i][j].dpi)
6275             {
6276                 trace("%d(%d): font %s %d dpi doesn't match test data %d\n",
6277                       i, j, lf.lfFaceName, ret, td[i][j].dpi);
6278                 continue;
6279             }
6280 
6281             /* FIXME: Remove once Wine is fixed */
6282             todo_wine_if (td[i][j].dpi != 96 &&
6283                 /* MS Sans Serif for 120 dpi and higher should include 12 pixel bitmap set */
6284                 ((!strcmp(td[i][j].face_name, "MS Sans Serif") && td[i][j].height == 12) ||
6285                 /* System for 120 dpi and higher should include 20 pixel bitmap set */
6286                 (!strcmp(td[i][j].face_name, "System") && td[i][j].height > 16)))
6287             ok(height == td[i][j].height_pixels, "%d(%d): expected height %d, got %d\n", i, j, td[i][j].height_pixels, height);
6288 
6289             ok(td[i][j].weight == lf.lfWeight, "%d(%d): expected lfWeight %d, got %d\n", i, j, td[i][j].weight, lf.lfWeight);
6290             ok(td[i][j].height == lf.lfHeight, "%d(%d): expected lfHeight %d, got %d\n", i, j, td[i][j].height, lf.lfHeight);
6291             if (td[i][j].face_name[0] == '?')
6292             {
6293                 /* Wine doesn't have this font, skip this case for now.
6294                    Actually, the face name is localized on Windows and varies
6295                    dpending on Windows versions (e.g. Japanese NT4 vs win2k). */
6296                 trace("%d(%d): default gui font is %s\n", i, j, lf.lfFaceName);
6297             }
6298             else
6299             {
6300                 ok(!strcmp(td[i][j].face_name, lf.lfFaceName), "%d(%d): expected lfFaceName %s, got %s\n", i, j, td[i][j].face_name, lf.lfFaceName);
6301             }
6302             break;
6303         }
6304     }
6305 }
6306 
6307 static void test_max_height(void)
6308 {
6309     HDC hdc;
6310     LOGFONTA lf;
6311     HFONT hfont, hfont_old;
6312     TEXTMETRICA tm1, tm;
6313     BOOL r;
6314     LONG invalid_height[] = { -65536, -123456, 123456 };
6315     size_t i;
6316 
6317     memset(&tm1, 0, sizeof(tm1));
6318     memset(&lf, 0, sizeof(lf));
6319     strcpy(lf.lfFaceName, "Tahoma");
6320     lf.lfHeight = -1;
6321 
6322     hdc = GetDC(NULL);
6323 
6324     /* get 1 ppem value */
6325     hfont = CreateFontIndirectA(&lf);
6326     hfont_old = SelectObject(hdc, hfont);
6327     r = GetTextMetricsA(hdc, &tm1);
6328     ok(r, "GetTextMetrics failed\n");
6329     ok(tm1.tmHeight > 0, "expected a positive value, got %d\n", tm1.tmHeight);
6330     ok(tm1.tmAveCharWidth > 0, "expected a positive value, got %d\n", tm1.tmHeight);
6331     DeleteObject(SelectObject(hdc, hfont_old));
6332 
6333     /* test the largest value */
6334     lf.lfHeight = -((1 << 16) - 1);
6335     hfont = CreateFontIndirectA(&lf);
6336     hfont_old = SelectObject(hdc, hfont);
6337     memset(&tm, 0, sizeof(tm));
6338     r = GetTextMetricsA(hdc, &tm);
6339     ok(r, "GetTextMetrics failed\n");
6340     ok(tm.tmHeight > tm1.tmHeight,
6341        "expected greater than 1 ppem value (%d), got %d\n", tm1.tmHeight, tm.tmHeight);
6342     ok(tm.tmAveCharWidth > tm1.tmAveCharWidth,
6343        "expected greater than 1 ppem value (%d), got %d\n", tm1.tmAveCharWidth, tm.tmAveCharWidth);
6344     DeleteObject(SelectObject(hdc, hfont_old));
6345 
6346     /* test an invalid value */
6347     for (i = 0; i < sizeof(invalid_height)/sizeof(invalid_height[0]); i++) {
6348         lf.lfHeight = invalid_height[i];
6349         hfont = CreateFontIndirectA(&lf);
6350         hfont_old = SelectObject(hdc, hfont);
6351         memset(&tm, 0, sizeof(tm));
6352         r = GetTextMetricsA(hdc, &tm);
6353         ok(r, "GetTextMetrics failed\n");
6354         ok(tm.tmHeight == tm1.tmHeight,
6355            "expected 1 ppem value (%d), got %d\n", tm1.tmHeight, tm.tmHeight);
6356         ok(tm.tmAveCharWidth == tm1.tmAveCharWidth,
6357            "expected 1 ppem value (%d), got %d\n", tm1.tmAveCharWidth, tm.tmAveCharWidth);
6358         DeleteObject(SelectObject(hdc, hfont_old));
6359     }
6360 
6361     ReleaseDC(NULL, hdc);
6362     return;
6363 }
6364 
6365 static void test_vertical_order(void)
6366 {
6367     struct enum_font_data efd;
6368     LOGFONTA lf;
6369     HDC hdc;
6370     int i, j;
6371 
6372     hdc = CreateCompatibleDC(0);
6373     ok(hdc != NULL, "CreateCompatibleDC failed\n");
6374 
6375     memset(&lf, 0, sizeof(lf));
6376     lf.lfCharSet = DEFAULT_CHARSET;
6377     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
6378     lf.lfHeight = 16;
6379     lf.lfWidth = 16;
6380     lf.lfQuality = DEFAULT_QUALITY;
6381     lf.lfItalic = FALSE;
6382     lf.lfWeight = FW_DONTCARE;
6383     memset( &efd, 0, sizeof(efd) );
6384     EnumFontFamiliesExA(hdc, &lf, enum_font_data_proc, (LPARAM)&efd, 0);
6385     for (i = 0; i < efd.total; i++)
6386     {
6387         if (efd.lf[i].lfFaceName[0] != '@') continue;
6388         for (j = 0; j < efd.total; j++)
6389         {
6390             if (!strcmp(efd.lf[i].lfFaceName + 1, efd.lf[j].lfFaceName))
6391             {
6392                 ok(i > j,"Found vertical font %s before its horizontal version\n", efd.lf[i].lfFaceName);
6393                 break;
6394             }
6395         }
6396     }
6397     heap_free( efd.lf );
6398     DeleteDC( hdc );
6399 }
6400 
6401 static void test_GetCharWidth32(void)
6402 {
6403     BOOL ret;
6404     HDC hdc;
6405     LOGFONTA lf;
6406     HFONT hfont;
6407     INT bufferA;
6408     INT bufferW;
6409     HWND hwnd;
6410 
6411     if (!pGetCharWidth32A || !pGetCharWidth32W)
6412     {
6413         win_skip("GetCharWidth32A/W not available on this platform\n");
6414         return;
6415     }
6416 
6417     memset(&lf, 0, sizeof(lf));
6418     strcpy(lf.lfFaceName, "System");
6419     lf.lfHeight = 20;
6420 
6421     hfont = CreateFontIndirectA(&lf);
6422     hdc = GetDC(0);
6423     hfont = SelectObject(hdc, hfont);
6424 
6425     ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6426     ok(ret, "GetCharWidth32W should have succeeded\n");
6427     ret = pGetCharWidth32A(hdc, 'a', 'a', &bufferA);
6428     ok(ret, "GetCharWidth32A should have succeeded\n");
6429     ok (bufferA == bufferW, "Widths should be the same\n");
6430     ok (bufferA > 0," Width should be greater than zero\n");
6431 
6432     hfont = SelectObject(hdc, hfont);
6433     DeleteObject(hfont);
6434     ReleaseDC(NULL, hdc);
6435 
6436     memset(&lf, 0, sizeof(lf));
6437     strcpy(lf.lfFaceName, "Tahoma");
6438     lf.lfHeight = 20;
6439 
6440     hfont = CreateFontIndirectA(&lf);
6441     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
6442                            0, 0, 0, NULL);
6443     hdc = GetDC(hwnd);
6444     SetMapMode( hdc, MM_ANISOTROPIC );
6445     SelectObject(hdc, hfont);
6446 
6447     ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6448     ok(ret, "GetCharWidth32W should have succeeded\n");
6449     ok (bufferW > 0," Width should be greater than zero\n");
6450     SetWindowExtEx(hdc, -1,-1,NULL);
6451     SetGraphicsMode(hdc, GM_COMPATIBLE);
6452     ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6453     ok(ret, "GetCharWidth32W should have succeeded\n");
6454     ok (bufferW > 0," Width should be greater than zero\n");
6455     SetGraphicsMode(hdc, GM_ADVANCED);
6456     ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6457     ok(ret, "GetCharWidth32W should have succeeded\n");
6458     ok (bufferW > 0," Width should be greater than zero\n");
6459     SetWindowExtEx(hdc, 1,1,NULL);
6460     SetGraphicsMode(hdc, GM_COMPATIBLE);
6461     ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6462     ok(ret, "GetCharWidth32W should have succeeded\n");
6463     ok (bufferW > 0," Width should be greater than zero\n");
6464     SetGraphicsMode(hdc, GM_ADVANCED);
6465     ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6466     ok(ret, "GetCharWidth32W should have succeeded\n");
6467     ok (bufferW > 0," Width should be greater than zero\n");
6468 
6469     ReleaseDC(hwnd, hdc);
6470     DestroyWindow(hwnd);
6471 
6472     hwnd = CreateWindowExA(WS_EX_LAYOUTRTL, "static", "", WS_POPUP, 0,0,100,100,
6473                            0, 0, 0, NULL);
6474     hdc = GetDC(hwnd);
6475     SetMapMode( hdc, MM_ANISOTROPIC );
6476     SelectObject(hdc, hfont);
6477 
6478     ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6479     ok(ret, "GetCharWidth32W should have succeeded\n");
6480     ok (bufferW > 0," Width should be greater than zero\n");
6481     SetWindowExtEx(hdc, -1,-1,NULL);
6482     SetGraphicsMode(hdc, GM_COMPATIBLE);
6483     ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6484     ok(ret, "GetCharWidth32W should have succeeded\n");
6485     ok (bufferW > 0," Width should be greater than zero\n");
6486     SetGraphicsMode(hdc, GM_ADVANCED);
6487     ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6488     ok(ret, "GetCharWidth32W should have succeeded\n");
6489     ok (bufferW > 0," Width should be greater than zero\n");
6490     SetWindowExtEx(hdc, 1,1,NULL);
6491     SetGraphicsMode(hdc, GM_COMPATIBLE);
6492     ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6493     ok(ret, "GetCharWidth32W should have succeeded\n");
6494     ok (bufferW > 0," Width should be greater than zero\n");
6495     SetGraphicsMode(hdc, GM_ADVANCED);
6496     ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
6497     ok(ret, "GetCharWidth32W should have succeeded\n");
6498     ok (bufferW > 0," Width should be greater than zero\n");
6499 
6500     ReleaseDC(hwnd, hdc);
6501     DestroyWindow(hwnd);
6502     DeleteObject(hfont);
6503 }
6504 
6505 static void test_fake_bold_font(void)
6506 {
6507     static const MAT2 x2_mat = { {0,2}, {0,0}, {0,0}, {0,2} };
6508     HDC hdc;
6509     LOGFONTA lf;
6510     BOOL ret;
6511     struct glyph_data {
6512         TEXTMETRICA tm;
6513         ABC abc;
6514         INT w;
6515         GLYPHMETRICS gm;
6516     } data[4];
6517     int i;
6518     DWORD r;
6519 
6520     if (!pGetCharWidth32A || !pGetCharABCWidthsA) {
6521         win_skip("GetCharWidth32A/GetCharABCWidthA is not available on this platform\n");
6522         return;
6523     }
6524 
6525     /* Test outline font */
6526     memset(&lf, 0, sizeof(lf));
6527     strcpy(lf.lfFaceName, "Wingdings");
6528     lf.lfCharSet = SYMBOL_CHARSET;
6529 
6530     hdc = GetDC(NULL);
6531 
6532     for (i = 0; i <= 1; i++)
6533     {
6534         HFONT hfont, hfont_old;
6535 
6536         lf.lfWeight = i ? FW_BOLD : FW_NORMAL;
6537         hfont = CreateFontIndirectA(&lf);
6538         hfont_old = SelectObject(hdc, hfont);
6539 
6540         ret = GetTextMetricsA(hdc, &data[i].tm);
6541         ok(ret, "got %d\n", ret);
6542         ret = pGetCharABCWidthsA(hdc, 0x76, 0x76, &data[i].abc);
6543         ok(ret, "got %d\n", ret);
6544         data[i].w = data[i].abc.abcA + data[i].abc.abcB + data[i].abc.abcC;
6545         r = GetGlyphOutlineA(hdc, 0x76, GGO_METRICS, &data[i].gm, 0, NULL, &x2_mat);
6546         ok(r != GDI_ERROR, "got %d\n", ret);
6547 
6548         SelectObject(hdc, hfont_old);
6549         DeleteObject(hfont);
6550     }
6551     ReleaseDC(NULL, hdc);
6552 
6553     /* compare results (outline) */
6554     ok(data[0].tm.tmHeight == data[1].tm.tmHeight,
6555        "expected %d, got %d\n", data[0].tm.tmHeight, data[1].tm.tmHeight);
6556     ok(data[0].tm.tmAscent == data[1].tm.tmAscent,
6557        "expected %d, got %d\n", data[0].tm.tmAscent, data[1].tm.tmAscent);
6558     ok(data[0].tm.tmDescent == data[1].tm.tmDescent,
6559        "expected %d, got %d\n", data[0].tm.tmDescent, data[1].tm.tmDescent);
6560     ok(data[0].tm.tmAveCharWidth + 1 == data[1].tm.tmAveCharWidth,
6561        "expected %d, got %d\n", data[0].tm.tmAveCharWidth + 1, data[1].tm.tmAveCharWidth);
6562     ok(data[0].tm.tmMaxCharWidth + 1 == data[1].tm.tmMaxCharWidth,
6563        "expected %d, got %d\n", data[0].tm.tmMaxCharWidth + 1, data[1].tm.tmMaxCharWidth);
6564     ok(data[0].tm.tmOverhang == data[1].tm.tmOverhang,
6565        "expected %d, got %d\n", data[0].tm.tmOverhang, data[1].tm.tmOverhang);
6566     ok(data[0].w + 1 == data[1].w,
6567        "expected %d, got %d\n", data[0].w + 1, data[1].w);
6568 
6569     ok(data[0].gm.gmCellIncX + 1 == data[1].gm.gmCellIncX,
6570        "expected %d, got %d\n", data[0].gm.gmCellIncX + 1, data[1].gm.gmCellIncX);
6571     ok(data[0].gm.gmCellIncY == data[1].gm.gmCellIncY,
6572        "expected %d, got %d\n", data[0].gm.gmCellIncY, data[1].gm.gmCellIncY);
6573 
6574     /* Test bitmap font */
6575     memset(&data, 0xaa, sizeof(data));
6576     memset(&lf, 0, sizeof(lf));
6577     strcpy(lf.lfFaceName, "Courier");
6578     lf.lfCharSet = ANSI_CHARSET;
6579 
6580     hdc = GetDC(NULL);
6581 
6582     for (i = 0; i < 4; i++)
6583     {
6584         HFONT hfont, hfont_old;
6585 
6586         lf.lfWeight = (i % 2) ? FW_BOLD : FW_NORMAL;
6587         lf.lfHeight = (i > 1) ? data[0].tm.tmHeight * x2_mat.eM11.value : 0;
6588         hfont = CreateFontIndirectA(&lf);
6589         hfont_old = SelectObject(hdc, hfont);
6590 
6591         ret = GetTextMetricsA(hdc, &data[i].tm);
6592         ok(ret, "got %d\n", ret);
6593         ret = pGetCharWidth32A(hdc, 0x76, 0x76, &data[i].w);
6594         ok(ret, "got %d\n", ret);
6595 
6596         SelectObject(hdc, hfont_old);
6597         DeleteObject(hfont);
6598     }
6599     ReleaseDC(NULL, hdc);
6600 
6601     /* compare results (bitmap) */
6602     for (i = 0; i < 4; i+=2)
6603     {
6604         int diff = (i > 1) ? x2_mat.eM11.value : 1;
6605         if (data[i].tm.tmPitchAndFamily & TMPF_TRUETYPE)
6606         {
6607             skip("TrueType font is selected (expected a bitmap one)\n");
6608             continue;
6609         }
6610         ok(data[i].tm.tmHeight == data[i+1].tm.tmHeight,
6611            "expected %d, got %d\n", data[i].tm.tmHeight, data[i+1].tm.tmHeight);
6612         ok(data[i].tm.tmAscent == data[i+1].tm.tmAscent,
6613            "expected %d, got %d\n", data[i].tm.tmAscent, data[i+1].tm.tmAscent);
6614         ok(data[i].tm.tmDescent == data[i+1].tm.tmDescent,
6615            "expected %d, got %d\n", data[i].tm.tmDescent, data[i+1].tm.tmDescent);
6616         ok(data[i+1].tm.tmAveCharWidth - data[i].tm.tmAveCharWidth == diff,
6617            "expected %d, got %d\n", diff, data[i+1].tm.tmAveCharWidth - data[i].tm.tmAveCharWidth);
6618         ok(data[i+1].tm.tmMaxCharWidth - data[i].tm.tmMaxCharWidth == diff,
6619            "expected %d, got %d\n", diff, data[i+1].tm.tmMaxCharWidth - data[i].tm.tmMaxCharWidth);
6620         ok(data[i].tm.tmOverhang == 0,
6621            "expected 0, got %d\n", data[i].tm.tmOverhang);
6622         ok(data[i+1].tm.tmOverhang == 1,
6623            "expected 1, got %d\n", data[i+1].tm.tmOverhang);
6624         ok(data[i].w + 1 == data[i+1].w,
6625            "expected %d, got %d\n", data[i].w + 1, data[i+1].w);
6626     }
6627 }
6628 
6629 static void test_bitmap_font_glyph_index(void)
6630 {
6631     const WCHAR text[] = {'#','!','/','b','i','n','/','s','h',0};
6632     const struct {
6633         LPCSTR face;
6634         BYTE charset;
6635     } bitmap_font_list[] = {
6636         { "Courier", ANSI_CHARSET },
6637         { "Small Fonts", ANSI_CHARSET },
6638         { "Fixedsys", DEFAULT_CHARSET },
6639         { "System", DEFAULT_CHARSET }
6640     };
6641     HDC hdc;
6642     LOGFONTA lf;
6643     HFONT hFont;
6644     CHAR facename[LF_FACESIZE];
6645     BITMAPINFO bmi;
6646     HBITMAP hBmp[2];
6647     void *pixels[2];
6648     int i, j;
6649     DWORD ret;
6650     BITMAP bmp;
6651     TEXTMETRICA tm;
6652     CHARSETINFO ci;
6653     BYTE chr = '\xA9';
6654 
6655     if (!pGetGlyphIndicesW || !pGetGlyphIndicesA) {
6656         win_skip("GetGlyphIndices is unavailable\n");
6657         return;
6658     }
6659 
6660     hdc = CreateCompatibleDC(0);
6661     ok(hdc != NULL, "CreateCompatibleDC failed\n");
6662 
6663     memset(&bmi, 0, sizeof(bmi));
6664     bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
6665     bmi.bmiHeader.biBitCount = 32;
6666     bmi.bmiHeader.biPlanes = 1;
6667     bmi.bmiHeader.biWidth = 128;
6668     bmi.bmiHeader.biHeight = 32;
6669     bmi.bmiHeader.biCompression = BI_RGB;
6670 
6671     for (i = 0; i < sizeof(bitmap_font_list)/sizeof(bitmap_font_list[0]); i++) {
6672         memset(&lf, 0, sizeof(lf));
6673         lf.lfCharSet = bitmap_font_list[i].charset;
6674         strcpy(lf.lfFaceName, bitmap_font_list[i].face);
6675         hFont = CreateFontIndirectA(&lf);
6676         ok(hFont != NULL, "Can't create font (%s:%d)\n", lf.lfFaceName, lf.lfCharSet);
6677         hFont = SelectObject(hdc, hFont);
6678         ret = GetTextMetricsA(hdc, &tm);
6679         ok(ret, "GetTextMetric failed\n");
6680         ret = GetTextFaceA(hdc, sizeof(facename), facename);
6681         ok(ret, "GetTextFace failed\n");
6682         if (tm.tmPitchAndFamily & TMPF_TRUETYPE) {
6683             skip("TrueType font (%s) was selected for \"%s\"\n", facename, bitmap_font_list[i].face);
6684             continue;
6685         }
6686         if (lstrcmpiA(facename, lf.lfFaceName) != 0) {
6687             skip("expected %s, got %s\n", lf.lfFaceName, facename);
6688             continue;
6689         }
6690 
6691         for (j = 0; j < 2; j++) {
6692             HBITMAP hBmpPrev;
6693             hBmp[j] = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pixels[j], NULL, 0);
6694             ok(hBmp[j] != NULL, "Can't create DIB\n");
6695             hBmpPrev = SelectObject(hdc, hBmp[j]);
6696             switch (j) {
6697             case 0:
6698                 ret = ExtTextOutW(hdc, 0, 0, 0, NULL, text, lstrlenW(text), NULL);
6699                 break;
6700             case 1:
6701             {
6702                 int len = lstrlenW(text);
6703                 LPWORD indices = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WORD));
6704                 ret = pGetGlyphIndicesW(hdc, text, len, indices, 0);
6705                 ok(ret, "GetGlyphIndices failed\n");
6706                 ok(memcmp(indices, text, sizeof(WORD) * len) == 0,
6707                    "Glyph indices and text are different for %s:%d\n", lf.lfFaceName, tm.tmCharSet);
6708                 ret = ExtTextOutW(hdc, 0, 0, ETO_GLYPH_INDEX, NULL, indices, len, NULL);
6709                 HeapFree(GetProcessHeap(), 0, indices);
6710                 break;
6711             }
6712             }
6713             ok(ret, "ExtTextOutW failed\n");
6714             SelectObject(hdc, hBmpPrev);
6715         }
6716 
6717         GetObjectA(hBmp[0], sizeof(bmp), &bmp);
6718         ok(memcmp(pixels[0], pixels[1], bmp.bmHeight * bmp.bmWidthBytes) == 0,
6719            "Images are different (%s:%d)\n", lf.lfFaceName, tm.tmCharSet);
6720 
6721         ret = TranslateCharsetInfo((LPDWORD)(DWORD_PTR)tm.tmCharSet, &ci, TCI_SRCCHARSET);
6722         if (!ret) {
6723             skip("Can't get charset info for (%s:%d)\n", lf.lfFaceName, tm.tmCharSet);
6724             goto next;
6725         }
6726         if (IsDBCSLeadByteEx(ci.ciACP, chr)) {
6727             skip("High-ascii character is not defined in codepage %d\n", ci.ciACP);
6728             goto next;
6729         }
6730 
6731         for (j = 0; j < 2; j++) {
6732             HBITMAP hBmpPrev;
6733             WORD code;
6734             hBmpPrev = SelectObject(hdc, hBmp[j]);
6735             switch (j) {
6736             case 0:
6737                 ret = ExtTextOutA(hdc, 100, 0, 0, NULL, (LPCSTR)&chr, 1, NULL);
6738                 break;
6739             case 1:
6740                 ret = pGetGlyphIndicesA(hdc, (LPCSTR)&chr, 1, &code, 0);
6741                 ok(ret, "GetGlyphIndices failed\n");
6742                 ok(code == chr, "expected %02x, got %02x (%s:%d)\n", chr, code, lf.lfFaceName, tm.tmCharSet);
6743                 ret = ExtTextOutA(hdc, 100, 0, ETO_GLYPH_INDEX, NULL, (LPCSTR)&code, 1, NULL);
6744                 break;
6745             }
6746             ok(ret, "ExtTextOutA failed\n");
6747             SelectObject(hdc, hBmpPrev);
6748         }
6749 
6750         ok(memcmp(pixels[0], pixels[1], bmp.bmHeight * bmp.bmWidthBytes) == 0,
6751            "Images are different (%s:%d)\n", lf.lfFaceName, tm.tmCharSet);
6752     next:
6753         for (j = 0; j < 2; j++)
6754             DeleteObject(hBmp[j]);
6755         hFont = SelectObject(hdc, hFont);
6756         DeleteObject(hFont);
6757     }
6758 
6759     DeleteDC(hdc);
6760 }
6761 
6762 static void test_GetCharWidthI(void)
6763 {
6764     static const char *teststr = "wine ";
6765     HFONT hfont, prev_hfont;
6766     WORD glyphs[5];
6767     INT widths[5];
6768     LOGFONTA lf;
6769     ABC abc[5];
6770     int len, i;
6771     DWORD nb;
6772     BOOL ret;
6773     HDC hdc;
6774 
6775     memset(&lf, 0, sizeof(lf));
6776     strcpy(lf.lfFaceName, "Tahoma");
6777     lf.lfHeight = -20;
6778 
6779     hdc = GetDC(0);
6780 
6781     hfont = CreateFontIndirectA(&lf);
6782     prev_hfont = SelectObject(hdc, hfont);
6783 
6784     len = strlen(teststr);
6785     nb = GetGlyphIndicesA(hdc, teststr, len, glyphs, 0);
6786     ok(nb == len, "\n");
6787 
6788     memset(abc, 0xcc, sizeof(abc));
6789     ret = GetCharABCWidthsI(hdc, 0, len, glyphs, abc);
6790     ok(ret, "GetCharABCWidthsI failed\n");
6791 
6792     memset(widths, 0xcc, sizeof(widths));
6793     ret = GetCharWidthI(hdc, 0, len, glyphs, widths);
6794     ok(ret, "GetCharWidthI failed\n");
6795 
6796     for (i = 0; i < len; i++)
6797         ok(widths[i] == abc[i].abcA + abc[i].abcB + abc[i].abcC, "%u, glyph %u, got width %d\n",
6798             i, glyphs[i], widths[i]);
6799 
6800     DeleteObject(SelectObject(hdc, prev_hfont));
6801     ReleaseDC(0, hdc);
6802 }
6803 
6804 static INT CALLBACK long_enum_proc(const LOGFONTA *lf, const TEXTMETRICA *tm, DWORD type, LPARAM lparam)
6805 {
6806     BOOL *found_font = (BOOL *)lparam;
6807     *found_font = TRUE;
6808     return 1;
6809 }
6810 
6811 static void test_long_names(void)
6812 {
6813     char ttf_name[MAX_PATH];
6814     LOGFONTA font = {0};
6815     HFONT handle_font;
6816     BOOL found_font;
6817     int ret;
6818     HDC dc;
6819 
6820     if (!write_ttf_file("wine_longname.ttf", ttf_name))
6821     {
6822         skip("Failed to create ttf file for testing\n");
6823         return;
6824     }
6825 
6826     dc = GetDC(NULL);
6827 
6828     ret = AddFontResourceExA(ttf_name, FR_PRIVATE, 0);
6829     ok(ret, "AddFontResourceEx() failed\n");
6830 
6831     strcpy(font.lfFaceName, "wine_3_this_is_a_very_long_name");
6832     found_font = FALSE;
6833     EnumFontFamiliesExA(dc, &font, long_enum_proc, (LPARAM)&found_font, 0);
6834     ok(found_font == TRUE, "EnumFontFamiliesExA didn't find font.\n");
6835 
6836     strcpy(font.lfFaceName, "wine_2_this_is_a_very_long_name");
6837     found_font = FALSE;
6838     EnumFontFamiliesExA(dc, &font, long_enum_proc, (LPARAM)&found_font, 0);
6839     ok(found_font == TRUE, "EnumFontFamiliesExA didn't find font.\n");
6840 
6841     strcpy(font.lfFaceName, "wine_1_this_is_a_very_long_name");
6842     found_font = FALSE;
6843     EnumFontFamiliesExA(dc, &font, long_enum_proc, (LPARAM)&found_font, 0);
6844     ok(found_font == FALSE, "EnumFontFamiliesExA must not find font.\n");
6845 
6846     handle_font = CreateFontIndirectA(&font);
6847     ok(handle_font != NULL, "CreateFontIndirectA failed\n");
6848     DeleteObject(handle_font);
6849 
6850     ret = RemoveFontResourceExA(ttf_name, FR_PRIVATE, 0);
6851     ok(ret, "RemoveFontResourceEx() failed\n");
6852 
6853     DeleteFileA(ttf_name);
6854     ReleaseDC(NULL, dc);
6855 }
6856 
6857 START_TEST(font)
6858 {
6859     init();
6860 
6861     test_stock_fonts();
6862     test_logfont();
6863     test_bitmap_font();
6864     test_outline_font();
6865     test_bitmap_font_metrics();
6866     test_GdiGetCharDimensions();
6867     test_GetCharABCWidths();
6868     test_text_extents();
6869     test_GetGlyphIndices();
6870     test_GetKerningPairs();
6871     test_GetOutlineTextMetrics();
6872     test_SetTextJustification();
6873     test_font_charset();
6874     test_GdiGetCodePage();
6875     test_GetFontUnicodeRanges();
6876     test_nonexistent_font();
6877     test_orientation();
6878     test_height_selection();
6879     test_AddFontMemResource();
6880     test_EnumFonts();
6881     test_EnumFonts_subst();
6882 
6883     /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
6884      * I'd like to avoid them in this test.
6885      */
6886     test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
6887     test_EnumFontFamilies("Symbol", SYMBOL_CHARSET);
6888     if (is_truetype_font_installed("Arial Black") &&
6889         (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
6890     {
6891         test_EnumFontFamilies("", ANSI_CHARSET);
6892         test_EnumFontFamilies("", SYMBOL_CHARSET);
6893         test_EnumFontFamilies("", DEFAULT_CHARSET);
6894     }
6895     else
6896         skip("Arial Black or Symbol/Wingdings is not installed\n");
6897     test_EnumFontFamiliesEx_default_charset();
6898     test_GetTextMetrics();
6899     test_RealizationInfo();
6900     test_GetTextFace();
6901     test_GetGlyphOutline();
6902     test_GetTextMetrics2("Tahoma", -11);
6903     test_GetTextMetrics2("Tahoma", -55);
6904     test_GetTextMetrics2("Tahoma", -110);
6905     test_GetTextMetrics2("Arial", -11);
6906     test_GetTextMetrics2("Arial", -55);
6907     test_GetTextMetrics2("Arial", -110);
6908     test_GetCharacterPlacement();
6909     test_CreateFontIndirect();
6910     test_CreateFontIndirectEx();
6911     test_oemcharset();
6912     test_fullname();
6913     test_fullname2();
6914     test_east_asian_font_selection();
6915     test_max_height();
6916     test_vertical_order();
6917     test_GetCharWidth32();
6918     test_fake_bold_font();
6919     test_bitmap_font_glyph_index();
6920     test_GetCharWidthI();
6921     test_long_names();
6922 
6923     /* These tests should be last test until RemoveFontResource
6924      * is properly implemented.
6925      */
6926     test_vertical_font();
6927     test_CreateScalableFontResource();
6928 }
6929