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 "SkDataTable.h"
9 #include "SkFontMgr.h"
10 #include "SkFontMgr_indirect.h"
11 #include "SkFontStyle.h"
12 #include "SkMutex.h"
13 #include "SkOnce.h"
14 #include "SkRefCnt.h"
15 #include "SkRemotableFontMgr.h"
16 #include "SkStream.h"
17 #include "SkString.h"
18 #include "SkTArray.h"
19 #include "SkTypeface.h"
20 #include "SkTypes.h"
21 #include "SkTemplates.h"
22
23 class SkData;
24
25 class SkStyleSet_Indirect : public SkFontStyleSet {
26 public:
27 /** Takes ownership of the SkRemotableFontIdentitySet. */
SkStyleSet_Indirect(const SkFontMgr_Indirect * owner,int familyIndex,SkRemotableFontIdentitySet * data)28 SkStyleSet_Indirect(const SkFontMgr_Indirect* owner, int familyIndex,
29 SkRemotableFontIdentitySet* data)
30 : fOwner(SkRef(owner)), fFamilyIndex(familyIndex), fData(data)
31 { }
32
count()33 int count() override { return fData->count(); }
34
getStyle(int index,SkFontStyle * fs,SkString * style)35 void getStyle(int index, SkFontStyle* fs, SkString* style) override {
36 if (fs) {
37 *fs = fData->at(index).fFontStyle;
38 }
39 if (style) {
40 // TODO: is this useful? Current locale?
41 style->reset();
42 }
43 }
44
createTypeface(int index)45 SkTypeface* createTypeface(int index) override {
46 return fOwner->createTypefaceFromFontId(fData->at(index));
47 }
48
matchStyle(const SkFontStyle & pattern)49 SkTypeface* matchStyle(const SkFontStyle& pattern) override {
50 if (fFamilyIndex >= 0) {
51 SkFontIdentity id = fOwner->fProxy->matchIndexStyle(fFamilyIndex, pattern);
52 return fOwner->createTypefaceFromFontId(id);
53 }
54
55 return this->matchStyleCSS3(pattern);
56 }
57 private:
58 SkAutoTUnref<const SkFontMgr_Indirect> fOwner;
59 int fFamilyIndex;
60 SkAutoTUnref<SkRemotableFontIdentitySet> fData;
61 };
62
set_up_family_names(const SkFontMgr_Indirect * self)63 void SkFontMgr_Indirect::set_up_family_names(const SkFontMgr_Indirect* self) {
64 self->fFamilyNames.reset(self->fProxy->getFamilyNames());
65 }
66
onCountFamilies() const67 int SkFontMgr_Indirect::onCountFamilies() const {
68 SkOnce(&fFamilyNamesInited, &fFamilyNamesMutex, SkFontMgr_Indirect::set_up_family_names, this);
69 return fFamilyNames->count();
70 }
71
onGetFamilyName(int index,SkString * familyName) const72 void SkFontMgr_Indirect::onGetFamilyName(int index, SkString* familyName) const {
73 SkOnce(&fFamilyNamesInited, &fFamilyNamesMutex, SkFontMgr_Indirect::set_up_family_names, this);
74 if (index >= fFamilyNames->count()) {
75 familyName->reset();
76 return;
77 }
78 familyName->set(fFamilyNames->atStr(index));
79 }
80
onCreateStyleSet(int index) const81 SkFontStyleSet* SkFontMgr_Indirect::onCreateStyleSet(int index) const {
82 SkRemotableFontIdentitySet* set = fProxy->getIndex(index);
83 if (nullptr == set) {
84 return nullptr;
85 }
86 return new SkStyleSet_Indirect(this, index, set);
87 }
88
onMatchFamily(const char familyName[]) const89 SkFontStyleSet* SkFontMgr_Indirect::onMatchFamily(const char familyName[]) const {
90 return new SkStyleSet_Indirect(this, -1, fProxy->matchName(familyName));
91 }
92
createTypefaceFromFontId(const SkFontIdentity & id) const93 SkTypeface* SkFontMgr_Indirect::createTypefaceFromFontId(const SkFontIdentity& id) const {
94 if (id.fDataId == SkFontIdentity::kInvalidDataId) {
95 return nullptr;
96 }
97
98 SkAutoMutexAcquire ama(fDataCacheMutex);
99
100 SkAutoTUnref<SkTypeface> dataTypeface;
101 int dataTypefaceIndex = 0;
102 for (int i = 0; i < fDataCache.count(); ++i) {
103 const DataEntry& entry = fDataCache[i];
104 if (entry.fDataId == id.fDataId) {
105 if (entry.fTtcIndex == id.fTtcIndex &&
106 !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref())
107 {
108 return entry.fTypeface;
109 }
110 if (dataTypeface.get() == nullptr &&
111 !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref())
112 {
113 dataTypeface.reset(entry.fTypeface);
114 dataTypefaceIndex = entry.fTtcIndex;
115 }
116 }
117
118 if (entry.fTypeface->weak_expired()) {
119 fDataCache.removeShuffle(i);
120 --i;
121 }
122 }
123
124 // No exact match, but did find a data match.
125 if (dataTypeface.get() != nullptr) {
126 SkAutoTDelete<SkStreamAsset> stream(dataTypeface->openStream(nullptr));
127 if (stream.get() != nullptr) {
128 return fImpl->createFromStream(stream.detach(), dataTypefaceIndex);
129 }
130 }
131
132 // No data match, request data and add entry.
133 SkAutoTDelete<SkStreamAsset> stream(fProxy->getData(id.fDataId));
134 if (stream.get() == nullptr) {
135 return nullptr;
136 }
137
138 SkAutoTUnref<SkTypeface> typeface(fImpl->createFromStream(stream.detach(), id.fTtcIndex));
139 if (typeface.get() == nullptr) {
140 return nullptr;
141 }
142
143 DataEntry& newEntry = fDataCache.push_back();
144 typeface->weak_ref();
145 newEntry.fDataId = id.fDataId;
146 newEntry.fTtcIndex = id.fTtcIndex;
147 newEntry.fTypeface = typeface.get(); // weak reference passed to new entry.
148
149 return typeface.detach();
150 }
151
onMatchFamilyStyle(const char familyName[],const SkFontStyle & fontStyle) const152 SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyle(const char familyName[],
153 const SkFontStyle& fontStyle) const {
154 SkFontIdentity id = fProxy->matchNameStyle(familyName, fontStyle);
155 return this->createTypefaceFromFontId(id);
156 }
157
onMatchFamilyStyleCharacter(const char familyName[],const SkFontStyle & style,const char * bcp47[],int bcp47Count,SkUnichar character) const158 SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyleCharacter(const char familyName[],
159 const SkFontStyle& style,
160 const char* bcp47[],
161 int bcp47Count,
162 SkUnichar character) const {
163 SkFontIdentity id = fProxy->matchNameStyleCharacter(familyName, style, bcp47,
164 bcp47Count, character);
165 return this->createTypefaceFromFontId(id);
166 }
167
onMatchFaceStyle(const SkTypeface * familyMember,const SkFontStyle & fontStyle) const168 SkTypeface* SkFontMgr_Indirect::onMatchFaceStyle(const SkTypeface* familyMember,
169 const SkFontStyle& fontStyle) const {
170 SkString familyName;
171 familyMember->getFamilyName(&familyName);
172 return this->matchFamilyStyle(familyName.c_str(), fontStyle);
173 }
174
onCreateFromStream(SkStreamAsset * stream,int ttcIndex) const175 SkTypeface* SkFontMgr_Indirect::onCreateFromStream(SkStreamAsset* stream, int ttcIndex) const {
176 return fImpl->createFromStream(stream, ttcIndex);
177 }
178
onCreateFromFile(const char path[],int ttcIndex) const179 SkTypeface* SkFontMgr_Indirect::onCreateFromFile(const char path[], int ttcIndex) const {
180 return fImpl->createFromFile(path, ttcIndex);
181 }
182
onCreateFromData(SkData * data,int ttcIndex) const183 SkTypeface* SkFontMgr_Indirect::onCreateFromData(SkData* data, int ttcIndex) const {
184 return fImpl->createFromData(data, ttcIndex);
185 }
186
onLegacyCreateTypeface(const char familyName[],unsigned styleBits) const187 SkTypeface* SkFontMgr_Indirect::onLegacyCreateTypeface(const char familyName[],
188 unsigned styleBits) const {
189 bool bold = SkToBool(styleBits & SkTypeface::kBold);
190 bool italic = SkToBool(styleBits & SkTypeface::kItalic);
191 SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight
192 : SkFontStyle::kNormal_Weight,
193 SkFontStyle::kNormal_Width,
194 italic ? SkFontStyle::kItalic_Slant
195 : SkFontStyle::kUpright_Slant);
196
197 SkAutoTUnref<SkTypeface> face(this->matchFamilyStyle(familyName, style));
198
199 if (nullptr == face.get()) {
200 face.reset(this->matchFamilyStyle(nullptr, style));
201 }
202
203 if (nullptr == face.get()) {
204 SkFontIdentity fontId = this->fProxy->matchIndexStyle(0, style);
205 face.reset(this->createTypefaceFromFontId(fontId));
206 }
207
208 return face.detach();
209 }
210