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