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