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