gdi32/tests: Fix System font test for Japanese.
[wine] / dlls / gdi32 / tests / font.c
1 /*
2  * Unit test suite for fonts
3  *
4  * Copyright 2002 Mike McCormack
5  * Copyright 2004 Dmitry Timoshkov
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23 #include <assert.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winnls.h"
30
31 #include "wine/test.h"
32
33 /* Do not allow more than 1 deviation here */
34 #define match_off_by_1(a, b) (abs((a) - (b)) <= 1)
35
36 #define near_match(a, b) (abs((a) - (b)) <= 6)
37 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
38
39 static LONG  (WINAPI *pGdiGetCharDimensions)(HDC hdc, LPTEXTMETRICW lptm, LONG *height);
40 static BOOL  (WINAPI *pGetCharABCWidthsI)(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPABC abc);
41 static BOOL  (WINAPI *pGetCharABCWidthsW)(HDC hdc, UINT first, UINT last, LPABC abc);
42 static DWORD (WINAPI *pGetFontUnicodeRanges)(HDC hdc, LPGLYPHSET lpgs);
43 static DWORD (WINAPI *pGetGlyphIndicesA)(HDC hdc, LPCSTR lpstr, INT count, LPWORD pgi, DWORD flags);
44 static DWORD (WINAPI *pGetGlyphIndicesW)(HDC hdc, LPCWSTR lpstr, INT count, LPWORD pgi, DWORD flags);
45 static BOOL  (WINAPI *pGdiRealizationInfo)(HDC hdc, DWORD *);
46 static HFONT (WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDV *);
47 static HANDLE (WINAPI *pAddFontMemResourceEx)(PVOID, DWORD, PVOID, DWORD *);
48 static 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         { "System", FW_NORMAL, 18, 16, 2, 0, 2, 8, 16, 96, FS_JISJAPAN },
733
734         { "System", FW_BOLD, 20, 16, 4, 4, 0, 9, 14, 120, FS_LATIN1 },
735         { "System", FW_BOLD, 20, 16, 4, 4, 0, 9, 17, 120, FS_LATIN2 | FS_CYRILLIC },
736
737         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 2, 96, FS_LATIN1 },
738         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 8, 96, FS_LATIN2 | FS_CYRILLIC },
739         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 2, 4, 96, FS_JISJAPAN },
740         { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 3, 4, 96, FS_LATIN1 },
741         { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 2, 8, 96, FS_LATIN2 | FS_CYRILLIC },
742         { "Small Fonts", FW_NORMAL, 5, 4, 1, 0, 0, 3, 6, 96, FS_JISJAPAN },
743         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 13, 96, FS_LATIN1 },
744         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 96, FS_LATIN2 | FS_CYRILLIC },
745         { "Small Fonts", FW_NORMAL, 6, 5, 1, 0, 0, 4, 8, 96, FS_JISJAPAN },
746         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 7, 96, FS_LATIN1 },
747         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 96, FS_LATIN2 | FS_CYRILLIC },
748         { "Small Fonts", FW_NORMAL, 8, 7, 1, 0, 0, 5, 10, 96, FS_JISJAPAN },
749         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8, 96, FS_LATIN1 | FS_LATIN2 },
750         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 96, FS_CYRILLIC },
751         { "Small Fonts", FW_NORMAL, 10, 8, 2, 0, 0, 6, 12, 96, FS_JISJAPAN },
752         { "Small Fonts", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9, 96, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
753         { "Small Fonts", FW_NORMAL, 11, 9, 2, 0, 0, 7, 14, 96, FS_JISJAPAN },
754
755         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 2, 120, FS_LATIN1 | FS_JISJAPAN },
756         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 8, 120, FS_LATIN2 | FS_CYRILLIC },
757         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 5, 120, FS_LATIN1 | FS_JISJAPAN },
758         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 120, FS_LATIN2 | FS_CYRILLIC },
759         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 7, 120, FS_LATIN1 | FS_JISJAPAN },
760         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 120, FS_LATIN2 | FS_CYRILLIC },
761         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 9, 120, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
762         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 120, FS_CYRILLIC },
763         { "Small Fonts", FW_NORMAL, 12, 10, 2, 2, 0, 5, 10, 120, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
764         { "Small Fonts", FW_NORMAL, 12, 10, 2, 2, 0, 6, 10, 120, FS_CYRILLIC },
765         { "Small Fonts", FW_NORMAL, 13, 11, 2, 2, 0, 6, 12, 120, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
766         { "Small Fonts", FW_NORMAL, 13, 11, 2, 2, 0, 6, 11, 120, FS_CYRILLIC },
767
768         { "Fixedsys", FW_NORMAL, 15, 12, 3, 3, 0, 8, 8, 96, FS_LATIN1 | FS_LATIN2 },
769         { "Fixedsys", FW_NORMAL, 16, 12, 4, 3, 0, 8, 8, 96, FS_CYRILLIC },
770         { "FixedSys", FW_NORMAL, 18, 16, 2, 0, 0, 8, 16, 96, FS_JISJAPAN },
771
772         /* The 120dpi version still has its dpi marked as 96 */
773         { "Fixedsys", FW_NORMAL, 20, 16, 4, 2, 0, 10, 10, 96, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC }
774
775         /* FIXME: add "Terminal" */
776     };
777     HDC hdc;
778     LOGFONT lf;
779     HFONT hfont, old_hfont;
780     TEXTMETRIC tm;
781     INT ret, i;
782
783     hdc = CreateCompatibleDC(0);
784     assert(hdc);
785
786     for (i = 0; i < sizeof(fd)/sizeof(fd[0]); i++)
787     {
788         int bit;
789
790         memset(&lf, 0, sizeof(lf));
791
792         lf.lfHeight = fd[i].height;
793         strcpy(lf.lfFaceName, fd[i].face_name);
794
795         for(bit = 0; bit < 32; bit++)
796         {
797             DWORD fs[2];
798             CHARSETINFO csi;
799             BOOL bRet;
800
801             fs[0] = 1L << bit;
802             fs[1] = 0;
803             if((fd[i].ansi_bitfield & fs[0]) == 0) continue;
804             if(!TranslateCharsetInfo( fs, &csi, TCI_SRCFONTSIG )) continue;
805
806             lf.lfCharSet = csi.ciCharset;
807             ret = EnumFontFamiliesEx(hdc, &lf, find_font_proc, (LPARAM)&lf, 0);
808             if (ret) continue;
809
810             hfont = create_font(lf.lfFaceName, &lf);
811             old_hfont = SelectObject(hdc, hfont);
812             bRet = GetTextMetrics(hdc, &tm);
813             ok(bRet, "GetTextMetrics error %d\n", GetLastError());
814             if(fd[i].dpi == tm.tmDigitizedAspectX)
815             {
816                 trace("found font %s, height %d charset %x dpi %d\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet, fd[i].dpi);
817                 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);
818                 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);
819                 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);
820                 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);
821                 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);
822                 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);
823                 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);
824
825                 /* Don't run the max char width test on System/ANSI_CHARSET.  We have extra characters in our font
826                    that make the max width bigger */
827                 if(strcmp(lf.lfFaceName, "System") || lf.lfCharSet != ANSI_CHARSET)
828                     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);
829             }
830             SelectObject(hdc, old_hfont);
831             DeleteObject(hfont);
832         }
833     }
834
835     DeleteDC(hdc);
836 }
837
838 static void test_GdiGetCharDimensions(void)
839 {
840     HDC hdc;
841     TEXTMETRICW tm;
842     LONG ret;
843     SIZE size;
844     LONG avgwidth, height;
845     static const char szAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
846
847     if (!pGdiGetCharDimensions)
848     {
849         win_skip("GdiGetCharDimensions not available on this platform\n");
850         return;
851     }
852
853     hdc = CreateCompatibleDC(NULL);
854
855     GetTextExtentPoint(hdc, szAlphabet, strlen(szAlphabet), &size);
856     avgwidth = ((size.cx / 26) + 1) / 2;
857
858     ret = pGdiGetCharDimensions(hdc, &tm, &height);
859     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
860     ok(height == tm.tmHeight, "GdiGetCharDimensions should have set height to %d instead of %d\n", tm.tmHeight, height);
861
862     ret = pGdiGetCharDimensions(hdc, &tm, NULL);
863     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
864
865     ret = pGdiGetCharDimensions(hdc, NULL, NULL);
866     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
867
868     height = 0;
869     ret = pGdiGetCharDimensions(hdc, NULL, &height);
870     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
871     ok(height == size.cy, "GdiGetCharDimensions should have set height to %d instead of %d\n", size.cy, height);
872
873     DeleteDC(hdc);
874 }
875
876 static void test_GetCharABCWidths(void)
877 {
878     static const WCHAR str[] = {'a',0};
879     BOOL ret;
880     HDC hdc;
881     LOGFONTA lf;
882     HFONT hfont;
883     ABC abc[1];
884     WORD glyphs[1];
885     DWORD nb;
886
887     if (!pGetCharABCWidthsW || !pGetCharABCWidthsI)
888     {
889         win_skip("GetCharABCWidthsW/I not available on this platform\n");
890         return;
891     }
892
893     memset(&lf, 0, sizeof(lf));
894     strcpy(lf.lfFaceName, "System");
895     lf.lfHeight = 20;
896
897     hfont = CreateFontIndirectA(&lf);
898     hdc = GetDC(0);
899     hfont = SelectObject(hdc, hfont);
900
901     nb = pGetGlyphIndicesW(hdc, str, 1, glyphs, 0);
902     ok(nb == 1, "GetGlyphIndicesW should have returned 1\n");
903
904     ret = pGetCharABCWidthsI(NULL, 0, 1, glyphs, abc);
905     ok(!ret, "GetCharABCWidthsI should have failed\n");
906
907     ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, NULL);
908     ok(!ret, "GetCharABCWidthsI should have failed\n");
909
910     ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, abc);
911     ok(ret, "GetCharABCWidthsI should have succeeded\n");
912
913     ret = pGetCharABCWidthsW(NULL, 'a', 'a', abc);
914     ok(!ret, "GetCharABCWidthsW should have failed\n");
915
916     ret = pGetCharABCWidthsW(hdc, 'a', 'a', NULL);
917     ok(!ret, "GetCharABCWidthsW should have failed\n");
918
919     ret = pGetCharABCWidthsW(hdc, 'a', 'a', abc);
920     ok(!ret, "GetCharABCWidthsW should have failed\n");
921
922     hfont = SelectObject(hdc, hfont);
923     DeleteObject(hfont);
924     ReleaseDC(NULL, hdc);
925 }
926
927 static void test_text_extents(void)
928 {
929     static const WCHAR wt[] = {'O','n','e','\n','t','w','o',' ','3',0};
930     LPINT extents;
931     INT i, len, fit1, fit2;
932     LOGFONTA lf;
933     TEXTMETRICA tm;
934     HDC hdc;
935     HFONT hfont;
936     SIZE sz;
937     SIZE sz1, sz2;
938
939     memset(&lf, 0, sizeof(lf));
940     strcpy(lf.lfFaceName, "Arial");
941     lf.lfHeight = 20;
942
943     hfont = CreateFontIndirectA(&lf);
944     hdc = GetDC(0);
945     hfont = SelectObject(hdc, hfont);
946     GetTextMetricsA(hdc, &tm);
947     GetTextExtentPointA(hdc, "o", 1, &sz);
948     ok(sz.cy == tm.tmHeight, "cy %d tmHeight %d\n", sz.cy, tm.tmHeight);
949
950     SetLastError(0xdeadbeef);
951     GetTextExtentExPointW(hdc, wt, 1, 1, &fit1, &fit2, &sz1);
952     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
953     {
954         win_skip("Skipping remainder of text extents test on a Win9x platform\n");
955         hfont = SelectObject(hdc, hfont);
956         DeleteObject(hfont);
957         ReleaseDC(0, hdc);
958         return;
959     }
960
961     len = lstrlenW(wt);
962     extents = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof extents[0]);
963     extents[0] = 1;         /* So that the increasing sequence test will fail
964                                if the extents array is untouched.  */
965     GetTextExtentExPointW(hdc, wt, len, 32767, &fit1, extents, &sz1);
966     GetTextExtentPointW(hdc, wt, len, &sz2);
967     ok(sz1.cy == sz2.cy,
968        "cy from GetTextExtentExPointW (%d) and GetTextExtentPointW (%d) differ\n", sz1.cy, sz2.cy);
969     /* Because of the '\n' in the string GetTextExtentExPoint and
970        GetTextExtentPoint return different widths under Win2k, but
971        under WinXP they return the same width.  So we don't test that
972        here. */
973
974     for (i = 1; i < len; ++i)
975         ok(extents[i-1] <= extents[i],
976            "GetTextExtentExPointW generated a non-increasing sequence of partial extents (at position %d)\n",
977            i);
978     ok(extents[len-1] == sz1.cx, "GetTextExtentExPointW extents and size don't match\n");
979     ok(0 <= fit1 && fit1 <= len, "GetTextExtentExPointW generated illegal value %d for fit\n", fit1);
980     ok(0 < fit1, "GetTextExtentExPointW says we can't even fit one letter in 32767 logical units\n");
981     GetTextExtentExPointW(hdc, wt, len, extents[2], &fit2, NULL, &sz2);
982     ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy, "GetTextExtentExPointW returned different sizes for the same string\n");
983     ok(fit2 == 3, "GetTextExtentExPointW extents isn't consistent with fit\n");
984     GetTextExtentExPointW(hdc, wt, len, extents[2]-1, &fit2, NULL, &sz2);
985     ok(fit2 == 2, "GetTextExtentExPointW extents isn't consistent with fit\n");
986     GetTextExtentExPointW(hdc, wt, 2, 0, NULL, extents + 2, &sz2);
987     ok(extents[0] == extents[2] && extents[1] == extents[3],
988        "GetTextExtentExPointW with lpnFit == NULL returns incorrect results\n");
989     GetTextExtentExPointW(hdc, wt, 2, 0, NULL, NULL, &sz1);
990     ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy,
991        "GetTextExtentExPointW with lpnFit and alpDx both NULL returns incorrect results\n");
992     HeapFree(GetProcessHeap(), 0, extents);
993
994     hfont = SelectObject(hdc, hfont);
995     DeleteObject(hfont);
996     ReleaseDC(NULL, hdc);
997 }
998
999 static void test_GetGlyphIndices(void)
1000 {
1001     HDC      hdc;
1002     HFONT    hfont;
1003     DWORD    charcount;
1004     LOGFONTA lf;
1005     DWORD    flags = 0;
1006     WCHAR    testtext[] = {'T','e','s','t',0xffff,0};
1007     WORD     glyphs[(sizeof(testtext)/2)-1];
1008     TEXTMETRIC textm;
1009     HFONT hOldFont;
1010
1011     if (!pGetGlyphIndicesW) {
1012         win_skip("GetGlyphIndicesW not available on platform\n");
1013         return;
1014     }
1015
1016     hdc = GetDC(0);
1017
1018     memset(&lf, 0, sizeof(lf));
1019     strcpy(lf.lfFaceName, "System");
1020     lf.lfHeight = 16;
1021     lf.lfCharSet = ANSI_CHARSET;
1022
1023     hfont = CreateFontIndirectA(&lf);
1024     ok(GetTextMetrics(hdc, &textm), "GetTextMetric failed\n");
1025     if (textm.tmCharSet == ANSI_CHARSET)
1026     {
1027         flags |= GGI_MARK_NONEXISTING_GLYPHS;
1028         charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1029         ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1030         ok((glyphs[4] == 0x001f || glyphs[4] == 0xffff /* Vista */), "GetGlyphIndicesW should have returned a nonexistent char not %04x\n", glyphs[4]);
1031         flags = 0;
1032         charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1033         ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1034         ok(glyphs[4] == textm.tmDefaultChar, "GetGlyphIndicesW should have returned a %04x not %04x\n",
1035                         textm.tmDefaultChar, glyphs[4]);
1036     }
1037     else
1038         /* FIXME: Write tests for non-ANSI charsets. */
1039         skip("GetGlyphIndices System font tests only for ANSI_CHARSET\n");
1040
1041     if(!is_font_installed("Tahoma"))
1042     {
1043         skip("Tahoma is not installed so skipping this test\n");
1044         return;
1045     }
1046     memset(&lf, 0, sizeof(lf));
1047     strcpy(lf.lfFaceName, "Tahoma");
1048     lf.lfHeight = 20;
1049
1050     hfont = CreateFontIndirectA(&lf);
1051     hOldFont = SelectObject(hdc, hfont);
1052     ok(GetTextMetrics(hdc, &textm), "GetTextMetric failed\n");
1053     flags |= GGI_MARK_NONEXISTING_GLYPHS;
1054     charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1055     ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1056     ok(glyphs[4] == 0xffff, "GetGlyphIndicesW should have returned 0xffff char not %04x\n", glyphs[4]);
1057     flags = 0;
1058     testtext[0] = textm.tmDefaultChar;
1059     charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1060     ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1061     ok(glyphs[0] == 0, "GetGlyphIndicesW for tmDefaultChar should be 0 not %04x\n", glyphs[0]);
1062     ok(glyphs[4] == 0, "GetGlyphIndicesW should have returned 0 not %04x\n", glyphs[4]);
1063     DeleteObject(SelectObject(hdc, hOldFont));
1064 }
1065
1066 static void test_GetKerningPairs(void)
1067 {
1068     static const struct kerning_data
1069     {
1070         const char face_name[LF_FACESIZE];
1071         LONG height;
1072         /* some interesting fields from OUTLINETEXTMETRIC */
1073         LONG tmHeight, tmAscent, tmDescent;
1074         UINT otmEMSquare;
1075         INT  otmAscent;
1076         INT  otmDescent;
1077         UINT otmLineGap;
1078         UINT otmsCapEmHeight;
1079         UINT otmsXHeight;
1080         INT  otmMacAscent;
1081         INT  otmMacDescent;
1082         UINT otmMacLineGap;
1083         UINT otmusMinimumPPEM;
1084         /* small subset of kerning pairs to test */
1085         DWORD total_kern_pairs;
1086         const KERNINGPAIR kern_pair[26];
1087     } kd[] =
1088     {
1089         {"Arial", 12, 12, 9, 3,
1090                   2048, 7, -2, 1, 5, 2, 8, -2, 0, 9,
1091                   26,
1092             {
1093                 {' ','A',-1},{' ','T',0},{' ','Y',0},{'1','1',-1},
1094                 {'A',' ',-1},{'A','T',-1},{'A','V',-1},{'A','W',0},
1095                 {'A','Y',-1},{'A','v',0},{'A','w',0},{'A','y',0},
1096                 {'F',',',-1},{'F','.',-1},{'F','A',-1},{'L',' ',0},
1097                 {'L','T',-1},{'L','V',-1},{'L','W',-1},{'L','Y',-1},
1098                 {915,912,+1},{915,913,-1},{910,912,+1},{910,913,-1},
1099                 {933,970,+1},{933,972,-1}
1100                 }
1101         },
1102         {"Arial", -34, 39, 32, 7,
1103                   2048, 25, -7, 5, 17, 9, 31, -7, 1, 9,
1104                   26,
1105             {
1106                 {' ','A',-2},{' ','T',-1},{' ','Y',-1},{'1','1',-3},
1107                 {'A',' ',-2},{'A','T',-3},{'A','V',-3},{'A','W',-1},
1108                 {'A','Y',-3},{'A','v',-1},{'A','w',-1},{'A','y',-1},
1109                 {'F',',',-4},{'F','.',-4},{'F','A',-2},{'L',' ',-1},
1110                 {'L','T',-3},{'L','V',-3},{'L','W',-3},{'L','Y',-3},
1111                 {915,912,+3},{915,913,-3},{910,912,+3},{910,913,-3},
1112                 {933,970,+2},{933,972,-3}
1113             }
1114         },
1115         { "Arial", 120, 120, 97, 23,
1116                    2048, 79, -23, 16, 54, 27, 98, -23, 4, 9,
1117                    26,
1118             {
1119                 {' ','A',-6},{' ','T',-2},{' ','Y',-2},{'1','1',-8},
1120                 {'A',' ',-6},{'A','T',-8},{'A','V',-8},{'A','W',-4},
1121                 {'A','Y',-8},{'A','v',-2},{'A','w',-2},{'A','y',-2},
1122                 {'F',',',-12},{'F','.',-12},{'F','A',-6},{'L',' ',-4},
1123                 {'L','T',-8},{'L','V',-8},{'L','W',-8},{'L','Y',-8},
1124                 {915,912,+9},{915,913,-10},{910,912,+9},{910,913,-8},
1125                 {933,970,+6},{933,972,-10}
1126             }
1127         },
1128 #if 0 /* this set fails due to +1/-1 errors (rounding bug?), needs investigation. */
1129         { "Arial", 1024 /* usually 1/2 of EM Square */, 1024, 830, 194,
1130                    2048, 668, -193, 137, 459, 229, 830, -194, 30, 9,
1131                    26,
1132             {
1133                 {' ','A',-51},{' ','T',-17},{' ','Y',-17},{'1','1',-68},
1134                 {'A',' ',-51},{'A','T',-68},{'A','V',-68},{'A','W',-34},
1135                 {'A','Y',-68},{'A','v',-17},{'A','w',-17},{'A','y',-17},
1136                 {'F',',',-102},{'F','.',-102},{'F','A',-51},{'L',' ',-34},
1137                 {'L','T',-68},{'L','V',-68},{'L','W',-68},{'L','Y',-68},
1138                 {915,912,+73},{915,913,-84},{910,912,+76},{910,913,-68},
1139                 {933,970,+54},{933,972,-83}
1140             }
1141         }
1142 #endif
1143     };
1144     LOGFONT lf;
1145     HFONT hfont, hfont_old;
1146     KERNINGPAIR *kern_pair;
1147     HDC hdc;
1148     DWORD total_kern_pairs, ret, i, n, matches;
1149
1150     hdc = GetDC(0);
1151
1152     /* GetKerningPairsA maps unicode set of kerning pairs to current code page
1153      * which may render this test unusable, so we're trying to avoid that.
1154      */
1155     SetLastError(0xdeadbeef);
1156     GetKerningPairsW(hdc, 0, NULL);
1157     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1158     {
1159         win_skip("Skipping the GetKerningPairs test on a Win9x platform\n");
1160         ReleaseDC(0, hdc);
1161         return;
1162     }
1163
1164     for (i = 0; i < sizeof(kd)/sizeof(kd[0]); i++)
1165     {
1166         OUTLINETEXTMETRICW otm;
1167         UINT uiRet;
1168
1169         if (!is_font_installed(kd[i].face_name))
1170         {
1171             trace("%s is not installed so skipping this test\n", kd[i].face_name);
1172             continue;
1173         }
1174
1175         trace("testing font %s, height %d\n", kd[i].face_name, kd[i].height);
1176
1177         memset(&lf, 0, sizeof(lf));
1178         strcpy(lf.lfFaceName, kd[i].face_name);
1179         lf.lfHeight = kd[i].height;
1180         hfont = CreateFontIndirect(&lf);
1181         assert(hfont != 0);
1182
1183         hfont_old = SelectObject(hdc, hfont);
1184
1185         SetLastError(0xdeadbeef);
1186         otm.otmSize = sizeof(otm); /* just in case for Win9x compatibility */
1187         uiRet = GetOutlineTextMetricsW(hdc, sizeof(otm), &otm);
1188         ok(uiRet == sizeof(otm), "GetOutlineTextMetricsW error %d\n", GetLastError());
1189
1190         ok(match_off_by_1(kd[i].tmHeight, otm.otmTextMetrics.tmHeight), "expected %d, got %d\n",
1191            kd[i].tmHeight, otm.otmTextMetrics.tmHeight);
1192         ok(match_off_by_1(kd[i].tmAscent, otm.otmTextMetrics.tmAscent), "expected %d, got %d\n",
1193            kd[i].tmAscent, otm.otmTextMetrics.tmAscent);
1194         ok(kd[i].tmDescent == otm.otmTextMetrics.tmDescent, "expected %d, got %d\n",
1195            kd[i].tmDescent, otm.otmTextMetrics.tmDescent);
1196
1197         ok(kd[i].otmEMSquare == otm.otmEMSquare, "expected %u, got %u\n",
1198            kd[i].otmEMSquare, otm.otmEMSquare);
1199         ok(kd[i].otmAscent == otm.otmAscent, "expected %d, got %d\n",
1200            kd[i].otmAscent, otm.otmAscent);
1201         ok(kd[i].otmDescent == otm.otmDescent, "expected %d, got %d\n",
1202            kd[i].otmDescent, otm.otmDescent);
1203         ok(kd[i].otmLineGap == otm.otmLineGap, "expected %u, got %u\n",
1204            kd[i].otmLineGap, otm.otmLineGap);
1205         ok(near_match(kd[i].otmMacDescent, otm.otmMacDescent), "expected %d, got %d\n",
1206            kd[i].otmMacDescent, otm.otmMacDescent);
1207         ok(near_match(kd[i].otmMacAscent, otm.otmMacAscent), "expected %d, got %d\n",
1208            kd[i].otmMacAscent, otm.otmMacAscent);
1209 todo_wine {
1210         ok(kd[i].otmsCapEmHeight == otm.otmsCapEmHeight, "expected %u, got %u\n",
1211            kd[i].otmsCapEmHeight, otm.otmsCapEmHeight);
1212         ok(kd[i].otmsXHeight == otm.otmsXHeight, "expected %u, got %u\n",
1213            kd[i].otmsXHeight, otm.otmsXHeight);
1214         /* FIXME: this one sometimes succeeds due to expected 0, enable it when removing todo */
1215         if (0) ok(kd[i].otmMacLineGap == otm.otmMacLineGap, "expected %u, got %u\n",
1216            kd[i].otmMacLineGap, otm.otmMacLineGap);
1217         ok(kd[i].otmusMinimumPPEM == otm.otmusMinimumPPEM, "expected %u, got %u\n",
1218            kd[i].otmusMinimumPPEM, otm.otmusMinimumPPEM);
1219 }
1220
1221         total_kern_pairs = GetKerningPairsW(hdc, 0, NULL);
1222         trace("total_kern_pairs %u\n", total_kern_pairs);
1223         kern_pair = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pair));
1224
1225 #if 0 /* Win98 (GetKerningPairsA) and XP behave differently here, the test passes on XP */
1226         SetLastError(0xdeadbeef);
1227         ret = GetKerningPairsW(hdc, 0, kern_pair);
1228         ok(GetLastError() == ERROR_INVALID_PARAMETER,
1229            "got error %ld, expected ERROR_INVALID_PARAMETER\n", GetLastError());
1230         ok(ret == 0, "got %lu, expected 0\n", ret);
1231 #endif
1232
1233         ret = GetKerningPairsW(hdc, 100, NULL);
1234         ok(ret == total_kern_pairs, "got %u, expected %u\n", ret, total_kern_pairs);
1235
1236         ret = GetKerningPairsW(hdc, total_kern_pairs/2, kern_pair);
1237         ok(ret == total_kern_pairs/2, "got %u, expected %u\n", ret, total_kern_pairs/2);
1238
1239         ret = GetKerningPairsW(hdc, total_kern_pairs, kern_pair);
1240         ok(ret == total_kern_pairs, "got %u, expected %u\n", ret, total_kern_pairs);
1241
1242         matches = 0;
1243
1244         for (n = 0; n < ret; n++)
1245         {
1246             DWORD j;
1247 #if 0
1248             if (kern_pair[n].wFirst < 127 && kern_pair[n].wSecond < 127)
1249                 trace("{'%c','%c',%d},\n",
1250                       kern_pair[n].wFirst, kern_pair[n].wSecond, kern_pair[n].iKernAmount);
1251 #endif
1252             for (j = 0; j < kd[i].total_kern_pairs; j++)
1253             {
1254                 if (kern_pair[n].wFirst == kd[i].kern_pair[j].wFirst &&
1255                     kern_pair[n].wSecond == kd[i].kern_pair[j].wSecond)
1256                 {
1257                     ok(kern_pair[n].iKernAmount == kd[i].kern_pair[j].iKernAmount,
1258                        "pair %d:%d got %d, expected %d\n",
1259                        kern_pair[n].wFirst, kern_pair[n].wSecond,
1260                        kern_pair[n].iKernAmount, kd[i].kern_pair[j].iKernAmount);
1261                     matches++;
1262                 }
1263             }
1264         }
1265
1266         ok(matches == kd[i].total_kern_pairs, "got matches %u, expected %u\n",
1267            matches, kd[i].total_kern_pairs);
1268
1269         HeapFree(GetProcessHeap(), 0, kern_pair);
1270
1271         SelectObject(hdc, hfont_old);
1272         DeleteObject(hfont);
1273     }
1274
1275     ReleaseDC(0, hdc);
1276 }
1277
1278 static void test_height_selection(void)
1279 {
1280     static const struct font_data
1281     {
1282         const char face_name[LF_FACESIZE];
1283         int requested_height;
1284         int weight, height, ascent, descent, int_leading, ext_leading, dpi;
1285     } fd[] =
1286     {
1287         {"Tahoma", -12, FW_NORMAL, 14, 12, 2, 2, 0, 96 },
1288         {"Tahoma", -24, FW_NORMAL, 29, 24, 5, 5, 0, 96 },
1289         {"Tahoma", -48, FW_NORMAL, 58, 48, 10, 10, 0, 96 },
1290         {"Tahoma", -96, FW_NORMAL, 116, 96, 20, 20, 0, 96 },
1291         {"Tahoma", -192, FW_NORMAL, 232, 192, 40, 40, 0, 96 },
1292         {"Tahoma", 12, FW_NORMAL, 12, 10, 2, 2, 0, 96 },
1293         {"Tahoma", 24, FW_NORMAL, 24, 20, 4, 4, 0, 96 },
1294         {"Tahoma", 48, FW_NORMAL, 48, 40, 8, 8, 0, 96 },
1295         {"Tahoma", 96, FW_NORMAL, 96, 80, 16, 17, 0, 96 },
1296         {"Tahoma", 192, FW_NORMAL, 192, 159, 33, 33, 0, 96 }
1297     };
1298     HDC hdc;
1299     LOGFONT lf;
1300     HFONT hfont, old_hfont;
1301     TEXTMETRIC tm;
1302     INT ret, i;
1303
1304     hdc = CreateCompatibleDC(0);
1305     assert(hdc);
1306
1307     for (i = 0; i < sizeof(fd)/sizeof(fd[0]); i++)
1308     {
1309         if (!is_truetype_font_installed(fd[i].face_name))
1310         {
1311             skip("%s is not installed\n", fd[i].face_name);
1312             continue;
1313         }
1314
1315         memset(&lf, 0, sizeof(lf));
1316         lf.lfHeight = fd[i].requested_height;
1317         lf.lfWeight = fd[i].weight;
1318         strcpy(lf.lfFaceName, fd[i].face_name);
1319
1320         hfont = CreateFontIndirect(&lf);
1321         assert(hfont);
1322
1323         old_hfont = SelectObject(hdc, hfont);
1324         ret = GetTextMetrics(hdc, &tm);
1325         ok(ret, "GetTextMetrics error %d\n", GetLastError());
1326         if(fd[i].dpi == tm.tmDigitizedAspectX)
1327         {
1328             trace("found font %s, height %d charset %x dpi %d\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet, fd[i].dpi);
1329             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);
1330             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);
1331             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);
1332             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);
1333 #if 0 /* FIXME: calculation of tmInternalLeading in Wine doesn't match what Windows does */
1334             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);
1335 #endif
1336             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);
1337         }
1338
1339         SelectObject(hdc, old_hfont);
1340         DeleteObject(hfont);
1341     }
1342
1343     DeleteDC(hdc);
1344 }
1345
1346 static void test_GetOutlineTextMetrics(void)
1347 {
1348     OUTLINETEXTMETRIC *otm;
1349     LOGFONT lf;
1350     HFONT hfont, hfont_old;
1351     HDC hdc;
1352     DWORD ret, otm_size;
1353     LPSTR unset_ptr;
1354
1355     if (!is_font_installed("Arial"))
1356     {
1357         skip("Arial is not installed\n");
1358         return;
1359     }
1360
1361     hdc = GetDC(0);
1362
1363     memset(&lf, 0, sizeof(lf));
1364     strcpy(lf.lfFaceName, "Arial");
1365     lf.lfHeight = -13;
1366     lf.lfWeight = FW_NORMAL;
1367     lf.lfPitchAndFamily = DEFAULT_PITCH;
1368     lf.lfQuality = PROOF_QUALITY;
1369     hfont = CreateFontIndirect(&lf);
1370     assert(hfont != 0);
1371
1372     hfont_old = SelectObject(hdc, hfont);
1373     otm_size = GetOutlineTextMetrics(hdc, 0, NULL);
1374     trace("otm buffer size %u (0x%x)\n", otm_size, otm_size);
1375
1376     otm = HeapAlloc(GetProcessHeap(), 0, otm_size);
1377
1378     memset(otm, 0xAA, otm_size);
1379     SetLastError(0xdeadbeef);
1380     otm->otmSize = sizeof(*otm); /* just in case for Win9x compatibility */
1381     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1382     ok(ret == 1 /* Win9x */ ||
1383        ret == otm->otmSize /* XP*/,
1384        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1385     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1386     {
1387         ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
1388         ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
1389         ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
1390         ok(otm->otmpFullName == NULL, "expected NULL got %p\n", otm->otmpFullName);
1391     }
1392
1393     memset(otm, 0xAA, otm_size);
1394     SetLastError(0xdeadbeef);
1395     otm->otmSize = otm_size; /* just in case for Win9x compatibility */
1396     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1397     ok(ret == 1 /* Win9x */ ||
1398        ret == otm->otmSize /* XP*/,
1399        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1400     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1401     {
1402         ok(otm->otmpFamilyName != NULL, "expected not NULL got %p\n", otm->otmpFamilyName);
1403         ok(otm->otmpFaceName != NULL, "expected not NULL got %p\n", otm->otmpFaceName);
1404         ok(otm->otmpStyleName != NULL, "expected not NULL got %p\n", otm->otmpStyleName);
1405         ok(otm->otmpFullName != NULL, "expected not NULL got %p\n", otm->otmpFullName);
1406     }
1407
1408     /* ask about truncated data */
1409     memset(otm, 0xAA, otm_size);
1410     memset(&unset_ptr, 0xAA, sizeof(unset_ptr));
1411     SetLastError(0xdeadbeef);
1412     otm->otmSize = sizeof(*otm) - sizeof(LPSTR); /* just in case for Win9x compatibility */
1413     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1414     ok(ret == 1 /* Win9x */ ||
1415        ret == otm->otmSize /* XP*/,
1416        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1417     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1418     {
1419         ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
1420         ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
1421         ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
1422     }
1423     ok(otm->otmpFullName == unset_ptr, "expected %p got %p\n", unset_ptr, otm->otmpFullName);
1424
1425     HeapFree(GetProcessHeap(), 0, otm);
1426
1427     SelectObject(hdc, hfont_old);
1428     DeleteObject(hfont);
1429
1430     ReleaseDC(0, hdc);
1431 }
1432
1433 static void testJustification(HDC hdc, PSTR str, RECT *clientArea)
1434 {
1435     INT         y,
1436                 breakCount,
1437                 justifiedWidth = 0, /* to test GetTextExtentExPointW() */
1438                 areaWidth = clientArea->right - clientArea->left,
1439                 nErrors = 0, e;
1440     BOOL        lastExtent = FALSE;
1441     PSTR        pFirstChar, pLastChar;
1442     SIZE        size;
1443     TEXTMETRICA tm;
1444     struct err
1445     {
1446         char extent[100];
1447         int  GetTextExtentExPointWWidth;
1448     } error[10];
1449
1450     GetTextMetricsA(hdc, &tm);
1451     y = clientArea->top;
1452     do {
1453         breakCount = 0;
1454         while (*str == tm.tmBreakChar) str++; /* skip leading break chars */
1455         pFirstChar = str;
1456
1457         do {
1458             pLastChar = str;
1459
1460             /* if not at the end of the string, ... */
1461             if (*str == '\0') break;
1462             /* ... add the next word to the current extent */
1463             while (*str != '\0' && *str++ != tm.tmBreakChar);
1464             breakCount++;
1465             SetTextJustification(hdc, 0, 0);
1466             GetTextExtentPoint32(hdc, pFirstChar, str - pFirstChar - 1, &size);
1467         } while ((int) size.cx < areaWidth);
1468
1469         /* ignore trailing break chars */
1470         breakCount--;
1471         while (*(pLastChar - 1) == tm.tmBreakChar)
1472         {
1473             pLastChar--;
1474             breakCount--;
1475         }
1476
1477         if (*str == '\0' || breakCount <= 0) pLastChar = str;
1478
1479         SetTextJustification(hdc, 0, 0);
1480         GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
1481
1482         /* do not justify the last extent */
1483         if (*str != '\0' && breakCount > 0)
1484         {
1485             SetTextJustification(hdc, areaWidth - size.cx, breakCount);
1486             GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
1487             justifiedWidth = size.cx;
1488         }
1489         else lastExtent = TRUE;
1490
1491         /* catch errors and report them */
1492         if (!lastExtent && (justifiedWidth != areaWidth))
1493         {
1494             memset(error[nErrors].extent, 0, 100);
1495             memcpy(error[nErrors].extent, pFirstChar, pLastChar - pFirstChar);
1496             error[nErrors].GetTextExtentExPointWWidth = justifiedWidth;
1497             nErrors++;
1498         }
1499
1500         y += size.cy;
1501         str = pLastChar;
1502     } while (*str && y < clientArea->bottom);
1503
1504     for (e = 0; e < nErrors; e++)
1505     {
1506         /* The width returned by GetTextExtentPoint32() is exactly the same
1507            returned by GetTextExtentExPointW() - see dlls/gdi32/font.c */
1508         ok(error[e].GetTextExtentExPointWWidth == areaWidth,
1509             "GetTextExtentPointW() for \"%s\" should have returned a width of %d, not %d.\n",
1510             error[e].extent, areaWidth, error[e].GetTextExtentExPointWWidth);
1511     }
1512 }
1513
1514 static void test_SetTextJustification(void)
1515 {
1516     HDC hdc;
1517     RECT clientArea;
1518     LOGFONTA lf;
1519     HFONT hfont;
1520     HWND hwnd;
1521     static char testText[] =
1522             "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
1523             "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
1524             "enim ad minim veniam, quis nostrud exercitation ullamco laboris "
1525             "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in "
1526             "reprehenderit in voluptate velit esse cillum dolore eu fugiat "
1527             "nulla pariatur. Excepteur sint occaecat cupidatat non proident, "
1528             "sunt in culpa qui officia deserunt mollit anim id est laborum.";
1529
1530     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0, 400,400, 0, 0, 0, NULL);
1531     GetClientRect( hwnd, &clientArea );
1532     hdc = GetDC( hwnd );
1533
1534     memset(&lf, 0, sizeof lf);
1535     lf.lfCharSet = ANSI_CHARSET;
1536     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1537     lf.lfWeight = FW_DONTCARE;
1538     lf.lfHeight = 20;
1539     lf.lfQuality = DEFAULT_QUALITY;
1540     lstrcpyA(lf.lfFaceName, "Times New Roman");
1541     hfont = create_font("Times New Roman", &lf);
1542     SelectObject(hdc, hfont);
1543
1544     testJustification(hdc, testText, &clientArea);
1545
1546     DeleteObject(hfont);
1547     ReleaseDC(hwnd, hdc);
1548     DestroyWindow(hwnd);
1549 }
1550
1551 static BOOL get_glyph_indices(INT charset, UINT code_page, WORD *idx, UINT count, BOOL unicode)
1552 {
1553     HDC hdc;
1554     LOGFONTA lf;
1555     HFONT hfont, hfont_old;
1556     CHARSETINFO csi;
1557     FONTSIGNATURE fs;
1558     INT cs;
1559     DWORD i, ret;
1560     char name[64];
1561
1562     assert(count <= 128);
1563
1564     memset(&lf, 0, sizeof(lf));
1565
1566     lf.lfCharSet = charset;
1567     lf.lfHeight = 10;
1568     lstrcpyA(lf.lfFaceName, "Arial");
1569     SetLastError(0xdeadbeef);
1570     hfont = CreateFontIndirectA(&lf);
1571     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
1572
1573     hdc = GetDC(0);
1574     hfont_old = SelectObject(hdc, hfont);
1575
1576     cs = GetTextCharsetInfo(hdc, &fs, 0);
1577     ok(cs == charset, "expected %d, got %d\n", charset, cs);
1578
1579     SetLastError(0xdeadbeef);
1580     ret = GetTextFaceA(hdc, sizeof(name), name);
1581     ok(ret, "GetTextFaceA error %u\n", GetLastError());
1582
1583     if (charset == SYMBOL_CHARSET)
1584     {
1585         ok(strcmp("Arial", name), "face name should NOT be Arial\n");
1586         ok(fs.fsCsb[0] & (1 << 31), "symbol encoding should be available\n");
1587     }
1588     else
1589     {
1590         ok(!strcmp("Arial", name), "face name should be Arial, not %s\n", name);
1591         ok(!(fs.fsCsb[0] & (1 << 31)), "symbol encoding should NOT be available\n");
1592     }
1593
1594     if (!TranslateCharsetInfo((DWORD *)(INT_PTR)cs, &csi, TCI_SRCCHARSET))
1595     {
1596         trace("Can't find codepage for charset %d\n", cs);
1597         ReleaseDC(0, hdc);
1598         return FALSE;
1599     }
1600     ok(csi.ciACP == code_page, "expected %d, got %d\n", code_page, csi.ciACP);
1601
1602     if (unicode)
1603     {
1604         char ansi_buf[128];
1605         WCHAR unicode_buf[128];
1606
1607         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
1608
1609         MultiByteToWideChar(code_page, 0, ansi_buf, count, unicode_buf, count);
1610
1611         SetLastError(0xdeadbeef);
1612         ret = pGetGlyphIndicesW(hdc, unicode_buf, count, idx, 0);
1613         ok(ret == count, "GetGlyphIndicesW error %u\n", GetLastError());
1614     }
1615     else
1616     {
1617         char ansi_buf[128];
1618
1619         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
1620
1621         SetLastError(0xdeadbeef);
1622         ret = pGetGlyphIndicesA(hdc, ansi_buf, count, idx, 0);
1623         ok(ret == count, "GetGlyphIndicesA error %u\n", GetLastError());
1624     }
1625
1626     SelectObject(hdc, hfont_old);
1627     DeleteObject(hfont);
1628
1629     ReleaseDC(0, hdc);
1630
1631     return TRUE;
1632 }
1633
1634 static void test_font_charset(void)
1635 {
1636     static struct charset_data
1637     {
1638         INT charset;
1639         UINT code_page;
1640         WORD font_idxA[128], font_idxW[128];
1641     } cd[] =
1642     {
1643         { ANSI_CHARSET, 1252 },
1644         { RUSSIAN_CHARSET, 1251 },
1645         { SYMBOL_CHARSET, CP_SYMBOL } /* keep it as the last one */
1646     };
1647     int i;
1648
1649     if (!pGetGlyphIndicesA || !pGetGlyphIndicesW)
1650     {
1651         win_skip("Skipping the font charset test on a Win9x platform\n");
1652         return;
1653     }
1654
1655     if (!is_font_installed("Arial"))
1656     {
1657         skip("Arial is not installed\n");
1658         return;
1659     }
1660
1661     for (i = 0; i < sizeof(cd)/sizeof(cd[0]); i++)
1662     {
1663         if (cd[i].charset == SYMBOL_CHARSET)
1664         {
1665             if (!is_font_installed("Symbol") && !is_font_installed("Wingdings"))
1666             {
1667                 skip("Symbol or Wingdings is not installed\n");
1668                 break;
1669             }
1670         }
1671         get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxA, 128, FALSE);
1672         get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxW, 128, TRUE);
1673         ok(!memcmp(cd[i].font_idxA, cd[i].font_idxW, 128*sizeof(WORD)), "%d: indices don't match\n", i);
1674     }
1675
1676     ok(memcmp(cd[0].font_idxW, cd[1].font_idxW, 128*sizeof(WORD)), "0 vs 1: indices shouldn't match\n");
1677     if (i > 2)
1678     {
1679         ok(memcmp(cd[0].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "0 vs 2: indices shouldn't match\n");
1680         ok(memcmp(cd[1].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "1 vs 2: indices shouldn't match\n");
1681     }
1682     else
1683         skip("Symbol or Wingdings is not installed\n");
1684 }
1685
1686 static void test_GetFontUnicodeRanges(void)
1687 {
1688     LOGFONTA lf;
1689     HDC hdc;
1690     HFONT hfont, hfont_old;
1691     DWORD size;
1692     GLYPHSET *gs;
1693
1694     if (!pGetFontUnicodeRanges)
1695     {
1696         win_skip("GetFontUnicodeRanges not available before W2K\n");
1697         return;
1698     }
1699
1700     memset(&lf, 0, sizeof(lf));
1701     lstrcpyA(lf.lfFaceName, "Arial");
1702     hfont = create_font("Arial", &lf);
1703
1704     hdc = GetDC(0);
1705     hfont_old = SelectObject(hdc, hfont);
1706
1707     size = pGetFontUnicodeRanges(NULL, NULL);
1708     ok(!size, "GetFontUnicodeRanges succeeded unexpectedly\n");
1709
1710     size = pGetFontUnicodeRanges(hdc, NULL);
1711     ok(size, "GetFontUnicodeRanges failed unexpectedly\n");
1712
1713     gs = HeapAlloc(GetProcessHeap(), 0, size);
1714
1715     size = pGetFontUnicodeRanges(hdc, gs);
1716     ok(size, "GetFontUnicodeRanges failed\n");
1717 #if 0
1718     for (i = 0; i < gs->cRanges; i++)
1719         trace("%03d wcLow %04x cGlyphs %u\n", i, gs->ranges[i].wcLow, gs->ranges[i].cGlyphs);
1720 #endif
1721     trace("found %u ranges\n", gs->cRanges);
1722
1723     HeapFree(GetProcessHeap(), 0, gs);
1724
1725     SelectObject(hdc, hfont_old);
1726     DeleteObject(hfont);
1727     ReleaseDC(NULL, hdc);
1728 }
1729
1730 #define MAX_ENUM_FONTS 4096
1731
1732 struct enum_font_data
1733 {
1734     int total;
1735     LOGFONT lf[MAX_ENUM_FONTS];
1736 };
1737
1738 struct enum_font_dataW
1739 {
1740     int total;
1741     LOGFONTW lf[MAX_ENUM_FONTS];
1742 };
1743
1744 static INT CALLBACK arial_enum_proc(const LOGFONT *lf, const TEXTMETRIC *tm, DWORD type, LPARAM lParam)
1745 {
1746     struct enum_font_data *efd = (struct enum_font_data *)lParam;
1747
1748     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
1749
1750     if (type != TRUETYPE_FONTTYPE) return 1;
1751 #if 0
1752     trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
1753           lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
1754 #endif
1755     if (efd->total < MAX_ENUM_FONTS)
1756         efd->lf[efd->total++] = *lf;
1757     else
1758         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
1759
1760     return 1;
1761 }
1762
1763 static INT CALLBACK arial_enum_procw(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
1764 {
1765     struct enum_font_dataW *efd = (struct enum_font_dataW *)lParam;
1766
1767     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
1768
1769     if (type != TRUETYPE_FONTTYPE) return 1;
1770 #if 0
1771     trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
1772           lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
1773 #endif
1774     if (efd->total < MAX_ENUM_FONTS)
1775         efd->lf[efd->total++] = *lf;
1776     else
1777         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
1778
1779     return 1;
1780 }
1781
1782 static void get_charset_stats(struct enum_font_data *efd,
1783                               int *ansi_charset, int *symbol_charset,
1784                               int *russian_charset)
1785 {
1786     int i;
1787
1788     *ansi_charset = 0;
1789     *symbol_charset = 0;
1790     *russian_charset = 0;
1791
1792     for (i = 0; i < efd->total; i++)
1793     {
1794         switch (efd->lf[i].lfCharSet)
1795         {
1796         case ANSI_CHARSET:
1797             (*ansi_charset)++;
1798             break;
1799         case SYMBOL_CHARSET:
1800             (*symbol_charset)++;
1801             break;
1802         case RUSSIAN_CHARSET:
1803             (*russian_charset)++;
1804             break;
1805         }
1806     }
1807 }
1808
1809 static void get_charset_statsW(struct enum_font_dataW *efd,
1810                               int *ansi_charset, int *symbol_charset,
1811                               int *russian_charset)
1812 {
1813     int i;
1814
1815     *ansi_charset = 0;
1816     *symbol_charset = 0;
1817     *russian_charset = 0;
1818
1819     for (i = 0; i < efd->total; i++)
1820     {
1821         switch (efd->lf[i].lfCharSet)
1822         {
1823         case ANSI_CHARSET:
1824             (*ansi_charset)++;
1825             break;
1826         case SYMBOL_CHARSET:
1827             (*symbol_charset)++;
1828             break;
1829         case RUSSIAN_CHARSET:
1830             (*russian_charset)++;
1831             break;
1832         }
1833     }
1834 }
1835
1836 static void test_EnumFontFamilies(const char *font_name, INT font_charset)
1837 {
1838     struct enum_font_data efd;
1839     struct enum_font_dataW efdw;
1840     LOGFONT lf;
1841     HDC hdc;
1842     int i, ret, ansi_charset, symbol_charset, russian_charset;
1843
1844     trace("Testing font %s, charset %d\n", *font_name ? font_name : "<empty>", font_charset);
1845
1846     if (*font_name && !is_truetype_font_installed(font_name))
1847     {
1848         skip("%s is not installed\n", font_name);
1849         return;
1850     }
1851
1852     hdc = GetDC(0);
1853
1854     /* Observed behaviour: EnumFontFamilies enumerates aliases like "Arial Cyr"
1855      * while EnumFontFamiliesEx doesn't.
1856      */
1857     if (!*font_name && font_charset == DEFAULT_CHARSET) /* do it only once */
1858     {
1859         /*
1860          * Use EnumFontFamiliesW since win98 crashes when the
1861          *    second parameter is NULL using EnumFontFamilies
1862          */
1863         efdw.total = 0;
1864         SetLastError(0xdeadbeef);
1865         ret = EnumFontFamiliesW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw);
1866         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesW error %u\n", GetLastError());
1867         if(ret)
1868         {
1869             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
1870             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
1871                   ansi_charset, symbol_charset, russian_charset);
1872             ok(efdw.total > 0, "fonts enumerated: NULL\n");
1873             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
1874             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
1875             ok(russian_charset > 0 ||
1876                broken(russian_charset == 0), /* NT4 */
1877                "NULL family should enumerate RUSSIAN_CHARSET\n");
1878         }
1879
1880         efdw.total = 0;
1881         SetLastError(0xdeadbeef);
1882         ret = EnumFontFamiliesExW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw, 0);
1883         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesExW error %u\n", GetLastError());
1884         if(ret)
1885         {
1886             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
1887             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
1888                   ansi_charset, symbol_charset, russian_charset);
1889             ok(efdw.total > 0, "fonts enumerated: NULL\n");
1890             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
1891             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
1892             ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
1893         }
1894     }
1895
1896     efd.total = 0;
1897     SetLastError(0xdeadbeef);
1898     ret = EnumFontFamilies(hdc, font_name, arial_enum_proc, (LPARAM)&efd);
1899     ok(ret, "EnumFontFamilies error %u\n", GetLastError());
1900     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1901     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s\n",
1902           ansi_charset, symbol_charset, russian_charset,
1903           *font_name ? font_name : "<empty>");
1904     if (*font_name)
1905         ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
1906     else
1907         ok(!efd.total, "no fonts should be enumerated for empty font_name\n");
1908     for (i = 0; i < efd.total; i++)
1909     {
1910 /* FIXME: remove completely once Wine is fixed */
1911 if (efd.lf[i].lfCharSet != font_charset)
1912 {
1913 todo_wine
1914     ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1915 }
1916 else
1917         ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1918         ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1919            font_name, efd.lf[i].lfFaceName);
1920     }
1921
1922     memset(&lf, 0, sizeof(lf));
1923     lf.lfCharSet = ANSI_CHARSET;
1924     lstrcpy(lf.lfFaceName, font_name);
1925     efd.total = 0;
1926     SetLastError(0xdeadbeef);
1927     ret = EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
1928     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
1929     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1930     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s ANSI_CHARSET\n",
1931           ansi_charset, symbol_charset, russian_charset,
1932           *font_name ? font_name : "<empty>");
1933     if (font_charset == SYMBOL_CHARSET)
1934     {
1935         if (*font_name)
1936             ok(efd.total == 0, "no fonts should be enumerated: %s ANSI_CHARSET\n", font_name);
1937         else
1938             ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
1939     }
1940     else
1941     {
1942         ok(efd.total > 0, "no fonts enumerated: %s ANSI_CHARSET\n", font_name);
1943         for (i = 0; i < efd.total; i++)
1944         {
1945             ok(efd.lf[i].lfCharSet == ANSI_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1946             if (*font_name)
1947                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1948                    font_name, efd.lf[i].lfFaceName);
1949         }
1950     }
1951
1952     /* DEFAULT_CHARSET should enumerate all available charsets */
1953     memset(&lf, 0, sizeof(lf));
1954     lf.lfCharSet = DEFAULT_CHARSET;
1955     lstrcpy(lf.lfFaceName, font_name);
1956     efd.total = 0;
1957     SetLastError(0xdeadbeef);
1958     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
1959     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
1960     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1961     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s DEFAULT_CHARSET\n",
1962           ansi_charset, symbol_charset, russian_charset,
1963           *font_name ? font_name : "<empty>");
1964     ok(efd.total > 0, "no fonts enumerated: %s DEFAULT_CHARSET\n", font_name);
1965     for (i = 0; i < efd.total; i++)
1966     {
1967         if (*font_name)
1968             ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1969                font_name, efd.lf[i].lfFaceName);
1970     }
1971     if (*font_name)
1972     {
1973         switch (font_charset)
1974         {
1975         case ANSI_CHARSET:
1976             ok(ansi_charset > 0,
1977                "ANSI_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
1978             ok(!symbol_charset,
1979                "ANSI_CHARSET should NOT enumerate SYMBOL_CHARSET for %s\n", font_name);
1980             ok(russian_charset > 0,
1981                "ANSI_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
1982             break;
1983         case SYMBOL_CHARSET:
1984             ok(!ansi_charset,
1985                "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", font_name);
1986             ok(symbol_charset,
1987                "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
1988             ok(!russian_charset,
1989                "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", font_name);
1990             break;
1991         case DEFAULT_CHARSET:
1992             ok(ansi_charset > 0,
1993                "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
1994             ok(symbol_charset > 0,
1995                "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
1996             ok(russian_charset > 0,
1997                "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
1998             break;
1999         }
2000     }
2001     else
2002     {
2003         ok(ansi_charset > 0,
2004            "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2005         ok(symbol_charset > 0,
2006            "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2007         ok(russian_charset > 0,
2008            "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2009     }
2010
2011     memset(&lf, 0, sizeof(lf));
2012     lf.lfCharSet = SYMBOL_CHARSET;
2013     lstrcpy(lf.lfFaceName, font_name);
2014     efd.total = 0;
2015     SetLastError(0xdeadbeef);
2016     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2017     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2018     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2019     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s SYMBOL_CHARSET\n",
2020           ansi_charset, symbol_charset, russian_charset,
2021           *font_name ? font_name : "<empty>");
2022     if (*font_name && font_charset == ANSI_CHARSET)
2023         ok(efd.total == 0, "no fonts should be enumerated: %s SYMBOL_CHARSET\n", font_name);
2024     else
2025     {
2026         ok(efd.total > 0, "no fonts enumerated: %s SYMBOL_CHARSET\n", font_name);
2027         for (i = 0; i < efd.total; i++)
2028         {
2029             ok(efd.lf[i].lfCharSet == SYMBOL_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2030             if (*font_name)
2031                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2032                    font_name, efd.lf[i].lfFaceName);
2033         }
2034
2035         ok(!ansi_charset,
2036            "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2037         ok(symbol_charset > 0,
2038            "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2039         ok(!russian_charset,
2040            "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2041     }
2042
2043     ReleaseDC(0, hdc);
2044 }
2045
2046 static void test_negative_width(HDC hdc, const LOGFONTA *lf)
2047 {
2048     HFONT hfont, hfont_prev;
2049     DWORD ret;
2050     GLYPHMETRICS gm1, gm2;
2051     LOGFONTA lf2 = *lf;
2052     WORD idx;
2053     MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
2054
2055     if(!pGetGlyphIndicesA)
2056         return;
2057
2058     /* negative widths are handled just as positive ones */
2059     lf2.lfWidth = -lf->lfWidth;
2060
2061     SetLastError(0xdeadbeef);
2062     hfont = CreateFontIndirectA(lf);
2063     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2064     check_font("original", lf, hfont);
2065
2066     hfont_prev = SelectObject(hdc, hfont);
2067
2068     ret = pGetGlyphIndicesA(hdc, "x", 1, &idx, GGI_MARK_NONEXISTING_GLYPHS);
2069     if (ret == GDI_ERROR || idx == 0xffff)
2070     {
2071         SelectObject(hdc, hfont_prev);
2072         DeleteObject(hfont);
2073         skip("Font %s doesn't contain 'x', skipping the test\n", lf->lfFaceName);
2074         return;
2075     }
2076
2077     /* filling with 0xaa causes false pass under WINEDEBUG=warn+heap */
2078     memset(&gm1, 0xab, sizeof(gm1));
2079     SetLastError(0xdeadbeef);
2080     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm1, 0, NULL, &mat);
2081     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
2082
2083     SelectObject(hdc, hfont_prev);
2084     DeleteObject(hfont);
2085
2086     SetLastError(0xdeadbeef);
2087     hfont = CreateFontIndirectA(&lf2);
2088     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2089     check_font("negative width", &lf2, hfont);
2090
2091     hfont_prev = SelectObject(hdc, hfont);
2092
2093     memset(&gm2, 0xbb, sizeof(gm2));
2094     SetLastError(0xdeadbeef);
2095     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm2, 0, NULL, &mat);
2096     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
2097
2098     SelectObject(hdc, hfont_prev);
2099     DeleteObject(hfont);
2100
2101     ok(gm1.gmBlackBoxX == gm2.gmBlackBoxX &&
2102        gm1.gmBlackBoxY == gm2.gmBlackBoxY &&
2103        gm1.gmptGlyphOrigin.x == gm2.gmptGlyphOrigin.x &&
2104        gm1.gmptGlyphOrigin.y == gm2.gmptGlyphOrigin.y &&
2105        gm1.gmCellIncX == gm2.gmCellIncX &&
2106        gm1.gmCellIncY == gm2.gmCellIncY,
2107        "gm1=%d,%d,%d,%d,%d,%d gm2=%d,%d,%d,%d,%d,%d\n",
2108        gm1.gmBlackBoxX, gm1.gmBlackBoxY, gm1.gmptGlyphOrigin.x,
2109        gm1.gmptGlyphOrigin.y, gm1.gmCellIncX, gm1.gmCellIncY,
2110        gm2.gmBlackBoxX, gm2.gmBlackBoxY, gm2.gmptGlyphOrigin.x,
2111        gm2.gmptGlyphOrigin.y, gm2.gmCellIncX, gm2.gmCellIncY);
2112 }
2113
2114 /* PANOSE is 10 bytes in size, need to pack the structure properly */
2115 #include "pshpack2.h"
2116 typedef struct
2117 {
2118     USHORT version;
2119     SHORT xAvgCharWidth;
2120     USHORT usWeightClass;
2121     USHORT usWidthClass;
2122     SHORT fsType;
2123     SHORT ySubscriptXSize;
2124     SHORT ySubscriptYSize;
2125     SHORT ySubscriptXOffset;
2126     SHORT ySubscriptYOffset;
2127     SHORT ySuperscriptXSize;
2128     SHORT ySuperscriptYSize;
2129     SHORT ySuperscriptXOffset;
2130     SHORT ySuperscriptYOffset;
2131     SHORT yStrikeoutSize;
2132     SHORT yStrikeoutPosition;
2133     SHORT sFamilyClass;
2134     PANOSE panose;
2135     ULONG ulUnicodeRange1;
2136     ULONG ulUnicodeRange2;
2137     ULONG ulUnicodeRange3;
2138     ULONG ulUnicodeRange4;
2139     CHAR achVendID[4];
2140     USHORT fsSelection;
2141     USHORT usFirstCharIndex;
2142     USHORT usLastCharIndex;
2143     /* According to the Apple spec, original version didn't have the below fields,
2144      * version numbers were taked from the OpenType spec.
2145      */
2146     /* version 0 (TrueType 1.5) */
2147     USHORT sTypoAscender;
2148     USHORT sTypoDescender;
2149     USHORT sTypoLineGap;
2150     USHORT usWinAscent;
2151     USHORT usWinDescent;
2152     /* version 1 (TrueType 1.66) */
2153     ULONG ulCodePageRange1;
2154     ULONG ulCodePageRange2;
2155     /* version 2 (OpenType 1.2) */
2156     SHORT sxHeight;
2157     SHORT sCapHeight;
2158     USHORT usDefaultChar;
2159     USHORT usBreakChar;
2160     USHORT usMaxContext;
2161 } TT_OS2_V2;
2162 #include "poppack.h"
2163
2164 #ifdef WORDS_BIGENDIAN
2165 #define GET_BE_WORD(x) (x)
2166 #define GET_BE_DWORD(x) (x)
2167 #else
2168 #define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
2169 #define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
2170 #endif
2171
2172 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
2173                     ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
2174                     ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
2175 #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
2176 #define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
2177
2178 typedef struct
2179 {
2180     USHORT version;
2181     USHORT num_tables;
2182 } cmap_header;
2183
2184 typedef struct
2185 {
2186     USHORT plat_id;
2187     USHORT enc_id;
2188     ULONG offset;
2189 } cmap_encoding_record;
2190
2191 typedef struct
2192 {
2193     USHORT format;
2194     USHORT length;
2195     USHORT language;
2196
2197     BYTE glyph_ids[256];
2198 } cmap_format_0;
2199
2200 typedef struct
2201 {
2202     USHORT format;
2203     USHORT length;
2204     USHORT language;
2205
2206     USHORT seg_countx2;
2207     USHORT search_range;
2208     USHORT entry_selector;
2209     USHORT range_shift;
2210
2211     USHORT end_count[1]; /* this is a variable-sized array of length seg_countx2 / 2 */
2212 /* Then follows:
2213     USHORT pad;
2214     USHORT start_count[seg_countx2 / 2];
2215     USHORT id_delta[seg_countx2 / 2];
2216     USHORT id_range_offset[seg_countx2 / 2];
2217     USHORT glyph_ids[];
2218 */
2219 } cmap_format_4;
2220
2221 typedef struct
2222 {
2223     USHORT end_count;
2224     USHORT start_count;
2225     USHORT id_delta;
2226     USHORT id_range_offset;
2227 } cmap_format_4_seg;
2228
2229 static void expect_ff(const TEXTMETRICA *tmA, const TT_OS2_V2 *os2, WORD family, const char *name)
2230 {
2231     ok((tmA->tmPitchAndFamily & 0xf0) == family, "%s: expected family %02x got %02x. panose %d-%d-%d-%d-...\n",
2232        name, family, tmA->tmPitchAndFamily, os2->panose.bFamilyType, os2->panose.bSerifStyle,
2233        os2->panose.bWeight, os2->panose.bProportion);
2234 }
2235
2236 static BOOL get_first_last_from_cmap0(void *ptr, DWORD *first, DWORD *last)
2237 {
2238     int i;
2239     cmap_format_0 *cmap = (cmap_format_0*)ptr;
2240
2241     *first = 256;
2242
2243     for(i = 0; i < 256; i++)
2244     {
2245         if(cmap->glyph_ids[i] == 0) continue;
2246         *last = i;
2247         if(*first == 256) *first = i;
2248     }
2249     if(*first == 256) return FALSE;
2250     return TRUE;
2251 }
2252
2253 static void get_seg4(cmap_format_4 *cmap, USHORT seg_num, cmap_format_4_seg *seg)
2254 {
2255     USHORT segs = GET_BE_WORD(cmap->seg_countx2) / 2;
2256     seg->end_count = GET_BE_WORD(cmap->end_count[seg_num]);
2257     seg->start_count = GET_BE_WORD(cmap->end_count[segs + 1 + seg_num]);
2258     seg->id_delta = GET_BE_WORD(cmap->end_count[2 * segs + 1 + seg_num]);
2259     seg->id_range_offset = GET_BE_WORD(cmap->end_count[3 * segs + 1 + seg_num]);
2260 }
2261
2262 static BOOL get_first_last_from_cmap4(void *ptr, DWORD *first, DWORD *last, DWORD limit)
2263 {
2264     int i;
2265     cmap_format_4 *cmap = (cmap_format_4*)ptr;
2266     USHORT seg_count = GET_BE_WORD(cmap->seg_countx2) / 2;
2267     USHORT const *glyph_ids = cmap->end_count + 4 * seg_count + 1;
2268
2269     *first = 0x10000;
2270
2271     for(i = 0; i < seg_count; i++)
2272     {
2273         DWORD code, index;
2274         cmap_format_4_seg seg;
2275
2276         get_seg4(cmap, i, &seg);
2277         for(code = seg.start_count; code <= seg.end_count; code++)
2278         {
2279             if(seg.id_range_offset == 0)
2280                 index = (seg.id_delta + code) & 0xffff;
2281             else
2282             {
2283                 index = seg.id_range_offset / 2
2284                     + code - seg.start_count
2285                     + i - seg_count;
2286
2287                 /* some fonts have broken last segment */
2288                 if ((char *)(glyph_ids + index + sizeof(*glyph_ids)) < (char *)ptr + limit)
2289                     index = GET_BE_WORD(glyph_ids[index]);
2290                 else
2291                 {
2292                     trace("segment %04x/%04x index %04x points to nowhere\n",
2293                           seg.start_count, seg.end_count, index);
2294                     index = 0;
2295                 }
2296                 if(index) index += seg.id_delta;
2297             }
2298             if(*first == 0x10000)
2299                 *last = *first = code;
2300             else if(index)
2301                 *last = code;
2302         }
2303     }
2304
2305     if(*first == 0x10000) return FALSE;
2306     return TRUE;
2307 }
2308
2309 static void *get_cmap(cmap_header *header, USHORT plat_id, USHORT enc_id)
2310 {
2311     USHORT i;
2312     cmap_encoding_record *record = (cmap_encoding_record *)(header + 1);
2313
2314     for(i = 0; i < GET_BE_WORD(header->num_tables); i++)
2315     {
2316         if(GET_BE_WORD(record->plat_id) == plat_id && GET_BE_WORD(record->enc_id) == enc_id)
2317             return (BYTE *)header + GET_BE_DWORD(record->offset);
2318         record++;
2319     }
2320     return NULL;
2321 }
2322
2323 typedef enum
2324 {
2325     cmap_none,
2326     cmap_ms_unicode,
2327     cmap_ms_symbol
2328 } cmap_type;
2329
2330 static BOOL get_first_last_from_cmap(HDC hdc, DWORD *first, DWORD *last, cmap_type *cmap_type)
2331 {
2332     LONG size, ret;
2333     cmap_header *header;
2334     void *cmap;
2335     BOOL r = FALSE;
2336     WORD format;
2337
2338     size = GetFontData(hdc, MS_CMAP_TAG, 0, NULL, 0);
2339     ok(size != GDI_ERROR, "no cmap table found\n");
2340     if(size == GDI_ERROR) return FALSE;
2341
2342     header = HeapAlloc(GetProcessHeap(), 0, size);
2343     ret = GetFontData(hdc, MS_CMAP_TAG, 0, header, size);
2344     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2345     ok(GET_BE_WORD(header->version) == 0, "got cmap version %d\n", GET_BE_WORD(header->version));
2346
2347     cmap = get_cmap(header, 3, 1);
2348     if(cmap)
2349         *cmap_type = cmap_ms_unicode;
2350     else
2351     {
2352         cmap = get_cmap(header, 3, 0);
2353         if(cmap) *cmap_type = cmap_ms_symbol;
2354     }
2355     if(!cmap)
2356     {
2357         *cmap_type = cmap_none;
2358         goto end;
2359     }
2360
2361     format = GET_BE_WORD(*(WORD *)cmap);
2362     switch(format)
2363     {
2364     case 0:
2365         r = get_first_last_from_cmap0(cmap, first, last);
2366         break;
2367     case 4:
2368         r = get_first_last_from_cmap4(cmap, first, last, size);
2369         break;
2370     default:
2371         trace("unhandled cmap format %d\n", format);
2372         break;
2373     }
2374
2375 end:
2376     HeapFree(GetProcessHeap(), 0, header);
2377     return r;
2378 }
2379
2380 static void test_text_metrics(const LOGFONTA *lf)
2381 {
2382     HDC hdc;
2383     HFONT hfont, hfont_old;
2384     TEXTMETRICA tmA;
2385     TT_OS2_V2 tt_os2;
2386     LONG size, ret;
2387     const char *font_name = lf->lfFaceName;
2388     DWORD cmap_first = 0, cmap_last = 0;
2389     cmap_type cmap_type;
2390
2391     hdc = GetDC(0);
2392
2393     SetLastError(0xdeadbeef);
2394     hfont = CreateFontIndirectA(lf);
2395     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2396
2397     hfont_old = SelectObject(hdc, hfont);
2398
2399     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
2400     if (size == GDI_ERROR)
2401     {
2402         trace("OS/2 chunk was not found\n");
2403         goto end_of_test;
2404     }
2405     if (size > sizeof(tt_os2))
2406     {
2407         trace("got too large OS/2 chunk of size %u\n", size);
2408         size = sizeof(tt_os2);
2409     }
2410
2411     memset(&tt_os2, 0, sizeof(tt_os2));
2412     ret = GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size);
2413     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2414
2415     SetLastError(0xdeadbeef);
2416     ret = GetTextMetricsA(hdc, &tmA);
2417     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
2418
2419     if(!get_first_last_from_cmap(hdc, &cmap_first, &cmap_last, &cmap_type))
2420     {
2421         skip("Unable to retrieve first and last glyphs from cmap\n");
2422     }
2423     else
2424     {
2425         USHORT expect_first_A, expect_last_A, expect_break_A, expect_default_A;
2426         USHORT expect_first_W, expect_last_W, expect_break_W, expect_default_W;
2427         UINT os2_first_char, os2_last_char, default_char, break_char;
2428         USHORT version;
2429         TEXTMETRICW tmW;
2430
2431         version = GET_BE_WORD(tt_os2.version);
2432
2433         os2_first_char = GET_BE_WORD(tt_os2.usFirstCharIndex);
2434         os2_last_char = GET_BE_WORD(tt_os2.usLastCharIndex);
2435         default_char = GET_BE_WORD(tt_os2.usDefaultChar);
2436         break_char = GET_BE_WORD(tt_os2.usBreakChar);
2437
2438         trace("font %s charset %u: %x-%x (%x-%x) default %x break %x OS/2 version %u vendor %4.4s\n",
2439               font_name, lf->lfCharSet, os2_first_char, os2_last_char, cmap_first, cmap_last,
2440               default_char, break_char, version, (LPCSTR)&tt_os2.achVendID);
2441
2442         if (cmap_type == cmap_ms_symbol || (cmap_first >= 0xf000 && cmap_first < 0xf100))
2443         {
2444             expect_first_W    = 0;
2445             switch(GetACP())
2446             {
2447             case 1257:  /* Baltic */
2448                 expect_last_W = 0xf8fd;
2449                 break;
2450             default:
2451                 expect_last_W = 0xf0ff;
2452             }
2453             expect_break_W    = 0x20;
2454             expect_default_W  = expect_break_W - 1;
2455             expect_first_A    = 0x1e;
2456             expect_last_A     = min(os2_last_char - os2_first_char + 0x20, 0xff);
2457         }
2458         else
2459         {
2460             expect_first_W    = cmap_first;
2461             expect_last_W     = min(cmap_last, os2_last_char);
2462             if(os2_first_char <= 1)
2463                 expect_break_W = os2_first_char + 2;
2464             else if(os2_first_char > 0xff)
2465                 expect_break_W = 0x20;
2466             else
2467                 expect_break_W = os2_first_char;
2468             expect_default_W  = expect_break_W - 1;
2469             expect_first_A    = expect_default_W - 1;
2470             expect_last_A     = min(expect_last_W, 0xff);
2471         }
2472         expect_break_A    = expect_break_W;
2473         expect_default_A  = expect_default_W;
2474
2475         /* Wine currently uses SYMBOL_CHARSET to identify whether the ANSI metrics need special handling */
2476         if(cmap_type != cmap_ms_symbol && tmA.tmCharSet == SYMBOL_CHARSET && expect_first_A != 0x1e)
2477             todo_wine ok(tmA.tmFirstChar == expect_first_A ||
2478                          tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2479                          "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2480         else
2481             ok(tmA.tmFirstChar == expect_first_A ||
2482                tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2483                "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2484         ok(tmA.tmLastChar == expect_last_A ||
2485            tmA.tmLastChar == 0xff /* win9x */,
2486            "A: tmLastChar for %s got %02x expected %02x\n", font_name, tmA.tmLastChar, expect_last_A);
2487         ok(tmA.tmBreakChar == expect_break_A, "A: tmBreakChar for %s got %02x expected %02x\n",
2488            font_name, tmA.tmBreakChar, expect_break_A);
2489         ok(tmA.tmDefaultChar == expect_default_A, "A: tmDefaultChar for %s got %02x expected %02x\n",
2490            font_name, tmA.tmDefaultChar, expect_default_A);
2491
2492
2493         SetLastError(0xdeadbeef);
2494         ret = GetTextMetricsW(hdc, &tmW);
2495         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
2496            "GetTextMetricsW error %u\n", GetLastError());
2497         if (ret)
2498         {
2499             /* Wine uses the os2 first char */
2500             if(cmap_first != os2_first_char && cmap_type != cmap_ms_symbol)
2501                 todo_wine ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2502                              font_name, tmW.tmFirstChar, expect_first_W);
2503             else
2504                 ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2505                    font_name, tmW.tmFirstChar, expect_first_W);
2506
2507             /* Wine uses the os2 last char */
2508             if(expect_last_W != os2_last_char && cmap_type != cmap_ms_symbol)
2509                 todo_wine ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2510                              font_name, tmW.tmLastChar, expect_last_W);
2511             else
2512                 ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2513                    font_name, tmW.tmLastChar, expect_last_W);
2514             ok(tmW.tmBreakChar == expect_break_W, "W: tmBreakChar for %s got %02x expected %02x\n",
2515                font_name, tmW.tmBreakChar, expect_break_W);
2516             ok(tmW.tmDefaultChar == expect_default_W, "W: tmDefaultChar for %s got %02x expected %02x\n",
2517                font_name, tmW.tmDefaultChar, expect_default_W);
2518
2519             /* Test the aspect ratio while we have tmW */
2520             ret = GetDeviceCaps(hdc, LOGPIXELSX);
2521             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectX %u != %u\n",
2522                tmW.tmDigitizedAspectX, ret);
2523             ret = GetDeviceCaps(hdc, LOGPIXELSY);
2524             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectY %u != %u\n",
2525                tmW.tmDigitizedAspectX, ret);
2526         }
2527     }
2528
2529     /* test FF_ values */
2530     switch(tt_os2.panose.bFamilyType)
2531     {
2532     case PAN_ANY:
2533     case PAN_NO_FIT:
2534     case PAN_FAMILY_TEXT_DISPLAY:
2535     case PAN_FAMILY_PICTORIAL:
2536     default:
2537         if((tmA.tmPitchAndFamily & 1) == 0 || /* fixed */
2538            tt_os2.panose.bProportion == PAN_PROP_MONOSPACED)
2539         {
2540             expect_ff(&tmA, &tt_os2, FF_MODERN, font_name);
2541             break;
2542         }
2543         switch(tt_os2.panose.bSerifStyle)
2544         {
2545         case PAN_ANY:
2546         case PAN_NO_FIT:
2547         default:
2548             expect_ff(&tmA, &tt_os2, FF_DONTCARE, font_name);
2549             break;
2550
2551         case PAN_SERIF_COVE:
2552         case PAN_SERIF_OBTUSE_COVE:
2553         case PAN_SERIF_SQUARE_COVE:
2554         case PAN_SERIF_OBTUSE_SQUARE_COVE:
2555         case PAN_SERIF_SQUARE:
2556         case PAN_SERIF_THIN:
2557         case PAN_SERIF_BONE:
2558         case PAN_SERIF_EXAGGERATED:
2559         case PAN_SERIF_TRIANGLE:
2560             expect_ff(&tmA, &tt_os2, FF_ROMAN, font_name);
2561             break;
2562
2563         case PAN_SERIF_NORMAL_SANS:
2564         case PAN_SERIF_OBTUSE_SANS:
2565         case PAN_SERIF_PERP_SANS:
2566         case PAN_SERIF_FLARED:
2567         case PAN_SERIF_ROUNDED:
2568             expect_ff(&tmA, &tt_os2, FF_SWISS, font_name);
2569             break;
2570         }
2571         break;
2572
2573     case PAN_FAMILY_SCRIPT:
2574         expect_ff(&tmA, &tt_os2, FF_SCRIPT, font_name);
2575         break;
2576
2577     case PAN_FAMILY_DECORATIVE:
2578         expect_ff(&tmA, &tt_os2, FF_DECORATIVE, font_name);
2579         break;
2580     }
2581
2582     test_negative_width(hdc, lf);
2583
2584 end_of_test:
2585     SelectObject(hdc, hfont_old);
2586     DeleteObject(hfont);
2587
2588     ReleaseDC(0, hdc);
2589 }
2590
2591 static INT CALLBACK enum_truetype_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
2592 {
2593     INT *enumed = (INT *)lParam;
2594
2595     if (type == TRUETYPE_FONTTYPE)
2596     {
2597         (*enumed)++;
2598         test_text_metrics(lf);
2599     }
2600     return 1;
2601 }
2602
2603 static void test_GetTextMetrics(void)
2604 {
2605     LOGFONTA lf;
2606     HDC hdc;
2607     INT enumed;
2608
2609     /* Report only once */
2610     if(!pGetGlyphIndicesA)
2611         win_skip("GetGlyphIndicesA is unavailable, negative width will not be checked\n");
2612
2613     hdc = GetDC(0);
2614
2615     memset(&lf, 0, sizeof(lf));
2616     lf.lfCharSet = DEFAULT_CHARSET;
2617     enumed = 0;
2618     EnumFontFamiliesExA(hdc, &lf, enum_truetype_font_proc, (LPARAM)&enumed, 0);
2619     trace("Tested metrics of %d truetype fonts\n", enumed);
2620
2621     ReleaseDC(0, hdc);
2622 }
2623
2624 static void test_nonexistent_font(void)
2625 {
2626     static const struct
2627     {
2628         const char *name;
2629         int charset;
2630     } font_subst[] =
2631     {
2632         { "Times New Roman Baltic", 186 },
2633         { "Times New Roman CE", 238 },
2634         { "Times New Roman CYR", 204 },
2635         { "Times New Roman Greek", 161 },
2636         { "Times New Roman TUR", 162 }
2637     };
2638     LOGFONTA lf;
2639     HDC hdc;
2640     HFONT hfont;
2641     CHARSETINFO csi;
2642     INT cs, expected_cs, i;
2643     char buf[LF_FACESIZE];
2644
2645     if (!is_truetype_font_installed("Arial") ||
2646         !is_truetype_font_installed("Times New Roman"))
2647     {
2648         skip("Arial or Times New Roman not installed\n");
2649         return;
2650     }
2651
2652     expected_cs = GetACP();
2653     if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
2654     {
2655         skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
2656         return;
2657     }
2658     expected_cs = csi.ciCharset;
2659     trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
2660
2661     hdc = GetDC(0);
2662
2663     memset(&lf, 0, sizeof(lf));
2664     lf.lfHeight = 100;
2665     lf.lfWeight = FW_REGULAR;
2666     lf.lfCharSet = ANSI_CHARSET;
2667     lf.lfPitchAndFamily = FF_SWISS;
2668     strcpy(lf.lfFaceName, "Nonexistent font");
2669     hfont = CreateFontIndirectA(&lf);
2670     hfont = SelectObject(hdc, hfont);
2671     GetTextFaceA(hdc, sizeof(buf), buf);
2672     ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
2673     cs = GetTextCharset(hdc);
2674     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2675     DeleteObject(SelectObject(hdc, hfont));
2676
2677     memset(&lf, 0, sizeof(lf));
2678     lf.lfHeight = -13;
2679     lf.lfWeight = FW_DONTCARE;
2680     strcpy(lf.lfFaceName, "Nonexistent font");
2681     hfont = CreateFontIndirectA(&lf);
2682     hfont = SelectObject(hdc, hfont);
2683     GetTextFaceA(hdc, sizeof(buf), buf);
2684 todo_wine /* Wine uses Arial for all substitutions */
2685     ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ ||
2686        !lstrcmpiA(buf, "MS Serif") || /* Win9x */
2687        !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
2688        "Got %s\n", buf);
2689     cs = GetTextCharset(hdc);
2690     ok(cs == expected_cs, "expected %d, got %d\n", expected_cs, cs);
2691     DeleteObject(SelectObject(hdc, hfont));
2692
2693     memset(&lf, 0, sizeof(lf));
2694     lf.lfHeight = -13;
2695     lf.lfWeight = FW_REGULAR;
2696     strcpy(lf.lfFaceName, "Nonexistent font");
2697     hfont = CreateFontIndirectA(&lf);
2698     hfont = SelectObject(hdc, hfont);
2699     GetTextFaceA(hdc, sizeof(buf), buf);
2700     ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
2701        !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "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     memset(&lf, 0, sizeof(lf));
2707     lf.lfHeight = -13;
2708     lf.lfWeight = FW_DONTCARE;
2709     strcpy(lf.lfFaceName, "Times New Roman");
2710     hfont = CreateFontIndirectA(&lf);
2711     hfont = SelectObject(hdc, hfont);
2712     GetTextFaceA(hdc, sizeof(buf), buf);
2713     ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf);
2714     cs = GetTextCharset(hdc);
2715     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2716     DeleteObject(SelectObject(hdc, hfont));
2717
2718     for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++)
2719     {
2720         memset(&lf, 0, sizeof(lf));
2721         lf.lfHeight = -13;
2722         lf.lfWeight = FW_REGULAR;
2723         strcpy(lf.lfFaceName, font_subst[i].name);
2724         hfont = CreateFontIndirectA(&lf);
2725         hfont = SelectObject(hdc, hfont);
2726         cs = GetTextCharset(hdc);
2727         if (font_subst[i].charset == expected_cs)
2728         {
2729             ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
2730             GetTextFaceA(hdc, sizeof(buf), buf);
2731             ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf);
2732         }
2733         else
2734         {
2735             ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d for font %s\n", cs, font_subst[i].name);
2736             GetTextFaceA(hdc, sizeof(buf), buf);
2737             ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
2738                !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got %s for font %s\n", buf, font_subst[i].name);
2739         }
2740         DeleteObject(SelectObject(hdc, hfont));
2741
2742         memset(&lf, 0, sizeof(lf));
2743         lf.lfHeight = -13;
2744         lf.lfWeight = FW_DONTCARE;
2745         strcpy(lf.lfFaceName, font_subst[i].name);
2746         hfont = CreateFontIndirectA(&lf);
2747         hfont = SelectObject(hdc, hfont);
2748         GetTextFaceA(hdc, sizeof(buf), buf);
2749         ok(!lstrcmpiA(buf, "Arial") /* Wine */ ||
2750            !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ ||
2751            !lstrcmpiA(buf, "MS Serif") /* Win9x */ ||
2752            !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
2753            "got %s for font %s\n", buf, font_subst[i].name);
2754         cs = GetTextCharset(hdc);
2755         ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
2756         DeleteObject(SelectObject(hdc, hfont));
2757     }
2758
2759     ReleaseDC(0, hdc);
2760 }
2761
2762 static void test_GdiRealizationInfo(void)
2763 {
2764     HDC hdc;
2765     DWORD info[4];
2766     BOOL r;
2767     HFONT hfont, hfont_old;
2768     LOGFONTA lf;
2769
2770     if(!pGdiRealizationInfo)
2771     {
2772         win_skip("GdiRealizationInfo not available\n");
2773         return;
2774     }
2775
2776     hdc = GetDC(0);
2777
2778     memset(info, 0xcc, sizeof(info));
2779     r = pGdiRealizationInfo(hdc, info);
2780     ok(r != 0, "ret 0\n");
2781     ok((info[0] & 0xf) == 1, "info[0] = %x for the system font\n", info[0]);
2782     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
2783
2784     if (!is_truetype_font_installed("Arial"))
2785     {
2786         skip("skipping GdiRealizationInfo with truetype font\n");
2787         goto end;
2788     }
2789
2790     memset(&lf, 0, sizeof(lf));
2791     strcpy(lf.lfFaceName, "Arial");
2792     lf.lfHeight = 20;
2793     lf.lfWeight = FW_NORMAL;
2794     hfont = CreateFontIndirectA(&lf);
2795     hfont_old = SelectObject(hdc, hfont);
2796
2797     memset(info, 0xcc, sizeof(info));
2798     r = pGdiRealizationInfo(hdc, info);
2799     ok(r != 0, "ret 0\n");
2800     ok((info[0] & 0xf) == 3, "info[0] = %x for arial\n", info[0]);
2801     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
2802
2803     DeleteObject(SelectObject(hdc, hfont_old));
2804
2805  end:
2806     ReleaseDC(0, hdc);
2807 }
2808
2809 /* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include
2810    the nul in the count of characters copied when the face name buffer is not
2811    NULL, whereas it does if the buffer is NULL.  Further, the Unicode version
2812    always includes it.  */
2813 static void test_GetTextFace(void)
2814 {
2815     static const char faceA[] = "Tahoma";
2816     static const WCHAR faceW[] = {'T','a','h','o','m','a', 0};
2817     LOGFONTA fA = {0};
2818     LOGFONTW fW = {0};
2819     char bufA[LF_FACESIZE];
2820     WCHAR bufW[LF_FACESIZE];
2821     HFONT f, g;
2822     HDC dc;
2823     int n;
2824
2825     if(!is_font_installed("Tahoma"))
2826     {
2827         skip("Tahoma is not installed so skipping this test\n");
2828         return;
2829     }
2830
2831     /* 'A' case.  */
2832     memcpy(fA.lfFaceName, faceA, sizeof faceA);
2833     f = CreateFontIndirectA(&fA);
2834     ok(f != NULL, "CreateFontIndirectA failed\n");
2835
2836     dc = GetDC(NULL);
2837     g = SelectObject(dc, f);
2838     n = GetTextFaceA(dc, sizeof bufA, bufA);
2839     ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n);
2840     ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n");
2841
2842     /* Play with the count arg.  */
2843     bufA[0] = 'x';
2844     n = GetTextFaceA(dc, 0, bufA);
2845     ok(n == 0, "GetTextFaceA returned %d\n", n);
2846     ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]);
2847
2848     bufA[0] = 'x';
2849     n = GetTextFaceA(dc, 1, bufA);
2850     ok(n == 0, "GetTextFaceA returned %d\n", n);
2851     ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]);
2852
2853     bufA[0] = 'x'; bufA[1] = 'y';
2854     n = GetTextFaceA(dc, 2, bufA);
2855     ok(n == 1, "GetTextFaceA returned %d\n", n);
2856     ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n");
2857
2858     n = GetTextFaceA(dc, 0, NULL);
2859     ok(n == sizeof faceA ||
2860        broken(n == 0), /* win98, winMe */
2861        "GetTextFaceA returned %d\n", n);
2862
2863     DeleteObject(SelectObject(dc, g));
2864     ReleaseDC(NULL, dc);
2865
2866     /* 'W' case.  */
2867     memcpy(fW.lfFaceName, faceW, sizeof faceW);
2868     SetLastError(0xdeadbeef);
2869     f = CreateFontIndirectW(&fW);
2870     if (!f && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2871     {
2872         win_skip("CreateFontIndirectW is not implemented\n");
2873         return;
2874     }
2875     ok(f != NULL, "CreateFontIndirectW failed\n");
2876
2877     dc = GetDC(NULL);
2878     g = SelectObject(dc, f);
2879     n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW);
2880     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
2881     ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
2882
2883     /* Play with the count arg.  */
2884     bufW[0] = 'x';
2885     n = GetTextFaceW(dc, 0, bufW);
2886     ok(n == 0, "GetTextFaceW returned %d\n", n);
2887     ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]);
2888
2889     bufW[0] = 'x';
2890     n = GetTextFaceW(dc, 1, bufW);
2891     ok(n == 1, "GetTextFaceW returned %d\n", n);
2892     ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]);
2893
2894     bufW[0] = 'x'; bufW[1] = 'y';
2895     n = GetTextFaceW(dc, 2, bufW);
2896     ok(n == 2, "GetTextFaceW returned %d\n", n);
2897     ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n");
2898
2899     n = GetTextFaceW(dc, 0, NULL);
2900     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
2901
2902     DeleteObject(SelectObject(dc, g));
2903     ReleaseDC(NULL, dc);
2904 }
2905
2906 static void test_orientation(void)
2907 {
2908     static const char test_str[11] = "Test String";
2909     HDC hdc;
2910     LOGFONTA lf;
2911     HFONT hfont, old_hfont;
2912     SIZE size;
2913
2914     if (!is_truetype_font_installed("Arial"))
2915     {
2916         skip("Arial is not installed\n");
2917         return;
2918     }
2919
2920     hdc = CreateCompatibleDC(0);
2921     memset(&lf, 0, sizeof(lf));
2922     lstrcpyA(lf.lfFaceName, "Arial");
2923     lf.lfHeight = 72;
2924     lf.lfOrientation = lf.lfEscapement = 900;
2925     hfont = create_font("orientation", &lf);
2926     old_hfont = SelectObject(hdc, hfont);
2927     ok(GetTextExtentExPointA(hdc, test_str, sizeof(test_str), 32767, NULL, NULL, &size), "GetTextExtentExPointA failed\n");
2928     ok(near_match(311, size.cx), "cx should be about 311, got %d\n", size.cx);
2929     ok(near_match(75, size.cy), "cy should be about 75, got %d\n", size.cy);
2930     SelectObject(hdc, old_hfont);
2931     DeleteObject(hfont);
2932     DeleteDC(hdc);
2933 }
2934
2935 static void test_oemcharset(void)
2936 {
2937     HDC hdc;
2938     LOGFONTA lf, clf;
2939     HFONT hfont, old_hfont;
2940     int charset;
2941
2942     hdc = CreateCompatibleDC(0);
2943     ZeroMemory(&lf, sizeof(lf));
2944     lf.lfHeight = 12;
2945     lf.lfCharSet = OEM_CHARSET;
2946     lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
2947     lstrcpyA(lf.lfFaceName, "Terminal");
2948     hfont = CreateFontIndirectA(&lf);
2949     old_hfont = SelectObject(hdc, hfont);
2950     charset = GetTextCharset(hdc);
2951 todo_wine
2952     ok(charset == OEM_CHARSET, "expected %d charset, got %d\n", OEM_CHARSET, charset);
2953     hfont = SelectObject(hdc, old_hfont);
2954     GetObjectA(hfont, sizeof(clf), &clf);
2955     ok(!lstrcmpA(clf.lfFaceName, lf.lfFaceName), "expected %s face name, got %s\n", lf.lfFaceName, clf.lfFaceName);
2956     ok(clf.lfPitchAndFamily == lf.lfPitchAndFamily, "expected %x family, got %x\n", lf.lfPitchAndFamily, clf.lfPitchAndFamily);
2957     ok(clf.lfCharSet == lf.lfCharSet, "expected %d charset, got %d\n", lf.lfCharSet, clf.lfCharSet);
2958     ok(clf.lfHeight == lf.lfHeight, "expected %d height, got %d\n", lf.lfHeight, clf.lfHeight);
2959     DeleteObject(hfont);
2960     DeleteDC(hdc);
2961 }
2962
2963 static void test_GetGlyphOutline(void)
2964 {
2965     MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
2966     HDC hdc;
2967     GLYPHMETRICS gm;
2968     LOGFONTA lf;
2969     HFONT hfont, old_hfont;
2970     INT ret;
2971
2972     if (!is_truetype_font_installed("Tahoma"))
2973     {
2974         skip("Tahoma is not installed\n");
2975         return;
2976     }
2977
2978     hdc = CreateCompatibleDC(0);
2979     memset(&lf, 0, sizeof(lf));
2980     lf.lfHeight = 72;
2981     lstrcpyA(lf.lfFaceName, "Tahoma");
2982     SetLastError(0xdeadbeef);
2983     hfont = CreateFontIndirectA(&lf);
2984     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
2985     old_hfont = SelectObject(hdc, hfont);
2986
2987     memset(&gm, 0, sizeof(gm));
2988     SetLastError(0xdeadbeef);
2989     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
2990     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
2991
2992     memset(&gm, 0, sizeof(gm));
2993     SetLastError(0xdeadbeef);
2994     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
2995     ok(ret == GDI_ERROR, "GetGlyphOutlineA should fail\n");
2996     ok(GetLastError() == 0xdeadbeef ||
2997        GetLastError() == ERROR_INVALID_PARAMETER, /* win98, winMe */
2998        "expected 0xdeadbeef, got %u\n", GetLastError());
2999
3000     memset(&gm, 0, sizeof(gm));
3001     SetLastError(0xdeadbeef);
3002     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3003     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3004         ok(ret != GDI_ERROR, "GetGlyphOutlineW error %u\n", GetLastError());
3005
3006     memset(&gm, 0, sizeof(gm));
3007     SetLastError(0xdeadbeef);
3008     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
3009     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3010     {
3011        ok(ret == GDI_ERROR, "GetGlyphOutlineW should fail\n");
3012        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
3013     }
3014
3015     /* test for needed buffer size request on space char */
3016     memset(&gm, 0, sizeof(gm));
3017     SetLastError(0xdeadbeef);
3018     ret = GetGlyphOutlineW(hdc, ' ', GGO_NATIVE, &gm, 0, NULL, &mat);
3019     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3020         ok(ret == 0, "GetGlyphOutlineW should return 0 buffer size for space char\n");
3021
3022     /* requesting buffer size for space char + error */
3023     memset(&gm, 0, sizeof(gm));
3024     SetLastError(0xdeadbeef);
3025     ret = GetGlyphOutlineW(0, ' ', GGO_NATIVE, &gm, 0, NULL, NULL);
3026     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3027     {
3028        ok(ret == GDI_ERROR, "GetGlyphOutlineW should return GDI_ERROR\n");
3029        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
3030     }
3031
3032     SelectObject(hdc, old_hfont);
3033     DeleteObject(hfont);
3034     DeleteDC(hdc);
3035 }
3036
3037 /* bug #9995: there is a limit to the character width that can be specified */
3038 static void test_GetTextMetrics2(const char *fontname, int font_height)
3039 {
3040     HFONT of, hf;
3041     HDC hdc;
3042     TEXTMETRICA tm;
3043     BOOL ret;
3044     int ave_width, height, width, ratio, scale;
3045
3046     if (!is_truetype_font_installed( fontname)) {
3047         skip("%s is not installed\n", fontname);
3048         return;
3049     }
3050     hdc = CreateCompatibleDC(0);
3051     ok( hdc != NULL, "CreateCompatibleDC failed\n");
3052     /* select width = 0 */
3053     hf = CreateFontA(font_height, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3054             DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3055             DEFAULT_QUALITY, VARIABLE_PITCH,
3056             fontname);
3057     ok( hf != NULL, "CreateFontA(%s, %d) failed\n", fontname, font_height);
3058     of = SelectObject( hdc, hf);
3059     ret = GetTextMetricsA( hdc, &tm);
3060     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
3061     height = tm.tmHeight;
3062     ave_width = tm.tmAveCharWidth;
3063     SelectObject( hdc, of);
3064     DeleteObject( hf);
3065
3066     trace("height %d, ave width %d\n", height, ave_width);
3067
3068     for (width = ave_width * 2; /* nothing*/; width += ave_width)
3069     {
3070         hf = CreateFont(height, width, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3071                         DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3072                         DEFAULT_QUALITY, VARIABLE_PITCH, fontname);
3073         ok(hf != 0, "CreateFont failed\n");
3074         of = SelectObject(hdc, hf);
3075         ret = GetTextMetrics(hdc, &tm);
3076         ok(ret, "GetTextMetrics error %u\n", GetLastError());
3077         SelectObject(hdc, of);
3078         DeleteObject(hf);
3079
3080         if (match_off_by_1(tm.tmAveCharWidth, ave_width) || width / height > 200)
3081             break;
3082     }
3083
3084     DeleteDC(hdc);
3085
3086     ratio = width / height;
3087     scale = width / ave_width;
3088
3089     trace("max width/height ratio (%d / %d) %d, max width scale (%d / %d) %d\n",
3090           width, height, ratio, width, ave_width, scale);
3091
3092     ok(ratio >= 90 && ratio <= 110, "expected width/height ratio 90-110, got %d\n", ratio);
3093 }
3094
3095 static void test_CreateFontIndirect(void)
3096 {
3097     LOGFONTA lf, getobj_lf;
3098     int ret, i;
3099     HFONT hfont;
3100     char TestName[][16] = {"Arial", "Arial Bold", "Arial Italic", "Arial Baltic"};
3101
3102     memset(&lf, 0, sizeof(lf));
3103     lf.lfCharSet = ANSI_CHARSET;
3104     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
3105     lf.lfHeight = 16;
3106     lf.lfWidth = 16;
3107     lf.lfQuality = DEFAULT_QUALITY;
3108     lf.lfItalic = FALSE;
3109     lf.lfWeight = FW_DONTCARE;
3110
3111     for (i = 0; i < sizeof(TestName)/sizeof(TestName[0]); i++)
3112     {
3113         lstrcpyA(lf.lfFaceName, TestName[i]);
3114         hfont = CreateFontIndirectA(&lf);
3115         ok(hfont != 0, "CreateFontIndirectA failed\n");
3116         SetLastError(0xdeadbeef);
3117         ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf);
3118         ok(ret, "GetObject failed: %d\n", GetLastError());
3119         ok(lf.lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf.lfItalic, getobj_lf.lfItalic);
3120         ok(lf.lfWeight == getobj_lf.lfWeight ||
3121            broken((SHORT)lf.lfWeight == getobj_lf.lfWeight), /* win9x */
3122            "lfWeight: expect %08x got %08x\n", lf.lfWeight, getobj_lf.lfWeight);
3123         ok(!lstrcmpA(lf.lfFaceName, getobj_lf.lfFaceName) ||
3124            broken(!memcmp(lf.lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
3125            "font names don't match: %s != %s\n", lf.lfFaceName, getobj_lf.lfFaceName);
3126         DeleteObject(hfont);
3127     }
3128 }
3129
3130 static void test_CreateFontIndirectEx(void)
3131 {
3132     ENUMLOGFONTEXDVA lfex;
3133     HFONT hfont;
3134
3135     if (!pCreateFontIndirectExA)
3136     {
3137         win_skip("CreateFontIndirectExA is not available\n");
3138         return;
3139     }
3140
3141     if (!is_truetype_font_installed("Arial"))
3142     {
3143         skip("Arial is not installed\n");
3144         return;
3145     }
3146
3147     SetLastError(0xdeadbeef);
3148     hfont = pCreateFontIndirectExA(NULL);
3149     ok(hfont == NULL, "got %p\n", hfont);
3150     ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
3151
3152     memset(&lfex, 0, sizeof(lfex));
3153     lstrcpyA(lfex.elfEnumLogfontEx.elfLogFont.lfFaceName, "Arial");
3154     hfont = pCreateFontIndirectExA(&lfex);
3155     ok(hfont != 0, "CreateFontIndirectEx failed\n");
3156     if (hfont)
3157         check_font("Arial", &lfex.elfEnumLogfontEx.elfLogFont, hfont);
3158     DeleteObject(hfont);
3159 }
3160
3161 static void free_font(void *font)
3162 {
3163     UnmapViewOfFile(font);
3164 }
3165
3166 static void *load_font(const char *font_name, DWORD *font_size)
3167 {
3168     char file_name[MAX_PATH];
3169     HANDLE file, mapping;
3170     void *font;
3171
3172     if (!GetWindowsDirectory(file_name, sizeof(file_name))) return NULL;
3173     strcat(file_name, "\\fonts\\");
3174     strcat(file_name, font_name);
3175
3176     file = CreateFile(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
3177     if (file == INVALID_HANDLE_VALUE) return NULL;
3178
3179     *font_size = GetFileSize(file, NULL);
3180
3181     mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
3182     if (!mapping)
3183     {
3184         CloseHandle(file);
3185         return NULL;
3186     }
3187
3188     font = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
3189
3190     CloseHandle(file);
3191     CloseHandle(mapping);
3192     return font;
3193 }
3194
3195 static void test_AddFontMemResource(void)
3196 {
3197     void *font;
3198     DWORD font_size, num_fonts;
3199     HANDLE ret;
3200     BOOL bRet;
3201
3202     if (!pAddFontMemResourceEx || !pRemoveFontMemResourceEx)
3203     {
3204         win_skip("AddFontMemResourceEx is not available on this platform\n");
3205         return;
3206     }
3207
3208     font = load_font("sserife.fon", &font_size);
3209     if (!font)
3210     {
3211         skip("Unable to locate and load font sserife.fon\n");
3212         return;
3213     }
3214
3215     SetLastError(0xdeadbeef);
3216     ret = pAddFontMemResourceEx(NULL, 0, NULL, NULL);
3217     ok(!ret, "AddFontMemResourceEx should fail\n");
3218     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3219        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3220        GetLastError());
3221
3222     SetLastError(0xdeadbeef);
3223     ret = pAddFontMemResourceEx(NULL, 10, NULL, NULL);
3224     ok(!ret, "AddFontMemResourceEx should fail\n");
3225     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3226        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3227        GetLastError());
3228
3229     SetLastError(0xdeadbeef);
3230     ret = pAddFontMemResourceEx(NULL, 0, NULL, &num_fonts);
3231     ok(!ret, "AddFontMemResourceEx should fail\n");
3232     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3233        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3234        GetLastError());
3235
3236     SetLastError(0xdeadbeef);
3237     ret = pAddFontMemResourceEx(NULL, 10, NULL, &num_fonts);
3238     ok(!ret, "AddFontMemResourceEx should fail\n");
3239     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3240        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3241        GetLastError());
3242
3243     SetLastError(0xdeadbeef);
3244     ret = pAddFontMemResourceEx(font, 0, NULL, NULL);
3245     ok(!ret, "AddFontMemResourceEx should fail\n");
3246     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3247        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3248        GetLastError());
3249
3250     SetLastError(0xdeadbeef);
3251     ret = pAddFontMemResourceEx(font, 10, NULL, NULL);
3252     ok(!ret, "AddFontMemResourceEx should fail\n");
3253     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3254        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3255        GetLastError());
3256
3257     num_fonts = 0xdeadbeef;
3258     SetLastError(0xdeadbeef);
3259     ret = pAddFontMemResourceEx(font, 0, NULL, &num_fonts);
3260     ok(!ret, "AddFontMemResourceEx should fail\n");
3261     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3262        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3263        GetLastError());
3264     ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
3265
3266     if (0) /* hangs under windows 2000 */
3267     {
3268         num_fonts = 0xdeadbeef;
3269         SetLastError(0xdeadbeef);
3270         ret = pAddFontMemResourceEx(font, 10, NULL, &num_fonts);
3271         ok(!ret, "AddFontMemResourceEx should fail\n");
3272         ok(GetLastError() == 0xdeadbeef,
3273            "Expected GetLastError() to return 0xdeadbeef, got %u\n",
3274            GetLastError());
3275         ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
3276     }
3277
3278     num_fonts = 0xdeadbeef;
3279     SetLastError(0xdeadbeef);
3280     ret = pAddFontMemResourceEx(font, font_size, NULL, &num_fonts);
3281     ok(ret != 0, "AddFontMemResourceEx error %d\n", GetLastError());
3282     ok(num_fonts != 0xdeadbeef, "number of loaded fonts should not be 0xdeadbeef\n");
3283     ok(num_fonts != 0, "number of loaded fonts should not be 0\n");
3284
3285     free_font(font);
3286
3287     SetLastError(0xdeadbeef);
3288     bRet = pRemoveFontMemResourceEx(ret);
3289     ok(bRet, "RemoveFontMemResourceEx error %d\n", GetLastError());
3290
3291     /* test invalid pointer to number of loaded fonts */
3292     font = load_font("sserife.fon", &font_size);
3293     ok(font != NULL, "Unable to locate and load font sserife.fon\n");
3294
3295     SetLastError(0xdeadbeef);
3296     ret = pAddFontMemResourceEx(font, font_size, NULL, (void *)0xdeadbeef);
3297     ok(!ret, "AddFontMemResourceEx should fail\n");
3298     ok(GetLastError() == 0xdeadbeef,
3299        "Expected GetLastError() to return 0xdeadbeef, got %u\n",
3300        GetLastError());
3301
3302     SetLastError(0xdeadbeef);
3303     ret = pAddFontMemResourceEx(font, font_size, NULL, NULL);
3304     ok(!ret, "AddFontMemResourceEx should fail\n");
3305     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3306        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3307        GetLastError());
3308
3309     free_font(font);
3310 }
3311
3312 START_TEST(font)
3313 {
3314     init();
3315
3316     test_logfont();
3317     test_bitmap_font();
3318     test_outline_font();
3319     test_bitmap_font_metrics();
3320     test_GdiGetCharDimensions();
3321     test_GetCharABCWidths();
3322     test_text_extents();
3323     test_GetGlyphIndices();
3324     test_GetKerningPairs();
3325     test_GetOutlineTextMetrics();
3326     test_SetTextJustification();
3327     test_font_charset();
3328     test_GetFontUnicodeRanges();
3329     test_nonexistent_font();
3330     test_orientation();
3331     test_height_selection();
3332     test_AddFontMemResource();
3333
3334     /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
3335      * I'd like to avoid them in this test.
3336      */
3337     test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
3338     test_EnumFontFamilies("Symbol", SYMBOL_CHARSET);
3339     if (is_truetype_font_installed("Arial Black") &&
3340         (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
3341     {
3342         test_EnumFontFamilies("", ANSI_CHARSET);
3343         test_EnumFontFamilies("", SYMBOL_CHARSET);
3344         test_EnumFontFamilies("", DEFAULT_CHARSET);
3345     }
3346     else
3347         skip("Arial Black or Symbol/Wingdings is not installed\n");
3348     test_GetTextMetrics();
3349     test_GdiRealizationInfo();
3350     test_GetTextFace();
3351     test_GetGlyphOutline();
3352     test_GetTextMetrics2("Tahoma", -11);
3353     test_GetTextMetrics2("Tahoma", -55);
3354     test_GetTextMetrics2("Tahoma", -110);
3355     test_GetTextMetrics2("Arial", -11);
3356     test_GetTextMetrics2("Arial", -55);
3357     test_GetTextMetrics2("Arial", -110);
3358     test_CreateFontIndirect();
3359     test_CreateFontIndirectEx();
3360     test_oemcharset();
3361 }