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