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