gdi32: Implement font selection by its full name.
[wine] / dlls / gdi32 / tests / font.c
1 /*
2  * Unit test suite for fonts
3  *
4  * Copyright 2002 Mike McCormack
5  * Copyright 2004 Dmitry Timoshkov
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23 #include <assert.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winnls.h"
30
31 #include "wine/test.h"
32
33 /* Do not allow more than 1 deviation here */
34 #define match_off_by_1(a, b) (abs((a) - (b)) <= 1)
35
36 #define near_match(a, b) (abs((a) - (b)) <= 6)
37 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
38
39 static LONG  (WINAPI *pGdiGetCharDimensions)(HDC hdc, LPTEXTMETRICW lptm, LONG *height);
40 static DWORD (WINAPI *pGdiGetCodePage)(HDC hdc);
41 static BOOL  (WINAPI *pGetCharABCWidthsI)(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPABC abc);
42 static BOOL  (WINAPI *pGetCharABCWidthsA)(HDC hdc, UINT first, UINT last, LPABC abc);
43 static BOOL  (WINAPI *pGetCharABCWidthsW)(HDC hdc, UINT first, UINT last, LPABC abc);
44 static DWORD (WINAPI *pGetFontUnicodeRanges)(HDC hdc, LPGLYPHSET lpgs);
45 static DWORD (WINAPI *pGetGlyphIndicesA)(HDC hdc, LPCSTR lpstr, INT count, LPWORD pgi, DWORD flags);
46 static DWORD (WINAPI *pGetGlyphIndicesW)(HDC hdc, LPCWSTR lpstr, INT count, LPWORD pgi, DWORD flags);
47 static BOOL  (WINAPI *pGdiRealizationInfo)(HDC hdc, DWORD *);
48 static HFONT (WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDV *);
49 static HANDLE (WINAPI *pAddFontMemResourceEx)(PVOID, DWORD, PVOID, DWORD *);
50 static BOOL  (WINAPI *pRemoveFontMemResourceEx)(HANDLE);
51
52 static HMODULE hgdi32 = 0;
53 static const MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
54
55 static void init(void)
56 {
57     hgdi32 = GetModuleHandleA("gdi32.dll");
58
59     pGdiGetCharDimensions = (void *)GetProcAddress(hgdi32, "GdiGetCharDimensions");
60     pGdiGetCodePage = (void *) GetProcAddress(hgdi32,"GdiGetCodePage");
61     pGetCharABCWidthsI = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsI");
62     pGetCharABCWidthsA = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsA");
63     pGetCharABCWidthsW = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsW");
64     pGetFontUnicodeRanges = (void *)GetProcAddress(hgdi32, "GetFontUnicodeRanges");
65     pGetGlyphIndicesA = (void *)GetProcAddress(hgdi32, "GetGlyphIndicesA");
66     pGetGlyphIndicesW = (void *)GetProcAddress(hgdi32, "GetGlyphIndicesW");
67     pGdiRealizationInfo = (void *)GetProcAddress(hgdi32, "GdiRealizationInfo");
68     pCreateFontIndirectExA = (void *)GetProcAddress(hgdi32, "CreateFontIndirectExA");
69     pAddFontMemResourceEx = (void *)GetProcAddress(hgdi32, "AddFontMemResourceEx");
70     pRemoveFontMemResourceEx = (void *)GetProcAddress(hgdi32, "RemoveFontMemResourceEx");
71 }
72
73 static INT CALLBACK is_truetype_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
74 {
75     if (type != TRUETYPE_FONTTYPE) return 1;
76
77     return 0;
78 }
79
80 static BOOL is_truetype_font_installed(const char *name)
81 {
82     HDC hdc = GetDC(0);
83     BOOL ret = FALSE;
84
85     if (!EnumFontFamiliesA(hdc, name, is_truetype_font_installed_proc, 0))
86         ret = TRUE;
87
88     ReleaseDC(0, hdc);
89     return ret;
90 }
91
92 static INT CALLBACK is_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
93 {
94     return 0;
95 }
96
97 static BOOL is_font_installed(const char *name)
98 {
99     HDC hdc = GetDC(0);
100     BOOL ret = FALSE;
101
102     if(!EnumFontFamiliesA(hdc, name, is_font_installed_proc, 0))
103         ret = TRUE;
104
105     ReleaseDC(0, hdc);
106     return ret;
107 }
108
109 static void check_font(const char* test, const LOGFONTA* lf, HFONT hfont)
110 {
111     LOGFONTA getobj_lf;
112     int ret, minlen = 0;
113
114     if (!hfont)
115         return;
116
117     ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf);
118     /* NT4 tries to be clever and only returns the minimum length */
119     while (lf->lfFaceName[minlen] && minlen < LF_FACESIZE-1)
120         minlen++;
121     minlen += FIELD_OFFSET(LOGFONTA, lfFaceName) + 1;
122     ok(ret == sizeof(LOGFONTA) || ret == minlen, "%s: GetObject returned %d\n", test, ret);
123     ok(lf->lfHeight == getobj_lf.lfHeight ||
124        broken((SHORT)lf->lfHeight == getobj_lf.lfHeight), /* win9x */
125        "lfHeight: expect %08x got %08x\n", lf->lfHeight, getobj_lf.lfHeight);
126     ok(lf->lfWidth == getobj_lf.lfWidth ||
127        broken((SHORT)lf->lfWidth == getobj_lf.lfWidth), /* win9x */
128        "lfWidth: expect %08x got %08x\n", lf->lfWidth, getobj_lf.lfWidth);
129     ok(lf->lfEscapement == getobj_lf.lfEscapement ||
130        broken((SHORT)lf->lfEscapement == getobj_lf.lfEscapement), /* win9x */
131        "lfEscapement: expect %08x got %08x\n", lf->lfEscapement, getobj_lf.lfEscapement);
132     ok(lf->lfOrientation == getobj_lf.lfOrientation ||
133        broken((SHORT)lf->lfOrientation == getobj_lf.lfOrientation), /* win9x */
134        "lfOrientation: expect %08x got %08x\n", lf->lfOrientation, getobj_lf.lfOrientation);
135     ok(lf->lfWeight == getobj_lf.lfWeight ||
136        broken((SHORT)lf->lfWeight == getobj_lf.lfWeight), /* win9x */
137        "lfWeight: expect %08x got %08x\n", lf->lfWeight, getobj_lf.lfWeight);
138     ok(lf->lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf->lfItalic, getobj_lf.lfItalic);
139     ok(lf->lfUnderline == getobj_lf.lfUnderline, "lfUnderline: expect %02x got %02x\n", lf->lfUnderline, getobj_lf.lfUnderline);
140     ok(lf->lfStrikeOut == getobj_lf.lfStrikeOut, "lfStrikeOut: expect %02x got %02x\n", lf->lfStrikeOut, getobj_lf.lfStrikeOut);
141     ok(lf->lfCharSet == getobj_lf.lfCharSet, "lfCharSet: expect %02x got %02x\n", lf->lfCharSet, getobj_lf.lfCharSet);
142     ok(lf->lfOutPrecision == getobj_lf.lfOutPrecision, "lfOutPrecision: expect %02x got %02x\n", lf->lfOutPrecision, getobj_lf.lfOutPrecision);
143     ok(lf->lfClipPrecision == getobj_lf.lfClipPrecision, "lfClipPrecision: expect %02x got %02x\n", lf->lfClipPrecision, getobj_lf.lfClipPrecision);
144     ok(lf->lfQuality == getobj_lf.lfQuality, "lfQuality: expect %02x got %02x\n", lf->lfQuality, getobj_lf.lfQuality);
145     ok(lf->lfPitchAndFamily == getobj_lf.lfPitchAndFamily, "lfPitchAndFamily: expect %02x got %02x\n", lf->lfPitchAndFamily, getobj_lf.lfPitchAndFamily);
146     ok(!lstrcmpA(lf->lfFaceName, getobj_lf.lfFaceName) ||
147        broken(!memcmp(lf->lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
148        "%s: font names don't match: %s != %s\n", test, lf->lfFaceName, getobj_lf.lfFaceName);
149 }
150
151 static HFONT create_font(const char* test, const LOGFONTA* lf)
152 {
153     HFONT hfont = CreateFontIndirectA(lf);
154     ok(hfont != 0, "%s: CreateFontIndirect failed\n", test);
155     if (hfont)
156         check_font(test, lf, hfont);
157     return hfont;
158 }
159
160 static void test_logfont(void)
161 {
162     LOGFONTA lf;
163     HFONT hfont;
164
165     memset(&lf, 0, sizeof lf);
166
167     lf.lfCharSet = ANSI_CHARSET;
168     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
169     lf.lfWeight = FW_DONTCARE;
170     lf.lfHeight = 16;
171     lf.lfWidth = 16;
172     lf.lfQuality = DEFAULT_QUALITY;
173
174     lstrcpyA(lf.lfFaceName, "Arial");
175     hfont = create_font("Arial", &lf);
176     DeleteObject(hfont);
177
178     memset(&lf, 'A', sizeof(lf));
179     hfont = CreateFontIndirectA(&lf);
180     ok(hfont != 0, "CreateFontIndirectA with strange LOGFONT failed\n");
181     
182     lf.lfFaceName[LF_FACESIZE - 1] = 0;
183     check_font("AAA...", &lf, hfont);
184     DeleteObject(hfont);
185 }
186
187 static INT CALLBACK font_enum_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
188 {
189     if (type & RASTER_FONTTYPE)
190     {
191         LOGFONT *lf = (LOGFONT *)lParam;
192         *lf = *elf;
193         return 0; /* stop enumeration */
194     }
195
196     return 1; /* continue enumeration */
197 }
198
199 static void compare_tm(const TEXTMETRICA *tm, const TEXTMETRICA *otm)
200 {
201     ok(tm->tmHeight == otm->tmHeight, "tmHeight %d != %d\n", tm->tmHeight, otm->tmHeight);
202     ok(tm->tmAscent == otm->tmAscent, "tmAscent %d != %d\n", tm->tmAscent, otm->tmAscent);
203     ok(tm->tmDescent == otm->tmDescent, "tmDescent %d != %d\n", tm->tmDescent, otm->tmDescent);
204     ok(tm->tmInternalLeading == otm->tmInternalLeading, "tmInternalLeading %d != %d\n", tm->tmInternalLeading, otm->tmInternalLeading);
205     ok(tm->tmExternalLeading == otm->tmExternalLeading, "tmExternalLeading %d != %d\n", tm->tmExternalLeading, otm->tmExternalLeading);
206     ok(tm->tmAveCharWidth == otm->tmAveCharWidth, "tmAveCharWidth %d != %d\n", tm->tmAveCharWidth, otm->tmAveCharWidth);
207     ok(tm->tmMaxCharWidth == otm->tmMaxCharWidth, "tmMaxCharWidth %d != %d\n", tm->tmMaxCharWidth, otm->tmMaxCharWidth);
208     ok(tm->tmWeight == otm->tmWeight, "tmWeight %d != %d\n", tm->tmWeight, otm->tmWeight);
209     ok(tm->tmOverhang == otm->tmOverhang, "tmOverhang %d != %d\n", tm->tmOverhang, otm->tmOverhang);
210     ok(tm->tmDigitizedAspectX == otm->tmDigitizedAspectX, "tmDigitizedAspectX %d != %d\n", tm->tmDigitizedAspectX, otm->tmDigitizedAspectX);
211     ok(tm->tmDigitizedAspectY == otm->tmDigitizedAspectY, "tmDigitizedAspectY %d != %d\n", tm->tmDigitizedAspectY, otm->tmDigitizedAspectY);
212     ok(tm->tmFirstChar == otm->tmFirstChar, "tmFirstChar %d != %d\n", tm->tmFirstChar, otm->tmFirstChar);
213     ok(tm->tmLastChar == otm->tmLastChar, "tmLastChar %d != %d\n", tm->tmLastChar, otm->tmLastChar);
214     ok(tm->tmDefaultChar == otm->tmDefaultChar, "tmDefaultChar %d != %d\n", tm->tmDefaultChar, otm->tmDefaultChar);
215     ok(tm->tmBreakChar == otm->tmBreakChar, "tmBreakChar %d != %d\n", tm->tmBreakChar, otm->tmBreakChar);
216     ok(tm->tmItalic == otm->tmItalic, "tmItalic %d != %d\n", tm->tmItalic, otm->tmItalic);
217     ok(tm->tmUnderlined == otm->tmUnderlined, "tmUnderlined %d != %d\n", tm->tmUnderlined, otm->tmUnderlined);
218     ok(tm->tmStruckOut == otm->tmStruckOut, "tmStruckOut %d != %d\n", tm->tmStruckOut, otm->tmStruckOut);
219     ok(tm->tmPitchAndFamily == otm->tmPitchAndFamily, "tmPitchAndFamily %d != %d\n", tm->tmPitchAndFamily, otm->tmPitchAndFamily);
220     ok(tm->tmCharSet == otm->tmCharSet, "tmCharSet %d != %d\n", tm->tmCharSet, otm->tmCharSet);
221 }
222
223 static void test_font_metrics(HDC hdc, HFONT hfont, LONG lfHeight,
224                               LONG lfWidth, const char *test_str,
225                               INT test_str_len, const TEXTMETRICA *tm_orig,
226                               const SIZE *size_orig, INT width_of_A_orig,
227                               INT scale_x, INT scale_y)
228 {
229     LOGFONTA lf;
230     OUTLINETEXTMETRIC otm;
231     TEXTMETRICA tm;
232     SIZE size;
233     INT width_of_A, cx, cy;
234     UINT ret;
235
236     if (!hfont)
237         return;
238
239     ok(GetCurrentObject(hdc, OBJ_FONT) == hfont, "hfont should be selected\n");
240
241     GetObjectA(hfont, sizeof(lf), &lf);
242
243     if (GetOutlineTextMetricsA(hdc, 0, NULL))
244     {
245         otm.otmSize = sizeof(otm) / 2;
246         ret = GetOutlineTextMetricsA(hdc, otm.otmSize, &otm);
247         ok(ret == sizeof(otm)/2 /* XP */ ||
248            ret == 1 /* Win9x */, "expected sizeof(otm)/2, got %u\n", ret);
249
250         memset(&otm, 0x1, sizeof(otm));
251         otm.otmSize = sizeof(otm);
252         ret = GetOutlineTextMetricsA(hdc, otm.otmSize, &otm);
253         ok(ret == sizeof(otm) /* XP */ ||
254            ret == 1 /* Win9x */, "expected sizeof(otm), got %u\n", ret);
255
256         memset(&tm, 0x2, sizeof(tm));
257         ret = GetTextMetricsA(hdc, &tm);
258         ok(ret, "GetTextMetricsA failed\n");
259         /* the structure size is aligned */
260         if (memcmp(&tm, &otm.otmTextMetrics, FIELD_OFFSET(TEXTMETRICA, tmCharSet) + 1))
261         {
262             ok(0, "tm != otm\n");
263             compare_tm(&tm, &otm.otmTextMetrics);
264         }
265
266         tm = otm.otmTextMetrics;
267 if (0) /* these metrics are scaled too, but with rounding errors */
268 {
269         ok(otm.otmAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmAscent, tm.tmAscent);
270         ok(otm.otmDescent == -tm.tmDescent, "descent %d != %d\n", otm.otmDescent, -tm.tmDescent);
271 }
272         ok(otm.otmMacAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmMacAscent, tm.tmAscent);
273         ok(otm.otmDescent < 0, "otm.otmDescent should be < 0\n");
274         ok(otm.otmMacDescent < 0, "otm.otmMacDescent should be < 0\n");
275         ok(tm.tmDescent > 0, "tm.tmDescent should be > 0\n");
276         ok(otm.otmMacDescent == -tm.tmDescent, "descent %d != %d\n", otm.otmMacDescent, -tm.tmDescent);
277         ok(otm.otmEMSquare == 2048, "expected 2048, got %d\n", otm.otmEMSquare);
278     }
279     else
280     {
281         ret = GetTextMetricsA(hdc, &tm);
282         ok(ret, "GetTextMetricsA failed\n");
283     }
284
285     cx = tm.tmAveCharWidth / tm_orig->tmAveCharWidth;
286     cy = tm.tmHeight / tm_orig->tmHeight;
287     ok(cx == scale_x && cy == scale_y, "height %d: expected scale_x %d, scale_y %d, got cx %d, cy %d\n",
288        lfHeight, scale_x, scale_y, cx, cy);
289     ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "height %d != %d\n", tm.tmHeight, tm_orig->tmHeight * scale_y);
290     ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "ascent %d != %d\n", tm.tmAscent, tm_orig->tmAscent * scale_y);
291     ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "descent %d != %d\n", tm.tmDescent, tm_orig->tmDescent * scale_y);
292     ok(near_match(tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x), "ave width %d != %d\n", tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x);
293     ok(near_match(tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x), "max width %d != %d\n", tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x);
294
295     ok(lf.lfHeight == lfHeight, "lfHeight %d != %d\n", lf.lfHeight, lfHeight);
296     if (lf.lfHeight)
297     {
298         if (lf.lfWidth)
299             ok(lf.lfWidth == tm.tmAveCharWidth, "lfWidth %d != tm %d\n", lf.lfWidth, tm.tmAveCharWidth);
300     }
301     else
302         ok(lf.lfWidth == lfWidth, "lfWidth %d != %d\n", lf.lfWidth, lfWidth);
303
304     GetTextExtentPoint32A(hdc, test_str, test_str_len, &size);
305
306     ok(near_match(size.cx, size_orig->cx * scale_x), "cx %d != %d\n", size.cx, size_orig->cx * scale_x);
307     ok(size.cy == size_orig->cy * scale_y, "cy %d != %d\n", size.cy, size_orig->cy * scale_y);
308
309     GetCharWidthA(hdc, 'A', 'A', &width_of_A);
310
311     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);
312 }
313
314 /* Test how GDI scales bitmap font metrics */
315 static void test_bitmap_font(void)
316 {
317     static const char test_str[11] = "Test String";
318     HDC hdc;
319     LOGFONTA bitmap_lf;
320     HFONT hfont, old_hfont;
321     TEXTMETRICA tm_orig;
322     SIZE size_orig;
323     INT ret, i, width_orig, height_orig, scale, lfWidth;
324
325     hdc = GetDC(0);
326
327     /* "System" has only 1 pixel size defined, otherwise the test breaks */
328     ret = EnumFontFamiliesA(hdc, "System", font_enum_proc, (LPARAM)&bitmap_lf);
329     if (ret)
330     {
331         ReleaseDC(0, hdc);
332         trace("no bitmap fonts were found, skipping the test\n");
333         return;
334     }
335
336     trace("found bitmap font %s, height %d\n", bitmap_lf.lfFaceName, bitmap_lf.lfHeight);
337
338     height_orig = bitmap_lf.lfHeight;
339     lfWidth = bitmap_lf.lfWidth;
340
341     hfont = create_font("bitmap", &bitmap_lf);
342     old_hfont = SelectObject(hdc, hfont);
343     ok(GetTextMetricsA(hdc, &tm_orig), "GetTextMetricsA failed\n");
344     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
345     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
346     SelectObject(hdc, old_hfont);
347     DeleteObject(hfont);
348
349     bitmap_lf.lfHeight = 0;
350     bitmap_lf.lfWidth = 4;
351     hfont = create_font("bitmap", &bitmap_lf);
352     old_hfont = SelectObject(hdc, hfont);
353     test_font_metrics(hdc, hfont, 0, 4, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, 1);
354     SelectObject(hdc, old_hfont);
355     DeleteObject(hfont);
356
357     bitmap_lf.lfHeight = height_orig;
358     bitmap_lf.lfWidth = lfWidth;
359
360     /* test fractional scaling */
361     for (i = 1; i <= height_orig * 6; i++)
362     {
363         INT nearest_height;
364
365         bitmap_lf.lfHeight = i;
366         hfont = create_font("fractional", &bitmap_lf);
367         scale = (i + height_orig - 1) / height_orig;
368         nearest_height = scale * height_orig;
369         /* Only jump to the next height if the difference <= 25% original height */
370         if (scale > 2 && nearest_height - i > height_orig / 4) scale--;
371         /* The jump between unscaled and doubled is delayed by 1 in winnt+ but not in win9x,
372            so we'll not test this particular height. */
373         else if(scale == 2 && nearest_height - i == (height_orig / 4)) continue;
374         else if(scale == 2 && nearest_height - i > (height_orig / 4 - 1)) scale--;
375         old_hfont = SelectObject(hdc, hfont);
376         test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, scale);
377         SelectObject(hdc, old_hfont);
378         DeleteObject(hfont);
379     }
380
381     /* test integer scaling 3x2 */
382     bitmap_lf.lfHeight = height_orig * 2;
383     bitmap_lf.lfWidth *= 3;
384     hfont = create_font("3x2", &bitmap_lf);
385     old_hfont = SelectObject(hdc, hfont);
386     test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 2);
387     SelectObject(hdc, old_hfont);
388     DeleteObject(hfont);
389
390     /* test integer scaling 3x3 */
391     bitmap_lf.lfHeight = height_orig * 3;
392     bitmap_lf.lfWidth = 0;
393     hfont = create_font("3x3", &bitmap_lf);
394     old_hfont = SelectObject(hdc, hfont);
395     test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 3);
396     SelectObject(hdc, old_hfont);
397     DeleteObject(hfont);
398
399     ReleaseDC(0, hdc);
400 }
401
402 /* Test how GDI scales outline font metrics */
403 static void test_outline_font(void)
404 {
405     static const char test_str[11] = "Test String";
406     HDC hdc, hdc_2;
407     LOGFONTA lf;
408     HFONT hfont, old_hfont, old_hfont_2;
409     OUTLINETEXTMETRICA otm;
410     SIZE size_orig;
411     INT width_orig, height_orig, lfWidth;
412     XFORM xform;
413     GLYPHMETRICS gm;
414     MAT2 mat2 = { {0x8000,0}, {0,0}, {0,0}, {0x8000,0} };
415     POINT pt;
416     INT ret;
417
418     if (!is_truetype_font_installed("Arial"))
419     {
420         skip("Arial is not installed\n");
421         return;
422     }
423
424     hdc = CreateCompatibleDC(0);
425
426     memset(&lf, 0, sizeof(lf));
427     strcpy(lf.lfFaceName, "Arial");
428     lf.lfHeight = 72;
429     hfont = create_font("outline", &lf);
430     old_hfont = SelectObject(hdc, hfont);
431     otm.otmSize = sizeof(otm);
432     ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n");
433     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
434     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
435
436     test_font_metrics(hdc, hfont, lf.lfHeight, otm.otmTextMetrics.tmAveCharWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
437     SelectObject(hdc, old_hfont);
438     DeleteObject(hfont);
439
440     /* font of otmEMSquare height helps to avoid a lot of rounding errors */
441     lf.lfHeight = otm.otmEMSquare;
442     lf.lfHeight = -lf.lfHeight;
443     hfont = create_font("outline", &lf);
444     old_hfont = SelectObject(hdc, hfont);
445     otm.otmSize = sizeof(otm);
446     ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n");
447     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
448     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
449     SelectObject(hdc, old_hfont);
450     DeleteObject(hfont);
451
452     height_orig = otm.otmTextMetrics.tmHeight;
453     lfWidth = otm.otmTextMetrics.tmAveCharWidth;
454
455     /* test integer scaling 3x2 */
456     lf.lfHeight = height_orig * 2;
457     lf.lfWidth = lfWidth * 3;
458     hfont = create_font("3x2", &lf);
459     old_hfont = SelectObject(hdc, hfont);
460     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 2);
461     SelectObject(hdc, old_hfont);
462     DeleteObject(hfont);
463
464     /* test integer scaling 3x3 */
465     lf.lfHeight = height_orig * 3;
466     lf.lfWidth = lfWidth * 3;
467     hfont = create_font("3x3", &lf);
468     old_hfont = SelectObject(hdc, hfont);
469     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 3);
470     SelectObject(hdc, old_hfont);
471     DeleteObject(hfont);
472
473     /* test integer scaling 1x1 */
474     lf.lfHeight = height_orig * 1;
475     lf.lfWidth = lfWidth * 1;
476     hfont = create_font("1x1", &lf);
477     old_hfont = SelectObject(hdc, hfont);
478     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
479     SelectObject(hdc, old_hfont);
480     DeleteObject(hfont);
481
482     /* test integer scaling 1x1 */
483     lf.lfHeight = height_orig;
484     lf.lfWidth = 0;
485     hfont = create_font("1x1", &lf);
486     old_hfont = SelectObject(hdc, hfont);
487     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
488
489     /* with an identity matrix */
490     memset(&gm, 0, sizeof(gm));
491     SetLastError(0xdeadbeef);
492     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
493     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
494     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
495     ok(gm.gmCellIncX == width_orig, "incX %d != %d\n", gm.gmCellIncX, width_orig);
496     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
497     /* with a custom matrix */
498     memset(&gm, 0, sizeof(gm));
499     SetLastError(0xdeadbeef);
500     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
501     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
502     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
503     ok(gm.gmCellIncX == width_orig/2, "incX %d != %d\n", gm.gmCellIncX, width_orig/2);
504     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
505
506     /* Test that changing the DC transformation affects only the font
507      * selected on this DC and doesn't affect the same font selected on
508      * another DC.
509      */
510     hdc_2 = CreateCompatibleDC(0);
511     old_hfont_2 = SelectObject(hdc_2, hfont);
512     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
513
514     SetMapMode(hdc, MM_ANISOTROPIC);
515
516     /* font metrics on another DC should be unchanged */
517     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
518
519     /* test restrictions of compatibility mode GM_COMPATIBLE */
520     /*  part 1: rescaling only X should not change font scaling on screen.
521                 So compressing the X axis by 2 is not done, and this
522                 appears as X scaling of 2 that no one requested. */
523     SetWindowExtEx(hdc, 100, 100, NULL);
524     SetViewportExtEx(hdc, 50, 100, NULL);
525     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 2, 1);
526     /* font metrics on another DC should be unchanged */
527     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
528
529     /*  part 2: rescaling only Y should change font scaling.
530                 As also X is scaled by a factor of 2, but this is not
531                 requested by the DC transformation, we get a scaling factor
532                 of 2 in the X coordinate. */
533     SetViewportExtEx(hdc, 100, 200, NULL);
534     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 2, 1);
535     /* font metrics on another DC should be unchanged */
536     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
537
538     /* restore scaling */
539     SetMapMode(hdc, MM_TEXT);
540
541     /* font metrics on another DC should be unchanged */
542     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
543
544     SelectObject(hdc_2, old_hfont_2);
545     DeleteDC(hdc_2);
546
547     if (!SetGraphicsMode(hdc, GM_ADVANCED))
548     {
549         SelectObject(hdc, old_hfont);
550         DeleteObject(hfont);
551         DeleteDC(hdc);
552         skip("GM_ADVANCED is not supported on this platform\n");
553         return;
554     }
555
556     xform.eM11 = 20.0f;
557     xform.eM12 = 0.0f;
558     xform.eM21 = 0.0f;
559     xform.eM22 = 20.0f;
560     xform.eDx = 0.0f;
561     xform.eDy = 0.0f;
562
563     SetLastError(0xdeadbeef);
564     ret = SetWorldTransform(hdc, &xform);
565     ok(ret, "SetWorldTransform error %u\n", GetLastError());
566
567     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
568
569     /* with an identity matrix */
570     memset(&gm, 0, sizeof(gm));
571     SetLastError(0xdeadbeef);
572     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
573     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
574     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
575     pt.x = width_orig; pt.y = 0;
576     LPtoDP(hdc, &pt, 1);
577     ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x);
578     ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig);
579     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
580     /* with a custom matrix */
581     memset(&gm, 0, sizeof(gm));
582     SetLastError(0xdeadbeef);
583     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
584     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
585     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
586     pt.x = width_orig; pt.y = 0;
587     LPtoDP(hdc, &pt, 1);
588     ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2);
589     ok(near_match(gm.gmCellIncX, 10 * width_orig), "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig);
590     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
591
592     SetLastError(0xdeadbeef);
593     ret = SetMapMode(hdc, MM_LOMETRIC);
594     ok(ret == MM_TEXT, "expected MM_TEXT, got %d, error %u\n", ret, GetLastError());
595
596     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
597
598     /* with an identity matrix */
599     memset(&gm, 0, sizeof(gm));
600     SetLastError(0xdeadbeef);
601     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
602     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
603     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
604     pt.x = width_orig; pt.y = 0;
605     LPtoDP(hdc, &pt, 1);
606     ok(near_match(gm.gmCellIncX, pt.x), "incX %d != %d\n", gm.gmCellIncX, pt.x);
607     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
608     /* with a custom matrix */
609     memset(&gm, 0, sizeof(gm));
610     SetLastError(0xdeadbeef);
611     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
612     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
613     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
614     pt.x = width_orig; pt.y = 0;
615     LPtoDP(hdc, &pt, 1);
616     ok(near_match(gm.gmCellIncX, (pt.x + 1)/2), "incX %d != %d\n", gm.gmCellIncX, (pt.x + 1)/2);
617     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
618
619     SetLastError(0xdeadbeef);
620     ret = SetMapMode(hdc, MM_TEXT);
621     ok(ret == MM_LOMETRIC, "expected MM_LOMETRIC, got %d, error %u\n", ret, GetLastError());
622
623     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
624
625     /* with an identity matrix */
626     memset(&gm, 0, sizeof(gm));
627     SetLastError(0xdeadbeef);
628     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
629     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
630     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
631     pt.x = width_orig; pt.y = 0;
632     LPtoDP(hdc, &pt, 1);
633     ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x);
634     ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig);
635     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
636     /* with a custom matrix */
637     memset(&gm, 0, sizeof(gm));
638     SetLastError(0xdeadbeef);
639     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
640     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
641     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
642     pt.x = width_orig; pt.y = 0;
643     LPtoDP(hdc, &pt, 1);
644     ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2);
645     ok(gm.gmCellIncX == 10 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig);
646     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
647
648     SelectObject(hdc, old_hfont);
649     DeleteObject(hfont);
650     DeleteDC(hdc);
651 }
652
653 static INT CALLBACK find_font_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
654 {
655     LOGFONT *lf = (LOGFONT *)lParam;
656
657     if (elf->lfHeight == lf->lfHeight && !strcmp(elf->lfFaceName, lf->lfFaceName))
658     {
659         *lf = *elf;
660         return 0; /* stop enumeration */
661     }
662     return 1; /* continue enumeration */
663 }
664
665 static void test_bitmap_font_metrics(void)
666 {
667     static const struct font_data
668     {
669         const char face_name[LF_FACESIZE];
670         int weight, height, ascent, descent, int_leading, ext_leading;
671         int ave_char_width, max_char_width, dpi;
672         DWORD ansi_bitfield;
673         WORD skip_lang_id;
674     } fd[] =
675     {
676         { "MS Sans Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, 96, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
677         { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 96, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
678         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 16, 96, FS_LATIN1 | FS_CYRILLIC },
679         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 96, FS_LATIN2 },
680         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 19, 96, FS_LATIN1 },
681         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 24, 96, FS_LATIN2 },
682         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 20, 96, FS_CYRILLIC },
683         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 24, 96, FS_LATIN1 },
684         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 6, 0, 12, 24, 96, FS_LATIN2 },
685         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 25, 96, FS_CYRILLIC },
686         { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32, 96, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
687
688         { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 120, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
689         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 120, FS_LATIN1 | FS_LATIN2 },
690         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 17, 120, FS_CYRILLIC },
691         { "MS Sans Serif", FW_NORMAL, 25, 20, 5, 5, 0, 10, 21, 120, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
692         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 6, 0, 12, 24, 120, FS_LATIN1 | FS_LATIN2 },
693         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 24, 120, FS_CYRILLIC },
694         { "MS Sans Serif", FW_NORMAL, 36, 29, 7, 6, 0, 15, 30, 120, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
695         { "MS Sans Serif", FW_NORMAL, 46, 37, 9, 6, 0, 20, 40, 120, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
696
697         { "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8, 96, FS_LATIN1 | FS_LATIN2 },
698         { "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 96, FS_CYRILLIC },
699         { "MS Serif", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9, 96, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
700         { "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, 96, FS_LATIN1 },
701         { "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 12, 96, FS_LATIN2 | FS_CYRILLIC },
702         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 14, 96, FS_LATIN1 | FS_LATIN2 },
703         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 16, 96, FS_CYRILLIC },
704         { "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 18, 96, FS_LATIN1 | FS_LATIN2 },
705         { "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 19, 96, FS_CYRILLIC },
706         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 17, 96, FS_LATIN1 },
707         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 22, 96, FS_LATIN2 },
708         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 23, 96, FS_CYRILLIC },
709         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 23, 96, FS_LATIN1 },
710         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 26, 96, FS_LATIN2 },
711         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 27, 96, FS_CYRILLIC },
712         { "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 33, 96, FS_LATIN1 | FS_LATIN2 },
713         { "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 34, 96, FS_CYRILLIC },
714
715         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 14, 120, FS_LATIN1 | FS_CYRILLIC },
716         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 13, 120, FS_LATIN2 },
717         { "MS Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 120, FS_LATIN1 | FS_CYRILLIC },
718         { "MS Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 15, 120, FS_LATIN2 },
719         { "MS Serif", FW_NORMAL, 23, 18, 5, 3, 0, 10, 21, 120, FS_LATIN1 | FS_CYRILLIC },
720         { "MS Serif", FW_NORMAL, 23, 18, 5, 3, 0, 10, 19, 120, FS_LATIN2 },
721         { "MS Serif", FW_NORMAL, 27, 21, 6, 4, 0, 12, 23, 120, FS_LATIN1 | FS_LATIN2 },
722         { "MS Serif", FW_MEDIUM, 27, 22, 5, 2, 0, 12, 30, 120, FS_CYRILLIC },
723         { "MS Serif", FW_NORMAL, 33, 26, 7, 3, 0, 14, 30, 120, FS_LATIN1 | FS_LATIN2 },
724         { "MS Serif", FW_MEDIUM, 32, 25, 7, 2, 0, 14, 32, 120, FS_CYRILLIC },
725         { "MS Serif", FW_NORMAL, 43, 34, 9, 3, 0, 19, 39, 120, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
726
727         { "Courier", FW_NORMAL, 13, 11, 2, 0, 0, 8, 8, 96, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
728         { "Courier", FW_NORMAL, 16, 13, 3, 0, 0, 9, 9, 96, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
729         { "Courier", FW_NORMAL, 20, 16, 4, 0, 0, 12, 12, 96, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
730
731         { "Courier", FW_NORMAL, 16, 13, 3, 0, 0, 9, 9, 120, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
732         { "Courier", FW_NORMAL, 20, 16, 4, 0, 0, 12, 12, 120, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
733         { "Courier", FW_NORMAL, 25, 20, 5, 0, 0, 15, 15, 120, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
734
735         { "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 14, 96, FS_LATIN1 },
736         { "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 15, 96, FS_LATIN2 | FS_CYRILLIC },
737         { "System", FW_NORMAL, 18, 16, 2, 0, 2, 8, 16, 96, FS_JISJAPAN },
738
739         { "System", FW_BOLD, 20, 16, 4, 4, 0, 9, 14, 120, FS_LATIN1 },
740         { "System", FW_BOLD, 20, 16, 4, 4, 0, 9, 17, 120, FS_LATIN2 | FS_CYRILLIC },
741
742         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 2, 96, FS_LATIN1 },
743         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 8, 96, FS_LATIN2 | FS_CYRILLIC },
744         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 2, 4, 96, FS_JISJAPAN },
745         { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 3, 4, 96, FS_LATIN1, LANG_ARABIC },
746         { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 2, 8, 96, FS_LATIN2 | FS_CYRILLIC },
747         { "Small Fonts", FW_NORMAL, 5, 4, 1, 0, 0, 3, 6, 96, FS_JISJAPAN },
748         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 13, 96, FS_LATIN1, LANG_ARABIC },
749         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 96, FS_LATIN2 | FS_CYRILLIC },
750         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 96, FS_ARABIC },
751         { "Small Fonts", FW_NORMAL, 6, 5, 1, 0, 0, 4, 8, 96, FS_JISJAPAN },
752         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 7, 96, FS_LATIN1, LANG_ARABIC },
753         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 96, FS_LATIN2 | FS_CYRILLIC },
754         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 96, FS_ARABIC },
755         { "Small Fonts", FW_NORMAL, 8, 7, 1, 0, 0, 5, 10, 96, FS_JISJAPAN },
756         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8, 96, FS_LATIN1 | FS_LATIN2, LANG_ARABIC },
757         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 96, FS_CYRILLIC },
758         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 4, 9, 96, FS_ARABIC },
759         { "Small Fonts", FW_NORMAL, 10, 8, 2, 0, 0, 6, 12, 96, FS_JISJAPAN },
760         { "Small Fonts", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9, 96, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC, LANG_ARABIC },
761         { "Small Fonts", FW_NORMAL, 11, 9, 2, 2, 0, 4, 10, 96, FS_ARABIC },
762         { "Small Fonts", FW_NORMAL, 11, 9, 2, 0, 0, 7, 14, 96, FS_JISJAPAN },
763
764         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 2, 120, FS_LATIN1 | FS_JISJAPAN },
765         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 8, 120, FS_LATIN2 | FS_CYRILLIC },
766         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 5, 120, FS_LATIN1 | FS_JISJAPAN },
767         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 120, FS_LATIN2 | FS_CYRILLIC },
768         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 7, 120, FS_LATIN1 | FS_JISJAPAN },
769         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 120, FS_LATIN2 | FS_CYRILLIC },
770         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 9, 120, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
771         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 120, FS_CYRILLIC },
772         { "Small Fonts", FW_NORMAL, 12, 10, 2, 2, 0, 5, 10, 120, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
773         { "Small Fonts", FW_NORMAL, 12, 10, 2, 2, 0, 6, 10, 120, FS_CYRILLIC },
774         { "Small Fonts", FW_NORMAL, 13, 11, 2, 2, 0, 6, 12, 120, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
775         { "Small Fonts", FW_NORMAL, 13, 11, 2, 2, 0, 6, 11, 120, FS_CYRILLIC },
776
777         { "Fixedsys", FW_NORMAL, 15, 12, 3, 3, 0, 8, 8, 96, FS_LATIN1 | FS_LATIN2 },
778         { "Fixedsys", FW_NORMAL, 16, 12, 4, 3, 0, 8, 8, 96, FS_CYRILLIC },
779         { "FixedSys", FW_NORMAL, 18, 16, 2, 0, 0, 8, 16, 96, FS_JISJAPAN },
780
781         /* The 120dpi version still has its dpi marked as 96 */
782         { "Fixedsys", FW_NORMAL, 20, 16, 4, 2, 0, 10, 10, 96, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC }
783
784         /* FIXME: add "Terminal" */
785     };
786     HDC hdc;
787     LOGFONT lf;
788     HFONT hfont, old_hfont;
789     TEXTMETRIC tm;
790     INT ret, i;
791     WORD system_lang_id;
792
793     system_lang_id = PRIMARYLANGID(GetSystemDefaultLangID());
794
795     hdc = CreateCompatibleDC(0);
796     assert(hdc);
797
798     for (i = 0; i < sizeof(fd)/sizeof(fd[0]); i++)
799     {
800         int bit;
801
802         memset(&lf, 0, sizeof(lf));
803
804         lf.lfHeight = fd[i].height;
805         strcpy(lf.lfFaceName, fd[i].face_name);
806
807         for(bit = 0; bit < 32; bit++)
808         {
809             DWORD fs[2];
810             CHARSETINFO csi;
811             BOOL bRet;
812
813             fs[0] = 1L << bit;
814             fs[1] = 0;
815             if((fd[i].ansi_bitfield & fs[0]) == 0) continue;
816             if(!TranslateCharsetInfo( fs, &csi, TCI_SRCFONTSIG )) continue;
817
818             lf.lfCharSet = csi.ciCharset;
819             ret = EnumFontFamiliesEx(hdc, &lf, find_font_proc, (LPARAM)&lf, 0);
820             if (ret) continue;
821
822             hfont = create_font(lf.lfFaceName, &lf);
823             old_hfont = SelectObject(hdc, hfont);
824             bRet = GetTextMetrics(hdc, &tm);
825             ok(bRet, "GetTextMetrics error %d\n", GetLastError());
826             if(fd[i].dpi == tm.tmDigitizedAspectX)
827             {
828                 trace("found font %s, height %d charset %x dpi %d\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet, fd[i].dpi);
829                 if (fd[i].skip_lang_id == 0 || system_lang_id != fd[i].skip_lang_id)
830                 {
831                     ok(tm.tmWeight == fd[i].weight, "%s(%d): tm.tmWeight %d != %d\n", fd[i].face_name, fd[i].height, tm.tmWeight, fd[i].weight);
832                     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);
833                     ok(tm.tmAscent == fd[i].ascent, "%s(%d): tm.tmAscent %d != %d\n", fd[i].face_name, fd[i].height, tm.tmAscent, fd[i].ascent);
834                     ok(tm.tmDescent == fd[i].descent, "%s(%d): tm.tmDescent %d != %d\n", fd[i].face_name, fd[i].height, tm.tmDescent, fd[i].descent);
835                     ok(tm.tmInternalLeading == fd[i].int_leading, "%s(%d): tm.tmInternalLeading %d != %d\n", fd[i].face_name, fd[i].height, tm.tmInternalLeading, fd[i].int_leading);
836                     ok(tm.tmExternalLeading == fd[i].ext_leading, "%s(%d): tm.tmExternalLeading %d != %d\n", fd[i].face_name, fd[i].height, tm.tmExternalLeading, fd[i].ext_leading);
837                     ok(tm.tmAveCharWidth == fd[i].ave_char_width, "%s(%d): tm.tmAveCharWidth %d != %d\n", fd[i].face_name, fd[i].height, tm.tmAveCharWidth, fd[i].ave_char_width);
838
839                     /* Don't run the max char width test on System/ANSI_CHARSET.  We have extra characters in our font
840                        that make the max width bigger */
841                     if(strcmp(lf.lfFaceName, "System") || lf.lfCharSet != ANSI_CHARSET)
842                         ok(tm.tmMaxCharWidth == fd[i].max_char_width, "%s(%d): tm.tmMaxCharWidth %d != %d\n", fd[i].face_name, fd[i].height, tm.tmMaxCharWidth, fd[i].max_char_width);
843                 }
844                 else
845                     skip("Skipping font metrics test for system langid 0x%x\n",
846                          system_lang_id);
847             }
848             SelectObject(hdc, old_hfont);
849             DeleteObject(hfont);
850         }
851     }
852
853     DeleteDC(hdc);
854 }
855
856 static void test_GdiGetCharDimensions(void)
857 {
858     HDC hdc;
859     TEXTMETRICW tm;
860     LONG ret;
861     SIZE size;
862     LONG avgwidth, height;
863     static const char szAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
864
865     if (!pGdiGetCharDimensions)
866     {
867         win_skip("GdiGetCharDimensions not available on this platform\n");
868         return;
869     }
870
871     hdc = CreateCompatibleDC(NULL);
872
873     GetTextExtentPoint(hdc, szAlphabet, strlen(szAlphabet), &size);
874     avgwidth = ((size.cx / 26) + 1) / 2;
875
876     ret = pGdiGetCharDimensions(hdc, &tm, &height);
877     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
878     ok(height == tm.tmHeight, "GdiGetCharDimensions should have set height to %d instead of %d\n", tm.tmHeight, height);
879
880     ret = pGdiGetCharDimensions(hdc, &tm, NULL);
881     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
882
883     ret = pGdiGetCharDimensions(hdc, NULL, NULL);
884     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
885
886     height = 0;
887     ret = pGdiGetCharDimensions(hdc, NULL, &height);
888     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
889     ok(height == size.cy, "GdiGetCharDimensions should have set height to %d instead of %d\n", size.cy, height);
890
891     DeleteDC(hdc);
892 }
893
894 static int CALLBACK create_font_proc(const LOGFONT *lpelfe,
895                                      const TEXTMETRIC *lpntme,
896                                      DWORD FontType, LPARAM lParam)
897 {
898     if (FontType & TRUETYPE_FONTTYPE)
899     {
900         HFONT hfont;
901
902         hfont = CreateFontIndirect(lpelfe);
903         if (hfont)
904         {
905             *(HFONT *)lParam = hfont;
906             return 0;
907         }
908     }
909
910     return 1;
911 }
912
913 static void test_GetCharABCWidths(void)
914 {
915     static const WCHAR str[] = {'a',0};
916     BOOL ret;
917     HDC hdc;
918     LOGFONTA lf;
919     HFONT hfont;
920     ABC abc[1];
921     WORD glyphs[1];
922     DWORD nb;
923     static const struct
924     {
925         UINT first;
926         UINT last;
927     } range[] =
928     {
929         {0xff, 0xff},
930         {0x100, 0x100},
931         {0xff, 0x100},
932         {0x1ff, 0xff00},
933         {0xffff, 0xffff},
934         {0x10000, 0x10000},
935         {0xffff, 0x10000},
936         {0xffffff, 0xffffff},
937         {0x1000000, 0x1000000},
938         {0xffffff, 0x1000000},
939         {0xffffffff, 0xffffffff}
940     };
941     static const struct
942     {
943         UINT cs;
944         UINT a;
945         UINT w;
946         BOOL r[sizeof range / sizeof range[0]];
947     } c[] =
948     {
949         {ANSI_CHARSET, 0x30, 0x30, {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}},
950         {SHIFTJIS_CHARSET, 0x82a0, 0x3042, {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}},
951         {HANGEUL_CHARSET, 0x8141, 0xac02, {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}},
952         {JOHAB_CHARSET, 0x8446, 0x3135, {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}},
953         {GB2312_CHARSET, 0x8141, 0x4e04, {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}},
954         {CHINESEBIG5_CHARSET, 0xa142, 0x3001, {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}}
955     };
956     UINT i;
957
958     if (!pGetCharABCWidthsA || !pGetCharABCWidthsW || !pGetCharABCWidthsI)
959     {
960         win_skip("GetCharABCWidthsA/W/I not available on this platform\n");
961         return;
962     }
963
964     memset(&lf, 0, sizeof(lf));
965     strcpy(lf.lfFaceName, "System");
966     lf.lfHeight = 20;
967
968     hfont = CreateFontIndirectA(&lf);
969     hdc = GetDC(0);
970     hfont = SelectObject(hdc, hfont);
971
972     nb = pGetGlyphIndicesW(hdc, str, 1, glyphs, 0);
973     ok(nb == 1, "GetGlyphIndicesW should have returned 1\n");
974
975     ret = pGetCharABCWidthsI(NULL, 0, 1, glyphs, abc);
976     ok(!ret, "GetCharABCWidthsI should have failed\n");
977
978     ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, NULL);
979     ok(!ret, "GetCharABCWidthsI should have failed\n");
980
981     ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, abc);
982     ok(ret, "GetCharABCWidthsI should have succeeded\n");
983
984     ret = pGetCharABCWidthsW(NULL, 'a', 'a', abc);
985     ok(!ret, "GetCharABCWidthsW should have failed\n");
986
987     ret = pGetCharABCWidthsW(hdc, 'a', 'a', NULL);
988     ok(!ret, "GetCharABCWidthsW should have failed\n");
989
990     ret = pGetCharABCWidthsW(hdc, 'a', 'a', abc);
991     ok(!ret, "GetCharABCWidthsW should have failed\n");
992
993     hfont = SelectObject(hdc, hfont);
994     DeleteObject(hfont);
995
996     for (i = 0; i < sizeof c / sizeof c[0]; ++i)
997     {
998         ABC a[2], w[2];
999         ABC full[256];
1000         UINT code = 0x41, j;
1001
1002         lf.lfFaceName[0] = '\0';
1003         lf.lfCharSet = c[i].cs;
1004         lf.lfPitchAndFamily = 0;
1005         if (EnumFontFamiliesEx(hdc, &lf, create_font_proc, (LPARAM)&hfont, 0))
1006         {
1007             skip("TrueType font for charset %u is not installed\n", c[i].cs);
1008             continue;
1009         }
1010
1011         memset(a, 0, sizeof a);
1012         memset(w, 0, sizeof w);
1013         hfont = SelectObject(hdc, hfont);
1014         ok(pGetCharABCWidthsA(hdc, c[i].a, c[i].a + 1, a) &&
1015            pGetCharABCWidthsW(hdc, c[i].w, c[i].w + 1, w) &&
1016            memcmp(a, w, sizeof a) == 0,
1017            "GetCharABCWidthsA and GetCharABCWidthsW should return same widths. charset = %u\n", c[i].cs);
1018
1019         memset(a, 0xbb, sizeof a);
1020         ret = pGetCharABCWidthsA(hdc, code, code, a);
1021         ok(ret, "GetCharABCWidthsA should have succeeded\n");
1022         memset(full, 0xcc, sizeof full);
1023         ret = pGetCharABCWidthsA(hdc, 0x00, code, full);
1024         ok(ret, "GetCharABCWidthsA should have succeeded\n");
1025         ok(memcmp(&a[0], &full[code], sizeof(ABC)) == 0,
1026            "GetCharABCWidthsA info should match. codepage = %u\n", c[i].cs);
1027
1028         for (j = 0; j < sizeof range / sizeof range[0]; ++j)
1029         {
1030             ret = pGetCharABCWidthsA(hdc, range[j].first, range[j].last, full);
1031             ok(ret == c[i].r[j], "GetCharABCWidthsA %x - %x should have %s\n",
1032                range[j].first, range[j].last, c[i].r[j] ? "succeeded" : "failed");
1033         }
1034
1035         hfont = SelectObject(hdc, hfont);
1036         DeleteObject(hfont);
1037     }
1038
1039     ReleaseDC(NULL, hdc);
1040 }
1041
1042 static void test_text_extents(void)
1043 {
1044     static const WCHAR wt[] = {'O','n','e','\n','t','w','o',' ','3',0};
1045     LPINT extents;
1046     INT i, len, fit1, fit2;
1047     LOGFONTA lf;
1048     TEXTMETRICA tm;
1049     HDC hdc;
1050     HFONT hfont;
1051     SIZE sz;
1052     SIZE sz1, sz2;
1053
1054     memset(&lf, 0, sizeof(lf));
1055     strcpy(lf.lfFaceName, "Arial");
1056     lf.lfHeight = 20;
1057
1058     hfont = CreateFontIndirectA(&lf);
1059     hdc = GetDC(0);
1060     hfont = SelectObject(hdc, hfont);
1061     GetTextMetricsA(hdc, &tm);
1062     GetTextExtentPointA(hdc, "o", 1, &sz);
1063     ok(sz.cy == tm.tmHeight, "cy %d tmHeight %d\n", sz.cy, tm.tmHeight);
1064
1065     SetLastError(0xdeadbeef);
1066     GetTextExtentExPointW(hdc, wt, 1, 1, &fit1, &fit2, &sz1);
1067     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1068     {
1069         win_skip("Skipping remainder of text extents test on a Win9x platform\n");
1070         hfont = SelectObject(hdc, hfont);
1071         DeleteObject(hfont);
1072         ReleaseDC(0, hdc);
1073         return;
1074     }
1075
1076     len = lstrlenW(wt);
1077     extents = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof extents[0]);
1078     extents[0] = 1;         /* So that the increasing sequence test will fail
1079                                if the extents array is untouched.  */
1080     GetTextExtentExPointW(hdc, wt, len, 32767, &fit1, extents, &sz1);
1081     GetTextExtentPointW(hdc, wt, len, &sz2);
1082     ok(sz1.cy == sz2.cy,
1083        "cy from GetTextExtentExPointW (%d) and GetTextExtentPointW (%d) differ\n", sz1.cy, sz2.cy);
1084     /* Because of the '\n' in the string GetTextExtentExPoint and
1085        GetTextExtentPoint return different widths under Win2k, but
1086        under WinXP they return the same width.  So we don't test that
1087        here. */
1088
1089     for (i = 1; i < len; ++i)
1090         ok(extents[i-1] <= extents[i],
1091            "GetTextExtentExPointW generated a non-increasing sequence of partial extents (at position %d)\n",
1092            i);
1093     ok(extents[len-1] == sz1.cx, "GetTextExtentExPointW extents and size don't match\n");
1094     ok(0 <= fit1 && fit1 <= len, "GetTextExtentExPointW generated illegal value %d for fit\n", fit1);
1095     ok(0 < fit1, "GetTextExtentExPointW says we can't even fit one letter in 32767 logical units\n");
1096     GetTextExtentExPointW(hdc, wt, len, extents[2], &fit2, NULL, &sz2);
1097     ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy, "GetTextExtentExPointW returned different sizes for the same string\n");
1098     ok(fit2 == 3, "GetTextExtentExPointW extents isn't consistent with fit\n");
1099     GetTextExtentExPointW(hdc, wt, len, extents[2]-1, &fit2, NULL, &sz2);
1100     ok(fit2 == 2, "GetTextExtentExPointW extents isn't consistent with fit\n");
1101     GetTextExtentExPointW(hdc, wt, 2, 0, NULL, extents + 2, &sz2);
1102     ok(extents[0] == extents[2] && extents[1] == extents[3],
1103        "GetTextExtentExPointW with lpnFit == NULL returns incorrect results\n");
1104     GetTextExtentExPointW(hdc, wt, 2, 0, NULL, NULL, &sz1);
1105     ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy,
1106        "GetTextExtentExPointW with lpnFit and alpDx both NULL returns incorrect results\n");
1107     HeapFree(GetProcessHeap(), 0, extents);
1108
1109     hfont = SelectObject(hdc, hfont);
1110     DeleteObject(hfont);
1111     ReleaseDC(NULL, hdc);
1112 }
1113
1114 static void test_GetGlyphIndices(void)
1115 {
1116     HDC      hdc;
1117     HFONT    hfont;
1118     DWORD    charcount;
1119     LOGFONTA lf;
1120     DWORD    flags = 0;
1121     WCHAR    testtext[] = {'T','e','s','t',0xffff,0};
1122     WORD     glyphs[(sizeof(testtext)/2)-1];
1123     TEXTMETRIC textm;
1124     HFONT hOldFont;
1125
1126     if (!pGetGlyphIndicesW) {
1127         win_skip("GetGlyphIndicesW not available on platform\n");
1128         return;
1129     }
1130
1131     hdc = GetDC(0);
1132
1133     memset(&lf, 0, sizeof(lf));
1134     strcpy(lf.lfFaceName, "System");
1135     lf.lfHeight = 16;
1136     lf.lfCharSet = ANSI_CHARSET;
1137
1138     hfont = CreateFontIndirectA(&lf);
1139     ok(hfont != 0, "CreateFontIndirectEx failed\n");
1140     ok(GetTextMetrics(hdc, &textm), "GetTextMetric failed\n");
1141     if (textm.tmCharSet == ANSI_CHARSET)
1142     {
1143         flags |= GGI_MARK_NONEXISTING_GLYPHS;
1144         charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1145         ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1146         ok((glyphs[4] == 0x001f || glyphs[4] == 0xffff /* Vista */), "GetGlyphIndicesW should have returned a nonexistent char not %04x\n", glyphs[4]);
1147         flags = 0;
1148         charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1149         ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1150         ok(glyphs[4] == textm.tmDefaultChar, "GetGlyphIndicesW should have returned a %04x not %04x\n",
1151                         textm.tmDefaultChar, glyphs[4]);
1152     }
1153     else
1154         /* FIXME: Write tests for non-ANSI charsets. */
1155         skip("GetGlyphIndices System font tests only for ANSI_CHARSET\n");
1156
1157     if(!is_font_installed("Tahoma"))
1158     {
1159         skip("Tahoma is not installed so skipping this test\n");
1160         return;
1161     }
1162     memset(&lf, 0, sizeof(lf));
1163     strcpy(lf.lfFaceName, "Tahoma");
1164     lf.lfHeight = 20;
1165
1166     hfont = CreateFontIndirectA(&lf);
1167     hOldFont = SelectObject(hdc, hfont);
1168     ok(GetTextMetrics(hdc, &textm), "GetTextMetric failed\n");
1169     flags |= GGI_MARK_NONEXISTING_GLYPHS;
1170     charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1171     ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1172     ok(glyphs[4] == 0xffff, "GetGlyphIndicesW should have returned 0xffff char not %04x\n", glyphs[4]);
1173     flags = 0;
1174     testtext[0] = textm.tmDefaultChar;
1175     charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1176     ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1177     ok(glyphs[0] == 0, "GetGlyphIndicesW for tmDefaultChar should be 0 not %04x\n", glyphs[0]);
1178     ok(glyphs[4] == 0, "GetGlyphIndicesW should have returned 0 not %04x\n", glyphs[4]);
1179     DeleteObject(SelectObject(hdc, hOldFont));
1180 }
1181
1182 static void test_GetKerningPairs(void)
1183 {
1184     static const struct kerning_data
1185     {
1186         const char face_name[LF_FACESIZE];
1187         LONG height;
1188         /* some interesting fields from OUTLINETEXTMETRIC */
1189         LONG tmHeight, tmAscent, tmDescent;
1190         UINT otmEMSquare;
1191         INT  otmAscent;
1192         INT  otmDescent;
1193         UINT otmLineGap;
1194         UINT otmsCapEmHeight;
1195         UINT otmsXHeight;
1196         INT  otmMacAscent;
1197         INT  otmMacDescent;
1198         UINT otmMacLineGap;
1199         UINT otmusMinimumPPEM;
1200         /* small subset of kerning pairs to test */
1201         DWORD total_kern_pairs;
1202         const KERNINGPAIR kern_pair[26];
1203     } kd[] =
1204     {
1205         {"Arial", 12, 12, 9, 3,
1206                   2048, 7, -2, 1, 5, 2, 8, -2, 0, 9,
1207                   26,
1208             {
1209                 {' ','A',-1},{' ','T',0},{' ','Y',0},{'1','1',-1},
1210                 {'A',' ',-1},{'A','T',-1},{'A','V',-1},{'A','W',0},
1211                 {'A','Y',-1},{'A','v',0},{'A','w',0},{'A','y',0},
1212                 {'F',',',-1},{'F','.',-1},{'F','A',-1},{'L',' ',0},
1213                 {'L','T',-1},{'L','V',-1},{'L','W',-1},{'L','Y',-1},
1214                 {915,912,+1},{915,913,-1},{910,912,+1},{910,913,-1},
1215                 {933,970,+1},{933,972,-1}
1216                 }
1217         },
1218         {"Arial", -34, 39, 32, 7,
1219                   2048, 25, -7, 5, 17, 9, 31, -7, 1, 9,
1220                   26,
1221             {
1222                 {' ','A',-2},{' ','T',-1},{' ','Y',-1},{'1','1',-3},
1223                 {'A',' ',-2},{'A','T',-3},{'A','V',-3},{'A','W',-1},
1224                 {'A','Y',-3},{'A','v',-1},{'A','w',-1},{'A','y',-1},
1225                 {'F',',',-4},{'F','.',-4},{'F','A',-2},{'L',' ',-1},
1226                 {'L','T',-3},{'L','V',-3},{'L','W',-3},{'L','Y',-3},
1227                 {915,912,+3},{915,913,-3},{910,912,+3},{910,913,-3},
1228                 {933,970,+2},{933,972,-3}
1229             }
1230         },
1231         { "Arial", 120, 120, 97, 23,
1232                    2048, 79, -23, 16, 54, 27, 98, -23, 4, 9,
1233                    26,
1234             {
1235                 {' ','A',-6},{' ','T',-2},{' ','Y',-2},{'1','1',-8},
1236                 {'A',' ',-6},{'A','T',-8},{'A','V',-8},{'A','W',-4},
1237                 {'A','Y',-8},{'A','v',-2},{'A','w',-2},{'A','y',-2},
1238                 {'F',',',-12},{'F','.',-12},{'F','A',-6},{'L',' ',-4},
1239                 {'L','T',-8},{'L','V',-8},{'L','W',-8},{'L','Y',-8},
1240                 {915,912,+9},{915,913,-10},{910,912,+9},{910,913,-8},
1241                 {933,970,+6},{933,972,-10}
1242             }
1243         },
1244 #if 0 /* this set fails due to +1/-1 errors (rounding bug?), needs investigation. */
1245         { "Arial", 1024 /* usually 1/2 of EM Square */, 1024, 830, 194,
1246                    2048, 668, -193, 137, 459, 229, 830, -194, 30, 9,
1247                    26,
1248             {
1249                 {' ','A',-51},{' ','T',-17},{' ','Y',-17},{'1','1',-68},
1250                 {'A',' ',-51},{'A','T',-68},{'A','V',-68},{'A','W',-34},
1251                 {'A','Y',-68},{'A','v',-17},{'A','w',-17},{'A','y',-17},
1252                 {'F',',',-102},{'F','.',-102},{'F','A',-51},{'L',' ',-34},
1253                 {'L','T',-68},{'L','V',-68},{'L','W',-68},{'L','Y',-68},
1254                 {915,912,+73},{915,913,-84},{910,912,+76},{910,913,-68},
1255                 {933,970,+54},{933,972,-83}
1256             }
1257         }
1258 #endif
1259     };
1260     LOGFONT lf;
1261     HFONT hfont, hfont_old;
1262     KERNINGPAIR *kern_pair;
1263     HDC hdc;
1264     DWORD total_kern_pairs, ret, i, n, matches;
1265
1266     hdc = GetDC(0);
1267
1268     /* GetKerningPairsA maps unicode set of kerning pairs to current code page
1269      * which may render this test unusable, so we're trying to avoid that.
1270      */
1271     SetLastError(0xdeadbeef);
1272     GetKerningPairsW(hdc, 0, NULL);
1273     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1274     {
1275         win_skip("Skipping the GetKerningPairs test on a Win9x platform\n");
1276         ReleaseDC(0, hdc);
1277         return;
1278     }
1279
1280     for (i = 0; i < sizeof(kd)/sizeof(kd[0]); i++)
1281     {
1282         OUTLINETEXTMETRICW otm;
1283         UINT uiRet;
1284
1285         if (!is_font_installed(kd[i].face_name))
1286         {
1287             trace("%s is not installed so skipping this test\n", kd[i].face_name);
1288             continue;
1289         }
1290
1291         trace("testing font %s, height %d\n", kd[i].face_name, kd[i].height);
1292
1293         memset(&lf, 0, sizeof(lf));
1294         strcpy(lf.lfFaceName, kd[i].face_name);
1295         lf.lfHeight = kd[i].height;
1296         hfont = CreateFontIndirect(&lf);
1297         assert(hfont != 0);
1298
1299         hfont_old = SelectObject(hdc, hfont);
1300
1301         SetLastError(0xdeadbeef);
1302         otm.otmSize = sizeof(otm); /* just in case for Win9x compatibility */
1303         uiRet = GetOutlineTextMetricsW(hdc, sizeof(otm), &otm);
1304         ok(uiRet == sizeof(otm), "GetOutlineTextMetricsW error %d\n", GetLastError());
1305
1306         ok(match_off_by_1(kd[i].tmHeight, otm.otmTextMetrics.tmHeight), "expected %d, got %d\n",
1307            kd[i].tmHeight, otm.otmTextMetrics.tmHeight);
1308         ok(match_off_by_1(kd[i].tmAscent, otm.otmTextMetrics.tmAscent), "expected %d, got %d\n",
1309            kd[i].tmAscent, otm.otmTextMetrics.tmAscent);
1310         ok(kd[i].tmDescent == otm.otmTextMetrics.tmDescent, "expected %d, got %d\n",
1311            kd[i].tmDescent, otm.otmTextMetrics.tmDescent);
1312
1313         ok(kd[i].otmEMSquare == otm.otmEMSquare, "expected %u, got %u\n",
1314            kd[i].otmEMSquare, otm.otmEMSquare);
1315         ok(kd[i].otmAscent == otm.otmAscent, "expected %d, got %d\n",
1316            kd[i].otmAscent, otm.otmAscent);
1317         ok(kd[i].otmDescent == otm.otmDescent, "expected %d, got %d\n",
1318            kd[i].otmDescent, otm.otmDescent);
1319         ok(kd[i].otmLineGap == otm.otmLineGap, "expected %u, got %u\n",
1320            kd[i].otmLineGap, otm.otmLineGap);
1321         ok(near_match(kd[i].otmMacDescent, otm.otmMacDescent), "expected %d, got %d\n",
1322            kd[i].otmMacDescent, otm.otmMacDescent);
1323         ok(near_match(kd[i].otmMacAscent, otm.otmMacAscent), "expected %d, got %d\n",
1324            kd[i].otmMacAscent, otm.otmMacAscent);
1325 todo_wine {
1326         ok(kd[i].otmsCapEmHeight == otm.otmsCapEmHeight, "expected %u, got %u\n",
1327            kd[i].otmsCapEmHeight, otm.otmsCapEmHeight);
1328         ok(kd[i].otmsXHeight == otm.otmsXHeight, "expected %u, got %u\n",
1329            kd[i].otmsXHeight, otm.otmsXHeight);
1330         /* FIXME: this one sometimes succeeds due to expected 0, enable it when removing todo */
1331         if (0) ok(kd[i].otmMacLineGap == otm.otmMacLineGap, "expected %u, got %u\n",
1332            kd[i].otmMacLineGap, otm.otmMacLineGap);
1333         ok(kd[i].otmusMinimumPPEM == otm.otmusMinimumPPEM, "expected %u, got %u\n",
1334            kd[i].otmusMinimumPPEM, otm.otmusMinimumPPEM);
1335 }
1336
1337         total_kern_pairs = GetKerningPairsW(hdc, 0, NULL);
1338         trace("total_kern_pairs %u\n", total_kern_pairs);
1339         kern_pair = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pair));
1340
1341 #if 0 /* Win98 (GetKerningPairsA) and XP behave differently here, the test passes on XP */
1342         SetLastError(0xdeadbeef);
1343         ret = GetKerningPairsW(hdc, 0, kern_pair);
1344         ok(GetLastError() == ERROR_INVALID_PARAMETER,
1345            "got error %ld, expected ERROR_INVALID_PARAMETER\n", GetLastError());
1346         ok(ret == 0, "got %lu, expected 0\n", ret);
1347 #endif
1348
1349         ret = GetKerningPairsW(hdc, 100, NULL);
1350         ok(ret == total_kern_pairs, "got %u, expected %u\n", ret, total_kern_pairs);
1351
1352         ret = GetKerningPairsW(hdc, total_kern_pairs/2, kern_pair);
1353         ok(ret == total_kern_pairs/2, "got %u, expected %u\n", ret, total_kern_pairs/2);
1354
1355         ret = GetKerningPairsW(hdc, total_kern_pairs, kern_pair);
1356         ok(ret == total_kern_pairs, "got %u, expected %u\n", ret, total_kern_pairs);
1357
1358         matches = 0;
1359
1360         for (n = 0; n < ret; n++)
1361         {
1362             DWORD j;
1363 #if 0
1364             if (kern_pair[n].wFirst < 127 && kern_pair[n].wSecond < 127)
1365                 trace("{'%c','%c',%d},\n",
1366                       kern_pair[n].wFirst, kern_pair[n].wSecond, kern_pair[n].iKernAmount);
1367 #endif
1368             for (j = 0; j < kd[i].total_kern_pairs; j++)
1369             {
1370                 if (kern_pair[n].wFirst == kd[i].kern_pair[j].wFirst &&
1371                     kern_pair[n].wSecond == kd[i].kern_pair[j].wSecond)
1372                 {
1373                     ok(kern_pair[n].iKernAmount == kd[i].kern_pair[j].iKernAmount,
1374                        "pair %d:%d got %d, expected %d\n",
1375                        kern_pair[n].wFirst, kern_pair[n].wSecond,
1376                        kern_pair[n].iKernAmount, kd[i].kern_pair[j].iKernAmount);
1377                     matches++;
1378                 }
1379             }
1380         }
1381
1382         ok(matches == kd[i].total_kern_pairs, "got matches %u, expected %u\n",
1383            matches, kd[i].total_kern_pairs);
1384
1385         HeapFree(GetProcessHeap(), 0, kern_pair);
1386
1387         SelectObject(hdc, hfont_old);
1388         DeleteObject(hfont);
1389     }
1390
1391     ReleaseDC(0, hdc);
1392 }
1393
1394 static void test_height_selection(void)
1395 {
1396     static const struct font_data
1397     {
1398         const char face_name[LF_FACESIZE];
1399         int requested_height;
1400         int weight, height, ascent, descent, int_leading, ext_leading, dpi;
1401     } fd[] =
1402     {
1403         {"Tahoma", -12, FW_NORMAL, 14, 12, 2, 2, 0, 96 },
1404         {"Tahoma", -24, FW_NORMAL, 29, 24, 5, 5, 0, 96 },
1405         {"Tahoma", -48, FW_NORMAL, 58, 48, 10, 10, 0, 96 },
1406         {"Tahoma", -96, FW_NORMAL, 116, 96, 20, 20, 0, 96 },
1407         {"Tahoma", -192, FW_NORMAL, 232, 192, 40, 40, 0, 96 },
1408         {"Tahoma", 12, FW_NORMAL, 12, 10, 2, 2, 0, 96 },
1409         {"Tahoma", 24, FW_NORMAL, 24, 20, 4, 4, 0, 96 },
1410         {"Tahoma", 48, FW_NORMAL, 48, 40, 8, 8, 0, 96 },
1411         {"Tahoma", 96, FW_NORMAL, 96, 80, 16, 17, 0, 96 },
1412         {"Tahoma", 192, FW_NORMAL, 192, 159, 33, 33, 0, 96 }
1413     };
1414     HDC hdc;
1415     LOGFONT lf;
1416     HFONT hfont, old_hfont;
1417     TEXTMETRIC tm;
1418     INT ret, i;
1419
1420     hdc = CreateCompatibleDC(0);
1421     assert(hdc);
1422
1423     for (i = 0; i < sizeof(fd)/sizeof(fd[0]); i++)
1424     {
1425         if (!is_truetype_font_installed(fd[i].face_name))
1426         {
1427             skip("%s is not installed\n", fd[i].face_name);
1428             continue;
1429         }
1430
1431         memset(&lf, 0, sizeof(lf));
1432         lf.lfHeight = fd[i].requested_height;
1433         lf.lfWeight = fd[i].weight;
1434         strcpy(lf.lfFaceName, fd[i].face_name);
1435
1436         hfont = CreateFontIndirect(&lf);
1437         assert(hfont);
1438
1439         old_hfont = SelectObject(hdc, hfont);
1440         ret = GetTextMetrics(hdc, &tm);
1441         ok(ret, "GetTextMetrics error %d\n", GetLastError());
1442         if(fd[i].dpi == tm.tmDigitizedAspectX)
1443         {
1444             trace("found font %s, height %d charset %x dpi %d\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet, fd[i].dpi);
1445             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);
1446             ok(match_off_by_1(tm.tmHeight, fd[i].height), "%s(%d): tm.tmHeight %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmHeight, fd[i].height);
1447             ok(match_off_by_1(tm.tmAscent, fd[i].ascent), "%s(%d): tm.tmAscent %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmAscent, fd[i].ascent);
1448             ok(match_off_by_1(tm.tmDescent, fd[i].descent), "%s(%d): tm.tmDescent %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmDescent, fd[i].descent);
1449 #if 0 /* FIXME: calculation of tmInternalLeading in Wine doesn't match what Windows does */
1450             ok(tm.tmInternalLeading == fd[i].int_leading, "%s(%d): tm.tmInternalLeading %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmInternalLeading, fd[i].int_leading);
1451 #endif
1452             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);
1453         }
1454
1455         SelectObject(hdc, old_hfont);
1456         DeleteObject(hfont);
1457     }
1458
1459     DeleteDC(hdc);
1460 }
1461
1462 static void test_GetOutlineTextMetrics(void)
1463 {
1464     OUTLINETEXTMETRIC *otm;
1465     LOGFONT lf;
1466     HFONT hfont, hfont_old;
1467     HDC hdc;
1468     DWORD ret, otm_size;
1469     LPSTR unset_ptr;
1470
1471     if (!is_font_installed("Arial"))
1472     {
1473         skip("Arial is not installed\n");
1474         return;
1475     }
1476
1477     hdc = GetDC(0);
1478
1479     memset(&lf, 0, sizeof(lf));
1480     strcpy(lf.lfFaceName, "Arial");
1481     lf.lfHeight = -13;
1482     lf.lfWeight = FW_NORMAL;
1483     lf.lfPitchAndFamily = DEFAULT_PITCH;
1484     lf.lfQuality = PROOF_QUALITY;
1485     hfont = CreateFontIndirect(&lf);
1486     assert(hfont != 0);
1487
1488     hfont_old = SelectObject(hdc, hfont);
1489     otm_size = GetOutlineTextMetrics(hdc, 0, NULL);
1490     trace("otm buffer size %u (0x%x)\n", otm_size, otm_size);
1491
1492     otm = HeapAlloc(GetProcessHeap(), 0, otm_size);
1493
1494     memset(otm, 0xAA, otm_size);
1495     SetLastError(0xdeadbeef);
1496     otm->otmSize = sizeof(*otm); /* just in case for Win9x compatibility */
1497     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1498     ok(ret == 1 /* Win9x */ ||
1499        ret == otm->otmSize /* XP*/,
1500        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1501     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1502     {
1503         ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
1504         ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
1505         ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
1506         ok(otm->otmpFullName == NULL, "expected NULL got %p\n", otm->otmpFullName);
1507     }
1508
1509     memset(otm, 0xAA, otm_size);
1510     SetLastError(0xdeadbeef);
1511     otm->otmSize = otm_size; /* just in case for Win9x compatibility */
1512     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1513     ok(ret == 1 /* Win9x */ ||
1514        ret == otm->otmSize /* XP*/,
1515        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1516     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1517     {
1518         ok(otm->otmpFamilyName != NULL, "expected not NULL got %p\n", otm->otmpFamilyName);
1519         ok(otm->otmpFaceName != NULL, "expected not NULL got %p\n", otm->otmpFaceName);
1520         ok(otm->otmpStyleName != NULL, "expected not NULL got %p\n", otm->otmpStyleName);
1521         ok(otm->otmpFullName != NULL, "expected not NULL got %p\n", otm->otmpFullName);
1522     }
1523
1524     /* ask about truncated data */
1525     memset(otm, 0xAA, otm_size);
1526     memset(&unset_ptr, 0xAA, sizeof(unset_ptr));
1527     SetLastError(0xdeadbeef);
1528     otm->otmSize = sizeof(*otm) - sizeof(LPSTR); /* just in case for Win9x compatibility */
1529     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1530     ok(ret == 1 /* Win9x */ ||
1531        ret == otm->otmSize /* XP*/,
1532        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1533     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1534     {
1535         ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
1536         ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
1537         ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
1538     }
1539     ok(otm->otmpFullName == unset_ptr, "expected %p got %p\n", unset_ptr, otm->otmpFullName);
1540
1541     HeapFree(GetProcessHeap(), 0, otm);
1542
1543     SelectObject(hdc, hfont_old);
1544     DeleteObject(hfont);
1545
1546     ReleaseDC(0, hdc);
1547 }
1548
1549 static void testJustification(HDC hdc, PSTR str, RECT *clientArea)
1550 {
1551     INT         y,
1552                 breakCount,
1553                 justifiedWidth = 0, /* to test GetTextExtentExPointW() */
1554                 areaWidth = clientArea->right - clientArea->left,
1555                 nErrors = 0, e;
1556     BOOL        lastExtent = FALSE;
1557     PSTR        pFirstChar, pLastChar;
1558     SIZE        size;
1559     TEXTMETRICA tm;
1560     struct err
1561     {
1562         char extent[100];
1563         int  GetTextExtentExPointWWidth;
1564     } error[10];
1565
1566     GetTextMetricsA(hdc, &tm);
1567     y = clientArea->top;
1568     do {
1569         breakCount = 0;
1570         while (*str == tm.tmBreakChar) str++; /* skip leading break chars */
1571         pFirstChar = str;
1572
1573         do {
1574             pLastChar = str;
1575
1576             /* if not at the end of the string, ... */
1577             if (*str == '\0') break;
1578             /* ... add the next word to the current extent */
1579             while (*str != '\0' && *str++ != tm.tmBreakChar);
1580             breakCount++;
1581             SetTextJustification(hdc, 0, 0);
1582             GetTextExtentPoint32(hdc, pFirstChar, str - pFirstChar - 1, &size);
1583         } while ((int) size.cx < areaWidth);
1584
1585         /* ignore trailing break chars */
1586         breakCount--;
1587         while (*(pLastChar - 1) == tm.tmBreakChar)
1588         {
1589             pLastChar--;
1590             breakCount--;
1591         }
1592
1593         if (*str == '\0' || breakCount <= 0) pLastChar = str;
1594
1595         SetTextJustification(hdc, 0, 0);
1596         GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
1597
1598         /* do not justify the last extent */
1599         if (*str != '\0' && breakCount > 0)
1600         {
1601             SetTextJustification(hdc, areaWidth - size.cx, breakCount);
1602             GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
1603             justifiedWidth = size.cx;
1604         }
1605         else lastExtent = TRUE;
1606
1607         /* catch errors and report them */
1608         if (!lastExtent && (justifiedWidth != areaWidth))
1609         {
1610             memset(error[nErrors].extent, 0, 100);
1611             memcpy(error[nErrors].extent, pFirstChar, pLastChar - pFirstChar);
1612             error[nErrors].GetTextExtentExPointWWidth = justifiedWidth;
1613             nErrors++;
1614         }
1615
1616         y += size.cy;
1617         str = pLastChar;
1618     } while (*str && y < clientArea->bottom);
1619
1620     for (e = 0; e < nErrors; e++)
1621     {
1622         /* The width returned by GetTextExtentPoint32() is exactly the same
1623            returned by GetTextExtentExPointW() - see dlls/gdi32/font.c */
1624         ok(error[e].GetTextExtentExPointWWidth == areaWidth,
1625             "GetTextExtentPointW() for \"%s\" should have returned a width of %d, not %d.\n",
1626             error[e].extent, areaWidth, error[e].GetTextExtentExPointWWidth);
1627     }
1628 }
1629
1630 static void test_SetTextJustification(void)
1631 {
1632     HDC hdc;
1633     RECT clientArea;
1634     LOGFONTA lf;
1635     HFONT hfont;
1636     HWND hwnd;
1637     static char testText[] =
1638             "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
1639             "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
1640             "enim ad minim veniam, quis nostrud exercitation ullamco laboris "
1641             "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in "
1642             "reprehenderit in voluptate velit esse cillum dolore eu fugiat "
1643             "nulla pariatur. Excepteur sint occaecat cupidatat non proident, "
1644             "sunt in culpa qui officia deserunt mollit anim id est laborum.";
1645
1646     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0, 400,400, 0, 0, 0, NULL);
1647     GetClientRect( hwnd, &clientArea );
1648     hdc = GetDC( hwnd );
1649
1650     memset(&lf, 0, sizeof lf);
1651     lf.lfCharSet = ANSI_CHARSET;
1652     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1653     lf.lfWeight = FW_DONTCARE;
1654     lf.lfHeight = 20;
1655     lf.lfQuality = DEFAULT_QUALITY;
1656     lstrcpyA(lf.lfFaceName, "Times New Roman");
1657     hfont = create_font("Times New Roman", &lf);
1658     SelectObject(hdc, hfont);
1659
1660     testJustification(hdc, testText, &clientArea);
1661
1662     DeleteObject(hfont);
1663     ReleaseDC(hwnd, hdc);
1664     DestroyWindow(hwnd);
1665 }
1666
1667 static BOOL get_glyph_indices(INT charset, UINT code_page, WORD *idx, UINT count, BOOL unicode)
1668 {
1669     HDC hdc;
1670     LOGFONTA lf;
1671     HFONT hfont, hfont_old;
1672     CHARSETINFO csi;
1673     FONTSIGNATURE fs;
1674     INT cs;
1675     DWORD i, ret;
1676     char name[64];
1677
1678     assert(count <= 128);
1679
1680     memset(&lf, 0, sizeof(lf));
1681
1682     lf.lfCharSet = charset;
1683     lf.lfHeight = 10;
1684     lstrcpyA(lf.lfFaceName, "Arial");
1685     SetLastError(0xdeadbeef);
1686     hfont = CreateFontIndirectA(&lf);
1687     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
1688
1689     hdc = GetDC(0);
1690     hfont_old = SelectObject(hdc, hfont);
1691
1692     cs = GetTextCharsetInfo(hdc, &fs, 0);
1693     ok(cs == charset, "expected %d, got %d\n", charset, cs);
1694
1695     SetLastError(0xdeadbeef);
1696     ret = GetTextFaceA(hdc, sizeof(name), name);
1697     ok(ret, "GetTextFaceA error %u\n", GetLastError());
1698
1699     if (charset == SYMBOL_CHARSET)
1700     {
1701         ok(strcmp("Arial", name), "face name should NOT be Arial\n");
1702         ok(fs.fsCsb[0] & (1 << 31), "symbol encoding should be available\n");
1703     }
1704     else
1705     {
1706         ok(!strcmp("Arial", name), "face name should be Arial, not %s\n", name);
1707         ok(!(fs.fsCsb[0] & (1 << 31)), "symbol encoding should NOT be available\n");
1708     }
1709
1710     if (!TranslateCharsetInfo((DWORD *)(INT_PTR)cs, &csi, TCI_SRCCHARSET))
1711     {
1712         trace("Can't find codepage for charset %d\n", cs);
1713         ReleaseDC(0, hdc);
1714         return FALSE;
1715     }
1716     ok(csi.ciACP == code_page, "expected %d, got %d\n", code_page, csi.ciACP);
1717
1718     if (pGdiGetCodePage != NULL && pGdiGetCodePage(hdc) != code_page)
1719     {
1720         skip("Font code page %d, looking for code page %d\n",
1721              pGdiGetCodePage(hdc), code_page);
1722         ReleaseDC(0, hdc);
1723         return FALSE;
1724     }
1725
1726     if (unicode)
1727     {
1728         char ansi_buf[128];
1729         WCHAR unicode_buf[128];
1730
1731         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
1732
1733         MultiByteToWideChar(code_page, 0, ansi_buf, count, unicode_buf, count);
1734
1735         SetLastError(0xdeadbeef);
1736         ret = pGetGlyphIndicesW(hdc, unicode_buf, count, idx, 0);
1737         ok(ret == count, "GetGlyphIndicesW expected %d got %d, error %u\n",
1738            count, ret, GetLastError());
1739     }
1740     else
1741     {
1742         char ansi_buf[128];
1743
1744         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
1745
1746         SetLastError(0xdeadbeef);
1747         ret = pGetGlyphIndicesA(hdc, ansi_buf, count, idx, 0);
1748         ok(ret == count, "GetGlyphIndicesA expected %d got %d, error %u\n",
1749            count, ret, GetLastError());
1750     }
1751
1752     SelectObject(hdc, hfont_old);
1753     DeleteObject(hfont);
1754
1755     ReleaseDC(0, hdc);
1756
1757     return TRUE;
1758 }
1759
1760 static void test_font_charset(void)
1761 {
1762     static struct charset_data
1763     {
1764         INT charset;
1765         UINT code_page;
1766         WORD font_idxA[128], font_idxW[128];
1767     } cd[] =
1768     {
1769         { ANSI_CHARSET, 1252 },
1770         { RUSSIAN_CHARSET, 1251 },
1771         { SYMBOL_CHARSET, CP_SYMBOL } /* keep it as the last one */
1772     };
1773     int i;
1774
1775     if (!pGetGlyphIndicesA || !pGetGlyphIndicesW)
1776     {
1777         win_skip("Skipping the font charset test on a Win9x platform\n");
1778         return;
1779     }
1780
1781     if (!is_font_installed("Arial"))
1782     {
1783         skip("Arial is not installed\n");
1784         return;
1785     }
1786
1787     for (i = 0; i < sizeof(cd)/sizeof(cd[0]); i++)
1788     {
1789         if (cd[i].charset == SYMBOL_CHARSET)
1790         {
1791             if (!is_font_installed("Symbol") && !is_font_installed("Wingdings"))
1792             {
1793                 skip("Symbol or Wingdings is not installed\n");
1794                 break;
1795             }
1796         }
1797         if (get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxA, 128, FALSE) &&
1798             get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxW, 128, TRUE))
1799             ok(!memcmp(cd[i].font_idxA, cd[i].font_idxW, 128*sizeof(WORD)), "%d: indices don't match\n", i);
1800     }
1801
1802     ok(memcmp(cd[0].font_idxW, cd[1].font_idxW, 128*sizeof(WORD)), "0 vs 1: indices shouldn't match\n");
1803     if (i > 2)
1804     {
1805         ok(memcmp(cd[0].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "0 vs 2: indices shouldn't match\n");
1806         ok(memcmp(cd[1].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "1 vs 2: indices shouldn't match\n");
1807     }
1808     else
1809         skip("Symbol or Wingdings is not installed\n");
1810 }
1811
1812 static void test_GetFontUnicodeRanges(void)
1813 {
1814     LOGFONTA lf;
1815     HDC hdc;
1816     HFONT hfont, hfont_old;
1817     DWORD size;
1818     GLYPHSET *gs;
1819
1820     if (!pGetFontUnicodeRanges)
1821     {
1822         win_skip("GetFontUnicodeRanges not available before W2K\n");
1823         return;
1824     }
1825
1826     memset(&lf, 0, sizeof(lf));
1827     lstrcpyA(lf.lfFaceName, "Arial");
1828     hfont = create_font("Arial", &lf);
1829
1830     hdc = GetDC(0);
1831     hfont_old = SelectObject(hdc, hfont);
1832
1833     size = pGetFontUnicodeRanges(NULL, NULL);
1834     ok(!size, "GetFontUnicodeRanges succeeded unexpectedly\n");
1835
1836     size = pGetFontUnicodeRanges(hdc, NULL);
1837     ok(size, "GetFontUnicodeRanges failed unexpectedly\n");
1838
1839     gs = HeapAlloc(GetProcessHeap(), 0, size);
1840
1841     size = pGetFontUnicodeRanges(hdc, gs);
1842     ok(size, "GetFontUnicodeRanges failed\n");
1843 #if 0
1844     for (i = 0; i < gs->cRanges; i++)
1845         trace("%03d wcLow %04x cGlyphs %u\n", i, gs->ranges[i].wcLow, gs->ranges[i].cGlyphs);
1846 #endif
1847     trace("found %u ranges\n", gs->cRanges);
1848
1849     HeapFree(GetProcessHeap(), 0, gs);
1850
1851     SelectObject(hdc, hfont_old);
1852     DeleteObject(hfont);
1853     ReleaseDC(NULL, hdc);
1854 }
1855
1856 #define MAX_ENUM_FONTS 4096
1857
1858 struct enum_font_data
1859 {
1860     int total;
1861     LOGFONT lf[MAX_ENUM_FONTS];
1862 };
1863
1864 struct enum_font_dataW
1865 {
1866     int total;
1867     LOGFONTW lf[MAX_ENUM_FONTS];
1868 };
1869
1870 static INT CALLBACK arial_enum_proc(const LOGFONT *lf, const TEXTMETRIC *tm, DWORD type, LPARAM lParam)
1871 {
1872     struct enum_font_data *efd = (struct enum_font_data *)lParam;
1873
1874     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
1875
1876     if (type != TRUETYPE_FONTTYPE) return 1;
1877 #if 0
1878     trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
1879           lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
1880 #endif
1881     if (efd->total < MAX_ENUM_FONTS)
1882         efd->lf[efd->total++] = *lf;
1883     else
1884         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
1885
1886     return 1;
1887 }
1888
1889 static INT CALLBACK arial_enum_procw(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
1890 {
1891     struct enum_font_dataW *efd = (struct enum_font_dataW *)lParam;
1892
1893     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
1894
1895     if (type != TRUETYPE_FONTTYPE) return 1;
1896 #if 0
1897     trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
1898           lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
1899 #endif
1900     if (efd->total < MAX_ENUM_FONTS)
1901         efd->lf[efd->total++] = *lf;
1902     else
1903         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
1904
1905     return 1;
1906 }
1907
1908 static void get_charset_stats(struct enum_font_data *efd,
1909                               int *ansi_charset, int *symbol_charset,
1910                               int *russian_charset)
1911 {
1912     int i;
1913
1914     *ansi_charset = 0;
1915     *symbol_charset = 0;
1916     *russian_charset = 0;
1917
1918     for (i = 0; i < efd->total; i++)
1919     {
1920         switch (efd->lf[i].lfCharSet)
1921         {
1922         case ANSI_CHARSET:
1923             (*ansi_charset)++;
1924             break;
1925         case SYMBOL_CHARSET:
1926             (*symbol_charset)++;
1927             break;
1928         case RUSSIAN_CHARSET:
1929             (*russian_charset)++;
1930             break;
1931         }
1932     }
1933 }
1934
1935 static void get_charset_statsW(struct enum_font_dataW *efd,
1936                               int *ansi_charset, int *symbol_charset,
1937                               int *russian_charset)
1938 {
1939     int i;
1940
1941     *ansi_charset = 0;
1942     *symbol_charset = 0;
1943     *russian_charset = 0;
1944
1945     for (i = 0; i < efd->total; i++)
1946     {
1947         switch (efd->lf[i].lfCharSet)
1948         {
1949         case ANSI_CHARSET:
1950             (*ansi_charset)++;
1951             break;
1952         case SYMBOL_CHARSET:
1953             (*symbol_charset)++;
1954             break;
1955         case RUSSIAN_CHARSET:
1956             (*russian_charset)++;
1957             break;
1958         }
1959     }
1960 }
1961
1962 static void test_EnumFontFamilies(const char *font_name, INT font_charset)
1963 {
1964     struct enum_font_data efd;
1965     struct enum_font_dataW efdw;
1966     LOGFONT lf;
1967     HDC hdc;
1968     int i, ret, ansi_charset, symbol_charset, russian_charset;
1969
1970     trace("Testing font %s, charset %d\n", *font_name ? font_name : "<empty>", font_charset);
1971
1972     if (*font_name && !is_truetype_font_installed(font_name))
1973     {
1974         skip("%s is not installed\n", font_name);
1975         return;
1976     }
1977
1978     hdc = GetDC(0);
1979
1980     /* Observed behaviour: EnumFontFamilies enumerates aliases like "Arial Cyr"
1981      * while EnumFontFamiliesEx doesn't.
1982      */
1983     if (!*font_name && font_charset == DEFAULT_CHARSET) /* do it only once */
1984     {
1985         /*
1986          * Use EnumFontFamiliesW since win98 crashes when the
1987          *    second parameter is NULL using EnumFontFamilies
1988          */
1989         efdw.total = 0;
1990         SetLastError(0xdeadbeef);
1991         ret = EnumFontFamiliesW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw);
1992         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesW error %u\n", GetLastError());
1993         if(ret)
1994         {
1995             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
1996             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
1997                   ansi_charset, symbol_charset, russian_charset);
1998             ok(efdw.total > 0, "fonts enumerated: NULL\n");
1999             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
2000             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
2001             ok(russian_charset > 0 ||
2002                broken(russian_charset == 0), /* NT4 */
2003                "NULL family should enumerate RUSSIAN_CHARSET\n");
2004         }
2005
2006         efdw.total = 0;
2007         SetLastError(0xdeadbeef);
2008         ret = EnumFontFamiliesExW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw, 0);
2009         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesExW error %u\n", GetLastError());
2010         if(ret)
2011         {
2012             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
2013             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
2014                   ansi_charset, symbol_charset, russian_charset);
2015             ok(efdw.total > 0, "fonts enumerated: NULL\n");
2016             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
2017             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
2018             ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
2019         }
2020     }
2021
2022     efd.total = 0;
2023     SetLastError(0xdeadbeef);
2024     ret = EnumFontFamilies(hdc, font_name, arial_enum_proc, (LPARAM)&efd);
2025     ok(ret, "EnumFontFamilies error %u\n", GetLastError());
2026     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2027     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s\n",
2028           ansi_charset, symbol_charset, russian_charset,
2029           *font_name ? font_name : "<empty>");
2030     if (*font_name)
2031         ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
2032     else
2033         ok(!efd.total, "no fonts should be enumerated for empty font_name\n");
2034     for (i = 0; i < efd.total; i++)
2035     {
2036 /* FIXME: remove completely once Wine is fixed */
2037 if (efd.lf[i].lfCharSet != font_charset)
2038 {
2039 todo_wine
2040     ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2041 }
2042 else
2043         ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2044         ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2045            font_name, efd.lf[i].lfFaceName);
2046     }
2047
2048     memset(&lf, 0, sizeof(lf));
2049     lf.lfCharSet = ANSI_CHARSET;
2050     lstrcpy(lf.lfFaceName, font_name);
2051     efd.total = 0;
2052     SetLastError(0xdeadbeef);
2053     ret = EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2054     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2055     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2056     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s ANSI_CHARSET\n",
2057           ansi_charset, symbol_charset, russian_charset,
2058           *font_name ? font_name : "<empty>");
2059     if (font_charset == SYMBOL_CHARSET)
2060     {
2061         if (*font_name)
2062             ok(efd.total == 0, "no fonts should be enumerated: %s ANSI_CHARSET\n", font_name);
2063         else
2064             ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
2065     }
2066     else
2067     {
2068         ok(efd.total > 0, "no fonts enumerated: %s ANSI_CHARSET\n", font_name);
2069         for (i = 0; i < efd.total; i++)
2070         {
2071             ok(efd.lf[i].lfCharSet == ANSI_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2072             if (*font_name)
2073                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2074                    font_name, efd.lf[i].lfFaceName);
2075         }
2076     }
2077
2078     /* DEFAULT_CHARSET should enumerate all available charsets */
2079     memset(&lf, 0, sizeof(lf));
2080     lf.lfCharSet = DEFAULT_CHARSET;
2081     lstrcpy(lf.lfFaceName, font_name);
2082     efd.total = 0;
2083     SetLastError(0xdeadbeef);
2084     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2085     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2086     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2087     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s DEFAULT_CHARSET\n",
2088           ansi_charset, symbol_charset, russian_charset,
2089           *font_name ? font_name : "<empty>");
2090     ok(efd.total > 0, "no fonts enumerated: %s DEFAULT_CHARSET\n", font_name);
2091     for (i = 0; i < efd.total; i++)
2092     {
2093         if (*font_name)
2094             ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2095                font_name, efd.lf[i].lfFaceName);
2096     }
2097     if (*font_name)
2098     {
2099         switch (font_charset)
2100         {
2101         case ANSI_CHARSET:
2102             ok(ansi_charset > 0,
2103                "ANSI_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
2104             ok(!symbol_charset,
2105                "ANSI_CHARSET should NOT enumerate SYMBOL_CHARSET for %s\n", font_name);
2106             ok(russian_charset > 0,
2107                "ANSI_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
2108             break;
2109         case SYMBOL_CHARSET:
2110             ok(!ansi_charset,
2111                "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", font_name);
2112             ok(symbol_charset,
2113                "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
2114             ok(!russian_charset,
2115                "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", font_name);
2116             break;
2117         case DEFAULT_CHARSET:
2118             ok(ansi_charset > 0,
2119                "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
2120             ok(symbol_charset > 0,
2121                "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
2122             ok(russian_charset > 0,
2123                "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
2124             break;
2125         }
2126     }
2127     else
2128     {
2129         ok(ansi_charset > 0,
2130            "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2131         ok(symbol_charset > 0,
2132            "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2133         ok(russian_charset > 0,
2134            "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2135     }
2136
2137     memset(&lf, 0, sizeof(lf));
2138     lf.lfCharSet = SYMBOL_CHARSET;
2139     lstrcpy(lf.lfFaceName, font_name);
2140     efd.total = 0;
2141     SetLastError(0xdeadbeef);
2142     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2143     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2144     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2145     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s SYMBOL_CHARSET\n",
2146           ansi_charset, symbol_charset, russian_charset,
2147           *font_name ? font_name : "<empty>");
2148     if (*font_name && font_charset == ANSI_CHARSET)
2149         ok(efd.total == 0, "no fonts should be enumerated: %s SYMBOL_CHARSET\n", font_name);
2150     else
2151     {
2152         ok(efd.total > 0, "no fonts enumerated: %s SYMBOL_CHARSET\n", font_name);
2153         for (i = 0; i < efd.total; i++)
2154         {
2155             ok(efd.lf[i].lfCharSet == SYMBOL_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2156             if (*font_name)
2157                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2158                    font_name, efd.lf[i].lfFaceName);
2159         }
2160
2161         ok(!ansi_charset,
2162            "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2163         ok(symbol_charset > 0,
2164            "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2165         ok(!russian_charset,
2166            "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2167     }
2168
2169     ReleaseDC(0, hdc);
2170 }
2171
2172 static INT CALLBACK enum_font_data_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
2173 {
2174     struct enum_font_data *efd = (struct enum_font_data *)lParam;
2175
2176     if (type != TRUETYPE_FONTTYPE) return 1;
2177
2178     if (efd->total < MAX_ENUM_FONTS)
2179         efd->lf[efd->total++] = *lf;
2180     else
2181         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
2182
2183     return 1;
2184 }
2185
2186 static void test_EnumFontFamiliesEx_default_charset(void)
2187 {
2188     struct enum_font_data efd;
2189     LOGFONT gui_font, enum_font;
2190     DWORD ret;
2191     HDC hdc;
2192
2193     ret = GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(gui_font), &gui_font);
2194     ok(ret, "GetObject failed.\n");
2195     if (!ret)
2196         return;
2197
2198     efd.total = 0;
2199
2200     hdc = GetDC(0);
2201     memset(&enum_font, 0, sizeof(enum_font));
2202     lstrcpy(enum_font.lfFaceName, gui_font.lfFaceName);
2203     enum_font.lfCharSet = DEFAULT_CHARSET;
2204     EnumFontFamiliesEx(hdc, &enum_font, enum_font_data_proc, (LPARAM)&efd, 0);
2205     ReleaseDC(0, hdc);
2206
2207     if (efd.total == 0) {
2208         skip("'%s' is not found or not a TrueType font.\n", gui_font.lfFaceName);
2209         return;
2210     }
2211     trace("'%s' has %d charsets.\n", gui_font.lfFaceName, efd.total);
2212
2213     ok(efd.lf[0].lfCharSet == gui_font.lfCharSet,
2214        "(%s) got charset %d expected %d\n",
2215        efd.lf[0].lfFaceName, efd.lf[0].lfCharSet, gui_font.lfCharSet);
2216
2217     return;
2218 }
2219
2220 static void test_negative_width(HDC hdc, const LOGFONTA *lf)
2221 {
2222     HFONT hfont, hfont_prev;
2223     DWORD ret;
2224     GLYPHMETRICS gm1, gm2;
2225     LOGFONTA lf2 = *lf;
2226     WORD idx;
2227
2228     if(!pGetGlyphIndicesA)
2229         return;
2230
2231     /* negative widths are handled just as positive ones */
2232     lf2.lfWidth = -lf->lfWidth;
2233
2234     SetLastError(0xdeadbeef);
2235     hfont = CreateFontIndirectA(lf);
2236     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2237     check_font("original", lf, hfont);
2238
2239     hfont_prev = SelectObject(hdc, hfont);
2240
2241     ret = pGetGlyphIndicesA(hdc, "x", 1, &idx, GGI_MARK_NONEXISTING_GLYPHS);
2242     if (ret == GDI_ERROR || idx == 0xffff)
2243     {
2244         SelectObject(hdc, hfont_prev);
2245         DeleteObject(hfont);
2246         skip("Font %s doesn't contain 'x', skipping the test\n", lf->lfFaceName);
2247         return;
2248     }
2249
2250     /* filling with 0xaa causes false pass under WINEDEBUG=warn+heap */
2251     memset(&gm1, 0xab, sizeof(gm1));
2252     SetLastError(0xdeadbeef);
2253     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm1, 0, NULL, &mat);
2254     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
2255
2256     SelectObject(hdc, hfont_prev);
2257     DeleteObject(hfont);
2258
2259     SetLastError(0xdeadbeef);
2260     hfont = CreateFontIndirectA(&lf2);
2261     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2262     check_font("negative width", &lf2, hfont);
2263
2264     hfont_prev = SelectObject(hdc, hfont);
2265
2266     memset(&gm2, 0xbb, sizeof(gm2));
2267     SetLastError(0xdeadbeef);
2268     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm2, 0, NULL, &mat);
2269     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
2270
2271     SelectObject(hdc, hfont_prev);
2272     DeleteObject(hfont);
2273
2274     ok(gm1.gmBlackBoxX == gm2.gmBlackBoxX &&
2275        gm1.gmBlackBoxY == gm2.gmBlackBoxY &&
2276        gm1.gmptGlyphOrigin.x == gm2.gmptGlyphOrigin.x &&
2277        gm1.gmptGlyphOrigin.y == gm2.gmptGlyphOrigin.y &&
2278        gm1.gmCellIncX == gm2.gmCellIncX &&
2279        gm1.gmCellIncY == gm2.gmCellIncY,
2280        "gm1=%d,%d,%d,%d,%d,%d gm2=%d,%d,%d,%d,%d,%d\n",
2281        gm1.gmBlackBoxX, gm1.gmBlackBoxY, gm1.gmptGlyphOrigin.x,
2282        gm1.gmptGlyphOrigin.y, gm1.gmCellIncX, gm1.gmCellIncY,
2283        gm2.gmBlackBoxX, gm2.gmBlackBoxY, gm2.gmptGlyphOrigin.x,
2284        gm2.gmptGlyphOrigin.y, gm2.gmCellIncX, gm2.gmCellIncY);
2285 }
2286
2287 /* PANOSE is 10 bytes in size, need to pack the structure properly */
2288 #include "pshpack2.h"
2289 typedef struct
2290 {
2291     USHORT version;
2292     SHORT xAvgCharWidth;
2293     USHORT usWeightClass;
2294     USHORT usWidthClass;
2295     SHORT fsType;
2296     SHORT ySubscriptXSize;
2297     SHORT ySubscriptYSize;
2298     SHORT ySubscriptXOffset;
2299     SHORT ySubscriptYOffset;
2300     SHORT ySuperscriptXSize;
2301     SHORT ySuperscriptYSize;
2302     SHORT ySuperscriptXOffset;
2303     SHORT ySuperscriptYOffset;
2304     SHORT yStrikeoutSize;
2305     SHORT yStrikeoutPosition;
2306     SHORT sFamilyClass;
2307     PANOSE panose;
2308     ULONG ulUnicodeRange1;
2309     ULONG ulUnicodeRange2;
2310     ULONG ulUnicodeRange3;
2311     ULONG ulUnicodeRange4;
2312     CHAR achVendID[4];
2313     USHORT fsSelection;
2314     USHORT usFirstCharIndex;
2315     USHORT usLastCharIndex;
2316     /* According to the Apple spec, original version didn't have the below fields,
2317      * version numbers were taked from the OpenType spec.
2318      */
2319     /* version 0 (TrueType 1.5) */
2320     USHORT sTypoAscender;
2321     USHORT sTypoDescender;
2322     USHORT sTypoLineGap;
2323     USHORT usWinAscent;
2324     USHORT usWinDescent;
2325     /* version 1 (TrueType 1.66) */
2326     ULONG ulCodePageRange1;
2327     ULONG ulCodePageRange2;
2328     /* version 2 (OpenType 1.2) */
2329     SHORT sxHeight;
2330     SHORT sCapHeight;
2331     USHORT usDefaultChar;
2332     USHORT usBreakChar;
2333     USHORT usMaxContext;
2334 } TT_OS2_V2;
2335 #include "poppack.h"
2336
2337 #ifdef WORDS_BIGENDIAN
2338 #define GET_BE_WORD(x) (x)
2339 #define GET_BE_DWORD(x) (x)
2340 #else
2341 #define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
2342 #define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
2343 #endif
2344
2345 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
2346                     ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
2347                     ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
2348 #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
2349 #define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
2350 #define MS_NAME_TAG MS_MAKE_TAG('n','a','m','e')
2351
2352 typedef struct
2353 {
2354     USHORT version;
2355     USHORT num_tables;
2356 } cmap_header;
2357
2358 typedef struct
2359 {
2360     USHORT plat_id;
2361     USHORT enc_id;
2362     ULONG offset;
2363 } cmap_encoding_record;
2364
2365 typedef struct
2366 {
2367     USHORT format;
2368     USHORT length;
2369     USHORT language;
2370
2371     BYTE glyph_ids[256];
2372 } cmap_format_0;
2373
2374 typedef struct
2375 {
2376     USHORT format;
2377     USHORT length;
2378     USHORT language;
2379
2380     USHORT seg_countx2;
2381     USHORT search_range;
2382     USHORT entry_selector;
2383     USHORT range_shift;
2384
2385     USHORT end_count[1]; /* this is a variable-sized array of length seg_countx2 / 2 */
2386 /* Then follows:
2387     USHORT pad;
2388     USHORT start_count[seg_countx2 / 2];
2389     USHORT id_delta[seg_countx2 / 2];
2390     USHORT id_range_offset[seg_countx2 / 2];
2391     USHORT glyph_ids[];
2392 */
2393 } cmap_format_4;
2394
2395 typedef struct
2396 {
2397     USHORT end_count;
2398     USHORT start_count;
2399     USHORT id_delta;
2400     USHORT id_range_offset;
2401 } cmap_format_4_seg;
2402
2403 static void expect_ff(const TEXTMETRICA *tmA, const TT_OS2_V2 *os2, WORD family, const char *name)
2404 {
2405     ok((tmA->tmPitchAndFamily & 0xf0) == family ||
2406        broken(PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH),
2407        "%s: expected family %02x got %02x. panose %d-%d-%d-%d-...\n",
2408        name, family, tmA->tmPitchAndFamily, os2->panose.bFamilyType, os2->panose.bSerifStyle,
2409        os2->panose.bWeight, os2->panose.bProportion);
2410 }
2411
2412 static BOOL get_first_last_from_cmap0(void *ptr, DWORD *first, DWORD *last)
2413 {
2414     int i;
2415     cmap_format_0 *cmap = (cmap_format_0*)ptr;
2416
2417     *first = 256;
2418
2419     for(i = 0; i < 256; i++)
2420     {
2421         if(cmap->glyph_ids[i] == 0) continue;
2422         *last = i;
2423         if(*first == 256) *first = i;
2424     }
2425     if(*first == 256) return FALSE;
2426     return TRUE;
2427 }
2428
2429 static void get_seg4(cmap_format_4 *cmap, USHORT seg_num, cmap_format_4_seg *seg)
2430 {
2431     USHORT segs = GET_BE_WORD(cmap->seg_countx2) / 2;
2432     seg->end_count = GET_BE_WORD(cmap->end_count[seg_num]);
2433     seg->start_count = GET_BE_WORD(cmap->end_count[segs + 1 + seg_num]);
2434     seg->id_delta = GET_BE_WORD(cmap->end_count[2 * segs + 1 + seg_num]);
2435     seg->id_range_offset = GET_BE_WORD(cmap->end_count[3 * segs + 1 + seg_num]);
2436 }
2437
2438 static BOOL get_first_last_from_cmap4(void *ptr, DWORD *first, DWORD *last, DWORD limit)
2439 {
2440     int i;
2441     cmap_format_4 *cmap = (cmap_format_4*)ptr;
2442     USHORT seg_count = GET_BE_WORD(cmap->seg_countx2) / 2;
2443     USHORT const *glyph_ids = cmap->end_count + 4 * seg_count + 1;
2444
2445     *first = 0x10000;
2446
2447     for(i = 0; i < seg_count; i++)
2448     {
2449         DWORD code, index;
2450         cmap_format_4_seg seg;
2451
2452         get_seg4(cmap, i, &seg);
2453         for(code = seg.start_count; code <= seg.end_count; code++)
2454         {
2455             if(seg.id_range_offset == 0)
2456                 index = (seg.id_delta + code) & 0xffff;
2457             else
2458             {
2459                 index = seg.id_range_offset / 2
2460                     + code - seg.start_count
2461                     + i - seg_count;
2462
2463                 /* some fonts have broken last segment */
2464                 if ((char *)(glyph_ids + index + sizeof(*glyph_ids)) < (char *)ptr + limit)
2465                     index = GET_BE_WORD(glyph_ids[index]);
2466                 else
2467                 {
2468                     trace("segment %04x/%04x index %04x points to nowhere\n",
2469                           seg.start_count, seg.end_count, index);
2470                     index = 0;
2471                 }
2472                 if(index) index += seg.id_delta;
2473             }
2474             if(*first == 0x10000)
2475                 *last = *first = code;
2476             else if(index)
2477                 *last = code;
2478         }
2479     }
2480
2481     if(*first == 0x10000) return FALSE;
2482     return TRUE;
2483 }
2484
2485 static void *get_cmap(cmap_header *header, USHORT plat_id, USHORT enc_id)
2486 {
2487     USHORT i;
2488     cmap_encoding_record *record = (cmap_encoding_record *)(header + 1);
2489
2490     for(i = 0; i < GET_BE_WORD(header->num_tables); i++)
2491     {
2492         if(GET_BE_WORD(record->plat_id) == plat_id && GET_BE_WORD(record->enc_id) == enc_id)
2493             return (BYTE *)header + GET_BE_DWORD(record->offset);
2494         record++;
2495     }
2496     return NULL;
2497 }
2498
2499 typedef enum
2500 {
2501     cmap_none,
2502     cmap_ms_unicode,
2503     cmap_ms_symbol
2504 } cmap_type;
2505
2506 static BOOL get_first_last_from_cmap(HDC hdc, DWORD *first, DWORD *last, cmap_type *cmap_type)
2507 {
2508     LONG size, ret;
2509     cmap_header *header;
2510     void *cmap;
2511     BOOL r = FALSE;
2512     WORD format;
2513
2514     size = GetFontData(hdc, MS_CMAP_TAG, 0, NULL, 0);
2515     ok(size != GDI_ERROR, "no cmap table found\n");
2516     if(size == GDI_ERROR) return FALSE;
2517
2518     header = HeapAlloc(GetProcessHeap(), 0, size);
2519     ret = GetFontData(hdc, MS_CMAP_TAG, 0, header, size);
2520     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2521     ok(GET_BE_WORD(header->version) == 0, "got cmap version %d\n", GET_BE_WORD(header->version));
2522
2523     cmap = get_cmap(header, 3, 1);
2524     if(cmap)
2525         *cmap_type = cmap_ms_unicode;
2526     else
2527     {
2528         cmap = get_cmap(header, 3, 0);
2529         if(cmap) *cmap_type = cmap_ms_symbol;
2530     }
2531     if(!cmap)
2532     {
2533         *cmap_type = cmap_none;
2534         goto end;
2535     }
2536
2537     format = GET_BE_WORD(*(WORD *)cmap);
2538     switch(format)
2539     {
2540     case 0:
2541         r = get_first_last_from_cmap0(cmap, first, last);
2542         break;
2543     case 4:
2544         r = get_first_last_from_cmap4(cmap, first, last, size);
2545         break;
2546     default:
2547         trace("unhandled cmap format %d\n", format);
2548         break;
2549     }
2550
2551 end:
2552     HeapFree(GetProcessHeap(), 0, header);
2553     return r;
2554 }
2555
2556 #define TT_PLATFORM_MICROSOFT 3
2557 #define TT_MS_ID_UNICODE_CS 1
2558 #define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409
2559 #define TT_NAME_ID_FULL_NAME 4
2560
2561 static BOOL get_ttf_nametable_entry(HDC hdc, WORD name_id, char *out_buf, SIZE_T out_size)
2562 {
2563     struct sfnt_name_header
2564     {
2565         USHORT format;
2566         USHORT number_of_record;
2567         USHORT storage_offset;
2568     } *header;
2569     struct sfnt_name
2570     {
2571         USHORT platform_id;
2572         USHORT encoding_id;
2573         USHORT language_id;
2574         USHORT name_id;
2575         USHORT length;
2576         USHORT offset;
2577     } *entry;
2578     BOOL r = FALSE;
2579     LONG size, offset, length;
2580     LONG c, ret;
2581     WCHAR *name;
2582     BYTE *data;
2583     USHORT i;
2584
2585     size = GetFontData(hdc, MS_NAME_TAG, 0, NULL, 0);
2586     ok(size != GDI_ERROR, "no name table found\n");
2587     if(size == GDI_ERROR) return FALSE;
2588
2589     data = HeapAlloc(GetProcessHeap(), 0, size);
2590     ret = GetFontData(hdc, MS_NAME_TAG, 0, data, size);
2591     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2592
2593     header = (void *)data;
2594     header->format = GET_BE_WORD(header->format);
2595     header->number_of_record = GET_BE_WORD(header->number_of_record);
2596     header->storage_offset = GET_BE_WORD(header->storage_offset);
2597     if (header->format != 0)
2598     {
2599         trace("got format %u\n", header->format);
2600         goto out;
2601     }
2602     if (header->number_of_record == 0 || sizeof(*header) + header->number_of_record * sizeof(*entry) > size)
2603     {
2604         trace("number records out of range: %d\n", header->number_of_record);
2605         goto out;
2606     }
2607     if (header->storage_offset >= size)
2608     {
2609         trace("storage_offset %u > size %u\n", header->storage_offset, size);
2610         goto out;
2611     }
2612
2613     entry = (void *)&header[1];
2614     for (i = 0; i < header->number_of_record; i++)
2615     {
2616         if (GET_BE_WORD(entry[i].platform_id) != TT_PLATFORM_MICROSOFT ||
2617             GET_BE_WORD(entry[i].encoding_id) != TT_MS_ID_UNICODE_CS ||
2618             GET_BE_WORD(entry[i].language_id) != TT_MS_LANGID_ENGLISH_UNITED_STATES ||
2619             GET_BE_WORD(entry[i].name_id) != name_id)
2620         {
2621             continue;
2622         }
2623
2624         offset = header->storage_offset + GET_BE_WORD(entry[i].offset);
2625         length = GET_BE_WORD(entry[i].length);
2626         if (offset + length > size)
2627         {
2628             trace("entry %d is out of range\n", i);
2629             break;
2630         }
2631         if (length >= out_size)
2632         {
2633             trace("buffer too small for entry %d\n", i);
2634             break;
2635         }
2636
2637         name = (WCHAR *)(data + offset);
2638         for (c = 0; c < length / 2; c++)
2639             out_buf[c] = GET_BE_WORD(name[c]);
2640         out_buf[c] = 0;
2641
2642         r = TRUE;
2643         break;
2644     }
2645
2646 out:
2647     HeapFree(GetProcessHeap(), 0, data);
2648     return r;
2649 }
2650
2651 static void test_text_metrics(const LOGFONTA *lf)
2652 {
2653     HDC hdc;
2654     HFONT hfont, hfont_old;
2655     TEXTMETRICA tmA;
2656     TT_OS2_V2 tt_os2;
2657     LONG size, ret;
2658     const char *font_name = lf->lfFaceName;
2659     DWORD cmap_first = 0, cmap_last = 0;
2660     cmap_type cmap_type;
2661     BOOL sys_lang_non_english;
2662
2663     sys_lang_non_english = PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH;
2664     hdc = GetDC(0);
2665
2666     SetLastError(0xdeadbeef);
2667     hfont = CreateFontIndirectA(lf);
2668     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2669
2670     hfont_old = SelectObject(hdc, hfont);
2671
2672     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
2673     if (size == GDI_ERROR)
2674     {
2675         trace("OS/2 chunk was not found\n");
2676         goto end_of_test;
2677     }
2678     if (size > sizeof(tt_os2))
2679     {
2680         trace("got too large OS/2 chunk of size %u\n", size);
2681         size = sizeof(tt_os2);
2682     }
2683
2684     memset(&tt_os2, 0, sizeof(tt_os2));
2685     ret = GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size);
2686     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2687
2688     SetLastError(0xdeadbeef);
2689     ret = GetTextMetricsA(hdc, &tmA);
2690     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
2691
2692     if(!get_first_last_from_cmap(hdc, &cmap_first, &cmap_last, &cmap_type))
2693     {
2694         skip("Unable to retrieve first and last glyphs from cmap\n");
2695     }
2696     else
2697     {
2698         USHORT expect_first_A, expect_last_A, expect_break_A, expect_default_A;
2699         USHORT expect_first_W, expect_last_W, expect_break_W, expect_default_W;
2700         UINT os2_first_char, os2_last_char, default_char, break_char;
2701         USHORT version;
2702         TEXTMETRICW tmW;
2703
2704         version = GET_BE_WORD(tt_os2.version);
2705
2706         os2_first_char = GET_BE_WORD(tt_os2.usFirstCharIndex);
2707         os2_last_char = GET_BE_WORD(tt_os2.usLastCharIndex);
2708         default_char = GET_BE_WORD(tt_os2.usDefaultChar);
2709         break_char = GET_BE_WORD(tt_os2.usBreakChar);
2710
2711         trace("font %s charset %u: %x-%x (%x-%x) default %x break %x OS/2 version %u vendor %4.4s\n",
2712               font_name, lf->lfCharSet, os2_first_char, os2_last_char, cmap_first, cmap_last,
2713               default_char, break_char, version, (LPCSTR)&tt_os2.achVendID);
2714
2715         if (cmap_type == cmap_ms_symbol || (cmap_first >= 0xf000 && cmap_first < 0xf100))
2716         {
2717             expect_first_W    = 0;
2718             switch(GetACP())
2719             {
2720             case 1257:  /* Baltic */
2721                 expect_last_W = 0xf8fd;
2722                 break;
2723             default:
2724                 expect_last_W = 0xf0ff;
2725             }
2726             expect_break_W    = 0x20;
2727             expect_default_W  = expect_break_W - 1;
2728             expect_first_A    = 0x1e;
2729             expect_last_A     = min(os2_last_char - os2_first_char + 0x20, 0xff);
2730         }
2731         else
2732         {
2733             expect_first_W    = cmap_first;
2734             expect_last_W     = min(cmap_last, os2_last_char);
2735             if(os2_first_char <= 1)
2736                 expect_break_W = os2_first_char + 2;
2737             else if(os2_first_char > 0xff)
2738                 expect_break_W = 0x20;
2739             else
2740                 expect_break_W = os2_first_char;
2741             expect_default_W  = expect_break_W - 1;
2742             expect_first_A    = expect_default_W - 1;
2743             expect_last_A     = min(expect_last_W, 0xff);
2744         }
2745         expect_break_A    = expect_break_W;
2746         expect_default_A  = expect_default_W;
2747
2748         /* Wine currently uses SYMBOL_CHARSET to identify whether the ANSI metrics need special handling */
2749         if(cmap_type != cmap_ms_symbol && tmA.tmCharSet == SYMBOL_CHARSET && expect_first_A != 0x1e)
2750             todo_wine ok(tmA.tmFirstChar == expect_first_A ||
2751                          tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2752                          "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2753         else
2754             ok(tmA.tmFirstChar == expect_first_A ||
2755                tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2756                "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2757         if (pGdiGetCodePage == NULL || ! IsDBCSLeadByteEx(pGdiGetCodePage(hdc), tmA.tmLastChar))
2758             ok(tmA.tmLastChar == expect_last_A ||
2759                tmA.tmLastChar == 0xff /* win9x */,
2760                "A: tmLastChar for %s got %02x expected %02x\n", font_name, tmA.tmLastChar, expect_last_A);
2761         else
2762            skip("tmLastChar is DBCS lead byte\n");
2763         ok(tmA.tmBreakChar == expect_break_A, "A: tmBreakChar for %s got %02x expected %02x\n",
2764            font_name, tmA.tmBreakChar, expect_break_A);
2765         ok(tmA.tmDefaultChar == expect_default_A || broken(sys_lang_non_english),
2766            "A: tmDefaultChar for %s got %02x expected %02x\n",
2767            font_name, tmA.tmDefaultChar, expect_default_A);
2768
2769
2770         SetLastError(0xdeadbeef);
2771         ret = GetTextMetricsW(hdc, &tmW);
2772         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
2773            "GetTextMetricsW error %u\n", GetLastError());
2774         if (ret)
2775         {
2776             /* Wine uses the os2 first char */
2777             if(cmap_first != os2_first_char && cmap_type != cmap_ms_symbol)
2778                 todo_wine ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2779                              font_name, tmW.tmFirstChar, expect_first_W);
2780             else
2781                 ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2782                    font_name, tmW.tmFirstChar, expect_first_W);
2783
2784             /* Wine uses the os2 last char */
2785             if(expect_last_W != os2_last_char && cmap_type != cmap_ms_symbol)
2786                 todo_wine ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2787                              font_name, tmW.tmLastChar, expect_last_W);
2788             else
2789                 ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2790                    font_name, tmW.tmLastChar, expect_last_W);
2791             ok(tmW.tmBreakChar == expect_break_W, "W: tmBreakChar for %s got %02x expected %02x\n",
2792                font_name, tmW.tmBreakChar, expect_break_W);
2793             ok(tmW.tmDefaultChar == expect_default_W || broken(sys_lang_non_english),
2794                "W: tmDefaultChar for %s got %02x expected %02x\n",
2795                font_name, tmW.tmDefaultChar, expect_default_W);
2796
2797             /* Test the aspect ratio while we have tmW */
2798             ret = GetDeviceCaps(hdc, LOGPIXELSX);
2799             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectX %u != %u\n",
2800                tmW.tmDigitizedAspectX, ret);
2801             ret = GetDeviceCaps(hdc, LOGPIXELSY);
2802             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectY %u != %u\n",
2803                tmW.tmDigitizedAspectX, ret);
2804         }
2805     }
2806
2807     /* test FF_ values */
2808     switch(tt_os2.panose.bFamilyType)
2809     {
2810     case PAN_ANY:
2811     case PAN_NO_FIT:
2812     case PAN_FAMILY_TEXT_DISPLAY:
2813     case PAN_FAMILY_PICTORIAL:
2814     default:
2815         if((tmA.tmPitchAndFamily & 1) == 0 || /* fixed */
2816            tt_os2.panose.bProportion == PAN_PROP_MONOSPACED)
2817         {
2818             expect_ff(&tmA, &tt_os2, FF_MODERN, font_name);
2819             break;
2820         }
2821         switch(tt_os2.panose.bSerifStyle)
2822         {
2823         case PAN_ANY:
2824         case PAN_NO_FIT:
2825         default:
2826             expect_ff(&tmA, &tt_os2, FF_DONTCARE, font_name);
2827             break;
2828
2829         case PAN_SERIF_COVE:
2830         case PAN_SERIF_OBTUSE_COVE:
2831         case PAN_SERIF_SQUARE_COVE:
2832         case PAN_SERIF_OBTUSE_SQUARE_COVE:
2833         case PAN_SERIF_SQUARE:
2834         case PAN_SERIF_THIN:
2835         case PAN_SERIF_BONE:
2836         case PAN_SERIF_EXAGGERATED:
2837         case PAN_SERIF_TRIANGLE:
2838             expect_ff(&tmA, &tt_os2, FF_ROMAN, font_name);
2839             break;
2840
2841         case PAN_SERIF_NORMAL_SANS:
2842         case PAN_SERIF_OBTUSE_SANS:
2843         case PAN_SERIF_PERP_SANS:
2844         case PAN_SERIF_FLARED:
2845         case PAN_SERIF_ROUNDED:
2846             expect_ff(&tmA, &tt_os2, FF_SWISS, font_name);
2847             break;
2848         }
2849         break;
2850
2851     case PAN_FAMILY_SCRIPT:
2852         expect_ff(&tmA, &tt_os2, FF_SCRIPT, font_name);
2853         break;
2854
2855     case PAN_FAMILY_DECORATIVE:
2856         expect_ff(&tmA, &tt_os2, FF_DECORATIVE, font_name);
2857         break;
2858     }
2859
2860     test_negative_width(hdc, lf);
2861
2862 end_of_test:
2863     SelectObject(hdc, hfont_old);
2864     DeleteObject(hfont);
2865
2866     ReleaseDC(0, hdc);
2867 }
2868
2869 static INT CALLBACK enum_truetype_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
2870 {
2871     INT *enumed = (INT *)lParam;
2872
2873     if (type == TRUETYPE_FONTTYPE)
2874     {
2875         (*enumed)++;
2876         test_text_metrics(lf);
2877     }
2878     return 1;
2879 }
2880
2881 static void test_GetTextMetrics(void)
2882 {
2883     LOGFONTA lf;
2884     HDC hdc;
2885     INT enumed;
2886
2887     /* Report only once */
2888     if(!pGetGlyphIndicesA)
2889         win_skip("GetGlyphIndicesA is unavailable, negative width will not be checked\n");
2890
2891     hdc = GetDC(0);
2892
2893     memset(&lf, 0, sizeof(lf));
2894     lf.lfCharSet = DEFAULT_CHARSET;
2895     enumed = 0;
2896     EnumFontFamiliesExA(hdc, &lf, enum_truetype_font_proc, (LPARAM)&enumed, 0);
2897     trace("Tested metrics of %d truetype fonts\n", enumed);
2898
2899     ReleaseDC(0, hdc);
2900 }
2901
2902 static void test_nonexistent_font(void)
2903 {
2904     static const struct
2905     {
2906         const char *name;
2907         int charset;
2908     } font_subst[] =
2909     {
2910         { "Times New Roman Baltic", 186 },
2911         { "Times New Roman CE", 238 },
2912         { "Times New Roman CYR", 204 },
2913         { "Times New Roman Greek", 161 },
2914         { "Times New Roman TUR", 162 }
2915     };
2916     LOGFONTA lf;
2917     HDC hdc;
2918     HFONT hfont;
2919     CHARSETINFO csi;
2920     INT cs, expected_cs, i;
2921     char buf[LF_FACESIZE];
2922
2923     if (!is_truetype_font_installed("Arial") ||
2924         !is_truetype_font_installed("Times New Roman"))
2925     {
2926         skip("Arial or Times New Roman not installed\n");
2927         return;
2928     }
2929
2930     expected_cs = GetACP();
2931     if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
2932     {
2933         skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
2934         return;
2935     }
2936     expected_cs = csi.ciCharset;
2937     trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
2938
2939     hdc = GetDC(0);
2940
2941     memset(&lf, 0, sizeof(lf));
2942     lf.lfHeight = 100;
2943     lf.lfWeight = FW_REGULAR;
2944     lf.lfCharSet = ANSI_CHARSET;
2945     lf.lfPitchAndFamily = FF_SWISS;
2946     strcpy(lf.lfFaceName, "Nonexistent font");
2947     hfont = CreateFontIndirectA(&lf);
2948     hfont = SelectObject(hdc, hfont);
2949     GetTextFaceA(hdc, sizeof(buf), buf);
2950     ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
2951     cs = GetTextCharset(hdc);
2952     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2953     DeleteObject(SelectObject(hdc, hfont));
2954
2955     memset(&lf, 0, sizeof(lf));
2956     lf.lfHeight = -13;
2957     lf.lfWeight = FW_DONTCARE;
2958     strcpy(lf.lfFaceName, "Nonexistent font");
2959     hfont = CreateFontIndirectA(&lf);
2960     hfont = SelectObject(hdc, hfont);
2961     GetTextFaceA(hdc, sizeof(buf), buf);
2962 todo_wine /* Wine uses Arial for all substitutions */
2963     ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ ||
2964        !lstrcmpiA(buf, "MS Serif") || /* Win9x */
2965        !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
2966        "Got %s\n", buf);
2967     cs = GetTextCharset(hdc);
2968     ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d\n", expected_cs, cs);
2969     DeleteObject(SelectObject(hdc, hfont));
2970
2971     memset(&lf, 0, sizeof(lf));
2972     lf.lfHeight = -13;
2973     lf.lfWeight = FW_REGULAR;
2974     strcpy(lf.lfFaceName, "Nonexistent font");
2975     hfont = CreateFontIndirectA(&lf);
2976     hfont = SelectObject(hdc, hfont);
2977     GetTextFaceA(hdc, sizeof(buf), buf);
2978     ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
2979        !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "Got %s\n", buf);
2980     cs = GetTextCharset(hdc);
2981     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2982     DeleteObject(SelectObject(hdc, hfont));
2983
2984     memset(&lf, 0, sizeof(lf));
2985     lf.lfHeight = -13;
2986     lf.lfWeight = FW_DONTCARE;
2987     strcpy(lf.lfFaceName, "Times New Roman");
2988     hfont = CreateFontIndirectA(&lf);
2989     hfont = SelectObject(hdc, hfont);
2990     GetTextFaceA(hdc, sizeof(buf), buf);
2991     ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf);
2992     cs = GetTextCharset(hdc);
2993     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2994     DeleteObject(SelectObject(hdc, hfont));
2995
2996     for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++)
2997     {
2998         memset(&lf, 0, sizeof(lf));
2999         lf.lfHeight = -13;
3000         lf.lfWeight = FW_REGULAR;
3001         strcpy(lf.lfFaceName, font_subst[i].name);
3002         hfont = CreateFontIndirectA(&lf);
3003         hfont = SelectObject(hdc, hfont);
3004         cs = GetTextCharset(hdc);
3005         if (font_subst[i].charset == expected_cs)
3006         {
3007             ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
3008             GetTextFaceA(hdc, sizeof(buf), buf);
3009             ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf);
3010         }
3011         else
3012         {
3013             ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d for font %s\n", cs, font_subst[i].name);
3014             GetTextFaceA(hdc, sizeof(buf), buf);
3015             ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
3016                !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got %s for font %s\n", buf, font_subst[i].name);
3017         }
3018         DeleteObject(SelectObject(hdc, hfont));
3019
3020         memset(&lf, 0, sizeof(lf));
3021         lf.lfHeight = -13;
3022         lf.lfWeight = FW_DONTCARE;
3023         strcpy(lf.lfFaceName, font_subst[i].name);
3024         hfont = CreateFontIndirectA(&lf);
3025         hfont = SelectObject(hdc, hfont);
3026         GetTextFaceA(hdc, sizeof(buf), buf);
3027         ok(!lstrcmpiA(buf, "Arial") /* Wine */ ||
3028            !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ ||
3029            !lstrcmpiA(buf, "MS Serif") /* Win9x */ ||
3030            !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
3031            "got %s for font %s\n", buf, font_subst[i].name);
3032         cs = GetTextCharset(hdc);
3033         ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
3034         DeleteObject(SelectObject(hdc, hfont));
3035     }
3036
3037     ReleaseDC(0, hdc);
3038 }
3039
3040 static void test_GdiRealizationInfo(void)
3041 {
3042     HDC hdc;
3043     DWORD info[4];
3044     BOOL r;
3045     HFONT hfont, hfont_old;
3046     LOGFONTA lf;
3047
3048     if(!pGdiRealizationInfo)
3049     {
3050         win_skip("GdiRealizationInfo not available\n");
3051         return;
3052     }
3053
3054     hdc = GetDC(0);
3055
3056     memset(info, 0xcc, sizeof(info));
3057     r = pGdiRealizationInfo(hdc, info);
3058     ok(r != 0, "ret 0\n");
3059     ok((info[0] & 0xf) == 1, "info[0] = %x for the system font\n", info[0]);
3060     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
3061
3062     if (!is_truetype_font_installed("Arial"))
3063     {
3064         skip("skipping GdiRealizationInfo with truetype font\n");
3065         goto end;
3066     }
3067
3068     memset(&lf, 0, sizeof(lf));
3069     strcpy(lf.lfFaceName, "Arial");
3070     lf.lfHeight = 20;
3071     lf.lfWeight = FW_NORMAL;
3072     hfont = CreateFontIndirectA(&lf);
3073     hfont_old = SelectObject(hdc, hfont);
3074
3075     memset(info, 0xcc, sizeof(info));
3076     r = pGdiRealizationInfo(hdc, info);
3077     ok(r != 0, "ret 0\n");
3078     ok((info[0] & 0xf) == 3, "info[0] = %x for arial\n", info[0]);
3079     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
3080
3081     DeleteObject(SelectObject(hdc, hfont_old));
3082
3083  end:
3084     ReleaseDC(0, hdc);
3085 }
3086
3087 /* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include
3088    the nul in the count of characters copied when the face name buffer is not
3089    NULL, whereas it does if the buffer is NULL.  Further, the Unicode version
3090    always includes it.  */
3091 static void test_GetTextFace(void)
3092 {
3093     static const char faceA[] = "Tahoma";
3094     static const WCHAR faceW[] = {'T','a','h','o','m','a', 0};
3095     LOGFONTA fA = {0};
3096     LOGFONTW fW = {0};
3097     char bufA[LF_FACESIZE];
3098     WCHAR bufW[LF_FACESIZE];
3099     HFONT f, g;
3100     HDC dc;
3101     int n;
3102
3103     if(!is_font_installed("Tahoma"))
3104     {
3105         skip("Tahoma is not installed so skipping this test\n");
3106         return;
3107     }
3108
3109     /* 'A' case.  */
3110     memcpy(fA.lfFaceName, faceA, sizeof faceA);
3111     f = CreateFontIndirectA(&fA);
3112     ok(f != NULL, "CreateFontIndirectA failed\n");
3113
3114     dc = GetDC(NULL);
3115     g = SelectObject(dc, f);
3116     n = GetTextFaceA(dc, sizeof bufA, bufA);
3117     ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n);
3118     ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n");
3119
3120     /* Play with the count arg.  */
3121     bufA[0] = 'x';
3122     n = GetTextFaceA(dc, 0, bufA);
3123     ok(n == 0, "GetTextFaceA returned %d\n", n);
3124     ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]);
3125
3126     bufA[0] = 'x';
3127     n = GetTextFaceA(dc, 1, bufA);
3128     ok(n == 0, "GetTextFaceA returned %d\n", n);
3129     ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]);
3130
3131     bufA[0] = 'x'; bufA[1] = 'y';
3132     n = GetTextFaceA(dc, 2, bufA);
3133     ok(n == 1, "GetTextFaceA returned %d\n", n);
3134     ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n");
3135
3136     n = GetTextFaceA(dc, 0, NULL);
3137     ok(n == sizeof faceA ||
3138        broken(n == 0), /* win98, winMe */
3139        "GetTextFaceA returned %d\n", n);
3140
3141     DeleteObject(SelectObject(dc, g));
3142     ReleaseDC(NULL, dc);
3143
3144     /* 'W' case.  */
3145     memcpy(fW.lfFaceName, faceW, sizeof faceW);
3146     SetLastError(0xdeadbeef);
3147     f = CreateFontIndirectW(&fW);
3148     if (!f && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
3149     {
3150         win_skip("CreateFontIndirectW is not implemented\n");
3151         return;
3152     }
3153     ok(f != NULL, "CreateFontIndirectW failed\n");
3154
3155     dc = GetDC(NULL);
3156     g = SelectObject(dc, f);
3157     n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW);
3158     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
3159     ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
3160
3161     /* Play with the count arg.  */
3162     bufW[0] = 'x';
3163     n = GetTextFaceW(dc, 0, bufW);
3164     ok(n == 0, "GetTextFaceW returned %d\n", n);
3165     ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]);
3166
3167     bufW[0] = 'x';
3168     n = GetTextFaceW(dc, 1, bufW);
3169     ok(n == 1, "GetTextFaceW returned %d\n", n);
3170     ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]);
3171
3172     bufW[0] = 'x'; bufW[1] = 'y';
3173     n = GetTextFaceW(dc, 2, bufW);
3174     ok(n == 2, "GetTextFaceW returned %d\n", n);
3175     ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n");
3176
3177     n = GetTextFaceW(dc, 0, NULL);
3178     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
3179
3180     DeleteObject(SelectObject(dc, g));
3181     ReleaseDC(NULL, dc);
3182 }
3183
3184 static void test_orientation(void)
3185 {
3186     static const char test_str[11] = "Test String";
3187     HDC hdc;
3188     LOGFONTA lf;
3189     HFONT hfont, old_hfont;
3190     SIZE size;
3191
3192     if (!is_truetype_font_installed("Arial"))
3193     {
3194         skip("Arial is not installed\n");
3195         return;
3196     }
3197
3198     hdc = CreateCompatibleDC(0);
3199     memset(&lf, 0, sizeof(lf));
3200     lstrcpyA(lf.lfFaceName, "Arial");
3201     lf.lfHeight = 72;
3202     lf.lfOrientation = lf.lfEscapement = 900;
3203     hfont = create_font("orientation", &lf);
3204     old_hfont = SelectObject(hdc, hfont);
3205     ok(GetTextExtentExPointA(hdc, test_str, sizeof(test_str), 32767, NULL, NULL, &size), "GetTextExtentExPointA failed\n");
3206     ok(near_match(311, size.cx), "cx should be about 311, got %d\n", size.cx);
3207     ok(near_match(75, size.cy), "cy should be about 75, got %d\n", size.cy);
3208     SelectObject(hdc, old_hfont);
3209     DeleteObject(hfont);
3210     DeleteDC(hdc);
3211 }
3212
3213 static void test_oemcharset(void)
3214 {
3215     HDC hdc;
3216     LOGFONTA lf, clf;
3217     HFONT hfont, old_hfont;
3218     int charset;
3219
3220     hdc = CreateCompatibleDC(0);
3221     ZeroMemory(&lf, sizeof(lf));
3222     lf.lfHeight = 12;
3223     lf.lfCharSet = OEM_CHARSET;
3224     lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
3225     lstrcpyA(lf.lfFaceName, "Terminal");
3226     hfont = CreateFontIndirectA(&lf);
3227     old_hfont = SelectObject(hdc, hfont);
3228     charset = GetTextCharset(hdc);
3229 todo_wine
3230     ok(charset == OEM_CHARSET, "expected %d charset, got %d\n", OEM_CHARSET, charset);
3231     hfont = SelectObject(hdc, old_hfont);
3232     GetObjectA(hfont, sizeof(clf), &clf);
3233     ok(!lstrcmpA(clf.lfFaceName, lf.lfFaceName), "expected %s face name, got %s\n", lf.lfFaceName, clf.lfFaceName);
3234     ok(clf.lfPitchAndFamily == lf.lfPitchAndFamily, "expected %x family, got %x\n", lf.lfPitchAndFamily, clf.lfPitchAndFamily);
3235     ok(clf.lfCharSet == lf.lfCharSet, "expected %d charset, got %d\n", lf.lfCharSet, clf.lfCharSet);
3236     ok(clf.lfHeight == lf.lfHeight, "expected %d height, got %d\n", lf.lfHeight, clf.lfHeight);
3237     DeleteObject(hfont);
3238     DeleteDC(hdc);
3239 }
3240
3241 static void test_GetGlyphOutline(void)
3242 {
3243     HDC hdc;
3244     GLYPHMETRICS gm, gm2;
3245     LOGFONTA lf;
3246     HFONT hfont, old_hfont;
3247     INT ret, ret2;
3248     static const struct
3249     {
3250         UINT cs;
3251         UINT a;
3252         UINT w;
3253     } c[] =
3254     {
3255         {ANSI_CHARSET, 0x30, 0x30},
3256         {SHIFTJIS_CHARSET, 0x82a0, 0x3042},
3257         {HANGEUL_CHARSET, 0x8141, 0xac02},
3258         {JOHAB_CHARSET, 0x8446, 0x3135},
3259         {GB2312_CHARSET, 0x8141, 0x4e04},
3260         {CHINESEBIG5_CHARSET, 0xa142, 0x3001}
3261     };
3262     UINT i;
3263
3264     if (!is_truetype_font_installed("Tahoma"))
3265     {
3266         skip("Tahoma is not installed\n");
3267         return;
3268     }
3269
3270     hdc = CreateCompatibleDC(0);
3271     memset(&lf, 0, sizeof(lf));
3272     lf.lfHeight = 72;
3273     lstrcpyA(lf.lfFaceName, "Tahoma");
3274     SetLastError(0xdeadbeef);
3275     hfont = CreateFontIndirectA(&lf);
3276     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
3277     old_hfont = SelectObject(hdc, hfont);
3278
3279     memset(&gm, 0, sizeof(gm));
3280     SetLastError(0xdeadbeef);
3281     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3282     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
3283
3284     memset(&gm, 0, sizeof(gm));
3285     SetLastError(0xdeadbeef);
3286     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
3287     ok(ret == GDI_ERROR, "GetGlyphOutlineA should fail\n");
3288     ok(GetLastError() == 0xdeadbeef ||
3289        GetLastError() == ERROR_INVALID_PARAMETER, /* win98, winMe */
3290        "expected 0xdeadbeef, got %u\n", GetLastError());
3291
3292     memset(&gm, 0, sizeof(gm));
3293     SetLastError(0xdeadbeef);
3294     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3295     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3296         ok(ret != GDI_ERROR, "GetGlyphOutlineW error %u\n", GetLastError());
3297
3298     memset(&gm, 0, sizeof(gm));
3299     SetLastError(0xdeadbeef);
3300     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
3301     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3302     {
3303        ok(ret == GDI_ERROR, "GetGlyphOutlineW should fail\n");
3304        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
3305     }
3306
3307     /* test for needed buffer size request on space char */
3308     memset(&gm, 0, sizeof(gm));
3309     SetLastError(0xdeadbeef);
3310     ret = GetGlyphOutlineW(hdc, ' ', GGO_NATIVE, &gm, 0, NULL, &mat);
3311     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3312         ok(ret == 0, "GetGlyphOutlineW should return 0 buffer size for space char\n");
3313
3314     /* requesting buffer size for space char + error */
3315     memset(&gm, 0, sizeof(gm));
3316     SetLastError(0xdeadbeef);
3317     ret = GetGlyphOutlineW(0, ' ', GGO_NATIVE, &gm, 0, NULL, NULL);
3318     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3319     {
3320        ok(ret == GDI_ERROR, "GetGlyphOutlineW should return GDI_ERROR\n");
3321        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
3322     }
3323
3324     SelectObject(hdc, old_hfont);
3325     DeleteObject(hfont);
3326
3327     for (i = 0; i < sizeof c / sizeof c[0]; ++i)
3328     {
3329         lf.lfFaceName[0] = '\0';
3330         lf.lfCharSet = c[i].cs;
3331         lf.lfPitchAndFamily = 0;
3332         if (EnumFontFamiliesEx(hdc, &lf, create_font_proc, (LPARAM)&hfont, 0))
3333         {
3334             skip("TrueType font for charset %u is not installed\n", c[i].cs);
3335             continue;
3336         }
3337
3338         old_hfont = SelectObject(hdc, hfont);
3339
3340         /* expected to ignore superfluous bytes (sigle-byte character) */
3341         ret = GetGlyphOutlineA(hdc, 0x8041, GGO_BITMAP, &gm, 0, NULL, &mat);
3342         ret2 = GetGlyphOutlineA(hdc, 0x41, GGO_BITMAP, &gm2, 0, NULL, &mat);
3343         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
3344
3345         ret = GetGlyphOutlineA(hdc, 0xcc8041, GGO_BITMAP, &gm, 0, NULL, &mat);
3346         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
3347            "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
3348
3349         /* expected to ignore superfluous bytes (double-byte character) */
3350         ret = GetGlyphOutlineA(hdc, c[i].a, GGO_BITMAP, &gm, 0, NULL, &mat);
3351         ret2 = GetGlyphOutlineA(hdc, c[i].a | 0xdead0000, GGO_BITMAP, &gm2, 0, NULL, &mat);
3352         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
3353            "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
3354
3355         /* expected to match wide-char version results */
3356         ret2 = GetGlyphOutlineW(hdc, c[i].w, GGO_BITMAP, &gm2, 0, NULL, &mat);
3357         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
3358
3359         hfont = SelectObject(hdc, old_hfont);
3360         DeleteObject(hfont);
3361     }
3362
3363     DeleteDC(hdc);
3364 }
3365
3366 /* bug #9995: there is a limit to the character width that can be specified */
3367 static void test_GetTextMetrics2(const char *fontname, int font_height)
3368 {
3369     HFONT of, hf;
3370     HDC hdc;
3371     TEXTMETRICA tm;
3372     BOOL ret;
3373     int ave_width, height, width, ratio, scale;
3374
3375     if (!is_truetype_font_installed( fontname)) {
3376         skip("%s is not installed\n", fontname);
3377         return;
3378     }
3379     hdc = CreateCompatibleDC(0);
3380     ok( hdc != NULL, "CreateCompatibleDC failed\n");
3381     /* select width = 0 */
3382     hf = CreateFontA(font_height, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3383             DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3384             DEFAULT_QUALITY, VARIABLE_PITCH,
3385             fontname);
3386     ok( hf != NULL, "CreateFontA(%s, %d) failed\n", fontname, font_height);
3387     of = SelectObject( hdc, hf);
3388     ret = GetTextMetricsA( hdc, &tm);
3389     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
3390     height = tm.tmHeight;
3391     ave_width = tm.tmAveCharWidth;
3392     SelectObject( hdc, of);
3393     DeleteObject( hf);
3394
3395     trace("height %d, ave width %d\n", height, ave_width);
3396
3397     for (width = ave_width * 2; /* nothing*/; width += ave_width)
3398     {
3399         hf = CreateFont(height, width, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3400                         DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3401                         DEFAULT_QUALITY, VARIABLE_PITCH, fontname);
3402         ok(hf != 0, "CreateFont failed\n");
3403         of = SelectObject(hdc, hf);
3404         ret = GetTextMetrics(hdc, &tm);
3405         ok(ret, "GetTextMetrics error %u\n", GetLastError());
3406         SelectObject(hdc, of);
3407         DeleteObject(hf);
3408
3409         if (match_off_by_1(tm.tmAveCharWidth, ave_width) || width / height > 200)
3410             break;
3411     }
3412
3413     DeleteDC(hdc);
3414
3415     ratio = width / height;
3416     scale = width / ave_width;
3417
3418     trace("max width/height ratio (%d / %d) %d, max width scale (%d / %d) %d\n",
3419           width, height, ratio, width, ave_width, scale);
3420
3421     ok(ratio >= 90 && ratio <= 110, "expected width/height ratio 90-110, got %d\n", ratio);
3422 }
3423
3424 static void test_CreateFontIndirect(void)
3425 {
3426     LOGFONTA lf, getobj_lf;
3427     int ret, i;
3428     HFONT hfont;
3429     char TestName[][16] = {"Arial", "Arial Bold", "Arial Italic", "Arial Baltic"};
3430
3431     memset(&lf, 0, sizeof(lf));
3432     lf.lfCharSet = ANSI_CHARSET;
3433     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
3434     lf.lfHeight = 16;
3435     lf.lfWidth = 16;
3436     lf.lfQuality = DEFAULT_QUALITY;
3437     lf.lfItalic = FALSE;
3438     lf.lfWeight = FW_DONTCARE;
3439
3440     for (i = 0; i < sizeof(TestName)/sizeof(TestName[0]); i++)
3441     {
3442         lstrcpyA(lf.lfFaceName, TestName[i]);
3443         hfont = CreateFontIndirectA(&lf);
3444         ok(hfont != 0, "CreateFontIndirectA failed\n");
3445         SetLastError(0xdeadbeef);
3446         ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf);
3447         ok(ret, "GetObject failed: %d\n", GetLastError());
3448         ok(lf.lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf.lfItalic, getobj_lf.lfItalic);
3449         ok(lf.lfWeight == getobj_lf.lfWeight ||
3450            broken((SHORT)lf.lfWeight == getobj_lf.lfWeight), /* win9x */
3451            "lfWeight: expect %08x got %08x\n", lf.lfWeight, getobj_lf.lfWeight);
3452         ok(!lstrcmpA(lf.lfFaceName, getobj_lf.lfFaceName) ||
3453            broken(!memcmp(lf.lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
3454            "font names don't match: %s != %s\n", lf.lfFaceName, getobj_lf.lfFaceName);
3455         DeleteObject(hfont);
3456     }
3457 }
3458
3459 static void test_CreateFontIndirectEx(void)
3460 {
3461     ENUMLOGFONTEXDVA lfex;
3462     HFONT hfont;
3463
3464     if (!pCreateFontIndirectExA)
3465     {
3466         win_skip("CreateFontIndirectExA is not available\n");
3467         return;
3468     }
3469
3470     if (!is_truetype_font_installed("Arial"))
3471     {
3472         skip("Arial is not installed\n");
3473         return;
3474     }
3475
3476     SetLastError(0xdeadbeef);
3477     hfont = pCreateFontIndirectExA(NULL);
3478     ok(hfont == NULL, "got %p\n", hfont);
3479     ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
3480
3481     memset(&lfex, 0, sizeof(lfex));
3482     lstrcpyA(lfex.elfEnumLogfontEx.elfLogFont.lfFaceName, "Arial");
3483     hfont = pCreateFontIndirectExA(&lfex);
3484     ok(hfont != 0, "CreateFontIndirectEx failed\n");
3485     if (hfont)
3486         check_font("Arial", &lfex.elfEnumLogfontEx.elfLogFont, hfont);
3487     DeleteObject(hfont);
3488 }
3489
3490 static void free_font(void *font)
3491 {
3492     UnmapViewOfFile(font);
3493 }
3494
3495 static void *load_font(const char *font_name, DWORD *font_size)
3496 {
3497     char file_name[MAX_PATH];
3498     HANDLE file, mapping;
3499     void *font;
3500
3501     if (!GetWindowsDirectory(file_name, sizeof(file_name))) return NULL;
3502     strcat(file_name, "\\fonts\\");
3503     strcat(file_name, font_name);
3504
3505     file = CreateFile(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
3506     if (file == INVALID_HANDLE_VALUE) return NULL;
3507
3508     *font_size = GetFileSize(file, NULL);
3509
3510     mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
3511     if (!mapping)
3512     {
3513         CloseHandle(file);
3514         return NULL;
3515     }
3516
3517     font = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
3518
3519     CloseHandle(file);
3520     CloseHandle(mapping);
3521     return font;
3522 }
3523
3524 static void test_AddFontMemResource(void)
3525 {
3526     void *font;
3527     DWORD font_size, num_fonts;
3528     HANDLE ret;
3529     BOOL bRet;
3530
3531     if (!pAddFontMemResourceEx || !pRemoveFontMemResourceEx)
3532     {
3533         win_skip("AddFontMemResourceEx is not available on this platform\n");
3534         return;
3535     }
3536
3537     font = load_font("sserife.fon", &font_size);
3538     if (!font)
3539     {
3540         skip("Unable to locate and load font sserife.fon\n");
3541         return;
3542     }
3543
3544     SetLastError(0xdeadbeef);
3545     ret = pAddFontMemResourceEx(NULL, 0, NULL, NULL);
3546     ok(!ret, "AddFontMemResourceEx should fail\n");
3547     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3548        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3549        GetLastError());
3550
3551     SetLastError(0xdeadbeef);
3552     ret = pAddFontMemResourceEx(NULL, 10, NULL, NULL);
3553     ok(!ret, "AddFontMemResourceEx should fail\n");
3554     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3555        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3556        GetLastError());
3557
3558     SetLastError(0xdeadbeef);
3559     ret = pAddFontMemResourceEx(NULL, 0, NULL, &num_fonts);
3560     ok(!ret, "AddFontMemResourceEx should fail\n");
3561     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3562        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3563        GetLastError());
3564
3565     SetLastError(0xdeadbeef);
3566     ret = pAddFontMemResourceEx(NULL, 10, NULL, &num_fonts);
3567     ok(!ret, "AddFontMemResourceEx should fail\n");
3568     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3569        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3570        GetLastError());
3571
3572     SetLastError(0xdeadbeef);
3573     ret = pAddFontMemResourceEx(font, 0, NULL, NULL);
3574     ok(!ret, "AddFontMemResourceEx should fail\n");
3575     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3576        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3577        GetLastError());
3578
3579     SetLastError(0xdeadbeef);
3580     ret = pAddFontMemResourceEx(font, 10, NULL, NULL);
3581     ok(!ret, "AddFontMemResourceEx should fail\n");
3582     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3583        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3584        GetLastError());
3585
3586     num_fonts = 0xdeadbeef;
3587     SetLastError(0xdeadbeef);
3588     ret = pAddFontMemResourceEx(font, 0, NULL, &num_fonts);
3589     ok(!ret, "AddFontMemResourceEx should fail\n");
3590     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3591        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3592        GetLastError());
3593     ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
3594
3595     if (0) /* hangs under windows 2000 */
3596     {
3597         num_fonts = 0xdeadbeef;
3598         SetLastError(0xdeadbeef);
3599         ret = pAddFontMemResourceEx(font, 10, NULL, &num_fonts);
3600         ok(!ret, "AddFontMemResourceEx should fail\n");
3601         ok(GetLastError() == 0xdeadbeef,
3602            "Expected GetLastError() to return 0xdeadbeef, got %u\n",
3603            GetLastError());
3604         ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
3605     }
3606
3607     num_fonts = 0xdeadbeef;
3608     SetLastError(0xdeadbeef);
3609     ret = pAddFontMemResourceEx(font, font_size, NULL, &num_fonts);
3610     ok(ret != 0, "AddFontMemResourceEx error %d\n", GetLastError());
3611     ok(num_fonts != 0xdeadbeef, "number of loaded fonts should not be 0xdeadbeef\n");
3612     ok(num_fonts != 0, "number of loaded fonts should not be 0\n");
3613
3614     free_font(font);
3615
3616     SetLastError(0xdeadbeef);
3617     bRet = pRemoveFontMemResourceEx(ret);
3618     ok(bRet, "RemoveFontMemResourceEx error %d\n", GetLastError());
3619
3620     /* test invalid pointer to number of loaded fonts */
3621     font = load_font("sserife.fon", &font_size);
3622     ok(font != NULL, "Unable to locate and load font sserife.fon\n");
3623
3624     SetLastError(0xdeadbeef);
3625     ret = pAddFontMemResourceEx(font, font_size, NULL, (void *)0xdeadbeef);
3626     ok(!ret, "AddFontMemResourceEx should fail\n");
3627     ok(GetLastError() == 0xdeadbeef,
3628        "Expected GetLastError() to return 0xdeadbeef, got %u\n",
3629        GetLastError());
3630
3631     SetLastError(0xdeadbeef);
3632     ret = pAddFontMemResourceEx(font, font_size, NULL, NULL);
3633     ok(!ret, "AddFontMemResourceEx should fail\n");
3634     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3635        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3636        GetLastError());
3637
3638     free_font(font);
3639 }
3640
3641 static INT CALLBACK enum_fonts_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3642 {
3643     LOGFONT *lf;
3644
3645     if (type != TRUETYPE_FONTTYPE) return 1;
3646
3647     ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
3648
3649     lf = (LOGFONT *)lparam;
3650     *lf = *elf;
3651     return 0;
3652 }
3653
3654 static INT CALLBACK enum_all_fonts_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3655 {
3656     int ret;
3657     LOGFONT *lf;
3658
3659     if (type != TRUETYPE_FONTTYPE) return 1;
3660
3661     lf = (LOGFONT *)lparam;
3662     ret = strcmp(lf->lfFaceName, elf->lfFaceName);
3663     if(ret == 0)
3664     {
3665         ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
3666         *lf = *elf;
3667         return 0;
3668     }
3669     return 1;
3670 }
3671
3672 static void test_EnumFonts(void)
3673 {
3674     int ret;
3675     LOGFONT lf;
3676     HDC hdc;
3677
3678     if (!is_truetype_font_installed("Arial"))
3679     {
3680         skip("Arial is not installed\n");
3681         return;
3682     }
3683
3684     /* Windows uses localized font face names, so Arial Bold won't be found */
3685     if (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH)
3686     {
3687         skip("User locale is not English, skipping the test\n");
3688         return;
3689     }
3690
3691     hdc = CreateCompatibleDC(0);
3692
3693     ret = EnumFontFamilies(hdc, "Arial", enum_fonts_proc, (LPARAM)&lf);
3694     ok(!ret, "font Arial is not enumerated\n");
3695     ret = strcmp(lf.lfFaceName, "Arial");
3696     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3697     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
3698
3699     lstrcpy(lf.lfFaceName, "Arial");
3700     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3701     ok(!ret, "font Arial is not enumerated\n");
3702     ret = strcmp(lf.lfFaceName, "Arial");
3703     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3704     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
3705
3706     ret = EnumFontFamilies(hdc, "Arial Bold", enum_fonts_proc, (LPARAM)&lf);
3707     ok(!ret, "font Arial Bold is not enumerated\n");
3708     ret = strcmp(lf.lfFaceName, "Arial");
3709     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3710     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
3711
3712     lstrcpy(lf.lfFaceName, "Arial Bold");
3713     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3714     ok(ret, "font Arial Bold should not be enumerated\n");
3715
3716     ret = EnumFontFamilies(hdc, "Arial Bold Italic", enum_fonts_proc, (LPARAM)&lf);
3717     ok(!ret, "font Arial Bold Italic is not enumerated\n");
3718     ret = strcmp(lf.lfFaceName, "Arial");
3719     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3720     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
3721
3722     lstrcpy(lf.lfFaceName, "Arial Bold Italic");
3723     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3724     ok(ret, "font Arial Bold Italic should not be enumerated\n");
3725
3726     ret = EnumFontFamilies(hdc, "Arial Italic Bold", enum_fonts_proc, (LPARAM)&lf);
3727     ok(ret, "font Arial Italic Bold  should not be enumerated\n");
3728
3729     lstrcpy(lf.lfFaceName, "Arial Italic Bold");
3730     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3731     ok(ret, "font Arial Italic Bold should not be enumerated\n");
3732
3733     DeleteDC(hdc);
3734 }
3735
3736 static void test_fullname(void)
3737 {
3738     static const char *TestName[] = {"Lucida Sans Demibold Roman", "Lucida Sans Italic"};
3739     char buf[LF_FULLFACESIZE];
3740     HFONT hfont, of;
3741     LOGFONTA lf;
3742     HDC hdc;
3743     int i;
3744
3745     /* Lucida Sans comes with XP SP2 or later */
3746     if (!is_truetype_font_installed("Lucida Sans"))
3747     {
3748         skip("Lucida Sans is not installed\n");
3749         return;
3750     }
3751
3752     hdc = CreateCompatibleDC(0);
3753     ok(hdc != NULL, "CreateCompatibleDC failed\n");
3754
3755     memset(&lf, 0, sizeof(lf));
3756     lf.lfCharSet = ANSI_CHARSET;
3757     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
3758     lf.lfHeight = 16;
3759     lf.lfWidth = 16;
3760     lf.lfQuality = DEFAULT_QUALITY;
3761     lf.lfItalic = FALSE;
3762     lf.lfWeight = FW_DONTCARE;
3763
3764     for (i = 0; i < sizeof(TestName) / sizeof(TestName[0]); i++)
3765     {
3766         lstrcpyA(lf.lfFaceName, TestName[i]);
3767         hfont = CreateFontIndirectA(&lf);
3768         ok(hfont != 0, "CreateFontIndirectA failed\n");
3769
3770         of = SelectObject(hdc, hfont);
3771         buf[0] = 0;
3772         ok(get_ttf_nametable_entry(hdc, TT_NAME_ID_FULL_NAME, buf, sizeof(buf)),
3773            "face full name could not be read\n");
3774         ok(!lstrcmpA(buf, TestName[i]), "font full names don't match: %s != %s\n", TestName[i], buf);
3775         SelectObject(hdc, of);
3776         DeleteObject(hfont);
3777     }
3778     DeleteDC(hdc);
3779 }
3780
3781 START_TEST(font)
3782 {
3783     init();
3784
3785     test_logfont();
3786     test_bitmap_font();
3787     test_outline_font();
3788     test_bitmap_font_metrics();
3789     test_GdiGetCharDimensions();
3790     test_GetCharABCWidths();
3791     test_text_extents();
3792     test_GetGlyphIndices();
3793     test_GetKerningPairs();
3794     test_GetOutlineTextMetrics();
3795     test_SetTextJustification();
3796     test_font_charset();
3797     test_GetFontUnicodeRanges();
3798     test_nonexistent_font();
3799     test_orientation();
3800     test_height_selection();
3801     test_AddFontMemResource();
3802     test_EnumFonts();
3803
3804     /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
3805      * I'd like to avoid them in this test.
3806      */
3807     test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
3808     test_EnumFontFamilies("Symbol", SYMBOL_CHARSET);
3809     if (is_truetype_font_installed("Arial Black") &&
3810         (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
3811     {
3812         test_EnumFontFamilies("", ANSI_CHARSET);
3813         test_EnumFontFamilies("", SYMBOL_CHARSET);
3814         test_EnumFontFamilies("", DEFAULT_CHARSET);
3815     }
3816     else
3817         skip("Arial Black or Symbol/Wingdings is not installed\n");
3818     test_EnumFontFamiliesEx_default_charset();
3819     test_GetTextMetrics();
3820     test_GdiRealizationInfo();
3821     test_GetTextFace();
3822     test_GetGlyphOutline();
3823     test_GetTextMetrics2("Tahoma", -11);
3824     test_GetTextMetrics2("Tahoma", -55);
3825     test_GetTextMetrics2("Tahoma", -110);
3826     test_GetTextMetrics2("Arial", -11);
3827     test_GetTextMetrics2("Arial", -55);
3828     test_GetTextMetrics2("Arial", -110);
3829     test_CreateFontIndirect();
3830     test_CreateFontIndirectEx();
3831     test_oemcharset();
3832     test_fullname();
3833 }