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