~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/gdi32/tests/font.c

Version: ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  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 #define near_match(a, b) (abs((a) - (b)) <= 6)
 34 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
 35 
 36 LONG  (WINAPI *pGdiGetCharDimensions)(HDC hdc, LPTEXTMETRICW lptm, LONG *height);
 37 BOOL  (WINAPI *pGetCharABCWidthsI)(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPABC abc);
 38 BOOL  (WINAPI *pGetCharABCWidthsW)(HDC hdc, UINT first, UINT last, LPABC abc);
 39 DWORD (WINAPI *pGetFontUnicodeRanges)(HDC hdc, LPGLYPHSET lpgs);
 40 DWORD (WINAPI *pGetGlyphIndicesA)(HDC hdc, LPCSTR lpstr, INT count, LPWORD pgi, DWORD flags);
 41 DWORD (WINAPI *pGetGlyphIndicesW)(HDC hdc, LPCWSTR lpstr, INT count, LPWORD pgi, DWORD flags);
 42 BOOL  (WINAPI *pGdiRealizationInfo)(HDC hdc, DWORD *);
 43 
 44 static HMODULE hgdi32 = 0;
 45 
 46 static void init(void)
 47 {
 48     hgdi32 = GetModuleHandleA("gdi32.dll");
 49 
 50     pGdiGetCharDimensions = (void *)GetProcAddress(hgdi32, "GdiGetCharDimensions");
 51     pGetCharABCWidthsI = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsI");
 52     pGetCharABCWidthsW = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsW");
 53     pGetFontUnicodeRanges = (void *)GetProcAddress(hgdi32, "GetFontUnicodeRanges");
 54     pGetGlyphIndicesA = (void *)GetProcAddress(hgdi32, "GetGlyphIndicesA");
 55     pGetGlyphIndicesW = (void *)GetProcAddress(hgdi32, "GetGlyphIndicesW");
 56     pGdiRealizationInfo = (void *)GetProcAddress(hgdi32, "GdiRealizationInfo");
 57 }
 58 
 59 static INT CALLBACK is_truetype_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
 60 {
 61     if (type != TRUETYPE_FONTTYPE) return 1;
 62 
 63     return 0;
 64 }
 65 
 66 static BOOL is_truetype_font_installed(const char *name)
 67 {
 68     HDC hdc = GetDC(0);
 69     BOOL ret = FALSE;
 70 
 71     if (!EnumFontFamiliesA(hdc, name, is_truetype_font_installed_proc, 0))
 72         ret = TRUE;
 73 
 74     ReleaseDC(0, hdc);
 75     return ret;
 76 }
 77 
 78 static INT CALLBACK is_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
 79 {
 80     return 0;
 81 }
 82 
 83 static BOOL is_font_installed(const char *name)
 84 {
 85     HDC hdc = GetDC(0);
 86     BOOL ret = FALSE;
 87 
 88     if(!EnumFontFamiliesA(hdc, name, is_font_installed_proc, 0))
 89         ret = TRUE;
 90 
 91     ReleaseDC(0, hdc);
 92     return ret;
 93 }
 94 
 95 static void check_font(const char* test, const LOGFONTA* lf, HFONT hfont)
 96 {
 97     LOGFONTA getobj_lf;
 98     int ret, minlen = 0;
 99 
100     if (!hfont)
101         return;
102 
103     ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf);
104     /* NT4 tries to be clever and only returns the minimum length */
105     while (lf->lfFaceName[minlen] && minlen < LF_FACESIZE-1)
106         minlen++;
107     minlen += FIELD_OFFSET(LOGFONTA, lfFaceName) + 1;
108     ok(ret == sizeof(LOGFONTA) || ret == minlen, "%s: GetObject returned %d\n", test, ret);
109     ok(!memcmp(&lf, &lf, FIELD_OFFSET(LOGFONTA, lfFaceName)), "%s: fonts don't match\n", test);
110     ok(!lstrcmpA(lf->lfFaceName, getobj_lf.lfFaceName),
111        "%s: font names don't match: %s != %s\n", test, lf->lfFaceName, getobj_lf.lfFaceName);
112 }
113 
114 static HFONT create_font(const char* test, const LOGFONTA* lf)
115 {
116     HFONT hfont = CreateFontIndirectA(lf);
117     ok(hfont != 0, "%s: CreateFontIndirect failed\n", test);
118     if (hfont)
119         check_font(test, lf, hfont);
120     return hfont;
121 }
122 
123 static void test_logfont(void)
124 {
125     LOGFONTA lf;
126     HFONT hfont;
127 
128     memset(&lf, 0, sizeof lf);
129 
130     lf.lfCharSet = ANSI_CHARSET;
131     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
132     lf.lfWeight = FW_DONTCARE;
133     lf.lfHeight = 16;
134     lf.lfWidth = 16;
135     lf.lfQuality = DEFAULT_QUALITY;
136 
137     lstrcpyA(lf.lfFaceName, "Arial");
138     hfont = create_font("Arial", &lf);
139     DeleteObject(hfont);
140 
141     memset(&lf, 'A', sizeof(lf));
142     hfont = CreateFontIndirectA(&lf);
143     ok(hfont != 0, "CreateFontIndirectA with strange LOGFONT failed\n");
144     
145     lf.lfFaceName[LF_FACESIZE - 1] = 0;
146     check_font("AAA...", &lf, hfont);
147     DeleteObject(hfont);
148 }
149 
150 static INT CALLBACK font_enum_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
151 {
152     if (type & RASTER_FONTTYPE)
153     {
154         LOGFONT *lf = (LOGFONT *)lParam;
155         *lf = *elf;
156         return 0; /* stop enumeration */
157     }
158 
159     return 1; /* continue enumeration */
160 }
161 
162 static void compare_tm(const TEXTMETRICA *tm, const TEXTMETRICA *otm)
163 {
164     ok(tm->tmHeight == otm->tmHeight, "tmHeight %d != %d\n", tm->tmHeight, otm->tmHeight);
165     ok(tm->tmAscent == otm->tmAscent, "tmAscent %d != %d\n", tm->tmAscent, otm->tmAscent);
166     ok(tm->tmDescent == otm->tmDescent, "tmDescent %d != %d\n", tm->tmDescent, otm->tmDescent);
167     ok(tm->tmInternalLeading == otm->tmInternalLeading, "tmInternalLeading %d != %d\n", tm->tmInternalLeading, otm->tmInternalLeading);
168     ok(tm->tmExternalLeading == otm->tmExternalLeading, "tmExternalLeading %d != %d\n", tm->tmExternalLeading, otm->tmExternalLeading);
169     ok(tm->tmAveCharWidth == otm->tmAveCharWidth, "tmAveCharWidth %d != %d\n", tm->tmAveCharWidth, otm->tmAveCharWidth);
170     ok(tm->tmMaxCharWidth == otm->tmMaxCharWidth, "tmMaxCharWidth %d != %d\n", tm->tmMaxCharWidth, otm->tmMaxCharWidth);
171     ok(tm->tmWeight == otm->tmWeight, "tmWeight %d != %d\n", tm->tmWeight, otm->tmWeight);
172     ok(tm->tmOverhang == otm->tmOverhang, "tmOverhang %d != %d\n", tm->tmOverhang, otm->tmOverhang);
173     ok(tm->tmDigitizedAspectX == otm->tmDigitizedAspectX, "tmDigitizedAspectX %d != %d\n", tm->tmDigitizedAspectX, otm->tmDigitizedAspectX);
174     ok(tm->tmDigitizedAspectY == otm->tmDigitizedAspectY, "tmDigitizedAspectY %d != %d\n", tm->tmDigitizedAspectY, otm->tmDigitizedAspectY);
175     ok(tm->tmFirstChar == otm->tmFirstChar, "tmFirstChar %d != %d\n", tm->tmFirstChar, otm->tmFirstChar);
176     ok(tm->tmLastChar == otm->tmLastChar, "tmLastChar %d != %d\n", tm->tmLastChar, otm->tmLastChar);
177     ok(tm->tmDefaultChar == otm->tmDefaultChar, "tmDefaultChar %d != %d\n", tm->tmDefaultChar, otm->tmDefaultChar);
178     ok(tm->tmBreakChar == otm->tmBreakChar, "tmBreakChar %d != %d\n", tm->tmBreakChar, otm->tmBreakChar);
179     ok(tm->tmItalic == otm->tmItalic, "tmItalic %d != %d\n", tm->tmItalic, otm->tmItalic);
180     ok(tm->tmUnderlined == otm->tmUnderlined, "tmUnderlined %d != %d\n", tm->tmUnderlined, otm->tmUnderlined);
181     ok(tm->tmStruckOut == otm->tmStruckOut, "tmStruckOut %d != %d\n", tm->tmStruckOut, otm->tmStruckOut);
182     ok(tm->tmPitchAndFamily == otm->tmPitchAndFamily, "tmPitchAndFamily %d != %d\n", tm->tmPitchAndFamily, otm->tmPitchAndFamily);
183     ok(tm->tmCharSet == otm->tmCharSet, "tmCharSet %d != %d\n", tm->tmCharSet, otm->tmCharSet);
184 }
185 
186 static void test_font_metrics(HDC hdc, HFONT hfont, LONG lfHeight,
187                               LONG lfWidth, const char *test_str,
188                               INT test_str_len, const TEXTMETRICA *tm_orig,
189                               const SIZE *size_orig, INT width_of_A_orig,
190                               INT scale_x, INT scale_y)
191 {
192     HFONT old_hfont;
193     LOGFONTA lf;
194     OUTLINETEXTMETRIC otm;
195     TEXTMETRICA tm;
196     SIZE size;
197     INT width_of_A, cx, cy;
198     UINT ret;
199 
200     if (!hfont)
201         return;
202 
203     GetObjectA(hfont, sizeof(lf), &lf);
204 
205     old_hfont = SelectObject(hdc, hfont);
206 
207     if (GetOutlineTextMetricsA(hdc, 0, NULL))
208     {
209         otm.otmSize = sizeof(otm) / 2;
210         ret = GetOutlineTextMetricsA(hdc, otm.otmSize, &otm);
211         ok(ret == sizeof(otm)/2 /* XP */ ||
212            ret == 1 /* Win9x */, "expected sizeof(otm)/2, got %u\n", ret);
213 
214         memset(&otm, 0x1, sizeof(otm));
215         otm.otmSize = sizeof(otm);
216         ret = GetOutlineTextMetricsA(hdc, otm.otmSize, &otm);
217         ok(ret == sizeof(otm) /* XP */ ||
218            ret == 1 /* Win9x */, "expected sizeof(otm), got %u\n", ret);
219 
220         memset(&tm, 0x2, sizeof(tm));
221         ret = GetTextMetricsA(hdc, &tm);
222         ok(ret, "GetTextMetricsA failed\n");
223         /* the structure size is aligned */
224         if (memcmp(&tm, &otm.otmTextMetrics, FIELD_OFFSET(TEXTMETRICA, tmCharSet) + 1))
225         {
226             ok(0, "tm != otm\n");
227             compare_tm(&tm, &otm.otmTextMetrics);
228         }
229 
230         tm = otm.otmTextMetrics;
231 if (0) /* these metrics are scaled too, but with rounding errors */
232 {
233         ok(otm.otmAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmAscent, tm.tmAscent);
234         ok(otm.otmDescent == -tm.tmDescent, "descent %d != %d\n", otm.otmDescent, -tm.tmDescent);
235 }
236         ok(otm.otmMacAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmMacAscent, tm.tmAscent);
237         ok(otm.otmDescent < 0, "otm.otmDescent should be < 0\n");
238         ok(otm.otmMacDescent < 0, "otm.otmMacDescent should be < 0\n");
239         ok(tm.tmDescent > 0, "tm.tmDescent should be > 0\n");
240         ok(otm.otmMacDescent == -tm.tmDescent, "descent %d != %d\n", otm.otmMacDescent, -tm.tmDescent);
241         ok(otm.otmEMSquare == 2048, "expected 2048, got %d\n", otm.otmEMSquare);
242     }
243     else
244     {
245         ret = GetTextMetricsA(hdc, &tm);
246         ok(ret, "GetTextMetricsA failed\n");
247     }
248 
249     cx = tm.tmAveCharWidth / tm_orig->tmAveCharWidth;
250     cy = tm.tmHeight / tm_orig->tmHeight;
251     ok(cx == scale_x && cy == scale_y, "expected scale_x %d, scale_y %d, got cx %d, cy %d\n",
252        scale_x, scale_y, cx, cy);
253     ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "height %d != %d\n", tm.tmHeight, tm_orig->tmHeight * scale_y);
254     ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "ascent %d != %d\n", tm.tmAscent, tm_orig->tmAscent * scale_y);
255     ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "descent %d != %d\n", tm.tmDescent, tm_orig->tmDescent * scale_y);
256     ok(near_match(tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x), "ave width %d != %d\n", tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x);
257     ok(near_match(tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x), "max width %d != %d\n", tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x);
258 
259     ok(lf.lfHeight == lfHeight, "lfHeight %d != %d\n", lf.lfHeight, lfHeight);
260     if (lf.lfHeight)
261     {
262         if (lf.lfWidth)
263             ok(lf.lfWidth == tm.tmAveCharWidth, "lfWidth %d != tm %d\n", lf.lfWidth, tm.tmAveCharWidth);
264     }
265     else
266         ok(lf.lfWidth == lfWidth, "lfWidth %d != %d\n", lf.lfWidth, lfWidth);
267 
268     GetTextExtentPoint32A(hdc, test_str, test_str_len, &size);
269 
270     ok(near_match(size.cx, size_orig->cx * scale_x), "cx %d != %d\n", size.cx, size_orig->cx * scale_x);
271     ok(size.cy == size_orig->cy * scale_y, "cy %d != %d\n", size.cy, size_orig->cy * scale_y);
272 
273     GetCharWidthA(hdc, 'A', 'A', &width_of_A);
274 
275     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);
276 
277     SelectObject(hdc, old_hfont);
278 }
279 
280 /* Test how GDI scales bitmap font metrics */
281 static void test_bitmap_font(void)
282 {
283     static const char test_str[11] = "Test String";
284     HDC hdc;
285     LOGFONTA bitmap_lf;
286     HFONT hfont, old_hfont;
287     TEXTMETRICA tm_orig;
288     SIZE size_orig;
289     INT ret, i, width_orig, height_orig, scale, lfWidth;
290 
291     hdc = GetDC(0);
292 
293     /* "System" has only 1 pixel size defined, otherwise the test breaks */
294     ret = EnumFontFamiliesA(hdc, "System", font_enum_proc, (LPARAM)&bitmap_lf);
295     if (ret)
296     {
297         ReleaseDC(0, hdc);
298         trace("no bitmap fonts were found, skipping the test\n");
299         return;
300     }
301 
302     trace("found bitmap font %s, height %d\n", bitmap_lf.lfFaceName, bitmap_lf.lfHeight);
303 
304     height_orig = bitmap_lf.lfHeight;
305     lfWidth = bitmap_lf.lfWidth;
306 
307     hfont = create_font("bitmap", &bitmap_lf);
308     old_hfont = SelectObject(hdc, hfont);
309     ok(GetTextMetricsA(hdc, &tm_orig), "GetTextMetricsA failed\n");
310     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
311     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
312     SelectObject(hdc, old_hfont);
313     DeleteObject(hfont);
314 
315     bitmap_lf.lfHeight = 0;
316     bitmap_lf.lfWidth = 4;
317     hfont = create_font("bitmap", &bitmap_lf);
318     test_font_metrics(hdc, hfont, 0, 4, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, 1);
319     DeleteObject(hfont);
320 
321     bitmap_lf.lfHeight = height_orig;
322     bitmap_lf.lfWidth = lfWidth;
323 
324     /* test fractional scaling */
325     for (i = 1; i <= height_orig * 3; i++)
326     {
327         INT nearest_height;
328 
329         bitmap_lf.lfHeight = i;
330         hfont = create_font("fractional", &bitmap_lf);
331         scale = (i + height_orig - 1) / height_orig;
332         nearest_height = scale * height_orig;
333         /* XP allows not more than 10% deviation */
334         if (scale > 1 && nearest_height - i > nearest_height / 10) scale--;
335         test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, scale);
336         DeleteObject(hfont);
337     }
338 
339     /* test integer scaling 3x2 */
340     bitmap_lf.lfHeight = height_orig * 2;
341     bitmap_lf.lfWidth *= 3;
342     hfont = create_font("3x2", &bitmap_lf);
343     test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 2);
344     DeleteObject(hfont);
345 
346     /* test integer scaling 3x3 */
347     bitmap_lf.lfHeight = height_orig * 3;
348     bitmap_lf.lfWidth = 0;
349     hfont = create_font("3x3", &bitmap_lf);
350     test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 3);
351     DeleteObject(hfont);
352 
353     ReleaseDC(0, hdc);
354 }
355 
356 /* Test how GDI scales outline font metrics */
357 static void test_outline_font(void)
358 {
359     static const char test_str[11] = "Test String";
360     HDC hdc;
361     LOGFONTA lf;
362     HFONT hfont, old_hfont;
363     OUTLINETEXTMETRICA otm;
364     SIZE size_orig;
365     INT width_orig, height_orig, lfWidth;
366     XFORM xform;
367     GLYPHMETRICS gm;
368     MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
369     MAT2 mat2 = { {0x8000,0}, {0,0}, {0,0}, {0x8000,0} };
370     POINT pt;
371     INT ret;
372 
373     if (!is_truetype_font_installed("Arial"))
374     {
375         skip("Arial is not installed\n");
376         return;
377     }
378 
379     hdc = CreateCompatibleDC(0);
380 
381     memset(&lf, 0, sizeof(lf));
382     strcpy(lf.lfFaceName, "Arial");
383     lf.lfHeight = 72;
384     hfont = create_font("outline", &lf);
385     old_hfont = SelectObject(hdc, hfont);
386     otm.otmSize = sizeof(otm);
387     ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n");
388     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
389     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
390     SelectObject(hdc, old_hfont);
391 
392     test_font_metrics(hdc, hfont, lf.lfHeight, otm.otmTextMetrics.tmAveCharWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
393     DeleteObject(hfont);
394 
395     /* font of otmEMSquare height helps to avoid a lot of rounding errors */
396     lf.lfHeight = otm.otmEMSquare;
397     lf.lfHeight = -lf.lfHeight;
398     hfont = create_font("outline", &lf);
399     old_hfont = SelectObject(hdc, hfont);
400     otm.otmSize = sizeof(otm);
401     ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n");
402     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
403     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
404     SelectObject(hdc, old_hfont);
405     DeleteObject(hfont);
406 
407     height_orig = otm.otmTextMetrics.tmHeight;
408     lfWidth = otm.otmTextMetrics.tmAveCharWidth;
409 
410     /* test integer scaling 3x2 */
411     lf.lfHeight = height_orig * 2;
412     lf.lfWidth = lfWidth * 3;
413     hfont = create_font("3x2", &lf);
414     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 2);
415     DeleteObject(hfont);
416 
417     /* test integer scaling 3x3 */
418     lf.lfHeight = height_orig * 3;
419     lf.lfWidth = lfWidth * 3;
420     hfont = create_font("3x3", &lf);
421     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 3);
422     DeleteObject(hfont);
423 
424     /* test integer scaling 1x1 */
425     lf.lfHeight = height_orig * 1;
426     lf.lfWidth = lfWidth * 1;
427     hfont = create_font("1x1", &lf);
428     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
429     DeleteObject(hfont);
430 
431     /* test integer scaling 1x1 */
432     lf.lfHeight = height_orig;
433     lf.lfWidth = 0;
434     hfont = create_font("1x1", &lf);
435     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
436 
437     old_hfont = SelectObject(hdc, hfont);
438     /* with an identity matrix */
439     memset(&gm, 0, sizeof(gm));
440     SetLastError(0xdeadbeef);
441     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
442     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
443     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
444     ok(gm.gmCellIncX == width_orig, "incX %d != %d\n", gm.gmCellIncX, width_orig);
445     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
446     /* with a custom matrix */
447     memset(&gm, 0, sizeof(gm));
448     SetLastError(0xdeadbeef);
449     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
450     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
451     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
452     ok(gm.gmCellIncX == width_orig/2, "incX %d != %d\n", gm.gmCellIncX, width_orig/2);
453     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
454     SelectObject(hdc, old_hfont);
455 
456     SetMapMode(hdc, MM_ANISOTROPIC);
457     /* test restrictions of compatibility mode GM_COMPATIBLE */
458     /*  part 1: rescaling only X should not change font scaling on screen.
459                 So compressing the X axis by 2 is not done, and this
460                 appears as X scaling of 2 that no one requested. */
461     SetWindowExtEx(hdc, 100, 100, NULL);
462     SetViewportExtEx(hdc, 50, 100, NULL);
463     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 2, 1);
464 
465     /*  part 2: rescaling only Y should change font scaling.
466                 As also X is scaled by a factor of 2, but this is not
467                 requested by the DC transformation, we get a scaling factor
468                 of 2 in the X coordinate. */
469     SetViewportExtEx(hdc, 100, 200, NULL);
470     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 2, 1);
471 
472     /* restore scaling */
473     SetMapMode(hdc, MM_TEXT);
474 
475     if (!SetGraphicsMode(hdc, GM_ADVANCED))
476     {
477         DeleteObject(hfont);
478         DeleteDC(hdc);
479         skip("GM_ADVANCED is not supported on this platform\n");
480         return;
481     }
482 
483     xform.eM11 = 20.0f;
484     xform.eM12 = 0.0f;
485     xform.eM21 = 0.0f;
486     xform.eM22 = 20.0f;
487     xform.eDx = 0.0f;
488     xform.eDy = 0.0f;
489 
490     SetLastError(0xdeadbeef);
491     ret = SetWorldTransform(hdc, &xform);
492     ok(ret, "SetWorldTransform error %u\n", GetLastError());
493 
494     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
495 
496     old_hfont = SelectObject(hdc, hfont);
497     /* with an identity matrix */
498     memset(&gm, 0, sizeof(gm));
499     SetLastError(0xdeadbeef);
500     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
501     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
502     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
503     pt.x = width_orig; pt.y = 0;
504     LPtoDP(hdc, &pt, 1);
505     ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x);
506     ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig);
507     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
508     /* with a custom matrix */
509     memset(&gm, 0, sizeof(gm));
510     SetLastError(0xdeadbeef);
511     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
512     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
513     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
514     pt.x = width_orig; pt.y = 0;
515     LPtoDP(hdc, &pt, 1);
516     ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2);
517     ok(near_match(gm.gmCellIncX, 10 * width_orig), "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig);
518     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
519     SelectObject(hdc, old_hfont);
520 
521     SetLastError(0xdeadbeef);
522     ret = SetMapMode(hdc, MM_LOMETRIC);
523     ok(ret == MM_TEXT, "expected MM_TEXT, got %d, error %u\n", ret, GetLastError());
524 
525     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
526 
527     old_hfont = SelectObject(hdc, hfont);
528     /* with an identity matrix */
529     memset(&gm, 0, sizeof(gm));
530     SetLastError(0xdeadbeef);
531     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
532     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
533     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
534     pt.x = width_orig; pt.y = 0;
535     LPtoDP(hdc, &pt, 1);
536     ok(near_match(gm.gmCellIncX, pt.x), "incX %d != %d\n", gm.gmCellIncX, pt.x);
537     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
538     /* with a custom matrix */
539     memset(&gm, 0, sizeof(gm));
540     SetLastError(0xdeadbeef);
541     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
542     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
543     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
544     pt.x = width_orig; pt.y = 0;
545     LPtoDP(hdc, &pt, 1);
546     ok(near_match(gm.gmCellIncX, (pt.x + 1)/2), "incX %d != %d\n", gm.gmCellIncX, (pt.x + 1)/2);
547     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
548     SelectObject(hdc, old_hfont);
549 
550     SetLastError(0xdeadbeef);
551     ret = SetMapMode(hdc, MM_TEXT);
552     ok(ret == MM_LOMETRIC, "expected MM_LOMETRIC, got %d, error %u\n", ret, GetLastError());
553 
554     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
555 
556     old_hfont = SelectObject(hdc, hfont);
557     /* with an identity matrix */
558     memset(&gm, 0, sizeof(gm));
559     SetLastError(0xdeadbeef);
560     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
561     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
562     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
563     pt.x = width_orig; pt.y = 0;
564     LPtoDP(hdc, &pt, 1);
565     ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x);
566     ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig);
567     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
568     /* with a custom matrix */
569     memset(&gm, 0, sizeof(gm));
570     SetLastError(0xdeadbeef);
571     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
572     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
573     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
574     pt.x = width_orig; pt.y = 0;
575     LPtoDP(hdc, &pt, 1);
576     ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2);
577     ok(gm.gmCellIncX == 10 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig);
578     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
579     SelectObject(hdc, old_hfont);
580 
581     DeleteObject(hfont);
582     DeleteDC(hdc);
583 }
584 
585 static INT CALLBACK find_font_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
586 {
587     LOGFONT *lf = (LOGFONT *)lParam;
588 
589     if (elf->lfHeight == lf->lfHeight && !strcmp(elf->lfFaceName, lf->lfFaceName))
590     {
591         *lf = *elf;
592         return 0; /* stop enumeration */
593     }
594     return 1; /* continue enumeration */
595 }
596 
597 static void test_bitmap_font_metrics(void)
598 {
599     static const struct font_data
600     {
601         const char face_name[LF_FACESIZE];
602         int weight, height, ascent, descent, int_leading, ext_leading;
603         int ave_char_width, max_char_width;
604         DWORD ansi_bitfield;
605     } fd[] =
606     {
607         { "MS Sans Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
608         { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
609         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 16, FS_LATIN1 | FS_CYRILLIC },
610         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, FS_LATIN2 },
611         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 19, FS_LATIN1 },
612         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 24, FS_LATIN2 },
613         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 20, FS_CYRILLIC },
614         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 24, FS_LATIN1 },
615         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 6, 0, 12, 24, FS_LATIN2 },
616         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 25, FS_CYRILLIC },
617         { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
618         { "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8, FS_LATIN1 | FS_LATIN2 },
619         { "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, FS_CYRILLIC },
620         { "MS Serif", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
621         { "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, FS_LATIN1 },
622         { "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 12, FS_LATIN2 | FS_CYRILLIC },
623         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 14, FS_LATIN1 | FS_LATIN2 },
624         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 16, FS_CYRILLIC },
625         { "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 18, FS_LATIN1 | FS_LATIN2 },
626         { "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 19, FS_CYRILLIC },
627         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 17, FS_LATIN1 },
628         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 22, FS_LATIN2 },
629         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 23, FS_CYRILLIC },
630         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 23, FS_LATIN1 },
631         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 26, FS_LATIN2 },
632         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 27, FS_CYRILLIC },
633         { "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 33, FS_LATIN1 | FS_LATIN2 },
634         { "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 34, FS_CYRILLIC },
635         { "Courier", FW_NORMAL, 13, 11, 2, 0, 0, 8, 8, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
636         { "Courier", FW_NORMAL, 16, 13, 3, 0, 0, 9, 9, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
637         { "Courier", FW_NORMAL, 20, 16, 4, 0, 0, 12, 12, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
638         { "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 14, FS_LATIN1 },
639         { "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 15, FS_LATIN2 | FS_CYRILLIC },
640 /*
641  * TODO:  the system for CP932 should be NORMAL, not BOLD.  However that would
642  *        require a new system.sfd for that font
643  */
644         { "System", FW_BOLD, 18, 16, 2, 0, 2, 8, 16, FS_JISJAPAN },
645         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 2, FS_LATIN1 },
646         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 8, FS_LATIN2 | FS_CYRILLIC },
647         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 2, 4, FS_JISJAPAN },
648         { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 3, 4, FS_LATIN1 },
649         { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 2, 8, FS_LATIN2 | FS_CYRILLIC },
650         { "Small Fonts", FW_NORMAL, 5, 4, 1, 0, 0, 3, 6, FS_JISJAPAN },
651         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 13, FS_LATIN1 },
652         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, FS_LATIN2 | FS_CYRILLIC },
653         { "Small Fonts", FW_NORMAL, 6, 5, 1, 0, 0, 4, 8, FS_JISJAPAN },
654         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 7, FS_LATIN1 },
655         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, FS_LATIN2 | FS_CYRILLIC },
656         { "Small Fonts", FW_NORMAL, 8, 7, 1, 0, 0, 5, 10, FS_JISJAPAN },
657         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8, FS_LATIN1 | FS_LATIN2 },
658         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, FS_CYRILLIC },
659         { "Small Fonts", FW_NORMAL, 10, 8, 2, 0, 0, 6, 12, FS_JISJAPAN },
660         { "Small Fonts", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
661         { "Small Fonts", FW_NORMAL, 11, 9, 2, 0, 0, 7, 14, FS_JISJAPAN },
662         { "Fixedsys", FW_NORMAL, 15, 12, 3, 3, 0, 8, 8, FS_LATIN1 | FS_LATIN2 },
663         { "Fixedsys", FW_NORMAL, 16, 12, 4, 3, 0, 8, 8, FS_CYRILLIC },
664         { "FixedSys", FW_NORMAL, 18, 16, 2, 0, 0, 8, 16, FS_JISJAPAN }
665 
666         /* FIXME: add "Terminal" */
667     };
668     HDC hdc;
669     LOGFONT lf;
670     HFONT hfont, old_hfont;
671     TEXTMETRIC tm;
672     INT ret, i;
673 
674     hdc = CreateCompatibleDC(0);
675     assert(hdc);
676 
677     for (i = 0; i < sizeof(fd)/sizeof(fd[0]); i++)
678     {
679         int bit;
680 
681         memset(&lf, 0, sizeof(lf));
682 
683         lf.lfHeight = fd[i].height;
684         strcpy(lf.lfFaceName, fd[i].face_name);
685 
686         for(bit = 0; bit < 32; bit++)
687         {
688             DWORD fs[2];
689             CHARSETINFO csi;
690 
691             fs[0] = 1L << bit;
692             fs[1] = 0;
693             if((fd[i].ansi_bitfield & fs[0]) == 0) continue;
694             if(!TranslateCharsetInfo( fs, &csi, TCI_SRCFONTSIG )) continue;
695 
696             lf.lfCharSet = csi.ciCharset;
697             ret = EnumFontFamiliesEx(hdc, &lf, find_font_proc, (LPARAM)&lf, 0);
698             if (ret) continue;
699 
700             trace("found font %s, height %d charset %x\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet);
701 
702             hfont = create_font(lf.lfFaceName, &lf);
703             old_hfont = SelectObject(hdc, hfont);
704             ok(GetTextMetrics(hdc, &tm), "GetTextMetrics error %d\n", GetLastError());
705 
706             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);
707             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);
708             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);
709             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);
710             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);
711             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);
712             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);
713 
714             /* Don't run the max char width test on System/ANSI_CHARSET.  We have extra characters in our font
715                that make the max width bigger */
716             if(strcmp(lf.lfFaceName, "System") || lf.lfCharSet != ANSI_CHARSET)
717                 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);
718 
719             SelectObject(hdc, old_hfont);
720             DeleteObject(hfont);
721         }
722     }
723 
724     DeleteDC(hdc);
725 }
726 
727 static void test_GdiGetCharDimensions(void)
728 {
729     HDC hdc;
730     TEXTMETRICW tm;
731     LONG ret;
732     SIZE size;
733     LONG avgwidth, height;
734     static const char szAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
735 
736     if (!pGdiGetCharDimensions)
737     {
738         skip("GdiGetCharDimensions not available on this platform\n");
739         return;
740     }
741 
742     hdc = CreateCompatibleDC(NULL);
743 
744     GetTextExtentPoint(hdc, szAlphabet, strlen(szAlphabet), &size);
745     avgwidth = ((size.cx / 26) + 1) / 2;
746 
747     ret = pGdiGetCharDimensions(hdc, &tm, &height);
748     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
749     ok(height == tm.tmHeight, "GdiGetCharDimensions should have set height to %d instead of %d\n", tm.tmHeight, height);
750 
751     ret = pGdiGetCharDimensions(hdc, &tm, NULL);
752     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
753 
754     ret = pGdiGetCharDimensions(hdc, NULL, NULL);
755     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
756 
757     height = 0;
758     ret = pGdiGetCharDimensions(hdc, NULL, &height);
759     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
760     ok(height == size.cy, "GdiGetCharDimensions should have set height to %d instead of %d\n", size.cy, height);
761 
762     DeleteDC(hdc);
763 }
764 
765 static void test_GetCharABCWidths(void)
766 {
767     static const WCHAR str[] = {'a',0};
768     BOOL ret;
769     HDC hdc;
770     LOGFONTA lf;
771     HFONT hfont;
772     ABC abc[