jscript: Get rid of BSTR in date.c.
[wine] / dlls / gdiplus / tests / font.c
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 #include "windows.h"
25 #include "gdiplus.h"
26 #include "wine/test.h"
27
28 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
29 #define expectf_(expected, got, precision) ok(fabs((expected) - (got)) <= (precision), "Expected %f, got %f\n", (expected), (got))
30 #define expectf(expected, got) expectf_((expected), (got), 0.001)
31
32 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'};
33 static const WCHAR MSSansSerif[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'};
34 static const WCHAR MicrosoftSansSerif[] = {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f','\0'};
35 static const WCHAR TimesNewRoman[] = {'T','i','m','e','s',' ','N','e','w',' ','R','o','m','a','n','\0'};
36 static const WCHAR CourierNew[] = {'C','o','u','r','i','e','r',' ','N','e','w','\0'};
37 static const WCHAR Tahoma[] = {'T','a','h','o','m','a',0};
38 static const WCHAR LiberationSerif[] = {'L','i','b','e','r','a','t','i','o','n',' ','S','e','r','i','f',0};
39
40 static void set_rect_empty(RectF *rc)
41 {
42     rc->X = 0.0;
43     rc->Y = 0.0;
44     rc->Width = 0.0;
45     rc->Height = 0.0;
46 }
47
48 static void test_createfont(void)
49 {
50     GpFontFamily* fontfamily = NULL, *fontfamily2;
51     GpFont* font = NULL;
52     GpStatus stat;
53     Unit unit;
54     UINT i;
55     REAL size;
56     WCHAR familyname[LF_FACESIZE];
57
58     stat = GdipCreateFontFamilyFromName(nonexistent, NULL, &fontfamily);
59     expect (FontFamilyNotFound, stat);
60     stat = GdipDeleteFont(font);
61     expect (InvalidParameter, stat);
62     stat = GdipCreateFontFamilyFromName(Tahoma, NULL, &fontfamily);
63     expect (Ok, stat);
64     stat = GdipCreateFont(fontfamily, 12, FontStyleRegular, UnitPoint, &font);
65     expect (Ok, stat);
66     stat = GdipGetFontUnit (font, &unit);
67     expect (Ok, stat);
68     expect (UnitPoint, unit);
69
70     stat = GdipGetFamily(font, &fontfamily2);
71     expect(Ok, stat);
72     stat = GdipGetFamilyName(fontfamily2, familyname, 0);
73     expect(Ok, stat);
74     ok (lstrcmpiW(Tahoma, familyname) == 0, "Expected Tahoma, got %s\n",
75             wine_dbgstr_w(familyname));
76     stat = GdipDeleteFontFamily(fontfamily2);
77     expect(Ok, stat);
78
79     /* Test to see if returned size is based on unit (its not) */
80     GdipGetFontSize(font, &size);
81     ok (size == 12, "Expected 12, got %f\n", size);
82     GdipDeleteFont(font);
83
84     /* Make sure everything is converted correctly for all Units */
85     for (i = UnitWorld; i <=UnitMillimeter; i++)
86     {
87         if (i == UnitDisplay) continue; /* Crashes WindowsXP, wtf? */
88         GdipCreateFont(fontfamily, 24, FontStyleRegular, i, &font);
89         GdipGetFontSize (font, &size);
90         ok (size == 24, "Expected 24, got %f (with unit: %d)\n", size, i);
91         GdipGetFontUnit (font, &unit);
92         expect (i, unit);
93         GdipDeleteFont(font);
94     }
95
96     GdipDeleteFontFamily(fontfamily);
97 }
98
99 static void test_logfont(void)
100 {
101     LOGFONTA lfa, lfa2;
102     GpFont *font;
103     GpFontFamily *family;
104     GpStatus stat;
105     GpGraphics *graphics;
106     HDC hdc = GetDC(0);
107     INT style;
108     REAL rval;
109     UINT16 em_height, line_spacing;
110     Unit unit;
111
112     GdipCreateFromHDC(hdc, &graphics);
113
114     memset(&lfa, 0, sizeof(LOGFONTA));
115     memset(&lfa2, 0xff, sizeof(LOGFONTA));
116     lstrcpyA(lfa.lfFaceName, "Tahoma");
117
118     stat = GdipCreateFontFromLogfontA(hdc, &lfa, &font);
119     expect(Ok, stat);
120     stat = GdipGetLogFontA(font, graphics, &lfa2);
121     expect(Ok, stat);
122
123     ok(lfa2.lfHeight < 0, "Expected negative height\n");
124     expect(0, lfa2.lfWidth);
125     expect(0, lfa2.lfEscapement);
126     expect(0, lfa2.lfOrientation);
127     ok((lfa2.lfWeight >= 100) && (lfa2.lfWeight <= 900), "Expected weight to be set\n");
128     expect(0, lfa2.lfItalic);
129     expect(0, lfa2.lfUnderline);
130     expect(0, lfa2.lfStrikeOut);
131     ok(lfa2.lfCharSet == GetTextCharset(hdc) || lfa2.lfCharSet == ANSI_CHARSET,
132         "Expected %x or %x, got %x\n", GetTextCharset(hdc), ANSI_CHARSET, lfa2.lfCharSet);
133     expect(0, lfa2.lfOutPrecision);
134     expect(0, lfa2.lfClipPrecision);
135     expect(0, lfa2.lfQuality);
136     expect(0, lfa2.lfPitchAndFamily);
137
138     GdipDeleteFont(font);
139
140     memset(&lfa, 0, sizeof(LOGFONTA));
141     lfa.lfHeight = 25;
142     lfa.lfWidth = 25;
143     lfa.lfEscapement = lfa.lfOrientation = 50;
144     lfa.lfItalic = lfa.lfUnderline = lfa.lfStrikeOut = TRUE;
145
146     memset(&lfa2, 0xff, sizeof(LOGFONTA));
147     lstrcpyA(lfa.lfFaceName, "Tahoma");
148
149     stat = GdipCreateFontFromLogfontA(hdc, &lfa, &font);
150     expect(Ok, stat);
151     stat = GdipGetLogFontA(font, graphics, &lfa2);
152     expect(Ok, stat);
153
154     ok(lfa2.lfHeight < 0, "Expected negative height\n");
155     expect(0, lfa2.lfWidth);
156     expect(0, lfa2.lfEscapement);
157     expect(0, lfa2.lfOrientation);
158     ok((lfa2.lfWeight >= 100) && (lfa2.lfWeight <= 900), "Expected weight to be set\n");
159     expect(TRUE, lfa2.lfItalic);
160     expect(TRUE, lfa2.lfUnderline);
161     expect(TRUE, lfa2.lfStrikeOut);
162     ok(lfa2.lfCharSet == GetTextCharset(hdc) || lfa2.lfCharSet == ANSI_CHARSET,
163         "Expected %x or %x, got %x\n", GetTextCharset(hdc), ANSI_CHARSET, lfa2.lfCharSet);
164     expect(0, lfa2.lfOutPrecision);
165     expect(0, lfa2.lfClipPrecision);
166     expect(0, lfa2.lfQuality);
167     expect(0, lfa2.lfPitchAndFamily);
168
169     stat = GdipGetFontStyle(font, &style);
170     expect(Ok, stat);
171     ok (style == (FontStyleItalic | FontStyleUnderline | FontStyleStrikeout),
172             "Expected , got %d\n", style);
173
174     stat = GdipGetFontUnit(font, &unit);
175     expect(Ok, stat);
176     expect(UnitWorld, unit);
177
178     stat = GdipGetFontHeight(font, graphics, &rval);
179     expect(Ok, stat);
180     expectf(25.347656, rval);
181     stat = GdipGetFontSize(font, &rval);
182     expect(Ok, stat);
183     expectf(21.0, rval);
184
185     stat = GdipGetFamily(font, &family);
186     expect(Ok, stat);
187     stat = GdipGetEmHeight(family, FontStyleRegular, &em_height);
188     expect(Ok, stat);
189     expect(2048, em_height);
190     stat = GdipGetLineSpacing(family, FontStyleRegular, &line_spacing);
191     expect(Ok, stat);
192     expect(2472, line_spacing);
193     GdipDeleteFontFamily(family);
194
195     GdipDeleteFont(font);
196
197     memset(&lfa, 0, sizeof(lfa));
198     lfa.lfHeight = -25;
199     lstrcpyA(lfa.lfFaceName, "Tahoma");
200     stat = GdipCreateFontFromLogfontA(hdc, &lfa, &font);
201     expect(Ok, stat);
202     memset(&lfa2, 0xff, sizeof(lfa2));
203     stat = GdipGetLogFontA(font, graphics, &lfa2);
204     expect(Ok, stat);
205     expect(lfa.lfHeight, lfa2.lfHeight);
206
207     stat = GdipGetFontUnit(font, &unit);
208     expect(Ok, stat);
209     expect(UnitWorld, unit);
210
211     stat = GdipGetFontHeight(font, graphics, &rval);
212     expect(Ok, stat);
213     expectf(30.175781, rval);
214     stat = GdipGetFontSize(font, &rval);
215     expect(Ok, stat);
216     expectf(25.0, rval);
217
218     stat = GdipGetFamily(font, &family);
219     expect(Ok, stat);
220     stat = GdipGetEmHeight(family, FontStyleRegular, &em_height);
221     expect(Ok, stat);
222     expect(2048, em_height);
223     stat = GdipGetLineSpacing(family, FontStyleRegular, &line_spacing);
224     expect(Ok, stat);
225     expect(2472, line_spacing);
226     GdipDeleteFontFamily(family);
227
228     GdipDeleteFont(font);
229
230     GdipDeleteGraphics(graphics);
231     ReleaseDC(0, hdc);
232 }
233
234 static void test_fontfamily (void)
235 {
236     GpFontFamily *family, *clonedFontFamily;
237     WCHAR itsName[LF_FACESIZE];
238     GpStatus stat;
239
240     /* FontFamily cannot be NULL */
241     stat = GdipCreateFontFamilyFromName (Tahoma , NULL, NULL);
242     expect (InvalidParameter, stat);
243
244     /* FontFamily must be able to actually find the family.
245      * If it can't, any subsequent calls should fail.
246      */
247     stat = GdipCreateFontFamilyFromName (nonexistent, NULL, &family);
248     expect (FontFamilyNotFound, stat);
249
250     /* Bitmap fonts are not found */
251     stat = GdipCreateFontFamilyFromName (MSSansSerif, NULL, &family);
252     expect (FontFamilyNotFound, stat);
253     if(stat == Ok) GdipDeleteFontFamily(family);
254
255     stat = GdipCreateFontFamilyFromName (Tahoma, NULL, &family);
256     expect (Ok, stat);
257
258     stat = GdipGetFamilyName (family, itsName, LANG_NEUTRAL);
259     expect (Ok, stat);
260     expect (0, lstrcmpiW(itsName, Tahoma));
261
262     if (0)
263     {
264         /* Crashes on Windows XP SP2, Vista, and so Wine as well */
265         stat = GdipGetFamilyName (family, NULL, LANG_NEUTRAL);
266         expect (Ok, stat);
267     }
268
269     /* Make sure we don't read old data */
270     ZeroMemory (itsName, sizeof(itsName));
271     stat = GdipCloneFontFamily(family, &clonedFontFamily);
272     expect (Ok, stat);
273     GdipDeleteFontFamily(family);
274     stat = GdipGetFamilyName(clonedFontFamily, itsName, LANG_NEUTRAL);
275     expect(Ok, stat);
276     expect(0, lstrcmpiW(itsName, Tahoma));
277
278     GdipDeleteFontFamily(clonedFontFamily);
279 }
280
281 static void test_fontfamily_properties (void)
282 {
283     GpFontFamily* FontFamily = NULL;
284     GpStatus stat;
285     UINT16 result = 0;
286
287     stat = GdipCreateFontFamilyFromName(Tahoma, NULL, &FontFamily);
288     expect(Ok, stat);
289
290     stat = GdipGetLineSpacing(FontFamily, FontStyleRegular, &result);
291     expect(Ok, stat);
292     ok (result == 2472, "Expected 2472, got %d\n", result);
293     result = 0;
294     stat = GdipGetEmHeight(FontFamily, FontStyleRegular, &result);
295     expect(Ok, stat);
296     ok(result == 2048, "Expected 2048, got %d\n", result);
297     result = 0;
298     stat = GdipGetCellAscent(FontFamily, FontStyleRegular, &result);
299     expect(Ok, stat);
300     ok(result == 2049, "Expected 2049, got %d\n", result);
301     result = 0;
302     stat = GdipGetCellDescent(FontFamily, FontStyleRegular, &result);
303     expect(Ok, stat);
304     ok(result == 423, "Expected 423, got %d\n", result);
305     GdipDeleteFontFamily(FontFamily);
306
307     stat = GdipCreateFontFamilyFromName(TimesNewRoman, NULL, &FontFamily);
308     if(stat == FontFamilyNotFound)
309         skip("Times New Roman not installed\n");
310     else
311     {
312         result = 0;
313         stat = GdipGetLineSpacing(FontFamily, FontStyleRegular, &result);
314         expect(Ok, stat);
315         ok(result == 2355, "Expected 2355, got %d\n", result);
316         result = 0;
317         stat = GdipGetEmHeight(FontFamily, FontStyleRegular, &result);
318         expect(Ok, stat);
319         ok(result == 2048, "Expected 2048, got %d\n", result);
320         result = 0;
321         stat = GdipGetCellAscent(FontFamily, FontStyleRegular, &result);
322         expect(Ok, stat);
323         ok(result == 1825, "Expected 1825, got %d\n", result);
324         result = 0;
325         stat = GdipGetCellDescent(FontFamily, FontStyleRegular, &result);
326         expect(Ok, stat);
327         ok(result == 443, "Expected 443 got %d\n", result);
328         GdipDeleteFontFamily(FontFamily);
329     }
330 }
331
332 static void check_family(const char* context, GpFontFamily *family, WCHAR *name)
333 {
334     GpStatus stat;
335     GpFont* font;
336
337     *name = 0;
338     stat = GdipGetFamilyName(family, name, LANG_NEUTRAL);
339     ok(stat == Ok, "could not get the %s family name: %.8x\n", context, stat);
340
341     stat = GdipCreateFont(family, 12, FontStyleRegular, UnitPixel, &font);
342     ok(stat == Ok, "could not create a font for the %s family: %.8x\n", context, stat);
343     if (stat == Ok)
344     {
345         stat = GdipDeleteFont(font);
346         ok(stat == Ok, "could not delete the %s family font: %.8x\n", context, stat);
347     }
348
349     stat = GdipDeleteFontFamily(family);
350     ok(stat == Ok, "could not delete the %s family: %.8x\n", context, stat);
351 }
352
353 static void test_getgenerics (void)
354 {
355     GpStatus stat;
356     GpFontFamily *family;
357     WCHAR sansname[LF_FACESIZE], serifname[LF_FACESIZE], mononame[LF_FACESIZE];
358     int missingfonts = 0;
359
360     stat = GdipGetGenericFontFamilySansSerif(&family);
361     expect (Ok, stat);
362     if (stat == FontFamilyNotFound)
363         missingfonts = 1;
364     else
365         check_family("Sans Serif", family, sansname);
366
367     stat = GdipGetGenericFontFamilySerif(&family);
368     expect (Ok, stat);
369     if (stat == FontFamilyNotFound)
370         missingfonts = 1;
371     else
372         check_family("Serif", family, serifname);
373
374     stat = GdipGetGenericFontFamilyMonospace(&family);
375     expect (Ok, stat);
376     if (stat == FontFamilyNotFound)
377         missingfonts = 1;
378     else
379         check_family("Monospace", family, mononame);
380
381     if (missingfonts && strcmp(winetest_platform, "wine") == 0)
382         trace("You may need to install either the Microsoft Web Fonts or the Liberation Fonts\n");
383
384     /* Check that the family names are all different */
385     ok(lstrcmpiW(sansname, serifname) != 0, "Sans Serif and Serif families should be different: %s\n", wine_dbgstr_w(sansname));
386     ok(lstrcmpiW(sansname, mononame) != 0, "Sans Serif and Monospace families should be different: %s\n", wine_dbgstr_w(sansname));
387     ok(lstrcmpiW(serifname, mononame) != 0, "Serif and Monospace families should be different: %s\n", wine_dbgstr_w(serifname));
388 }
389
390 static void test_installedfonts (void)
391 {
392     GpStatus stat;
393     GpFontCollection* collection=NULL;
394
395     stat = GdipNewInstalledFontCollection(NULL);
396     expect (InvalidParameter, stat);
397
398     stat = GdipNewInstalledFontCollection(&collection);
399     expect (Ok, stat);
400     ok (collection != NULL, "got NULL font collection\n");
401 }
402
403 static void test_heightgivendpi(void)
404 {
405     GpStatus stat;
406     GpFont* font = NULL;
407     GpFontFamily* fontfamily = NULL;
408     REAL height;
409     Unit unit;
410
411     stat = GdipCreateFontFamilyFromName(Tahoma, NULL, &fontfamily);
412     expect(Ok, stat);
413
414     stat = GdipCreateFont(fontfamily, 30, FontStyleRegular, UnitPixel, &font);
415     expect(Ok, stat);
416
417     stat = GdipGetFontHeightGivenDPI(NULL, 96, &height);
418     expect(InvalidParameter, stat);
419
420     stat = GdipGetFontHeightGivenDPI(font, 96, NULL);
421     expect(InvalidParameter, stat);
422
423     stat = GdipGetFontHeightGivenDPI(font, 96, &height);
424     expect(Ok, stat);
425     expectf(36.210938, height);
426     GdipDeleteFont(font);
427
428     height = 12345;
429     stat = GdipCreateFont(fontfamily, 30, FontStyleRegular, UnitWorld, &font);
430     expect(Ok, stat);
431
432     stat = GdipGetFontUnit(font, &unit);
433     expect(Ok, stat);
434     expect(UnitWorld, unit);
435
436     stat = GdipGetFontHeightGivenDPI(font, 96, &height);
437     expect(Ok, stat);
438     expectf(36.210938, height);
439     GdipDeleteFont(font);
440
441     height = 12345;
442     stat = GdipCreateFont(fontfamily, 30, FontStyleRegular, UnitPoint, &font);
443     expect(Ok, stat);
444     stat = GdipGetFontHeightGivenDPI(font, 96, &height);
445     expect(Ok, stat);
446     expectf(48.281250, height);
447     GdipDeleteFont(font);
448
449     height = 12345;
450     stat = GdipCreateFont(fontfamily, 30, FontStyleRegular, UnitInch, &font);
451     expect(Ok, stat);
452
453     stat = GdipGetFontUnit(font, &unit);
454     expect(Ok, stat);
455     expect(UnitInch, unit);
456
457     stat = GdipGetFontHeightGivenDPI(font, 96, &height);
458     expect(Ok, stat);
459     expectf(3476.250000, height);
460     GdipDeleteFont(font);
461
462     height = 12345;
463     stat = GdipCreateFont(fontfamily, 30, FontStyleRegular, UnitDocument, &font);
464     expect(Ok, stat);
465
466     stat = GdipGetFontUnit(font, &unit);
467     expect(Ok, stat);
468     expect(UnitDocument, unit);
469
470     stat = GdipGetFontHeightGivenDPI(font, 96, &height);
471     expect(Ok, stat);
472     expectf(11.587500, height);
473     GdipDeleteFont(font);
474
475     height = 12345;
476     stat = GdipCreateFont(fontfamily, 30, FontStyleRegular, UnitMillimeter, &font);
477     expect(Ok, stat);
478
479     stat = GdipGetFontUnit(font, &unit);
480     expect(Ok, stat);
481     expect(UnitMillimeter, unit);
482
483     stat = GdipGetFontHeightGivenDPI(font, 96, &height);
484     expect(Ok, stat);
485     expectf(136.860245, height);
486     GdipDeleteFont(font);
487
488     GdipDeleteFontFamily(fontfamily);
489 }
490
491 static int CALLBACK font_enum_proc(const LOGFONTW *lfe, const TEXTMETRICW *ntme,
492                                    DWORD type, LPARAM lparam)
493 {
494     NEWTEXTMETRICW *ntm = (NEWTEXTMETRICW *)lparam;
495
496     if (type != TRUETYPE_FONTTYPE) return 1;
497
498     *ntm = *(NEWTEXTMETRICW *)ntme;
499     return 0;
500 }
501
502 struct font_metrics
503 {
504     UINT16 em_height, line_spacing, ascent, descent;
505     REAL font_height, font_size;
506     INT lfHeight;
507 };
508
509 static void gdi_get_font_metrics(LOGFONTW *lf, struct font_metrics *fm)
510 {
511     HDC hdc;
512     HFONT hfont;
513     NEWTEXTMETRICW ntm;
514     OUTLINETEXTMETRICW otm;
515     int ret;
516
517     hdc = CreateCompatibleDC(0);
518
519     /* it's the only way to get extended NEWTEXTMETRIC fields */
520     ret = EnumFontFamiliesExW(hdc, lf, font_enum_proc, (LPARAM)&ntm, 0);
521     ok(!ret, "EnumFontFamiliesExW failed to find %s\n", wine_dbgstr_w(lf->lfFaceName));
522
523     hfont = CreateFontIndirectW(lf);
524     SelectObject(hdc, hfont);
525
526     otm.otmSize = sizeof(otm);
527     ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
528     ok(ret, "GetOutlineTextMetrics failed\n");
529
530     DeleteDC(hdc);
531     DeleteObject(hfont);
532
533     fm->lfHeight = -otm.otmTextMetrics.tmAscent;
534     fm->line_spacing = ntm.ntmCellHeight;
535     fm->font_size = (REAL)otm.otmTextMetrics.tmAscent;
536     fm->font_height = (REAL)fm->line_spacing * fm->font_size / (REAL)ntm.ntmSizeEM;
537     fm->em_height = ntm.ntmSizeEM;
538     fm->ascent = ntm.ntmSizeEM;
539     fm->descent = ntm.ntmCellHeight - ntm.ntmSizeEM;
540 }
541
542 static void gdip_get_font_metrics(GpFont *font, struct font_metrics *fm)
543 {
544     INT style;
545     GpFontFamily *family;
546     GpStatus stat;
547
548     stat = GdipGetFontStyle(font, &style);
549     expect(Ok, 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     HDC hdc;
732     HFONT hfont;
733     LOGFONT lf;
734     GpStatus status;
735     GpGraphics *graphics;
736     GpFont *font;
737     GpFontFamily *family;
738     int ret;
739
740     hdc = CreateCompatibleDC(0);
741     status = GdipCreateFromHDC(hdc, &graphics);
742     expect(Ok, status);
743
744     hfont = GetStockObject(DEFAULT_GUI_FONT);
745     ok(hfont != 0, "GetStockObject(DEFAULT_GUI_FONT) failed\n");
746
747     memset(&lf, 0xfe, sizeof(lf));
748     ret = GetObject(hfont, sizeof(lf), &lf);
749     ok(ret == sizeof(lf), "GetObject failed\n");
750     ok(!lstrcmp(lf.lfFaceName, "MS Shell Dlg"), "wrong face name %s\n", lf.lfFaceName);
751     MultiByteToWideChar(CP_ACP, 0, lf.lfFaceName, -1, ms_shell_dlg, LF_FACESIZE);
752
753     status = GdipCreateFontFromLogfontA(hdc, &lf, &font);
754     expect(Ok, status);
755     memset(&lf, 0xfe, sizeof(lf));
756     status = GdipGetLogFontA(font, graphics, &lf);
757     expect(Ok, status);
758     ok(!lstrcmp(lf.lfFaceName, "Microsoft Sans Serif") ||
759        !lstrcmp(lf.lfFaceName, "Tahoma"), "wrong face name %s\n", lf.lfFaceName);
760     GdipDeleteFont(font);
761
762     status = GdipCreateFontFamilyFromName(ms_shell_dlg, NULL, &family);
763     expect(Ok, status);
764     status = GdipCreateFont(family, 12, FontStyleRegular, UnitPoint, &font);
765     expect(Ok, status);
766     memset(&lf, 0xfe, sizeof(lf));
767     status = GdipGetLogFontA(font, graphics, &lf);
768     expect(Ok, status);
769     ok(!lstrcmp(lf.lfFaceName, "Microsoft Sans Serif") ||
770        !lstrcmp(lf.lfFaceName, "Tahoma"), "wrong face name %s\n", lf.lfFaceName);
771     GdipDeleteFont(font);
772     GdipDeleteFontFamily(family);
773
774     status = GdipCreateFontFamilyFromName(nonexistent, NULL, &family);
775     ok(status == FontFamilyNotFound, "expected FontFamilyNotFound, got %d\n", status);
776
777     lstrcpy(lf.lfFaceName, "ThisFontShouldNotExist");
778     status = GdipCreateFontFromLogfontA(hdc, &lf, &font);
779     expect(Ok, status);
780     memset(&lf, 0xfe, sizeof(lf));
781     status = GdipGetLogFontA(font, graphics, &lf);
782     expect(Ok, status);
783     ok(!lstrcmp(lf.lfFaceName, "Arial"), "wrong face name %s\n", lf.lfFaceName);
784     GdipDeleteFont(font);
785
786     /* empty FaceName */
787     lf.lfFaceName[0] = 0;
788     status = GdipCreateFontFromLogfontA(hdc, &lf, &font);
789     expect(Ok, status);
790     memset(&lf, 0xfe, sizeof(lf));
791     status = GdipGetLogFontA(font, graphics, &lf);
792     expect(Ok, status);
793     ok(!lstrcmp(lf.lfFaceName, "Arial"), "wrong face name %s\n", lf.lfFaceName);
794     GdipDeleteFont(font);
795
796     /* zeroing out lfWeight and lfCharSet leads to font creation failure */
797     lf.lfWeight = 0;
798     lf.lfCharSet = 0;
799     lstrcpy(lf.lfFaceName, "ThisFontShouldNotExist");
800     status = GdipCreateFontFromLogfontA(hdc, &lf, &font);
801 todo_wine
802     ok(status == NotTrueTypeFont || broken(status == FileNotFound), /* before XP */
803        "expected NotTrueTypeFont, got %d\n", status);
804
805     /* empty FaceName */
806     lf.lfFaceName[0] = 0;
807     status = GdipCreateFontFromLogfontA(hdc, &lf, &font);
808 todo_wine
809     ok(status == NotTrueTypeFont || broken(status == FileNotFound), /* before XP */
810        "expected NotTrueTypeFont, got %d\n", status);
811
812     GdipDeleteGraphics(graphics);
813     DeleteDC(hdc);
814 }
815
816 static void test_font_transform(void)
817 {
818     static const WCHAR string[] = { 'A',0 };
819     GpStatus status;
820     HDC hdc;
821     LOGFONT lf;
822     GpFont *font;
823     GpGraphics *graphics;
824     GpMatrix *matrix;
825     GpStringFormat *format, *typographic;
826     PointF pos[1] = { { 0,0 } };
827     REAL height;
828     RectF bounds, rect;
829
830     hdc = CreateCompatibleDC(0);
831     status = GdipCreateFromHDC(hdc, &graphics);
832     expect(Ok, status);
833
834     status = GdipSetPageUnit(graphics, UnitPixel);
835     expect(Ok, status);
836
837     status = GdipCreateStringFormat(0, LANG_NEUTRAL, &format);
838     expect(Ok, status);
839     status = GdipStringFormatGetGenericTypographic(&typographic);
840     expect(Ok, status);
841
842     memset(&lf, 0, sizeof(lf));
843     lstrcpy(lf.lfFaceName, "Tahoma");
844     lf.lfHeight = -100;
845     lf.lfWidth = 100;
846     status = GdipCreateFontFromLogfontA(hdc, &lf, &font);
847     expect(Ok, status);
848
849     /* identity matrix */
850     status = GdipCreateMatrix(&matrix);
851     expect(Ok, status);
852     status = GdipSetWorldTransform(graphics, matrix);
853     expect(Ok, status);
854     status = GdipGetLogFontA(font, graphics, &lf);
855     expect(Ok, status);
856     expect(-100, lf.lfHeight);
857     expect(0, lf.lfWidth);
858     status = GdipGetFontHeight(font, graphics, &height);
859     expect(Ok, status);
860     expectf(120.703125, height);
861     set_rect_empty(&rect);
862     set_rect_empty(&bounds);
863     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, NULL, NULL);
864     expect(Ok, status);
865     expectf(0.0, bounds.X);
866     expectf(0.0, bounds.Y);
867 todo_wine
868     expectf(133.203125, bounds.Height);
869     set_rect_empty(&rect);
870     set_rect_empty(&bounds);
871     status = GdipMeasureString(graphics, string, -1, font, &rect, typographic, &bounds, NULL, NULL);
872     expect(Ok, status);
873     expectf(0.0, bounds.X);
874     expectf(0.0, bounds.Y);
875 todo_wine
876     expectf(120.703125, bounds.Height);
877     set_rect_empty(&bounds);
878     status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos,
879                                      DriverStringOptionsCmapLookup, NULL, &bounds);
880     expect(Ok, status);
881     expectf(0.0, bounds.X);
882 todo_wine
883     expectf_(-100.0, bounds.Y, 0.05);
884 todo_wine
885     expectf(120.703125, bounds.Height);
886
887     /* scale matrix */
888     status = GdipScaleMatrix(matrix, 2.0, 3.0, MatrixOrderAppend);
889     expect(Ok, status);
890     status = GdipSetWorldTransform(graphics, matrix);
891     expect(Ok, status);
892     status = GdipGetLogFontA(font, graphics, &lf);
893     expect(Ok, status);
894 todo_wine
895     expect(-300, lf.lfHeight);
896     expect(0, lf.lfWidth);
897     status = GdipGetFontHeight(font, graphics, &height);
898     expect(Ok, status);
899     expectf(120.703125, height);
900     set_rect_empty(&rect);
901     set_rect_empty(&bounds);
902     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, NULL, NULL);
903     expect(Ok, status);
904     expectf(0.0, bounds.X);
905     expectf(0.0, bounds.Y);
906 todo_wine
907     expectf(133.203125, bounds.Height);
908     set_rect_empty(&rect);
909     set_rect_empty(&bounds);
910     status = GdipMeasureString(graphics, string, -1, font, &rect, typographic, &bounds, NULL, NULL);
911     expect(Ok, status);
912     expectf(0.0, bounds.X);
913     expectf(0.0, bounds.Y);
914 todo_wine
915     expectf(120.703125, bounds.Height);
916     set_rect_empty(&bounds);
917     status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos,
918                                      DriverStringOptionsCmapLookup, NULL, &bounds);
919     expect(Ok, status);
920     expectf(0.0, bounds.X);
921 todo_wine
922     expectf_(-100.0, bounds.Y, 0.05);
923 todo_wine
924     expectf(120.703125, bounds.Height);
925
926     /* scale + ratate matrix */
927     status = GdipRotateMatrix(matrix, 45.0, MatrixOrderAppend);
928     expect(Ok, status);
929     status = GdipSetWorldTransform(graphics, matrix);
930     expect(Ok, status);
931     status = GdipGetLogFontA(font, graphics, &lf);
932     expect(Ok, status);
933 todo_wine
934     expect(-300, lf.lfHeight);
935     expect(0, lf.lfWidth);
936     status = GdipGetFontHeight(font, graphics, &height);
937     expect(Ok, status);
938     expectf(120.703125, height);
939     set_rect_empty(&rect);
940     set_rect_empty(&bounds);
941     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, NULL, NULL);
942     expect(Ok, status);
943     expectf(0.0, bounds.X);
944     expectf(0.0, bounds.Y);
945 todo_wine
946     expectf(133.203125, bounds.Height);
947     set_rect_empty(&rect);
948     set_rect_empty(&bounds);
949     status = GdipMeasureString(graphics, string, -1, font, &rect, typographic, &bounds, NULL, NULL);
950     expect(Ok, status);
951     expectf(0.0, bounds.X);
952     expectf(0.0, bounds.Y);
953 todo_wine
954     expectf(120.703125, bounds.Height);
955     set_rect_empty(&bounds);
956     status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos,
957                                      DriverStringOptionsCmapLookup, NULL, &bounds);
958     expect(Ok, status);
959     expectf(0.0, bounds.X);
960 todo_wine
961     expectf_(-100.0, bounds.Y, 0.05);
962 todo_wine
963     expectf(120.703125, bounds.Height);
964
965     /* scale + ratate + shear matrix */
966     status = GdipShearMatrix(matrix, 4.0, 5.0, MatrixOrderAppend);
967     expect(Ok, status);
968     status = GdipSetWorldTransform(graphics, matrix);
969     expect(Ok, status);
970     status = GdipGetLogFontA(font, graphics, &lf);
971     expect(Ok, status);
972 todo_wine
973     expect(1032, lf.lfHeight);
974     expect(0, lf.lfWidth);
975     status = GdipGetFontHeight(font, graphics, &height);
976     expect(Ok, status);
977     expectf(120.703125, height);
978     set_rect_empty(&rect);
979     set_rect_empty(&bounds);
980     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, NULL, NULL);
981     expect(Ok, status);
982     expectf(0.0, bounds.X);
983     expectf(0.0, bounds.Y);
984 todo_wine
985     expectf(133.203125, bounds.Height);
986     set_rect_empty(&rect);
987     set_rect_empty(&bounds);
988     status = GdipMeasureString(graphics, string, -1, font, &rect, typographic, &bounds, NULL, NULL);
989     expect(Ok, status);
990     expectf(0.0, bounds.X);
991     expectf(0.0, bounds.Y);
992 todo_wine
993     expectf(120.703125, bounds.Height);
994     set_rect_empty(&bounds);
995     status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos,
996                                      DriverStringOptionsCmapLookup, NULL, &bounds);
997     expect(Ok, status);
998     expectf(0.0, bounds.X);
999 todo_wine
1000     expectf_(-100.0, bounds.Y, 0.05);
1001 todo_wine
1002     expectf(120.703125, bounds.Height);
1003
1004     /* scale + ratate + shear + translate matrix */
1005     status = GdipTranslateMatrix(matrix, 10.0, 20.0, MatrixOrderAppend);
1006     expect(Ok, status);
1007     status = GdipSetWorldTransform(graphics, matrix);
1008     expect(Ok, status);
1009     status = GdipGetLogFontA(font, graphics, &lf);
1010     expect(Ok, status);
1011 todo_wine
1012     expect(1032, lf.lfHeight);
1013     expect(0, lf.lfWidth);
1014     status = GdipGetFontHeight(font, graphics, &height);
1015     expect(Ok, status);
1016     expectf(120.703125, height);
1017     set_rect_empty(&rect);
1018     set_rect_empty(&bounds);
1019     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, NULL, NULL);
1020     expect(Ok, status);
1021     expectf(0.0, bounds.X);
1022     expectf(0.0, bounds.Y);
1023 todo_wine
1024     expectf(133.203125, bounds.Height);
1025     set_rect_empty(&rect);
1026     set_rect_empty(&bounds);
1027     status = GdipMeasureString(graphics, string, -1, font, &rect, typographic, &bounds, NULL, NULL);
1028     expect(Ok, status);
1029     expectf(0.0, bounds.X);
1030     expectf(0.0, bounds.Y);
1031 todo_wine
1032     expectf(120.703125, bounds.Height);
1033     set_rect_empty(&bounds);
1034     status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos,
1035                                      DriverStringOptionsCmapLookup, NULL, &bounds);
1036     expect(Ok, status);
1037     expectf(0.0, bounds.X);
1038 todo_wine
1039     expectf_(-100.0, bounds.Y, 0.05);
1040 todo_wine
1041     expectf(120.703125, bounds.Height);
1042
1043     GdipDeleteMatrix(matrix);
1044     GdipDeleteFont(font);
1045     GdipDeleteGraphics(graphics);
1046     GdipDeleteStringFormat(typographic);
1047     GdipDeleteStringFormat(format);
1048     DeleteDC(hdc);
1049 }
1050
1051 START_TEST(font)
1052 {
1053     struct GdiplusStartupInput gdiplusStartupInput;
1054     ULONG_PTR gdiplusToken;
1055
1056     gdiplusStartupInput.GdiplusVersion              = 1;
1057     gdiplusStartupInput.DebugEventCallback          = NULL;
1058     gdiplusStartupInput.SuppressBackgroundThread    = 0;
1059     gdiplusStartupInput.SuppressExternalCodecs      = 0;
1060
1061     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
1062
1063     test_font_transform();
1064     test_font_substitution();
1065     test_font_metrics();
1066     test_createfont();
1067     test_logfont();
1068     test_fontfamily();
1069     test_fontfamily_properties();
1070     test_getgenerics();
1071     test_installedfonts();
1072     test_heightgivendpi();
1073
1074     GdiplusShutdown(gdiplusToken);
1075 }