gdi32: Clip solid brush fills.
[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
2351 typedef struct
2352 {
2353     USHORT version;
2354     USHORT num_tables;
2355 } cmap_header;
2356
2357 typedef struct
2358 {
2359     USHORT plat_id;
2360     USHORT enc_id;
2361     ULONG offset;
2362 } cmap_encoding_record;
2363
2364 typedef struct
2365 {
2366     USHORT format;
2367     USHORT length;
2368     USHORT language;
2369
2370     BYTE glyph_ids[256];
2371 } cmap_format_0;
2372
2373 typedef struct
2374 {
2375     USHORT format;
2376     USHORT length;
2377     USHORT language;
2378
2379     USHORT seg_countx2;
2380     USHORT search_range;
2381     USHORT entry_selector;
2382     USHORT range_shift;
2383
2384     USHORT end_count[1]; /* this is a variable-sized array of length seg_countx2 / 2 */
2385 /* Then follows:
2386     USHORT pad;
2387     USHORT start_count[seg_countx2 / 2];
2388     USHORT id_delta[seg_countx2 / 2];
2389     USHORT id_range_offset[seg_countx2 / 2];
2390     USHORT glyph_ids[];
2391 */
2392 } cmap_format_4;
2393
2394 typedef struct
2395 {
2396     USHORT end_count;
2397     USHORT start_count;
2398     USHORT id_delta;
2399     USHORT id_range_offset;
2400 } cmap_format_4_seg;
2401
2402 static void expect_ff(const TEXTMETRICA *tmA, const TT_OS2_V2 *os2, WORD family, const char *name)
2403 {
2404     ok((tmA->tmPitchAndFamily & 0xf0) == family ||
2405        broken(PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH),
2406        "%s: expected family %02x got %02x. panose %d-%d-%d-%d-...\n",
2407        name, family, tmA->tmPitchAndFamily, os2->panose.bFamilyType, os2->panose.bSerifStyle,
2408        os2->panose.bWeight, os2->panose.bProportion);
2409 }
2410
2411 static BOOL get_first_last_from_cmap0(void *ptr, DWORD *first, DWORD *last)
2412 {
2413     int i;
2414     cmap_format_0 *cmap = (cmap_format_0*)ptr;
2415
2416     *first = 256;
2417
2418     for(i = 0; i < 256; i++)
2419     {
2420         if(cmap->glyph_ids[i] == 0) continue;
2421         *last = i;
2422         if(*first == 256) *first = i;
2423     }
2424     if(*first == 256) return FALSE;
2425     return TRUE;
2426 }
2427
2428 static void get_seg4(cmap_format_4 *cmap, USHORT seg_num, cmap_format_4_seg *seg)
2429 {
2430     USHORT segs = GET_BE_WORD(cmap->seg_countx2) / 2;
2431     seg->end_count = GET_BE_WORD(cmap->end_count[seg_num]);
2432     seg->start_count = GET_BE_WORD(cmap->end_count[segs + 1 + seg_num]);
2433     seg->id_delta = GET_BE_WORD(cmap->end_count[2 * segs + 1 + seg_num]);
2434     seg->id_range_offset = GET_BE_WORD(cmap->end_count[3 * segs + 1 + seg_num]);
2435 }
2436
2437 static BOOL get_first_last_from_cmap4(void *ptr, DWORD *first, DWORD *last, DWORD limit)
2438 {
2439     int i;
2440     cmap_format_4 *cmap = (cmap_format_4*)ptr;
2441     USHORT seg_count = GET_BE_WORD(cmap->seg_countx2) / 2;
2442     USHORT const *glyph_ids = cmap->end_count + 4 * seg_count + 1;
2443
2444     *first = 0x10000;
2445
2446     for(i = 0; i < seg_count; i++)
2447     {
2448         DWORD code, index;
2449         cmap_format_4_seg seg;
2450
2451         get_seg4(cmap, i, &seg);
2452         for(code = seg.start_count; code <= seg.end_count; code++)
2453         {
2454             if(seg.id_range_offset == 0)
2455                 index = (seg.id_delta + code) & 0xffff;
2456             else
2457             {
2458                 index = seg.id_range_offset / 2
2459                     + code - seg.start_count
2460                     + i - seg_count;
2461
2462                 /* some fonts have broken last segment */
2463                 if ((char *)(glyph_ids + index + sizeof(*glyph_ids)) < (char *)ptr + limit)
2464                     index = GET_BE_WORD(glyph_ids[index]);
2465                 else
2466                 {
2467                     trace("segment %04x/%04x index %04x points to nowhere\n",
2468                           seg.start_count, seg.end_count, index);
2469                     index = 0;
2470                 }
2471                 if(index) index += seg.id_delta;
2472             }
2473             if(*first == 0x10000)
2474                 *last = *first = code;
2475             else if(index)
2476                 *last = code;
2477         }
2478     }
2479
2480     if(*first == 0x10000) return FALSE;
2481     return TRUE;
2482 }
2483
2484 static void *get_cmap(cmap_header *header, USHORT plat_id, USHORT enc_id)
2485 {
2486     USHORT i;
2487     cmap_encoding_record *record = (cmap_encoding_record *)(header + 1);
2488
2489     for(i = 0; i < GET_BE_WORD(header->num_tables); i++)
2490     {
2491         if(GET_BE_WORD(record->plat_id) == plat_id && GET_BE_WORD(record->enc_id) == enc_id)
2492             return (BYTE *)header + GET_BE_DWORD(record->offset);
2493         record++;
2494     }
2495     return NULL;
2496 }
2497
2498 typedef enum
2499 {
2500     cmap_none,
2501     cmap_ms_unicode,
2502     cmap_ms_symbol
2503 } cmap_type;
2504
2505 static BOOL get_first_last_from_cmap(HDC hdc, DWORD *first, DWORD *last, cmap_type *cmap_type)
2506 {
2507     LONG size, ret;
2508     cmap_header *header;
2509     void *cmap;
2510     BOOL r = FALSE;
2511     WORD format;
2512
2513     size = GetFontData(hdc, MS_CMAP_TAG, 0, NULL, 0);
2514     ok(size != GDI_ERROR, "no cmap table found\n");
2515     if(size == GDI_ERROR) return FALSE;
2516
2517     header = HeapAlloc(GetProcessHeap(), 0, size);
2518     ret = GetFontData(hdc, MS_CMAP_TAG, 0, header, size);
2519     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2520     ok(GET_BE_WORD(header->version) == 0, "got cmap version %d\n", GET_BE_WORD(header->version));
2521
2522     cmap = get_cmap(header, 3, 1);
2523     if(cmap)
2524         *cmap_type = cmap_ms_unicode;
2525     else
2526     {
2527         cmap = get_cmap(header, 3, 0);
2528         if(cmap) *cmap_type = cmap_ms_symbol;
2529     }
2530     if(!cmap)
2531     {
2532         *cmap_type = cmap_none;
2533         goto end;
2534     }
2535
2536     format = GET_BE_WORD(*(WORD *)cmap);
2537     switch(format)
2538     {
2539     case 0:
2540         r = get_first_last_from_cmap0(cmap, first, last);
2541         break;
2542     case 4:
2543         r = get_first_last_from_cmap4(cmap, first, last, size);
2544         break;
2545     default:
2546         trace("unhandled cmap format %d\n", format);
2547         break;
2548     }
2549
2550 end:
2551     HeapFree(GetProcessHeap(), 0, header);
2552     return r;
2553 }
2554
2555 static void test_text_metrics(const LOGFONTA *lf)
2556 {
2557     HDC hdc;
2558     HFONT hfont, hfont_old;
2559     TEXTMETRICA tmA;
2560     TT_OS2_V2 tt_os2;
2561     LONG size, ret;
2562     const char *font_name = lf->lfFaceName;
2563     DWORD cmap_first = 0, cmap_last = 0;
2564     cmap_type cmap_type;
2565     BOOL sys_lang_non_english;
2566
2567     sys_lang_non_english = PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH;
2568     hdc = GetDC(0);
2569
2570     SetLastError(0xdeadbeef);
2571     hfont = CreateFontIndirectA(lf);
2572     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2573
2574     hfont_old = SelectObject(hdc, hfont);
2575
2576     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
2577     if (size == GDI_ERROR)
2578     {
2579         trace("OS/2 chunk was not found\n");
2580         goto end_of_test;
2581     }
2582     if (size > sizeof(tt_os2))
2583     {
2584         trace("got too large OS/2 chunk of size %u\n", size);
2585         size = sizeof(tt_os2);
2586     }
2587
2588     memset(&tt_os2, 0, sizeof(tt_os2));
2589     ret = GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size);
2590     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2591
2592     SetLastError(0xdeadbeef);
2593     ret = GetTextMetricsA(hdc, &tmA);
2594     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
2595
2596     if(!get_first_last_from_cmap(hdc, &cmap_first, &cmap_last, &cmap_type))
2597     {
2598         skip("Unable to retrieve first and last glyphs from cmap\n");
2599     }
2600     else
2601     {
2602         USHORT expect_first_A, expect_last_A, expect_break_A, expect_default_A;
2603         USHORT expect_first_W, expect_last_W, expect_break_W, expect_default_W;
2604         UINT os2_first_char, os2_last_char, default_char, break_char;
2605         USHORT version;
2606         TEXTMETRICW tmW;
2607
2608         version = GET_BE_WORD(tt_os2.version);
2609
2610         os2_first_char = GET_BE_WORD(tt_os2.usFirstCharIndex);
2611         os2_last_char = GET_BE_WORD(tt_os2.usLastCharIndex);
2612         default_char = GET_BE_WORD(tt_os2.usDefaultChar);
2613         break_char = GET_BE_WORD(tt_os2.usBreakChar);
2614
2615         trace("font %s charset %u: %x-%x (%x-%x) default %x break %x OS/2 version %u vendor %4.4s\n",
2616               font_name, lf->lfCharSet, os2_first_char, os2_last_char, cmap_first, cmap_last,
2617               default_char, break_char, version, (LPCSTR)&tt_os2.achVendID);
2618
2619         if (cmap_type == cmap_ms_symbol || (cmap_first >= 0xf000 && cmap_first < 0xf100))
2620         {
2621             expect_first_W    = 0;
2622             switch(GetACP())
2623             {
2624             case 1257:  /* Baltic */
2625                 expect_last_W = 0xf8fd;
2626                 break;
2627             default:
2628                 expect_last_W = 0xf0ff;
2629             }
2630             expect_break_W    = 0x20;
2631             expect_default_W  = expect_break_W - 1;
2632             expect_first_A    = 0x1e;
2633             expect_last_A     = min(os2_last_char - os2_first_char + 0x20, 0xff);
2634         }
2635         else
2636         {
2637             expect_first_W    = cmap_first;
2638             expect_last_W     = min(cmap_last, os2_last_char);
2639             if(os2_first_char <= 1)
2640                 expect_break_W = os2_first_char + 2;
2641             else if(os2_first_char > 0xff)
2642                 expect_break_W = 0x20;
2643             else
2644                 expect_break_W = os2_first_char;
2645             expect_default_W  = expect_break_W - 1;
2646             expect_first_A    = expect_default_W - 1;
2647             expect_last_A     = min(expect_last_W, 0xff);
2648         }
2649         expect_break_A    = expect_break_W;
2650         expect_default_A  = expect_default_W;
2651
2652         /* Wine currently uses SYMBOL_CHARSET to identify whether the ANSI metrics need special handling */
2653         if(cmap_type != cmap_ms_symbol && tmA.tmCharSet == SYMBOL_CHARSET && expect_first_A != 0x1e)
2654             todo_wine ok(tmA.tmFirstChar == expect_first_A ||
2655                          tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2656                          "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2657         else
2658             ok(tmA.tmFirstChar == expect_first_A ||
2659                tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2660                "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2661         if (pGdiGetCodePage == NULL || ! IsDBCSLeadByteEx(pGdiGetCodePage(hdc), tmA.tmLastChar))
2662             ok(tmA.tmLastChar == expect_last_A ||
2663                tmA.tmLastChar == 0xff /* win9x */,
2664                "A: tmLastChar for %s got %02x expected %02x\n", font_name, tmA.tmLastChar, expect_last_A);
2665         else
2666            skip("tmLastChar is DBCS lead byte\n");
2667         ok(tmA.tmBreakChar == expect_break_A, "A: tmBreakChar for %s got %02x expected %02x\n",
2668            font_name, tmA.tmBreakChar, expect_break_A);
2669         ok(tmA.tmDefaultChar == expect_default_A || broken(sys_lang_non_english),
2670            "A: tmDefaultChar for %s got %02x expected %02x\n",
2671            font_name, tmA.tmDefaultChar, expect_default_A);
2672
2673
2674         SetLastError(0xdeadbeef);
2675         ret = GetTextMetricsW(hdc, &tmW);
2676         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
2677            "GetTextMetricsW error %u\n", GetLastError());
2678         if (ret)
2679         {
2680             /* Wine uses the os2 first char */
2681             if(cmap_first != os2_first_char && cmap_type != cmap_ms_symbol)
2682                 todo_wine ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2683                              font_name, tmW.tmFirstChar, expect_first_W);
2684             else
2685                 ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2686                    font_name, tmW.tmFirstChar, expect_first_W);
2687
2688             /* Wine uses the os2 last char */
2689             if(expect_last_W != os2_last_char && cmap_type != cmap_ms_symbol)
2690                 todo_wine ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2691                              font_name, tmW.tmLastChar, expect_last_W);
2692             else
2693                 ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2694                    font_name, tmW.tmLastChar, expect_last_W);
2695             ok(tmW.tmBreakChar == expect_break_W, "W: tmBreakChar for %s got %02x expected %02x\n",
2696                font_name, tmW.tmBreakChar, expect_break_W);
2697             ok(tmW.tmDefaultChar == expect_default_W || broken(sys_lang_non_english),
2698                "W: tmDefaultChar for %s got %02x expected %02x\n",
2699                font_name, tmW.tmDefaultChar, expect_default_W);
2700
2701             /* Test the aspect ratio while we have tmW */
2702             ret = GetDeviceCaps(hdc, LOGPIXELSX);
2703             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectX %u != %u\n",
2704                tmW.tmDigitizedAspectX, ret);
2705             ret = GetDeviceCaps(hdc, LOGPIXELSY);
2706             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectY %u != %u\n",
2707                tmW.tmDigitizedAspectX, ret);
2708         }
2709     }
2710
2711     /* test FF_ values */
2712     switch(tt_os2.panose.bFamilyType)
2713     {
2714     case PAN_ANY:
2715     case PAN_NO_FIT:
2716     case PAN_FAMILY_TEXT_DISPLAY:
2717     case PAN_FAMILY_PICTORIAL:
2718     default:
2719         if((tmA.tmPitchAndFamily & 1) == 0 || /* fixed */
2720            tt_os2.panose.bProportion == PAN_PROP_MONOSPACED)
2721         {
2722             expect_ff(&tmA, &tt_os2, FF_MODERN, font_name);
2723             break;
2724         }
2725         switch(tt_os2.panose.bSerifStyle)
2726         {
2727         case PAN_ANY:
2728         case PAN_NO_FIT:
2729         default:
2730             expect_ff(&tmA, &tt_os2, FF_DONTCARE, font_name);
2731             break;
2732
2733         case PAN_SERIF_COVE:
2734         case PAN_SERIF_OBTUSE_COVE:
2735         case PAN_SERIF_SQUARE_COVE:
2736         case PAN_SERIF_OBTUSE_SQUARE_COVE:
2737         case PAN_SERIF_SQUARE:
2738         case PAN_SERIF_THIN:
2739         case PAN_SERIF_BONE:
2740         case PAN_SERIF_EXAGGERATED:
2741         case PAN_SERIF_TRIANGLE:
2742             expect_ff(&tmA, &tt_os2, FF_ROMAN, font_name);
2743             break;
2744
2745         case PAN_SERIF_NORMAL_SANS:
2746         case PAN_SERIF_OBTUSE_SANS:
2747         case PAN_SERIF_PERP_SANS:
2748         case PAN_SERIF_FLARED:
2749         case PAN_SERIF_ROUNDED:
2750             expect_ff(&tmA, &tt_os2, FF_SWISS, font_name);
2751             break;
2752         }
2753         break;
2754
2755     case PAN_FAMILY_SCRIPT:
2756         expect_ff(&tmA, &tt_os2, FF_SCRIPT, font_name);
2757         break;
2758
2759     case PAN_FAMILY_DECORATIVE:
2760         expect_ff(&tmA, &tt_os2, FF_DECORATIVE, font_name);
2761         break;
2762     }
2763
2764     test_negative_width(hdc, lf);
2765
2766 end_of_test:
2767     SelectObject(hdc, hfont_old);
2768     DeleteObject(hfont);
2769
2770     ReleaseDC(0, hdc);
2771 }
2772
2773 static INT CALLBACK enum_truetype_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
2774 {
2775     INT *enumed = (INT *)lParam;
2776
2777     if (type == TRUETYPE_FONTTYPE)
2778     {
2779         (*enumed)++;
2780         test_text_metrics(lf);
2781     }
2782     return 1;
2783 }
2784
2785 static void test_GetTextMetrics(void)
2786 {
2787     LOGFONTA lf;
2788     HDC hdc;
2789     INT enumed;
2790
2791     /* Report only once */
2792     if(!pGetGlyphIndicesA)
2793         win_skip("GetGlyphIndicesA is unavailable, negative width will not be checked\n");
2794
2795     hdc = GetDC(0);
2796
2797     memset(&lf, 0, sizeof(lf));
2798     lf.lfCharSet = DEFAULT_CHARSET;
2799     enumed = 0;
2800     EnumFontFamiliesExA(hdc, &lf, enum_truetype_font_proc, (LPARAM)&enumed, 0);
2801     trace("Tested metrics of %d truetype fonts\n", enumed);
2802
2803     ReleaseDC(0, hdc);
2804 }
2805
2806 static void test_nonexistent_font(void)
2807 {
2808     static const struct
2809     {
2810         const char *name;
2811         int charset;
2812     } font_subst[] =
2813     {
2814         { "Times New Roman Baltic", 186 },
2815         { "Times New Roman CE", 238 },
2816         { "Times New Roman CYR", 204 },
2817         { "Times New Roman Greek", 161 },
2818         { "Times New Roman TUR", 162 }
2819     };
2820     LOGFONTA lf;
2821     HDC hdc;
2822     HFONT hfont;
2823     CHARSETINFO csi;
2824     INT cs, expected_cs, i;
2825     char buf[LF_FACESIZE];
2826
2827     if (!is_truetype_font_installed("Arial") ||
2828         !is_truetype_font_installed("Times New Roman"))
2829     {
2830         skip("Arial or Times New Roman not installed\n");
2831         return;
2832     }
2833
2834     expected_cs = GetACP();
2835     if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
2836     {
2837         skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
2838         return;
2839     }
2840     expected_cs = csi.ciCharset;
2841     trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
2842
2843     hdc = GetDC(0);
2844
2845     memset(&lf, 0, sizeof(lf));
2846     lf.lfHeight = 100;
2847     lf.lfWeight = FW_REGULAR;
2848     lf.lfCharSet = ANSI_CHARSET;
2849     lf.lfPitchAndFamily = FF_SWISS;
2850     strcpy(lf.lfFaceName, "Nonexistent font");
2851     hfont = CreateFontIndirectA(&lf);
2852     hfont = SelectObject(hdc, hfont);
2853     GetTextFaceA(hdc, sizeof(buf), buf);
2854     ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
2855     cs = GetTextCharset(hdc);
2856     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2857     DeleteObject(SelectObject(hdc, hfont));
2858
2859     memset(&lf, 0, sizeof(lf));
2860     lf.lfHeight = -13;
2861     lf.lfWeight = FW_DONTCARE;
2862     strcpy(lf.lfFaceName, "Nonexistent font");
2863     hfont = CreateFontIndirectA(&lf);
2864     hfont = SelectObject(hdc, hfont);
2865     GetTextFaceA(hdc, sizeof(buf), buf);
2866 todo_wine /* Wine uses Arial for all substitutions */
2867     ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ ||
2868        !lstrcmpiA(buf, "MS Serif") || /* Win9x */
2869        !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
2870        "Got %s\n", buf);
2871     cs = GetTextCharset(hdc);
2872     ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d\n", expected_cs, cs);
2873     DeleteObject(SelectObject(hdc, hfont));
2874
2875     memset(&lf, 0, sizeof(lf));
2876     lf.lfHeight = -13;
2877     lf.lfWeight = FW_REGULAR;
2878     strcpy(lf.lfFaceName, "Nonexistent font");
2879     hfont = CreateFontIndirectA(&lf);
2880     hfont = SelectObject(hdc, hfont);
2881     GetTextFaceA(hdc, sizeof(buf), buf);
2882     ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
2883        !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "Got %s\n", buf);
2884     cs = GetTextCharset(hdc);
2885     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2886     DeleteObject(SelectObject(hdc, hfont));
2887
2888     memset(&lf, 0, sizeof(lf));
2889     lf.lfHeight = -13;
2890     lf.lfWeight = FW_DONTCARE;
2891     strcpy(lf.lfFaceName, "Times New Roman");
2892     hfont = CreateFontIndirectA(&lf);
2893     hfont = SelectObject(hdc, hfont);
2894     GetTextFaceA(hdc, sizeof(buf), buf);
2895     ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf);
2896     cs = GetTextCharset(hdc);
2897     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2898     DeleteObject(SelectObject(hdc, hfont));
2899
2900     for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++)
2901     {
2902         memset(&lf, 0, sizeof(lf));
2903         lf.lfHeight = -13;
2904         lf.lfWeight = FW_REGULAR;
2905         strcpy(lf.lfFaceName, font_subst[i].name);
2906         hfont = CreateFontIndirectA(&lf);
2907         hfont = SelectObject(hdc, hfont);
2908         cs = GetTextCharset(hdc);
2909         if (font_subst[i].charset == expected_cs)
2910         {
2911             ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
2912             GetTextFaceA(hdc, sizeof(buf), buf);
2913             ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf);
2914         }
2915         else
2916         {
2917             ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d for font %s\n", cs, font_subst[i].name);
2918             GetTextFaceA(hdc, sizeof(buf), buf);
2919             ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
2920                !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got %s for font %s\n", buf, font_subst[i].name);
2921         }
2922         DeleteObject(SelectObject(hdc, hfont));
2923
2924         memset(&lf, 0, sizeof(lf));
2925         lf.lfHeight = -13;
2926         lf.lfWeight = FW_DONTCARE;
2927         strcpy(lf.lfFaceName, font_subst[i].name);
2928         hfont = CreateFontIndirectA(&lf);
2929         hfont = SelectObject(hdc, hfont);
2930         GetTextFaceA(hdc, sizeof(buf), buf);
2931         ok(!lstrcmpiA(buf, "Arial") /* Wine */ ||
2932            !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ ||
2933            !lstrcmpiA(buf, "MS Serif") /* Win9x */ ||
2934            !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
2935            "got %s for font %s\n", buf, font_subst[i].name);
2936         cs = GetTextCharset(hdc);
2937         ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
2938         DeleteObject(SelectObject(hdc, hfont));
2939     }
2940
2941     ReleaseDC(0, hdc);
2942 }
2943
2944 static void test_GdiRealizationInfo(void)
2945 {
2946     HDC hdc;
2947     DWORD info[4];
2948     BOOL r;
2949     HFONT hfont, hfont_old;
2950     LOGFONTA lf;
2951
2952     if(!pGdiRealizationInfo)
2953     {
2954         win_skip("GdiRealizationInfo not available\n");
2955         return;
2956     }
2957
2958     hdc = GetDC(0);
2959
2960     memset(info, 0xcc, sizeof(info));
2961     r = pGdiRealizationInfo(hdc, info);
2962     ok(r != 0, "ret 0\n");
2963     ok((info[0] & 0xf) == 1, "info[0] = %x for the system font\n", info[0]);
2964     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
2965
2966     if (!is_truetype_font_installed("Arial"))
2967     {
2968         skip("skipping GdiRealizationInfo with truetype font\n");
2969         goto end;
2970     }
2971
2972     memset(&lf, 0, sizeof(lf));
2973     strcpy(lf.lfFaceName, "Arial");
2974     lf.lfHeight = 20;
2975     lf.lfWeight = FW_NORMAL;
2976     hfont = CreateFontIndirectA(&lf);
2977     hfont_old = SelectObject(hdc, hfont);
2978
2979     memset(info, 0xcc, sizeof(info));
2980     r = pGdiRealizationInfo(hdc, info);
2981     ok(r != 0, "ret 0\n");
2982     ok((info[0] & 0xf) == 3, "info[0] = %x for arial\n", info[0]);
2983     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
2984
2985     DeleteObject(SelectObject(hdc, hfont_old));
2986
2987  end:
2988     ReleaseDC(0, hdc);
2989 }
2990
2991 /* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include
2992    the nul in the count of characters copied when the face name buffer is not
2993    NULL, whereas it does if the buffer is NULL.  Further, the Unicode version
2994    always includes it.  */
2995 static void test_GetTextFace(void)
2996 {
2997     static const char faceA[] = "Tahoma";
2998     static const WCHAR faceW[] = {'T','a','h','o','m','a', 0};
2999     LOGFONTA fA = {0};
3000     LOGFONTW fW = {0};
3001     char bufA[LF_FACESIZE];
3002     WCHAR bufW[LF_FACESIZE];
3003     HFONT f, g;
3004     HDC dc;
3005     int n;
3006
3007     if(!is_font_installed("Tahoma"))
3008     {
3009         skip("Tahoma is not installed so skipping this test\n");
3010         return;
3011     }
3012
3013     /* 'A' case.  */
3014     memcpy(fA.lfFaceName, faceA, sizeof faceA);
3015     f = CreateFontIndirectA(&fA);
3016     ok(f != NULL, "CreateFontIndirectA failed\n");
3017
3018     dc = GetDC(NULL);
3019     g = SelectObject(dc, f);
3020     n = GetTextFaceA(dc, sizeof bufA, bufA);
3021     ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n);
3022     ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n");
3023
3024     /* Play with the count arg.  */
3025     bufA[0] = 'x';
3026     n = GetTextFaceA(dc, 0, bufA);
3027     ok(n == 0, "GetTextFaceA returned %d\n", n);
3028     ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]);
3029
3030     bufA[0] = 'x';
3031     n = GetTextFaceA(dc, 1, bufA);
3032     ok(n == 0, "GetTextFaceA returned %d\n", n);
3033     ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]);
3034
3035     bufA[0] = 'x'; bufA[1] = 'y';
3036     n = GetTextFaceA(dc, 2, bufA);
3037     ok(n == 1, "GetTextFaceA returned %d\n", n);
3038     ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n");
3039
3040     n = GetTextFaceA(dc, 0, NULL);
3041     ok(n == sizeof faceA ||
3042        broken(n == 0), /* win98, winMe */
3043        "GetTextFaceA returned %d\n", n);
3044
3045     DeleteObject(SelectObject(dc, g));
3046     ReleaseDC(NULL, dc);
3047
3048     /* 'W' case.  */
3049     memcpy(fW.lfFaceName, faceW, sizeof faceW);
3050     SetLastError(0xdeadbeef);
3051     f = CreateFontIndirectW(&fW);
3052     if (!f && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
3053     {
3054         win_skip("CreateFontIndirectW is not implemented\n");
3055         return;
3056     }
3057     ok(f != NULL, "CreateFontIndirectW failed\n");
3058
3059     dc = GetDC(NULL);
3060     g = SelectObject(dc, f);
3061     n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW);
3062     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
3063     ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
3064
3065     /* Play with the count arg.  */
3066     bufW[0] = 'x';
3067     n = GetTextFaceW(dc, 0, bufW);
3068     ok(n == 0, "GetTextFaceW returned %d\n", n);
3069     ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]);
3070
3071     bufW[0] = 'x';
3072     n = GetTextFaceW(dc, 1, bufW);
3073     ok(n == 1, "GetTextFaceW returned %d\n", n);
3074     ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]);
3075
3076     bufW[0] = 'x'; bufW[1] = 'y';
3077     n = GetTextFaceW(dc, 2, bufW);
3078     ok(n == 2, "GetTextFaceW returned %d\n", n);
3079     ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n");
3080
3081     n = GetTextFaceW(dc, 0, NULL);
3082     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
3083
3084     DeleteObject(SelectObject(dc, g));
3085     ReleaseDC(NULL, dc);
3086 }
3087
3088 static void test_orientation(void)
3089 {
3090     static const char test_str[11] = "Test String";
3091     HDC hdc;
3092     LOGFONTA lf;
3093     HFONT hfont, old_hfont;
3094     SIZE size;
3095
3096     if (!is_truetype_font_installed("Arial"))
3097     {
3098         skip("Arial is not installed\n");
3099         return;
3100     }
3101
3102     hdc = CreateCompatibleDC(0);
3103     memset(&lf, 0, sizeof(lf));
3104     lstrcpyA(lf.lfFaceName, "Arial");
3105     lf.lfHeight = 72;
3106     lf.lfOrientation = lf.lfEscapement = 900;
3107     hfont = create_font("orientation", &lf);
3108     old_hfont = SelectObject(hdc, hfont);
3109     ok(GetTextExtentExPointA(hdc, test_str, sizeof(test_str), 32767, NULL, NULL, &size), "GetTextExtentExPointA failed\n");
3110     ok(near_match(311, size.cx), "cx should be about 311, got %d\n", size.cx);
3111     ok(near_match(75, size.cy), "cy should be about 75, got %d\n", size.cy);
3112     SelectObject(hdc, old_hfont);
3113     DeleteObject(hfont);
3114     DeleteDC(hdc);
3115 }
3116
3117 static void test_oemcharset(void)
3118 {
3119     HDC hdc;
3120     LOGFONTA lf, clf;
3121     HFONT hfont, old_hfont;
3122     int charset;
3123
3124     hdc = CreateCompatibleDC(0);
3125     ZeroMemory(&lf, sizeof(lf));
3126     lf.lfHeight = 12;
3127     lf.lfCharSet = OEM_CHARSET;
3128     lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
3129     lstrcpyA(lf.lfFaceName, "Terminal");
3130     hfont = CreateFontIndirectA(&lf);
3131     old_hfont = SelectObject(hdc, hfont);
3132     charset = GetTextCharset(hdc);
3133 todo_wine
3134     ok(charset == OEM_CHARSET, "expected %d charset, got %d\n", OEM_CHARSET, charset);
3135     hfont = SelectObject(hdc, old_hfont);
3136     GetObjectA(hfont, sizeof(clf), &clf);
3137     ok(!lstrcmpA(clf.lfFaceName, lf.lfFaceName), "expected %s face name, got %s\n", lf.lfFaceName, clf.lfFaceName);
3138     ok(clf.lfPitchAndFamily == lf.lfPitchAndFamily, "expected %x family, got %x\n", lf.lfPitchAndFamily, clf.lfPitchAndFamily);
3139     ok(clf.lfCharSet == lf.lfCharSet, "expected %d charset, got %d\n", lf.lfCharSet, clf.lfCharSet);
3140     ok(clf.lfHeight == lf.lfHeight, "expected %d height, got %d\n", lf.lfHeight, clf.lfHeight);
3141     DeleteObject(hfont);
3142     DeleteDC(hdc);
3143 }
3144
3145 static void test_GetGlyphOutline(void)
3146 {
3147     HDC hdc;
3148     GLYPHMETRICS gm, gm2;
3149     LOGFONTA lf;
3150     HFONT hfont, old_hfont;
3151     INT ret, ret2;
3152     static const struct
3153     {
3154         UINT cs;
3155         UINT a;
3156         UINT w;
3157     } c[] =
3158     {
3159         {ANSI_CHARSET, 0x30, 0x30},
3160         {SHIFTJIS_CHARSET, 0x82a0, 0x3042},
3161         {HANGEUL_CHARSET, 0x8141, 0xac02},
3162         {JOHAB_CHARSET, 0x8446, 0x3135},
3163         {GB2312_CHARSET, 0x8141, 0x4e04},
3164         {CHINESEBIG5_CHARSET, 0xa142, 0x3001}
3165     };
3166     UINT i;
3167
3168     if (!is_truetype_font_installed("Tahoma"))
3169     {
3170         skip("Tahoma is not installed\n");
3171         return;
3172     }
3173
3174     hdc = CreateCompatibleDC(0);
3175     memset(&lf, 0, sizeof(lf));
3176     lf.lfHeight = 72;
3177     lstrcpyA(lf.lfFaceName, "Tahoma");
3178     SetLastError(0xdeadbeef);
3179     hfont = CreateFontIndirectA(&lf);
3180     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
3181     old_hfont = SelectObject(hdc, hfont);
3182
3183     memset(&gm, 0, sizeof(gm));
3184     SetLastError(0xdeadbeef);
3185     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3186     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
3187
3188     memset(&gm, 0, sizeof(gm));
3189     SetLastError(0xdeadbeef);
3190     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
3191     ok(ret == GDI_ERROR, "GetGlyphOutlineA should fail\n");
3192     ok(GetLastError() == 0xdeadbeef ||
3193        GetLastError() == ERROR_INVALID_PARAMETER, /* win98, winMe */
3194        "expected 0xdeadbeef, got %u\n", GetLastError());
3195
3196     memset(&gm, 0, sizeof(gm));
3197     SetLastError(0xdeadbeef);
3198     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3199     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3200         ok(ret != GDI_ERROR, "GetGlyphOutlineW error %u\n", GetLastError());
3201
3202     memset(&gm, 0, sizeof(gm));
3203     SetLastError(0xdeadbeef);
3204     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
3205     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3206     {
3207        ok(ret == GDI_ERROR, "GetGlyphOutlineW should fail\n");
3208        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
3209     }
3210
3211     /* test for needed buffer size request on space char */
3212     memset(&gm, 0, sizeof(gm));
3213     SetLastError(0xdeadbeef);
3214     ret = GetGlyphOutlineW(hdc, ' ', GGO_NATIVE, &gm, 0, NULL, &mat);
3215     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3216         ok(ret == 0, "GetGlyphOutlineW should return 0 buffer size for space char\n");
3217
3218     /* requesting buffer size for space char + error */
3219     memset(&gm, 0, sizeof(gm));
3220     SetLastError(0xdeadbeef);
3221     ret = GetGlyphOutlineW(0, ' ', GGO_NATIVE, &gm, 0, NULL, NULL);
3222     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3223     {
3224        ok(ret == GDI_ERROR, "GetGlyphOutlineW should return GDI_ERROR\n");
3225        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
3226     }
3227
3228     SelectObject(hdc, old_hfont);
3229     DeleteObject(hfont);
3230
3231     for (i = 0; i < sizeof c / sizeof c[0]; ++i)
3232     {
3233         lf.lfFaceName[0] = '\0';
3234         lf.lfCharSet = c[i].cs;
3235         lf.lfPitchAndFamily = 0;
3236         if (EnumFontFamiliesEx(hdc, &lf, create_font_proc, (LPARAM)&hfont, 0))
3237         {
3238             skip("TrueType font for charset %u is not installed\n", c[i].cs);
3239             continue;
3240         }
3241
3242         old_hfont = SelectObject(hdc, hfont);
3243
3244         ret = GetGlyphOutlineA(hdc, 0x8041, GGO_BITMAP, &gm, 0, NULL, &mat);
3245         ret2 = GetGlyphOutlineA(hdc, 0x41, GGO_BITMAP, &gm2, 0, NULL, &mat);
3246         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
3247
3248         ret = GetGlyphOutlineA(hdc, c[i].a, GGO_BITMAP, &gm, 0, NULL, &mat);
3249         ret2 = GetGlyphOutlineW(hdc, c[i].w, GGO_BITMAP, &gm2, 0, NULL, &mat);
3250         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
3251
3252         hfont = SelectObject(hdc, old_hfont);
3253         DeleteObject(hfont);
3254     }
3255
3256     DeleteDC(hdc);
3257 }
3258
3259 /* bug #9995: there is a limit to the character width that can be specified */
3260 static void test_GetTextMetrics2(const char *fontname, int font_height)
3261 {
3262     HFONT of, hf;
3263     HDC hdc;
3264     TEXTMETRICA tm;
3265     BOOL ret;
3266     int ave_width, height, width, ratio, scale;
3267
3268     if (!is_truetype_font_installed( fontname)) {
3269         skip("%s is not installed\n", fontname);
3270         return;
3271     }
3272     hdc = CreateCompatibleDC(0);
3273     ok( hdc != NULL, "CreateCompatibleDC failed\n");
3274     /* select width = 0 */
3275     hf = CreateFontA(font_height, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3276             DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3277             DEFAULT_QUALITY, VARIABLE_PITCH,
3278             fontname);
3279     ok( hf != NULL, "CreateFontA(%s, %d) failed\n", fontname, font_height);
3280     of = SelectObject( hdc, hf);
3281     ret = GetTextMetricsA( hdc, &tm);
3282     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
3283     height = tm.tmHeight;
3284     ave_width = tm.tmAveCharWidth;
3285     SelectObject( hdc, of);
3286     DeleteObject( hf);
3287
3288     trace("height %d, ave width %d\n", height, ave_width);
3289
3290     for (width = ave_width * 2; /* nothing*/; width += ave_width)
3291     {
3292         hf = CreateFont(height, width, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3293                         DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3294                         DEFAULT_QUALITY, VARIABLE_PITCH, fontname);
3295         ok(hf != 0, "CreateFont failed\n");
3296         of = SelectObject(hdc, hf);
3297         ret = GetTextMetrics(hdc, &tm);
3298         ok(ret, "GetTextMetrics error %u\n", GetLastError());
3299         SelectObject(hdc, of);
3300         DeleteObject(hf);
3301
3302         if (match_off_by_1(tm.tmAveCharWidth, ave_width) || width / height > 200)
3303             break;
3304     }
3305
3306     DeleteDC(hdc);
3307
3308     ratio = width / height;
3309     scale = width / ave_width;
3310
3311     trace("max width/height ratio (%d / %d) %d, max width scale (%d / %d) %d\n",
3312           width, height, ratio, width, ave_width, scale);
3313
3314     ok(ratio >= 90 && ratio <= 110, "expected width/height ratio 90-110, got %d\n", ratio);
3315 }
3316
3317 static void test_CreateFontIndirect(void)
3318 {
3319     LOGFONTA lf, getobj_lf;
3320     int ret, i;
3321     HFONT hfont;
3322     char TestName[][16] = {"Arial", "Arial Bold", "Arial Italic", "Arial Baltic"};
3323
3324     memset(&lf, 0, sizeof(lf));
3325     lf.lfCharSet = ANSI_CHARSET;
3326     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
3327     lf.lfHeight = 16;
3328     lf.lfWidth = 16;
3329     lf.lfQuality = DEFAULT_QUALITY;
3330     lf.lfItalic = FALSE;
3331     lf.lfWeight = FW_DONTCARE;
3332
3333     for (i = 0; i < sizeof(TestName)/sizeof(TestName[0]); i++)
3334     {
3335         lstrcpyA(lf.lfFaceName, TestName[i]);
3336         hfont = CreateFontIndirectA(&lf);
3337         ok(hfont != 0, "CreateFontIndirectA failed\n");
3338         SetLastError(0xdeadbeef);
3339         ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf);
3340         ok(ret, "GetObject failed: %d\n", GetLastError());
3341         ok(lf.lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf.lfItalic, getobj_lf.lfItalic);
3342         ok(lf.lfWeight == getobj_lf.lfWeight ||
3343            broken((SHORT)lf.lfWeight == getobj_lf.lfWeight), /* win9x */
3344            "lfWeight: expect %08x got %08x\n", lf.lfWeight, getobj_lf.lfWeight);
3345         ok(!lstrcmpA(lf.lfFaceName, getobj_lf.lfFaceName) ||
3346            broken(!memcmp(lf.lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
3347            "font names don't match: %s != %s\n", lf.lfFaceName, getobj_lf.lfFaceName);
3348         DeleteObject(hfont);
3349     }
3350 }
3351
3352 static void test_CreateFontIndirectEx(void)
3353 {
3354     ENUMLOGFONTEXDVA lfex;
3355     HFONT hfont;
3356
3357     if (!pCreateFontIndirectExA)
3358     {
3359         win_skip("CreateFontIndirectExA is not available\n");
3360         return;
3361     }
3362
3363     if (!is_truetype_font_installed("Arial"))
3364     {
3365         skip("Arial is not installed\n");
3366         return;
3367     }
3368
3369     SetLastError(0xdeadbeef);
3370     hfont = pCreateFontIndirectExA(NULL);
3371     ok(hfont == NULL, "got %p\n", hfont);
3372     ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
3373
3374     memset(&lfex, 0, sizeof(lfex));
3375     lstrcpyA(lfex.elfEnumLogfontEx.elfLogFont.lfFaceName, "Arial");
3376     hfont = pCreateFontIndirectExA(&lfex);
3377     ok(hfont != 0, "CreateFontIndirectEx failed\n");
3378     if (hfont)
3379         check_font("Arial", &lfex.elfEnumLogfontEx.elfLogFont, hfont);
3380     DeleteObject(hfont);
3381 }
3382
3383 static void free_font(void *font)
3384 {
3385     UnmapViewOfFile(font);
3386 }
3387
3388 static void *load_font(const char *font_name, DWORD *font_size)
3389 {
3390     char file_name[MAX_PATH];
3391     HANDLE file, mapping;
3392     void *font;
3393
3394     if (!GetWindowsDirectory(file_name, sizeof(file_name))) return NULL;
3395     strcat(file_name, "\\fonts\\");
3396     strcat(file_name, font_name);
3397
3398     file = CreateFile(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
3399     if (file == INVALID_HANDLE_VALUE) return NULL;
3400
3401     *font_size = GetFileSize(file, NULL);
3402
3403     mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
3404     if (!mapping)
3405     {
3406         CloseHandle(file);
3407         return NULL;
3408     }
3409
3410     font = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
3411
3412     CloseHandle(file);
3413     CloseHandle(mapping);
3414     return font;
3415 }
3416
3417 static void test_AddFontMemResource(void)
3418 {
3419     void *font;
3420     DWORD font_size, num_fonts;
3421     HANDLE ret;
3422     BOOL bRet;
3423
3424     if (!pAddFontMemResourceEx || !pRemoveFontMemResourceEx)
3425     {
3426         win_skip("AddFontMemResourceEx is not available on this platform\n");
3427         return;
3428     }
3429
3430     font = load_font("sserife.fon", &font_size);
3431     if (!font)
3432     {
3433         skip("Unable to locate and load font sserife.fon\n");
3434         return;
3435     }
3436
3437     SetLastError(0xdeadbeef);
3438     ret = pAddFontMemResourceEx(NULL, 0, NULL, NULL);
3439     ok(!ret, "AddFontMemResourceEx should fail\n");
3440     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3441        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3442        GetLastError());
3443
3444     SetLastError(0xdeadbeef);
3445     ret = pAddFontMemResourceEx(NULL, 10, NULL, NULL);
3446     ok(!ret, "AddFontMemResourceEx should fail\n");
3447     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3448        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3449        GetLastError());
3450
3451     SetLastError(0xdeadbeef);
3452     ret = pAddFontMemResourceEx(NULL, 0, NULL, &num_fonts);
3453     ok(!ret, "AddFontMemResourceEx should fail\n");
3454     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3455        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3456        GetLastError());
3457
3458     SetLastError(0xdeadbeef);
3459     ret = pAddFontMemResourceEx(NULL, 10, NULL, &num_fonts);
3460     ok(!ret, "AddFontMemResourceEx should fail\n");
3461     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3462        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3463        GetLastError());
3464
3465     SetLastError(0xdeadbeef);
3466     ret = pAddFontMemResourceEx(font, 0, NULL, NULL);
3467     ok(!ret, "AddFontMemResourceEx should fail\n");
3468     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3469        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3470        GetLastError());
3471
3472     SetLastError(0xdeadbeef);
3473     ret = pAddFontMemResourceEx(font, 10, NULL, NULL);
3474     ok(!ret, "AddFontMemResourceEx should fail\n");
3475     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3476        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3477        GetLastError());
3478
3479     num_fonts = 0xdeadbeef;
3480     SetLastError(0xdeadbeef);
3481     ret = pAddFontMemResourceEx(font, 0, NULL, &num_fonts);
3482     ok(!ret, "AddFontMemResourceEx should fail\n");
3483     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3484        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3485        GetLastError());
3486     ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
3487
3488     if (0) /* hangs under windows 2000 */
3489     {
3490         num_fonts = 0xdeadbeef;
3491         SetLastError(0xdeadbeef);
3492         ret = pAddFontMemResourceEx(font, 10, NULL, &num_fonts);
3493         ok(!ret, "AddFontMemResourceEx should fail\n");
3494         ok(GetLastError() == 0xdeadbeef,
3495            "Expected GetLastError() to return 0xdeadbeef, got %u\n",
3496            GetLastError());
3497         ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
3498     }
3499
3500     num_fonts = 0xdeadbeef;
3501     SetLastError(0xdeadbeef);
3502     ret = pAddFontMemResourceEx(font, font_size, NULL, &num_fonts);
3503     ok(ret != 0, "AddFontMemResourceEx error %d\n", GetLastError());
3504     ok(num_fonts != 0xdeadbeef, "number of loaded fonts should not be 0xdeadbeef\n");
3505     ok(num_fonts != 0, "number of loaded fonts should not be 0\n");
3506
3507     free_font(font);
3508
3509     SetLastError(0xdeadbeef);
3510     bRet = pRemoveFontMemResourceEx(ret);
3511     ok(bRet, "RemoveFontMemResourceEx error %d\n", GetLastError());
3512
3513     /* test invalid pointer to number of loaded fonts */
3514     font = load_font("sserife.fon", &font_size);
3515     ok(font != NULL, "Unable to locate and load font sserife.fon\n");
3516
3517     SetLastError(0xdeadbeef);
3518     ret = pAddFontMemResourceEx(font, font_size, NULL, (void *)0xdeadbeef);
3519     ok(!ret, "AddFontMemResourceEx should fail\n");
3520     ok(GetLastError() == 0xdeadbeef,
3521        "Expected GetLastError() to return 0xdeadbeef, got %u\n",
3522        GetLastError());
3523
3524     SetLastError(0xdeadbeef);
3525     ret = pAddFontMemResourceEx(font, font_size, NULL, NULL);
3526     ok(!ret, "AddFontMemResourceEx should fail\n");
3527     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3528        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3529        GetLastError());
3530
3531     free_font(font);
3532 }
3533
3534 static INT CALLBACK enum_fonts_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3535 {
3536     LOGFONT *lf;
3537
3538     if (type != TRUETYPE_FONTTYPE) return 1;
3539
3540     ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
3541
3542     lf = (LOGFONT *)lparam;
3543     *lf = *elf;
3544     return 0;
3545 }
3546
3547 static INT CALLBACK enum_all_fonts_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3548 {
3549     int ret;
3550     LOGFONT *lf;
3551
3552     if (type != TRUETYPE_FONTTYPE) return 1;
3553
3554     lf = (LOGFONT *)lparam;
3555     ret = strcmp(lf->lfFaceName, elf->lfFaceName);
3556     if(ret == 0)
3557     {
3558         ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
3559         *lf = *elf;
3560         return 0;
3561     }
3562     return 1;
3563 }
3564
3565 static void test_EnumFonts(void)
3566 {
3567     int ret;
3568     LOGFONT lf;
3569     HDC hdc;
3570
3571     if (!is_truetype_font_installed("Arial"))
3572     {
3573         skip("Arial is not installed\n");
3574         return;
3575     }
3576
3577     /* Windows uses localized font face names, so Arial Bold won't be found */
3578     if (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH)
3579     {
3580         skip("User locale is not English, skipping the test\n");
3581         return;
3582     }
3583
3584     hdc = CreateCompatibleDC(0);
3585
3586     ret = EnumFontFamilies(hdc, "Arial", enum_fonts_proc, (LPARAM)&lf);
3587     ok(!ret, "font Arial is not enumerated\n");
3588     ret = strcmp(lf.lfFaceName, "Arial");
3589     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3590     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
3591
3592     lstrcpy(lf.lfFaceName, "Arial");
3593     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3594     ok(!ret, "font Arial is not enumerated\n");
3595     ret = strcmp(lf.lfFaceName, "Arial");
3596     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3597     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
3598
3599     ret = EnumFontFamilies(hdc, "Arial Bold", enum_fonts_proc, (LPARAM)&lf);
3600     ok(!ret, "font Arial Bold is not enumerated\n");
3601     ret = strcmp(lf.lfFaceName, "Arial");
3602     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3603     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
3604
3605     lstrcpy(lf.lfFaceName, "Arial Bold");
3606     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3607     ok(ret, "font Arial Bold should not be enumerated\n");
3608
3609     ret = EnumFontFamilies(hdc, "Arial Bold Italic", enum_fonts_proc, (LPARAM)&lf);
3610     ok(!ret, "font Arial Bold Italic is not enumerated\n");
3611     ret = strcmp(lf.lfFaceName, "Arial");
3612     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3613     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
3614
3615     lstrcpy(lf.lfFaceName, "Arial Bold Italic");
3616     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3617     ok(ret, "font Arial Bold Italic should not be enumerated\n");
3618
3619     ret = EnumFontFamilies(hdc, "Arial Italic Bold", enum_fonts_proc, (LPARAM)&lf);
3620     ok(ret, "font Arial Italic Bold  should not be enumerated\n");
3621
3622     lstrcpy(lf.lfFaceName, "Arial Italic Bold");
3623     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3624     ok(ret, "font Arial Italic Bold should not be enumerated\n");
3625
3626     DeleteDC(hdc);
3627 }
3628
3629 START_TEST(font)
3630 {
3631     init();
3632
3633     test_logfont();
3634     test_bitmap_font();
3635     test_outline_font();
3636     test_bitmap_font_metrics();
3637     test_GdiGetCharDimensions();
3638     test_GetCharABCWidths();
3639     test_text_extents();
3640     test_GetGlyphIndices();
3641     test_GetKerningPairs();
3642     test_GetOutlineTextMetrics();
3643     test_SetTextJustification();
3644     test_font_charset();
3645     test_GetFontUnicodeRanges();
3646     test_nonexistent_font();
3647     test_orientation();
3648     test_height_selection();
3649     test_AddFontMemResource();
3650     test_EnumFonts();
3651
3652     /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
3653      * I'd like to avoid them in this test.
3654      */
3655     test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
3656     test_EnumFontFamilies("Symbol", SYMBOL_CHARSET);
3657     if (is_truetype_font_installed("Arial Black") &&
3658         (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
3659     {
3660         test_EnumFontFamilies("", ANSI_CHARSET);
3661         test_EnumFontFamilies("", SYMBOL_CHARSET);
3662         test_EnumFontFamilies("", DEFAULT_CHARSET);
3663     }
3664     else
3665         skip("Arial Black or Symbol/Wingdings is not installed\n");
3666     test_EnumFontFamiliesEx_default_charset();
3667     test_GetTextMetrics();
3668     test_GdiRealizationInfo();
3669     test_GetTextFace();
3670     test_GetGlyphOutline();
3671     test_GetTextMetrics2("Tahoma", -11);
3672     test_GetTextMetrics2("Tahoma", -55);
3673     test_GetTextMetrics2("Tahoma", -110);
3674     test_GetTextMetrics2("Arial", -11);
3675     test_GetTextMetrics2("Arial", -55);
3676     test_GetTextMetrics2("Arial", -110);
3677     test_CreateFontIndirect();
3678     test_CreateFontIndirectEx();
3679     test_oemcharset();
3680 }