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