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