1 /*
2  * Unit test suite for fonts
3  *
4  * Copyright (C) 2007 Google (Evan Stade)
5  * Copyright (C) 2012 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 <math.h>
23 
24 #define WIN32_NO_STATUS
25 #define _INC_WINDOWS
26 #define COM_NO_WINDOWS_H
27 
28 //#include "windows.h"
29 #include <wine/test.h>
30 #include <wingdi.h>
31 #include <winnls.h>
32 #include <objbase.h>
33 #include <gdiplus.h>
34 
35 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
36 #define expect_(expected, got, precision) ok(abs((expected) - (got)) <= (precision), "Expected %d, got %d\n", (expected), (got))
37 #define expectf_(expected, got, precision) ok(fabs((expected) - (got)) <= (precision), "Expected %f, got %f\n", (expected), (got))
38 #define expectf(expected, got) expectf_((expected), (got), 0.001)
39 
40 static const WCHAR nonexistent[] = {'T','h','i','s','F','o','n','t','s','h','o','u','l','d','N','o','t','E','x','i','s','t','\0'};
41 static const WCHAR MSSansSerif[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'};
42 static const WCHAR TimesNewRoman[] = {'T','i','m','e','s',' ','N','e','w',' ','R','o','m','a','n','\0'};
43 static const WCHAR Tahoma[] = {'T','a','h','o','m','a',0};
44 
45 static void set_rect_empty(RectF *rc)
46 {
47     rc->X = 0.0;
48     rc->Y = 0.0;
49     rc->Width = 0.0;
50     rc->Height = 0.0;
51 }
52 
53 static void test_createfont(void)
54 {
55     GpFontFamily* fontfamily = NULL, *fontfamily2;
56     GpFont* font = NULL;
57     GpStatus stat;
58     Unit unit;
59     UINT i;
60     REAL size;
61     WCHAR familyname[LF_FACESIZE];
62 
63     stat = GdipCreateFontFamilyFromName(nonexistent, NULL, &fontfamily);
64     expect (FontFamilyNotFound, stat);
65     stat = GdipDeleteFont(font);
66     expect (InvalidParameter, stat);
67     stat = GdipCreateFontFamilyFromName(Tahoma, NULL, &fontfamily);
68     expect (Ok, stat);
69     stat = GdipCreateFont(fontfamily, 12, FontStyleRegular, UnitPoint, &font);
70     expect (Ok, stat);
71     stat = GdipGetFontUnit (font, &unit);
72     expect (Ok, stat);
73     expect (UnitPoint, unit);
74 
75     stat = GdipGetFamily(font, &fontfamily2);
76     expect(Ok, stat);
77     stat = GdipGetFamilyName(fontfamily2, familyname, 0);
78     expect(Ok, stat);
79     ok (lstrcmpiW(Tahoma, familyname) == 0, "Expected Tahoma, got %s\n",
80             wine_dbgstr_w(familyname));
81     stat = GdipDeleteFontFamily(fontfamily2);
82     expect(Ok, stat);
83 
84     /* Test to see if returned size is based on unit (it's not) */
85     GdipGetFontSize(font, &size);
86     ok (size == 12, "Expected 12, got %f\n", size);
87     GdipDeleteFont(font);
88 
89     /* Make sure everything is converted correctly for all Units */
90     for (i = UnitWorld; i <=UnitMillimeter; i++)
91     {
92         if (i == UnitDisplay) continue; /* Crashes WindowsXP, wtf? */
93         GdipCreateFont(fontfamily, 24, FontStyleRegular, i, &font);
94         GdipGetFontSize (font, &size);
95         ok (size == 24, "Expected 24, got %f (with unit: %d)\n", size, i);
96         GdipGetFontUnit (font, &unit);
97         expect (i, unit);
98         GdipDeleteFont(font);
99     }
100 
101     GdipDeleteFontFamily(fontfamily);
102 }
103 
104 static void test_logfont(void)
105 {
106     LOGFONTA lfa, lfa2;
107     GpFont *font;
108     GpFontFamily *family;
109     GpStatus stat;
110     GpGraphics *graphics;
111     HDC hdc = GetDC(0);
112     INT style;
113     REAL rval;
114     UINT16 em_height, line_spacing;
115     Unit unit;
116 
117     GdipCreateFromHDC(hdc, &graphics);
118 
119     memset(&lfa, 0, sizeof(LOGFONTA));
120     memset(&lfa2, 0xff, sizeof(LOGFONTA));
121     lstrcpyA(lfa.lfFaceName, "Tahoma");
122 
123     stat = GdipCreateFontFromLogfontA(hdc, &lfa, &font);
124     expect(Ok, stat);
125     stat = GdipGetLogFontA(font, graphics, &lfa2);
126     expect(Ok, stat);
127 
128     ok(lfa2.lfHeight < 0, "Expected negative height\n");
129     expect(0, lfa2.lfWidth);
130     expect(0, lfa2.lfEscapement);
131     expect(0, lfa2.lfOrientation);
132     ok((lfa2.lfWeight >= 100) && (lfa2.lfWeight <= 900), "Expected weight to be set\n");
133     expect(0, lfa2.lfItalic);
134     expect(0, lfa2.lfUnderline);
135     expect(0, lfa2.lfStrikeOut);
136     ok(lfa2.lfCharSet == GetTextCharset(hdc) || lfa2.lfCharSet == ANSI_CHARSET,
137         "Expected %x or %x, got %x\n", GetTextCharset(hdc), ANSI_CHARSET, lfa2.lfCharSet);
138     expect(0, lfa2.lfOutPrecision);
139     expect(0, lfa2.lfClipPrecision);
140     expect(0, lfa2.lfQuality);
141     expect(0, lfa2.lfPitchAndFamily);
142 
143     GdipDeleteFont(font);
144 
145     memset(&lfa, 0, sizeof(LOGFONTA));
146     lfa.lfHeight = 25;
147     lfa.lfWidth = 25;
148     lfa.lfEscapement = lfa.lfOrientation = 50;
149     lfa.lfItalic = lfa.lfUnderline = lfa.lfStrikeOut = TRUE;
150 
151     memset(&lfa2, 0xff, sizeof(LOGFONTA));
152     lstrcpyA(lfa.lfFaceName, "Tahoma");
153 
154     stat = GdipCreateFontFromLogfontA(hdc, &lfa, &font);
155     expect(Ok, stat);
156     stat = GdipGetLogFontA(font, graphics, &lfa2);
157     expect(Ok, stat);
158 
159     ok(lfa2.lfHeight < 0, "Expected negative height\n");
160     expect(0, lfa2.lfWidth);
161     expect(0, lfa2.lfEscapement);
162     expect(0, lfa2.lfOrientation);
163     ok((lfa2.lfWeight >= 100) && (lfa2.lfWeight <= 900), "Expected weight to be set\n");
164     expect(TRUE, lfa2.lfItalic);
165     expect(TRUE, lfa2.lfUnderline);
166     expect(TRUE, lfa2.lfStrikeOut);
167     ok(lfa2.lfCharSet == GetTextCharset(hdc) || lfa2.lfCharSet == ANSI_CHARSET,
168         "Expected %x or %x, got %x\n", GetTextCharset(hdc), ANSI_CHARSET, lfa2.lfCharSet);
169     expect(0, lfa2.lfOutPrecision);
170     expect(0, lfa2.lfClipPrecision);
171     expect(0, lfa2.lfQuality);
172     expect(0, lfa2.lfPitchAndFamily);
173 
174     stat = GdipGetFontStyle(font, &style);
175     expect(Ok, stat);
176     ok (style == (FontStyleItalic | FontStyleUnderline | FontStyleStrikeout),
177             "Expected , got %d\n", style);
178 
179     stat = GdipGetFontUnit(font, &unit);
180     expect(Ok, stat);
181     expect(UnitWorld, unit);
182 
183     stat = GdipGetFontHeight(font, graphics, &rval);
184     expect(Ok, stat);
185     expectf(25.347656, rval);
186     stat = GdipGetFontSize(font, &rval);
187     expect(Ok, stat);
188     expectf(21.0, rval);
189 
190     stat = GdipGetFamily(font, &family);
191     expect(Ok, stat);
192     stat = GdipGetEmHeight(family, FontStyleRegular, &em_height);
193     expect(Ok, stat);
194     expect(2048, em_height);
195     stat = GdipGetLineSpacing(family, FontStyleRegular, &line_spacing);
196     expect(Ok, stat);
197     expect(2472, line_spacing);
198     GdipDeleteFontFamily(family);
199 
200     GdipDeleteFont(font);
201 
202     memset(&lfa, 0, sizeof(lfa));
203     lfa.lfHeight = -25;
204     lstrcpyA(lfa.lfFaceName, "Tahoma");
205     stat = GdipCreateFontFromLogfontA(hdc, &lfa, &font);
206     expect(Ok, stat);
207     memset(&lfa2, 0xff, sizeof(lfa2));
208     stat = GdipGetLogFontA(font, graphics, &lfa2);
209     expect(Ok, stat);
210     expect(lfa.lfHeight, lfa2.lfHeight);
211 
212     stat = GdipGetFontUnit(font, &unit);
213     expect(Ok, stat);
214     expect(UnitWorld, unit);
215 
216     stat = GdipGetFontHeight(font, graphics, &rval);
217     expect(Ok, stat);
218     expectf(30.175781, rval);
219     stat = GdipGetFontSize(font, &rval);
220     expect(Ok, stat);
221     expectf(25.0, rval);
222 
223     stat = GdipGetFamily(font, &family);
224     expect(Ok, stat);
225     stat = GdipGetEmHeight(family, FontStyleRegular, &em_height);
226     expect(Ok, stat);
227     expect(2048, em_height);
228     stat = GdipGetLineSpacing(family, FontStyleRegular, &line_spacing);
229     expect(Ok, stat);
230     expect(2472, line_spacing);
231     GdipDeleteFontFamily(family);
232 
233     GdipDeleteFont(font);
234 
235     GdipDeleteGraphics(graphics);
236     ReleaseDC(0, hdc);
237 }
238 
239 static void test_fontfamily (void)
240 {
241     GpFontFamily *family, *clonedFontFamily;
242     WCHAR itsName[LF_FACESIZE];
243     GpStatus stat;
244 
245     /* FontFamily cannot be NULL */
246     stat = GdipCreateFontFamilyFromName (Tahoma , NULL, NULL);
247     expect (InvalidParameter, stat);
248 
249     /* FontFamily must be able to actually find the family.
250      * If it can't, any subsequent calls should fail.
251      */
252     stat = GdipCreateFontFamilyFromName (nonexistent, NULL, &family);
253     expect (FontFamilyNotFound, stat);
254 
255     /* Bitmap fonts are not found */
256     stat = GdipCreateFontFamilyFromName (MSSansSerif, NULL, &family);
257     expect (FontFamilyNotFound, stat);
258     if(stat == Ok) GdipDeleteFontFamily(family);
259 
260     stat = GdipCreateFontFamilyFromName (Tahoma, NULL, &family);
261     expect (Ok, stat);
262 
263     stat = GdipGetFamilyName (family, itsName, LANG_NEUTRAL);
264     expect (Ok, stat);
265     expect (0, lstrcmpiW(itsName, Tahoma));
266 
267     if (0)
268     {
269         /* Crashes on Windows XP SP2, Vista, and so Wine as well */
270         stat = GdipGetFamilyName (family, NULL, LANG_NEUTRAL);
271         expect (Ok, stat);
272     }
273 
274     /* Make sure we don't read old data */
275     ZeroMemory (itsName, sizeof(itsName));
276     stat = GdipCloneFontFamily(family, &clonedFontFamily);
277     expect (Ok, stat);
278     GdipDeleteFontFamily(family);
279     stat = GdipGetFamilyName(clonedFontFamily, itsName, LANG_NEUTRAL);
280     expect(Ok, stat);
281     expect(0, lstrcmpiW(itsName, Tahoma));
282 
283     GdipDeleteFontFamily(clonedFontFamily);
284 }
285 
286 static void test_fontfamily_properties (void)
287 {
288     GpFontFamily* FontFamily = NULL;
289     GpStatus stat;
290     UINT16 result = 0;
291 
292     stat = GdipCreateFontFamilyFromName(Tahoma, NULL, &FontFamily);
293     expect(Ok, stat);
294 
295     stat = GdipGetLineSpacing(FontFamily, FontStyleRegular, &result);
296     expect(Ok, stat);
297     ok (result == 2472, "Expected 2472, got %d\n", result);
298     result = 0;
299     stat = GdipGetEmHeight(FontFamily, FontStyleRegular, &result);
300     expect(Ok, stat);
301     ok(result == 2048, "Expected 2048, got %d\n", result);
302     result = 0;
303     stat = GdipGetCellAscent(FontFamily, FontStyleRegular, &result);
304     expect(Ok, stat);
305     ok(result == 2049, "Expected 2049, got %d\n", result);
306     result = 0;
307     stat = GdipGetCellDescent(FontFamily, FontStyleRegular, &result);
308     expect(Ok, stat);
309     ok(result == 423, "Expected 423, got %d\n", result);
310     GdipDeleteFontFamily(FontFamily);
311 
312     stat = GdipCreateFontFamilyFromName(TimesNewRoman, NULL, &FontFamily);
313     if(stat == FontFamilyNotFound)
314         skip("Times New Roman not installed\n");
315     else
316     {
317         result = 0;
318         stat = GdipGetLineSpacing(FontFamily, FontStyleRegular, &result);
319         expect(Ok, stat);
320         ok(result == 2355, "Expected 2355, got %d\n", result);
321         result = 0;
322         stat = GdipGetEmHeight(FontFamily, FontStyleRegular, &result);
323         expect(Ok, stat);
324         ok(result == 2048, "Expected 2048, got %d\n", result);
325         result = 0;
326         stat = GdipGetCellAscent(FontFamily, FontStyleRegular, &result);
327         expect(Ok, stat);
328         ok(result == 1825, "Expected 1825, got %d\n", result);
329         result = 0;
330         stat = GdipGetCellDescent(FontFamily, FontStyleRegular, &result);
331         expect(Ok, stat);
332         ok(result == 443, "Expected 443 got %d\n", result);
333         GdipDeleteFontFamily(FontFamily);
334     }
335 }
336 
337 static void check_family(const char* context, GpFontFamily *family, WCHAR *name)
338 {
339     GpStatus stat;
340     GpFont* font;
341 
342     *name = 0;
343     stat = GdipGetFamilyName(family, name, LANG_NEUTRAL);
344     ok(stat == Ok, "could not get the %s family name: %.8x\n", context, stat);
345 
346     stat = GdipCreateFont(family, 12, FontStyleRegular, UnitPixel, &font);
347     ok(stat == Ok, "could not create a font for the %s family: %.8x\n", context, stat);
348     if (stat == Ok)
349     {
350         stat = GdipDeleteFont(font);
351         ok(stat == Ok, "could not delete the %s family font: %.8x\n", context, stat);
352     }
353 
354     stat = GdipDeleteFontFamily(family);
355     ok(stat == Ok, "could not delete the %s family: %.8x\n", context, stat);
356 }
357 
358 static void test_getgenerics (void)
359 {
360     GpStatus stat;
361     GpFontFamily *family;
362     WCHAR sansname[LF_FACESIZE], serifname[LF_FACESIZE], mononame[LF_FACESIZE];
363     int missingfonts = 0;
364 
365     stat = GdipGetGenericFontFamilySansSerif(&family);
366     expect (Ok, stat);
367     if (stat == FontFamilyNotFound)
368         missingfonts = 1;
369     else
370         check_family("Sans Serif", family, sansname);
371 
372     stat = GdipGetGenericFontFamilySerif(&family);
373     expect (Ok, stat);
374     if (stat == FontFamilyNotFound)
375         missingfonts = 1;
376     else
377         check_family("Serif", family, serifname);
378 
379     stat = GdipGetGenericFontFamilyMonospace(&family);
380     expect (Ok, stat);
381     if (stat == FontFamilyNotFound)
382         missingfonts = 1;
383     else
384         check_family("Monospace", family, mononame);
385 
386     if (missingfonts && strcmp(winetest_platform, "wine") == 0)
387         trace("You may need to install either the Microsoft Web Fonts or the Liberation Fonts\n");
388 
389     /* Check that the family names are all different */
390     ok(lstrcmpiW(sansname, serifname) != 0, "Sans Serif and Serif families should be different: %s\n", wine_dbgstr_w(sansname));
391     ok(lstrcmpiW(sansname, mononame) != 0, "Sans Serif and Monospace families should be different: %s\n", wine_dbgstr_w(sansname));
392     ok(lstrcmpiW(serifname, mononame) != 0, "Serif and Monospace families should be different: %s\n", wine_dbgstr_w(serifname));
393 }
394 
395 static void test_installedfonts (void)
396 {
397     GpStatus stat;
398     GpFontCollection* collection=NULL;
399 
400     stat = GdipNewInstalledFontCollection(NULL);
401     expect (InvalidParameter, stat);
402 
403     stat = GdipNewInstalledFontCollection(&collection);
404     expect (Ok, stat);
405     ok (collection != NULL, "got NULL font collection\n");
406 }
407 
408 static void test_heightgivendpi(void)
409 {
410     GpStatus stat;
411     GpFont* font = NULL;
412     GpFontFamily* fontfamily = NULL;
413     REAL height;
414     Unit unit;
415 
416     stat = GdipCreateFontFamilyFromName(Tahoma, NULL, &fontfamily);
417     expect(Ok, stat);
418 
419     stat = GdipCreateFont(fontfamily, 30, FontStyleRegular, UnitPixel, &font);
420     expect(Ok, stat);
421 
422     stat = GdipGetFontHeightGivenDPI(NULL, 96, &height);
423     expect(InvalidParameter, stat);
424 
425     stat = GdipGetFontHeightGivenDPI(font, 96, NULL);
426     expect(InvalidParameter, stat);
427 
428     stat = GdipGetFontHeightGivenDPI(font, 96, &height);
429     expect(Ok, stat);
430     expectf(36.210938, height);
431     GdipDeleteFont(font);
432 
433     height = 12345;
434     stat = GdipCreateFont(fontfamily, 30, FontStyleRegular, UnitWorld, &font);
435     expect(Ok, stat);
436 
437     stat = GdipGetFontUnit(font, &unit);
438     expect(Ok, stat);
439     expect(UnitWorld, unit);
440 
441     stat = GdipGetFontHeightGivenDPI(font, 96, &height);
442     expect(Ok, stat);
443     expectf(36.210938, height);
444     GdipDeleteFont(font);
445 
446     height = 12345;
447     stat = GdipCreateFont(fontfamily, 30, FontStyleRegular, UnitPoint, &font);
448     expect(Ok, stat);
449     stat = GdipGetFontHeightGivenDPI(font, 96, &height);
450     expect(Ok, stat);
451     expectf(48.281250, height);
452     GdipDeleteFont(font);
453 
454     height = 12345;
455     stat = GdipCreateFont(fontfamily, 30, FontStyleRegular, UnitInch, &font);
456     expect(Ok, stat);
457 
458     stat = GdipGetFontUnit(font, &unit);
459     expect(Ok, stat);
460     expect(UnitInch, unit);
461 
462     stat = GdipGetFontHeightGivenDPI(font, 96, &height);
463     expect(Ok, stat);
464     expectf(3476.250000, height);
465     GdipDeleteFont(font);
466 
467     height = 12345;
468     stat = GdipCreateFont(fontfamily, 30, FontStyleRegular, UnitDocument, &font);
469     expect(Ok, stat);
470 
471     stat = GdipGetFontUnit(font, &unit);
472     expect(Ok, stat);
473     expect(UnitDocument, unit);
474 
475     stat = GdipGetFontHeightGivenDPI(font, 96, &height);
476     expect(Ok, stat);
477     expectf(11.587500, height);
478     GdipDeleteFont(font);
479 
480     height = 12345;
481     stat = GdipCreateFont(fontfamily, 30, FontStyleRegular, UnitMillimeter, &font);
482     expect(Ok, stat);
483 
484     stat = GdipGetFontUnit(font, &unit);
485     expect(Ok, stat);
486     expect(UnitMillimeter, unit);
487 
488     stat = GdipGetFontHeightGivenDPI(font, 96, &height);
489     expect(Ok, stat);
490     expectf(136.860245, height);
491     GdipDeleteFont(font);
492 
493     GdipDeleteFontFamily(fontfamily);
494 }
495 
496 static int CALLBACK font_enum_proc(const LOGFONTW *lfe, const TEXTMETRICW *ntme,
497                                    DWORD type, LPARAM lparam)
498 {
499     NEWTEXTMETRICW *ntm = (NEWTEXTMETRICW *)lparam;
500 
501     if (type != TRUETYPE_FONTTYPE) return 1;
502 
503     *ntm = *(NEWTEXTMETRICW *)ntme;
504     return 0;
505 }
506 
507 struct font_metrics
508 {
509     UINT16 em_height, line_spacing, ascent, descent;
510     REAL font_height, font_size;
511     INT lfHeight;
512 };
513 
514 static void gdi_get_font_metrics(LOGFONTW *lf, struct font_metrics *fm)
515 {
516     HDC hdc;
517     HFONT hfont;
518     NEWTEXTMETRICW ntm;
519     OUTLINETEXTMETRICW otm;
520     int ret;
521 
522     hdc = CreateCompatibleDC(0);
523 
524     /* it's the only way to get extended NEWTEXTMETRIC fields */
525     ret = EnumFontFamiliesExW(hdc, lf, font_enum_proc, (LPARAM)&ntm, 0);
526     ok(!ret, "EnumFontFamiliesExW failed to find %s\n", wine_dbgstr_w(lf->lfFaceName));
527 
528     hfont = CreateFontIndirectW(lf);
529     SelectObject(hdc, hfont);
530 
531     otm.otmSize = sizeof(otm);
532     ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
533     ok(ret, "GetOutlineTextMetrics failed\n");
534 
535     DeleteDC(hdc);
536     DeleteObject(hfont);
537 
538     fm->lfHeight = -otm.otmTextMetrics.tmAscent;
539     fm->line_spacing = ntm.ntmCellHeight;
540     fm->font_size = (REAL)otm.otmTextMetrics.tmAscent;
541     fm->font_height = (REAL)fm->line_spacing * fm->font_size / (REAL)ntm.ntmSizeEM;
542     fm->em_height = ntm.ntmSizeEM;
543     fm->ascent = ntm.ntmSizeEM;
544     fm->descent = ntm.ntmCellHeight - ntm.ntmSizeEM;
545 }
546 
547 static void gdip_get_font_metrics(GpFont *font, struct font_metrics *fm)
548 {
549     INT style;
550     GpFontFamily *family;
551     GpStatus stat;
552 
553     stat = GdipGetFontStyle(font, &style);
554     expect(Ok, stat);
555 
556     stat = GdipGetFontHeight(NULL, NULL, &fm->font_height);
557     expect(InvalidParameter, stat);
558 
559     stat = GdipGetFontHeight(font, NULL, NULL);
560     expect(InvalidParameter, stat);
561 
562     stat = GdipGetFontHeight(font, NULL, &fm->font_height);
563     expect(Ok, stat);
564     stat = GdipGetFontSize(font, &fm->font_size);
565     expect(Ok, stat);
566 
567     fm->lfHeight = (INT)(fm->font_size * -1.0);
568 
569     stat = GdipGetFamily(font, &family);
570     expect(Ok, stat);
571 
572     stat = GdipGetEmHeight(family, style, &fm->em_height);
573     expect(Ok, stat);
574     stat = GdipGetLineSpacing(family, style, &fm->line_spacing);
575     expect(Ok, stat);
576     stat = GdipGetCellAscent(family, style, &fm->ascent);
577     expect(Ok, stat);
578     stat = GdipGetCellDescent(family, style, &fm->descent);
579     expect(Ok, stat);
580 
581     GdipDeleteFontFamily(family);
582 }
583 
584 static void cmp_font_metrics(struct font_metrics *fm1, struct font_metrics *fm2, int line)
585 {
586     ok_(__FILE__, line)(fm1->lfHeight == fm2->lfHeight, "lfHeight %d != %d\n", fm1->lfHeight, fm2->lfHeight);
587     ok_(__FILE__, line)(fm1->em_height == fm2->em_height, "em_height %u != %u\n", fm1->em_height, fm2->em_height);
588     ok_(__FILE__, line)(fm1->line_spacing == fm2->line_spacing, "line_spacing %u != %u\n", fm1->line_spacing, fm2->line_spacing);
589     ok_(__FILE__, line)(abs(fm1->ascent - fm2->ascent) <= 1, "ascent %u != %u\n", fm1->ascent, fm2->ascent);
590     ok_(__FILE__, line)(abs(fm1->descent - fm2->descent) <= 1, "descent %u != %u\n", fm1->descent, fm2->descent);
591     ok(fm1->font_height > 0.0, "fm1->font_height should be positive, got %f\n", fm1->font_height);
592     ok(fm2->font_height > 0.0, "fm2->font_height should be positive, got %f\n", fm2->font_height);
593     ok_(__FILE__, line)(fm1->font_height == fm2->font_height, "font_height %f != %f\n", fm1->font_height, fm2->font_height);
594     ok(fm1->font_size > 0.0, "fm1->font_size should be positive, got %f\n", fm1->font_size);
595     ok(fm2->font_size > 0.0, "fm2->font_size should be positive, got %f\n", fm2->font_size);
596     ok_(__FILE__, line)(fm1->font_size == fm2->font_size, "font_size %f != %f\n", fm1->font_size, fm2->font_size);
597 }
598 
599 static void test_font_metrics(void)
600 {
601     LOGFONTW lf;
602     GpFont *font;
603     GpFontFamily *family;
604     GpGraphics *graphics;
605     GpStatus stat;
606     Unit unit;
607     struct font_metrics fm_gdi, fm_gdip;
608     HDC hdc;
609 
610     hdc = CreateCompatibleDC(0);
611     stat = GdipCreateFromHDC(hdc, &graphics);
612     expect(Ok, stat);
613 
614     memset(&lf, 0, sizeof(lf));
615 
616     /* Tahoma,-13 */
617     lstrcpyW(lf.lfFaceName, Tahoma);
618     lf.lfHeight = -13;
619     stat = GdipCreateFontFromLogfontW(hdc, &lf, &font);
620     expect(Ok, stat);
621 
622     stat = GdipGetFontUnit(font, &unit);
623     expect(Ok, stat);
624     expect(UnitWorld, unit);
625 
626     gdip_get_font_metrics(font, &fm_gdip);
627     trace("gdiplus:\n");
628     trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
629           wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
630           fm_gdip.em_height, fm_gdip.line_spacing, fm_gdip.ascent, fm_gdip.descent,
631           fm_gdip.font_height, fm_gdip.font_size);
632 
633     gdi_get_font_metrics(&lf, &fm_gdi);
634     trace("gdi:\n");
635     trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
636           wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
637           fm_gdi.em_height, fm_gdi.line_spacing, fm_gdi.ascent, fm_gdi.descent,
638           fm_gdi.font_height, fm_gdi.font_size);
639 
640     cmp_font_metrics(&fm_gdip, &fm_gdi, __LINE__);
641 
642     stat = GdipGetLogFontW(font, graphics, &lf);
643     expect(Ok, stat);
644     ok(lf.lfHeight < 0, "lf.lfHeight should be negative, got %d\n", lf.lfHeight);
645     gdi_get_font_metrics(&lf, &fm_gdi);
646     trace("gdi:\n");
647     trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
648           wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
649           fm_gdi.em_height, fm_gdi.line_spacing, fm_gdi.ascent, fm_gdi.descent,
650           fm_gdi.font_height, fm_gdi.font_size);
651     ok((REAL)lf.lfHeight * -1.0 == fm_gdi.font_size, "expected %f, got %f\n", (REAL)lf.lfHeight * -1.0, fm_gdi.font_size);
652 
653     cmp_font_metrics(&fm_gdip, &fm_gdi, __LINE__);
654 
655     GdipDeleteFont(font);
656 
657     /* Tahoma,13 */
658     lstrcpyW(lf.lfFaceName, Tahoma);
659     lf.lfHeight = 13;
660     stat = GdipCreateFontFromLogfontW(hdc, &lf, &font);
661     expect(Ok, stat);
662 
663     stat = GdipGetFontUnit(font, &unit);
664     expect(Ok, stat);
665     expect(UnitWorld, unit);
666 
667     gdip_get_font_metrics(font, &fm_gdip);
668     trace("gdiplus:\n");
669     trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
670           wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
671           fm_gdip.em_height, fm_gdip.line_spacing, fm_gdip.ascent, fm_gdip.descent,
672           fm_gdip.font_height, fm_gdip.font_size);
673 
674     gdi_get_font_metrics(&lf, &fm_gdi);
675     trace("gdi:\n");
676     trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
677           wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
678           fm_gdi.em_height, fm_gdi.line_spacing, fm_gdi.ascent, fm_gdi.descent,
679           fm_gdi.font_height, fm_gdi.font_size);
680 
681     cmp_font_metrics(&fm_gdip, &fm_gdi, __LINE__);
682 
683     stat = GdipGetLogFontW(font, graphics, &lf);
684     expect(Ok, stat);
685     ok(lf.lfHeight < 0, "lf.lfHeight should be negative, got %d\n", lf.lfHeight);
686     gdi_get_font_metrics(&lf, &fm_gdi);
687     trace("gdi:\n");
688     trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
689           wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
690           fm_gdi.em_height, fm_gdi.line_spacing, fm_gdi.ascent, fm_gdi.descent,
691           fm_gdi.font_height, fm_gdi.font_size);
692     ok((REAL)lf.lfHeight * -1.0 == fm_gdi.font_size, "expected %f, got %f\n", (REAL)lf.lfHeight * -1.0, fm_gdi.font_size);
693 
694     cmp_font_metrics(&fm_gdip, &fm_gdi, __LINE__);
695 
696     GdipDeleteFont(font);
697 
698     stat = GdipCreateFontFamilyFromName(Tahoma, NULL, &family);
699     expect(Ok, stat);
700 
701     /* Tahoma,13 */
702     stat = GdipCreateFont(family, 13.0, FontStyleRegular, UnitPixel, &font);
703     expect(Ok, stat);
704 
705     gdip_get_font_metrics(font, &fm_gdip);
706     trace("gdiplus:\n");
707     trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
708           wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
709           fm_gdip.em_height, fm_gdip.line_spacing, fm_gdip.ascent, fm_gdip.descent,
710           fm_gdip.font_height, fm_gdip.font_size);
711 
712     stat = GdipGetLogFontW(font, graphics, &lf);
713     expect(Ok, stat);
714     ok(lf.lfHeight < 0, "lf.lfHeight should be negative, got %d\n", lf.lfHeight);
715     gdi_get_font_metrics(&lf, &fm_gdi);
716     trace("gdi:\n");
717     trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
718           wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
719           fm_gdi.em_height, fm_gdi.line_spacing, fm_gdi.ascent, fm_gdi.descent,
720           fm_gdi.font_height, fm_gdi.font_size);
721     ok((REAL)lf.lfHeight * -1.0 == fm_gdi.font_size, "expected %f, got %f\n", (REAL)lf.lfHeight * -1.0, fm_gdi.font_size);
722 
723     cmp_font_metrics(&fm_gdip, &fm_gdi, __LINE__);
724 
725     stat = GdipGetLogFontW(font, NULL, &lf);
726     expect(InvalidParameter, stat);
727 
728     GdipDeleteFont(font);
729 
730     stat = GdipCreateFont(family, -13.0, FontStyleRegular, UnitPixel, &font);
731     expect(InvalidParameter, stat);
732 
733     GdipDeleteFontFamily(family);
734 
735     GdipDeleteGraphics(graphics);
736     DeleteDC(hdc);
737 }
738 
739 static void test_font_substitution(void)
740 {
741     WCHAR ms_shell_dlg[LF_FACESIZE];
742     char fallback_font[LF_FACESIZE];
743     HDC hdc;
744     HFONT hfont;
745     LOGFONTA lf;
746     GpStatus status;
747     GpGraphics *graphics;
748     GpFont *font;
749     GpFontFamily *family;
750     int ret;
751 
752     hdc = CreateCompatibleDC(0);
753     status = GdipCreateFromHDC(hdc, &graphics);
754     expect(Ok, status);
755 
756     hfont = GetStockObject(DEFAULT_GUI_FONT);
757     ok(hfont != 0, "GetStockObject(DEFAULT_GUI_FONT) failed\n");
758 
759     memset(&lf, 0xfe, sizeof(lf));
760     ret = GetObjectA(hfont, sizeof(lf), &lf);
761     ok(ret == sizeof(lf), "GetObject failed\n");
762     ok(!lstrcmpA(lf.lfFaceName, "MS Shell Dlg"), "wrong face name %s\n", lf.lfFaceName);
763     MultiByteToWideChar(CP_ACP, 0, lf.lfFaceName, -1, ms_shell_dlg, LF_FACESIZE);
764 
765     status = GdipCreateFontFromLogfontA(hdc, &lf, &font);
766     expect(Ok, status);
767     memset(&lf, 0xfe, sizeof(lf));
768     status = GdipGetLogFontA(font, graphics, &lf);
769     expect(Ok, status);
770     ok(!lstrcmpA(lf.lfFaceName, "Microsoft Sans Serif") ||
771        !lstrcmpA(lf.lfFaceName, "Tahoma"), "wrong face name %s\n", lf.lfFaceName);
772     GdipDeleteFont(font);
773 
774     status = GdipCreateFontFamilyFromName(ms_shell_dlg, NULL, &family);
775     expect(Ok, status);
776     status = GdipCreateFont(family, 12, FontStyleRegular, UnitPoint, &font);
777     expect(Ok, status);
778     memset(&lf, 0xfe, sizeof(lf));
779     status = GdipGetLogFontA(font, graphics, &lf);
780     expect(Ok, status);
781     ok(!lstrcmpA(lf.lfFaceName, "Microsoft Sans Serif") ||
782        !lstrcmpA(lf.lfFaceName, "Tahoma"), "wrong face name %s\n", lf.lfFaceName);
783     GdipDeleteFont(font);
784     GdipDeleteFontFamily(family);
785 
786     status = GdipCreateFontFamilyFromName(nonexistent, NULL, &family);
787     ok(status == FontFamilyNotFound, "expected FontFamilyNotFound, got %d\n", status);
788 
789     /* nonexistent fonts fallback to Arial, or something else if it's missing */
790     strcpy(lf.lfFaceName,"Arial");
791     status = GdipCreateFontFromLogfontA(hdc, &lf, &font);
792     expect(Ok, status);
793     status = GdipGetLogFontA(font, graphics, &lf);
794     expect(Ok, status);
795     strcpy(fallback_font,lf.lfFaceName);
796     trace("fallback font %s\n", fallback_font);
797     GdipDeleteFont(font);
798 
799     lstrcpyA(lf.lfFaceName, "ThisFontShouldNotExist");
800     status = GdipCreateFontFromLogfontA(hdc, &lf, &font);
801     expect(Ok, status);
802     memset(&lf, 0xfe, sizeof(lf));
803     status = GdipGetLogFontA(font, graphics, &lf);
804     expect(Ok, status);
805     ok(!lstrcmpA(lf.lfFaceName, fallback_font), "wrong face name %s / %s\n", lf.lfFaceName, fallback_font);
806     GdipDeleteFont(font);
807 
808     /* empty FaceName */
809     lf.lfFaceName[0] = 0;
810     status = GdipCreateFontFromLogfontA(hdc, &lf, &font);
811     expect(Ok, status);
812     memset(&lf, 0xfe, sizeof(lf));
813     status = GdipGetLogFontA(font, graphics, &lf);
814     expect(Ok, status);
815     ok(!lstrcmpA(lf.lfFaceName, fallback_font), "wrong face name %s / %s\n", lf.lfFaceName, fallback_font);
816     GdipDeleteFont(font);
817 
818     /* zeroing out lfWeight and lfCharSet leads to font creation failure */
819     lf.lfWeight = 0;
820     lf.lfCharSet = 0;
821     lstrcpyA(lf.lfFaceName, "ThisFontShouldNotExist");
822     font = NULL;
823     status = GdipCreateFontFromLogfontA(hdc, &lf, &font);
824 todo_wine
825     ok(status == NotTrueTypeFont || broken(status == FileNotFound), /* before XP */
826        "expected NotTrueTypeFont, got %d\n", status);
827     /* FIXME: remove when wine is fixed */
828     if (font) GdipDeleteFont(font);
829 
830     /* empty FaceName */
831     lf.lfFaceName[0] = 0;
832     font = NULL;
833     status = GdipCreateFontFromLogfontA(hdc, &lf, &font);
834 todo_wine
835     ok(status == NotTrueTypeFont || broken(status == FileNotFound), /* before XP */
836        "expected NotTrueTypeFont, got %d\n", status);
837     /* FIXME: remove when wine is fixed */
838     if (font) GdipDeleteFont(font);
839 
840     GdipDeleteGraphics(graphics);
841     DeleteDC(hdc);
842 }
843 
844 static void test_font_transform(void)
845 {
846     static const WCHAR string[] = { 'A',0 };
847     GpStatus status;
848     HDC hdc;
849     LOGFONTA lf;
850     GpFont *font;
851     GpGraphics *graphics;
852     GpMatrix *matrix;
853     GpStringFormat *format, *typographic;
854     PointF pos[1] = { { 0,0 } };
855     REAL height, margin_y;
856     RectF bounds, rect;
857 
858     hdc = CreateCompatibleDC(0);
859     status = GdipCreateFromHDC(hdc, &graphics);
860     expect(Ok, status);
861 
862     status = GdipSetPageUnit(graphics, UnitPixel);
863     expect(Ok, status);
864 
865     status = GdipCreateStringFormat(0, LANG_NEUTRAL, &format);
866     expect(Ok, status);
867     status = GdipStringFormatGetGenericTypographic(&typographic);
868     expect(Ok, status);
869 
870     memset(&lf, 0, sizeof(lf));
871     lstrcpyA(lf.lfFaceName, "Tahoma");
872     lf.lfHeight = -100;
873     lf.lfWidth = 100;
874     status = GdipCreateFontFromLogfontA(hdc, &lf, &font);
875     expect(Ok, status);
876 
877     margin_y = 100.0 / 8.0;
878 
879     /* identity matrix */
880     status = GdipCreateMatrix(&matrix);
881     expect(Ok, status);
882     status = GdipSetWorldTransform(graphics, matrix);
883     expect(Ok, status);
884     status = GdipGetLogFontA(font, graphics, &lf);
885     expect(Ok, status);
886     expect(-100, lf.lfHeight);
887     expect(0, lf.lfWidth);
888     expect(0, lf.lfEscapement);
889     expect(0, lf.lfOrientation);
890     status = GdipGetFontHeight(font, graphics, &height);
891     expect(Ok, status);
892     expectf(120.703125, height);
893     set_rect_empty(&rect);
894     set_rect_empty(&bounds);
895     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, NULL, NULL);
896     expect(Ok, status);
897     expectf(0.0, bounds.X);
898     expectf(0.0, bounds.Y);
899 todo_wine
900     expectf(height + margin_y, bounds.Height);
901     set_rect_empty(&rect);
902     set_rect_empty(&bounds);
903     status = GdipMeasureString(graphics, string, -1, font, &rect, typographic, &bounds, NULL, NULL);
904     expect(Ok, status);
905     expectf(0.0, bounds.X);
906     expectf(0.0, bounds.Y);
907     expectf_(height, bounds.Height, 1.0);
908     set_rect_empty(&bounds);
909     status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos,
910                                      DriverStringOptionsCmapLookup, NULL, &bounds);
911     expect(Ok, status);
912     expectf(0.0, bounds.X);
913     expectf_(-100.0, bounds.Y, 0.05);
914     expectf_(height, bounds.Height, 0.5);
915     set_rect_empty(&bounds);
916     status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos,
917                                      DriverStringOptionsCmapLookup, matrix, &bounds);
918     expect(Ok, status);
919     expectf(0.0, bounds.X);
920     expectf_(-100.0, bounds.Y, 0.05);
921     expectf_(height, bounds.Height, 0.5);
922 
923     /* scale matrix */
924     status = GdipScaleMatrix(matrix, 2.0, 3.0, MatrixOrderAppend);
925     expect(Ok, status);
926     status = GdipSetWorldTransform(graphics, matrix);
927     expect(Ok, status);
928     status = GdipGetLogFontA(font, graphics, &lf);
929     expect(Ok, status);
930     expect(-300, lf.lfHeight);
931     expect(0, lf.lfWidth);
932     expect(0, lf.lfEscapement);
933     expect(0, lf.lfOrientation);
934     status = GdipGetFontHeight(font, graphics, &height);
935     expect(Ok, status);
936     expectf(120.703125, height);
937     set_rect_empty(&rect);
938     set_rect_empty(&bounds);
939     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, NULL, NULL);
940     expect(Ok, status);
941     expectf(0.0, bounds.X);
942     expectf(0.0, bounds.Y);
943 todo_wine
944     expectf(height + margin_y, bounds.Height);
945     set_rect_empty(&rect);
946     set_rect_empty(&bounds);
947     status = GdipMeasureString(graphics, string, -1, font, &rect, typographic, &bounds, NULL, NULL);
948     expect(Ok, status);
949     expectf(0.0, bounds.X);
950     expectf(0.0, bounds.Y);
951     expectf_(height, bounds.Height, 0.05);
952     set_rect_empty(&bounds);
953     status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos,
954                                      DriverStringOptionsCmapLookup, NULL, &bounds);
955     expect(Ok, status);
956     expectf(0.0, bounds.X);
957     expectf_(-100.0, bounds.Y, 0.05);
958     expectf_(height, bounds.Height, 0.2);
959     set_rect_empty(&bounds);
960     status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos,
961                                      DriverStringOptionsCmapLookup, matrix, &bounds);
962     expect(Ok, status);
963     expectf(0.0, bounds.X);
964 todo_wine
965     expectf_(-300.0, bounds.Y, 0.15);
966 todo_wine
967     expectf(height * 3.0, bounds.Height);
968 
969     /* scale + ratate matrix */
970     status = GdipRotateMatrix(matrix, 45.0, MatrixOrderAppend);
971     expect(Ok, status);
972     status = GdipSetWorldTransform(graphics, matrix);
973     expect(Ok, status);
974     status = GdipGetLogFontA(font, graphics, &lf);
975     expect(Ok, status);
976     expect(-300, lf.lfHeight);
977     expect(0, lf.lfWidth);
978     expect_(3151, lf.lfEscapement, 1);
979     expect_(3151, lf.lfOrientation, 1);
980     status = GdipGetFontHeight(font, graphics, &height);
981     expect(Ok, status);
982     expectf(120.703125, height);
983     set_rect_empty(&rect);
984     set_rect_empty(&bounds);
985     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, NULL, NULL);
986     expect(Ok, status);
987     expectf(0.0, bounds.X);
988     expectf(0.0, bounds.Y);
989 todo_wine
990     expectf(height + margin_y, bounds.Height);
991     set_rect_empty(&rect);
992     set_rect_empty(&bounds);
993     status = GdipMeasureString(graphics, string, -1, font, &rect, typographic, &bounds, NULL, NULL);
994     expect(Ok, status);
995     expectf(0.0, bounds.X);
996     expectf(0.0, bounds.Y);
997     expectf_(height, bounds.Height, 0.05);
998     set_rect_empty(&bounds);
999     status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos,
1000                                      DriverStringOptionsCmapLookup, NULL, &bounds);
1001     expect(Ok, status);
1002     expectf(0.0, bounds.X);
1003     expectf_(-100.0, bounds.Y, 0.05);
1004     expectf_(height, bounds.Height, 0.2);
1005     set_rect_empty(&bounds);
1006     status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos,
1007                                      DriverStringOptionsCmapLookup, matrix, &bounds);
1008     expect(Ok, status);
1009 todo_wine
1010     expectf_(-43.814377, bounds.X, 0.05);
1011 todo_wine
1012     expectf_(-212.235611, bounds.Y, 0.05);
1013 todo_wine
1014     expectf_(340.847534, bounds.Height, 0.05);
1015 
1016     /* scale + ratate + shear matrix */
1017     status = GdipShearMatrix(matrix, 4.0, 5.0, MatrixOrderAppend);
1018     expect(Ok, status);
1019     status = GdipSetWorldTransform(graphics, matrix);
1020     expect(Ok, status);
1021     status = GdipGetLogFontA(font, graphics, &lf);
1022     expect(Ok, status);
1023 todo_wine
1024     expect(1032, lf.lfHeight);
1025     expect(0, lf.lfWidth);
1026     expect_(3099, lf.lfEscapement, 1);
1027     expect_(3099, lf.lfOrientation, 1);
1028     status = GdipGetFontHeight(font, graphics, &height);
1029     expect(Ok, status);
1030     expectf(120.703125, height);
1031     set_rect_empty(&rect);
1032     set_rect_empty(&bounds);
1033     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, NULL, NULL);
1034     expect(Ok, status);
1035     expectf(0.0, bounds.X);
1036     expectf(0.0, bounds.Y);
1037 todo_wine
1038     expectf(height + margin_y, bounds.Height);
1039     set_rect_empty(&rect);
1040     set_rect_empty(&bounds);
1041     status = GdipMeasureString(graphics, string, -1, font, &rect, typographic, &bounds, NULL, NULL);
1042     expect(Ok, status);
1043     expectf(0.0, bounds.X);
1044     expectf(0.0, bounds.Y);
1045     expectf_(height, bounds.Height, 0.2);
1046     set_rect_empty(&bounds);
1047     status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos,
1048                                      DriverStringOptionsCmapLookup, NULL, &bounds);
1049     expect(Ok, status);
1050     expectf(0.0, bounds.X);
1051     expectf_(-100.0, bounds.Y, 0.2);
1052     expectf_(height, bounds.Height, 0.2);
1053     set_rect_empty(&bounds);
1054     status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos,
1055                                      DriverStringOptionsCmapLookup, matrix, &bounds);
1056     expect(Ok, status);
1057 todo_wine
1058     expectf_(-636.706848, bounds.X, 0.05);
1059 todo_wine
1060     expectf_(-175.257523, bounds.Y, 0.05);
1061 todo_wine
1062     expectf_(1532.984985, bounds.Height, 0.05);
1063 
1064     /* scale + ratate + shear + translate matrix */
1065     status = GdipTranslateMatrix(matrix, 10.0, 20.0, MatrixOrderAppend);
1066     expect(Ok, status);
1067     status = GdipSetWorldTransform(graphics, matrix);
1068     expect(Ok, status);
1069     status = GdipGetLogFontA(font, graphics, &lf);
1070     expect(Ok, status);
1071 todo_wine
1072     expect(1032, lf.lfHeight);
1073     expect(0, lf.lfWidth);
1074     expect_(3099, lf.lfEscapement, 1);
1075     expect_(3099, lf.lfOrientation, 1);
1076     status = GdipGetFontHeight(font, graphics, &height);
1077     expect(Ok, status);
1078     expectf(120.703125, height);
1079     set_rect_empty(&rect);
1080     set_rect_empty(&bounds);
1081     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, NULL, NULL);
1082     expect(Ok, status);
1083     expectf(0.0, bounds.X);
1084     expectf(0.0, bounds.Y);
1085 todo_wine
1086     expectf(height + margin_y, bounds.Height);
1087     set_rect_empty(&rect);
1088     set_rect_empty(&bounds);
1089     status = GdipMeasureString(graphics, string, -1, font, &rect, typographic, &bounds, NULL, NULL);
1090     expect(Ok, status);
1091     expectf(0.0, bounds.X);
1092     expectf(0.0, bounds.Y);
1093     expectf_(height, bounds.Height, 0.1);
1094     set_rect_empty(&bounds);
1095     status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos,
1096                                      DriverStringOptionsCmapLookup, NULL, &bounds);
1097     expect(Ok, status);
1098     expectf(0.0, bounds.X);
1099     expectf_(-100.0, bounds.Y, 0.2);
1100     expectf_(height, bounds.Height, 0.2);
1101     set_rect_empty(&bounds);
1102     status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos,
1103                                      DriverStringOptionsCmapLookup, matrix, &bounds);
1104     expect(Ok, status);
1105 todo_wine
1106     expectf_(-626.706848, bounds.X, 0.05);
1107 todo_wine
1108     expectf_(-155.257523, bounds.Y, 0.05);
1109 todo_wine
1110     expectf_(1532.984985, bounds.Height, 0.05);
1111 
1112     GdipDeleteMatrix(matrix);
1113     GdipDeleteFont(font);
1114     GdipDeleteGraphics(graphics);
1115     GdipDeleteStringFormat(typographic);
1116     GdipDeleteStringFormat(format);
1117     DeleteDC(hdc);
1118 }
1119 
1120 START_TEST(font)
1121 {
1122     struct GdiplusStartupInput gdiplusStartupInput;
1123     ULONG_PTR gdiplusToken;
1124     HMODULE hmsvcrt;
1125     int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
1126 
1127     /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
1128     hmsvcrt = LoadLibraryA("msvcrt");
1129     _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
1130     if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
1131 
1132     gdiplusStartupInput.GdiplusVersion              = 1;
1133     gdiplusStartupInput.DebugEventCallback          = NULL;
1134     gdiplusStartupInput.SuppressBackgroundThread    = 0;
1135     gdiplusStartupInput.SuppressExternalCodecs      = 0;
1136 
1137     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
1138 
1139     test_font_transform();
1140     if (!winetest_interactive)
1141         skip("ROSTESTS-154: Skipping test_font_substitution because of improper error handling\n");
1142     else
1143         test_font_substitution();
1144     test_font_metrics();
1145     test_createfont();
1146     test_logfont();
1147     test_fontfamily();
1148     test_fontfamily_properties();
1149     test_getgenerics();
1150     test_installedfonts();
1151     test_heightgivendpi();
1152 
1153     GdiplusShutdown(gdiplusToken);
1154 }
1155