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 } 1275