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
24class StreamFontFileLoader : public IDWriteFontFileLoader {
25public:
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
47private:
48    StreamFontFileLoader(SkStream* stream) : fRefCount(1), fStream(SkRef(stream)) { }
49    virtual ~StreamFontFileLoader() { }
50
51    ULONG fRefCount;
52};
53
54HRESULT 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
65ULONG StreamFontFileLoader::AddRef() {
66    return InterlockedIncrement(&fRefCount);
67}
68
69ULONG StreamFontFileLoader::Release() {
70    ULONG newCount = InterlockedDecrement(&fRefCount);
71    if (0 == newCount) {
72        delete this;
73    }
74    return newCount;
75}
76
77HRESULT 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
90class StreamFontFileEnumerator : public IDWriteFontFileEnumerator {
91public:
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    }
109private:
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
121StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory,
122                                                   IDWriteFontFileLoader* fontFileLoader)
123    : fRefCount(1)
124    , fFactory(SkRefComPtr(factory))
125    , fCurrentFile()
126    , fFontFileLoader(SkRefComPtr(fontFileLoader))
127    , fHasNext(true)
128{ }
129
130HRESULT 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
141ULONG StreamFontFileEnumerator::AddRef() {
142    return InterlockedIncrement(&fRefCount);
143}
144
145ULONG StreamFontFileEnumerator::Release() {
146    ULONG newCount = InterlockedDecrement(&fRefCount);
147    if (0 == newCount) {
148        delete this;
149    }
150    return newCount;
151}
152
153HRESULT 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
172HRESULT 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
184class StreamFontCollectionLoader : public IDWriteFontCollectionLoader {
185public:
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    }
206private:
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
217HRESULT 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
228ULONG StreamFontCollectionLoader::AddRef() {
229    return InterlockedIncrement(&fRefCount);
230}
231
232ULONG StreamFontCollectionLoader::Release() {
233    ULONG newCount = InterlockedDecrement(&fRefCount);
234    if (0 == newCount) {
235        delete this;
236    }
237    return newCount;
238}
239
240HRESULT 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
254class SkFontMgr_DirectWrite : public SkFontMgr {
255public:
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
266protected:
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
281private:
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
299class SkFontStyleSet_DirectWrite : public SkFontStyleSet {
300public:
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
312private:
313    SkAutoTUnref<const SkFontMgr_DirectWrite> fFontMgr;
314    SkTScopedComPtr<IDWriteFontFamily> fFontFamily;
315};
316
317static 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
328struct ProtoDWriteTypeface {
329    IDWriteFontFace* fDWriteFontFace;
330    IDWriteFont* fDWriteFont;
331    IDWriteFontFamily* fDWriteFontFamily;
332};
333
334static 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
428SkTypeface* 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
444int SkFontMgr_DirectWrite::onCountFamilies() const {
445    return fFontCollection->GetFontFamilyCount();
446}
447
448void 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
458SkFontStyleSet* 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
465SkFontStyleSet* 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
480SkTypeface* 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
486SkTypeface* 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
495template <typename T> class SkAutoIDWriteUnregister {
496public:
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
513private:
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
526SkTypeface* 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
572SkTypeface* SkFontMgr_DirectWrite::onCreateFromData(SkData* data, int ttcIndex) const {
573    SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data)));
574    return this->createFromStream(stream, ttcIndex);
575}
576
577SkTypeface* SkFontMgr_DirectWrite::onCreateFromFile(const char path[], int ttcIndex) const {
578    SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
579    return this->createFromStream(stream, ttcIndex);
580}
581
582HRESULT 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
594HRESULT 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
608SkTypeface* 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
648int SkFontStyleSet_DirectWrite::count() {
649    return fFontFamily->GetFontCount();
650}
651
652SkTypeface* 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
662void 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
694SkTypeface* 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
725SK_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"
758SK_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