|  | /* | 
|  | * Copyright 2014 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #include "include/core/SkFontMgr.h" | 
|  | #include "include/core/SkFontStyle.h" | 
|  | #include "include/core/SkRefCnt.h" | 
|  | #include "include/core/SkStream.h" | 
|  | #include "include/core/SkString.h" | 
|  | #include "include/core/SkTypeface.h" | 
|  | #include "include/core/SkTypes.h" | 
|  | #include "include/ports/SkFontMgr_indirect.h" | 
|  | #include "include/ports/SkRemotableFontMgr.h" | 
|  | #include "include/private/SkMutex.h" | 
|  | #include "include/private/SkOnce.h" | 
|  | #include "include/private/SkTArray.h" | 
|  | #include "include/private/SkTemplates.h" | 
|  |  | 
|  | class SkData; | 
|  |  | 
|  | class SkStyleSet_Indirect : public SkFontStyleSet { | 
|  | public: | 
|  | /** Takes ownership of the SkRemotableFontIdentitySet. */ | 
|  | SkStyleSet_Indirect(const SkFontMgr_Indirect* owner, int familyIndex, | 
|  | SkRemotableFontIdentitySet* data) | 
|  | : fOwner(SkRef(owner)), fFamilyIndex(familyIndex), fData(data) | 
|  | { } | 
|  |  | 
|  | int count() override { return fData->count(); } | 
|  |  | 
|  | void getStyle(int index, SkFontStyle* fs, SkString* style) override { | 
|  | if (fs) { | 
|  | *fs = fData->at(index).fFontStyle; | 
|  | } | 
|  | if (style) { | 
|  | // TODO: is this useful? Current locale? | 
|  | style->reset(); | 
|  | } | 
|  | } | 
|  |  | 
|  | SkTypeface* createTypeface(int index) override { | 
|  | return fOwner->createTypefaceFromFontId(fData->at(index)); | 
|  | } | 
|  |  | 
|  | SkTypeface* matchStyle(const SkFontStyle& pattern) override { | 
|  | if (fFamilyIndex >= 0) { | 
|  | SkFontIdentity id = fOwner->fProxy->matchIndexStyle(fFamilyIndex, pattern); | 
|  | return fOwner->createTypefaceFromFontId(id); | 
|  | } | 
|  |  | 
|  | return this->matchStyleCSS3(pattern); | 
|  | } | 
|  | private: | 
|  | sk_sp<const SkFontMgr_Indirect> fOwner; | 
|  | int fFamilyIndex; | 
|  | sk_sp<SkRemotableFontIdentitySet> fData; | 
|  | }; | 
|  |  | 
|  | int SkFontMgr_Indirect::onCountFamilies() const { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | void SkFontMgr_Indirect::onGetFamilyName(int index, SkString* familyName) const { | 
|  | SK_ABORT("Not implemented"); | 
|  | } | 
|  |  | 
|  | SkFontStyleSet* SkFontMgr_Indirect::onCreateStyleSet(int index) const { | 
|  | SK_ABORT("Not implemented"); | 
|  | } | 
|  |  | 
|  | SkFontStyleSet* SkFontMgr_Indirect::onMatchFamily(const char familyName[]) const { | 
|  | return new SkStyleSet_Indirect(this, -1, fProxy->matchName(familyName)); | 
|  | } | 
|  |  | 
|  | SkTypeface* SkFontMgr_Indirect::createTypefaceFromFontId(const SkFontIdentity& id) const { | 
|  | if (id.fDataId == SkFontIdentity::kInvalidDataId) { | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | SkAutoMutexExclusive ama(fDataCacheMutex); | 
|  |  | 
|  | sk_sp<SkTypeface> dataTypeface; | 
|  | int dataTypefaceIndex = 0; | 
|  | for (int i = 0; i < fDataCache.count(); ++i) { | 
|  | const DataEntry& entry = fDataCache[i]; | 
|  | if (entry.fDataId == id.fDataId) { | 
|  | if (entry.fTtcIndex == id.fTtcIndex && | 
|  | !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref()) | 
|  | { | 
|  | return entry.fTypeface; | 
|  | } | 
|  | if (dataTypeface.get() == nullptr && | 
|  | !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref()) | 
|  | { | 
|  | dataTypeface.reset(entry.fTypeface); | 
|  | dataTypefaceIndex = entry.fTtcIndex; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (entry.fTypeface->weak_expired()) { | 
|  | fDataCache.removeShuffle(i); | 
|  | --i; | 
|  | } | 
|  | } | 
|  |  | 
|  | // No exact match, but did find a data match. | 
|  | if (dataTypeface.get() != nullptr) { | 
|  | std::unique_ptr<SkStreamAsset> stream(dataTypeface->openStream(nullptr)); | 
|  | if (stream.get() != nullptr) { | 
|  | return fImpl->makeFromStream(std::move(stream), dataTypefaceIndex).release(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // No data match, request data and add entry. | 
|  | std::unique_ptr<SkStreamAsset> stream(fProxy->getData(id.fDataId)); | 
|  | if (stream.get() == nullptr) { | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | sk_sp<SkTypeface> typeface(fImpl->makeFromStream(std::move(stream), id.fTtcIndex)); | 
|  | if (typeface.get() == nullptr) { | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | DataEntry& newEntry = fDataCache.push_back(); | 
|  | typeface->weak_ref(); | 
|  | newEntry.fDataId = id.fDataId; | 
|  | newEntry.fTtcIndex = id.fTtcIndex; | 
|  | newEntry.fTypeface = typeface.get();  // weak reference passed to new entry. | 
|  |  | 
|  | return typeface.release(); | 
|  | } | 
|  |  | 
|  | SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyle(const char familyName[], | 
|  | const SkFontStyle& fontStyle) const { | 
|  | SkFontIdentity id = fProxy->matchNameStyle(familyName, fontStyle); | 
|  | return this->createTypefaceFromFontId(id); | 
|  | } | 
|  |  | 
|  | SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyleCharacter(const char familyName[], | 
|  | const SkFontStyle& style, | 
|  | const char* bcp47[], | 
|  | int bcp47Count, | 
|  | SkUnichar character) const { | 
|  | SkFontIdentity id = fProxy->matchNameStyleCharacter(familyName, style, bcp47, | 
|  | bcp47Count, character); | 
|  | return this->createTypefaceFromFontId(id); | 
|  | } | 
|  |  | 
|  | SkTypeface* SkFontMgr_Indirect::onMatchFaceStyle(const SkTypeface* familyMember, | 
|  | const SkFontStyle& fontStyle) const { | 
|  | SkString familyName; | 
|  | familyMember->getFamilyName(&familyName); | 
|  | return this->matchFamilyStyle(familyName.c_str(), fontStyle); | 
|  | } | 
|  |  | 
|  | sk_sp<SkTypeface> SkFontMgr_Indirect::onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream, | 
|  | int ttcIndex) const { | 
|  | return fImpl->makeFromStream(std::move(stream), ttcIndex); | 
|  | } | 
|  |  | 
|  | sk_sp<SkTypeface> SkFontMgr_Indirect::onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream, | 
|  | const SkFontArguments& args) const { | 
|  | return fImpl->makeFromStream(std::move(stream), args); | 
|  | } | 
|  |  | 
|  | sk_sp<SkTypeface> SkFontMgr_Indirect::onMakeFromFile(const char path[], int ttcIndex) const { | 
|  | return fImpl->makeFromFile(path, ttcIndex); | 
|  | } | 
|  |  | 
|  | sk_sp<SkTypeface> SkFontMgr_Indirect::onMakeFromData(sk_sp<SkData> data, int ttcIndex) const { | 
|  | return fImpl->makeFromData(std::move(data), ttcIndex); | 
|  | } | 
|  |  | 
|  | sk_sp<SkTypeface> SkFontMgr_Indirect::onLegacyMakeTypeface(const char familyName[], | 
|  | SkFontStyle style) const { | 
|  | sk_sp<SkTypeface> face(this->matchFamilyStyle(familyName, style)); | 
|  |  | 
|  | if (nullptr == face.get()) { | 
|  | face.reset(this->matchFamilyStyle(nullptr, style)); | 
|  | } | 
|  |  | 
|  | if (nullptr == face.get()) { | 
|  | SkFontIdentity fontId = this->fProxy->matchIndexStyle(0, style); | 
|  | face.reset(this->createTypefaceFromFontId(fontId)); | 
|  | } | 
|  |  | 
|  | return face; | 
|  | } |