1 /*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkFontMgr.h"
9 #include "SkFontMgr_indirect.h"
10 #include "SkFontStyle.h"
11 #include "SkMutex.h"
12 #include "SkOnce.h"
13 #include "SkRefCnt.h"
14 #include "SkRemotableFontMgr.h"
15 #include "SkStream.h"
16 #include "SkString.h"
17 #include "SkTArray.h"
18 #include "SkTypeface.h"
19 #include "SkTypes.h"
20 #include "SkTemplates.h"
21
22 class SkData;
23
24 class SkStyleSet_Indirect : public SkFontStyleSet {
25 public:
26 /** Takes ownership of the SkRemotableFontIdentitySet. */
SkStyleSet_Indirect(const SkFontMgr_Indirect * owner,int familyIndex,SkRemotableFontIdentitySet * data)27 SkStyleSet_Indirect(const SkFontMgr_Indirect* owner, int familyIndex,
28 SkRemotableFontIdentitySet* data)
29 : fOwner(SkRef(owner)), fFamilyIndex(familyIndex), fData(data)
30 { }
31
count()32 int count() override { return fData->count(); }
33
getStyle(int index,SkFontStyle * fs,SkString * style)34 void getStyle(int index, SkFontStyle* fs, SkString* style) override {
35 if (fs) {
36 *fs = fData->at(index).fFontStyle;
37 }
38 if (style) {
39 // TODO: is this useful? Current locale?
40 style->reset();
41 }
42 }
43
createTypeface(int index)44 SkTypeface* createTypeface(int index) override {
45 return fOwner->createTypefaceFromFontId(fData->at(index));
46 }
47
matchStyle(const SkFontStyle & pattern)48 SkTypeface* matchStyle(const SkFontStyle& pattern) override {
49 if (fFamilyIndex >= 0) {
50 SkFontIdentity id = fOwner->fProxy->matchIndexStyle(fFamilyIndex, pattern);
51 return fOwner->createTypefaceFromFontId(id);
52 }
53
54 return this->matchStyleCSS3(pattern);
55 }
56 private:
57 sk_sp<const SkFontMgr_Indirect> fOwner;
58 int fFamilyIndex;
59 sk_sp<SkRemotableFontIdentitySet> fData;
60 };
61
onCountFamilies() const62 int SkFontMgr_Indirect::onCountFamilies() const {
63 return 0;
64 }
65
onGetFamilyName(int index,SkString * familyName) const66 void SkFontMgr_Indirect::onGetFamilyName(int index, SkString* familyName) const {
67 SK_ABORT("Not implemented");
68 }
69
onCreateStyleSet(int index) const70 SkFontStyleSet* SkFontMgr_Indirect::onCreateStyleSet(int index) const {
71 SK_ABORT("Not implemented");
72 return nullptr;
73 }
74
onMatchFamily(const char familyName[]) const75 SkFontStyleSet* SkFontMgr_Indirect::onMatchFamily(const char familyName[]) const {
76 return new SkStyleSet_Indirect(this, -1, fProxy->matchName(familyName));
77 }
78
createTypefaceFromFontId(const SkFontIdentity & id) const79 SkTypeface* SkFontMgr_Indirect::createTypefaceFromFontId(const SkFontIdentity& id) const {
80 if (id.fDataId == SkFontIdentity::kInvalidDataId) {
81 return nullptr;
82 }
83
84 SkAutoMutexAcquire ama(fDataCacheMutex);
85
86 sk_sp<SkTypeface> dataTypeface;
87 int dataTypefaceIndex = 0;
88 for (int i = 0; i < fDataCache.count(); ++i) {
89 const DataEntry& entry = fDataCache[i];
90 if (entry.fDataId == id.fDataId) {
91 if (entry.fTtcIndex == id.fTtcIndex &&
92 !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref())
93 {
94 return entry.fTypeface;
95 }
96 if (dataTypeface.get() == nullptr &&
97 !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref())
98 {
99 dataTypeface.reset(entry.fTypeface);
100 dataTypefaceIndex = entry.fTtcIndex;
101 }
102 }
103
104 if (entry.fTypeface->weak_expired()) {
105 fDataCache.removeShuffle(i);
106 --i;
107 }
108 }
109
110 // No exact match, but did find a data match.
111 if (dataTypeface.get() != nullptr) {
112 std::unique_ptr<SkStreamAsset> stream(dataTypeface->openStream(nullptr));
113 if (stream.get() != nullptr) {
114 return fImpl->makeFromStream(std::move(stream), dataTypefaceIndex).release();
115 }
116 }
117
118 // No data match, request data and add entry.
119 std::unique_ptr<SkStreamAsset> stream(fProxy->getData(id.fDataId));
120 if (stream.get() == nullptr) {
121 return nullptr;
122 }
123
124 sk_sp<SkTypeface> typeface(fImpl->makeFromStream(std::move(stream), id.fTtcIndex));
125 if (typeface.get() == nullptr) {
126 return nullptr;
127 }
128
129 DataEntry& newEntry = fDataCache.push_back();
130 typeface->weak_ref();
131 newEntry.fDataId = id.fDataId;
132 newEntry.fTtcIndex = id.fTtcIndex;
133 newEntry.fTypeface = typeface.get(); // weak reference passed to new entry.
134
135 return typeface.release();
136 }
137
onMatchFamilyStyle(const char familyName[],const SkFontStyle & fontStyle) const138 SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyle(const char familyName[],
139 const SkFontStyle& fontStyle) const {
140 SkFontIdentity id = fProxy->matchNameStyle(familyName, fontStyle);
141 return this->createTypefaceFromFontId(id);
142 }
143
onMatchFamilyStyleCharacter(const char familyName[],const SkFontStyle & style,const char * bcp47[],int bcp47Count,SkUnichar character) const144 SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyleCharacter(const char familyName[],
145 const SkFontStyle& style,
146 const char* bcp47[],
147 int bcp47Count,
148 SkUnichar character) const {
149 SkFontIdentity id = fProxy->matchNameStyleCharacter(familyName, style, bcp47,
150 bcp47Count, character);
151 return this->createTypefaceFromFontId(id);
152 }
153
onMatchFaceStyle(const SkTypeface * familyMember,const SkFontStyle & fontStyle) const154 SkTypeface* SkFontMgr_Indirect::onMatchFaceStyle(const SkTypeface* familyMember,
155 const SkFontStyle& fontStyle) const {
156 SkString familyName;
157 familyMember->getFamilyName(&familyName);
158 return this->matchFamilyStyle(familyName.c_str(), fontStyle);
159 }
160
onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,int ttcIndex) const161 sk_sp<SkTypeface> SkFontMgr_Indirect::onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,
162 int ttcIndex) const {
163 return fImpl->makeFromStream(std::move(stream), ttcIndex);
164 }
165
onMakeFromFile(const char path[],int ttcIndex) const166 sk_sp<SkTypeface> SkFontMgr_Indirect::onMakeFromFile(const char path[], int ttcIndex) const {
167 return fImpl->makeFromFile(path, ttcIndex);
168 }
169
onMakeFromData(sk_sp<SkData> data,int ttcIndex) const170 sk_sp<SkTypeface> SkFontMgr_Indirect::onMakeFromData(sk_sp<SkData> data, int ttcIndex) const {
171 return fImpl->makeFromData(std::move(data), ttcIndex);
172 }
173
onLegacyMakeTypeface(const char familyName[],SkFontStyle style) const174 sk_sp<SkTypeface> SkFontMgr_Indirect::onLegacyMakeTypeface(const char familyName[],
175 SkFontStyle style) const {
176 sk_sp<SkTypeface> face(this->matchFamilyStyle(familyName, style));
177
178 if (nullptr == face.get()) {
179 face.reset(this->matchFamilyStyle(nullptr, style));
180 }
181
182 if (nullptr == face.get()) {
183 SkFontIdentity fontId = this->fProxy->matchIndexStyle(0, style);
184 face.reset(this->createTypefaceFromFontId(fontId));
185 }
186
187 return face;
188 }
189