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 */
772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkDataTable.h"
972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkDWrite.h"
1072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkDWriteFontFileStream.h"
1172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkHRESULT.h"
1272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkRemotableFontMgr.h"
1372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkStream.h"
1472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkString.h"
1572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkTArray.h"
1672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkThread.h"
1772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkTScopedComPtr.h"
1872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkTypeface_win.h"
1972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkTypes.h"
2072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkUtils.h"
2172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
2272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include <dwrite.h>
2372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
2472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comstruct DWriteStyle {
2572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    explicit DWriteStyle(const SkFontStyle& pattern) {
2672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        switch (pattern.slant()) {
2772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        case SkFontStyle::kUpright_Slant:
2872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            fSlant = DWRITE_FONT_STYLE_NORMAL;
2972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            break;
3072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        case SkFontStyle::kItalic_Slant:
3172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            fSlant = DWRITE_FONT_STYLE_ITALIC;
3272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            break;
3372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        default:
3472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            SkASSERT(false);
3572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
3672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
3772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        fWeight = (DWRITE_FONT_WEIGHT)pattern.weight();
3872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        fWidth = (DWRITE_FONT_STRETCH)pattern.width();
3972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
4072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    DWRITE_FONT_STYLE fSlant;
4172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    DWRITE_FONT_WEIGHT fWeight;
4272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    DWRITE_FONT_STRETCH fWidth;
4372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com};
4472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
4572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comclass SK_API SkRemotableFontMgr_DirectWrite : public SkRemotableFontMgr {
4672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comprivate:
4772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    struct DataId {
4872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        IUnknown* fLoader;  // In COM only IUnknown pointers may be safely used for identity.
4972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        void* fKey;
5072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        UINT32 fKeySize;
5172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
5272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        DataId() { }
5372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
5472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // This is actually a move!!!
5572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        explicit DataId(DataId& that)
5672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            : fLoader(that.fLoader), fKey(that.fKey), fKeySize(that.fKeySize)
5772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        {
5872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            that.fLoader = NULL;
5972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            that.fKey = NULL;
6072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            SkDEBUGCODE(that.fKeySize = 0xFFFFFFFF;)
6172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
6272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
6372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        ~DataId() {
6472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            if (fLoader) {
6572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                fLoader->Release();
6672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            }
6772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            sk_free(fKey);
6872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
6972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    };
7072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
7172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    mutable SkTArray<DataId> fDataIdCache;
7272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    mutable SkMutex fDataIdCacheMutex;
7372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
7472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    int FindOrAdd(IDWriteFontFileLoader* fontFileLoader,
7572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                  const void* refKey, UINT32 refKeySize) const
7672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    {
7772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IUnknown> fontFileLoaderId;
7872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR_GENERAL(fontFileLoader->QueryInterface(&fontFileLoaderId),
7972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   "Failed to re-convert to IDWriteFontFileLoader.",
8072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   SkFontIdentity::kInvalidDataId);
8172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
8272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkAutoMutexAcquire ama(fDataIdCacheMutex);
8372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        int count = fDataIdCache.count();
8472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        int i;
8572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        for (i = 0; i < count; ++i) {
8672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            const DataId& current = fDataIdCache[i];
8772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            if (fontFileLoaderId.get() == current.fLoader &&
8872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                refKeySize == current.fKeySize &&
8972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                0 == memcmp(refKey, current.fKey, refKeySize))
9072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            {
9172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                return i;
9272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            }
9372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
9472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        DataId& added = fDataIdCache.push_back();
9572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        added.fLoader = fontFileLoaderId.release();  // Ref is passed.
9672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        added.fKey = sk_malloc_throw(refKeySize);
9772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        memcpy(added.fKey, refKey, refKeySize);
9872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        added.fKeySize = refKeySize;
9972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
10072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return i;
10172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
10272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
10372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.compublic:
10472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SK_DECLARE_INST_COUNT(SkRemotableFontMgr_DirectWrite)
10572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
10672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    /** localeNameLength must include the null terminator. */
10772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkRemotableFontMgr_DirectWrite(IDWriteFontCollection* fontCollection,
10872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                   WCHAR* localeName, int localeNameLength)
10972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        : fFontCollection(SkRefComPtr(fontCollection))
11072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        , fLocaleName(localeNameLength)
11172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    {
11272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
11372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
11472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
11572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    virtual SkDataTable* getFamilyNames() const SK_OVERRIDE {
11672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        int count = fFontCollection->GetFontFamilyCount();
11772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
11872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkDataTableBuilder names(1024);
11972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        for (int index = 0; index < count; ++index) {
12072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            SkTScopedComPtr<IDWriteFontFamily> fontFamily;
12172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HRNM(fFontCollection->GetFontFamily(index, &fontFamily),
12272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                 "Could not get requested family.");
12372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
12472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
12572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HRNM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names.");
12672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
12772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            SkString familyName;
12872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            sk_get_locale_string(familyNames.get(), fLocaleName.get(), &familyName);
12972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
13072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            names.appendString(familyName);
13172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
13272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return names.detachDataTable();
13372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
13472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
13572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    HRESULT FontToIdentity(IDWriteFont* font, SkFontIdentity* fontId) const {
13672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IDWriteFontFace> fontFace;
13772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HRM(font->CreateFontFace(&fontFace), "Could not create font face.");
13872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
13972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        UINT32 numFiles;
14072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR(fontFace->GetFiles(&numFiles, NULL));
14172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (numFiles > 1) {
14272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return E_FAIL;
14372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
14472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
14572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // data id
14672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IDWriteFontFile> fontFile;
14772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR(fontFace->GetFiles(&numFiles, &fontFile));
14872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
14972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
15072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR(fontFile->GetLoader(&fontFileLoader));
15172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
15272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        const void* refKey;
15372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        UINT32 refKeySize;
15472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR(fontFile->GetReferenceKey(&refKey, &refKeySize));
15572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
15672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        fontId->fDataId = FindOrAdd(fontFileLoader.get(), refKey, refKeySize);
15772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
15872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // index
15972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        fontId->fTtcIndex = fontFace->GetIndex();
16072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
16172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // style
16272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkFontStyle::Slant slant;
16372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        switch (font->GetStyle()) {
16472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        case DWRITE_FONT_STYLE_NORMAL:
16572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            slant = SkFontStyle::kUpright_Slant;
16672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            break;
16772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        case DWRITE_FONT_STYLE_OBLIQUE:
16872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        case DWRITE_FONT_STYLE_ITALIC:
16972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            slant = SkFontStyle::kItalic_Slant;
17072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            break;
17172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        default:
17272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            SkASSERT(false);
17372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
17472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
17572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        int weight = font->GetWeight();
17672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        int width = font->GetStretch();
17772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
17872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        fontId->fFontStyle = SkFontStyle(weight, width, slant);
17972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return S_OK;
18072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
18172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
18272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    virtual SkRemotableFontIdentitySet* getIndex(int familyIndex) const SK_OVERRIDE {
18372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IDWriteFontFamily> fontFamily;
18472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HRNM(fFontCollection->GetFontFamily(familyIndex, &fontFamily),
18572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com             "Could not get requested family.");
18672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
18772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        int count = fontFamily->GetFontCount();
18872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkFontIdentity* fontIds;
18972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkAutoTUnref<SkRemotableFontIdentitySet> fontIdSet(
19072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            new SkRemotableFontIdentitySet(count, &fontIds));
19172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        for (int fontIndex = 0; fontIndex < count; ++fontIndex) {
19272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            SkTScopedComPtr<IDWriteFont> font;
19372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HRNM(fontFamily->GetFont(fontIndex, &font), "Could not get font.");
19472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
19572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HRN(FontToIdentity(font.get(), &fontIds[fontIndex]));
19672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
19772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return fontIdSet.detach();
19872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
19972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
20072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    virtual SkFontIdentity matchIndexStyle(int familyIndex,
20172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                           const SkFontStyle& pattern) const SK_OVERRIDE
20272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    {
20372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkFontIdentity identity = { SkFontIdentity::kInvalidDataId };
20472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
20572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IDWriteFontFamily> fontFamily;
20672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR_GENERAL(fFontCollection->GetFontFamily(familyIndex, &fontFamily),
20772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   "Could not get requested family.",
20872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   identity);
20972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
21072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        const DWriteStyle dwStyle(pattern);
21172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IDWriteFont> font;
21272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR_GENERAL(fontFamily->GetFirstMatchingFont(dwStyle.fWeight, dwStyle.fWidth,
21372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                                    dwStyle.fSlant, &font),
21472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   "Could not match font in family.",
21572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   identity);
21672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
21772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR_GENERAL(FontToIdentity(font.get(), &identity), NULL, identity);
21872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
21972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return identity;
22072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
22172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
22272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    static HRESULT getDefaultFontFamilyName(SkSMallocWCHAR* name) {
22372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        NONCLIENTMETRICSW metrics;
22472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        metrics.cbSize = sizeof(metrics);
22572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
22672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                       sizeof(metrics),
22772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                       &metrics,
22872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                       0)) {
22972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return E_UNEXPECTED;
23072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
23172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
23272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        size_t len = wcsnlen_s(metrics.lfMessageFont.lfFaceName, LF_FACESIZE) + 1;
23372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (0 != wcsncpy_s(name->reset(len), len, metrics.lfMessageFont.lfFaceName, _TRUNCATE)) {
23472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return E_UNEXPECTED;
23572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
23672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
23772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return S_OK;
23872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
23972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
24072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    virtual SkRemotableFontIdentitySet* matchName(const char familyName[]) const SK_OVERRIDE {
24172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkSMallocWCHAR dwFamilyName;
24272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (NULL == familyName) {
24372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HR_GENERAL(getDefaultFontFamilyName(&dwFamilyName),
24472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                       NULL, SkRemotableFontIdentitySet::NewEmpty());
24572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        } else {
24672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HR_GENERAL(sk_cstring_to_wchar(familyName, &dwFamilyName),
24772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                       NULL, SkRemotableFontIdentitySet::NewEmpty());
24872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
24972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
25072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        UINT32 index;
25172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        BOOL exists;
25272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR_GENERAL(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
25372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   "Failed while finding family by name.",
25472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   SkRemotableFontIdentitySet::NewEmpty());
25572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (!exists) {
25672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return SkRemotableFontIdentitySet::NewEmpty();
25772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
25872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
25972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return this->getIndex(index);
26072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
26172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
26272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    virtual SkFontIdentity matchNameStyle(const char familyName[],
26372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                          const SkFontStyle& style) const SK_OVERRIDE
26472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    {
26572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkFontIdentity identity = { SkFontIdentity::kInvalidDataId };
26672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
26772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkSMallocWCHAR dwFamilyName;
26872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (NULL == familyName) {
26972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HR_GENERAL(getDefaultFontFamilyName(&dwFamilyName), NULL, identity);
27072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        } else {
27172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HR_GENERAL(sk_cstring_to_wchar(familyName, &dwFamilyName), NULL, identity);
27272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
27372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
27472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        UINT32 index;
27572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        BOOL exists;
27672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR_GENERAL(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
27772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   "Failed while finding family by name.",
27872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   identity);
27972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (!exists) {
28072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return identity;
28172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
28272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
28372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return this->matchIndexStyle(index, style);
28472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
28572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
28672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    class FontFallbackRenderer : public IDWriteTextRenderer {
28772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    public:
28872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        FontFallbackRenderer(const SkRemotableFontMgr_DirectWrite* outer, UINT32 character)
28972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            : fRefCount(1), fOuter(SkSafeRef(outer)), fCharacter(character) {
29072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com          fIdentity.fDataId = SkFontIdentity::kInvalidDataId;
29172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
29272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
293d7f846bdd171e4be0c05cfe61bc4446caf5c99c6bungeman        virtual ~FontFallbackRenderer() { }
294d7f846bdd171e4be0c05cfe61bc4446caf5c99c6bungeman
29572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // IDWriteTextRenderer methods
29672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        virtual HRESULT STDMETHODCALLTYPE DrawGlyphRun(
29772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            void* clientDrawingContext,
29872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            FLOAT baselineOriginX,
29972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            FLOAT baselineOriginY,
30072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            DWRITE_MEASURING_MODE measuringMode,
30172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            DWRITE_GLYPH_RUN const* glyphRun,
30272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
30372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            IUnknown* clientDrawingEffect) SK_OVERRIDE
30472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        {
30572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            SkTScopedComPtr<IDWriteFont> font;
30672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HRM(fOuter->fFontCollection->GetFontFromFontFace(glyphRun->fontFace, &font),
30772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                "Could not get font from font face.");
30872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
30972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            // It is possible that the font passed does not actually have the requested character,
31072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            // due to no font being found and getting the fallback font.
31172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            // Check that the font actually contains the requested character.
31272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            BOOL exists;
31372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HRM(font->HasCharacter(fCharacter, &exists), "Could not find character.");
31472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
31572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            if (exists) {
31672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                HR(fOuter->FontToIdentity(font.get(), &fIdentity));
31772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            }
31872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
31972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return S_OK;
32072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
32172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
32272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        virtual HRESULT STDMETHODCALLTYPE DrawUnderline(
32372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            void* clientDrawingContext,
32472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            FLOAT baselineOriginX,
32572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            FLOAT baselineOriginY,
32672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            DWRITE_UNDERLINE const* underline,
32772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            IUnknown* clientDrawingEffect) SK_OVERRIDE
32872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        { return E_NOTIMPL; }
32972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
33072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        virtual HRESULT STDMETHODCALLTYPE DrawStrikethrough(
33172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            void* clientDrawingContext,
33272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            FLOAT baselineOriginX,
33372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            FLOAT baselineOriginY,
33472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            DWRITE_STRIKETHROUGH const* strikethrough,
33572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            IUnknown* clientDrawingEffect) SK_OVERRIDE
33672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        { return E_NOTIMPL; }
33772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
33872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        virtual HRESULT STDMETHODCALLTYPE DrawInlineObject(
33972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            void* clientDrawingContext,
34072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            FLOAT originX,
34172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            FLOAT originY,
34272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            IDWriteInlineObject* inlineObject,
34372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            BOOL isSideways,
34472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            BOOL isRightToLeft,
34572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            IUnknown* clientDrawingEffect) SK_OVERRIDE
34672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        { return E_NOTIMPL; }
34772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
34872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // IDWritePixelSnapping methods
34972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        virtual HRESULT STDMETHODCALLTYPE IsPixelSnappingDisabled(
35072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            void* clientDrawingContext,
35172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            BOOL* isDisabled) SK_OVERRIDE
35272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        {
35372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            *isDisabled = FALSE;
35472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return S_OK;
35572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
35672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
35772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        virtual HRESULT STDMETHODCALLTYPE GetCurrentTransform(
35872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            void* clientDrawingContext,
35972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            DWRITE_MATRIX* transform) SK_OVERRIDE
36072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        {
36172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            const DWRITE_MATRIX ident = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
36272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            *transform = ident;
36372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return S_OK;
36472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
36572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
36672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        virtual HRESULT STDMETHODCALLTYPE GetPixelsPerDip(
36772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            void* clientDrawingContext,
36872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            FLOAT* pixelsPerDip) SK_OVERRIDE
36972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        {
37072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            *pixelsPerDip = 1.0f;
37172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return S_OK;
37272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
37372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
37472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // IUnknown methods
37572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        virtual ULONG STDMETHODCALLTYPE AddRef() SK_OVERRIDE {
37672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return InterlockedIncrement(&fRefCount);
37772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
37872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
37972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        virtual ULONG STDMETHODCALLTYPE Release() SK_OVERRIDE {
38072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            ULONG newCount = InterlockedDecrement(&fRefCount);
38172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            if (0 == newCount) {
38272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                delete this;
38372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            }
38472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return newCount;
38572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
38672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
38772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        virtual HRESULT STDMETHODCALLTYPE QueryInterface(
38829d3777a82def082da486b735308f0fe57cec8d6skia.committer@gmail.com            IID const& riid, void** ppvObject) SK_OVERRIDE
38972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        {
39072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            if (__uuidof(IUnknown) == riid ||
39172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                __uuidof(IDWritePixelSnapping) == riid ||
39272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                __uuidof(IDWriteTextRenderer) == riid)
39372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            {
39472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                *ppvObject = this;
39572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                this->AddRef();
39672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                return S_OK;
39772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            }
39872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            *ppvObject = NULL;
39972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return E_FAIL;
40072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
40172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
40272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        const SkFontIdentity FallbackIdentity() { return fIdentity; }
40372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
40472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    protected:
40572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        ULONG fRefCount;
40672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkAutoTUnref<const SkRemotableFontMgr_DirectWrite> fOuter;
40772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        UINT32 fCharacter;
40872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkFontIdentity fIdentity;
40972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    };
41072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
41172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    virtual SkFontIdentity matchNameStyleCharacter(const char familyName[],
41272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                                   const SkFontStyle& pattern,
41372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                                   const char bpc47[],
41472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                                   SkUnichar character) const  SK_OVERRIDE
41572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    {
41672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkFontIdentity identity = { SkFontIdentity::kInvalidDataId };
41772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
41872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        IDWriteFactory* dwFactory = sk_get_dwrite_factory();
41972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (NULL == dwFactory) {
42072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return identity;
42172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
42272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
42372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // TODO: use IDWriteFactory2::GetSystemFontFallback when available.
42472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
42572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        const DWriteStyle dwStyle(pattern);
42672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
42772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkSMallocWCHAR dwFamilyName;
42872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (NULL == familyName) {
42972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HR_GENERAL(getDefaultFontFamilyName(&dwFamilyName), NULL, identity);
43072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        } else {
43172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HR_GENERAL(sk_cstring_to_wchar(familyName, &dwFamilyName), NULL, identity);
43272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
43372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
43472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        const SkSMallocWCHAR* dwBpc47;
43572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkSMallocWCHAR dwBpc47Local;
43672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (NULL == bpc47) {
43772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            dwBpc47 = &fLocaleName;
43872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        } else {
43972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            HR_GENERAL(sk_cstring_to_wchar(bpc47, &dwBpc47Local), NULL, identity);
44072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            dwBpc47 = &dwBpc47Local;
44172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
44272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
44372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IDWriteTextFormat> fallbackFormat;
44472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR_GENERAL(dwFactory->CreateTextFormat(dwFamilyName,
44572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                               fFontCollection.get(),
44672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                               dwStyle.fWeight,
44772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                               dwStyle.fSlant,
44872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                               dwStyle.fWidth,
44972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                               72.0f,
45072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                               *dwBpc47,
45172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                               &fallbackFormat),
45272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   "Could not create text format.",
45372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   identity);
45472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
45572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        WCHAR str[16];
4563d21f21cac33743e7aedace9abf0473c5063199fbungeman@google.com        UINT32 strLen = static_cast<UINT32>(
4573d21f21cac33743e7aedace9abf0473c5063199fbungeman@google.com            SkUTF16_FromUnichar(character, reinterpret_cast<uint16_t*>(str)));
45872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IDWriteTextLayout> fallbackLayout;
45972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR_GENERAL(dwFactory->CreateTextLayout(str, strLen, fallbackFormat.get(),
46072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                               200.0f, 200.0f,
46172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                               &fallbackLayout),
46272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   "Could not create text layout.",
46372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   identity);
46472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
46572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<FontFallbackRenderer> fontFallbackRenderer(
46672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            new FontFallbackRenderer(this, character));
46772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
46872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HR_GENERAL(fallbackLayout->Draw(NULL, fontFallbackRenderer.get(), 50.0f, 50.0f),
46972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   "Could not draw layout with renderer.",
47072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                   identity);
47172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
47272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return fontFallbackRenderer->FallbackIdentity();
47372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
47472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
47572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    virtual SkStreamAsset* getData(int dataId) const SK_OVERRIDE {
47672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkAutoMutexAcquire ama(fDataIdCacheMutex);
47772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (dataId >= fDataIdCache.count()) {
47872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return NULL;
47972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
48072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        const DataId& id = fDataIdCache[dataId];
48172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
48272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IDWriteFontFileLoader> loader;
48372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HRNM(id.fLoader->QueryInterface(&loader), "QuerryInterface IDWriteFontFileLoader failed");
48472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
48572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkTScopedComPtr<IDWriteFontFileStream> fontFileStream;
48672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        HRNM(loader->CreateStreamFromKey(id.fKey, id.fKeySize, &fontFileStream),
48772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com             "Could not create font file stream.");
48872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
48972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return SkNEW_ARGS(SkDWriteFontFileStream, (fontFileStream.get()));
49072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
49172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
49272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comprivate:
49372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
49472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkSMallocWCHAR fLocaleName;
49572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
49672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    typedef SkRemotableFontMgr INHERITED;
49772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com};
49872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
49972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comSkRemotableFontMgr* SkRemotableFontMgr_New_DirectWrite() {
50072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    IDWriteFactory* factory = sk_get_dwrite_factory();
50172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    if (NULL == factory) {
50272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return NULL;
50372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
50472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
50572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
50672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE),
50772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com         "Could not get system font collection.");
50872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
50972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
51072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    WCHAR* localeName = NULL;
51172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    int localeNameLen = 0;
51272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
51372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP.
51472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL;
51572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc);
51672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    if (NULL == getUserDefaultLocaleNameProc) {
51772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName.");
51872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    } else {
51972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH);
52072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (localeNameLen) {
52172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            localeName = localeNameStorage;
52272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        };
52372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
52472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
52572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    return SkNEW_ARGS(SkRemotableFontMgr_DirectWrite, (sysFontCollection.get(),
52672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                                       localeName, localeNameLen));
52772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
528