ScaledFontDWrite.cpp (22125B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "ScaledFontDWrite.h" 8 #include "gfxDWriteCommon.h" 9 #include "UnscaledFontDWrite.h" 10 #include "gfxFont.h" 11 #include "Logging.h" 12 #include "mozilla/FontPropertyTypes.h" 13 #include "mozilla/webrender/WebRenderTypes.h" 14 #include "StackArray.h" 15 16 #include "dwrite_3.h" 17 18 #include "PathSkia.h" 19 #include "skia/include/core/SkPaint.h" 20 #include "skia/include/core/SkPath.h" 21 #include "skia/include/ports/SkTypeface_win.h" 22 23 #include <vector> 24 25 #include "cairo-dwrite.h" 26 27 #include "HelpersWinFonts.h" 28 29 namespace mozilla { 30 namespace gfx { 31 32 #define GASP_TAG 0x70736167 33 #define GASP_DOGRAY 0x2 34 35 static inline unsigned short readShort(const char* aBuf) { 36 return (*aBuf << 8) | *(aBuf + 1); 37 } 38 39 static bool DoGrayscale(IDWriteFontFace* aDWFace, Float ppem) { 40 void* tableContext; 41 char* tableData; 42 UINT32 tableSize; 43 BOOL exists; 44 aDWFace->TryGetFontTable(GASP_TAG, (const void**)&tableData, &tableSize, 45 &tableContext, &exists); 46 47 if (exists) { 48 if (tableSize < 4) { 49 aDWFace->ReleaseFontTable(tableContext); 50 return true; 51 } 52 struct gaspRange { 53 unsigned short maxPPEM; // Stored big-endian 54 unsigned short behavior; // Stored big-endian 55 }; 56 unsigned short numRanges = readShort(tableData + 2); 57 if (tableSize < (UINT)4 + numRanges * 4) { 58 aDWFace->ReleaseFontTable(tableContext); 59 return true; 60 } 61 gaspRange* ranges = (gaspRange*)(tableData + 4); 62 for (int i = 0; i < numRanges; i++) { 63 if (readShort((char*)&ranges[i].maxPPEM) >= ppem) { 64 if (!(readShort((char*)&ranges[i].behavior) & GASP_DOGRAY)) { 65 aDWFace->ReleaseFontTable(tableContext); 66 return false; 67 } 68 break; 69 } 70 } 71 aDWFace->ReleaseFontTable(tableContext); 72 } 73 return true; 74 } 75 76 ScaledFontDWrite::ScaledFontDWrite(IDWriteFontFace* aFontFace, 77 const RefPtr<UnscaledFont>& aUnscaledFont, 78 Float aSize, bool aUseEmbeddedBitmap, 79 bool aUseMultistrikeBold, bool aGDIForced, 80 const gfxFontStyle* aStyle) 81 : ScaledFontBase(aUnscaledFont, aSize), 82 mFontFace(aFontFace), 83 mUseEmbeddedBitmap(aUseEmbeddedBitmap), 84 mUseMultistrikeBold(aUseMultistrikeBold), 85 mGDIForced(aGDIForced) { 86 if (aStyle) { 87 mStyle = SkFontStyle(aStyle->weight.ToIntRounded(), 88 DWriteFontStretchFromStretch(aStyle->stretch), 89 // FIXME(jwatt): also use kOblique_Slant 90 aStyle->style == FontSlantStyle::NORMAL 91 ? SkFontStyle::kUpright_Slant 92 : SkFontStyle::kItalic_Slant); 93 } 94 } 95 96 SkTypeface* ScaledFontDWrite::CreateSkTypeface() { 97 RefPtr<IDWriteFactory> factory = Factory::GetDWriteFactory(); 98 if (!factory) { 99 return nullptr; 100 } 101 102 auto& settings = DWriteSettings(); 103 Float gamma = settings.Gamma(); 104 // Skia doesn't support a gamma value outside of 0-4, so default to 2.2 105 if (gamma < 0.0f || gamma > 4.0f) { 106 gamma = 2.2f; 107 } 108 109 Float contrast = settings.EnhancedContrast(); 110 // Skia doesn't support a contrast value outside of 0-1, so default to 1.0 111 if (contrast < 0.0f || contrast > 1.0f) { 112 contrast = 1.0f; 113 } 114 115 Float clearTypeLevel = settings.ClearTypeLevel(); 116 if (clearTypeLevel < 0.0f || clearTypeLevel > 1.0f) { 117 clearTypeLevel = 1.0f; 118 } 119 120 IDWriteFont* font = 121 static_cast<UnscaledFontDWrite*>(mUnscaledFont.get())->GetFont(); 122 RefPtr<IDWriteFontFamily> family; 123 if (font) { 124 font->GetFontFamily(getter_AddRefs(family)); 125 } 126 return SkCreateTypefaceFromDWriteFont(factory, mFontFace, font, family, 127 mStyle, (int)settings.RenderingMode(), 128 gamma, contrast, clearTypeLevel); 129 } 130 131 void ScaledFontDWrite::SetupSkFontDrawOptions(SkFont& aFont) { 132 if (ForceGDIMode()) { 133 aFont.setEmbeddedBitmaps(true); 134 aFont.setSubpixel(false); 135 } else { 136 aFont.setEmbeddedBitmaps(UseEmbeddedBitmaps()); 137 aFont.setSubpixel(true); 138 } 139 } 140 141 bool ScaledFontDWrite::MayUseBitmaps() { 142 return ForceGDIMode() || UseEmbeddedBitmaps(); 143 } 144 145 bool UnscaledFontDWrite::GetFontFileData(FontFileDataOutput aDataCallback, 146 void* aBaton) { 147 UINT32 fileCount = 0; 148 HRESULT hr = mFontFace->GetFiles(&fileCount, nullptr); 149 150 if (FAILED(hr) || fileCount > 1) { 151 MOZ_ASSERT(false); 152 return false; 153 } 154 155 if (!aDataCallback) { 156 return true; 157 } 158 159 RefPtr<IDWriteFontFile> file; 160 hr = mFontFace->GetFiles(&fileCount, getter_AddRefs(file)); 161 if (FAILED(hr)) { 162 return false; 163 } 164 165 const void* referenceKey; 166 UINT32 refKeySize; 167 // XXX - This can currently crash for webfonts, as when we get the reference 168 // key out of the file, that can be an invalid reference key for the loader 169 // we use it with. The fix to this is not obvious but it will probably 170 // have to happen inside thebes. 171 hr = file->GetReferenceKey(&referenceKey, &refKeySize); 172 if (FAILED(hr)) { 173 return false; 174 } 175 176 RefPtr<IDWriteFontFileLoader> loader; 177 hr = file->GetLoader(getter_AddRefs(loader)); 178 if (FAILED(hr)) { 179 return false; 180 } 181 182 RefPtr<IDWriteFontFileStream> stream; 183 hr = loader->CreateStreamFromKey(referenceKey, refKeySize, 184 getter_AddRefs(stream)); 185 if (FAILED(hr)) { 186 return false; 187 } 188 189 UINT64 fileSize64; 190 hr = stream->GetFileSize(&fileSize64); 191 if (FAILED(hr) || fileSize64 > UINT32_MAX) { 192 MOZ_ASSERT(false); 193 return false; 194 } 195 196 // Try to catch any device memory exceptions that may occur while attempting 197 // to read the file fragment. 198 void* context = nullptr; 199 hr = E_FAIL; 200 MOZ_SEH_TRY { 201 uint32_t fileSize = static_cast<uint32_t>(fileSize64); 202 const void* fragmentStart = nullptr; 203 hr = stream->ReadFileFragment(&fragmentStart, 0, fileSize, &context); 204 if (SUCCEEDED(hr)) { 205 aDataCallback((uint8_t*)fragmentStart, fileSize, mFontFace->GetIndex(), 206 aBaton); 207 } 208 } 209 MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { 210 gfxCriticalNote << "Exception occurred reading DWrite font file data"; 211 } 212 if (FAILED(hr)) { 213 return false; 214 } 215 stream->ReleaseFileFragment(context); 216 return true; 217 } 218 219 static bool GetFontFileName(RefPtr<IDWriteFontFace> aFontFace, 220 std::vector<WCHAR>& aFileName) { 221 UINT32 numFiles; 222 HRESULT hr = aFontFace->GetFiles(&numFiles, nullptr); 223 if (FAILED(hr)) { 224 gfxDebug() << "Failed getting file count for WR font"; 225 return false; 226 } else if (numFiles != 1) { 227 gfxDebug() << "Invalid file count " << numFiles << " for WR font"; 228 return false; 229 } 230 231 RefPtr<IDWriteFontFile> file; 232 hr = aFontFace->GetFiles(&numFiles, getter_AddRefs(file)); 233 if (FAILED(hr)) { 234 gfxDebug() << "Failed getting file for WR font"; 235 return false; 236 } 237 238 const void* key; 239 UINT32 keySize; 240 hr = file->GetReferenceKey(&key, &keySize); 241 if (FAILED(hr)) { 242 gfxDebug() << "Failed getting file ref key for WR font"; 243 return false; 244 } 245 RefPtr<IDWriteFontFileLoader> loader; 246 hr = file->GetLoader(getter_AddRefs(loader)); 247 if (FAILED(hr)) { 248 gfxDebug() << "Failed getting file loader for WR font"; 249 return false; 250 } 251 RefPtr<IDWriteLocalFontFileLoader> localLoader; 252 loader->QueryInterface(__uuidof(IDWriteLocalFontFileLoader), 253 (void**)getter_AddRefs(localLoader)); 254 if (!localLoader) { 255 gfxDebug() << "Failed querying loader interface for WR font"; 256 return false; 257 } 258 UINT32 pathLen; 259 hr = localLoader->GetFilePathLengthFromKey(key, keySize, &pathLen); 260 if (FAILED(hr)) { 261 gfxDebug() << "Failed getting path length for WR font"; 262 return false; 263 } 264 aFileName.resize(pathLen + 1); 265 hr = localLoader->GetFilePathFromKey(key, keySize, aFileName.data(), 266 pathLen + 1); 267 if (FAILED(hr) || aFileName.back() != 0) { 268 gfxDebug() << "Failed getting path for WR font"; 269 return false; 270 } 271 272 // We leave the null terminator at the end of the returned file name. 273 return true; 274 } 275 276 bool UnscaledFontDWrite::GetFontDescriptor(FontDescriptorOutput aCb, 277 void* aBaton) { 278 MOZ_ASSERT(NS_IsMainThread()); 279 280 if (!mFont) { 281 return false; 282 } 283 284 // We cache the font file name as it involves multiple DirectWrite calls. 285 if (mFontFileName.empty()) { 286 if (!GetFontFileName(mFontFace, mFontFileName)) { 287 return false; 288 } 289 } 290 uint32_t index = mFontFace->GetIndex(); 291 292 aCb(reinterpret_cast<const uint8_t*>(mFontFileName.data()), 293 mFontFileName.size() * sizeof(WCHAR), index, aBaton); 294 return true; 295 } 296 297 ScaledFontDWrite::InstanceData::InstanceData( 298 const wr::FontInstanceOptions* aOptions, 299 const wr::FontInstancePlatformOptions* aPlatformOptions) { 300 if (aOptions) { 301 if (aOptions->flags & wr::FontInstanceFlags::EMBEDDED_BITMAPS) { 302 mUseEmbeddedBitmap = true; 303 } 304 if (aOptions->flags & wr::FontInstanceFlags::SYNTHETIC_BOLD) { 305 mUseBoldSimulation = true; 306 } 307 if (aOptions->flags & wr::FontInstanceFlags::MULTISTRIKE_BOLD) { 308 mUseMultistrikeBold = true; 309 } 310 if (aOptions->flags & wr::FontInstanceFlags::FORCE_GDI) { 311 mGDIForced = true; 312 } 313 } 314 } 315 316 bool ScaledFontDWrite::HasVariationSettings() { 317 RefPtr<IDWriteFontFace5> ff5; 318 mFontFace->QueryInterface(__uuidof(IDWriteFontFace5), 319 (void**)getter_AddRefs(ff5)); 320 if (!ff5 || !ff5->HasVariations()) { 321 return false; 322 } 323 324 uint32_t count = ff5->GetFontAxisValueCount(); 325 if (!count) { 326 return false; 327 } 328 329 RefPtr<IDWriteFontResource> res; 330 if (FAILED(ff5->GetFontResource(getter_AddRefs(res)))) { 331 return false; 332 } 333 334 std::vector<DWRITE_FONT_AXIS_VALUE> defaults(count); 335 if (FAILED(res->GetDefaultFontAxisValues(defaults.data(), count))) { 336 return false; 337 } 338 339 std::vector<DWRITE_FONT_AXIS_VALUE> values(count); 340 if (FAILED(ff5->GetFontAxisValues(values.data(), count))) { 341 return false; 342 } 343 344 for (uint32_t i = 0; i < count; i++) { 345 DWRITE_FONT_AXIS_ATTRIBUTES attr = res->GetFontAxisAttributes(i); 346 if (attr & DWRITE_FONT_AXIS_ATTRIBUTES_VARIABLE) { 347 if (values[i].value != defaults[i].value) { 348 return true; 349 } 350 } 351 } 352 353 return false; 354 } 355 356 // Helper for ScaledFontDWrite::GetFontInstanceData: if the font has variation 357 // axes, get their current values into the aOutput vector. 358 static void GetVariationsFromFontFace(IDWriteFontFace* aFace, 359 std::vector<FontVariation>* aOutput) { 360 RefPtr<IDWriteFontFace5> ff5; 361 aFace->QueryInterface(__uuidof(IDWriteFontFace5), 362 (void**)getter_AddRefs(ff5)); 363 if (!ff5 || !ff5->HasVariations()) { 364 return; 365 } 366 367 uint32_t count = ff5->GetFontAxisValueCount(); 368 if (!count) { 369 return; 370 } 371 372 RefPtr<IDWriteFontResource> res; 373 if (FAILED(ff5->GetFontResource(getter_AddRefs(res)))) { 374 return; 375 } 376 377 std::vector<DWRITE_FONT_AXIS_VALUE> values(count); 378 if (FAILED(ff5->GetFontAxisValues(values.data(), count))) { 379 return; 380 } 381 382 aOutput->reserve(count); 383 for (uint32_t i = 0; i < count; i++) { 384 DWRITE_FONT_AXIS_ATTRIBUTES attr = res->GetFontAxisAttributes(i); 385 if (attr & DWRITE_FONT_AXIS_ATTRIBUTES_VARIABLE) { 386 float v = values[i].value; 387 uint32_t t = TRUETYPE_TAG( 388 uint8_t(values[i].axisTag), uint8_t(values[i].axisTag >> 8), 389 uint8_t(values[i].axisTag >> 16), uint8_t(values[i].axisTag >> 24)); 390 aOutput->push_back(FontVariation{uint32_t(t), float(v)}); 391 } 392 } 393 } 394 395 bool ScaledFontDWrite::GetFontInstanceData(FontInstanceDataOutput aCb, 396 void* aBaton) { 397 InstanceData instance(this); 398 399 // If the font has variations, get the list of axis values. 400 std::vector<FontVariation> variations; 401 GetVariationsFromFontFace(mFontFace, &variations); 402 403 aCb(reinterpret_cast<uint8_t*>(&instance), sizeof(instance), 404 variations.data(), variations.size(), aBaton); 405 406 return true; 407 } 408 409 bool ScaledFontDWrite::GetWRFontInstanceOptions( 410 Maybe<wr::FontInstanceOptions>* aOutOptions, 411 Maybe<wr::FontInstancePlatformOptions>* aOutPlatformOptions, 412 std::vector<FontVariation>* aOutVariations) { 413 wr::FontInstanceOptions options = {}; 414 options.render_mode = wr::ToFontRenderMode(GetDefaultAAMode()); 415 options.flags = wr::FontInstanceFlags{0}; 416 if (HasBoldSimulation()) { 417 options.flags |= wr::FontInstanceFlags::SYNTHETIC_BOLD; 418 } 419 if (UseMultistrikeBold()) { 420 options.flags |= wr::FontInstanceFlags::MULTISTRIKE_BOLD; 421 } 422 if (UseEmbeddedBitmaps()) { 423 options.flags |= wr::FontInstanceFlags::EMBEDDED_BITMAPS; 424 } 425 if (ForceGDIMode()) { 426 options.flags |= wr::FontInstanceFlags::FORCE_GDI; 427 } else { 428 options.flags |= wr::FontInstanceFlags::SUBPIXEL_POSITION; 429 } 430 auto& settings = DWriteSettings(); 431 switch (settings.RenderingMode()) { 432 case DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC: 433 options.flags |= wr::FontInstanceFlags::FORCE_SYMMETRIC; 434 break; 435 case DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL: 436 options.flags |= wr::FontInstanceFlags::NO_SYMMETRIC; 437 break; 438 default: 439 break; 440 } 441 if (Factory::GetSubpixelOrder() == SubpixelOrder::BGR) { 442 options.flags |= wr::FontInstanceFlags::SUBPIXEL_BGR; 443 } 444 options.synthetic_italics = 445 wr::DegreesToSyntheticItalics(GetSyntheticObliqueAngle()); 446 447 wr::FontInstancePlatformOptions platformOptions; 448 platformOptions.gamma = uint16_t(std::round(settings.Gamma() * 100.0f)); 449 platformOptions.contrast = 450 uint8_t(std::round(std::min(settings.EnhancedContrast(), 1.0f) * 100.0f)); 451 platformOptions.cleartype_level = 452 uint8_t(std::round(std::min(settings.ClearTypeLevel(), 1.0f) * 100.0f)); 453 454 *aOutOptions = Some(options); 455 *aOutPlatformOptions = Some(platformOptions); 456 457 GetVariationsFromFontFace(mFontFace, aOutVariations); 458 459 return true; 460 } 461 462 DWriteSettings& ScaledFontDWrite::DWriteSettings() const { 463 return DWriteSettings::Get(mGDIForced); 464 } 465 466 // Helper for UnscaledFontDWrite::CreateScaledFont: create a clone of the 467 // given IDWriteFontFace, with specified variation-axis values applied. 468 // Returns nullptr in case of failure. 469 static already_AddRefed<IDWriteFontFace5> CreateFaceWithVariations( 470 IDWriteFontFace* aFace, DWRITE_FONT_SIMULATIONS aSimulations, 471 const FontVariation* aVariations = nullptr, uint32_t aNumVariations = 0) { 472 auto makeDWriteAxisTag = [](uint32_t aTag) { 473 return DWRITE_MAKE_FONT_AXIS_TAG((aTag >> 24) & 0xff, (aTag >> 16) & 0xff, 474 (aTag >> 8) & 0xff, aTag & 0xff); 475 }; 476 477 MOZ_SEH_TRY { 478 RefPtr<IDWriteFontFace5> ff5; 479 aFace->QueryInterface(__uuidof(IDWriteFontFace5), 480 (void**)getter_AddRefs(ff5)); 481 if (!ff5) { 482 return nullptr; 483 } 484 485 RefPtr<IDWriteFontResource> res; 486 if (FAILED(ff5->GetFontResource(getter_AddRefs(res)))) { 487 return nullptr; 488 } 489 490 std::vector<DWRITE_FONT_AXIS_VALUE> fontAxisValues; 491 if (aNumVariations) { 492 fontAxisValues.reserve(aNumVariations); 493 for (uint32_t i = 0; i < aNumVariations; i++) { 494 DWRITE_FONT_AXIS_VALUE axisValue = { 495 makeDWriteAxisTag(aVariations[i].mTag), aVariations[i].mValue}; 496 fontAxisValues.push_back(axisValue); 497 } 498 } else { 499 uint32_t count = ff5->GetFontAxisValueCount(); 500 if (count) { 501 fontAxisValues.resize(count); 502 if (FAILED(ff5->GetFontAxisValues(fontAxisValues.data(), count))) { 503 fontAxisValues.clear(); 504 } 505 } 506 } 507 508 RefPtr<IDWriteFontFace5> newFace; 509 if (FAILED(res->CreateFontFace(aSimulations, fontAxisValues.data(), 510 fontAxisValues.size(), 511 getter_AddRefs(newFace)))) { 512 return nullptr; 513 } 514 return newFace.forget(); 515 } 516 MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { 517 gfxCriticalNote << "Exception occurred initializing variation face"; 518 return nullptr; 519 } 520 } 521 522 bool UnscaledFontDWrite::InitBold() { 523 if (mFontFaceBold) { 524 return true; 525 } 526 527 DWRITE_FONT_SIMULATIONS sims = mFontFace->GetSimulations(); 528 if (sims & DWRITE_FONT_SIMULATIONS_BOLD) { 529 mFontFaceBold = mFontFace; 530 return true; 531 } 532 sims |= DWRITE_FONT_SIMULATIONS_BOLD; 533 534 RefPtr<IDWriteFontFace5> ff5 = CreateFaceWithVariations(mFontFace, sims); 535 if (ff5) { 536 mFontFaceBold = ff5; 537 } else { 538 MOZ_SEH_TRY { 539 UINT32 numFiles = 0; 540 if (FAILED(mFontFace->GetFiles(&numFiles, nullptr))) { 541 return false; 542 } 543 StackArray<IDWriteFontFile*, 1> files(numFiles); 544 if (FAILED(mFontFace->GetFiles(&numFiles, files.data()))) { 545 return false; 546 } 547 HRESULT hr = Factory::GetDWriteFactory()->CreateFontFace( 548 mFontFace->GetType(), numFiles, files.data(), mFontFace->GetIndex(), 549 sims, getter_AddRefs(mFontFaceBold)); 550 for (UINT32 i = 0; i < numFiles; ++i) { 551 files[i]->Release(); 552 } 553 if (FAILED(hr) || !mFontFaceBold) { 554 return false; 555 } 556 } 557 MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { 558 gfxCriticalNote << "Exception occurred initializing bold face"; 559 return false; 560 } 561 } 562 return true; 563 } 564 565 already_AddRefed<ScaledFont> UnscaledFontDWrite::CreateScaledFont( 566 Float aGlyphSize, const uint8_t* aInstanceData, 567 uint32_t aInstanceDataLength, const FontVariation* aVariations, 568 uint32_t aNumVariations) { 569 if (aInstanceDataLength < sizeof(ScaledFontDWrite::InstanceData)) { 570 gfxWarning() << "DWrite scaled font instance data is truncated."; 571 return nullptr; 572 } 573 const ScaledFontDWrite::InstanceData& instanceData = 574 *reinterpret_cast<const ScaledFontDWrite::InstanceData*>(aInstanceData); 575 576 IDWriteFontFace* face = mFontFace; 577 if (instanceData.mUseBoldSimulation) { 578 if (!InitBold()) { 579 gfxWarning() << "Failed creating bold IDWriteFontFace."; 580 return nullptr; 581 } 582 face = mFontFaceBold; 583 } 584 DWRITE_FONT_SIMULATIONS sims = face->GetSimulations(); 585 586 // If variations are required, we create a separate IDWriteFontFace5 with 587 // the requested settings applied. 588 RefPtr<IDWriteFontFace5> ff5; 589 if (aNumVariations) { 590 ff5 = 591 CreateFaceWithVariations(mFontFace, sims, aVariations, aNumVariations); 592 if (ff5) { 593 face = ff5; 594 } else { 595 gfxWarning() << "Failed to create IDWriteFontFace5 with variations."; 596 } 597 } 598 599 return MakeAndAddRef<ScaledFontDWrite>( 600 face, this, aGlyphSize, instanceData.mUseEmbeddedBitmap, 601 instanceData.mUseMultistrikeBold, instanceData.mGDIForced, nullptr); 602 } 603 604 already_AddRefed<ScaledFont> UnscaledFontDWrite::CreateScaledFontFromWRFont( 605 Float aGlyphSize, const wr::FontInstanceOptions* aOptions, 606 const wr::FontInstancePlatformOptions* aPlatformOptions, 607 const FontVariation* aVariations, uint32_t aNumVariations) { 608 ScaledFontDWrite::InstanceData instanceData(aOptions, aPlatformOptions); 609 return CreateScaledFont(aGlyphSize, reinterpret_cast<uint8_t*>(&instanceData), 610 sizeof(instanceData), aVariations, aNumVariations); 611 } 612 613 AntialiasMode ScaledFontDWrite::GetDefaultAAMode() { 614 AntialiasMode defaultMode = GetSystemDefaultAAMode(); 615 616 switch (defaultMode) { 617 case AntialiasMode::SUBPIXEL: 618 case AntialiasMode::DEFAULT: 619 if (DWriteSettings().ClearTypeLevel() == 0.0f) { 620 defaultMode = AntialiasMode::GRAY; 621 } 622 break; 623 case AntialiasMode::GRAY: 624 if (!DoGrayscale(mFontFace, mSize)) { 625 defaultMode = AntialiasMode::NONE; 626 } 627 break; 628 case AntialiasMode::NONE: 629 break; 630 } 631 632 return defaultMode; 633 } 634 635 cairo_font_face_t* ScaledFontDWrite::CreateCairoFontFace( 636 cairo_font_options_t* aFontOptions) { 637 if (!mFontFace) { 638 return nullptr; 639 } 640 641 return cairo_dwrite_font_face_create_for_dwrite_fontface(mFontFace); 642 } 643 644 void ScaledFontDWrite::PrepareCairoScaledFont(cairo_scaled_font_t* aFont) { 645 #if 0 646 if (mGDIForced) { 647 cairo_dwrite_scaled_font_set_force_GDI_classic(aFont, true); 648 } 649 #endif 650 } 651 652 already_AddRefed<UnscaledFont> UnscaledFontDWrite::CreateFromFontDescriptor( 653 const uint8_t* aData, uint32_t aDataLength, uint32_t aIndex) { 654 // Note that despite the type of aData here, it actually points to a 16-bit 655 // Windows font file path (hence the cast to WCHAR* below). 656 if (aDataLength == 0) { 657 gfxWarning() << "DWrite font descriptor is truncated."; 658 return nullptr; 659 } 660 661 RefPtr<IDWriteFactory> factory = Factory::GetDWriteFactory(); 662 if (!factory) { 663 return nullptr; 664 } 665 666 MOZ_SEH_TRY { 667 RefPtr<IDWriteFontFile> fontFile; 668 HRESULT hr = factory->CreateFontFileReference((const WCHAR*)aData, nullptr, 669 getter_AddRefs(fontFile)); 670 if (FAILED(hr)) { 671 return nullptr; 672 } 673 BOOL isSupported; 674 DWRITE_FONT_FILE_TYPE fileType; 675 DWRITE_FONT_FACE_TYPE faceType; 676 UINT32 numFaces; 677 hr = fontFile->Analyze(&isSupported, &fileType, &faceType, &numFaces); 678 if (FAILED(hr) || !isSupported || aIndex >= numFaces) { 679 return nullptr; 680 } 681 IDWriteFontFile* fontFiles[1] = {fontFile.get()}; 682 RefPtr<IDWriteFontFace> fontFace; 683 hr = factory->CreateFontFace(faceType, 1, fontFiles, aIndex, 684 DWRITE_FONT_SIMULATIONS_NONE, 685 getter_AddRefs(fontFace)); 686 if (FAILED(hr)) { 687 return nullptr; 688 } 689 RefPtr unscaledFont = new UnscaledFontDWrite(fontFace, nullptr); 690 return unscaledFont.forget(); 691 } 692 MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { 693 gfxCriticalNote << "Exception occurred creating unscaledFont for " 694 << NS_ConvertUTF16toUTF8((const char16_t*)aData).get(); 695 return nullptr; 696 } 697 } 698 699 } // namespace gfx 700 } // namespace mozilla