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 20 #include <dwrite.h> 21 22 //////////////////////////////////////////////////////////////////////////////// 23 24 class StreamFontFileLoader : public IDWriteFontFileLoader { 25 public: 26 // IUnknown methods 27 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); 28 virtual ULONG STDMETHODCALLTYPE AddRef(); 29 virtual ULONG STDMETHODCALLTYPE Release(); 30 31 // IDWriteFontFileLoader methods 32 virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey( 33 void const* fontFileReferenceKey, 34 UINT32 fontFileReferenceKeySize, 35 IDWriteFontFileStream** fontFileStream); 36 37 static HRESULT Create(SkStream* stream, StreamFontFileLoader** streamFontFileLoader) { 38 *streamFontFileLoader = new StreamFontFileLoader(stream); 39 if (NULL == streamFontFileLoader) { 40 return E_OUTOFMEMORY; 41 } 42 return S_OK; 43 } 44 45 SkAutoTUnref<SkStream> fStream; 46 47 private: 48 StreamFontFileLoader(SkStream* stream) : fRefCount(1), fStream(SkRef(stream)) { } 49 virtual ~StreamFontFileLoader() { } 50 51 ULONG fRefCount; 52 }; 53 54 HRESULT StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) { 55 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) { 56 *ppvObject = this; 57 AddRef(); 58 return S_OK; 59 } else { 60 *ppvObject = NULL; 61 return E_NOINTERFACE; 62 } 63 } 64 65 ULONG StreamFontFileLoader::AddRef() { 66 return InterlockedIncrement(&fRefCount); 67 } 68 69 ULONG StreamFontFileLoader::Release() { 70 ULONG newCount = InterlockedDecrement(&fRefCount); 71 if (0 == newCount) { 72 delete this; 73 } 74 return newCount; 75 } 76 77 HRESULT StreamFontFileLoader::CreateStreamFromKey( 78 void const* fontFileReferenceKey, 79 UINT32 fontFileReferenceKeySize, 80 IDWriteFontFileStream** fontFileStream) 81 { 82 SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream; 83 HR(SkDWriteFontFileStreamWrapper::Create(fStream, &stream)); 84 *fontFileStream = stream.release(); 85 return S_OK; 86 } 87 88 //////////////////////////////////////////////////////////////////////////////// 89 90 class StreamFontFileEnumerator : public IDWriteFontFileEnumerator { 91 public: 92 // IUnknown methods 93 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); 94 virtual ULONG STDMETHODCALLTYPE AddRef(); 95 virtual ULONG STDMETHODCALLTYPE Release(); 96 97 // IDWriteFontFileEnumerator methods 98 virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile); 99 virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontFile); 100 101 static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader, 102 StreamFontFileEnumerator** streamFontFileEnumerator) { 103 *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFileLoader); 104 if (NULL == streamFontFileEnumerator) { 105 return E_OUTOFMEMORY; 106 } 107 return S_OK; 108 } 109 private: 110 StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader); 111 virtual ~StreamFontFileEnumerator() { } 112 113 ULONG fRefCount; 114 115 SkTScopedComPtr<IDWriteFactory> fFactory; 116 SkTScopedComPtr<IDWriteFontFile> fCurrentFile; 117 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader; 118 bool fHasNext; 119 }; 120 121 StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory, 122 IDWriteFontFileLoader* fontFileLoader) 123 : fRefCount(1) 124 , fFactory(SkRefComPtr(factory)) 125 , fCurrentFile() 126 , fFontFileLoader(SkRefComPtr(fontFileLoader)) 127 , fHasNext(true) 128 { } 129 130 HRESULT StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) { 131 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) { 132 *ppvObject = this; 133 AddRef(); 134 return S_OK; 135 } else { 136 *ppvObject = NULL; 137 return E_NOINTERFACE; 138 } 139 } 140 141 ULONG StreamFontFileEnumerator::AddRef() { 142 return InterlockedIncrement(&fRefCount); 143 } 144 145 ULONG StreamFontFileEnumerator::Release() { 146 ULONG newCount = InterlockedDecrement(&fRefCount); 147 if (0 == newCount) { 148 delete this; 149 } 150 return newCount; 151 } 152 153 HRESULT StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) { 154 *hasCurrentFile = FALSE; 155 156 if (!fHasNext) { 157 return S_OK; 158 } 159 fHasNext = false; 160 161 UINT32 dummy = 0; 162 HR(fFactory->CreateCustomFontFileReference( 163 &dummy, //cannot be NULL 164 sizeof(dummy), //even if this is 0 165 fFontFileLoader.get(), 166 &fCurrentFile)); 167 168 *hasCurrentFile = TRUE; 169 return S_OK; 170 } 171 172 HRESULT StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) { 173 if (fCurrentFile.get() == NULL) { 174 *fontFile = NULL; 175 return E_FAIL; 176 } 177 178 *fontFile = SkRefComPtr(fCurrentFile.get()); 179 return S_OK; 180 } 181 182 //////////////////////////////////////////////////////////////////////////////// 183 184 class StreamFontCollectionLoader : public IDWriteFontCollectionLoader { 185 public: 186 // IUnknown methods 187 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); 188 virtual ULONG STDMETHODCALLTYPE AddRef(); 189 virtual ULONG STDMETHODCALLTYPE Release(); 190 191 // IDWriteFontCollectionLoader methods 192 virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey( 193 IDWriteFactory* factory, 194 void const* collectionKey, 195 UINT32 collectionKeySize, 196 IDWriteFontFileEnumerator** fontFileEnumerator); 197 198 static HRESULT Create(IDWriteFontFileLoader* fontFileLoader, 199 StreamFontCollectionLoader** streamFontCollectionLoader) { 200 *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoader); 201 if (NULL == streamFontCollectionLoader) { 202 return E_OUTOFMEMORY; 203 } 204 return S_OK; 205 } 206 private: 207 StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader) 208 : fRefCount(1) 209 , fFontFileLoader(SkRefComPtr(fontFileLoader)) 210 { } 211 virtual ~StreamFontCollectionLoader() { } 212 213 ULONG fRefCount; 214 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader; 215 }; 216 217 HRESULT StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) { 218 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) { 219 *ppvObject = this; 220 AddRef(); 221 return S_OK; 222 } else { 223 *ppvObject = NULL; 224 return E_NOINTERFACE; 225 } 226 } 227 228 ULONG StreamFontCollectionLoader::AddRef() { 229 return InterlockedIncrement(&fRefCount); 230 } 231 232 ULONG StreamFontCollectionLoader::Release() { 233 ULONG newCount = InterlockedDecrement(&fRefCount); 234 if (0 == newCount) { 235 delete this; 236 } 237 return newCount; 238 } 239 240 HRESULT StreamFontCollectionLoader::CreateEnumeratorFromKey( 241 IDWriteFactory* factory, 242 void const* collectionKey, 243 UINT32 collectionKeySize, 244 IDWriteFontFileEnumerator** fontFileEnumerator) 245 { 246 SkTScopedComPtr<StreamFontFileEnumerator> enumerator; 247 HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumerator)); 248 *fontFileEnumerator = enumerator.release(); 249 return S_OK; 250 } 251 252 //////////////////////////////////////////////////////////////////////////////// 253 254 class SkFontMgr_DirectWrite : public SkFontMgr { 255 public: 256 /** localeNameLength must include the null terminator. */ 257 SkFontMgr_DirectWrite(IDWriteFactory* factory, IDWriteFontCollection* fontCollection, 258 WCHAR* localeName, int localeNameLength) 259 : fFactory(SkRefComPtr(factory)) 260 , fFontCollection(SkRefComPtr(fontCollection)) 261 , fLocaleName(localeNameLength) 262 { 263 memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR)); 264 } 265 266 protected: 267 virtual int onCountFamilies() const SK_OVERRIDE; 268 virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE; 269 virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE; 270 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE; 271 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], 272 const SkFontStyle& fontstyle) const SK_OVERRIDE; 273 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, 274 const SkFontStyle& fontstyle) const SK_OVERRIDE; 275 virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE; 276 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE; 277 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE; 278 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], 279 unsigned styleBits) const SK_OVERRIDE; 280 281 private: 282 HRESULT getByFamilyName(const WCHAR familyName[], IDWriteFontFamily** fontFamily) const; 283 HRESULT getDefaultFontFamily(IDWriteFontFamily** fontFamily) const; 284 285 /** Creates a typeface using a typeface cache. */ 286 SkTypeface* createTypefaceFromDWriteFont(IDWriteFontFace* fontFace, 287 IDWriteFont* font, 288 IDWriteFontFamily* fontFamily) const; 289 290 SkTScopedComPtr<IDWriteFactory> fFactory; 291 SkTScopedComPtr<IDWriteFontCollection> fFontCollection; 292 SkSMallocWCHAR fLocaleName; 293 mutable SkMutex fTFCacheMutex; 294 mutable SkTypefaceCache fTFCache; 295 296 friend class SkFontStyleSet_DirectWrite; 297 }; 298 299 class SkFontStyleSet_DirectWrite : public SkFontStyleSet { 300 public: 301 SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite* fontMgr, 302 IDWriteFontFamily* fontFamily) 303 : fFontMgr(SkRef(fontMgr)) 304 , fFontFamily(SkRefComPtr(fontFamily)) 305 { } 306 307 virtual int count() SK_OVERRIDE; 308 virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName) SK_OVERRIDE; 309 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE; 310 virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE; 311 312 private: 313 SkAutoTUnref<const SkFontMgr_DirectWrite> fFontMgr; 314 SkTScopedComPtr<IDWriteFontFamily> fFontFamily; 315 }; 316 317 static HRESULT are_same(IUnknown* a, IUnknown* b, bool& same) { 318 SkTScopedComPtr<IUnknown> iunkA; 319 HRM(a->QueryInterface(&iunkA), "Failed to QI<IUnknown> for a."); 320 321 SkTScopedComPtr<IUnknown> iunkB; 322 HRM(b->QueryInterface(&iunkB), "Failed to QI<IUnknown> for b."); 323 324 same = (iunkA.get() == iunkB.get()); 325 return S_OK; 326 } 327 328 struct ProtoDWriteTypeface { 329 IDWriteFontFace* fDWriteFontFace; 330 IDWriteFont* fDWriteFont; 331 IDWriteFontFamily* fDWriteFontFamily; 332 }; 333 334 static bool FindByDWriteFont(SkTypeface* cached, SkTypeface::Style, void* ctx) { 335 DWriteFontTypeface* cshFace = reinterpret_cast<DWriteFontTypeface*>(cached); 336 ProtoDWriteTypeface* ctxFace = reinterpret_cast<ProtoDWriteTypeface*>(ctx); 337 bool same; 338 339 //Check to see if the two fonts are identical. 340 HRB(are_same(cshFace->fDWriteFont.get(), ctxFace->fDWriteFont, same)); 341 if (same) { 342 return true; 343 } 344 345 HRB(are_same(cshFace->fDWriteFontFace.get(), ctxFace->fDWriteFontFace, same)); 346 if (same) { 347 return true; 348 } 349 350 //Check if the two fonts share the same loader and have the same key. 351 UINT32 cshNumFiles; 352 UINT32 ctxNumFiles; 353 HRB(cshFace->fDWriteFontFace->GetFiles(&cshNumFiles, NULL)); 354 HRB(ctxFace->fDWriteFontFace->GetFiles(&ctxNumFiles, NULL)); 355 if (cshNumFiles != ctxNumFiles) { 356 return false; 357 } 358 359 SkTScopedComPtr<IDWriteFontFile> cshFontFile; 360 SkTScopedComPtr<IDWriteFontFile> ctxFontFile; 361 HRB(cshFace->fDWriteFontFace->GetFiles(&cshNumFiles, &cshFontFile)); 362 HRB(ctxFace->fDWriteFontFace->GetFiles(&ctxNumFiles, &ctxFontFile)); 363 364 //for (each file) { //we currently only admit fonts from one file. 365 SkTScopedComPtr<IDWriteFontFileLoader> cshFontFileLoader; 366 SkTScopedComPtr<IDWriteFontFileLoader> ctxFontFileLoader; 367 HRB(cshFontFile->GetLoader(&cshFontFileLoader)); 368 HRB(ctxFontFile->GetLoader(&ctxFontFileLoader)); 369 HRB(are_same(cshFontFileLoader.get(), ctxFontFileLoader.get(), same)); 370 if (!same) { 371 return false; 372 } 373 //} 374 375 const void* cshRefKey; 376 UINT32 cshRefKeySize; 377 const void* ctxRefKey; 378 UINT32 ctxRefKeySize; 379 HRB(cshFontFile->GetReferenceKey(&cshRefKey, &cshRefKeySize)); 380 HRB(ctxFontFile->GetReferenceKey(&ctxRefKey, &ctxRefKeySize)); 381 if (cshRefKeySize != ctxRefKeySize) { 382 return false; 383 } 384 if (0 != memcmp(cshRefKey, ctxRefKey, ctxRefKeySize)) { 385 return false; 386 } 387 388 //TODO: better means than comparing name strings? 389 //NOTE: .ttc and fake bold/italic will end up here. 390 SkTScopedComPtr<IDWriteLocalizedStrings> cshFamilyNames; 391 SkTScopedComPtr<IDWriteLocalizedStrings> cshFaceNames; 392 HRB(cshFace->fDWriteFontFamily->GetFamilyNames(&cshFamilyNames)); 393 HRB(cshFace->fDWriteFont->GetFaceNames(&cshFaceNames)); 394 UINT32 cshFamilyNameLength; 395 UINT32 cshFaceNameLength; 396 HRB(cshFamilyNames->GetStringLength(0, &cshFamilyNameLength)); 397 HRB(cshFaceNames->GetStringLength(0, &cshFaceNameLength)); 398 399 SkTScopedComPtr<IDWriteLocalizedStrings> ctxFamilyNames; 400 SkTScopedComPtr<IDWriteLocalizedStrings> ctxFaceNames; 401 HRB(ctxFace->fDWriteFontFamily->GetFamilyNames(&ctxFamilyNames)); 402 HRB(ctxFace->fDWriteFont->GetFaceNames(&ctxFaceNames)); 403 UINT32 ctxFamilyNameLength; 404 UINT32 ctxFaceNameLength; 405 HRB(ctxFamilyNames->GetStringLength(0, &ctxFamilyNameLength)); 406 HRB(ctxFaceNames->GetStringLength(0, &ctxFaceNameLength)); 407 408 if (cshFamilyNameLength != ctxFamilyNameLength || 409 cshFaceNameLength != ctxFaceNameLength) 410 { 411 return false; 412 } 413 414 SkSMallocWCHAR cshFamilyName(cshFamilyNameLength+1); 415 SkSMallocWCHAR cshFaceName(cshFaceNameLength+1); 416 HRB(cshFamilyNames->GetString(0, cshFamilyName.get(), cshFamilyNameLength+1)); 417 HRB(cshFaceNames->GetString(0, cshFaceName.get(), cshFaceNameLength+1)); 418 419 SkSMallocWCHAR ctxFamilyName(ctxFamilyNameLength+1); 420 SkSMallocWCHAR ctxFaceName(ctxFaceNameLength+1); 421 HRB(ctxFamilyNames->GetString(0, ctxFamilyName.get(), ctxFamilyNameLength+1)); 422 HRB(ctxFaceNames->GetString(0, ctxFaceName.get(), ctxFaceNameLength+1)); 423 424 return wcscmp(cshFamilyName.get(), ctxFamilyName.get()) == 0 && 425 wcscmp(cshFaceName.get(), ctxFaceName.get()) == 0; 426 } 427 428 SkTypeface* SkFontMgr_DirectWrite::createTypefaceFromDWriteFont( 429 IDWriteFontFace* fontFace, 430 IDWriteFont* font, 431 IDWriteFontFamily* fontFamily) const { 432 SkAutoMutexAcquire ama(fTFCacheMutex); 433 ProtoDWriteTypeface spec = { fontFace, font, fontFamily }; 434 SkTypeface* face = fTFCache.findByProcAndRef(FindByDWriteFont, &spec); 435 if (NULL == face) { 436 face = DWriteFontTypeface::Create(fFactory.get(), fontFace, font, fontFamily); 437 if (face) { 438 fTFCache.add(face, get_style(font), true); 439 } 440 } 441 return face; 442 } 443 444 int SkFontMgr_DirectWrite::onCountFamilies() const { 445 return fFontCollection->GetFontFamilyCount(); 446 } 447 448 void SkFontMgr_DirectWrite::onGetFamilyName(int index, SkString* familyName) const { 449 SkTScopedComPtr<IDWriteFontFamily> fontFamily; 450 HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family."); 451 452 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames; 453 HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names."); 454 455 sk_get_locale_string(familyNames.get(), fLocaleName.get(), familyName); 456 } 457 458 SkFontStyleSet* SkFontMgr_DirectWrite::onCreateStyleSet(int index) const { 459 SkTScopedComPtr<IDWriteFontFamily> fontFamily; 460 HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family."); 461 462 return SkNEW_ARGS(SkFontStyleSet_DirectWrite, (this, fontFamily.get())); 463 } 464 465 SkFontStyleSet* SkFontMgr_DirectWrite::onMatchFamily(const char familyName[]) const { 466 SkSMallocWCHAR dwFamilyName; 467 HRN(sk_cstring_to_wchar(familyName, &dwFamilyName)); 468 469 UINT32 index; 470 BOOL exists; 471 HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists), 472 "Failed while finding family by name."); 473 if (!exists) { 474 return NULL; 475 } 476 477 return this->onCreateStyleSet(index); 478 } 479 480 SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyle(const char familyName[], 481 const SkFontStyle& fontstyle) const { 482 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); 483 return sset->matchStyle(fontstyle); 484 } 485 486 SkTypeface* SkFontMgr_DirectWrite::onMatchFaceStyle(const SkTypeface* familyMember, 487 const SkFontStyle& fontstyle) const { 488 SkString familyName; 489 SkFontStyleSet_DirectWrite sset( 490 this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get() 491 ); 492 return sset.matchStyle(fontstyle); 493 } 494 495 template <typename T> class SkAutoIDWriteUnregister { 496 public: 497 SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister) 498 : fFactory(factory), fUnregister(unregister) 499 { } 500 501 ~SkAutoIDWriteUnregister() { 502 if (fUnregister) { 503 unregister(fFactory, fUnregister); 504 } 505 } 506 507 T* detatch() { 508 T* old = fUnregister; 509 fUnregister = NULL; 510 return old; 511 } 512 513 private: 514 HRESULT unregister(IDWriteFactory* factory, IDWriteFontFileLoader* unregister) { 515 return factory->UnregisterFontFileLoader(unregister); 516 } 517 518 HRESULT unregister(IDWriteFactory* factory, IDWriteFontCollectionLoader* unregister) { 519 return factory->UnregisterFontCollectionLoader(unregister); 520 } 521 522 IDWriteFactory* fFactory; 523 T* fUnregister; 524 }; 525 526 SkTypeface* SkFontMgr_DirectWrite::onCreateFromStream(SkStream* stream, int ttcIndex) const { 527 SkTScopedComPtr<StreamFontFileLoader> fontFileLoader; 528 HRN(StreamFontFileLoader::Create(stream, &fontFileLoader)); 529 HRN(fFactory->RegisterFontFileLoader(fontFileLoader.get())); 530 SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader( 531 fFactory.get(), fontFileLoader.get()); 532 533 SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader; 534 HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollectionLoader)); 535 HRN(fFactory->RegisterFontCollectionLoader(fontCollectionLoader.get())); 536 SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollectionLoader( 537 fFactory.get(), fontCollectionLoader.get()); 538 539 SkTScopedComPtr<IDWriteFontCollection> fontCollection; 540 HRN(fFactory->CreateCustomFontCollection(fontCollectionLoader.get(), NULL, 0, &fontCollection)); 541 542 // Find the first non-simulated font which has the given ttc index. 543 UINT32 familyCount = fontCollection->GetFontFamilyCount(); 544 for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) { 545 SkTScopedComPtr<IDWriteFontFamily> fontFamily; 546 HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily)); 547 548 UINT32 fontCount = fontFamily->GetFontCount(); 549 for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) { 550 SkTScopedComPtr<IDWriteFont> font; 551 HRN(fontFamily->GetFont(fontIndex, &font)); 552 if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) { 553 continue; 554 } 555 556 SkTScopedComPtr<IDWriteFontFace> fontFace; 557 HRN(font->CreateFontFace(&fontFace)); 558 559 UINT32 faceIndex = fontFace->GetIndex(); 560 if (faceIndex == ttcIndex) { 561 return DWriteFontTypeface::Create(fFactory.get(), 562 fontFace.get(), font.get(), fontFamily.get(), 563 autoUnregisterFontFileLoader.detatch(), 564 autoUnregisterFontCollectionLoader.detatch()); 565 } 566 } 567 } 568 569 return NULL; 570 } 571 572 SkTypeface* SkFontMgr_DirectWrite::onCreateFromData(SkData* data, int ttcIndex) const { 573 SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data))); 574 return this->createFromStream(stream, ttcIndex); 575 } 576 577 SkTypeface* SkFontMgr_DirectWrite::onCreateFromFile(const char path[], int ttcIndex) const { 578 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); 579 return this->createFromStream(stream, ttcIndex); 580 } 581 582 HRESULT SkFontMgr_DirectWrite::getByFamilyName(const WCHAR wideFamilyName[], 583 IDWriteFontFamily** fontFamily) const { 584 UINT32 index; 585 BOOL exists; 586 HR(fFontCollection->FindFamilyName(wideFamilyName, &index, &exists)); 587 588 if (exists) { 589 HR(fFontCollection->GetFontFamily(index, fontFamily)); 590 } 591 return S_OK; 592 } 593 594 HRESULT SkFontMgr_DirectWrite::getDefaultFontFamily(IDWriteFontFamily** fontFamily) const { 595 NONCLIENTMETRICSW metrics; 596 metrics.cbSize = sizeof(metrics); 597 if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 598 sizeof(metrics), 599 &metrics, 600 0)) { 601 return E_UNEXPECTED; 602 } 603 HRM(this->getByFamilyName(metrics.lfMessageFont.lfFaceName, fontFamily), 604 "Could not create DWrite font family from LOGFONT."); 605 return S_OK; 606 } 607 608 SkTypeface* SkFontMgr_DirectWrite::onLegacyCreateTypeface(const char familyName[], 609 unsigned styleBits) const { 610 SkTScopedComPtr<IDWriteFontFamily> fontFamily; 611 if (familyName) { 612 SkSMallocWCHAR wideFamilyName; 613 if (SUCCEEDED(sk_cstring_to_wchar(familyName, &wideFamilyName))) { 614 this->getByFamilyName(wideFamilyName, &fontFamily); 615 } 616 } 617 618 if (NULL == fontFamily.get()) { 619 // No family with given name, try default. 620 HRNM(this->getDefaultFontFamily(&fontFamily), "Could not get default font family."); 621 } 622 623 if (NULL == fontFamily.get()) { 624 // Could not obtain the default font. 625 HRNM(fFontCollection->GetFontFamily(0, &fontFamily), 626 "Could not get default-default font family."); 627 } 628 629 SkTScopedComPtr<IDWriteFont> font; 630 DWRITE_FONT_WEIGHT weight = (styleBits & SkTypeface::kBold) 631 ? DWRITE_FONT_WEIGHT_BOLD 632 : DWRITE_FONT_WEIGHT_NORMAL; 633 DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_NORMAL; 634 DWRITE_FONT_STYLE italic = (styleBits & SkTypeface::kItalic) 635 ? DWRITE_FONT_STYLE_ITALIC 636 : DWRITE_FONT_STYLE_NORMAL; 637 HRNM(fontFamily->GetFirstMatchingFont(weight, stretch, italic, &font), 638 "Could not get matching font."); 639 640 SkTScopedComPtr<IDWriteFontFace> fontFace; 641 HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); 642 643 return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get()); 644 } 645 646 /////////////////////////////////////////////////////////////////////////////// 647 648 int SkFontStyleSet_DirectWrite::count() { 649 return fFontFamily->GetFontCount(); 650 } 651 652 SkTypeface* SkFontStyleSet_DirectWrite::createTypeface(int index) { 653 SkTScopedComPtr<IDWriteFont> font; 654 HRNM(fFontFamily->GetFont(index, &font), "Could not get font."); 655 656 SkTScopedComPtr<IDWriteFontFace> fontFace; 657 HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); 658 659 return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get()); 660 } 661 662 void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) { 663 SkTScopedComPtr<IDWriteFont> font; 664 HRVM(fFontFamily->GetFont(index, &font), "Could not get font."); 665 666 if (fs) { 667 SkFontStyle::Slant slant; 668 switch (font->GetStyle()) { 669 case DWRITE_FONT_STYLE_NORMAL: 670 slant = SkFontStyle::kUpright_Slant; 671 break; 672 case DWRITE_FONT_STYLE_OBLIQUE: 673 case DWRITE_FONT_STYLE_ITALIC: 674 slant = SkFontStyle::kItalic_Slant; 675 break; 676 default: 677 SkASSERT(false); 678 } 679 680 int weight = font->GetWeight(); 681 int width = font->GetStretch(); 682 683 *fs = SkFontStyle(weight, width, slant); 684 } 685 686 if (styleName) { 687 SkTScopedComPtr<IDWriteLocalizedStrings> faceNames; 688 if (SUCCEEDED(font->GetFaceNames(&faceNames))) { 689 sk_get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName); 690 } 691 } 692 } 693 694 SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) { 695 DWRITE_FONT_STYLE slant; 696 switch (pattern.slant()) { 697 case SkFontStyle::kUpright_Slant: 698 slant = DWRITE_FONT_STYLE_NORMAL; 699 break; 700 case SkFontStyle::kItalic_Slant: 701 slant = DWRITE_FONT_STYLE_ITALIC; 702 break; 703 default: 704 SkASSERT(false); 705 } 706 707 DWRITE_FONT_WEIGHT weight = (DWRITE_FONT_WEIGHT)pattern.weight(); 708 DWRITE_FONT_STRETCH width = (DWRITE_FONT_STRETCH)pattern.width(); 709 710 SkTScopedComPtr<IDWriteFont> font; 711 // TODO: perhaps use GetMatchingFonts and get the least simulated? 712 HRNM(fFontFamily->GetFirstMatchingFont(weight, width, slant, &font), 713 "Could not match font in family."); 714 715 SkTScopedComPtr<IDWriteFontFace> fontFace; 716 HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); 717 718 return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), 719 fFontFamily.get()); 720 } 721 722 //////////////////////////////////////////////////////////////////////////////// 723 #include "SkTypeface_win.h" 724 725 SK_API SkFontMgr* SkFontMgr_New_DirectWrite(IDWriteFactory* factory) { 726 if (NULL == factory) { 727 factory = sk_get_dwrite_factory(); 728 if (NULL == factory) { 729 return NULL; 730 } 731 } 732 733 SkTScopedComPtr<IDWriteFontCollection> sysFontCollection; 734 HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE), 735 "Could not get system font collection."); 736 737 WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH]; 738 WCHAR* localeName = NULL; 739 int localeNameLen = 0; 740 741 // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP. 742 SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL; 743 HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc); 744 if (NULL == getUserDefaultLocaleNameProc) { 745 SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName."); 746 } else { 747 localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH); 748 if (localeNameLen) { 749 localeName = localeNameStorage; 750 }; 751 } 752 753 return SkNEW_ARGS(SkFontMgr_DirectWrite, (factory, sysFontCollection.get(), 754 localeName, localeNameLen)); 755 } 756 757 #include "SkFontMgr_indirect.h" 758 SK_API SkFontMgr* SkFontMgr_New_DirectWriteRenderer(SkRemotableFontMgr* proxy) { 759 SkAutoTUnref<SkFontMgr> impl(SkFontMgr_New_DirectWrite()); 760 if (impl.get() == NULL) { 761 return NULL; 762 } 763 return SkNEW_ARGS(SkFontMgr_Indirect, (impl.get(), proxy)); 764 } 765