• 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 "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