Home | History | Annotate | Download | only in ports
      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