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