1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2014 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci#include "src/utils/win/SkDWriteNTDDI_VERSION.h"
8cb93a386Sopenharmony_ci
9cb93a386Sopenharmony_ci#include "include/core/SkTypes.h"
10cb93a386Sopenharmony_ci#if defined(SK_BUILD_FOR_WIN)
11cb93a386Sopenharmony_ci
12cb93a386Sopenharmony_ci#include "include/core/SkStream.h"
13cb93a386Sopenharmony_ci#include "include/core/SkString.h"
14cb93a386Sopenharmony_ci#include "include/core/SkTypes.h"
15cb93a386Sopenharmony_ci#include "include/ports/SkRemotableFontMgr.h"
16cb93a386Sopenharmony_ci#include "include/private/SkMutex.h"
17cb93a386Sopenharmony_ci#include "include/private/SkTArray.h"
18cb93a386Sopenharmony_ci#include "src/ports/SkTypeface_win_dw.h"
19cb93a386Sopenharmony_ci#include "src/utils/SkUTF.h"
20cb93a386Sopenharmony_ci#include "src/utils/win/SkDWrite.h"
21cb93a386Sopenharmony_ci#include "src/utils/win/SkDWriteFontFileStream.h"
22cb93a386Sopenharmony_ci#include "src/utils/win/SkHRESULT.h"
23cb93a386Sopenharmony_ci#include "src/utils/win/SkObjBase.h"
24cb93a386Sopenharmony_ci#include "src/utils/win/SkTScopedComPtr.h"
25cb93a386Sopenharmony_ci
26cb93a386Sopenharmony_ci#include <dwrite.h>
27cb93a386Sopenharmony_ci
28cb93a386Sopenharmony_ciclass SK_API SkRemotableFontMgr_DirectWrite : public SkRemotableFontMgr {
29cb93a386Sopenharmony_ciprivate:
30cb93a386Sopenharmony_ci    struct DataId {
31cb93a386Sopenharmony_ci        IUnknown* fLoader;  // In COM only IUnknown pointers may be safely used for identity.
32cb93a386Sopenharmony_ci        void* fKey;
33cb93a386Sopenharmony_ci        UINT32 fKeySize;
34cb93a386Sopenharmony_ci
35cb93a386Sopenharmony_ci        DataId() { }
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_ci        DataId(DataId&& that) : fLoader(that.fLoader), fKey(that.fKey), fKeySize(that.fKeySize) {
38cb93a386Sopenharmony_ci            that.fLoader = nullptr;
39cb93a386Sopenharmony_ci            that.fKey = nullptr;
40cb93a386Sopenharmony_ci            SkDEBUGCODE(that.fKeySize = 0xFFFFFFFF;)
41cb93a386Sopenharmony_ci        }
42cb93a386Sopenharmony_ci
43cb93a386Sopenharmony_ci        ~DataId() {
44cb93a386Sopenharmony_ci            if (fLoader) {
45cb93a386Sopenharmony_ci                fLoader->Release();
46cb93a386Sopenharmony_ci            }
47cb93a386Sopenharmony_ci            sk_free(fKey);
48cb93a386Sopenharmony_ci        }
49cb93a386Sopenharmony_ci    };
50cb93a386Sopenharmony_ci
51cb93a386Sopenharmony_ci    mutable SkTArray<DataId> fDataIdCache;
52cb93a386Sopenharmony_ci    mutable SkMutex fDataIdCacheMutex;
53cb93a386Sopenharmony_ci
54cb93a386Sopenharmony_ci    int FindOrAdd(IDWriteFontFileLoader* fontFileLoader,
55cb93a386Sopenharmony_ci                  const void* refKey, UINT32 refKeySize) const
56cb93a386Sopenharmony_ci    {
57cb93a386Sopenharmony_ci        SkTScopedComPtr<IUnknown> fontFileLoaderId;
58cb93a386Sopenharmony_ci        HR_GENERAL(fontFileLoader->QueryInterface(&fontFileLoaderId),
59cb93a386Sopenharmony_ci                   "Failed to re-convert to IDWriteFontFileLoader.",
60cb93a386Sopenharmony_ci                   SkFontIdentity::kInvalidDataId);
61cb93a386Sopenharmony_ci
62cb93a386Sopenharmony_ci        SkAutoMutexExclusive ama(fDataIdCacheMutex);
63cb93a386Sopenharmony_ci        int count = fDataIdCache.count();
64cb93a386Sopenharmony_ci        int i;
65cb93a386Sopenharmony_ci        for (i = 0; i < count; ++i) {
66cb93a386Sopenharmony_ci            const DataId& current = fDataIdCache[i];
67cb93a386Sopenharmony_ci            if (fontFileLoaderId.get() == current.fLoader &&
68cb93a386Sopenharmony_ci                refKeySize == current.fKeySize &&
69cb93a386Sopenharmony_ci                0 == memcmp(refKey, current.fKey, refKeySize))
70cb93a386Sopenharmony_ci            {
71cb93a386Sopenharmony_ci                return i;
72cb93a386Sopenharmony_ci            }
73cb93a386Sopenharmony_ci        }
74cb93a386Sopenharmony_ci        DataId& added = fDataIdCache.push_back();
75cb93a386Sopenharmony_ci        added.fLoader = fontFileLoaderId.release();  // Ref is passed.
76cb93a386Sopenharmony_ci        added.fKey = sk_malloc_throw(refKeySize);
77cb93a386Sopenharmony_ci        memcpy(added.fKey, refKey, refKeySize);
78cb93a386Sopenharmony_ci        added.fKeySize = refKeySize;
79cb93a386Sopenharmony_ci
80cb93a386Sopenharmony_ci        return i;
81cb93a386Sopenharmony_ci    }
82cb93a386Sopenharmony_ci
83cb93a386Sopenharmony_cipublic:
84cb93a386Sopenharmony_ci
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_ci    /** localeNameLength must include the null terminator. */
87cb93a386Sopenharmony_ci    SkRemotableFontMgr_DirectWrite(IDWriteFontCollection* fontCollection,
88cb93a386Sopenharmony_ci                                   WCHAR* localeName, int localeNameLength)
89cb93a386Sopenharmony_ci        : fFontCollection(SkRefComPtr(fontCollection))
90cb93a386Sopenharmony_ci        , fLocaleName(localeNameLength)
91cb93a386Sopenharmony_ci    {
92cb93a386Sopenharmony_ci        memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
93cb93a386Sopenharmony_ci    }
94cb93a386Sopenharmony_ci
95cb93a386Sopenharmony_ci    HRESULT FontToIdentity(IDWriteFont* font, SkFontIdentity* fontId) const {
96cb93a386Sopenharmony_ci        SkTScopedComPtr<IDWriteFontFace> fontFace;
97cb93a386Sopenharmony_ci        HRM(font->CreateFontFace(&fontFace), "Could not create font face.");
98cb93a386Sopenharmony_ci
99cb93a386Sopenharmony_ci        UINT32 numFiles;
100cb93a386Sopenharmony_ci        HR(fontFace->GetFiles(&numFiles, nullptr));
101cb93a386Sopenharmony_ci        if (numFiles > 1) {
102cb93a386Sopenharmony_ci            return E_FAIL;
103cb93a386Sopenharmony_ci        }
104cb93a386Sopenharmony_ci
105cb93a386Sopenharmony_ci        // data id
106cb93a386Sopenharmony_ci        SkTScopedComPtr<IDWriteFontFile> fontFile;
107cb93a386Sopenharmony_ci        HR(fontFace->GetFiles(&numFiles, &fontFile));
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_ci        SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
110cb93a386Sopenharmony_ci        HR(fontFile->GetLoader(&fontFileLoader));
111cb93a386Sopenharmony_ci
112cb93a386Sopenharmony_ci        const void* refKey;
113cb93a386Sopenharmony_ci        UINT32 refKeySize;
114cb93a386Sopenharmony_ci        HR(fontFile->GetReferenceKey(&refKey, &refKeySize));
115cb93a386Sopenharmony_ci
116cb93a386Sopenharmony_ci        fontId->fDataId = FindOrAdd(fontFileLoader.get(), refKey, refKeySize);
117cb93a386Sopenharmony_ci
118cb93a386Sopenharmony_ci        // index
119cb93a386Sopenharmony_ci        fontId->fTtcIndex = fontFace->GetIndex();
120cb93a386Sopenharmony_ci
121cb93a386Sopenharmony_ci        // style
122cb93a386Sopenharmony_ci        fontId->fFontStyle = get_style(font);
123cb93a386Sopenharmony_ci        return S_OK;
124cb93a386Sopenharmony_ci    }
125cb93a386Sopenharmony_ci
126cb93a386Sopenharmony_ci    SkRemotableFontIdentitySet* getIndex(int familyIndex) const override {
127cb93a386Sopenharmony_ci        SkTScopedComPtr<IDWriteFontFamily> fontFamily;
128cb93a386Sopenharmony_ci        HRNM(fFontCollection->GetFontFamily(familyIndex, &fontFamily),
129cb93a386Sopenharmony_ci             "Could not get requested family.");
130cb93a386Sopenharmony_ci
131cb93a386Sopenharmony_ci        int count = fontFamily->GetFontCount();
132cb93a386Sopenharmony_ci        SkFontIdentity* fontIds;
133cb93a386Sopenharmony_ci        sk_sp<SkRemotableFontIdentitySet> fontIdSet(
134cb93a386Sopenharmony_ci            new SkRemotableFontIdentitySet(count, &fontIds));
135cb93a386Sopenharmony_ci        for (int fontIndex = 0; fontIndex < count; ++fontIndex) {
136cb93a386Sopenharmony_ci            SkTScopedComPtr<IDWriteFont> font;
137cb93a386Sopenharmony_ci            HRNM(fontFamily->GetFont(fontIndex, &font), "Could not get font.");
138cb93a386Sopenharmony_ci
139cb93a386Sopenharmony_ci            HRN(FontToIdentity(font.get(), &fontIds[fontIndex]));
140cb93a386Sopenharmony_ci        }
141cb93a386Sopenharmony_ci        return fontIdSet.release();
142cb93a386Sopenharmony_ci    }
143cb93a386Sopenharmony_ci
144cb93a386Sopenharmony_ci    virtual SkFontIdentity matchIndexStyle(int familyIndex,
145cb93a386Sopenharmony_ci                                           const SkFontStyle& pattern) const override
146cb93a386Sopenharmony_ci    {
147cb93a386Sopenharmony_ci        SkFontIdentity identity = { SkFontIdentity::kInvalidDataId };
148cb93a386Sopenharmony_ci
149cb93a386Sopenharmony_ci        SkTScopedComPtr<IDWriteFontFamily> fontFamily;
150cb93a386Sopenharmony_ci        HR_GENERAL(fFontCollection->GetFontFamily(familyIndex, &fontFamily),
151cb93a386Sopenharmony_ci                   "Could not get requested family.",
152cb93a386Sopenharmony_ci                   identity);
153cb93a386Sopenharmony_ci
154cb93a386Sopenharmony_ci        const DWriteStyle dwStyle(pattern);
155cb93a386Sopenharmony_ci        SkTScopedComPtr<IDWriteFont> font;
156cb93a386Sopenharmony_ci        HR_GENERAL(fontFamily->GetFirstMatchingFont(dwStyle.fWeight, dwStyle.fWidth,
157cb93a386Sopenharmony_ci                                                    dwStyle.fSlant, &font),
158cb93a386Sopenharmony_ci                   "Could not match font in family.",
159cb93a386Sopenharmony_ci                   identity);
160cb93a386Sopenharmony_ci
161cb93a386Sopenharmony_ci        HR_GENERAL(FontToIdentity(font.get(), &identity), nullptr, identity);
162cb93a386Sopenharmony_ci
163cb93a386Sopenharmony_ci        return identity;
164cb93a386Sopenharmony_ci    }
165cb93a386Sopenharmony_ci
166cb93a386Sopenharmony_ci    static HRESULT getDefaultFontFamilyName(SkSMallocWCHAR* name) {
167cb93a386Sopenharmony_ci        NONCLIENTMETRICSW metrics;
168cb93a386Sopenharmony_ci        metrics.cbSize = sizeof(metrics);
169cb93a386Sopenharmony_ci        if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
170cb93a386Sopenharmony_ci                                       sizeof(metrics),
171cb93a386Sopenharmony_ci                                       &metrics,
172cb93a386Sopenharmony_ci                                       0)) {
173cb93a386Sopenharmony_ci            return E_UNEXPECTED;
174cb93a386Sopenharmony_ci        }
175cb93a386Sopenharmony_ci
176cb93a386Sopenharmony_ci        size_t len = wcsnlen_s(metrics.lfMessageFont.lfFaceName, LF_FACESIZE) + 1;
177cb93a386Sopenharmony_ci        if (0 != wcsncpy_s(name->reset(len), len, metrics.lfMessageFont.lfFaceName, _TRUNCATE)) {
178cb93a386Sopenharmony_ci            return E_UNEXPECTED;
179cb93a386Sopenharmony_ci        }
180cb93a386Sopenharmony_ci
181cb93a386Sopenharmony_ci        return S_OK;
182cb93a386Sopenharmony_ci    }
183cb93a386Sopenharmony_ci
184cb93a386Sopenharmony_ci    SkRemotableFontIdentitySet* matchName(const char familyName[]) const override {
185cb93a386Sopenharmony_ci        SkSMallocWCHAR dwFamilyName;
186cb93a386Sopenharmony_ci        if (nullptr == familyName) {
187cb93a386Sopenharmony_ci            HR_GENERAL(getDefaultFontFamilyName(&dwFamilyName),
188cb93a386Sopenharmony_ci                       nullptr, SkRemotableFontIdentitySet::NewEmpty());
189cb93a386Sopenharmony_ci        } else {
190cb93a386Sopenharmony_ci            HR_GENERAL(sk_cstring_to_wchar(familyName, &dwFamilyName),
191cb93a386Sopenharmony_ci                       nullptr, SkRemotableFontIdentitySet::NewEmpty());
192cb93a386Sopenharmony_ci        }
193cb93a386Sopenharmony_ci
194cb93a386Sopenharmony_ci        UINT32 index;
195cb93a386Sopenharmony_ci        BOOL exists;
196cb93a386Sopenharmony_ci        HR_GENERAL(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
197cb93a386Sopenharmony_ci                   "Failed while finding family by name.",
198cb93a386Sopenharmony_ci                   SkRemotableFontIdentitySet::NewEmpty());
199cb93a386Sopenharmony_ci        if (!exists) {
200cb93a386Sopenharmony_ci            return SkRemotableFontIdentitySet::NewEmpty();
201cb93a386Sopenharmony_ci        }
202cb93a386Sopenharmony_ci
203cb93a386Sopenharmony_ci        return this->getIndex(index);
204cb93a386Sopenharmony_ci    }
205cb93a386Sopenharmony_ci
206cb93a386Sopenharmony_ci    virtual SkFontIdentity matchNameStyle(const char familyName[],
207cb93a386Sopenharmony_ci                                          const SkFontStyle& style) const override
208cb93a386Sopenharmony_ci    {
209cb93a386Sopenharmony_ci        SkFontIdentity identity = { SkFontIdentity::kInvalidDataId };
210cb93a386Sopenharmony_ci
211cb93a386Sopenharmony_ci        SkSMallocWCHAR dwFamilyName;
212cb93a386Sopenharmony_ci        if (nullptr == familyName) {
213cb93a386Sopenharmony_ci            HR_GENERAL(getDefaultFontFamilyName(&dwFamilyName), nullptr, identity);
214cb93a386Sopenharmony_ci        } else {
215cb93a386Sopenharmony_ci            HR_GENERAL(sk_cstring_to_wchar(familyName, &dwFamilyName), nullptr, identity);
216cb93a386Sopenharmony_ci        }
217cb93a386Sopenharmony_ci
218cb93a386Sopenharmony_ci        UINT32 index;
219cb93a386Sopenharmony_ci        BOOL exists;
220cb93a386Sopenharmony_ci        HR_GENERAL(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
221cb93a386Sopenharmony_ci                   "Failed while finding family by name.",
222cb93a386Sopenharmony_ci                   identity);
223cb93a386Sopenharmony_ci        if (!exists) {
224cb93a386Sopenharmony_ci            return identity;
225cb93a386Sopenharmony_ci        }
226cb93a386Sopenharmony_ci
227cb93a386Sopenharmony_ci        return this->matchIndexStyle(index, style);
228cb93a386Sopenharmony_ci    }
229cb93a386Sopenharmony_ci
230cb93a386Sopenharmony_ci    class FontFallbackRenderer : public IDWriteTextRenderer {
231cb93a386Sopenharmony_ci    public:
232cb93a386Sopenharmony_ci        FontFallbackRenderer(const SkRemotableFontMgr_DirectWrite* outer, UINT32 character)
233cb93a386Sopenharmony_ci            : fRefCount(1), fOuter(SkSafeRef(outer)), fCharacter(character) {
234cb93a386Sopenharmony_ci          fIdentity.fDataId = SkFontIdentity::kInvalidDataId;
235cb93a386Sopenharmony_ci        }
236cb93a386Sopenharmony_ci
237cb93a386Sopenharmony_ci        virtual ~FontFallbackRenderer() { }
238cb93a386Sopenharmony_ci
239cb93a386Sopenharmony_ci        // IDWriteTextRenderer methods
240cb93a386Sopenharmony_ci        SK_STDMETHODIMP DrawGlyphRun(
241cb93a386Sopenharmony_ci            void* clientDrawingContext,
242cb93a386Sopenharmony_ci            FLOAT baselineOriginX,
243cb93a386Sopenharmony_ci            FLOAT baselineOriginY,
244cb93a386Sopenharmony_ci            DWRITE_MEASURING_MODE measuringMode,
245cb93a386Sopenharmony_ci            DWRITE_GLYPH_RUN const* glyphRun,
246cb93a386Sopenharmony_ci            DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
247cb93a386Sopenharmony_ci            IUnknown* clientDrawingEffect) override
248cb93a386Sopenharmony_ci        {
249cb93a386Sopenharmony_ci            SkTScopedComPtr<IDWriteFont> font;
250cb93a386Sopenharmony_ci            HRM(fOuter->fFontCollection->GetFontFromFontFace(glyphRun->fontFace, &font),
251cb93a386Sopenharmony_ci                "Could not get font from font face.");
252cb93a386Sopenharmony_ci
253cb93a386Sopenharmony_ci            // It is possible that the font passed does not actually have the requested character,
254cb93a386Sopenharmony_ci            // due to no font being found and getting the fallback font.
255cb93a386Sopenharmony_ci            // Check that the font actually contains the requested character.
256cb93a386Sopenharmony_ci            BOOL exists;
257cb93a386Sopenharmony_ci            HRM(font->HasCharacter(fCharacter, &exists), "Could not find character.");
258cb93a386Sopenharmony_ci
259cb93a386Sopenharmony_ci            if (exists) {
260cb93a386Sopenharmony_ci                HR(fOuter->FontToIdentity(font.get(), &fIdentity));
261cb93a386Sopenharmony_ci            }
262cb93a386Sopenharmony_ci
263cb93a386Sopenharmony_ci            return S_OK;
264cb93a386Sopenharmony_ci        }
265cb93a386Sopenharmony_ci
266cb93a386Sopenharmony_ci        SK_STDMETHODIMP DrawUnderline(
267cb93a386Sopenharmony_ci            void* clientDrawingContext,
268cb93a386Sopenharmony_ci            FLOAT baselineOriginX,
269cb93a386Sopenharmony_ci            FLOAT baselineOriginY,
270cb93a386Sopenharmony_ci            DWRITE_UNDERLINE const* underline,
271cb93a386Sopenharmony_ci            IUnknown* clientDrawingEffect) override
272cb93a386Sopenharmony_ci        { return E_NOTIMPL; }
273cb93a386Sopenharmony_ci
274cb93a386Sopenharmony_ci        SK_STDMETHODIMP DrawStrikethrough(
275cb93a386Sopenharmony_ci            void* clientDrawingContext,
276cb93a386Sopenharmony_ci            FLOAT baselineOriginX,
277cb93a386Sopenharmony_ci            FLOAT baselineOriginY,
278cb93a386Sopenharmony_ci            DWRITE_STRIKETHROUGH const* strikethrough,
279cb93a386Sopenharmony_ci            IUnknown* clientDrawingEffect) override
280cb93a386Sopenharmony_ci        { return E_NOTIMPL; }
281cb93a386Sopenharmony_ci
282cb93a386Sopenharmony_ci        SK_STDMETHODIMP DrawInlineObject(
283cb93a386Sopenharmony_ci            void* clientDrawingContext,
284cb93a386Sopenharmony_ci            FLOAT originX,
285cb93a386Sopenharmony_ci            FLOAT originY,
286cb93a386Sopenharmony_ci            IDWriteInlineObject* inlineObject,
287cb93a386Sopenharmony_ci            BOOL isSideways,
288cb93a386Sopenharmony_ci            BOOL isRightToLeft,
289cb93a386Sopenharmony_ci            IUnknown* clientDrawingEffect) override
290cb93a386Sopenharmony_ci        { return E_NOTIMPL; }
291cb93a386Sopenharmony_ci
292cb93a386Sopenharmony_ci        // IDWritePixelSnapping methods
293cb93a386Sopenharmony_ci        SK_STDMETHODIMP IsPixelSnappingDisabled(
294cb93a386Sopenharmony_ci            void* clientDrawingContext,
295cb93a386Sopenharmony_ci            BOOL* isDisabled) override
296cb93a386Sopenharmony_ci        {
297cb93a386Sopenharmony_ci            *isDisabled = FALSE;
298cb93a386Sopenharmony_ci            return S_OK;
299cb93a386Sopenharmony_ci        }
300cb93a386Sopenharmony_ci
301cb93a386Sopenharmony_ci        SK_STDMETHODIMP GetCurrentTransform(
302cb93a386Sopenharmony_ci            void* clientDrawingContext,
303cb93a386Sopenharmony_ci            DWRITE_MATRIX* transform) override
304cb93a386Sopenharmony_ci        {
305cb93a386Sopenharmony_ci            const DWRITE_MATRIX ident = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
306cb93a386Sopenharmony_ci            *transform = ident;
307cb93a386Sopenharmony_ci            return S_OK;
308cb93a386Sopenharmony_ci        }
309cb93a386Sopenharmony_ci
310cb93a386Sopenharmony_ci        SK_STDMETHODIMP GetPixelsPerDip(
311cb93a386Sopenharmony_ci            void* clientDrawingContext,
312cb93a386Sopenharmony_ci            FLOAT* pixelsPerDip) override
313cb93a386Sopenharmony_ci        {
314cb93a386Sopenharmony_ci            *pixelsPerDip = 1.0f;
315cb93a386Sopenharmony_ci            return S_OK;
316cb93a386Sopenharmony_ci        }
317cb93a386Sopenharmony_ci
318cb93a386Sopenharmony_ci        // IUnknown methods
319cb93a386Sopenharmony_ci        SK_STDMETHODIMP_(ULONG) AddRef() override {
320cb93a386Sopenharmony_ci            return InterlockedIncrement(&fRefCount);
321cb93a386Sopenharmony_ci        }
322cb93a386Sopenharmony_ci
323cb93a386Sopenharmony_ci        SK_STDMETHODIMP_(ULONG) Release() override {
324cb93a386Sopenharmony_ci            ULONG newCount = InterlockedDecrement(&fRefCount);
325cb93a386Sopenharmony_ci            if (0 == newCount) {
326cb93a386Sopenharmony_ci                delete this;
327cb93a386Sopenharmony_ci            }
328cb93a386Sopenharmony_ci            return newCount;
329cb93a386Sopenharmony_ci        }
330cb93a386Sopenharmony_ci
331cb93a386Sopenharmony_ci        SK_STDMETHODIMP QueryInterface(
332cb93a386Sopenharmony_ci            IID const& riid, void** ppvObject) override
333cb93a386Sopenharmony_ci        {
334cb93a386Sopenharmony_ci            if (__uuidof(IUnknown) == riid ||
335cb93a386Sopenharmony_ci                __uuidof(IDWritePixelSnapping) == riid ||
336cb93a386Sopenharmony_ci                __uuidof(IDWriteTextRenderer) == riid)
337cb93a386Sopenharmony_ci            {
338cb93a386Sopenharmony_ci                *ppvObject = this;
339cb93a386Sopenharmony_ci                this->AddRef();
340cb93a386Sopenharmony_ci                return S_OK;
341cb93a386Sopenharmony_ci            }
342cb93a386Sopenharmony_ci            *ppvObject = nullptr;
343cb93a386Sopenharmony_ci            return E_FAIL;
344cb93a386Sopenharmony_ci        }
345cb93a386Sopenharmony_ci
346cb93a386Sopenharmony_ci        const SkFontIdentity FallbackIdentity() { return fIdentity; }
347cb93a386Sopenharmony_ci
348cb93a386Sopenharmony_ci    protected:
349cb93a386Sopenharmony_ci        ULONG fRefCount;
350cb93a386Sopenharmony_ci        sk_sp<const SkRemotableFontMgr_DirectWrite> fOuter;
351cb93a386Sopenharmony_ci        UINT32 fCharacter;
352cb93a386Sopenharmony_ci        SkFontIdentity fIdentity;
353cb93a386Sopenharmony_ci    };
354cb93a386Sopenharmony_ci
355cb93a386Sopenharmony_ci    virtual SkFontIdentity matchNameStyleCharacter(const char familyName[],
356cb93a386Sopenharmony_ci                                                   const SkFontStyle& pattern,
357cb93a386Sopenharmony_ci                                                   const char* bcp47[], int bcp47Count,
358cb93a386Sopenharmony_ci                                                   SkUnichar character) const override
359cb93a386Sopenharmony_ci    {
360cb93a386Sopenharmony_ci        SkFontIdentity identity = { SkFontIdentity::kInvalidDataId };
361cb93a386Sopenharmony_ci
362cb93a386Sopenharmony_ci        IDWriteFactory* dwFactory = sk_get_dwrite_factory();
363cb93a386Sopenharmony_ci        if (nullptr == dwFactory) {
364cb93a386Sopenharmony_ci            return identity;
365cb93a386Sopenharmony_ci        }
366cb93a386Sopenharmony_ci
367cb93a386Sopenharmony_ci        // TODO: use IDWriteFactory2::GetSystemFontFallback when available.
368cb93a386Sopenharmony_ci
369cb93a386Sopenharmony_ci        const DWriteStyle dwStyle(pattern);
370cb93a386Sopenharmony_ci
371cb93a386Sopenharmony_ci        SkSMallocWCHAR dwFamilyName;
372cb93a386Sopenharmony_ci        if (nullptr == familyName) {
373cb93a386Sopenharmony_ci            HR_GENERAL(getDefaultFontFamilyName(&dwFamilyName), nullptr, identity);
374cb93a386Sopenharmony_ci        } else {
375cb93a386Sopenharmony_ci            HR_GENERAL(sk_cstring_to_wchar(familyName, &dwFamilyName), nullptr, identity);
376cb93a386Sopenharmony_ci        }
377cb93a386Sopenharmony_ci
378cb93a386Sopenharmony_ci        const SkSMallocWCHAR* dwBcp47;
379cb93a386Sopenharmony_ci        SkSMallocWCHAR dwBcp47Local;
380cb93a386Sopenharmony_ci        if (bcp47Count < 1) {
381cb93a386Sopenharmony_ci            dwBcp47 = &fLocaleName;
382cb93a386Sopenharmony_ci        } else {
383cb93a386Sopenharmony_ci            //TODO: support fallback stack.
384cb93a386Sopenharmony_ci            HR_GENERAL(sk_cstring_to_wchar(bcp47[bcp47Count-1], &dwBcp47Local), nullptr, identity);
385cb93a386Sopenharmony_ci            dwBcp47 = &dwBcp47Local;
386cb93a386Sopenharmony_ci        }
387cb93a386Sopenharmony_ci
388cb93a386Sopenharmony_ci        SkTScopedComPtr<IDWriteTextFormat> fallbackFormat;
389cb93a386Sopenharmony_ci        HR_GENERAL(dwFactory->CreateTextFormat(dwFamilyName,
390cb93a386Sopenharmony_ci                                               fFontCollection.get(),
391cb93a386Sopenharmony_ci                                               dwStyle.fWeight,
392cb93a386Sopenharmony_ci                                               dwStyle.fSlant,
393cb93a386Sopenharmony_ci                                               dwStyle.fWidth,
394cb93a386Sopenharmony_ci                                               72.0f,
395cb93a386Sopenharmony_ci                                               *dwBcp47,
396cb93a386Sopenharmony_ci                                               &fallbackFormat),
397cb93a386Sopenharmony_ci                   "Could not create text format.",
398cb93a386Sopenharmony_ci                   identity);
399cb93a386Sopenharmony_ci
400cb93a386Sopenharmony_ci        WCHAR str[16];
401cb93a386Sopenharmony_ci        UINT32 strLen = static_cast<UINT32>(
402cb93a386Sopenharmony_ci            SkUTF::ToUTF16(character, reinterpret_cast<uint16_t*>(str)));
403cb93a386Sopenharmony_ci        SkTScopedComPtr<IDWriteTextLayout> fallbackLayout;
404cb93a386Sopenharmony_ci        HR_GENERAL(dwFactory->CreateTextLayout(str, strLen, fallbackFormat.get(),
405cb93a386Sopenharmony_ci                                               200.0f, 200.0f,
406cb93a386Sopenharmony_ci                                               &fallbackLayout),
407cb93a386Sopenharmony_ci                   "Could not create text layout.",
408cb93a386Sopenharmony_ci                   identity);
409cb93a386Sopenharmony_ci
410cb93a386Sopenharmony_ci        SkTScopedComPtr<FontFallbackRenderer> fontFallbackRenderer(
411cb93a386Sopenharmony_ci            new FontFallbackRenderer(this, character));
412cb93a386Sopenharmony_ci
413cb93a386Sopenharmony_ci        HR_GENERAL(fallbackLayout->Draw(nullptr, fontFallbackRenderer.get(), 50.0f, 50.0f),
414cb93a386Sopenharmony_ci                   "Could not draw layout with renderer.",
415cb93a386Sopenharmony_ci                   identity);
416cb93a386Sopenharmony_ci
417cb93a386Sopenharmony_ci        return fontFallbackRenderer->FallbackIdentity();
418cb93a386Sopenharmony_ci    }
419cb93a386Sopenharmony_ci
420cb93a386Sopenharmony_ci    SkStreamAsset* getData(int dataId) const override {
421cb93a386Sopenharmony_ci        SkAutoMutexExclusive ama(fDataIdCacheMutex);
422cb93a386Sopenharmony_ci        if (dataId >= fDataIdCache.count()) {
423cb93a386Sopenharmony_ci            return nullptr;
424cb93a386Sopenharmony_ci        }
425cb93a386Sopenharmony_ci        const DataId& id = fDataIdCache[dataId];
426cb93a386Sopenharmony_ci
427cb93a386Sopenharmony_ci        SkTScopedComPtr<IDWriteFontFileLoader> loader;
428cb93a386Sopenharmony_ci        HRNM(id.fLoader->QueryInterface(&loader), "QuerryInterface IDWriteFontFileLoader failed");
429cb93a386Sopenharmony_ci
430cb93a386Sopenharmony_ci        SkTScopedComPtr<IDWriteFontFileStream> fontFileStream;
431cb93a386Sopenharmony_ci        HRNM(loader->CreateStreamFromKey(id.fKey, id.fKeySize, &fontFileStream),
432cb93a386Sopenharmony_ci             "Could not create font file stream.");
433cb93a386Sopenharmony_ci
434cb93a386Sopenharmony_ci        return new SkDWriteFontFileStream(fontFileStream.get());
435cb93a386Sopenharmony_ci    }
436cb93a386Sopenharmony_ci
437cb93a386Sopenharmony_ciprivate:
438cb93a386Sopenharmony_ci    SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
439cb93a386Sopenharmony_ci    SkSMallocWCHAR fLocaleName;
440cb93a386Sopenharmony_ci
441cb93a386Sopenharmony_ci    using INHERITED = SkRemotableFontMgr;
442cb93a386Sopenharmony_ci};
443cb93a386Sopenharmony_ci
444cb93a386Sopenharmony_ciSkRemotableFontMgr* SkRemotableFontMgr_New_DirectWrite() {
445cb93a386Sopenharmony_ci    IDWriteFactory* factory = sk_get_dwrite_factory();
446cb93a386Sopenharmony_ci    if (nullptr == factory) {
447cb93a386Sopenharmony_ci        return nullptr;
448cb93a386Sopenharmony_ci    }
449cb93a386Sopenharmony_ci
450cb93a386Sopenharmony_ci    SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
451cb93a386Sopenharmony_ci    HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE),
452cb93a386Sopenharmony_ci         "Could not get system font collection.");
453cb93a386Sopenharmony_ci
454cb93a386Sopenharmony_ci    WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
455cb93a386Sopenharmony_ci    WCHAR* localeName = nullptr;
456cb93a386Sopenharmony_ci    int localeNameLen = 0;
457cb93a386Sopenharmony_ci
458cb93a386Sopenharmony_ci    // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP.
459cb93a386Sopenharmony_ci    SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = nullptr;
460cb93a386Sopenharmony_ci    HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc);
461cb93a386Sopenharmony_ci    if (nullptr == getUserDefaultLocaleNameProc) {
462cb93a386Sopenharmony_ci        SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName.");
463cb93a386Sopenharmony_ci    } else {
464cb93a386Sopenharmony_ci        localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH);
465cb93a386Sopenharmony_ci        if (localeNameLen) {
466cb93a386Sopenharmony_ci            localeName = localeNameStorage;
467cb93a386Sopenharmony_ci        };
468cb93a386Sopenharmony_ci    }
469cb93a386Sopenharmony_ci
470cb93a386Sopenharmony_ci    return new SkRemotableFontMgr_DirectWrite(sysFontCollection.get(), localeName, localeNameLen);
471cb93a386Sopenharmony_ci}
472cb93a386Sopenharmony_ci#endif//defined(SK_BUILD_FOR_WIN)
473