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