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 "include/core/SkFontMgr.h"
9 #include "include/core/SkFontStyle.h"
10 #include "include/core/SkRefCnt.h"
11 #include "include/core/SkStream.h"
12 #include "include/core/SkString.h"
13 #include "include/core/SkTypeface.h"
14 #include "include/core/SkTypes.h"
15 #include "include/ports/SkFontMgr_indirect.h"
16 #include "include/ports/SkRemotableFontMgr.h"
17 #include "include/private/SkMutex.h"
18 #include "include/private/SkOnce.h"
19 #include "include/private/SkTArray.h"
20 #include "include/private/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 }
73
onMatchFamily(const char familyName[]) const74 SkFontStyleSet* SkFontMgr_Indirect::onMatchFamily(const char familyName[]) const {
75 return new SkStyleSet_Indirect(this, -1, fProxy->matchName(familyName));
76 }
77
createTypefaceFromFontId(const SkFontIdentity & id) const78 SkTypeface* SkFontMgr_Indirect::createTypefaceFromFontId(const SkFontIdentity& id) const {
79 if (id.fDataId == SkFontIdentity::kInvalidDataId) {
80 return nullptr;
81 }
82
83 SkAutoMutexExclusive ama(fDataCacheMutex);
84
85 sk_sp<SkTypeface> dataTypeface;
86 int dataTypefaceIndex = 0;
87 for (int i = 0; i < fDataCache.count(); ++i) {
88 const DataEntry& entry = fDataCache[i];
89 if (entry.fDataId == id.fDataId) {
90 if (entry.fTtcIndex == id.fTtcIndex &&
91 !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref())
92 {
93 return entry.fTypeface;
94 }
95 if (dataTypeface.get() == nullptr &&
96 !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref())
97 {
98 dataTypeface.reset(entry.fTypeface);
99 dataTypefaceIndex = entry.fTtcIndex;
100 }
101 }
102
103 if (entry.fTypeface->weak_expired()) {
104 fDataCache.removeShuffle(i);
105 --i;
106 }
107 }
108
109 // No exact match, but did find a data match.
110 if (dataTypeface.get() != nullptr) {
111 std::unique_ptr<SkStreamAsset> stream(dataTypeface->openStream(nullptr));
112 if (stream.get() != nullptr) {
113 return fImpl->makeFromStream(std::move(stream), dataTypefaceIndex).release();
114 }
115 }
116
117 // No data match, request data and add entry.
118 std::unique_ptr<SkStreamAsset> stream(fProxy->getData(id.fDataId));
119 if (stream.get() == nullptr) {
120 return nullptr;
121 }
122
123 sk_sp<SkTypeface> typeface(fImpl->makeFromStream(std::move(stream), id.fTtcIndex));
124 if (typeface.get() == nullptr) {
125 return nullptr;
126 }
127
128 DataEntry& newEntry = fDataCache.push_back();
129 typeface->weak_ref();
130 newEntry.fDataId = id.fDataId;
131 newEntry.fTtcIndex = id.fTtcIndex;
132 newEntry.fTypeface = typeface.get(); // weak reference passed to new entry.
133
134 return typeface.release();
135 }
136
onMatchFamilyStyle(const char familyName[],const SkFontStyle & fontStyle) const137 SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyle(const char familyName[],
138 const SkFontStyle& fontStyle) const {
139 SkFontIdentity id = fProxy->matchNameStyle(familyName, fontStyle);
140 return this->createTypefaceFromFontId(id);
141 }
142
onMatchFamilyStyleCharacter(const char familyName[],const SkFontStyle & style,const char * bcp47[],int bcp47Count,SkUnichar character) const143 SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyleCharacter(const char familyName[],
144 const SkFontStyle& style,
145 const char* bcp47[],
146 int bcp47Count,
147 SkUnichar character) const {
148 SkFontIdentity id = fProxy->matchNameStyleCharacter(familyName, style, bcp47,
149 bcp47Count, character);
150 return this->createTypefaceFromFontId(id);
151 }
152
onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,int ttcIndex) const153 sk_sp<SkTypeface> SkFontMgr_Indirect::onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,
154 int ttcIndex) const {
155 return fImpl->makeFromStream(std::move(stream), ttcIndex);
156 }
157
onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,const SkFontArguments & args) const158 sk_sp<SkTypeface> SkFontMgr_Indirect::onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,
159 const SkFontArguments& args) const {
160 return fImpl->makeFromStream(std::move(stream), args);
161 }
162
onMakeFromFile(const char path[],int ttcIndex) const163 sk_sp<SkTypeface> SkFontMgr_Indirect::onMakeFromFile(const char path[], int ttcIndex) const {
164 return fImpl->makeFromFile(path, ttcIndex);
165 }
166
onMakeFromData(sk_sp<SkData> data,int ttcIndex) const167 sk_sp<SkTypeface> SkFontMgr_Indirect::onMakeFromData(sk_sp<SkData> data, int ttcIndex) const {
168 return fImpl->makeFromData(std::move(data), ttcIndex);
169 }
170
onLegacyMakeTypeface(const char familyName[],SkFontStyle style) const171 sk_sp<SkTypeface> SkFontMgr_Indirect::onLegacyMakeTypeface(const char familyName[],
172 SkFontStyle style) const {
173 sk_sp<SkTypeface> face(this->matchFamilyStyle(familyName, style));
174
175 if (nullptr == face.get()) {
176 face.reset(this->matchFamilyStyle(nullptr, style));
177 }
178
179 if (nullptr == face.get()) {
180 SkFontIdentity fontId = this->fProxy->matchIndexStyle(0, style);
181 face.reset(this->createTypefaceFromFontId(fontId));
182 }
183
184 return face;
185 }
186