1/* 2 * Copyright 2014 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkTypes.h" 9#if defined(SK_BUILD_FOR_WIN) 10 11#include "SkDWrite.h" 12#include "SkDWriteFontFileStream.h" 13#include "SkFontMgr.h" 14#include "SkHRESULT.h" 15#include "SkMakeUnique.h" 16#include "SkMutex.h" 17#include "SkStream.h" 18#include "SkTScopedComPtr.h" 19#include "SkTypeface.h" 20#include "SkTypefaceCache.h" 21#include "SkTypeface_win_dw.h" 22#include "SkTypes.h" 23#include "SkUtils.h" 24 25#include <dwrite.h> 26#include <dwrite_2.h> 27 28//////////////////////////////////////////////////////////////////////////////// 29 30class StreamFontFileLoader : public IDWriteFontFileLoader { 31public: 32 // IUnknown methods 33 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); 34 virtual ULONG STDMETHODCALLTYPE AddRef(); 35 virtual ULONG STDMETHODCALLTYPE Release(); 36 37 // IDWriteFontFileLoader methods 38 virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey( 39 void const* fontFileReferenceKey, 40 UINT32 fontFileReferenceKeySize, 41 IDWriteFontFileStream** fontFileStream); 42 43 // Takes ownership of stream. 44 static HRESULT Create(std::unique_ptr<SkStreamAsset> stream, 45 StreamFontFileLoader** streamFontFileLoader) { 46 *streamFontFileLoader = new StreamFontFileLoader(std::move(stream)); 47 if (nullptr == *streamFontFileLoader) { 48 return E_OUTOFMEMORY; 49 } 50 return S_OK; 51 } 52 53 std::unique_ptr<SkStreamAsset> fStream; 54 55private: 56 StreamFontFileLoader(std::unique_ptr<SkStreamAsset> stream) 57 : fStream(std::move(stream)), fRefCount(1) 58 {} 59 virtual ~StreamFontFileLoader() { } 60 61 ULONG fRefCount; 62}; 63 64HRESULT StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) { 65 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) { 66 *ppvObject = this; 67 AddRef(); 68 return S_OK; 69 } else { 70 *ppvObject = nullptr; 71 return E_NOINTERFACE; 72 } 73} 74 75ULONG StreamFontFileLoader::AddRef() { 76 return InterlockedIncrement(&fRefCount); 77} 78 79ULONG StreamFontFileLoader::Release() { 80 ULONG newCount = InterlockedDecrement(&fRefCount); 81 if (0 == newCount) { 82 delete this; 83 } 84 return newCount; 85} 86 87HRESULT StreamFontFileLoader::CreateStreamFromKey( 88 void const* fontFileReferenceKey, 89 UINT32 fontFileReferenceKeySize, 90 IDWriteFontFileStream** fontFileStream) 91{ 92 SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream; 93 HR(SkDWriteFontFileStreamWrapper::Create(fStream->duplicate().release(), &stream)); 94 *fontFileStream = stream.release(); 95 return S_OK; 96} 97 98//////////////////////////////////////////////////////////////////////////////// 99 100class StreamFontFileEnumerator : public IDWriteFontFileEnumerator { 101public: 102 // IUnknown methods 103 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); 104 virtual ULONG STDMETHODCALLTYPE AddRef(); 105 virtual ULONG STDMETHODCALLTYPE Release(); 106 107 // IDWriteFontFileEnumerator methods 108 virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile); 109 virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontFile); 110 111 static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader, 112 StreamFontFileEnumerator** streamFontFileEnumerator) { 113 *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFileLoader); 114 if (nullptr == *streamFontFileEnumerator) { 115 return E_OUTOFMEMORY; 116 } 117 return S_OK; 118 } 119private: 120 StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader); 121 virtual ~StreamFontFileEnumerator() { } 122 123 ULONG fRefCount; 124 125 SkTScopedComPtr<IDWriteFactory> fFactory; 126 SkTScopedComPtr<IDWriteFontFile> fCurrentFile; 127 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader; 128 bool fHasNext; 129}; 130 131StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory, 132 IDWriteFontFileLoader* fontFileLoader) 133 : fRefCount(1) 134 , fFactory(SkRefComPtr(factory)) 135 , fCurrentFile() 136 , fFontFileLoader(SkRefComPtr(fontFileLoader)) 137 , fHasNext(true) 138{ } 139 140HRESULT StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) { 141 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) { 142 *ppvObject = this; 143 AddRef(); 144 return S_OK; 145 } else { 146 *ppvObject = nullptr; 147 return E_NOINTERFACE; 148 } 149} 150 151ULONG StreamFontFileEnumerator::AddRef() { 152 return InterlockedIncrement(&fRefCount); 153} 154 155ULONG StreamFontFileEnumerator::Release() { 156 ULONG newCount = InterlockedDecrement(&fRefCount); 157 if (0 == newCount) { 158 delete this; 159 } 160 return newCount; 161} 162 163HRESULT StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) { 164 *hasCurrentFile = FALSE; 165 166 if (!fHasNext) { 167 return S_OK; 168 } 169 fHasNext = false; 170 171 UINT32 dummy = 0; 172 HR(fFactory->CreateCustomFontFileReference( 173 &dummy, //cannot be nullptr 174 sizeof(dummy), //even if this is 0 175 fFontFileLoader.get(), 176 &fCurrentFile)); 177 178 *hasCurrentFile = TRUE; 179 return S_OK; 180} 181 182HRESULT StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) { 183 if (fCurrentFile.get() == nullptr) { 184 *fontFile = nullptr; 185 return E_FAIL; 186 } 187 188 *fontFile = SkRefComPtr(fCurrentFile.get()); 189 return S_OK; 190} 191 192//////////////////////////////////////////////////////////////////////////////// 193 194class StreamFontCollectionLoader : public IDWriteFontCollectionLoader { 195public: 196 // IUnknown methods 197 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); 198 virtual ULONG STDMETHODCALLTYPE AddRef(); 199 virtual ULONG STDMETHODCALLTYPE Release(); 200 201 // IDWriteFontCollectionLoader methods 202 virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey( 203 IDWriteFactory* factory, 204 void const* collectionKey, 205 UINT32 collectionKeySize, 206 IDWriteFontFileEnumerator** fontFileEnumerator); 207 208 static HRESULT Create(IDWriteFontFileLoader* fontFileLoader, 209 StreamFontCollectionLoader** streamFontCollectionLoader) { 210 *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoader); 211 if (nullptr == *streamFontCollectionLoader) { 212 return E_OUTOFMEMORY; 213 } 214 return S_OK; 215 } 216private: 217 StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader) 218 : fRefCount(1) 219 , fFontFileLoader(SkRefComPtr(fontFileLoader)) 220 { } 221 virtual ~StreamFontCollectionLoader() { } 222 223 ULONG fRefCount; 224 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader; 225}; 226 227HRESULT StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) { 228 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) { 229 *ppvObject = this; 230 AddRef(); 231 return S_OK; 232 } else { 233 *ppvObject = nullptr; 234 return E_NOINTERFACE; 235 } 236} 237 238ULONG StreamFontCollectionLoader::AddRef() { 239 return InterlockedIncrement(&fRefCount); 240} 241 242ULONG StreamFontCollectionLoader::Release() { 243 ULONG newCount = InterlockedDecrement(&fRefCount); 244 if (0 == newCount) { 245 delete this; 246 } 247 return newCount; 248} 249 250HRESULT StreamFontCollectionLoader::CreateEnumeratorFromKey( 251 IDWriteFactory* factory, 252 void const* collectionKey, 253 UINT32 collectionKeySize, 254 IDWriteFontFileEnumerator** fontFileEnumerator) 255{ 256 SkTScopedComPtr<StreamFontFileEnumerator> enumerator; 257 HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumerator)); 258 *fontFileEnumerator = enumerator.release(); 259 return S_OK; 260} 261 262//////////////////////////////////////////////////////////////////////////////// 263 264class SkFontMgr_DirectWrite : public SkFontMgr { 265public: 266 /** localeNameLength must include the null terminator. */ 267 SkFontMgr_DirectWrite(IDWriteFactory* factory, IDWriteFontCollection* fontCollection, 268 IDWriteFontFallback* fallback, WCHAR* localeName, int localeNameLength) 269 : fFactory(SkRefComPtr(factory)) 270 , fFontFallback(SkSafeRefComPtr(fallback)) 271 , fFontCollection(SkRefComPtr(fontCollection)) 272 , fLocaleName(localeNameLength) 273 { 274 if (!SUCCEEDED(fFactory->QueryInterface(&fFactory2))) { 275 // IUnknown::QueryInterface states that if it fails, punk will be set to nullptr. 276 // http://blogs.msdn.com/b/oldnewthing/archive/2004/03/26/96777.aspx 277 SkASSERT_RELEASE(nullptr == fFactory2.get()); 278 } 279 if (fFontFallback.get()) { 280 // factory must be provided if fallback is non-null, else the fallback will not be used. 281 SkASSERT(fFactory2.get()); 282 } 283 memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR)); 284 } 285 286protected: 287 int onCountFamilies() const override; 288 void onGetFamilyName(int index, SkString* familyName) const override; 289 SkFontStyleSet* onCreateStyleSet(int index) const override; 290 SkFontStyleSet* onMatchFamily(const char familyName[]) const override; 291 SkTypeface* onMatchFamilyStyle(const char familyName[], 292 const SkFontStyle& fontstyle) const override; 293 SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&, 294 const char* bcp47[], int bcp47Count, 295 SkUnichar character) const override; 296 SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, 297 const SkFontStyle& fontstyle) const override; 298 sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>, int ttcIndex) const override; 299 sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int ttcIndex) const override; 300 sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override; 301 sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle) const override; 302 303private: 304 HRESULT getByFamilyName(const WCHAR familyName[], IDWriteFontFamily** fontFamily) const; 305 HRESULT getDefaultFontFamily(IDWriteFontFamily** fontFamily) const; 306 307 /** Creates a typeface using a typeface cache. */ 308 sk_sp<SkTypeface> makeTypefaceFromDWriteFont(IDWriteFontFace* fontFace, 309 IDWriteFont* font, 310 IDWriteFontFamily* fontFamily) const; 311 312 SkTScopedComPtr<IDWriteFactory> fFactory; 313 SkTScopedComPtr<IDWriteFactory2> fFactory2; 314 SkTScopedComPtr<IDWriteFontFallback> fFontFallback; 315 SkTScopedComPtr<IDWriteFontCollection> fFontCollection; 316 SkSMallocWCHAR fLocaleName; 317 mutable SkMutex fTFCacheMutex; 318 mutable SkTypefaceCache fTFCache; 319 320 friend class SkFontStyleSet_DirectWrite; 321 friend class FontFallbackRenderer; 322}; 323 324class SkFontStyleSet_DirectWrite : public SkFontStyleSet { 325public: 326 SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite* fontMgr, 327 IDWriteFontFamily* fontFamily) 328 : fFontMgr(SkRef(fontMgr)) 329 , fFontFamily(SkRefComPtr(fontFamily)) 330 { } 331 332 int count() override; 333 void getStyle(int index, SkFontStyle* fs, SkString* styleName) override; 334 SkTypeface* createTypeface(int index) override; 335 SkTypeface* matchStyle(const SkFontStyle& pattern) override; 336 337private: 338 sk_sp<const SkFontMgr_DirectWrite> fFontMgr; 339 SkTScopedComPtr<IDWriteFontFamily> fFontFamily; 340}; 341 342static HRESULT are_same(IUnknown* a, IUnknown* b, bool& same) { 343 SkTScopedComPtr<IUnknown> iunkA; 344 HRM(a->QueryInterface(&iunkA), "Failed to QI<IUnknown> for a."); 345 346 SkTScopedComPtr<IUnknown> iunkB; 347 HRM(b->QueryInterface(&iunkB), "Failed to QI<IUnknown> for b."); 348 349 same = (iunkA.get() == iunkB.get()); 350 return S_OK; 351} 352 353struct ProtoDWriteTypeface { 354 IDWriteFontFace* fDWriteFontFace; 355 IDWriteFont* fDWriteFont; 356 IDWriteFontFamily* fDWriteFontFamily; 357}; 358 359static bool FindByDWriteFont(SkTypeface* cached, void* ctx) { 360 DWriteFontTypeface* cshFace = reinterpret_cast<DWriteFontTypeface*>(cached); 361 ProtoDWriteTypeface* ctxFace = reinterpret_cast<ProtoDWriteTypeface*>(ctx); 362 bool same; 363 364 //Check to see if the two fonts are identical. 365 HRB(are_same(cshFace->fDWriteFont.get(), ctxFace->fDWriteFont, same)); 366 if (same) { 367 return true; 368 } 369 370 HRB(are_same(cshFace->fDWriteFontFace.get(), ctxFace->fDWriteFontFace, same)); 371 if (same) { 372 return true; 373 } 374 375 //Check if the two fonts share the same loader and have the same key. 376 UINT32 cshNumFiles; 377 UINT32 ctxNumFiles; 378 HRB(cshFace->fDWriteFontFace->GetFiles(&cshNumFiles, nullptr)); 379 HRB(ctxFace->fDWriteFontFace->GetFiles(&ctxNumFiles, nullptr)); 380 if (cshNumFiles != ctxNumFiles) { 381 return false; 382 } 383 384 SkTScopedComPtr<IDWriteFontFile> cshFontFile; 385 SkTScopedComPtr<IDWriteFontFile> ctxFontFile; 386 HRB(cshFace->fDWriteFontFace->GetFiles(&cshNumFiles, &cshFontFile)); 387 HRB(ctxFace->fDWriteFontFace->GetFiles(&ctxNumFiles, &ctxFontFile)); 388 389 //for (each file) { //we currently only admit fonts from one file. 390 SkTScopedComPtr<IDWriteFontFileLoader> cshFontFileLoader; 391 SkTScopedComPtr<IDWriteFontFileLoader> ctxFontFileLoader; 392 HRB(cshFontFile->GetLoader(&cshFontFileLoader)); 393 HRB(ctxFontFile->GetLoader(&ctxFontFileLoader)); 394 HRB(are_same(cshFontFileLoader.get(), ctxFontFileLoader.get(), same)); 395 if (!same) { 396 return false; 397 } 398 //} 399 400 const void* cshRefKey; 401 UINT32 cshRefKeySize; 402 const void* ctxRefKey; 403 UINT32 ctxRefKeySize; 404 HRB(cshFontFile->GetReferenceKey(&cshRefKey, &cshRefKeySize)); 405 HRB(ctxFontFile->GetReferenceKey(&ctxRefKey, &ctxRefKeySize)); 406 if (cshRefKeySize != ctxRefKeySize) { 407 return false; 408 } 409 if (0 != memcmp(cshRefKey, ctxRefKey, ctxRefKeySize)) { 410 return false; 411 } 412 413 //TODO: better means than comparing name strings? 414 //NOTE: .ttc and fake bold/italic will end up here. 415 SkTScopedComPtr<IDWriteLocalizedStrings> cshFamilyNames; 416 SkTScopedComPtr<IDWriteLocalizedStrings> cshFaceNames; 417 HRB(cshFace->fDWriteFontFamily->GetFamilyNames(&cshFamilyNames)); 418 HRB(cshFace->fDWriteFont->GetFaceNames(&cshFaceNames)); 419 UINT32 cshFamilyNameLength; 420 UINT32 cshFaceNameLength; 421 HRB(cshFamilyNames->GetStringLength(0, &cshFamilyNameLength)); 422 HRB(cshFaceNames->GetStringLength(0, &cshFaceNameLength)); 423 424 SkTScopedComPtr<IDWriteLocalizedStrings> ctxFamilyNames; 425 SkTScopedComPtr<IDWriteLocalizedStrings> ctxFaceNames; 426 HRB(ctxFace->fDWriteFontFamily->GetFamilyNames(&ctxFamilyNames)); 427 HRB(ctxFace->fDWriteFont->GetFaceNames(&ctxFaceNames)); 428 UINT32 ctxFamilyNameLength; 429 UINT32 ctxFaceNameLength; 430 HRB(ctxFamilyNames->GetStringLength(0, &ctxFamilyNameLength)); 431 HRB(ctxFaceNames->GetStringLength(0, &ctxFaceNameLength)); 432 433 if (cshFamilyNameLength != ctxFamilyNameLength || 434 cshFaceNameLength != ctxFaceNameLength) 435 { 436 return false; 437 } 438 439 SkSMallocWCHAR cshFamilyName(cshFamilyNameLength+1); 440 SkSMallocWCHAR cshFaceName(cshFaceNameLength+1); 441 HRB(cshFamilyNames->GetString(0, cshFamilyName.get(), cshFamilyNameLength+1)); 442 HRB(cshFaceNames->GetString(0, cshFaceName.get(), cshFaceNameLength+1)); 443 444 SkSMallocWCHAR ctxFamilyName(ctxFamilyNameLength+1); 445 SkSMallocWCHAR ctxFaceName(ctxFaceNameLength+1); 446 HRB(ctxFamilyNames->GetString(0, ctxFamilyName.get(), ctxFamilyNameLength+1)); 447 HRB(ctxFaceNames->GetString(0, ctxFaceName.get(), ctxFaceNameLength+1)); 448 449 return wcscmp(cshFamilyName.get(), ctxFamilyName.get()) == 0 && 450 wcscmp(cshFaceName.get(), ctxFaceName.get()) == 0; 451} 452 453sk_sp<SkTypeface> SkFontMgr_DirectWrite::makeTypefaceFromDWriteFont( 454 IDWriteFontFace* fontFace, 455 IDWriteFont* font, 456 IDWriteFontFamily* fontFamily) const { 457 SkAutoMutexAcquire ama(fTFCacheMutex); 458 ProtoDWriteTypeface spec = { fontFace, font, fontFamily }; 459 SkTypeface* face = fTFCache.findByProcAndRef(FindByDWriteFont, &spec); 460 if (nullptr == face) { 461 face = DWriteFontTypeface::Create(fFactory.get(), fontFace, font, fontFamily); 462 if (face) { 463 fTFCache.add(face); 464 } 465 } 466 return sk_sp<SkTypeface>(face); 467} 468 469int SkFontMgr_DirectWrite::onCountFamilies() const { 470 return fFontCollection->GetFontFamilyCount(); 471} 472 473void SkFontMgr_DirectWrite::onGetFamilyName(int index, SkString* familyName) const { 474 SkTScopedComPtr<IDWriteFontFamily> fontFamily; 475 HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family."); 476 477 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames; 478 HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names."); 479 480 sk_get_locale_string(familyNames.get(), fLocaleName.get(), familyName); 481} 482 483SkFontStyleSet* SkFontMgr_DirectWrite::onCreateStyleSet(int index) const { 484 SkTScopedComPtr<IDWriteFontFamily> fontFamily; 485 HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family."); 486 487 return new SkFontStyleSet_DirectWrite(this, fontFamily.get()); 488} 489 490SkFontStyleSet* SkFontMgr_DirectWrite::onMatchFamily(const char familyName[]) const { 491 if (!familyName) { 492 return nullptr; 493 } 494 495 SkSMallocWCHAR dwFamilyName; 496 HRN(sk_cstring_to_wchar(familyName, &dwFamilyName)); 497 498 UINT32 index; 499 BOOL exists; 500 HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists), 501 "Failed while finding family by name."); 502 if (!exists) { 503 return nullptr; 504 } 505 506 return this->onCreateStyleSet(index); 507} 508 509SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyle(const char familyName[], 510 const SkFontStyle& fontstyle) const { 511 sk_sp<SkFontStyleSet> sset(this->matchFamily(familyName)); 512 return sset->matchStyle(fontstyle); 513} 514 515class FontFallbackRenderer : public IDWriteTextRenderer { 516public: 517 FontFallbackRenderer(const SkFontMgr_DirectWrite* outer, UINT32 character) 518 : fRefCount(1), fOuter(SkSafeRef(outer)), fCharacter(character), fResolvedTypeface(nullptr) { 519 } 520 521 virtual ~FontFallbackRenderer() { } 522 523 // IDWriteTextRenderer methods 524 virtual HRESULT STDMETHODCALLTYPE DrawGlyphRun( 525 void* clientDrawingContext, 526 FLOAT baselineOriginX, 527 FLOAT baselineOriginY, 528 DWRITE_MEASURING_MODE measuringMode, 529 DWRITE_GLYPH_RUN const* glyphRun, 530 DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, 531 IUnknown* clientDrawingEffect) override 532 { 533 SkTScopedComPtr<IDWriteFont> font; 534 HRM(fOuter->fFontCollection->GetFontFromFontFace(glyphRun->fontFace, &font), 535 "Could not get font from font face."); 536 537 // It is possible that the font passed does not actually have the requested character, 538 // due to no font being found and getting the fallback font. 539 // Check that the font actually contains the requested character. 540 BOOL exists; 541 HRM(font->HasCharacter(fCharacter, &exists), "Could not find character."); 542 543 if (exists) { 544 SkTScopedComPtr<IDWriteFontFamily> fontFamily; 545 HRM(font->GetFontFamily(&fontFamily), "Could not get family."); 546 fResolvedTypeface = fOuter->makeTypefaceFromDWriteFont(glyphRun->fontFace, 547 font.get(), 548 fontFamily.get()).release(); 549 } 550 551 return S_OK; 552 } 553 554 virtual HRESULT STDMETHODCALLTYPE DrawUnderline( 555 void* clientDrawingContext, 556 FLOAT baselineOriginX, 557 FLOAT baselineOriginY, 558 DWRITE_UNDERLINE const* underline, 559 IUnknown* clientDrawingEffect) override 560 { return E_NOTIMPL; } 561 562 virtual HRESULT STDMETHODCALLTYPE DrawStrikethrough( 563 void* clientDrawingContext, 564 FLOAT baselineOriginX, 565 FLOAT baselineOriginY, 566 DWRITE_STRIKETHROUGH const* strikethrough, 567 IUnknown* clientDrawingEffect) override 568 { return E_NOTIMPL; } 569 570 virtual HRESULT STDMETHODCALLTYPE DrawInlineObject( 571 void* clientDrawingContext, 572 FLOAT originX, 573 FLOAT originY, 574 IDWriteInlineObject* inlineObject, 575 BOOL isSideways, 576 BOOL isRightToLeft, 577 IUnknown* clientDrawingEffect) override 578 { return E_NOTIMPL; } 579 580 // IDWritePixelSnapping methods 581 virtual HRESULT STDMETHODCALLTYPE IsPixelSnappingDisabled( 582 void* clientDrawingContext, 583 BOOL* isDisabled) override 584 { 585 *isDisabled = FALSE; 586 return S_OK; 587 } 588 589 virtual HRESULT STDMETHODCALLTYPE GetCurrentTransform( 590 void* clientDrawingContext, 591 DWRITE_MATRIX* transform) override 592 { 593 const DWRITE_MATRIX ident = { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }; 594 *transform = ident; 595 return S_OK; 596 } 597 598 virtual HRESULT STDMETHODCALLTYPE GetPixelsPerDip( 599 void* clientDrawingContext, 600 FLOAT* pixelsPerDip) override 601 { 602 *pixelsPerDip = 1.0f; 603 return S_OK; 604 } 605 606 // IUnknown methods 607 ULONG STDMETHODCALLTYPE AddRef() override { 608 return InterlockedIncrement(&fRefCount); 609 } 610 611 ULONG STDMETHODCALLTYPE Release() override { 612 ULONG newCount = InterlockedDecrement(&fRefCount); 613 if (0 == newCount) { 614 delete this; 615 } 616 return newCount; 617 } 618 619 virtual HRESULT STDMETHODCALLTYPE QueryInterface(IID const& riid, void** ppvObject) override{ 620 if (__uuidof(IUnknown) == riid || 621 __uuidof(IDWritePixelSnapping) == riid || 622 __uuidof(IDWriteTextRenderer) == riid) 623 { 624 *ppvObject = this; 625 this->AddRef(); 626 return S_OK; 627 } 628 *ppvObject = nullptr; 629 return E_FAIL; 630 } 631 632 SkTypeface* FallbackTypeface() { return fResolvedTypeface; } 633 634protected: 635 ULONG fRefCount; 636 sk_sp<const SkFontMgr_DirectWrite> fOuter; 637 UINT32 fCharacter; 638 SkTypeface* fResolvedTypeface; 639}; 640 641class FontFallbackSource : public IDWriteTextAnalysisSource { 642public: 643 FontFallbackSource(const WCHAR* string, UINT32 length, const WCHAR* locale, 644 IDWriteNumberSubstitution* numberSubstitution) 645 : fString(string) 646 , fLength(length) 647 , fLocale(locale) 648 , fNumberSubstitution(numberSubstitution) 649 { } 650 651 virtual ~FontFallbackSource() { } 652 653 // IDWriteTextAnalysisSource methods 654 virtual HRESULT STDMETHODCALLTYPE GetTextAtPosition( 655 UINT32 textPosition, 656 WCHAR const** textString, 657 UINT32* textLength) override 658 { 659 if (fLength <= textPosition) { 660 *textString = nullptr; 661 *textLength = 0; 662 return S_OK; 663 } 664 *textString = fString + textPosition; 665 *textLength = fLength - textPosition; 666 return S_OK; 667 } 668 669 virtual HRESULT STDMETHODCALLTYPE GetTextBeforePosition( 670 UINT32 textPosition, 671 WCHAR const** textString, 672 UINT32* textLength) override 673 { 674 if (textPosition < 1 || fLength <= textPosition) { 675 *textString = nullptr; 676 *textLength = 0; 677 return S_OK; 678 } 679 *textString = fString; 680 *textLength = textPosition; 681 return S_OK; 682 } 683 684 virtual DWRITE_READING_DIRECTION STDMETHODCALLTYPE GetParagraphReadingDirection() override { 685 // TODO: this is also interesting. 686 return DWRITE_READING_DIRECTION_LEFT_TO_RIGHT; 687 } 688 689 virtual HRESULT STDMETHODCALLTYPE GetLocaleName( 690 UINT32 textPosition, 691 UINT32* textLength, 692 WCHAR const** localeName) override 693 { 694 *localeName = fLocale; 695 return S_OK; 696 } 697 698 virtual HRESULT STDMETHODCALLTYPE GetNumberSubstitution( 699 UINT32 textPosition, 700 UINT32* textLength, 701 IDWriteNumberSubstitution** numberSubstitution) override 702 { 703 *numberSubstitution = fNumberSubstitution; 704 return S_OK; 705 } 706 707 // IUnknown methods 708 ULONG STDMETHODCALLTYPE AddRef() override { 709 return InterlockedIncrement(&fRefCount); 710 } 711 712 ULONG STDMETHODCALLTYPE Release() override { 713 ULONG newCount = InterlockedDecrement(&fRefCount); 714 if (0 == newCount) { 715 delete this; 716 } 717 return newCount; 718 } 719 720 virtual HRESULT STDMETHODCALLTYPE QueryInterface(IID const& riid, void** ppvObject) override{ 721 if (__uuidof(IUnknown) == riid || 722 __uuidof(IDWriteTextAnalysisSource) == riid) 723 { 724 *ppvObject = this; 725 this->AddRef(); 726 return S_OK; 727 } 728 *ppvObject = nullptr; 729 return E_FAIL; 730 } 731 732protected: 733 ULONG fRefCount; 734 const WCHAR* fString; 735 UINT32 fLength; 736 const WCHAR* fLocale; 737 IDWriteNumberSubstitution* fNumberSubstitution; 738}; 739 740SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyleCharacter(const char familyName[], 741 const SkFontStyle& style, 742 const char* bcp47[], int bcp47Count, 743 SkUnichar character) const 744{ 745 const DWriteStyle dwStyle(style); 746 747 const WCHAR* dwFamilyName = nullptr; 748 SkSMallocWCHAR dwFamilyNameLocal; 749 if (familyName) { 750 HRN(sk_cstring_to_wchar(familyName, &dwFamilyNameLocal)); 751 dwFamilyName = dwFamilyNameLocal; 752 } 753 754 WCHAR str[16]; 755 UINT32 strLen = static_cast<UINT32>( 756 SkUTF16_FromUnichar(character, reinterpret_cast<uint16_t*>(str))); 757 758 const SkSMallocWCHAR* dwBcp47; 759 SkSMallocWCHAR dwBcp47Local; 760 if (bcp47Count < 1) { 761 dwBcp47 = &fLocaleName; 762 } else { 763 // TODO: support fallback stack. 764 // TODO: DirectWrite supports 'zh-CN' or 'zh-Hans', but 'zh' misses completely 765 // and may produce a Japanese font. 766 HRN(sk_cstring_to_wchar(bcp47[bcp47Count - 1], &dwBcp47Local)); 767 dwBcp47 = &dwBcp47Local; 768 } 769 770 if (fFactory2.get()) { 771 SkTScopedComPtr<IDWriteFontFallback> systemFontFallback; 772 IDWriteFontFallback* fontFallback = fFontFallback.get(); 773 if (!fontFallback) { 774 HRNM(fFactory2->GetSystemFontFallback(&systemFontFallback), 775 "Could not get system fallback."); 776 fontFallback = systemFontFallback.get(); 777 } 778 779 SkTScopedComPtr<IDWriteNumberSubstitution> numberSubstitution; 780 HRNM(fFactory2->CreateNumberSubstitution(DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE, nullptr, TRUE, 781 &numberSubstitution), 782 "Could not create number substitution."); 783 SkTScopedComPtr<FontFallbackSource> fontFallbackSource( 784 new FontFallbackSource(str, strLen, *dwBcp47, numberSubstitution.get())); 785 786 UINT32 mappedLength; 787 SkTScopedComPtr<IDWriteFont> font; 788 FLOAT scale; 789 HRNM(fontFallback->MapCharacters(fontFallbackSource.get(), 790 0, // textPosition, 791 strLen, 792 fFontCollection.get(), 793 dwFamilyName, 794 dwStyle.fWeight, 795 dwStyle.fSlant, 796 dwStyle.fWidth, 797 &mappedLength, 798 &font, 799 &scale), 800 "Could not map characters"); 801 if (!font.get()) { 802 return nullptr; 803 } 804 805 SkTScopedComPtr<IDWriteFontFace> fontFace; 806 HRNM(font->CreateFontFace(&fontFace), "Could not get font face from font."); 807 808 SkTScopedComPtr<IDWriteFontFamily> fontFamily; 809 HRNM(font->GetFontFamily(&fontFamily), "Could not get family from font."); 810 return this->makeTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get()).release(); 811 } 812 813 SkTScopedComPtr<IDWriteTextFormat> fallbackFormat; 814 HRNM(fFactory->CreateTextFormat(dwFamilyName ? dwFamilyName : L"", 815 fFontCollection.get(), 816 dwStyle.fWeight, 817 dwStyle.fSlant, 818 dwStyle.fWidth, 819 72.0f, 820 *dwBcp47, 821 &fallbackFormat), 822 "Could not create text format."); 823 824 SkTScopedComPtr<IDWriteTextLayout> fallbackLayout; 825 HRNM(fFactory->CreateTextLayout(str, strLen, fallbackFormat.get(), 826 200.0f, 200.0f, 827 &fallbackLayout), 828 "Could not create text layout."); 829 830 SkTScopedComPtr<FontFallbackRenderer> fontFallbackRenderer( 831 new FontFallbackRenderer(this, character)); 832 833 HRNM(fallbackLayout->Draw(nullptr, fontFallbackRenderer.get(), 50.0f, 50.0f), 834 "Could not draw layout with renderer."); 835 836 return fontFallbackRenderer->FallbackTypeface(); 837} 838 839SkTypeface* SkFontMgr_DirectWrite::onMatchFaceStyle(const SkTypeface* familyMember, 840 const SkFontStyle& fontstyle) const { 841 SkString familyName; 842 SkFontStyleSet_DirectWrite sset( 843 this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get() 844 ); 845 return sset.matchStyle(fontstyle); 846} 847 848template <typename T> class SkAutoIDWriteUnregister { 849public: 850 SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister) 851 : fFactory(factory), fUnregister(unregister) 852 { } 853 854 ~SkAutoIDWriteUnregister() { 855 if (fUnregister) { 856 unregister(fFactory, fUnregister); 857 } 858 } 859 860 T* detatch() { 861 T* old = fUnregister; 862 fUnregister = nullptr; 863 return old; 864 } 865 866private: 867 HRESULT unregister(IDWriteFactory* factory, IDWriteFontFileLoader* unregister) { 868 return factory->UnregisterFontFileLoader(unregister); 869 } 870 871 HRESULT unregister(IDWriteFactory* factory, IDWriteFontCollectionLoader* unregister) { 872 return factory->UnregisterFontCollectionLoader(unregister); 873 } 874 875 IDWriteFactory* fFactory; 876 T* fUnregister; 877}; 878 879sk_sp<SkTypeface> SkFontMgr_DirectWrite::onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream, 880 int ttcIndex) const { 881 SkTScopedComPtr<StreamFontFileLoader> fontFileLoader; 882 // This transfers ownership of stream to the new object. 883 HRN(StreamFontFileLoader::Create(std::move(stream), &fontFileLoader)); 884 HRN(fFactory->RegisterFontFileLoader(fontFileLoader.get())); 885 SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader( 886 fFactory.get(), fontFileLoader.get()); 887 888 SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader; 889 HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollectionLoader)); 890 HRN(fFactory->RegisterFontCollectionLoader(fontCollectionLoader.get())); 891 SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollectionLoader( 892 fFactory.get(), fontCollectionLoader.get()); 893 894 SkTScopedComPtr<IDWriteFontCollection> fontCollection; 895 HRN(fFactory->CreateCustomFontCollection(fontCollectionLoader.get(), nullptr, 0, &fontCollection)); 896 897 // Find the first non-simulated font which has the given ttc index. 898 UINT32 familyCount = fontCollection->GetFontFamilyCount(); 899 for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) { 900 SkTScopedComPtr<IDWriteFontFamily> fontFamily; 901 HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily)); 902 903 UINT32 fontCount = fontFamily->GetFontCount(); 904 for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) { 905 SkTScopedComPtr<IDWriteFont> font; 906 HRN(fontFamily->GetFont(fontIndex, &font)); 907 if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) { 908 continue; 909 } 910 911 SkTScopedComPtr<IDWriteFontFace> fontFace; 912 HRN(font->CreateFontFace(&fontFace)); 913 914 int faceIndex = fontFace->GetIndex(); 915 if (faceIndex == ttcIndex) { 916 return sk_sp<SkTypeface>(DWriteFontTypeface::Create(fFactory.get(), 917 fontFace.get(), font.get(), fontFamily.get(), 918 autoUnregisterFontFileLoader.detatch(), 919 autoUnregisterFontCollectionLoader.detatch())); 920 } 921 } 922 } 923 924 return nullptr; 925} 926 927sk_sp<SkTypeface> SkFontMgr_DirectWrite::onMakeFromData(sk_sp<SkData> data, int ttcIndex) const { 928 return this->makeFromStream(skstd::make_unique<SkMemoryStream>(std::move(data)), ttcIndex); 929} 930 931sk_sp<SkTypeface> SkFontMgr_DirectWrite::onMakeFromFile(const char path[], int ttcIndex) const { 932 return this->makeFromStream(SkStream::MakeFromFile(path), ttcIndex); 933} 934 935HRESULT SkFontMgr_DirectWrite::getByFamilyName(const WCHAR wideFamilyName[], 936 IDWriteFontFamily** fontFamily) const { 937 UINT32 index; 938 BOOL exists; 939 HR(fFontCollection->FindFamilyName(wideFamilyName, &index, &exists)); 940 941 if (exists) { 942 HR(fFontCollection->GetFontFamily(index, fontFamily)); 943 } 944 return S_OK; 945} 946 947HRESULT SkFontMgr_DirectWrite::getDefaultFontFamily(IDWriteFontFamily** fontFamily) const { 948 NONCLIENTMETRICSW metrics; 949 metrics.cbSize = sizeof(metrics); 950 if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(metrics), &metrics, 0)) { 951 return E_UNEXPECTED; 952 } 953 HRM(this->getByFamilyName(metrics.lfMessageFont.lfFaceName, fontFamily), 954 "Could not create DWrite font family from LOGFONT."); 955 return S_OK; 956} 957 958sk_sp<SkTypeface> SkFontMgr_DirectWrite::onLegacyMakeTypeface(const char familyName[], 959 SkFontStyle style) const { 960 SkTScopedComPtr<IDWriteFontFamily> fontFamily; 961 if (familyName) { 962 SkSMallocWCHAR wideFamilyName; 963 if (SUCCEEDED(sk_cstring_to_wchar(familyName, &wideFamilyName))) { 964 this->getByFamilyName(wideFamilyName, &fontFamily); 965 } 966 } 967 968 if (nullptr == fontFamily.get()) { 969 // No family with given name, try default. 970 this->getDefaultFontFamily(&fontFamily); 971 } 972 973 if (nullptr == fontFamily.get()) { 974 // Could not obtain the default font. 975 HRNM(fFontCollection->GetFontFamily(0, &fontFamily), 976 "Could not get default-default font family."); 977 } 978 979 SkTScopedComPtr<IDWriteFont> font; 980 DWriteStyle dwStyle(style); 981 HRNM(fontFamily->GetFirstMatchingFont(dwStyle.fWeight, dwStyle.fWidth, dwStyle.fSlant, &font), 982 "Could not get matching font."); 983 984 SkTScopedComPtr<IDWriteFontFace> fontFace; 985 HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); 986 987 return this->makeTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get()); 988} 989 990/////////////////////////////////////////////////////////////////////////////// 991 992int SkFontStyleSet_DirectWrite::count() { 993 return fFontFamily->GetFontCount(); 994} 995 996SkTypeface* SkFontStyleSet_DirectWrite::createTypeface(int index) { 997 SkTScopedComPtr<IDWriteFont> font; 998 HRNM(fFontFamily->GetFont(index, &font), "Could not get font."); 999 1000 SkTScopedComPtr<IDWriteFontFace> fontFace; 1001 HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); 1002 1003 return fFontMgr->makeTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get()).release(); 1004} 1005 1006void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) { 1007 SkTScopedComPtr<IDWriteFont> font; 1008 HRVM(fFontFamily->GetFont(index, &font), "Could not get font."); 1009 1010 if (fs) { 1011 *fs = get_style(font.get()); 1012 } 1013 1014 if (styleName) { 1015 SkTScopedComPtr<IDWriteLocalizedStrings> faceNames; 1016 if (SUCCEEDED(font->GetFaceNames(&faceNames))) { 1017 sk_get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName); 1018 } 1019 } 1020} 1021 1022SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) { 1023 SkTScopedComPtr<IDWriteFont> font; 1024 DWriteStyle dwStyle(pattern); 1025 // TODO: perhaps use GetMatchingFonts and get the least simulated? 1026 HRNM(fFontFamily->GetFirstMatchingFont(dwStyle.fWeight, dwStyle.fWidth, dwStyle.fSlant, &font), 1027 "Could not match font in family."); 1028 1029 SkTScopedComPtr<IDWriteFontFace> fontFace; 1030 HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); 1031 1032 return fFontMgr->makeTypefaceFromDWriteFont(fontFace.get(), font.get(), 1033 fFontFamily.get()).release(); 1034} 1035 1036//////////////////////////////////////////////////////////////////////////////// 1037#include "SkTypeface_win.h" 1038 1039SK_API sk_sp<SkFontMgr> SkFontMgr_New_DirectWrite(IDWriteFactory* factory, 1040 IDWriteFontCollection* collection) { 1041 return SkFontMgr_New_DirectWrite(factory, collection, nullptr); 1042} 1043 1044SK_API sk_sp<SkFontMgr> SkFontMgr_New_DirectWrite(IDWriteFactory* factory, 1045 IDWriteFontCollection* collection, 1046 IDWriteFontFallback* fallback) { 1047 if (nullptr == factory) { 1048 factory = sk_get_dwrite_factory(); 1049 if (nullptr == factory) { 1050 return nullptr; 1051 } 1052 } 1053 1054 SkTScopedComPtr<IDWriteFontCollection> systemFontCollection; 1055 if (nullptr == collection) { 1056 HRNM(factory->GetSystemFontCollection(&systemFontCollection, FALSE), 1057 "Could not get system font collection."); 1058 collection = systemFontCollection.get(); 1059 } 1060 1061 WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH]; 1062 WCHAR* localeName = nullptr; 1063 int localeNameLen = 0; 1064 1065 // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP. 1066 SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = nullptr; 1067 HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc); 1068 if (nullptr == getUserDefaultLocaleNameProc) { 1069 SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName."); 1070 } else { 1071 localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH); 1072 if (localeNameLen) { 1073 localeName = localeNameStorage; 1074 }; 1075 } 1076 1077 return sk_make_sp<SkFontMgr_DirectWrite>(factory, collection, fallback, 1078 localeName, localeNameLen); 1079} 1080 1081#include "SkFontMgr_indirect.h" 1082SK_API sk_sp<SkFontMgr> SkFontMgr_New_DirectWriteRenderer(sk_sp<SkRemotableFontMgr> proxy) { 1083 sk_sp<SkFontMgr> impl(SkFontMgr_New_DirectWrite()); 1084 if (!impl) { 1085 return nullptr; 1086 } 1087 return sk_make_sp<SkFontMgr_Indirect>(std::move(impl), std::move(proxy)); 1088} 1089#endif//defined(SK_BUILD_FOR_WIN) 1090