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