• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
onMatchFaceStyle(const SkTypeface * familyMember,const SkFontStyle & fontStyle) const153 SkTypeface* SkFontMgr_Indirect::onMatchFaceStyle(const SkTypeface* familyMember,
154                                                  const SkFontStyle& fontStyle) const {
155     SkString familyName;
156     familyMember->getFamilyName(&familyName);
157     return this->matchFamilyStyle(familyName.c_str(), fontStyle);
158 }
159 
onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,int ttcIndex) const160 sk_sp<SkTypeface> SkFontMgr_Indirect::onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,
161                                                             int ttcIndex) const {
162     return fImpl->makeFromStream(std::move(stream), ttcIndex);
163 }
164 
onMakeFromFile(const char path[],int ttcIndex) const165 sk_sp<SkTypeface> SkFontMgr_Indirect::onMakeFromFile(const char path[], int ttcIndex) const {
166     return fImpl->makeFromFile(path, ttcIndex);
167 }
168 
onMakeFromData(sk_sp<SkData> data,int ttcIndex) const169 sk_sp<SkTypeface> SkFontMgr_Indirect::onMakeFromData(sk_sp<SkData> data, int ttcIndex) const {
170     return fImpl->makeFromData(std::move(data), ttcIndex);
171 }
172 
onLegacyMakeTypeface(const char familyName[],SkFontStyle style) const173 sk_sp<SkTypeface> SkFontMgr_Indirect::onLegacyMakeTypeface(const char familyName[],
174                                                            SkFontStyle style) const {
175     sk_sp<SkTypeface> face(this->matchFamilyStyle(familyName, style));
176 
177     if (nullptr == face.get()) {
178         face.reset(this->matchFamilyStyle(nullptr, style));
179     }
180 
181     if (nullptr == face.get()) {
182         SkFontIdentity fontId = this->fProxy->matchIndexStyle(0, style);
183         face.reset(this->createTypefaceFromFontId(fontId));
184     }
185 
186     return face;
187 }
188