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