172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com/*
272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com * Copyright 2014 Google Inc.
372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com *
472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com * Use of this source code is governed by a BSD-style license that can be
572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com * found in the LICENSE file.
672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com */
71ee76510f5dbf632d30975fc3509ef4f609156d2mtklein#include "SkTypes.h"
81ee76510f5dbf632d30975fc3509ef4f609156d2mtklein#if defined(SK_BUILD_FOR_WIN32)
972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
1072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkDWrite.h"
1172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkDWriteFontFileStream.h"
121b24933e52f50773de29332387a12721811f3012mtklein#include "SkDataTable.h"
1372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkHRESULT.h"
141b24933e52f50773de29332387a12721811f3012mtklein#include "SkMutex.h"
1572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkRemotableFontMgr.h"
1672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkStream.h"
1772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkString.h"
1872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkTArray.h"
1972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkTScopedComPtr.h"
2072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkTypeface_win.h"
2172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkTypes.h"
2272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkUtils.h"
2372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
2472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include <dwrite.h>
2572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
2672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comclass SK_API SkRemotableFontMgr_DirectWrite : public SkRemotableFontMgr {
2772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comprivate:
2872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    struct DataId {
2972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        IUnknown* fLoader;  // In COM only IUnknown pointers may be safely used for identity.
3072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        void* fKey;
3172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        UINT32 fKeySize;
3272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
3372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        DataId() { }
3472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
35918090c819109585f8fd2295039385a60eb0b572bungeman        DataId(DataId&& that) : fLoader(that.fLoader), fKey(that.fKey), fKeySize(that.fKeySize) {
3696fcdcc219d2a0d3579719b84b28bede76efba64halcanary            that.fLoader = nullptr;
3796fcdcc219d2a0d3579719b84b28bede76efba64halcanary            that.fKey = nullptr;
3872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            SkDEBUGCODE(that.fKeySize = 0xFFFFFFFF;)
3972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
4072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
4172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        ~DataId() {
4272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            if (fLoader) {
4372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                fLoader->Release();
4472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            }
4572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            sk_free(fKey);
4672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
4772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    };
4872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
4972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    mutable SkTArray<DataId> fDataIdCache;
5072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    mutable SkMutex fDataIdCacheMutex;
5172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
5272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    int FindOrAdd(IDWriteFontFileLoader* fontFileLoader,
5372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                  const void* refKey, UINT32 refKeySize) const
5472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    {
5572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IUnknown> fontFileLoaderId;
5672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR_GENERAL(fontFileLoader->QueryInterface(&fontFileLoaderId),
5772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   "Failed to re-convert to IDWriteFontFileLoader.",
5872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   SkFontIdentity::kInvalidDataId);
5972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
6072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkAutoMutexAcquire ama(fDataIdCacheMutex);
6172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        int count = fDataIdCache.count();
6272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        int i;
6372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        for (i = 0; i < count; ++i) {
6472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            const DataId& current = fDataIdCache[i];
6572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            if (fontFileLoaderId.get() == current.fLoader &&
6672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                refKeySize == current.fKeySize &&
6772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                0 == memcmp(refKey, current.fKey, refKeySize))
6872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            {
6972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                return i;
7072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            }
7172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
7272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        DataId& added = fDataIdCache.push_back();
7372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        added.fLoader = fontFileLoaderId.release();  // Ref is passed.
7472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        added.fKey = sk_malloc_throw(refKeySize);
7572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        memcpy(added.fKey, refKey, refKeySize);
7672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        added.fKeySize = refKeySize;
7772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
7872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return i;
7972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
8072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
8172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.compublic:
821b24933e52f50773de29332387a12721811f3012mtklein
8372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
8472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    /** localeNameLength must include the null terminator. */
8572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkRemotableFontMgr_DirectWrite(IDWriteFontCollection* fontCollection,
8672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                   WCHAR* localeName, int localeNameLength)
8772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        : fFontCollection(SkRefComPtr(fontCollection))
8872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        , fLocaleName(localeNameLength)
8972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    {
9072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
9172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
9272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
9336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkDataTable* getFamilyNames() const override {
9472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        int count = fFontCollection->GetFontFamilyCount();
9572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
9672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkDataTableBuilder names(1024);
9772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        for (int index = 0; index < count; ++index) {
9872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            SkTScopedComPtr<IDWriteFontFamily> fontFamily;
9972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HRNM(fFontCollection->GetFontFamily(index, &fontFamily),
10072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                 "Could not get requested family.");
10172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
10272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
10372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HRNM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names.");
10472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
10572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            SkString familyName;
10672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            sk_get_locale_string(familyNames.get(), fLocaleName.get(), &familyName);
10772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
10872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            names.appendString(familyName);
10972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
11072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return names.detachDataTable();
11172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
11272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
11372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    HRESULT FontToIdentity(IDWriteFont* font, SkFontIdentity* fontId) const {
11472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IDWriteFontFace> fontFace;
11572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HRM(font->CreateFontFace(&fontFace), "Could not create font face.");
11672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
11772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        UINT32 numFiles;
11896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        HR(fontFace->GetFiles(&numFiles, nullptr));
11972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (numFiles > 1) {
12072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return E_FAIL;
12172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
12272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
12372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // data id
12472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IDWriteFontFile> fontFile;
12572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR(fontFace->GetFiles(&numFiles, &fontFile));
12672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
12772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
12872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR(fontFile->GetLoader(&fontFileLoader));
12972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
13072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        const void* refKey;
13172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        UINT32 refKeySize;
13272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR(fontFile->GetReferenceKey(&refKey, &refKeySize));
13372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
13472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        fontId->fDataId = FindOrAdd(fontFileLoader.get(), refKey, refKeySize);
13572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
13672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // index
13772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        fontId->fTtcIndex = fontFace->GetIndex();
13872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
13972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // style
14072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkFontStyle::Slant slant;
14172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        switch (font->GetStyle()) {
14272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        case DWRITE_FONT_STYLE_NORMAL:
14372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            slant = SkFontStyle::kUpright_Slant;
14472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            break;
14572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        case DWRITE_FONT_STYLE_OBLIQUE:
14672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        case DWRITE_FONT_STYLE_ITALIC:
14772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            slant = SkFontStyle::kItalic_Slant;
14872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            break;
14972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        default:
15072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            SkASSERT(false);
15172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
15272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
15372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        int weight = font->GetWeight();
15472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        int width = font->GetStretch();
15572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
15672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        fontId->fFontStyle = SkFontStyle(weight, width, slant);
15772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return S_OK;
15872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
15972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
16036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkRemotableFontIdentitySet* getIndex(int familyIndex) const override {
16172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IDWriteFontFamily> fontFamily;
16272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HRNM(fFontCollection->GetFontFamily(familyIndex, &fontFamily),
16372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com             "Could not get requested family.");
16472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
16572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        int count = fontFamily->GetFontCount();
16672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkFontIdentity* fontIds;
16772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkAutoTUnref<SkRemotableFontIdentitySet> fontIdSet(
16872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            new SkRemotableFontIdentitySet(count, &fontIds));
16972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        for (int fontIndex = 0; fontIndex < count; ++fontIndex) {
17072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            SkTScopedComPtr<IDWriteFont> font;
17172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HRNM(fontFamily->GetFont(fontIndex, &font), "Could not get font.");
17272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
17372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HRN(FontToIdentity(font.get(), &fontIds[fontIndex]));
17472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
17572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return fontIdSet.detach();
17672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
17772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
17872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    virtual SkFontIdentity matchIndexStyle(int familyIndex,
17936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                                           const SkFontStyle& pattern) const override
18072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    {
18172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkFontIdentity identity = { SkFontIdentity::kInvalidDataId };
18272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
18372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IDWriteFontFamily> fontFamily;
18472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR_GENERAL(fFontCollection->GetFontFamily(familyIndex, &fontFamily),
18572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   "Could not get requested family.",
18672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   identity);
18772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
18872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        const DWriteStyle dwStyle(pattern);
18972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IDWriteFont> font;
19072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR_GENERAL(fontFamily->GetFirstMatchingFont(dwStyle.fWeight, dwStyle.fWidth,
19172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                                    dwStyle.fSlant, &font),
19272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   "Could not match font in family.",
19372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   identity);
19472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
19596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        HR_GENERAL(FontToIdentity(font.get(), &identity), nullptr, identity);
19672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
19772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return identity;
19872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
19972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
20072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    static HRESULT getDefaultFontFamilyName(SkSMallocWCHAR* name) {
20172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        NONCLIENTMETRICSW metrics;
20272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        metrics.cbSize = sizeof(metrics);
20372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
20472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                       sizeof(metrics),
20572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                       &metrics,
20672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                       0)) {
20772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return E_UNEXPECTED;
20872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
20972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
21072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        size_t len = wcsnlen_s(metrics.lfMessageFont.lfFaceName, LF_FACESIZE) + 1;
21172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (0 != wcsncpy_s(name->reset(len), len, metrics.lfMessageFont.lfFaceName, _TRUNCATE)) {
21272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return E_UNEXPECTED;
21372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
21472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
21572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return S_OK;
21672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
21772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
21836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkRemotableFontIdentitySet* matchName(const char familyName[]) const override {
21972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkSMallocWCHAR dwFamilyName;
22096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == familyName) {
22172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HR_GENERAL(getDefaultFontFamilyName(&dwFamilyName),
22296fcdcc219d2a0d3579719b84b28bede76efba64halcanary                       nullptr, SkRemotableFontIdentitySet::NewEmpty());
22372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        } else {
22472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HR_GENERAL(sk_cstring_to_wchar(familyName, &dwFamilyName),
22596fcdcc219d2a0d3579719b84b28bede76efba64halcanary                       nullptr, SkRemotableFontIdentitySet::NewEmpty());
22672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
22772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
22872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        UINT32 index;
22972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        BOOL exists;
23072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR_GENERAL(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
23172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   "Failed while finding family by name.",
23272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   SkRemotableFontIdentitySet::NewEmpty());
23372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (!exists) {
23472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return SkRemotableFontIdentitySet::NewEmpty();
23572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
23672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
23772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return this->getIndex(index);
23872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
23972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
24072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    virtual SkFontIdentity matchNameStyle(const char familyName[],
24136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                                          const SkFontStyle& style) const override
24272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    {
24372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkFontIdentity identity = { SkFontIdentity::kInvalidDataId };
24472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
24572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkSMallocWCHAR dwFamilyName;
24696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == familyName) {
24796fcdcc219d2a0d3579719b84b28bede76efba64halcanary            HR_GENERAL(getDefaultFontFamilyName(&dwFamilyName), nullptr, identity);
24872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        } else {
24996fcdcc219d2a0d3579719b84b28bede76efba64halcanary            HR_GENERAL(sk_cstring_to_wchar(familyName, &dwFamilyName), nullptr, identity);
25072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
25172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
25272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        UINT32 index;
25372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        BOOL exists;
25472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR_GENERAL(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
25572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   "Failed while finding family by name.",
25672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   identity);
25772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (!exists) {
25872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return identity;
25972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
26072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
26172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return this->matchIndexStyle(index, style);
26272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
26372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
26472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    class FontFallbackRenderer : public IDWriteTextRenderer {
26572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    public:
26672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        FontFallbackRenderer(const SkRemotableFontMgr_DirectWrite* outer, UINT32 character)
26772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            : fRefCount(1), fOuter(SkSafeRef(outer)), fCharacter(character) {
26872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com          fIdentity.fDataId = SkFontIdentity::kInvalidDataId;
26972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
27072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
271d7f846bdd171e4be0c05cfe61bc4446caf5c99c6bungeman        virtual ~FontFallbackRenderer() { }
272d7f846bdd171e4be0c05cfe61bc4446caf5c99c6bungeman
27372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // IDWriteTextRenderer methods
27472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        virtual HRESULT STDMETHODCALLTYPE DrawGlyphRun(
27572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            void* clientDrawingContext,
27672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            FLOAT baselineOriginX,
27772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            FLOAT baselineOriginY,
27872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            DWRITE_MEASURING_MODE measuringMode,
27972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            DWRITE_GLYPH_RUN const* glyphRun,
28072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
28136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein            IUnknown* clientDrawingEffect) override
28272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        {
28372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            SkTScopedComPtr<IDWriteFont> font;
28472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HRM(fOuter->fFontCollection->GetFontFromFontFace(glyphRun->fontFace, &font),
28572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                "Could not get font from font face.");
28672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
28772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            // It is possible that the font passed does not actually have the requested character,
28872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            // due to no font being found and getting the fallback font.
28972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            // Check that the font actually contains the requested character.
29072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            BOOL exists;
29172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HRM(font->HasCharacter(fCharacter, &exists), "Could not find character.");
29272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
29372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            if (exists) {
29472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                HR(fOuter->FontToIdentity(font.get(), &fIdentity));
29572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            }
29672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
29772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return S_OK;
29872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
29972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
30072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        virtual HRESULT STDMETHODCALLTYPE DrawUnderline(
30172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            void* clientDrawingContext,
30272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            FLOAT baselineOriginX,
30372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            FLOAT baselineOriginY,
30472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            DWRITE_UNDERLINE const* underline,
30536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein            IUnknown* clientDrawingEffect) override
30672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        { return E_NOTIMPL; }
30772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
30872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        virtual HRESULT STDMETHODCALLTYPE DrawStrikethrough(
30972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            void* clientDrawingContext,
31072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            FLOAT baselineOriginX,
31172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            FLOAT baselineOriginY,
31272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            DWRITE_STRIKETHROUGH const* strikethrough,
31336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein            IUnknown* clientDrawingEffect) override
31472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        { return E_NOTIMPL; }
31572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
31672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        virtual HRESULT STDMETHODCALLTYPE DrawInlineObject(
31772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            void* clientDrawingContext,
31872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            FLOAT originX,
31972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            FLOAT originY,
32072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            IDWriteInlineObject* inlineObject,
32172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            BOOL isSideways,
32272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            BOOL isRightToLeft,
32336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein            IUnknown* clientDrawingEffect) override
32472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        { return E_NOTIMPL; }
32572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
32672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // IDWritePixelSnapping methods
32772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        virtual HRESULT STDMETHODCALLTYPE IsPixelSnappingDisabled(
32872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            void* clientDrawingContext,
32936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein            BOOL* isDisabled) override
33072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        {
33172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            *isDisabled = FALSE;
33272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return S_OK;
33372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
33472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
33572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        virtual HRESULT STDMETHODCALLTYPE GetCurrentTransform(
33672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            void* clientDrawingContext,
33736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein            DWRITE_MATRIX* transform) override
33872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        {
33972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            const DWRITE_MATRIX ident = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
34072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            *transform = ident;
34172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return S_OK;
34272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
34372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
34472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        virtual HRESULT STDMETHODCALLTYPE GetPixelsPerDip(
34572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            void* clientDrawingContext,
34636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein            FLOAT* pixelsPerDip) override
34772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        {
34872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            *pixelsPerDip = 1.0f;
34972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return S_OK;
35072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
35172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
35272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // IUnknown methods
35336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein        ULONG STDMETHODCALLTYPE AddRef() override {
35472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return InterlockedIncrement(&fRefCount);
35572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
35672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
35736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein        ULONG STDMETHODCALLTYPE Release() override {
35872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            ULONG newCount = InterlockedDecrement(&fRefCount);
35972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            if (0 == newCount) {
36072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                delete this;
36172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            }
36272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return newCount;
36372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
36472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
36572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        virtual HRESULT STDMETHODCALLTYPE QueryInterface(
36636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein            IID const& riid, void** ppvObject) override
36772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        {
36872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            if (__uuidof(IUnknown) == riid ||
36972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                __uuidof(IDWritePixelSnapping) == riid ||
37072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                __uuidof(IDWriteTextRenderer) == riid)
37172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            {
37272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                *ppvObject = this;
37372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                this->AddRef();
37472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                return S_OK;
37572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            }
37696fcdcc219d2a0d3579719b84b28bede76efba64halcanary            *ppvObject = nullptr;
37772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return E_FAIL;
37872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
37972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
38072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        const SkFontIdentity FallbackIdentity() { return fIdentity; }
38172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
38272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    protected:
38372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        ULONG fRefCount;
38472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkAutoTUnref<const SkRemotableFontMgr_DirectWrite> fOuter;
38572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        UINT32 fCharacter;
38672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkFontIdentity fIdentity;
38772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    };
38872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
389c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman    virtual SkFontIdentity matchNameStyleCharacter(const char familyName[],
3904aa75b798049741f214aac4a9ed959aa46d54d7ebungeman                                                   const SkFontStyle& pattern,
391c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman                                                   const char* bcp47[], int bcp47Count,
39236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                                                   SkUnichar character) const override
393c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman    {
39472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkFontIdentity identity = { SkFontIdentity::kInvalidDataId };
39572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
39672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        IDWriteFactory* dwFactory = sk_get_dwrite_factory();
39796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == dwFactory) {
39872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return identity;
39972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
40072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
40172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // TODO: use IDWriteFactory2::GetSystemFontFallback when available.
40272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
40372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        const DWriteStyle dwStyle(pattern);
40472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
40572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkSMallocWCHAR dwFamilyName;
40696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == familyName) {
40796fcdcc219d2a0d3579719b84b28bede76efba64halcanary            HR_GENERAL(getDefaultFontFamilyName(&dwFamilyName), nullptr, identity);
40872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        } else {
40996fcdcc219d2a0d3579719b84b28bede76efba64halcanary            HR_GENERAL(sk_cstring_to_wchar(familyName, &dwFamilyName), nullptr, identity);
41072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
41172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
412c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman        const SkSMallocWCHAR* dwBcp47;
413c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman        SkSMallocWCHAR dwBcp47Local;
414c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman        if (bcp47Count < 1) {
415c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman            dwBcp47 = &fLocaleName;
41672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        } else {
417c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman            //TODO: support fallback stack.
41896fcdcc219d2a0d3579719b84b28bede76efba64halcanary            HR_GENERAL(sk_cstring_to_wchar(bcp47[bcp47Count-1], &dwBcp47Local), nullptr, identity);
419c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman            dwBcp47 = &dwBcp47Local;
42072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
42172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
42272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IDWriteTextFormat> fallbackFormat;
42372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR_GENERAL(dwFactory->CreateTextFormat(dwFamilyName,
42472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                               fFontCollection.get(),
42572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                               dwStyle.fWeight,
42672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                               dwStyle.fSlant,
42772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                               dwStyle.fWidth,
42872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                               72.0f,
429c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman                                               *dwBcp47,
43072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                               &fallbackFormat),
43172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   "Could not create text format.",
43272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   identity);
43372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
43472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        WCHAR str[16];
4353d21f21cac33743e7aedace9abf0473c5063199fbungeman@google.com        UINT32 strLen = static_cast<UINT32>(
4363d21f21cac33743e7aedace9abf0473c5063199fbungeman@google.com            SkUTF16_FromUnichar(character, reinterpret_cast<uint16_t*>(str)));
43772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IDWriteTextLayout> fallbackLayout;
43872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR_GENERAL(dwFactory->CreateTextLayout(str, strLen, fallbackFormat.get(),
43972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                               200.0f, 200.0f,
44072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                               &fallbackLayout),
44172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   "Could not create text layout.",
44272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   identity);
44372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
44472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<FontFallbackRenderer> fontFallbackRenderer(
44572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            new FontFallbackRenderer(this, character));
44672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
44796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        HR_GENERAL(fallbackLayout->Draw(nullptr, fontFallbackRenderer.get(), 50.0f, 50.0f),
44872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   "Could not draw layout with renderer.",
44972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   identity);
45072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
45172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return fontFallbackRenderer->FallbackIdentity();
45272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
45372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
45436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkStreamAsset* getData(int dataId) const override {
45572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkAutoMutexAcquire ama(fDataIdCacheMutex);
45672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (dataId >= fDataIdCache.count()) {
45796fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return nullptr;
45872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
45972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        const DataId& id = fDataIdCache[dataId];
46072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
46172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IDWriteFontFileLoader> loader;
46272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HRNM(id.fLoader->QueryInterface(&loader), "QuerryInterface IDWriteFontFileLoader failed");
46372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
46472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IDWriteFontFileStream> fontFileStream;
46572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HRNM(loader->CreateStreamFromKey(id.fKey, id.fKeySize, &fontFileStream),
46672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com             "Could not create font file stream.");
46772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
468385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        return new SkDWriteFontFileStream(fontFileStream.get());
46972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
47072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
47172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comprivate:
47272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
47372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkSMallocWCHAR fLocaleName;
47472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
47572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    typedef SkRemotableFontMgr INHERITED;
47672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com};
47772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
47872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comSkRemotableFontMgr* SkRemotableFontMgr_New_DirectWrite() {
47972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    IDWriteFactory* factory = sk_get_dwrite_factory();
48096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == factory) {
48196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
48272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
48372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
48472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
48572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE),
48672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com         "Could not get system font collection.");
48772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
48872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
48996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    WCHAR* localeName = nullptr;
49072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    int localeNameLen = 0;
49172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
49272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP.
49396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = nullptr;
49472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc);
49596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == getUserDefaultLocaleNameProc) {
49672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName.");
49772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    } else {
49872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH);
49972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (localeNameLen) {
50072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            localeName = localeNameStorage;
50172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        };
50272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
50372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
504385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    return new SkRemotableFontMgr_DirectWrite(sysFontCollection.get(), localeName, localeNameLen);
50572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
5061ee76510f5dbf632d30975fc3509ef4f609156d2mtklein#endif//defined(SK_BUILD_FOR_WIN32)
507