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