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