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