gdiplus: GdipGetFontHeight should convert height from font to device units.
[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) ok(fabs(expected - got) < 0.0001, "Expected %f, got %f\n", expected, got)
30
31 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'};
32 static const WCHAR MSSansSerif[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'};
33 static const WCHAR MicrosoftSansSerif[] = {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f','\0'};
34 static const WCHAR TimesNewRoman[] = {'T','i','m','e','s',' ','N','e','w',' ','R','o','m','a','n','\0'};
35 static const WCHAR CourierNew[] = {'C','o','u','r','i','e','r',' ','N','e','w','\0'};
36 static const WCHAR Tahoma[] = {'T','a','h','o','m','a',0};
37 static const WCHAR LiberationSerif[] = {'L','i','b','e','r','a','t','i','o','n',' ','S','e','r','i','f',0};
38
39 static void test_createfont(void)
40 {
41     GpFontFamily* fontfamily = NULL, *fontfamily2;
42     GpFont* font = NULL;
43     GpStatus stat;
44     Unit unit;
45     UINT i;
46     REAL size;
47     WCHAR familyname[LF_FACESIZE];
48
49     stat = GdipCreateFontFamilyFromName(nonexistent, NULL, &fontfamily);
50     expect (FontFamilyNotFound, stat);
51     stat = GdipDeleteFont(font);
52     expect (InvalidParameter, stat);
53     stat = GdipCreateFontFamilyFromName(Tahoma, NULL, &fontfamily);
54     expect (Ok, stat);
55     stat = GdipCreateFont(fontfamily, 12, FontStyleRegular, UnitPoint, &font);
56     expect (Ok, stat);
57     stat = GdipGetFontUnit (font, &unit);
58     expect (Ok, stat);
59     expect (UnitPoint, unit);
60
61     stat = GdipGetFamily(font, &fontfamily2);
62     expect(Ok, stat);
63     stat = GdipGetFamilyName(fontfamily2, familyname, 0);
64     expect(Ok, stat);
65     ok (lstrcmpiW(Tahoma, familyname) == 0, "Expected Tahoma, got %s\n",
66             wine_dbgstr_w(familyname));
67     stat = GdipDeleteFontFamily(fontfamily2);
68     expect(Ok, stat);
69
70     /* Test to see if returned size is based on unit (its not) */
71     GdipGetFontSize(font, &size);
72     ok (size == 12, "Expected 12, got %f\n", size);
73     GdipDeleteFont(font);
74
75     /* Make sure everything is converted correctly for all Units */
76     for (i = UnitWorld; i <=UnitMillimeter; i++)
77     {
78         if (i == UnitDisplay) continue; /* Crashes WindowsXP, wtf? */
79         GdipCreateFont(fontfamily, 24, FontStyleRegular, i, &font);
80         GdipGetFontSize (font, &size);
81         ok (size == 24, "Expected 24, got %f (with unit: %d)\n", size, i);
82         GdipGetFontUnit (font, &unit);
83         expect (i, unit);
84         GdipDeleteFont(font);
85     }
86
87     GdipDeleteFontFamily(fontfamily);
88 }
89
90 static void test_logfont(void)
91 {
92     LOGFONTA lfa, lfa2;
93     GpFont *font;
94     GpFontFamily *family;
95     GpStatus stat;
96     GpGraphics *graphics;
97     HDC hdc = GetDC(0);
98     INT style;
99     REAL rval;
100     UINT16 em_height, line_spacing;
101     Unit unit;
102
103     GdipCreateFromHDC(hdc, &graphics);
104
105     memset(&lfa, 0, sizeof(LOGFONTA));
106     memset(&lfa2, 0xff, sizeof(LOGFONTA));
107
108     lstrcpyA(lfa.lfFaceName, "Nonexistent font");
109     stat = GdipCreateFontFromLogfontA(hdc, &lfa, &font);
110     ok(stat == NotTrueTypeFont || broken(stat == FileNotFound), /* before XP */
111        "expected NotTrueTypeFont, got %d\n", stat);
112
113     /* empty FaceName */
114     lfa.lfFaceName[0] = 0;
115     stat = GdipCreateFontFromLogfontA(hdc, &lfa, &font);
116     expect(NotTrueTypeFont, stat);
117
118     lstrcpyA(lfa.lfFaceName, "Tahoma");
119
120     stat = GdipCreateFontFromLogfontA(hdc, &lfa, &font);
121     expect(Ok, stat);
122     stat = GdipGetLogFontA(font, graphics, &lfa2);
123     expect(Ok, stat);
124
125     ok(lfa2.lfHeight < 0, "Expected negative height\n");
126     expect(0, lfa2.lfWidth);
127     expect(0, lfa2.lfEscapement);
128     expect(0, lfa2.lfOrientation);
129     ok((lfa2.lfWeight >= 100) && (lfa2.lfWeight <= 900), "Expected weight to be set\n");
130     expect(0, lfa2.lfItalic);
131     expect(0, lfa2.lfUnderline);
132     expect(0, lfa2.lfStrikeOut);
133     ok(lfa2.lfCharSet == GetTextCharset(hdc) || lfa2.lfCharSet == ANSI_CHARSET,
134         "Expected %x or %x, got %x\n", GetTextCharset(hdc), ANSI_CHARSET, lfa2.lfCharSet);
135     expect(0, lfa2.lfOutPrecision);
136     expect(0, lfa2.lfClipPrecision);
137     expect(0, lfa2.lfQuality);
138     expect(0, lfa2.lfPitchAndFamily);
139
140     GdipDeleteFont(font);
141
142     memset(&lfa, 0, sizeof(LOGFONTA));
143     lfa.lfHeight = 25;
144     lfa.lfWidth = 25;
145     lfa.lfEscapement = lfa.lfOrientation = 50;
146     lfa.lfItalic = lfa.lfUnderline = lfa.lfStrikeOut = TRUE;
147
148     memset(&lfa2, 0xff, sizeof(LOGFONTA));
149     lstrcpyA(lfa.lfFaceName, "Tahoma");
150
151     stat = GdipCreateFontFromLogfontA(hdc, &lfa, &font);
152     expect(Ok, stat);
153     stat = GdipGetLogFontA(font, graphics, &lfa2);
154     expect(Ok, stat);
155
156     ok(lfa2.lfHeight < 0, "Expected negative height\n");
157     expect(0, lfa2.lfWidth);
158     expect(0, lfa2.lfEscapement);
159     expect(0, lfa2.lfOrientation);
160     ok((lfa2.lfWeight >= 100) && (lfa2.lfWeight <= 900), "Expected weight to be set\n");
161     expect(TRUE, lfa2.lfItalic);
162     expect(TRUE, lfa2.lfUnderline);
163     expect(TRUE, lfa2.lfStrikeOut);
164     ok(lfa2.lfCharSet == GetTextCharset(hdc) || lfa2.lfCharSet == ANSI_CHARSET,
165         "Expected %x or %x, got %x\n", GetTextCharset(hdc), ANSI_CHARSET, lfa2.lfCharSet);
166     expect(0, lfa2.lfOutPrecision);
167     expect(0, lfa2.lfClipPrecision);
168     expect(0, lfa2.lfQuality);
169     expect(0, lfa2.lfPitchAndFamily);
170
171     stat = GdipGetFontStyle(font, &style);
172     expect(Ok, stat);
173     ok (style == (FontStyleItalic | FontStyleUnderline | FontStyleStrikeout),
174             "Expected , got %d\n", style);
175
176     stat = GdipGetFontUnit(font, &unit);
177     expect(Ok, stat);
178     expect(UnitWorld, unit);
179
180     stat = GdipGetFontHeight(font, graphics, &rval);
181     expect(Ok, stat);
182     expectf(25.347656, rval);
183     stat = GdipGetFontSize(font, &rval);
184     expect(Ok, stat);
185     expectf(21.0, rval);
186
187     stat = GdipGetFamily(font, &family);
188     expect(Ok, stat);
189     stat = GdipGetEmHeight(family, FontStyleRegular, &em_height);
190     expect(Ok, stat);
191     expect(2048, em_height);
192     stat = GdipGetLineSpacing(family, FontStyleRegular, &line_spacing);
193     expect(Ok, stat);
194     expect(2472, line_spacing);
195     GdipDeleteFontFamily(family);
196
197     GdipDeleteFont(font);
198
199     memset(&lfa, 0, sizeof(lfa));
200     lfa.lfHeight = -25;
201     lstrcpyA(lfa.lfFaceName, "Tahoma");
202     stat = GdipCreateFontFromLogfontA(hdc, &lfa, &font);
203     expect(Ok, stat);
204     memset(&lfa2, 0xff, sizeof(lfa2));
205     stat = GdipGetLogFontA(font, graphics, &lfa2);
206     expect(Ok, stat);
207     expect(lfa.lfHeight, lfa2.lfHeight);
208
209     stat = GdipGetFontUnit(font, &unit);
210     expect(Ok, stat);
211     expect(UnitWorld, unit);
212
213     stat = GdipGetFontHeight(font, graphics, &rval);
214     expect(Ok, stat);
215     expectf(30.175781, rval);
216     stat = GdipGetFontSize(font, &rval);
217     expect(Ok, stat);
218     expectf(25.0, rval);
219
220     stat = GdipGetFamily(font, &family);
221     expect(Ok, stat);
222     stat = GdipGetEmHeight(family, FontStyleRegular, &em_height);
223     expect(Ok, stat);
224     expect(2048, em_height);
225     stat = GdipGetLineSpacing(family, FontStyleRegular, &line_spacing);
226     expect(Ok, stat);
227     expect(2472, line_spacing);
228     GdipDeleteFontFamily(family);
229
230     GdipDeleteFont(font);
231
232     GdipDeleteGraphics(graphics);
233     ReleaseDC(0, hdc);
234 }
235
236 static void test_fontfamily (void)
237 {
238     GpFontFamily *family, *clonedFontFamily;
239     WCHAR itsName[LF_FACESIZE];
240     GpStatus stat;
241
242     /* FontFamily cannot be NULL */
243     stat = GdipCreateFontFamilyFromName (Tahoma , NULL, NULL);
244     expect (InvalidParameter, stat);
245
246     /* FontFamily must be able to actually find the family.
247      * If it can't, any subsequent calls should fail.
248      */
249     stat = GdipCreateFontFamilyFromName (nonexistent, NULL, &family);
250     expect (FontFamilyNotFound, stat);
251
252     /* Bitmap fonts are not found */
253     stat = GdipCreateFontFamilyFromName (MSSansSerif, NULL, &family);
254     expect (FontFamilyNotFound, stat);
255     if(stat == Ok) GdipDeleteFontFamily(family);
256
257     stat = GdipCreateFontFamilyFromName (Tahoma, NULL, &family);
258     expect (Ok, stat);
259
260     stat = GdipGetFamilyName (family, itsName, LANG_NEUTRAL);
261     expect (Ok, stat);
262     expect (0, lstrcmpiW(itsName, Tahoma));
263
264     if (0)
265     {
266         /* Crashes on Windows XP SP2, Vista, and so Wine as well */
267         stat = GdipGetFamilyName (family, NULL, LANG_NEUTRAL);
268         expect (Ok, stat);
269     }
270
271     /* Make sure we don't read old data */
272     ZeroMemory (itsName, sizeof(itsName));
273     stat = GdipCloneFontFamily(family, &clonedFontFamily);
274     expect (Ok, stat);
275     GdipDeleteFontFamily(family);
276     stat = GdipGetFamilyName(clonedFontFamily, itsName, LANG_NEUTRAL);
277     expect(Ok, stat);
278     expect(0, lstrcmpiW(itsName, Tahoma));
279
280     GdipDeleteFontFamily(clonedFontFamily);
281 }
282
283 static void test_fontfamily_properties (void)
284 {
285     GpFontFamily* FontFamily = NULL;
286     GpStatus stat;
287     UINT16 result = 0;
288
289     stat = GdipCreateFontFamilyFromName(Tahoma, NULL, &FontFamily);
290     expect(Ok, stat);
291
292     stat = GdipGetLineSpacing(FontFamily, FontStyleRegular, &result);
293     expect(Ok, stat);
294     ok (result == 2472, "Expected 2472, got %d\n", result);
295     result = 0;
296     stat = GdipGetEmHeight(FontFamily, FontStyleRegular, &result);
297     expect(Ok, stat);
298     ok(result == 2048, "Expected 2048, got %d\n", result);
299     result = 0;
300     stat = GdipGetCellAscent(FontFamily, FontStyleRegular, &result);
301     expect(Ok, stat);
302     ok(result == 2049, "Expected 2049, got %d\n", result);
303     result = 0;
304     stat = GdipGetCellDescent(FontFamily, FontStyleRegular, &result);
305     expect(Ok, stat);
306     ok(result == 423, "Expected 423, got %d\n", result);
307     GdipDeleteFontFamily(FontFamily);
308
309     stat = GdipCreateFontFamilyFromName(TimesNewRoman, NULL, &FontFamily);
310     if(stat == FontFamilyNotFound)
311         skip("Times New Roman not installed\n");
312     else
313     {
314         result = 0;
315         stat = GdipGetLineSpacing(FontFamily, FontStyleRegular, &result);
316         expect(Ok, stat);
317         ok(result == 2355, "Expected 2355, got %d\n", result);
318         result = 0;
319         stat = GdipGetEmHeight(FontFamily, FontStyleRegular, &result);
320         expect(Ok, stat);
321         ok(result == 2048, "Expected 2048, got %d\n", result);
322         result = 0;
323         stat = GdipGetCellAscent(FontFamily, FontStyleRegular, &result);
324         expect(Ok, stat);
325         ok(result == 1825, "Expected 1825, got %d\n", result);
326         result = 0;
327         stat = GdipGetCellDescent(FontFamily, FontStyleRegular, &result);
328         expect(Ok, stat);
329         ok(result == 443, "Expected 443 got %d\n", result);
330         GdipDeleteFontFamily(FontFamily);
331     }
332 }
333
334 static void check_family(const char* context, GpFontFamily *family, WCHAR *name)
335 {
336     GpStatus stat;
337     GpFont* font;
338
339     *name = 0;
340     stat = GdipGetFamilyName(family, name, LANG_NEUTRAL);
341     ok(stat == Ok, "could not get the %s family name: %.8x\n", context, stat);
342
343     stat = GdipCreateFont(family, 12, FontStyleRegular, UnitPixel, &font);
344     ok(stat == Ok, "could not create a font for the %s family: %.8x\n", context, stat);
345     if (stat == Ok)
346     {
347         stat = GdipDeleteFont(font);
348         ok(stat == Ok, "could not delete the %s family font: %.8x\n", context, stat);
349     }
350
351     stat = GdipDeleteFontFamily(family);
352     ok(stat == Ok, "could not delete the %s family: %.8x\n", context, stat);
353 }
354
355 static void test_getgenerics (void)
356 {
357     GpStatus stat;
358     GpFontFamily *family;
359     WCHAR sansname[LF_FACESIZE], serifname[LF_FACESIZE], mononame[LF_FACESIZE];
360     int missingfonts = 0;
361
362     stat = GdipGetGenericFontFamilySansSerif(&family);
363     expect (Ok, stat);
364     if (stat == FontFamilyNotFound)
365         missingfonts = 1;
366     else
367         check_family("Sans Serif", family, sansname);
368
369     stat = GdipGetGenericFontFamilySerif(&family);
370     expect (Ok, stat);
371     if (stat == FontFamilyNotFound)
372         missingfonts = 1;
373     else
374         check_family("Serif", family, serifname);
375
376     stat = GdipGetGenericFontFamilyMonospace(&family);
377     expect (Ok, stat);
378     if (stat == FontFamilyNotFound)
379         missingfonts = 1;
380     else
381         check_family("Monospace", family, mononame);
382
383     if (missingfonts && strcmp(winetest_platform, "wine") == 0)
384         trace("You may need to install either the Microsoft Web Fonts or the Liberation Fonts\n");
385
386     /* Check that the family names are all different */
387     ok(lstrcmpiW(sansname, serifname) != 0, "Sans Serif and Serif families should be different: %s\n", wine_dbgstr_w(sansname));
388     ok(lstrcmpiW(sansname, mononame) != 0, "Sans Serif and Monospace families should be different: %s\n", wine_dbgstr_w(sansname));
389     ok(lstrcmpiW(serifname, mononame) != 0, "Serif and Monospace families should be different: %s\n", wine_dbgstr_w(serifname));
390 }
391
392 static void test_installedfonts (void)
393 {
394     GpStatus stat;
395     GpFontCollection* collection=NULL;
396
397     stat = GdipNewInstalledFontCollection(NULL);
398     expect (InvalidParameter, stat);
399
400     stat = GdipNewInstalledFontCollection(&collection);
401     expect (Ok, stat);
402     ok (collection != NULL, "got NULL font collection\n");
403 }
404
405 static void test_heightgivendpi(void)
406 {
407     GpStatus stat;
408     GpFont* font = NULL;
409     GpFontFamily* fontfamily = NULL;
410     REAL height;
411     Unit unit;
412
413     stat = GdipCreateFontFamilyFromName(Tahoma, NULL, &fontfamily);
414     expect(Ok, stat);
415
416     stat = GdipCreateFont(fontfamily, 30, FontStyleRegular, UnitPixel, &font);
417     expect(Ok, stat);
418
419     stat = GdipGetFontHeightGivenDPI(NULL, 96, &height);
420     expect(InvalidParameter, stat);
421
422     stat = GdipGetFontHeightGivenDPI(font, 96, NULL);
423     expect(InvalidParameter, stat);
424
425     stat = GdipGetFontHeightGivenDPI(font, 96, &height);
426     expect(Ok, stat);
427     expectf(36.210938, height);
428     GdipDeleteFont(font);
429
430     height = 12345;
431     stat = GdipCreateFont(fontfamily, 30, FontStyleRegular, UnitWorld, &font);
432     expect(Ok, stat);
433
434     stat = GdipGetFontUnit(font, &unit);
435     expect(Ok, stat);
436     expect(UnitWorld, unit);
437
438     stat = GdipGetFontHeightGivenDPI(font, 96, &height);
439     expect(Ok, stat);
440     expectf(36.210938, height);
441     GdipDeleteFont(font);
442
443     height = 12345;
444     stat = GdipCreateFont(fontfamily, 30, FontStyleRegular, UnitPoint, &font);
445     expect(Ok, stat);
446     stat = GdipGetFontHeightGivenDPI(font, 96, &height);
447     expect(Ok, stat);
448     expectf(48.281250, height);
449     GdipDeleteFont(font);
450
451     height = 12345;
452     stat = GdipCreateFont(fontfamily, 30, FontStyleRegular, UnitInch, &font);
453     expect(Ok, stat);
454
455     stat = GdipGetFontUnit(font, &unit);
456     expect(Ok, stat);
457     expect(UnitInch, unit);
458
459     stat = GdipGetFontHeightGivenDPI(font, 96, &height);
460     expect(Ok, stat);
461     expectf(3476.250000, height);
462     GdipDeleteFont(font);
463
464     height = 12345;
465     stat = GdipCreateFont(fontfamily, 30, FontStyleRegular, UnitDocument, &font);
466     expect(Ok, stat);
467
468     stat = GdipGetFontUnit(font, &unit);
469     expect(Ok, stat);
470     expect(UnitDocument, unit);
471
472     stat = GdipGetFontHeightGivenDPI(font, 96, &height);
473     expect(Ok, stat);
474     expectf(11.587500, height);
475     GdipDeleteFont(font);
476
477     height = 12345;
478     stat = GdipCreateFont(fontfamily, 30, FontStyleRegular, UnitMillimeter, &font);
479     expect(Ok, stat);
480
481     stat = GdipGetFontUnit(font, &unit);
482     expect(Ok, stat);
483     expect(UnitMillimeter, unit);
484
485     stat = GdipGetFontHeightGivenDPI(font, 96, &height);
486     expect(Ok, stat);
487     expectf(136.860245, height);
488     GdipDeleteFont(font);
489
490     GdipDeleteFontFamily(fontfamily);
491 }
492
493 static int CALLBACK font_enum_proc(const LOGFONTW *lfe, const TEXTMETRICW *ntme,
494                                    DWORD type, LPARAM lparam)
495 {
496     NEWTEXTMETRICW *ntm = (NEWTEXTMETRICW *)lparam;
497
498     if (type != TRUETYPE_FONTTYPE) return 1;
499
500     *ntm = *(NEWTEXTMETRICW *)ntme;
501     return 0;
502 }
503
504 struct font_metrics
505 {
506     UINT16 em_height, line_spacing, ascent, descent;
507     REAL font_height, font_size;
508     INT lfHeight;
509 };
510
511 static void gdi_get_font_metrics(LOGFONTW *lf, struct font_metrics *fm)
512 {
513     HDC hdc;
514     HFONT hfont;
515     NEWTEXTMETRICW ntm;
516     OUTLINETEXTMETRICW otm;
517     int ret;
518
519     hdc = CreateCompatibleDC(0);
520
521     /* it's the only way to get extended NEWTEXTMETRIC fields */
522     ret = EnumFontFamiliesExW(hdc, lf, font_enum_proc, (LPARAM)&ntm, 0);
523     ok(!ret, "EnumFontFamiliesExW failed to find %s\n", wine_dbgstr_w(lf->lfFaceName));
524
525     hfont = CreateFontIndirectW(lf);
526     SelectObject(hdc, hfont);
527
528     otm.otmSize = sizeof(otm);
529     ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
530     ok(ret, "GetOutlineTextMetrics failed\n");
531
532     DeleteDC(hdc);
533     DeleteObject(hfont);
534
535     fm->lfHeight = -otm.otmTextMetrics.tmAscent;
536     fm->line_spacing = ntm.ntmCellHeight;
537     fm->font_size = (REAL)otm.otmTextMetrics.tmAscent;
538     fm->font_height = (REAL)fm->line_spacing * fm->font_size / (REAL)ntm.ntmSizeEM;
539     fm->em_height = ntm.ntmSizeEM;
540     fm->ascent = ntm.ntmSizeEM;
541     fm->descent = ntm.ntmCellHeight - ntm.ntmSizeEM;
542 }
543
544 static void gdip_get_font_metrics(GpFont *font, struct font_metrics *fm)
545 {
546     INT style;
547     GpFontFamily *family;
548     GpStatus stat;
549
550     stat = GdipGetFontStyle(font, &style);
551     expect(Ok, stat);
552
553     stat = GdipGetFontHeight(font, NULL, &fm->font_height);
554     expect(Ok, stat);
555     stat = GdipGetFontSize(font, &fm->font_size);
556     expect(Ok, stat);
557
558     fm->lfHeight = (INT)(fm->font_size * -1.0);
559
560     stat = GdipGetFamily(font, &family);
561     expect(Ok, stat);
562
563     stat = GdipGetEmHeight(family, style, &fm->em_height);
564     expect(Ok, stat);
565     stat = GdipGetLineSpacing(family, style, &fm->line_spacing);
566     expect(Ok, stat);
567     stat = GdipGetCellAscent(family, style, &fm->ascent);
568     expect(Ok, stat);
569     stat = GdipGetCellDescent(family, style, &fm->descent);
570     expect(Ok, stat);
571
572     GdipDeleteFontFamily(family);
573 }
574
575 static void cmp_font_metrics(struct font_metrics *fm1, struct font_metrics *fm2, int line)
576 {
577     ok_(__FILE__, line)(fm1->lfHeight == fm2->lfHeight, "lfHeight %d != %d\n", fm1->lfHeight, fm2->lfHeight);
578     ok_(__FILE__, line)(fm1->em_height == fm2->em_height, "em_height %u != %u\n", fm1->em_height, fm2->em_height);
579     ok_(__FILE__, line)(fm1->line_spacing == fm2->line_spacing, "line_spacing %u != %u\n", fm1->line_spacing, fm2->line_spacing);
580     ok_(__FILE__, line)(abs(fm1->ascent - fm2->ascent) <= 1, "ascent %u != %u\n", fm1->ascent, fm2->ascent);
581     ok_(__FILE__, line)(abs(fm1->descent - fm2->descent) <= 1, "descent %u != %u\n", fm1->descent, fm2->descent);
582     ok(fm1->font_height > 0.0, "fm1->font_height should be positive, got %f\n", fm1->font_height);
583     ok(fm2->font_height > 0.0, "fm2->font_height should be positive, got %f\n", fm2->font_height);
584     ok_(__FILE__, line)(fm1->font_height == fm2->font_height, "font_height %f != %f\n", fm1->font_height, fm2->font_height);
585     ok(fm1->font_size > 0.0, "fm1->font_size should be positive, got %f\n", fm1->font_size);
586     ok(fm2->font_size > 0.0, "fm2->font_size should be positive, got %f\n", fm2->font_size);
587     ok_(__FILE__, line)(fm1->font_size == fm2->font_size, "font_size %f != %f\n", fm1->font_size, fm2->font_size);
588 }
589
590 static void test_font_metrics(void)
591 {
592     LOGFONTW lf;
593     GpFont *font;
594     GpFontFamily *family;
595     GpGraphics *graphics;
596     GpStatus stat;
597     Unit unit;
598     struct font_metrics fm_gdi, fm_gdip;
599     HDC hdc;
600
601     hdc = CreateCompatibleDC(0);
602     stat = GdipCreateFromHDC(hdc, &graphics);
603     expect(Ok, stat);
604
605     memset(&lf, 0, sizeof(lf));
606
607     /* Tahoma,-13 */
608     lstrcpyW(lf.lfFaceName, Tahoma);
609     lf.lfHeight = -13;
610     stat = GdipCreateFontFromLogfontW(hdc, &lf, &font);
611     expect(Ok, stat);
612
613     stat = GdipGetFontUnit(font, &unit);
614     expect(Ok, stat);
615     expect(UnitWorld, unit);
616
617     gdip_get_font_metrics(font, &fm_gdip);
618     trace("gdiplus:\n");
619     trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
620           wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
621           fm_gdip.em_height, fm_gdip.line_spacing, fm_gdip.ascent, fm_gdip.descent,
622           fm_gdip.font_height, fm_gdip.font_size);
623
624     gdi_get_font_metrics(&lf, &fm_gdi);
625     trace("gdi:\n");
626     trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
627           wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
628           fm_gdi.em_height, fm_gdi.line_spacing, fm_gdi.ascent, fm_gdi.descent,
629           fm_gdi.font_height, fm_gdi.font_size);
630
631     cmp_font_metrics(&fm_gdip, &fm_gdi, __LINE__);
632
633     stat = GdipGetLogFontW(font, graphics, &lf);
634     expect(Ok, stat);
635     ok(lf.lfHeight < 0, "lf.lfHeight should be negative, got %d\n", lf.lfHeight);
636     gdi_get_font_metrics(&lf, &fm_gdi);
637     trace("gdi:\n");
638     trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
639           wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
640           fm_gdi.em_height, fm_gdi.line_spacing, fm_gdi.ascent, fm_gdi.descent,
641           fm_gdi.font_height, fm_gdi.font_size);
642     ok((REAL)lf.lfHeight * -1.0 == fm_gdi.font_size, "expected %f, got %f\n", (REAL)lf.lfHeight * -1.0, fm_gdi.font_size);
643
644     cmp_font_metrics(&fm_gdip, &fm_gdi, __LINE__);
645
646     GdipDeleteFont(font);
647
648     /* Tahoma,13 */
649     lstrcpyW(lf.lfFaceName, Tahoma);
650     lf.lfHeight = 13;
651     stat = GdipCreateFontFromLogfontW(hdc, &lf, &font);
652     expect(Ok, stat);
653
654     stat = GdipGetFontUnit(font, &unit);
655     expect(Ok, stat);
656     expect(UnitWorld, unit);
657
658     gdip_get_font_metrics(font, &fm_gdip);
659     trace("gdiplus:\n");
660     trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
661           wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
662           fm_gdip.em_height, fm_gdip.line_spacing, fm_gdip.ascent, fm_gdip.descent,
663           fm_gdip.font_height, fm_gdip.font_size);
664
665     gdi_get_font_metrics(&lf, &fm_gdi);
666     trace("gdi:\n");
667     trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
668           wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
669           fm_gdi.em_height, fm_gdi.line_spacing, fm_gdi.ascent, fm_gdi.descent,
670           fm_gdi.font_height, fm_gdi.font_size);
671
672     cmp_font_metrics(&fm_gdip, &fm_gdi, __LINE__);
673
674     stat = GdipGetLogFontW(font, graphics, &lf);
675     expect(Ok, stat);
676     ok(lf.lfHeight < 0, "lf.lfHeight should be negative, got %d\n", lf.lfHeight);
677     gdi_get_font_metrics(&lf, &fm_gdi);
678     trace("gdi:\n");
679     trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
680           wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
681           fm_gdi.em_height, fm_gdi.line_spacing, fm_gdi.ascent, fm_gdi.descent,
682           fm_gdi.font_height, fm_gdi.font_size);
683     ok((REAL)lf.lfHeight * -1.0 == fm_gdi.font_size, "expected %f, got %f\n", (REAL)lf.lfHeight * -1.0, fm_gdi.font_size);
684
685     cmp_font_metrics(&fm_gdip, &fm_gdi, __LINE__);
686
687     GdipDeleteFont(font);
688
689     stat = GdipCreateFontFamilyFromName(Tahoma, NULL, &family);
690     expect(Ok, stat);
691
692     /* Tahoma,13 */
693     stat = GdipCreateFont(family, 13.0, FontStyleRegular, UnitPixel, &font);
694     expect(Ok, stat);
695
696     gdip_get_font_metrics(font, &fm_gdip);
697     trace("gdiplus:\n");
698     trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
699           wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
700           fm_gdip.em_height, fm_gdip.line_spacing, fm_gdip.ascent, fm_gdip.descent,
701           fm_gdip.font_height, fm_gdip.font_size);
702
703     stat = GdipGetLogFontW(font, graphics, &lf);
704     expect(Ok, stat);
705     ok(lf.lfHeight < 0, "lf.lfHeight should be negative, got %d\n", lf.lfHeight);
706     gdi_get_font_metrics(&lf, &fm_gdi);
707     trace("gdi:\n");
708     trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
709           wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
710           fm_gdi.em_height, fm_gdi.line_spacing, fm_gdi.ascent, fm_gdi.descent,
711           fm_gdi.font_height, fm_gdi.font_size);
712     ok((REAL)lf.lfHeight * -1.0 == fm_gdi.font_size, "expected %f, got %f\n", (REAL)lf.lfHeight * -1.0, fm_gdi.font_size);
713
714     cmp_font_metrics(&fm_gdip, &fm_gdi, __LINE__);
715
716     stat = GdipGetLogFontW(font, NULL, &lf);
717     expect(InvalidParameter, stat);
718
719     GdipDeleteFont(font);
720
721     stat = GdipCreateFont(family, -13.0, FontStyleRegular, UnitPixel, &font);
722     expect(InvalidParameter, stat);
723
724     GdipDeleteFontFamily(family);
725
726     GdipDeleteGraphics(graphics);
727     DeleteDC(hdc);
728 }
729
730 START_TEST(font)
731 {
732     struct GdiplusStartupInput gdiplusStartupInput;
733     ULONG_PTR gdiplusToken;
734
735     gdiplusStartupInput.GdiplusVersion              = 1;
736     gdiplusStartupInput.DebugEventCallback          = NULL;
737     gdiplusStartupInput.SuppressBackgroundThread    = 0;
738     gdiplusStartupInput.SuppressExternalCodecs      = 0;
739
740     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
741
742     test_font_metrics();
743     test_createfont();
744     test_logfont();
745     test_fontfamily();
746     test_fontfamily_properties();
747     test_getgenerics();
748     test_installedfonts();
749     test_heightgivendpi();
750
751     GdiplusShutdown(gdiplusToken);
752 }