2 * Unit test suite for fonts
4 * Copyright (C) 2007 Google (Evan Stade)
5 * Copyright (C) 2012 Dmitry Timoshkov
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.
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.
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
24 #define WIN32_NO_STATUS
26 #define COM_NO_WINDOWS_H
28 //#include "windows.h"
29 #include <wine/test.h>
35 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
36 #define expect_(expected, got, precision) ok(abs((expected) - (got)) <= (precision), "Expected %d, got %d\n", (expected), (got))
37 #define expectf_(expected, got, precision) ok(fabs((expected) - (got)) <= (precision), "Expected %f, got %f\n", (expected), (got))
38 #define expectf(expected, got) expectf_((expected), (got), 0.001)
40 static const WCHAR nonexistent
[] = {'T','h','i','s','F','o','n','t','s','h','o','u','l','d','N','o','t','E','x','i','s','t','\0'};
41 static const WCHAR MSSansSerif
[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'};
42 static const WCHAR TimesNewRoman
[] = {'T','i','m','e','s',' ','N','e','w',' ','R','o','m','a','n','\0'};
43 static const WCHAR Tahoma
[] = {'T','a','h','o','m','a',0};
45 static void set_rect_empty(RectF
*rc
)
53 static void test_createfont(void)
55 GpFontFamily
* fontfamily
= NULL
, *fontfamily2
;
61 WCHAR familyname
[LF_FACESIZE
];
63 stat
= GdipCreateFontFamilyFromName(nonexistent
, NULL
, &fontfamily
);
64 expect (FontFamilyNotFound
, stat
);
65 stat
= GdipDeleteFont(font
);
66 expect (InvalidParameter
, stat
);
67 stat
= GdipCreateFontFamilyFromName(Tahoma
, NULL
, &fontfamily
);
69 stat
= GdipCreateFont(fontfamily
, 12, FontStyleRegular
, UnitPoint
, &font
);
71 stat
= GdipGetFontUnit (font
, &unit
);
73 expect (UnitPoint
, unit
);
75 stat
= GdipGetFamily(font
, &fontfamily2
);
77 stat
= GdipGetFamilyName(fontfamily2
, familyname
, 0);
79 ok (lstrcmpiW(Tahoma
, familyname
) == 0, "Expected Tahoma, got %s\n",
80 wine_dbgstr_w(familyname
));
81 stat
= GdipDeleteFontFamily(fontfamily2
);
84 /* Test to see if returned size is based on unit (its not) */
85 GdipGetFontSize(font
, &size
);
86 ok (size
== 12, "Expected 12, got %f\n", size
);
89 /* Make sure everything is converted correctly for all Units */
90 for (i
= UnitWorld
; i
<=UnitMillimeter
; i
++)
92 if (i
== UnitDisplay
) continue; /* Crashes WindowsXP, wtf? */
93 GdipCreateFont(fontfamily
, 24, FontStyleRegular
, i
, &font
);
94 GdipGetFontSize (font
, &size
);
95 ok (size
== 24, "Expected 24, got %f (with unit: %d)\n", size
, i
);
96 GdipGetFontUnit (font
, &unit
);
101 GdipDeleteFontFamily(fontfamily
);
104 static void test_logfont(void)
108 GpFontFamily
*family
;
110 GpGraphics
*graphics
;
114 UINT16 em_height
, line_spacing
;
117 GdipCreateFromHDC(hdc
, &graphics
);
119 memset(&lfa
, 0, sizeof(LOGFONTA
));
120 memset(&lfa2
, 0xff, sizeof(LOGFONTA
));
121 lstrcpyA(lfa
.lfFaceName
, "Tahoma");
123 stat
= GdipCreateFontFromLogfontA(hdc
, &lfa
, &font
);
125 stat
= GdipGetLogFontA(font
, graphics
, &lfa2
);
128 ok(lfa2
.lfHeight
< 0, "Expected negative height\n");
129 expect(0, lfa2
.lfWidth
);
130 expect(0, lfa2
.lfEscapement
);
131 expect(0, lfa2
.lfOrientation
);
132 ok((lfa2
.lfWeight
>= 100) && (lfa2
.lfWeight
<= 900), "Expected weight to be set\n");
133 expect(0, lfa2
.lfItalic
);
134 expect(0, lfa2
.lfUnderline
);
135 expect(0, lfa2
.lfStrikeOut
);
136 ok(lfa2
.lfCharSet
== GetTextCharset(hdc
) || lfa2
.lfCharSet
== ANSI_CHARSET
,
137 "Expected %x or %x, got %x\n", GetTextCharset(hdc
), ANSI_CHARSET
, lfa2
.lfCharSet
);
138 expect(0, lfa2
.lfOutPrecision
);
139 expect(0, lfa2
.lfClipPrecision
);
140 expect(0, lfa2
.lfQuality
);
141 expect(0, lfa2
.lfPitchAndFamily
);
143 GdipDeleteFont(font
);
145 memset(&lfa
, 0, sizeof(LOGFONTA
));
148 lfa
.lfEscapement
= lfa
.lfOrientation
= 50;
149 lfa
.lfItalic
= lfa
.lfUnderline
= lfa
.lfStrikeOut
= TRUE
;
151 memset(&lfa2
, 0xff, sizeof(LOGFONTA
));
152 lstrcpyA(lfa
.lfFaceName
, "Tahoma");
154 stat
= GdipCreateFontFromLogfontA(hdc
, &lfa
, &font
);
156 stat
= GdipGetLogFontA(font
, graphics
, &lfa2
);
159 ok(lfa2
.lfHeight
< 0, "Expected negative height\n");
160 expect(0, lfa2
.lfWidth
);
161 expect(0, lfa2
.lfEscapement
);
162 expect(0, lfa2
.lfOrientation
);
163 ok((lfa2
.lfWeight
>= 100) && (lfa2
.lfWeight
<= 900), "Expected weight to be set\n");
164 expect(TRUE
, lfa2
.lfItalic
);
165 expect(TRUE
, lfa2
.lfUnderline
);
166 expect(TRUE
, lfa2
.lfStrikeOut
);
167 ok(lfa2
.lfCharSet
== GetTextCharset(hdc
) || lfa2
.lfCharSet
== ANSI_CHARSET
,
168 "Expected %x or %x, got %x\n", GetTextCharset(hdc
), ANSI_CHARSET
, lfa2
.lfCharSet
);
169 expect(0, lfa2
.lfOutPrecision
);
170 expect(0, lfa2
.lfClipPrecision
);
171 expect(0, lfa2
.lfQuality
);
172 expect(0, lfa2
.lfPitchAndFamily
);
174 stat
= GdipGetFontStyle(font
, &style
);
176 ok (style
== (FontStyleItalic
| FontStyleUnderline
| FontStyleStrikeout
),
177 "Expected , got %d\n", style
);
179 stat
= GdipGetFontUnit(font
, &unit
);
181 expect(UnitWorld
, unit
);
183 stat
= GdipGetFontHeight(font
, graphics
, &rval
);
185 expectf(25.347656, rval
);
186 stat
= GdipGetFontSize(font
, &rval
);
190 stat
= GdipGetFamily(font
, &family
);
192 stat
= GdipGetEmHeight(family
, FontStyleRegular
, &em_height
);
194 expect(2048, em_height
);
195 stat
= GdipGetLineSpacing(family
, FontStyleRegular
, &line_spacing
);
197 expect(2472, line_spacing
);
198 GdipDeleteFontFamily(family
);
200 GdipDeleteFont(font
);
202 memset(&lfa
, 0, sizeof(lfa
));
204 lstrcpyA(lfa
.lfFaceName
, "Tahoma");
205 stat
= GdipCreateFontFromLogfontA(hdc
, &lfa
, &font
);
207 memset(&lfa2
, 0xff, sizeof(lfa2
));
208 stat
= GdipGetLogFontA(font
, graphics
, &lfa2
);
210 expect(lfa
.lfHeight
, lfa2
.lfHeight
);
212 stat
= GdipGetFontUnit(font
, &unit
);
214 expect(UnitWorld
, unit
);
216 stat
= GdipGetFontHeight(font
, graphics
, &rval
);
218 expectf(30.175781, rval
);
219 stat
= GdipGetFontSize(font
, &rval
);
223 stat
= GdipGetFamily(font
, &family
);
225 stat
= GdipGetEmHeight(family
, FontStyleRegular
, &em_height
);
227 expect(2048, em_height
);
228 stat
= GdipGetLineSpacing(family
, FontStyleRegular
, &line_spacing
);
230 expect(2472, line_spacing
);
231 GdipDeleteFontFamily(family
);
233 GdipDeleteFont(font
);
235 GdipDeleteGraphics(graphics
);
239 static void test_fontfamily (void)
241 GpFontFamily
*family
, *clonedFontFamily
;
242 WCHAR itsName
[LF_FACESIZE
];
245 /* FontFamily cannot be NULL */
246 stat
= GdipCreateFontFamilyFromName (Tahoma
, NULL
, NULL
);
247 expect (InvalidParameter
, stat
);
249 /* FontFamily must be able to actually find the family.
250 * If it can't, any subsequent calls should fail.
252 stat
= GdipCreateFontFamilyFromName (nonexistent
, NULL
, &family
);
253 expect (FontFamilyNotFound
, stat
);
255 /* Bitmap fonts are not found */
256 stat
= GdipCreateFontFamilyFromName (MSSansSerif
, NULL
, &family
);
257 expect (FontFamilyNotFound
, stat
);
258 if(stat
== Ok
) GdipDeleteFontFamily(family
);
260 stat
= GdipCreateFontFamilyFromName (Tahoma
, NULL
, &family
);
263 stat
= GdipGetFamilyName (family
, itsName
, LANG_NEUTRAL
);
265 expect (0, lstrcmpiW(itsName
, Tahoma
));
269 /* Crashes on Windows XP SP2, Vista, and so Wine as well */
270 stat
= GdipGetFamilyName (family
, NULL
, LANG_NEUTRAL
);
274 /* Make sure we don't read old data */
275 ZeroMemory (itsName
, sizeof(itsName
));
276 stat
= GdipCloneFontFamily(family
, &clonedFontFamily
);
278 GdipDeleteFontFamily(family
);
279 stat
= GdipGetFamilyName(clonedFontFamily
, itsName
, LANG_NEUTRAL
);
281 expect(0, lstrcmpiW(itsName
, Tahoma
));
283 GdipDeleteFontFamily(clonedFontFamily
);
286 static void test_fontfamily_properties (void)
288 GpFontFamily
* FontFamily
= NULL
;
292 stat
= GdipCreateFontFamilyFromName(Tahoma
, NULL
, &FontFamily
);
295 stat
= GdipGetLineSpacing(FontFamily
, FontStyleRegular
, &result
);
297 ok (result
== 2472, "Expected 2472, got %d\n", result
);
299 stat
= GdipGetEmHeight(FontFamily
, FontStyleRegular
, &result
);
301 ok(result
== 2048, "Expected 2048, got %d\n", result
);
303 stat
= GdipGetCellAscent(FontFamily
, FontStyleRegular
, &result
);
305 ok(result
== 2049, "Expected 2049, got %d\n", result
);
307 stat
= GdipGetCellDescent(FontFamily
, FontStyleRegular
, &result
);
309 ok(result
== 423, "Expected 423, got %d\n", result
);
310 GdipDeleteFontFamily(FontFamily
);
312 stat
= GdipCreateFontFamilyFromName(TimesNewRoman
, NULL
, &FontFamily
);
313 if(stat
== FontFamilyNotFound
)
314 skip("Times New Roman not installed\n");
318 stat
= GdipGetLineSpacing(FontFamily
, FontStyleRegular
, &result
);
320 ok(result
== 2355, "Expected 2355, got %d\n", result
);
322 stat
= GdipGetEmHeight(FontFamily
, FontStyleRegular
, &result
);
324 ok(result
== 2048, "Expected 2048, got %d\n", result
);
326 stat
= GdipGetCellAscent(FontFamily
, FontStyleRegular
, &result
);
328 ok(result
== 1825, "Expected 1825, got %d\n", result
);
330 stat
= GdipGetCellDescent(FontFamily
, FontStyleRegular
, &result
);
332 ok(result
== 443, "Expected 443 got %d\n", result
);
333 GdipDeleteFontFamily(FontFamily
);
337 static void check_family(const char* context
, GpFontFamily
*family
, WCHAR
*name
)
343 stat
= GdipGetFamilyName(family
, name
, LANG_NEUTRAL
);
344 ok(stat
== Ok
, "could not get the %s family name: %.8x\n", context
, stat
);
346 stat
= GdipCreateFont(family
, 12, FontStyleRegular
, UnitPixel
, &font
);
347 ok(stat
== Ok
, "could not create a font for the %s family: %.8x\n", context
, stat
);
350 stat
= GdipDeleteFont(font
);
351 ok(stat
== Ok
, "could not delete the %s family font: %.8x\n", context
, stat
);
354 stat
= GdipDeleteFontFamily(family
);
355 ok(stat
== Ok
, "could not delete the %s family: %.8x\n", context
, stat
);
358 static void test_getgenerics (void)
361 GpFontFamily
*family
;
362 WCHAR sansname
[LF_FACESIZE
], serifname
[LF_FACESIZE
], mononame
[LF_FACESIZE
];
363 int missingfonts
= 0;
365 stat
= GdipGetGenericFontFamilySansSerif(&family
);
367 if (stat
== FontFamilyNotFound
)
370 check_family("Sans Serif", family
, sansname
);
372 stat
= GdipGetGenericFontFamilySerif(&family
);
374 if (stat
== FontFamilyNotFound
)
377 check_family("Serif", family
, serifname
);
379 stat
= GdipGetGenericFontFamilyMonospace(&family
);
381 if (stat
== FontFamilyNotFound
)
384 check_family("Monospace", family
, mononame
);
386 if (missingfonts
&& strcmp(winetest_platform
, "wine") == 0)
387 trace("You may need to install either the Microsoft Web Fonts or the Liberation Fonts\n");
389 /* Check that the family names are all different */
390 ok(lstrcmpiW(sansname
, serifname
) != 0, "Sans Serif and Serif families should be different: %s\n", wine_dbgstr_w(sansname
));
391 ok(lstrcmpiW(sansname
, mononame
) != 0, "Sans Serif and Monospace families should be different: %s\n", wine_dbgstr_w(sansname
));
392 ok(lstrcmpiW(serifname
, mononame
) != 0, "Serif and Monospace families should be different: %s\n", wine_dbgstr_w(serifname
));
395 static void test_installedfonts (void)
398 GpFontCollection
* collection
=NULL
;
400 stat
= GdipNewInstalledFontCollection(NULL
);
401 expect (InvalidParameter
, stat
);
403 stat
= GdipNewInstalledFontCollection(&collection
);
405 ok (collection
!= NULL
, "got NULL font collection\n");
408 static void test_heightgivendpi(void)
412 GpFontFamily
* fontfamily
= NULL
;
416 stat
= GdipCreateFontFamilyFromName(Tahoma
, NULL
, &fontfamily
);
419 stat
= GdipCreateFont(fontfamily
, 30, FontStyleRegular
, UnitPixel
, &font
);
422 stat
= GdipGetFontHeightGivenDPI(NULL
, 96, &height
);
423 expect(InvalidParameter
, stat
);
425 stat
= GdipGetFontHeightGivenDPI(font
, 96, NULL
);
426 expect(InvalidParameter
, stat
);
428 stat
= GdipGetFontHeightGivenDPI(font
, 96, &height
);
430 expectf(36.210938, height
);
431 GdipDeleteFont(font
);
434 stat
= GdipCreateFont(fontfamily
, 30, FontStyleRegular
, UnitWorld
, &font
);
437 stat
= GdipGetFontUnit(font
, &unit
);
439 expect(UnitWorld
, unit
);
441 stat
= GdipGetFontHeightGivenDPI(font
, 96, &height
);
443 expectf(36.210938, height
);
444 GdipDeleteFont(font
);
447 stat
= GdipCreateFont(fontfamily
, 30, FontStyleRegular
, UnitPoint
, &font
);
449 stat
= GdipGetFontHeightGivenDPI(font
, 96, &height
);
451 expectf(48.281250, height
);
452 GdipDeleteFont(font
);
455 stat
= GdipCreateFont(fontfamily
, 30, FontStyleRegular
, UnitInch
, &font
);
458 stat
= GdipGetFontUnit(font
, &unit
);
460 expect(UnitInch
, unit
);
462 stat
= GdipGetFontHeightGivenDPI(font
, 96, &height
);
464 expectf(3476.250000, height
);
465 GdipDeleteFont(font
);
468 stat
= GdipCreateFont(fontfamily
, 30, FontStyleRegular
, UnitDocument
, &font
);
471 stat
= GdipGetFontUnit(font
, &unit
);
473 expect(UnitDocument
, unit
);
475 stat
= GdipGetFontHeightGivenDPI(font
, 96, &height
);
477 expectf(11.587500, height
);
478 GdipDeleteFont(font
);
481 stat
= GdipCreateFont(fontfamily
, 30, FontStyleRegular
, UnitMillimeter
, &font
);
484 stat
= GdipGetFontUnit(font
, &unit
);
486 expect(UnitMillimeter
, unit
);
488 stat
= GdipGetFontHeightGivenDPI(font
, 96, &height
);
490 expectf(136.860245, height
);
491 GdipDeleteFont(font
);
493 GdipDeleteFontFamily(fontfamily
);
496 static int CALLBACK
font_enum_proc(const LOGFONTW
*lfe
, const TEXTMETRICW
*ntme
,
497 DWORD type
, LPARAM lparam
)
499 NEWTEXTMETRICW
*ntm
= (NEWTEXTMETRICW
*)lparam
;
501 if (type
!= TRUETYPE_FONTTYPE
) return 1;
503 *ntm
= *(NEWTEXTMETRICW
*)ntme
;
509 UINT16 em_height
, line_spacing
, ascent
, descent
;
510 REAL font_height
, font_size
;
514 static void gdi_get_font_metrics(LOGFONTW
*lf
, struct font_metrics
*fm
)
519 OUTLINETEXTMETRICW otm
;
522 hdc
= CreateCompatibleDC(0);
524 /* it's the only way to get extended NEWTEXTMETRIC fields */
525 ret
= EnumFontFamiliesExW(hdc
, lf
, font_enum_proc
, (LPARAM
)&ntm
, 0);
526 ok(!ret
, "EnumFontFamiliesExW failed to find %s\n", wine_dbgstr_w(lf
->lfFaceName
));
528 hfont
= CreateFontIndirectW(lf
);
529 SelectObject(hdc
, hfont
);
531 otm
.otmSize
= sizeof(otm
);
532 ret
= GetOutlineTextMetricsW(hdc
, otm
.otmSize
, &otm
);
533 ok(ret
, "GetOutlineTextMetrics failed\n");
538 fm
->lfHeight
= -otm
.otmTextMetrics
.tmAscent
;
539 fm
->line_spacing
= ntm
.ntmCellHeight
;
540 fm
->font_size
= (REAL
)otm
.otmTextMetrics
.tmAscent
;
541 fm
->font_height
= (REAL
)fm
->line_spacing
* fm
->font_size
/ (REAL
)ntm
.ntmSizeEM
;
542 fm
->em_height
= ntm
.ntmSizeEM
;
543 fm
->ascent
= ntm
.ntmSizeEM
;
544 fm
->descent
= ntm
.ntmCellHeight
- ntm
.ntmSizeEM
;
547 static void gdip_get_font_metrics(GpFont
*font
, struct font_metrics
*fm
)
550 GpFontFamily
*family
;
553 stat
= GdipGetFontStyle(font
, &style
);
556 stat
= GdipGetFontHeight(font
, NULL
, &fm
->font_height
);
558 stat
= GdipGetFontSize(font
, &fm
->font_size
);
561 fm
->lfHeight
= (INT
)(fm
->font_size
* -1.0);
563 stat
= GdipGetFamily(font
, &family
);
566 stat
= GdipGetEmHeight(family
, style
, &fm
->em_height
);
568 stat
= GdipGetLineSpacing(family
, style
, &fm
->line_spacing
);
570 stat
= GdipGetCellAscent(family
, style
, &fm
->ascent
);
572 stat
= GdipGetCellDescent(family
, style
, &fm
->descent
);
575 GdipDeleteFontFamily(family
);
578 static void cmp_font_metrics(struct font_metrics
*fm1
, struct font_metrics
*fm2
, int line
)
580 ok_(__FILE__
, line
)(fm1
->lfHeight
== fm2
->lfHeight
, "lfHeight %d != %d\n", fm1
->lfHeight
, fm2
->lfHeight
);
581 ok_(__FILE__
, line
)(fm1
->em_height
== fm2
->em_height
, "em_height %u != %u\n", fm1
->em_height
, fm2
->em_height
);
582 ok_(__FILE__
, line
)(fm1
->line_spacing
== fm2
->line_spacing
, "line_spacing %u != %u\n", fm1
->line_spacing
, fm2
->line_spacing
);
583 ok_(__FILE__
, line
)(abs(fm1
->ascent
- fm2
->ascent
) <= 1, "ascent %u != %u\n", fm1
->ascent
, fm2
->ascent
);
584 ok_(__FILE__
, line
)(abs(fm1
->descent
- fm2
->descent
) <= 1, "descent %u != %u\n", fm1
->descent
, fm2
->descent
);
585 ok(fm1
->font_height
> 0.0, "fm1->font_height should be positive, got %f\n", fm1
->font_height
);
586 ok(fm2
->font_height
> 0.0, "fm2->font_height should be positive, got %f\n", fm2
->font_height
);
587 ok_(__FILE__
, line
)(fm1
->font_height
== fm2
->font_height
, "font_height %f != %f\n", fm1
->font_height
, fm2
->font_height
);
588 ok(fm1
->font_size
> 0.0, "fm1->font_size should be positive, got %f\n", fm1
->font_size
);
589 ok(fm2
->font_size
> 0.0, "fm2->font_size should be positive, got %f\n", fm2
->font_size
);
590 ok_(__FILE__
, line
)(fm1
->font_size
== fm2
->font_size
, "font_size %f != %f\n", fm1
->font_size
, fm2
->font_size
);
593 static void test_font_metrics(void)
597 GpFontFamily
*family
;
598 GpGraphics
*graphics
;
601 struct font_metrics fm_gdi
, fm_gdip
;
604 hdc
= CreateCompatibleDC(0);
605 stat
= GdipCreateFromHDC(hdc
, &graphics
);
608 memset(&lf
, 0, sizeof(lf
));
611 lstrcpyW(lf
.lfFaceName
, Tahoma
);
613 stat
= GdipCreateFontFromLogfontW(hdc
, &lf
, &font
);
616 stat
= GdipGetFontUnit(font
, &unit
);
618 expect(UnitWorld
, unit
);
620 gdip_get_font_metrics(font
, &fm_gdip
);
622 trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
623 wine_dbgstr_w(lf
.lfFaceName
), lf
.lfHeight
,
624 fm_gdip
.em_height
, fm_gdip
.line_spacing
, fm_gdip
.ascent
, fm_gdip
.descent
,
625 fm_gdip
.font_height
, fm_gdip
.font_size
);
627 gdi_get_font_metrics(&lf
, &fm_gdi
);
629 trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
630 wine_dbgstr_w(lf
.lfFaceName
), lf
.lfHeight
,
631 fm_gdi
.em_height
, fm_gdi
.line_spacing
, fm_gdi
.ascent
, fm_gdi
.descent
,
632 fm_gdi
.font_height
, fm_gdi
.font_size
);
634 cmp_font_metrics(&fm_gdip
, &fm_gdi
, __LINE__
);
636 stat
= GdipGetLogFontW(font
, graphics
, &lf
);
638 ok(lf
.lfHeight
< 0, "lf.lfHeight should be negative, got %d\n", lf
.lfHeight
);
639 gdi_get_font_metrics(&lf
, &fm_gdi
);
641 trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
642 wine_dbgstr_w(lf
.lfFaceName
), lf
.lfHeight
,
643 fm_gdi
.em_height
, fm_gdi
.line_spacing
, fm_gdi
.ascent
, fm_gdi
.descent
,
644 fm_gdi
.font_height
, fm_gdi
.font_size
);
645 ok((REAL
)lf
.lfHeight
* -1.0 == fm_gdi
.font_size
, "expected %f, got %f\n", (REAL
)lf
.lfHeight
* -1.0, fm_gdi
.font_size
);
647 cmp_font_metrics(&fm_gdip
, &fm_gdi
, __LINE__
);
649 GdipDeleteFont(font
);
652 lstrcpyW(lf
.lfFaceName
, Tahoma
);
654 stat
= GdipCreateFontFromLogfontW(hdc
, &lf
, &font
);
657 stat
= GdipGetFontUnit(font
, &unit
);
659 expect(UnitWorld
, unit
);
661 gdip_get_font_metrics(font
, &fm_gdip
);
663 trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
664 wine_dbgstr_w(lf
.lfFaceName
), lf
.lfHeight
,
665 fm_gdip
.em_height
, fm_gdip
.line_spacing
, fm_gdip
.ascent
, fm_gdip
.descent
,
666 fm_gdip
.font_height
, fm_gdip
.font_size
);
668 gdi_get_font_metrics(&lf
, &fm_gdi
);
670 trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
671 wine_dbgstr_w(lf
.lfFaceName
), lf
.lfHeight
,
672 fm_gdi
.em_height
, fm_gdi
.line_spacing
, fm_gdi
.ascent
, fm_gdi
.descent
,
673 fm_gdi
.font_height
, fm_gdi
.font_size
);
675 cmp_font_metrics(&fm_gdip
, &fm_gdi
, __LINE__
);
677 stat
= GdipGetLogFontW(font
, graphics
, &lf
);
679 ok(lf
.lfHeight
< 0, "lf.lfHeight should be negative, got %d\n", lf
.lfHeight
);
680 gdi_get_font_metrics(&lf
, &fm_gdi
);
682 trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
683 wine_dbgstr_w(lf
.lfFaceName
), lf
.lfHeight
,
684 fm_gdi
.em_height
, fm_gdi
.line_spacing
, fm_gdi
.ascent
, fm_gdi
.descent
,
685 fm_gdi
.font_height
, fm_gdi
.font_size
);
686 ok((REAL
)lf
.lfHeight
* -1.0 == fm_gdi
.font_size
, "expected %f, got %f\n", (REAL
)lf
.lfHeight
* -1.0, fm_gdi
.font_size
);
688 cmp_font_metrics(&fm_gdip
, &fm_gdi
, __LINE__
);
690 GdipDeleteFont(font
);
692 stat
= GdipCreateFontFamilyFromName(Tahoma
, NULL
, &family
);
696 stat
= GdipCreateFont(family
, 13.0, FontStyleRegular
, UnitPixel
, &font
);
699 gdip_get_font_metrics(font
, &fm_gdip
);
701 trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
702 wine_dbgstr_w(lf
.lfFaceName
), lf
.lfHeight
,
703 fm_gdip
.em_height
, fm_gdip
.line_spacing
, fm_gdip
.ascent
, fm_gdip
.descent
,
704 fm_gdip
.font_height
, fm_gdip
.font_size
);
706 stat
= GdipGetLogFontW(font
, graphics
, &lf
);
708 ok(lf
.lfHeight
< 0, "lf.lfHeight should be negative, got %d\n", lf
.lfHeight
);
709 gdi_get_font_metrics(&lf
, &fm_gdi
);
711 trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
712 wine_dbgstr_w(lf
.lfFaceName
), lf
.lfHeight
,
713 fm_gdi
.em_height
, fm_gdi
.line_spacing
, fm_gdi
.ascent
, fm_gdi
.descent
,
714 fm_gdi
.font_height
, fm_gdi
.font_size
);
715 ok((REAL
)lf
.lfHeight
* -1.0 == fm_gdi
.font_size
, "expected %f, got %f\n", (REAL
)lf
.lfHeight
* -1.0, fm_gdi
.font_size
);
717 cmp_font_metrics(&fm_gdip
, &fm_gdi
, __LINE__
);
719 stat
= GdipGetLogFontW(font
, NULL
, &lf
);
720 expect(InvalidParameter
, stat
);
722 GdipDeleteFont(font
);
724 stat
= GdipCreateFont(family
, -13.0, FontStyleRegular
, UnitPixel
, &font
);
725 expect(InvalidParameter
, stat
);
727 GdipDeleteFontFamily(family
);
729 GdipDeleteGraphics(graphics
);
733 static void test_font_substitution(void)
735 WCHAR ms_shell_dlg
[LF_FACESIZE
];
740 GpGraphics
*graphics
;
742 GpFontFamily
*family
;
745 hdc
= CreateCompatibleDC(0);
746 status
= GdipCreateFromHDC(hdc
, &graphics
);
749 hfont
= GetStockObject(DEFAULT_GUI_FONT
);
750 ok(hfont
!= 0, "GetStockObject(DEFAULT_GUI_FONT) failed\n");
752 memset(&lf
, 0xfe, sizeof(lf
));
753 ret
= GetObjectA(hfont
, sizeof(lf
), &lf
);
754 ok(ret
== sizeof(lf
), "GetObject failed\n");
755 ok(!lstrcmpA(lf
.lfFaceName
, "MS Shell Dlg"), "wrong face name %s\n", lf
.lfFaceName
);
756 MultiByteToWideChar(CP_ACP
, 0, lf
.lfFaceName
, -1, ms_shell_dlg
, LF_FACESIZE
);
758 status
= GdipCreateFontFromLogfontA(hdc
, &lf
, &font
);
760 memset(&lf
, 0xfe, sizeof(lf
));
761 status
= GdipGetLogFontA(font
, graphics
, &lf
);
763 ok(!lstrcmpA(lf
.lfFaceName
, "Microsoft Sans Serif") ||
764 !lstrcmpA(lf
.lfFaceName
, "Tahoma"), "wrong face name %s\n", lf
.lfFaceName
);
765 GdipDeleteFont(font
);
767 status
= GdipCreateFontFamilyFromName(ms_shell_dlg
, NULL
, &family
);
769 status
= GdipCreateFont(family
, 12, FontStyleRegular
, UnitPoint
, &font
);
771 memset(&lf
, 0xfe, sizeof(lf
));
772 status
= GdipGetLogFontA(font
, graphics
, &lf
);
774 ok(!lstrcmpA(lf
.lfFaceName
, "Microsoft Sans Serif") ||
775 !lstrcmpA(lf
.lfFaceName
, "Tahoma"), "wrong face name %s\n", lf
.lfFaceName
);
776 GdipDeleteFont(font
);
777 GdipDeleteFontFamily(family
);
779 status
= GdipCreateFontFamilyFromName(nonexistent
, NULL
, &family
);
780 ok(status
== FontFamilyNotFound
, "expected FontFamilyNotFound, got %d\n", status
);
782 lstrcpyA(lf
.lfFaceName
, "ThisFontShouldNotExist");
783 status
= GdipCreateFontFromLogfontA(hdc
, &lf
, &font
);
785 memset(&lf
, 0xfe, sizeof(lf
));
786 status
= GdipGetLogFontA(font
, graphics
, &lf
);
788 ok(!lstrcmpA(lf
.lfFaceName
, "Arial"), "wrong face name %s\n", lf
.lfFaceName
);
789 GdipDeleteFont(font
);
792 lf
.lfFaceName
[0] = 0;
793 status
= GdipCreateFontFromLogfontA(hdc
, &lf
, &font
);
795 memset(&lf
, 0xfe, sizeof(lf
));
796 status
= GdipGetLogFontA(font
, graphics
, &lf
);
798 ok(!lstrcmpA(lf
.lfFaceName
, "Arial"), "wrong face name %s\n", lf
.lfFaceName
);
799 GdipDeleteFont(font
);
801 /* zeroing out lfWeight and lfCharSet leads to font creation failure */
804 lstrcpyA(lf
.lfFaceName
, "ThisFontShouldNotExist");
806 status
= GdipCreateFontFromLogfontA(hdc
, &lf
, &font
);
808 ok(status
== NotTrueTypeFont
|| broken(status
== FileNotFound
), /* before XP */
809 "expected NotTrueTypeFont, got %d\n", status
);
810 /* FIXME: remove when wine is fixed */
811 if (font
) GdipDeleteFont(font
);
814 lf
.lfFaceName
[0] = 0;
816 status
= GdipCreateFontFromLogfontA(hdc
, &lf
, &font
);
818 ok(status
== NotTrueTypeFont
|| broken(status
== FileNotFound
), /* before XP */
819 "expected NotTrueTypeFont, got %d\n", status
);
820 /* FIXME: remove when wine is fixed */
821 if (font
) GdipDeleteFont(font
);
823 GdipDeleteGraphics(graphics
);
827 static void test_font_transform(void)
829 static const WCHAR string
[] = { 'A',0 };
834 GpGraphics
*graphics
;
836 GpStringFormat
*format
, *typographic
;
837 PointF pos
[1] = { { 0,0 } };
838 REAL height
, margin_y
;
841 hdc
= CreateCompatibleDC(0);
842 status
= GdipCreateFromHDC(hdc
, &graphics
);
845 status
= GdipSetPageUnit(graphics
, UnitPixel
);
848 status
= GdipCreateStringFormat(0, LANG_NEUTRAL
, &format
);
850 status
= GdipStringFormatGetGenericTypographic(&typographic
);
853 memset(&lf
, 0, sizeof(lf
));
854 lstrcpyA(lf
.lfFaceName
, "Tahoma");
857 status
= GdipCreateFontFromLogfontA(hdc
, &lf
, &font
);
860 margin_y
= 100.0 / 8.0;
862 /* identity matrix */
863 status
= GdipCreateMatrix(&matrix
);
865 status
= GdipSetWorldTransform(graphics
, matrix
);
867 status
= GdipGetLogFontA(font
, graphics
, &lf
);
869 expect(-100, lf
.lfHeight
);
870 expect(0, lf
.lfWidth
);
871 expect(0, lf
.lfEscapement
);
872 expect(0, lf
.lfOrientation
);
873 status
= GdipGetFontHeight(font
, graphics
, &height
);
875 expectf(120.703125, height
);
876 set_rect_empty(&rect
);
877 set_rect_empty(&bounds
);
878 status
= GdipMeasureString(graphics
, string
, -1, font
, &rect
, format
, &bounds
, NULL
, NULL
);
880 expectf(0.0, bounds
.X
);
881 expectf(0.0, bounds
.Y
);
883 expectf(height
+ margin_y
, bounds
.Height
);
884 set_rect_empty(&rect
);
885 set_rect_empty(&bounds
);
886 status
= GdipMeasureString(graphics
, string
, -1, font
, &rect
, typographic
, &bounds
, NULL
, NULL
);
888 expectf(0.0, bounds
.X
);
889 expectf(0.0, bounds
.Y
);
890 expectf_(height
, bounds
.Height
, 1.0);
891 set_rect_empty(&bounds
);
892 status
= GdipMeasureDriverString(graphics
, (const UINT16
*)string
, -1, font
, pos
,
893 DriverStringOptionsCmapLookup
, NULL
, &bounds
);
895 expectf(0.0, bounds
.X
);
896 expectf_(-100.0, bounds
.Y
, 0.05);
897 expectf_(height
, bounds
.Height
, 0.5);
898 set_rect_empty(&bounds
);
899 status
= GdipMeasureDriverString(graphics
, (const UINT16
*)string
, -1, font
, pos
,
900 DriverStringOptionsCmapLookup
, matrix
, &bounds
);
902 expectf(0.0, bounds
.X
);
903 expectf_(-100.0, bounds
.Y
, 0.05);
904 expectf_(height
, bounds
.Height
, 0.5);
907 status
= GdipScaleMatrix(matrix
, 2.0, 3.0, MatrixOrderAppend
);
909 status
= GdipSetWorldTransform(graphics
, matrix
);
911 status
= GdipGetLogFontA(font
, graphics
, &lf
);
913 expect(-300, lf
.lfHeight
);
914 expect(0, lf
.lfWidth
);
915 expect(0, lf
.lfEscapement
);
916 expect(0, lf
.lfOrientation
);
917 status
= GdipGetFontHeight(font
, graphics
, &height
);
919 expectf(120.703125, height
);
920 set_rect_empty(&rect
);
921 set_rect_empty(&bounds
);
922 status
= GdipMeasureString(graphics
, string
, -1, font
, &rect
, format
, &bounds
, NULL
, NULL
);
924 expectf(0.0, bounds
.X
);
925 expectf(0.0, bounds
.Y
);
927 expectf(height
+ margin_y
, bounds
.Height
);
928 set_rect_empty(&rect
);
929 set_rect_empty(&bounds
);
930 status
= GdipMeasureString(graphics
, string
, -1, font
, &rect
, typographic
, &bounds
, NULL
, NULL
);
932 expectf(0.0, bounds
.X
);
933 expectf(0.0, bounds
.Y
);
934 expectf_(height
, bounds
.Height
, 0.05);
935 set_rect_empty(&bounds
);
936 status
= GdipMeasureDriverString(graphics
, (const UINT16
*)string
, -1, font
, pos
,
937 DriverStringOptionsCmapLookup
, NULL
, &bounds
);
939 expectf(0.0, bounds
.X
);
940 expectf_(-100.0, bounds
.Y
, 0.05);
941 expectf_(height
, bounds
.Height
, 0.2);
942 set_rect_empty(&bounds
);
943 status
= GdipMeasureDriverString(graphics
, (const UINT16
*)string
, -1, font
, pos
,
944 DriverStringOptionsCmapLookup
, matrix
, &bounds
);
946 expectf(0.0, bounds
.X
);
948 expectf_(-300.0, bounds
.Y
, 0.15);
950 expectf(height
* 3.0, bounds
.Height
);
952 /* scale + ratate matrix */
953 status
= GdipRotateMatrix(matrix
, 45.0, MatrixOrderAppend
);
955 status
= GdipSetWorldTransform(graphics
, matrix
);
957 status
= GdipGetLogFontA(font
, graphics
, &lf
);
959 expect(-300, lf
.lfHeight
);
960 expect(0, lf
.lfWidth
);
961 expect_(3151, lf
.lfEscapement
, 1);
962 expect_(3151, lf
.lfOrientation
, 1);
963 status
= GdipGetFontHeight(font
, graphics
, &height
);
965 expectf(120.703125, height
);
966 set_rect_empty(&rect
);
967 set_rect_empty(&bounds
);
968 status
= GdipMeasureString(graphics
, string
, -1, font
, &rect
, format
, &bounds
, NULL
, NULL
);
970 expectf(0.0, bounds
.X
);
971 expectf(0.0, bounds
.Y
);
973 expectf(height
+ margin_y
, bounds
.Height
);
974 set_rect_empty(&rect
);
975 set_rect_empty(&bounds
);
976 status
= GdipMeasureString(graphics
, string
, -1, font
, &rect
, typographic
, &bounds
, NULL
, NULL
);
978 expectf(0.0, bounds
.X
);
979 expectf(0.0, bounds
.Y
);
980 expectf_(height
, bounds
.Height
, 0.05);
981 set_rect_empty(&bounds
);
982 status
= GdipMeasureDriverString(graphics
, (const UINT16
*)string
, -1, font
, pos
,
983 DriverStringOptionsCmapLookup
, NULL
, &bounds
);
985 expectf(0.0, bounds
.X
);
986 expectf_(-100.0, bounds
.Y
, 0.05);
987 expectf_(height
, bounds
.Height
, 0.2);
988 set_rect_empty(&bounds
);
989 status
= GdipMeasureDriverString(graphics
, (const UINT16
*)string
, -1, font
, pos
,
990 DriverStringOptionsCmapLookup
, matrix
, &bounds
);
993 expectf_(-43.814377, bounds
.X
, 0.05);
995 expectf_(-212.235611, bounds
.Y
, 0.05);
997 expectf_(340.847534, bounds
.Height
, 0.05);
999 /* scale + ratate + shear matrix */
1000 status
= GdipShearMatrix(matrix
, 4.0, 5.0, MatrixOrderAppend
);
1002 status
= GdipSetWorldTransform(graphics
, matrix
);
1004 status
= GdipGetLogFontA(font
, graphics
, &lf
);
1007 expect(1032, lf
.lfHeight
);
1008 expect(0, lf
.lfWidth
);
1009 expect_(3099, lf
.lfEscapement
, 1);
1010 expect_(3099, lf
.lfOrientation
, 1);
1011 status
= GdipGetFontHeight(font
, graphics
, &height
);
1013 expectf(120.703125, height
);
1014 set_rect_empty(&rect
);
1015 set_rect_empty(&bounds
);
1016 status
= GdipMeasureString(graphics
, string
, -1, font
, &rect
, format
, &bounds
, NULL
, NULL
);
1018 expectf(0.0, bounds
.X
);
1019 expectf(0.0, bounds
.Y
);
1021 expectf(height
+ margin_y
, bounds
.Height
);
1022 set_rect_empty(&rect
);
1023 set_rect_empty(&bounds
);
1024 status
= GdipMeasureString(graphics
, string
, -1, font
, &rect
, typographic
, &bounds
, NULL
, NULL
);
1026 expectf(0.0, bounds
.X
);
1027 expectf(0.0, bounds
.Y
);
1028 expectf_(height
, bounds
.Height
, 0.2);
1029 set_rect_empty(&bounds
);
1030 status
= GdipMeasureDriverString(graphics
, (const UINT16
*)string
, -1, font
, pos
,
1031 DriverStringOptionsCmapLookup
, NULL
, &bounds
);
1033 expectf(0.0, bounds
.X
);
1034 expectf_(-100.0, bounds
.Y
, 0.2);
1035 expectf_(height
, bounds
.Height
, 0.2);
1036 set_rect_empty(&bounds
);
1037 status
= GdipMeasureDriverString(graphics
, (const UINT16
*)string
, -1, font
, pos
,
1038 DriverStringOptionsCmapLookup
, matrix
, &bounds
);
1041 expectf_(-636.706848, bounds
.X
, 0.05);
1043 expectf_(-175.257523, bounds
.Y
, 0.05);
1045 expectf_(1532.984985, bounds
.Height
, 0.05);
1047 /* scale + ratate + shear + translate matrix */
1048 status
= GdipTranslateMatrix(matrix
, 10.0, 20.0, MatrixOrderAppend
);
1050 status
= GdipSetWorldTransform(graphics
, matrix
);
1052 status
= GdipGetLogFontA(font
, graphics
, &lf
);
1055 expect(1032, lf
.lfHeight
);
1056 expect(0, lf
.lfWidth
);
1057 expect_(3099, lf
.lfEscapement
, 1);
1058 expect_(3099, lf
.lfOrientation
, 1);
1059 status
= GdipGetFontHeight(font
, graphics
, &height
);
1061 expectf(120.703125, height
);
1062 set_rect_empty(&rect
);
1063 set_rect_empty(&bounds
);
1064 status
= GdipMeasureString(graphics
, string
, -1, font
, &rect
, format
, &bounds
, NULL
, NULL
);
1066 expectf(0.0, bounds
.X
);
1067 expectf(0.0, bounds
.Y
);
1069 expectf(height
+ margin_y
, bounds
.Height
);
1070 set_rect_empty(&rect
);
1071 set_rect_empty(&bounds
);
1072 status
= GdipMeasureString(graphics
, string
, -1, font
, &rect
, typographic
, &bounds
, NULL
, NULL
);
1074 expectf(0.0, bounds
.X
);
1075 expectf(0.0, bounds
.Y
);
1076 expectf_(height
, bounds
.Height
, 0.1);
1077 set_rect_empty(&bounds
);
1078 status
= GdipMeasureDriverString(graphics
, (const UINT16
*)string
, -1, font
, pos
,
1079 DriverStringOptionsCmapLookup
, NULL
, &bounds
);
1081 expectf(0.0, bounds
.X
);
1082 expectf_(-100.0, bounds
.Y
, 0.2);
1083 expectf_(height
, bounds
.Height
, 0.2);
1084 set_rect_empty(&bounds
);
1085 status
= GdipMeasureDriverString(graphics
, (const UINT16
*)string
, -1, font
, pos
,
1086 DriverStringOptionsCmapLookup
, matrix
, &bounds
);
1089 expectf_(-626.706848, bounds
.X
, 0.05);
1091 expectf_(-155.257523, bounds
.Y
, 0.05);
1093 expectf_(1532.984985, bounds
.Height
, 0.05);
1095 GdipDeleteMatrix(matrix
);
1096 GdipDeleteFont(font
);
1097 GdipDeleteGraphics(graphics
);
1098 GdipDeleteStringFormat(typographic
);
1099 GdipDeleteStringFormat(format
);
1105 struct GdiplusStartupInput gdiplusStartupInput
;
1106 ULONG_PTR gdiplusToken
;
1108 gdiplusStartupInput
.GdiplusVersion
= 1;
1109 gdiplusStartupInput
.DebugEventCallback
= NULL
;
1110 gdiplusStartupInput
.SuppressBackgroundThread
= 0;
1111 gdiplusStartupInput
.SuppressExternalCodecs
= 0;
1113 GdiplusStartup(&gdiplusToken
, &gdiplusStartupInput
, NULL
);
1115 test_font_transform();
1116 if (!winetest_interactive
)
1117 skip("ROSTESTS-154: Skipping test_font_substitution because of improper error handling\n");
1119 test_font_substitution();
1120 test_font_metrics();
1124 test_fontfamily_properties();
1126 test_installedfonts();
1127 test_heightgivendpi();
1129 GdiplusShutdown(gdiplusToken
);