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 expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
25 #define expect_(expected, got, precision) ok(abs((expected) - (got)) <= (precision), "Expected %d, got %d\n", (expected), (got))
26 #define expectf_(expected, got, precision) ok(fabs((expected) - (got)) <= (precision), "Expected %f, got %f\n", (expected), (got))
27 #define expectf(expected, got) expectf_((expected), (got), 0.001)
29 static const WCHAR nonexistent
[] = {'T','h','i','s','F','o','n','t','s','h','o','u','l','d','N','o','t','E','x','i','s','t','\0'};
30 static const WCHAR MSSansSerif
[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'};
31 static const WCHAR TimesNewRoman
[] = {'T','i','m','e','s',' ','N','e','w',' ','R','o','m','a','n','\0'};
32 static const WCHAR Tahoma
[] = {'T','a','h','o','m','a',0};
34 static void set_rect_empty(RectF
*rc
)
42 static void test_createfont(void)
44 GpFontFamily
* fontfamily
= NULL
, *fontfamily2
;
50 WCHAR familyname
[LF_FACESIZE
];
52 stat
= GdipCreateFontFamilyFromName(nonexistent
, NULL
, &fontfamily
);
53 expect (FontFamilyNotFound
, stat
);
54 stat
= GdipDeleteFont(font
);
55 expect (InvalidParameter
, stat
);
56 stat
= GdipCreateFontFamilyFromName(Tahoma
, NULL
, &fontfamily
);
58 stat
= GdipCreateFont(fontfamily
, 12, FontStyleRegular
, UnitPoint
, &font
);
60 stat
= GdipGetFontUnit (font
, &unit
);
62 expect (UnitPoint
, unit
);
64 stat
= GdipGetFamily(font
, &fontfamily2
);
66 stat
= GdipGetFamilyName(fontfamily2
, familyname
, 0);
68 ok (lstrcmpiW(Tahoma
, familyname
) == 0, "Expected Tahoma, got %s\n",
69 wine_dbgstr_w(familyname
));
70 stat
= GdipDeleteFontFamily(fontfamily2
);
73 /* Test to see if returned size is based on unit (it's not) */
74 GdipGetFontSize(font
, &size
);
75 ok (size
== 12, "Expected 12, got %f\n", size
);
78 /* Make sure everything is converted correctly for all Units */
79 for (i
= UnitWorld
; i
<=UnitMillimeter
; i
++)
81 if (i
== UnitDisplay
) continue; /* Crashes WindowsXP, wtf? */
82 GdipCreateFont(fontfamily
, 24, FontStyleRegular
, i
, &font
);
83 GdipGetFontSize (font
, &size
);
84 ok (size
== 24, "Expected 24, got %f (with unit: %d)\n", size
, i
);
85 GdipGetFontUnit (font
, &unit
);
90 GdipDeleteFontFamily(fontfamily
);
93 static void test_logfont(void)
103 UINT16 em_height
, line_spacing
;
106 GdipCreateFromHDC(hdc
, &graphics
);
108 memset(&lfa
, 0, sizeof(LOGFONTA
));
109 memset(&lfa2
, 0xff, sizeof(LOGFONTA
));
110 lstrcpyA(lfa
.lfFaceName
, "Tahoma");
112 stat
= GdipCreateFontFromLogfontA(hdc
, &lfa
, &font
);
114 stat
= GdipGetLogFontA(font
, graphics
, &lfa2
);
117 ok(lfa2
.lfHeight
< 0, "Expected negative height\n");
118 expect(0, lfa2
.lfWidth
);
119 expect(0, lfa2
.lfEscapement
);
120 expect(0, lfa2
.lfOrientation
);
121 ok((lfa2
.lfWeight
>= 100) && (lfa2
.lfWeight
<= 900), "Expected weight to be set\n");
122 expect(0, lfa2
.lfItalic
);
123 expect(0, lfa2
.lfUnderline
);
124 expect(0, lfa2
.lfStrikeOut
);
125 ok(lfa2
.lfCharSet
== GetTextCharset(hdc
) || lfa2
.lfCharSet
== ANSI_CHARSET
,
126 "Expected %x or %x, got %x\n", GetTextCharset(hdc
), ANSI_CHARSET
, lfa2
.lfCharSet
);
127 expect(0, lfa2
.lfOutPrecision
);
128 expect(0, lfa2
.lfClipPrecision
);
129 expect(0, lfa2
.lfQuality
);
130 expect(0, lfa2
.lfPitchAndFamily
);
132 GdipDeleteFont(font
);
134 memset(&lfa
, 0, sizeof(LOGFONTA
));
137 lfa
.lfEscapement
= lfa
.lfOrientation
= 50;
138 lfa
.lfItalic
= lfa
.lfUnderline
= lfa
.lfStrikeOut
= TRUE
;
140 memset(&lfa2
, 0xff, sizeof(LOGFONTA
));
141 lstrcpyA(lfa
.lfFaceName
, "Tahoma");
143 stat
= GdipCreateFontFromLogfontA(hdc
, &lfa
, &font
);
145 stat
= GdipGetLogFontA(font
, graphics
, &lfa2
);
148 ok(lfa2
.lfHeight
< 0, "Expected negative height\n");
149 expect(0, lfa2
.lfWidth
);
150 expect(0, lfa2
.lfEscapement
);
151 expect(0, lfa2
.lfOrientation
);
152 ok((lfa2
.lfWeight
>= 100) && (lfa2
.lfWeight
<= 900), "Expected weight to be set\n");
153 expect(TRUE
, lfa2
.lfItalic
);
154 expect(TRUE
, lfa2
.lfUnderline
);
155 expect(TRUE
, lfa2
.lfStrikeOut
);
156 ok(lfa2
.lfCharSet
== GetTextCharset(hdc
) || lfa2
.lfCharSet
== ANSI_CHARSET
,
157 "Expected %x or %x, got %x\n", GetTextCharset(hdc
), ANSI_CHARSET
, lfa2
.lfCharSet
);
158 expect(0, lfa2
.lfOutPrecision
);
159 expect(0, lfa2
.lfClipPrecision
);
160 expect(0, lfa2
.lfQuality
);
161 expect(0, lfa2
.lfPitchAndFamily
);
163 stat
= GdipGetFontStyle(font
, &style
);
165 ok (style
== (FontStyleItalic
| FontStyleUnderline
| FontStyleStrikeout
),
166 "Expected , got %d\n", style
);
168 stat
= GdipGetFontUnit(font
, &unit
);
170 expect(UnitWorld
, unit
);
172 stat
= GdipGetFontHeight(font
, graphics
, &rval
);
174 expectf(25.347656, rval
);
175 stat
= GdipGetFontSize(font
, &rval
);
179 stat
= GdipGetFamily(font
, &family
);
181 stat
= GdipGetEmHeight(family
, FontStyleRegular
, &em_height
);
183 expect(2048, em_height
);
184 stat
= GdipGetLineSpacing(family
, FontStyleRegular
, &line_spacing
);
186 expect(2472, line_spacing
);
187 GdipDeleteFontFamily(family
);
189 GdipDeleteFont(font
);
191 memset(&lfa
, 0, sizeof(lfa
));
193 lstrcpyA(lfa
.lfFaceName
, "Tahoma");
194 stat
= GdipCreateFontFromLogfontA(hdc
, &lfa
, &font
);
196 memset(&lfa2
, 0xff, sizeof(lfa2
));
197 stat
= GdipGetLogFontA(font
, graphics
, &lfa2
);
199 expect(lfa
.lfHeight
, lfa2
.lfHeight
);
201 stat
= GdipGetFontUnit(font
, &unit
);
203 expect(UnitWorld
, unit
);
205 stat
= GdipGetFontHeight(font
, graphics
, &rval
);
207 expectf(30.175781, rval
);
208 stat
= GdipGetFontSize(font
, &rval
);
212 stat
= GdipGetFamily(font
, &family
);
214 stat
= GdipGetEmHeight(family
, FontStyleRegular
, &em_height
);
216 expect(2048, em_height
);
217 stat
= GdipGetLineSpacing(family
, FontStyleRegular
, &line_spacing
);
219 expect(2472, line_spacing
);
220 GdipDeleteFontFamily(family
);
222 GdipDeleteFont(font
);
224 GdipDeleteGraphics(graphics
);
228 static void test_fontfamily (void)
230 GpFontFamily
*family
, *clonedFontFamily
;
231 WCHAR itsName
[LF_FACESIZE
];
234 /* FontFamily cannot be NULL */
235 stat
= GdipCreateFontFamilyFromName (Tahoma
, NULL
, NULL
);
236 expect (InvalidParameter
, stat
);
238 /* FontFamily must be able to actually find the family.
239 * If it can't, any subsequent calls should fail.
241 stat
= GdipCreateFontFamilyFromName (nonexistent
, NULL
, &family
);
242 expect (FontFamilyNotFound
, stat
);
244 /* Bitmap fonts are not found */
245 stat
= GdipCreateFontFamilyFromName (MSSansSerif
, NULL
, &family
);
246 expect (FontFamilyNotFound
, stat
);
247 if(stat
== Ok
) GdipDeleteFontFamily(family
);
249 stat
= GdipCreateFontFamilyFromName (Tahoma
, NULL
, &family
);
252 stat
= GdipGetFamilyName (family
, itsName
, LANG_NEUTRAL
);
254 expect (0, lstrcmpiW(itsName
, Tahoma
));
258 /* Crashes on Windows XP SP2, Vista, and so Wine as well */
259 stat
= GdipGetFamilyName (family
, NULL
, LANG_NEUTRAL
);
263 /* Make sure we don't read old data */
264 ZeroMemory (itsName
, sizeof(itsName
));
265 stat
= GdipCloneFontFamily(family
, &clonedFontFamily
);
267 GdipDeleteFontFamily(family
);
268 stat
= GdipGetFamilyName(clonedFontFamily
, itsName
, LANG_NEUTRAL
);
270 expect(0, lstrcmpiW(itsName
, Tahoma
));
272 GdipDeleteFontFamily(clonedFontFamily
);
275 static void test_fontfamily_properties (void)
277 GpFontFamily
* FontFamily
= NULL
;
281 stat
= GdipCreateFontFamilyFromName(Tahoma
, NULL
, &FontFamily
);
284 stat
= GdipGetLineSpacing(FontFamily
, FontStyleRegular
, &result
);
286 ok (result
== 2472, "Expected 2472, got %d\n", result
);
288 stat
= GdipGetEmHeight(FontFamily
, FontStyleRegular
, &result
);
290 ok(result
== 2048, "Expected 2048, got %d\n", result
);
292 stat
= GdipGetCellAscent(FontFamily
, FontStyleRegular
, &result
);
294 ok(result
== 2049, "Expected 2049, got %d\n", result
);
296 stat
= GdipGetCellDescent(FontFamily
, FontStyleRegular
, &result
);
298 ok(result
== 423, "Expected 423, got %d\n", result
);
299 GdipDeleteFontFamily(FontFamily
);
301 stat
= GdipCreateFontFamilyFromName(TimesNewRoman
, NULL
, &FontFamily
);
302 if(stat
== FontFamilyNotFound
)
303 skip("Times New Roman not installed\n");
307 stat
= GdipGetLineSpacing(FontFamily
, FontStyleRegular
, &result
);
309 ok(result
== 2355, "Expected 2355, got %d\n", result
);
311 stat
= GdipGetEmHeight(FontFamily
, FontStyleRegular
, &result
);
313 ok(result
== 2048, "Expected 2048, got %d\n", result
);
315 stat
= GdipGetCellAscent(FontFamily
, FontStyleRegular
, &result
);
317 ok(result
== 1825, "Expected 1825, got %d\n", result
);
319 stat
= GdipGetCellDescent(FontFamily
, FontStyleRegular
, &result
);
321 ok(result
== 443, "Expected 443 got %d\n", result
);
322 GdipDeleteFontFamily(FontFamily
);
326 static void check_family(const char* context
, GpFontFamily
*family
, WCHAR
*name
)
332 stat
= GdipGetFamilyName(family
, name
, LANG_NEUTRAL
);
333 ok(stat
== Ok
, "could not get the %s family name: %.8x\n", context
, stat
);
335 stat
= GdipCreateFont(family
, 12, FontStyleRegular
, UnitPixel
, &font
);
336 ok(stat
== Ok
, "could not create a font for the %s family: %.8x\n", context
, stat
);
339 stat
= GdipDeleteFont(font
);
340 ok(stat
== Ok
, "could not delete the %s family font: %.8x\n", context
, stat
);
343 stat
= GdipDeleteFontFamily(family
);
344 ok(stat
== Ok
, "could not delete the %s family: %.8x\n", context
, stat
);
347 static void test_getgenerics (void)
350 GpFontFamily
*family
;
351 WCHAR sansname
[LF_FACESIZE
], serifname
[LF_FACESIZE
], mononame
[LF_FACESIZE
];
352 int missingfonts
= 0;
354 stat
= GdipGetGenericFontFamilySansSerif(&family
);
356 if (stat
== FontFamilyNotFound
)
359 check_family("Sans Serif", family
, sansname
);
361 stat
= GdipGetGenericFontFamilySerif(&family
);
363 if (stat
== FontFamilyNotFound
)
366 check_family("Serif", family
, serifname
);
368 stat
= GdipGetGenericFontFamilyMonospace(&family
);
370 if (stat
== FontFamilyNotFound
)
373 check_family("Monospace", family
, mononame
);
375 if (missingfonts
&& strcmp(winetest_platform
, "wine") == 0)
376 trace("You may need to install either the Microsoft Web Fonts or the Liberation Fonts\n");
378 /* Check that the family names are all different */
379 ok(lstrcmpiW(sansname
, serifname
) != 0, "Sans Serif and Serif families should be different: %s\n", wine_dbgstr_w(sansname
));
380 ok(lstrcmpiW(sansname
, mononame
) != 0, "Sans Serif and Monospace families should be different: %s\n", wine_dbgstr_w(sansname
));
381 ok(lstrcmpiW(serifname
, mononame
) != 0, "Serif and Monospace families should be different: %s\n", wine_dbgstr_w(serifname
));
384 static void test_installedfonts (void)
387 GpFontCollection
* collection
=NULL
;
389 stat
= GdipNewInstalledFontCollection(NULL
);
390 expect (InvalidParameter
, stat
);
392 stat
= GdipNewInstalledFontCollection(&collection
);
394 ok (collection
!= NULL
, "got NULL font collection\n");
397 static void test_heightgivendpi(void)
401 GpFontFamily
* fontfamily
= NULL
;
405 stat
= GdipCreateFontFamilyFromName(Tahoma
, NULL
, &fontfamily
);
408 stat
= GdipCreateFont(fontfamily
, 30, FontStyleRegular
, UnitPixel
, &font
);
411 stat
= GdipGetFontHeightGivenDPI(NULL
, 96, &height
);
412 expect(InvalidParameter
, stat
);
414 stat
= GdipGetFontHeightGivenDPI(font
, 96, NULL
);
415 expect(InvalidParameter
, stat
);
417 stat
= GdipGetFontHeightGivenDPI(font
, 96, &height
);
419 expectf(36.210938, height
);
420 GdipDeleteFont(font
);
423 stat
= GdipCreateFont(fontfamily
, 30, FontStyleRegular
, UnitWorld
, &font
);
426 stat
= GdipGetFontUnit(font
, &unit
);
428 expect(UnitWorld
, unit
);
430 stat
= GdipGetFontHeightGivenDPI(font
, 96, &height
);
432 expectf(36.210938, height
);
433 GdipDeleteFont(font
);
436 stat
= GdipCreateFont(fontfamily
, 30, FontStyleRegular
, UnitPoint
, &font
);
438 stat
= GdipGetFontHeightGivenDPI(font
, 96, &height
);
440 expectf(48.281250, height
);
441 GdipDeleteFont(font
);
444 stat
= GdipCreateFont(fontfamily
, 30, FontStyleRegular
, UnitInch
, &font
);
447 stat
= GdipGetFontUnit(font
, &unit
);
449 expect(UnitInch
, unit
);
451 stat
= GdipGetFontHeightGivenDPI(font
, 96, &height
);
453 expectf(3476.250000, height
);
454 GdipDeleteFont(font
);
457 stat
= GdipCreateFont(fontfamily
, 30, FontStyleRegular
, UnitDocument
, &font
);
460 stat
= GdipGetFontUnit(font
, &unit
);
462 expect(UnitDocument
, unit
);
464 stat
= GdipGetFontHeightGivenDPI(font
, 96, &height
);
466 expectf(11.587500, height
);
467 GdipDeleteFont(font
);
470 stat
= GdipCreateFont(fontfamily
, 30, FontStyleRegular
, UnitMillimeter
, &font
);
473 stat
= GdipGetFontUnit(font
, &unit
);
475 expect(UnitMillimeter
, unit
);
477 stat
= GdipGetFontHeightGivenDPI(font
, 96, &height
);
479 expectf(136.860245, height
);
480 GdipDeleteFont(font
);
482 GdipDeleteFontFamily(fontfamily
);
485 static int CALLBACK
font_enum_proc(const LOGFONTW
*lfe
, const TEXTMETRICW
*ntme
,
486 DWORD type
, LPARAM lparam
)
488 NEWTEXTMETRICW
*ntm
= (NEWTEXTMETRICW
*)lparam
;
490 if (type
!= TRUETYPE_FONTTYPE
) return 1;
492 *ntm
= *(NEWTEXTMETRICW
*)ntme
;
498 UINT16 em_height
, line_spacing
, ascent
, descent
;
499 REAL font_height
, font_size
;
503 static void gdi_get_font_metrics(LOGFONTW
*lf
, struct font_metrics
*fm
)
508 OUTLINETEXTMETRICW otm
;
511 hdc
= CreateCompatibleDC(0);
513 /* it's the only way to get extended NEWTEXTMETRIC fields */
514 ret
= EnumFontFamiliesExW(hdc
, lf
, font_enum_proc
, (LPARAM
)&ntm
, 0);
515 ok(!ret
, "EnumFontFamiliesExW failed to find %s\n", wine_dbgstr_w(lf
->lfFaceName
));
517 hfont
= CreateFontIndirectW(lf
);
518 SelectObject(hdc
, hfont
);
520 otm
.otmSize
= sizeof(otm
);
521 ret
= GetOutlineTextMetricsW(hdc
, otm
.otmSize
, &otm
);
522 ok(ret
, "GetOutlineTextMetrics failed\n");
527 fm
->lfHeight
= -otm
.otmTextMetrics
.tmAscent
;
528 fm
->line_spacing
= ntm
.ntmCellHeight
;
529 fm
->font_size
= (REAL
)otm
.otmTextMetrics
.tmAscent
;
530 fm
->font_height
= (REAL
)fm
->line_spacing
* fm
->font_size
/ (REAL
)ntm
.ntmSizeEM
;
531 fm
->em_height
= ntm
.ntmSizeEM
;
532 fm
->ascent
= ntm
.ntmSizeEM
;
533 fm
->descent
= ntm
.ntmCellHeight
- ntm
.ntmSizeEM
;
536 static void gdip_get_font_metrics(GpFont
*font
, struct font_metrics
*fm
)
539 GpFontFamily
*family
;
542 stat
= GdipGetFontStyle(font
, &style
);
545 stat
= GdipGetFontHeight(NULL
, NULL
, &fm
->font_height
);
546 expect(InvalidParameter
, stat
);
548 stat
= GdipGetFontHeight(font
, NULL
, NULL
);
549 expect(InvalidParameter
, stat
);
551 stat
= GdipGetFontHeight(font
, NULL
, &fm
->font_height
);
553 stat
= GdipGetFontSize(font
, &fm
->font_size
);
556 fm
->lfHeight
= (INT
)(fm
->font_size
* -1.0);
558 stat
= GdipGetFamily(font
, &family
);
561 stat
= GdipGetEmHeight(family
, style
, &fm
->em_height
);
563 stat
= GdipGetLineSpacing(family
, style
, &fm
->line_spacing
);
565 stat
= GdipGetCellAscent(family
, style
, &fm
->ascent
);
567 stat
= GdipGetCellDescent(family
, style
, &fm
->descent
);
570 GdipDeleteFontFamily(family
);
573 static void cmp_font_metrics(struct font_metrics
*fm1
, struct font_metrics
*fm2
, int line
)
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
);
588 static void test_font_metrics(void)
592 GpFontFamily
*family
;
593 GpGraphics
*graphics
;
596 struct font_metrics fm_gdi
, fm_gdip
;
599 hdc
= CreateCompatibleDC(0);
600 stat
= GdipCreateFromHDC(hdc
, &graphics
);
603 memset(&lf
, 0, sizeof(lf
));
606 lstrcpyW(lf
.lfFaceName
, Tahoma
);
608 stat
= GdipCreateFontFromLogfontW(hdc
, &lf
, &font
);
611 stat
= GdipGetFontUnit(font
, &unit
);
613 expect(UnitWorld
, unit
);
615 gdip_get_font_metrics(font
, &fm_gdip
);
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
);
622 gdi_get_font_metrics(&lf
, &fm_gdi
);
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
);
629 cmp_font_metrics(&fm_gdip
, &fm_gdi
, __LINE__
);
631 stat
= GdipGetLogFontW(font
, graphics
, &lf
);
633 ok(lf
.lfHeight
< 0, "lf.lfHeight should be negative, got %d\n", lf
.lfHeight
);
634 gdi_get_font_metrics(&lf
, &fm_gdi
);
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
);
642 cmp_font_metrics(&fm_gdip
, &fm_gdi
, __LINE__
);
644 GdipDeleteFont(font
);
647 lstrcpyW(lf
.lfFaceName
, Tahoma
);
649 stat
= GdipCreateFontFromLogfontW(hdc
, &lf
, &font
);
652 stat
= GdipGetFontUnit(font
, &unit
);
654 expect(UnitWorld
, unit
);
656 gdip_get_font_metrics(font
, &fm_gdip
);
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
);
663 gdi_get_font_metrics(&lf
, &fm_gdi
);
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
);
670 cmp_font_metrics(&fm_gdip
, &fm_gdi
, __LINE__
);
672 stat
= GdipGetLogFontW(font
, graphics
, &lf
);
674 ok(lf
.lfHeight
< 0, "lf.lfHeight should be negative, got %d\n", lf
.lfHeight
);
675 gdi_get_font_metrics(&lf
, &fm_gdi
);
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
);
683 cmp_font_metrics(&fm_gdip
, &fm_gdi
, __LINE__
);
685 GdipDeleteFont(font
);
687 stat
= GdipCreateFontFamilyFromName(Tahoma
, NULL
, &family
);
691 stat
= GdipCreateFont(family
, 13.0, FontStyleRegular
, UnitPixel
, &font
);
694 gdip_get_font_metrics(font
, &fm_gdip
);
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
);
701 stat
= GdipGetLogFontW(font
, graphics
, &lf
);
703 ok(lf
.lfHeight
< 0, "lf.lfHeight should be negative, got %d\n", lf
.lfHeight
);
704 gdi_get_font_metrics(&lf
, &fm_gdi
);
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
);
712 cmp_font_metrics(&fm_gdip
, &fm_gdi
, __LINE__
);
714 stat
= GdipGetLogFontW(font
, NULL
, &lf
);
715 expect(InvalidParameter
, stat
);
717 GdipDeleteFont(font
);
719 stat
= GdipCreateFont(family
, -13.0, FontStyleRegular
, UnitPixel
, &font
);
720 expect(InvalidParameter
, stat
);
722 GdipDeleteFontFamily(family
);
724 GdipDeleteGraphics(graphics
);
728 static void test_font_substitution(void)
730 WCHAR ms_shell_dlg
[LF_FACESIZE
];
731 char fallback_font
[LF_FACESIZE
];
736 GpGraphics
*graphics
;
738 GpFontFamily
*family
;
741 hdc
= CreateCompatibleDC(0);
742 status
= GdipCreateFromHDC(hdc
, &graphics
);
745 hfont
= GetStockObject(DEFAULT_GUI_FONT
);
746 ok(hfont
!= 0, "GetStockObject(DEFAULT_GUI_FONT) failed\n");
748 memset(&lf
, 0xfe, sizeof(lf
));
749 ret
= GetObjectA(hfont
, sizeof(lf
), &lf
);
750 ok(ret
== sizeof(lf
), "GetObject failed\n");
751 ok(!lstrcmpA(lf
.lfFaceName
, "MS Shell Dlg"), "wrong face name %s\n", lf
.lfFaceName
);
752 MultiByteToWideChar(CP_ACP
, 0, lf
.lfFaceName
, -1, ms_shell_dlg
, LF_FACESIZE
);
754 status
= GdipCreateFontFromLogfontA(hdc
, &lf
, &font
);
756 memset(&lf
, 0xfe, sizeof(lf
));
757 status
= GdipGetLogFontA(font
, graphics
, &lf
);
759 ok(!lstrcmpA(lf
.lfFaceName
, "Microsoft Sans Serif") ||
760 !lstrcmpA(lf
.lfFaceName
, "Tahoma"), "wrong face name %s\n", lf
.lfFaceName
);
761 GdipDeleteFont(font
);
763 status
= GdipCreateFontFamilyFromName(ms_shell_dlg
, NULL
, &family
);
765 status
= GdipCreateFont(family
, 12, FontStyleRegular
, UnitPoint
, &font
);
767 memset(&lf
, 0xfe, sizeof(lf
));
768 status
= GdipGetLogFontA(font
, graphics
, &lf
);
770 ok(!lstrcmpA(lf
.lfFaceName
, "Microsoft Sans Serif") ||
771 !lstrcmpA(lf
.lfFaceName
, "Tahoma"), "wrong face name %s\n", lf
.lfFaceName
);
772 GdipDeleteFont(font
);
773 GdipDeleteFontFamily(family
);
775 status
= GdipCreateFontFamilyFromName(nonexistent
, NULL
, &family
);
776 ok(status
== FontFamilyNotFound
, "expected FontFamilyNotFound, got %d\n", status
);
778 /* nonexistent fonts fallback to Arial, or something else if it's missing */
779 strcpy(lf
.lfFaceName
,"Arial");
780 status
= GdipCreateFontFromLogfontA(hdc
, &lf
, &font
);
782 status
= GdipGetLogFontA(font
, graphics
, &lf
);
784 strcpy(fallback_font
,lf
.lfFaceName
);
785 trace("fallback font %s\n", fallback_font
);
786 GdipDeleteFont(font
);
788 lstrcpyA(lf
.lfFaceName
, "ThisFontShouldNotExist");
789 status
= GdipCreateFontFromLogfontA(hdc
, &lf
, &font
);
791 memset(&lf
, 0xfe, sizeof(lf
));
792 status
= GdipGetLogFontA(font
, graphics
, &lf
);
794 ok(!lstrcmpA(lf
.lfFaceName
, fallback_font
), "wrong face name %s / %s\n", lf
.lfFaceName
, fallback_font
);
795 GdipDeleteFont(font
);
798 lf
.lfFaceName
[0] = 0;
799 status
= GdipCreateFontFromLogfontA(hdc
, &lf
, &font
);
801 memset(&lf
, 0xfe, sizeof(lf
));
802 status
= GdipGetLogFontA(font
, graphics
, &lf
);
804 ok(!lstrcmpA(lf
.lfFaceName
, fallback_font
), "wrong face name %s / %s\n", lf
.lfFaceName
, fallback_font
);
805 GdipDeleteFont(font
);
807 /* zeroing out lfWeight and lfCharSet leads to font creation failure */
810 lstrcpyA(lf
.lfFaceName
, "ThisFontShouldNotExist");
812 status
= GdipCreateFontFromLogfontA(hdc
, &lf
, &font
);
814 ok(status
== NotTrueTypeFont
|| broken(status
== FileNotFound
), /* before XP */
815 "expected NotTrueTypeFont, got %d\n", status
);
816 /* FIXME: remove when wine is fixed */
817 if (font
) GdipDeleteFont(font
);
820 lf
.lfFaceName
[0] = 0;
822 status
= GdipCreateFontFromLogfontA(hdc
, &lf
, &font
);
824 ok(status
== NotTrueTypeFont
|| broken(status
== FileNotFound
), /* before XP */
825 "expected NotTrueTypeFont, got %d\n", status
);
826 /* FIXME: remove when wine is fixed */
827 if (font
) GdipDeleteFont(font
);
829 GdipDeleteGraphics(graphics
);
833 static void test_font_transform(void)
835 static const WCHAR string
[] = { 'A',0 };
840 GpGraphics
*graphics
;
842 GpStringFormat
*format
, *typographic
;
843 PointF pos
[1] = { { 0,0 } };
844 REAL height
, margin_y
;
847 hdc
= CreateCompatibleDC(0);
848 status
= GdipCreateFromHDC(hdc
, &graphics
);
851 status
= GdipSetPageUnit(graphics
, UnitPixel
);
854 status
= GdipCreateStringFormat(0, LANG_NEUTRAL
, &format
);
856 status
= GdipStringFormatGetGenericTypographic(&typographic
);
859 memset(&lf
, 0, sizeof(lf
));
860 lstrcpyA(lf
.lfFaceName
, "Tahoma");
863 status
= GdipCreateFontFromLogfontA(hdc
, &lf
, &font
);
866 margin_y
= 100.0 / 8.0;
868 /* identity matrix */
869 status
= GdipCreateMatrix(&matrix
);
871 status
= GdipSetWorldTransform(graphics
, matrix
);
873 status
= GdipGetLogFontA(font
, graphics
, &lf
);
875 expect(-100, lf
.lfHeight
);
876 expect(0, lf
.lfWidth
);
877 expect(0, lf
.lfEscapement
);
878 expect(0, lf
.lfOrientation
);
879 status
= GdipGetFontHeight(font
, graphics
, &height
);
881 expectf(120.703125, height
);
882 set_rect_empty(&rect
);
883 set_rect_empty(&bounds
);
884 status
= GdipMeasureString(graphics
, string
, -1, font
, &rect
, format
, &bounds
, NULL
, NULL
);
886 expectf(0.0, bounds
.X
);
887 expectf(0.0, bounds
.Y
);
889 expectf(height
+ margin_y
, bounds
.Height
);
890 set_rect_empty(&rect
);
891 set_rect_empty(&bounds
);
892 status
= GdipMeasureString(graphics
, string
, -1, font
, &rect
, typographic
, &bounds
, NULL
, NULL
);
894 expectf(0.0, bounds
.X
);
895 expectf(0.0, bounds
.Y
);
896 expectf_(height
, bounds
.Height
, 1.0);
897 set_rect_empty(&bounds
);
898 status
= GdipMeasureDriverString(graphics
, (const UINT16
*)string
, -1, font
, pos
,
899 DriverStringOptionsCmapLookup
, NULL
, &bounds
);
901 expectf(0.0, bounds
.X
);
902 expectf_(-100.0, bounds
.Y
, 0.05);
903 expectf_(height
, bounds
.Height
, 0.5);
904 set_rect_empty(&bounds
);
905 status
= GdipMeasureDriverString(graphics
, (const UINT16
*)string
, -1, font
, pos
,
906 DriverStringOptionsCmapLookup
, matrix
, &bounds
);
908 expectf(0.0, bounds
.X
);
909 expectf_(-100.0, bounds
.Y
, 0.05);
910 expectf_(height
, bounds
.Height
, 0.5);
913 status
= GdipScaleMatrix(matrix
, 2.0, 3.0, MatrixOrderAppend
);
915 status
= GdipSetWorldTransform(graphics
, matrix
);
917 status
= GdipGetLogFontA(font
, graphics
, &lf
);
919 expect(-300, lf
.lfHeight
);
920 expect(0, lf
.lfWidth
);
921 expect(0, lf
.lfEscapement
);
922 expect(0, lf
.lfOrientation
);
923 status
= GdipGetFontHeight(font
, graphics
, &height
);
925 expectf(120.703125, height
);
926 set_rect_empty(&rect
);
927 set_rect_empty(&bounds
);
928 status
= GdipMeasureString(graphics
, string
, -1, font
, &rect
, format
, &bounds
, NULL
, NULL
);
930 expectf(0.0, bounds
.X
);
931 expectf(0.0, bounds
.Y
);
933 expectf(height
+ margin_y
, bounds
.Height
);
934 set_rect_empty(&rect
);
935 set_rect_empty(&bounds
);
936 status
= GdipMeasureString(graphics
, string
, -1, font
, &rect
, typographic
, &bounds
, NULL
, NULL
);
938 expectf(0.0, bounds
.X
);
939 expectf(0.0, bounds
.Y
);
940 expectf_(height
, bounds
.Height
, 0.05);
941 set_rect_empty(&bounds
);
942 status
= GdipMeasureDriverString(graphics
, (const UINT16
*)string
, -1, font
, pos
,
943 DriverStringOptionsCmapLookup
, NULL
, &bounds
);
945 expectf(0.0, bounds
.X
);
946 expectf_(-100.0, bounds
.Y
, 0.05);
947 expectf_(height
, bounds
.Height
, 0.2);
948 set_rect_empty(&bounds
);
949 status
= GdipMeasureDriverString(graphics
, (const UINT16
*)string
, -1, font
, pos
,
950 DriverStringOptionsCmapLookup
, matrix
, &bounds
);
952 expectf(0.0, bounds
.X
);
954 expectf_(-300.0, bounds
.Y
, 0.15);
956 expectf(height
* 3.0, bounds
.Height
);
958 /* scale + ratate matrix */
959 status
= GdipRotateMatrix(matrix
, 45.0, MatrixOrderAppend
);
961 status
= GdipSetWorldTransform(graphics
, matrix
);
963 status
= GdipGetLogFontA(font
, graphics
, &lf
);
965 expect(-300, lf
.lfHeight
);
966 expect(0, lf
.lfWidth
);
967 expect_(3151, lf
.lfEscapement
, 1);
968 expect_(3151, lf
.lfOrientation
, 1);
969 status
= GdipGetFontHeight(font
, graphics
, &height
);
971 expectf(120.703125, height
);
972 set_rect_empty(&rect
);
973 set_rect_empty(&bounds
);
974 status
= GdipMeasureString(graphics
, string
, -1, font
, &rect
, format
, &bounds
, NULL
, NULL
);
976 expectf(0.0, bounds
.X
);
977 expectf(0.0, bounds
.Y
);
979 expectf(height
+ margin_y
, bounds
.Height
);
980 set_rect_empty(&rect
);
981 set_rect_empty(&bounds
);
982 status
= GdipMeasureString(graphics
, string
, -1, font
, &rect
, typographic
, &bounds
, NULL
, NULL
);
984 expectf(0.0, bounds
.X
);
985 expectf(0.0, bounds
.Y
);
986 expectf_(height
, bounds
.Height
, 0.05);
987 set_rect_empty(&bounds
);
988 status
= GdipMeasureDriverString(graphics
, (const UINT16
*)string
, -1, font
, pos
,
989 DriverStringOptionsCmapLookup
, NULL
, &bounds
);
991 expectf(0.0, bounds
.X
);
992 expectf_(-100.0, bounds
.Y
, 0.05);
993 expectf_(height
, bounds
.Height
, 0.2);
994 set_rect_empty(&bounds
);
995 status
= GdipMeasureDriverString(graphics
, (const UINT16
*)string
, -1, font
, pos
,
996 DriverStringOptionsCmapLookup
, matrix
, &bounds
);
999 expectf_(-43.814377, bounds
.X
, 0.05);
1001 expectf_(-212.235611, bounds
.Y
, 0.05);
1003 expectf_(340.847534, bounds
.Height
, 0.05);
1005 /* scale + ratate + shear matrix */
1006 status
= GdipShearMatrix(matrix
, 4.0, 5.0, MatrixOrderAppend
);
1008 status
= GdipSetWorldTransform(graphics
, matrix
);
1010 status
= GdipGetLogFontA(font
, graphics
, &lf
);
1013 expect(1032, lf
.lfHeight
);
1014 expect(0, lf
.lfWidth
);
1015 expect_(3099, lf
.lfEscapement
, 1);
1016 expect_(3099, lf
.lfOrientation
, 1);
1017 status
= GdipGetFontHeight(font
, graphics
, &height
);
1019 expectf(120.703125, height
);
1020 set_rect_empty(&rect
);
1021 set_rect_empty(&bounds
);
1022 status
= GdipMeasureString(graphics
, string
, -1, font
, &rect
, format
, &bounds
, NULL
, NULL
);
1024 expectf(0.0, bounds
.X
);
1025 expectf(0.0, bounds
.Y
);
1027 expectf(height
+ margin_y
, bounds
.Height
);
1028 set_rect_empty(&rect
);
1029 set_rect_empty(&bounds
);
1030 status
= GdipMeasureString(graphics
, string
, -1, font
, &rect
, typographic
, &bounds
, NULL
, NULL
);
1032 expectf(0.0, bounds
.X
);
1033 expectf(0.0, bounds
.Y
);
1034 expectf_(height
, bounds
.Height
, 0.2);
1035 set_rect_empty(&bounds
);
1036 status
= GdipMeasureDriverString(graphics
, (const UINT16
*)string
, -1, font
, pos
,
1037 DriverStringOptionsCmapLookup
, NULL
, &bounds
);
1039 expectf(0.0, bounds
.X
);
1040 expectf_(-100.0, bounds
.Y
, 0.2);
1041 expectf_(height
, bounds
.Height
, 0.2);
1042 set_rect_empty(&bounds
);
1043 status
= GdipMeasureDriverString(graphics
, (const UINT16
*)string
, -1, font
, pos
,
1044 DriverStringOptionsCmapLookup
, matrix
, &bounds
);
1047 expectf_(-636.706848, bounds
.X
, 0.05);
1049 expectf_(-175.257523, bounds
.Y
, 0.05);
1051 expectf_(1532.984985, bounds
.Height
, 0.05);
1053 /* scale + ratate + shear + translate matrix */
1054 status
= GdipTranslateMatrix(matrix
, 10.0, 20.0, MatrixOrderAppend
);
1056 status
= GdipSetWorldTransform(graphics
, matrix
);
1058 status
= GdipGetLogFontA(font
, graphics
, &lf
);
1061 expect(1032, lf
.lfHeight
);
1062 expect(0, lf
.lfWidth
);
1063 expect_(3099, lf
.lfEscapement
, 1);
1064 expect_(3099, lf
.lfOrientation
, 1);
1065 status
= GdipGetFontHeight(font
, graphics
, &height
);
1067 expectf(120.703125, height
);
1068 set_rect_empty(&rect
);
1069 set_rect_empty(&bounds
);
1070 status
= GdipMeasureString(graphics
, string
, -1, font
, &rect
, format
, &bounds
, NULL
, NULL
);
1072 expectf(0.0, bounds
.X
);
1073 expectf(0.0, bounds
.Y
);
1075 expectf(height
+ margin_y
, bounds
.Height
);
1076 set_rect_empty(&rect
);
1077 set_rect_empty(&bounds
);
1078 status
= GdipMeasureString(graphics
, string
, -1, font
, &rect
, typographic
, &bounds
, NULL
, NULL
);
1080 expectf(0.0, bounds
.X
);
1081 expectf(0.0, bounds
.Y
);
1082 expectf_(height
, bounds
.Height
, 0.1);
1083 set_rect_empty(&bounds
);
1084 status
= GdipMeasureDriverString(graphics
, (const UINT16
*)string
, -1, font
, pos
,
1085 DriverStringOptionsCmapLookup
, NULL
, &bounds
);
1087 expectf(0.0, bounds
.X
);
1088 expectf_(-100.0, bounds
.Y
, 0.2);
1089 expectf_(height
, bounds
.Height
, 0.2);
1090 set_rect_empty(&bounds
);
1091 status
= GdipMeasureDriverString(graphics
, (const UINT16
*)string
, -1, font
, pos
,
1092 DriverStringOptionsCmapLookup
, matrix
, &bounds
);
1095 expectf_(-626.706848, bounds
.X
, 0.05);
1097 expectf_(-155.257523, bounds
.Y
, 0.05);
1099 expectf_(1532.984985, bounds
.Height
, 0.05);
1101 GdipDeleteMatrix(matrix
);
1102 GdipDeleteFont(font
);
1103 GdipDeleteGraphics(graphics
);
1104 GdipDeleteStringFormat(typographic
);
1105 GdipDeleteStringFormat(format
);
1111 struct GdiplusStartupInput gdiplusStartupInput
;
1112 ULONG_PTR gdiplusToken
;
1114 int (CDECL
* _controlfp_s
)(unsigned int *cur
, unsigned int newval
, unsigned int mask
);
1116 /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
1117 hmsvcrt
= LoadLibraryA("msvcrt");
1118 _controlfp_s
= (void*)GetProcAddress(hmsvcrt
, "_controlfp_s");
1119 if (_controlfp_s
) _controlfp_s(0, 0, 0x0008001e);
1121 gdiplusStartupInput
.GdiplusVersion
= 1;
1122 gdiplusStartupInput
.DebugEventCallback
= NULL
;
1123 gdiplusStartupInput
.SuppressBackgroundThread
= 0;
1124 gdiplusStartupInput
.SuppressExternalCodecs
= 0;
1126 GdiplusStartup(&gdiplusToken
, &gdiplusStartupInput
, NULL
);
1128 test_font_transform();
1129 if (!winetest_interactive
)
1130 skip("ROSTESTS-154: Skipping test_font_substitution because of improper error handling\n");
1132 test_font_substitution();
1133 test_font_metrics();
1137 test_fontfamily_properties();
1139 test_installedfonts();
1140 test_heightgivendpi();
1142 GdiplusShutdown(gdiplusToken
);