blob: ead0bf0b834d194f3b29706f95011704131dd846 [file] [log] [blame]
bungeman8d84c992014-07-24 08:05:09 -07001/*
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
mtklein1ee76512015-11-02 10:20:27 -08008#include "SkTypes.h"
mtklein1ee76512015-11-02 10:20:27 -08009
khushalsagarebc465b2016-02-12 12:42:48 -080010#include "SkData.h"
bungemanf20488b2015-07-29 11:49:40 -070011#include "SkFixed.h"
bungeman8d84c992014-07-24 08:05:09 -070012#include "SkFontDescriptor.h"
13#include "SkFontHost_FreeType_common.h"
14#include "SkFontMgr.h"
bungeman7fa87cd2015-02-06 07:59:19 -080015#include "SkFontMgr_android.h"
bungemanc5308542015-06-23 13:25:46 -070016#include "SkFontMgr_android_parser.h"
bungeman8d84c992014-07-24 08:05:09 -070017#include "SkFontStyle.h"
khushalsagarebc465b2016-02-12 12:42:48 -080018#include "SkOSFile.h"
bungeman24a104d2015-07-30 10:31:57 -070019#include "SkPaint.h"
bungemanf20488b2015-07-29 11:49:40 -070020#include "SkRefCnt.h"
21#include "SkString.h"
bungeman8d84c992014-07-24 08:05:09 -070022#include "SkStream.h"
bungemanf20488b2015-07-29 11:49:40 -070023#include "SkTArray.h"
bungeman8d84c992014-07-24 08:05:09 -070024#include "SkTDArray.h"
25#include "SkTSearch.h"
bungemanf20488b2015-07-29 11:49:40 -070026#include "SkTemplates.h"
bungeman8d84c992014-07-24 08:05:09 -070027#include "SkTypefaceCache.h"
28
29#include <limits>
bungeman8d84c992014-07-24 08:05:09 -070030
bungemanf20488b2015-07-29 11:49:40 -070031class SkData;
32
bungeman8d84c992014-07-24 08:05:09 -070033class SkTypeface_Android : public SkTypeface_FreeType {
34public:
bungeman41868fe2015-05-20 09:21:04 -070035 SkTypeface_Android(const SkFontStyle& style,
bungeman8d84c992014-07-24 08:05:09 -070036 bool isFixedPitch,
bungeman4b86bac2014-11-04 10:54:31 -080037 const SkString& familyName)
bungeman8d84c992014-07-24 08:05:09 -070038 : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch)
bungeman41868fe2015-05-20 09:21:04 -070039 , fFamilyName(familyName)
40 { }
bungeman8d84c992014-07-24 08:05:09 -070041
bungeman8d84c992014-07-24 08:05:09 -070042protected:
mtklein36352bf2015-03-25 18:17:31 -070043 void onGetFamilyName(SkString* familyName) const override {
bungemanb374d6a2014-09-17 07:48:59 -070044 *familyName = fFamilyName;
45 }
46
bungeman8d84c992014-07-24 08:05:09 -070047 SkString fFamilyName;
48
49private:
50 typedef SkTypeface_FreeType INHERITED;
51};
52
53class SkTypeface_AndroidSystem : public SkTypeface_Android {
54public:
bungeman4b86bac2014-11-04 10:54:31 -080055 SkTypeface_AndroidSystem(const SkString& pathName,
khushalsagarebc465b2016-02-12 12:42:48 -080056 const bool cacheFontFiles,
bungeman8d84c992014-07-24 08:05:09 -070057 int index,
bungeman41868fe2015-05-20 09:21:04 -070058 const SkFixed* axes, int axesCount,
bungemana4c4a2d2014-10-20 13:33:19 -070059 const SkFontStyle& style,
bungeman8d84c992014-07-24 08:05:09 -070060 bool isFixedPitch,
bungeman4b86bac2014-11-04 10:54:31 -080061 const SkString& familyName,
bungeman65fcd3d2014-08-06 11:12:20 -070062 const SkLanguage& lang,
djsollen3b625542014-08-14 06:29:02 -070063 FontVariant variantStyle)
bungeman41868fe2015-05-20 09:21:04 -070064 : INHERITED(style, isFixedPitch, familyName)
bungeman65fcd3d2014-08-06 11:12:20 -070065 , fPathName(pathName)
bungeman41868fe2015-05-20 09:21:04 -070066 , fIndex(index)
67 , fAxes(axes, axesCount)
bungeman65fcd3d2014-08-06 11:12:20 -070068 , fLang(lang)
khushalsagarebc465b2016-02-12 12:42:48 -080069 , fVariantStyle(variantStyle)
70 , fFile(cacheFontFiles ? sk_fopen(fPathName.c_str(), kRead_SkFILE_Flag) : nullptr) {
71 if (cacheFontFiles) {
72 SkASSERT(fFile);
73 }
74 }
75
76 SkStreamAsset* createStream() const {
77 if (fFile) {
78 SkData* data = SkData::NewFromFILE(fFile);
79 return data ? new SkMemoryStream(data) : nullptr;
80 }
81 return SkStream::NewFromFile(fPathName.c_str());
82 }
bungeman8d84c992014-07-24 08:05:09 -070083
bungeman41868fe2015-05-20 09:21:04 -070084 virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
bungeman8d84c992014-07-24 08:05:09 -070085 SkASSERT(desc);
86 SkASSERT(serialize);
87 desc->setFamilyName(fFamilyName.c_str());
bungeman8d84c992014-07-24 08:05:09 -070088 *serialize = false;
89 }
mtklein36352bf2015-03-25 18:17:31 -070090 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
bungeman8d84c992014-07-24 08:05:09 -070091 *ttcIndex = fIndex;
khushalsagarebc465b2016-02-12 12:42:48 -080092 return this->createStream();
bungeman8d84c992014-07-24 08:05:09 -070093 }
bungeman41868fe2015-05-20 09:21:04 -070094 SkFontData* onCreateFontData() const override {
khushalsagarebc465b2016-02-12 12:42:48 -080095 return new SkFontData(this->createStream(), fIndex, fAxes.begin(), fAxes.count());
bungeman41868fe2015-05-20 09:21:04 -070096 }
bungeman8d84c992014-07-24 08:05:09 -070097
bungeman65fcd3d2014-08-06 11:12:20 -070098 const SkString fPathName;
bungeman41868fe2015-05-20 09:21:04 -070099 int fIndex;
100 const SkSTArray<4, SkFixed, true> fAxes;
bungeman65fcd3d2014-08-06 11:12:20 -0700101 const SkLanguage fLang;
djsollen3b625542014-08-14 06:29:02 -0700102 const FontVariant fVariantStyle;
khushalsagarebc465b2016-02-12 12:42:48 -0800103 SkAutoTCallVProc<FILE, sk_fclose> fFile;
bungeman8d84c992014-07-24 08:05:09 -0700104
105 typedef SkTypeface_Android INHERITED;
106};
107
108class SkTypeface_AndroidStream : public SkTypeface_Android {
109public:
bungeman41868fe2015-05-20 09:21:04 -0700110 SkTypeface_AndroidStream(SkFontData* data,
bungemana4c4a2d2014-10-20 13:33:19 -0700111 const SkFontStyle& style,
bungeman8d84c992014-07-24 08:05:09 -0700112 bool isFixedPitch,
bungeman4b86bac2014-11-04 10:54:31 -0800113 const SkString& familyName)
bungeman41868fe2015-05-20 09:21:04 -0700114 : INHERITED(style, isFixedPitch, familyName)
115 , fData(data)
116 { }
bungeman8d84c992014-07-24 08:05:09 -0700117
118 virtual void onGetFontDescriptor(SkFontDescriptor* desc,
mtklein36352bf2015-03-25 18:17:31 -0700119 bool* serialize) const override {
bungeman8d84c992014-07-24 08:05:09 -0700120 SkASSERT(desc);
121 SkASSERT(serialize);
122 desc->setFamilyName(fFamilyName.c_str());
bungeman8d84c992014-07-24 08:05:09 -0700123 *serialize = true;
124 }
125
mtklein36352bf2015-03-25 18:17:31 -0700126 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
bungeman41868fe2015-05-20 09:21:04 -0700127 *ttcIndex = fData->getIndex();
128 return fData->duplicateStream();
129 }
130
131 SkFontData* onCreateFontData() const override {
132 return new SkFontData(*fData.get());
bungeman8d84c992014-07-24 08:05:09 -0700133 }
134
135private:
bungeman41868fe2015-05-20 09:21:04 -0700136 const SkAutoTDelete<const SkFontData> fData;
bungeman8d84c992014-07-24 08:05:09 -0700137 typedef SkTypeface_Android INHERITED;
138};
139
bungeman8d84c992014-07-24 08:05:09 -0700140class SkFontStyleSet_Android : public SkFontStyleSet {
bungeman41868fe2015-05-20 09:21:04 -0700141 typedef SkTypeface_FreeType::Scanner Scanner;
142
bungeman8d84c992014-07-24 08:05:09 -0700143public:
khushalsagarebc465b2016-02-12 12:42:48 -0800144 explicit SkFontStyleSet_Android(const FontFamily& family, const Scanner& scanner,
145 const bool cacheFontFiles) {
halcanary96fcdcc2015-08-27 07:41:13 -0700146 const SkString* cannonicalFamilyName = nullptr;
bungeman65fcd3d2014-08-06 11:12:20 -0700147 if (family.fNames.count() > 0) {
148 cannonicalFamilyName = &family.fNames[0];
149 }
bungeman8d84c992014-07-24 08:05:09 -0700150 // TODO? make this lazy
tomhudsond3ddea22014-08-11 11:28:00 -0700151 for (int i = 0; i < family.fFonts.count(); ++i) {
152 const FontFileInfo& fontFile = family.fFonts[i];
bungeman8d84c992014-07-24 08:05:09 -0700153
bungeman7fa87cd2015-02-06 07:59:19 -0800154 SkString pathName(family.fBasePath);
155 pathName.append(fontFile.fFileName);
bungeman8d84c992014-07-24 08:05:09 -0700156
scroggoa1193e42015-01-21 12:09:53 -0800157 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(pathName.c_str()));
bungeman8d84c992014-07-24 08:05:09 -0700158 if (!stream.get()) {
bungeman7fa87cd2015-02-06 07:59:19 -0800159 SkDEBUGF(("Requested font file %s does not exist or cannot be opened.\n",
160 pathName.c_str()));
bungeman8d84c992014-07-24 08:05:09 -0700161 continue;
162 }
163
bungeman65fcd3d2014-08-06 11:12:20 -0700164 const int ttcIndex = fontFile.fIndex;
165 SkString familyName;
bungemana4c4a2d2014-10-20 13:33:19 -0700166 SkFontStyle style;
bungeman8d84c992014-07-24 08:05:09 -0700167 bool isFixedWidth;
bungeman41868fe2015-05-20 09:21:04 -0700168 Scanner::AxisDefinitions axisDefinitions;
169 if (!scanner.scanFont(stream.get(), ttcIndex,
170 &familyName, &style, &isFixedWidth, &axisDefinitions))
171 {
bungeman7fa87cd2015-02-06 07:59:19 -0800172 SkDEBUGF(("Requested font file %s exists, but is not a valid font.\n",
173 pathName.c_str()));
bungeman8d84c992014-07-24 08:05:09 -0700174 continue;
175 }
176
bungemane85a7542015-04-17 13:51:08 -0700177 int weight = fontFile.fWeight != 0 ? fontFile.fWeight : style.weight();
178 SkFontStyle::Slant slant = style.slant();
179 switch (fontFile.fStyle) {
180 case FontFileInfo::Style::kAuto: slant = style.slant(); break;
181 case FontFileInfo::Style::kNormal: slant = SkFontStyle::kUpright_Slant; break;
182 case FontFileInfo::Style::kItalic: slant = SkFontStyle::kItalic_Slant; break;
183 default: SkASSERT(false); break;
bungeman4b86bac2014-11-04 10:54:31 -0800184 }
bungemane85a7542015-04-17 13:51:08 -0700185 style = SkFontStyle(weight, style.width(), slant);
bungeman4b86bac2014-11-04 10:54:31 -0800186
djsollen3b625542014-08-14 06:29:02 -0700187 const SkLanguage& lang = family.fLanguage;
188 uint32_t variant = family.fVariant;
189 if (kDefault_FontVariant == variant) {
190 variant = kCompact_FontVariant | kElegant_FontVariant;
bungeman65fcd3d2014-08-06 11:12:20 -0700191 }
192
193 // The first specified family name overrides the family name found in the font.
194 // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return
195 // all of the specified family names in addition to the names found in the font.
halcanary96fcdcc2015-08-27 07:41:13 -0700196 if (cannonicalFamilyName != nullptr) {
bungeman65fcd3d2014-08-06 11:12:20 -0700197 familyName = *cannonicalFamilyName;
198 }
199
bungeman41868fe2015-05-20 09:21:04 -0700200 SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
bungeman47a1e962016-02-25 11:20:01 -0800201 Scanner::computeAxisValues(axisDefinitions,
202 fontFile.fAxes.begin(), fontFile.fAxes.count(),
203 axisValues, familyName);
bungeman41868fe2015-05-20 09:21:04 -0700204
bungemanf6c71072016-01-21 14:17:47 -0800205 fStyles.push_back().reset(new SkTypeface_AndroidSystem(
khushalsagarebc465b2016-02-12 12:42:48 -0800206 pathName, cacheFontFiles, ttcIndex, axisValues.get(), axisDefinitions.count(),
207 style, isFixedWidth, familyName, lang, variant));
bungeman8d84c992014-07-24 08:05:09 -0700208 }
209 }
210
mtklein36352bf2015-03-25 18:17:31 -0700211 int count() override {
bungeman8d84c992014-07-24 08:05:09 -0700212 return fStyles.count();
213 }
mtklein36352bf2015-03-25 18:17:31 -0700214 void getStyle(int index, SkFontStyle* style, SkString* name) override {
bungeman8d84c992014-07-24 08:05:09 -0700215 if (index < 0 || fStyles.count() <= index) {
216 return;
217 }
218 if (style) {
219 *style = this->style(index);
220 }
221 if (name) {
222 name->reset();
223 }
224 }
mtklein36352bf2015-03-25 18:17:31 -0700225 SkTypeface_AndroidSystem* createTypeface(int index) override {
bungeman8d84c992014-07-24 08:05:09 -0700226 if (index < 0 || fStyles.count() <= index) {
halcanary96fcdcc2015-08-27 07:41:13 -0700227 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700228 }
229 return SkRef(fStyles[index].get());
230 }
231
232 /** Find the typeface in this style set that most closely matches the given pattern.
233 * TODO: consider replacing with SkStyleSet_Indirect::matchStyle();
234 * this simpler version using match_score() passes all our tests.
235 */
mtklein36352bf2015-03-25 18:17:31 -0700236 SkTypeface_AndroidSystem* matchStyle(const SkFontStyle& pattern) override {
bungeman8d84c992014-07-24 08:05:09 -0700237 if (0 == fStyles.count()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700238 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700239 }
bungeman65fcd3d2014-08-06 11:12:20 -0700240 SkTypeface_AndroidSystem* closest = fStyles[0];
bungeman8d84c992014-07-24 08:05:09 -0700241 int minScore = std::numeric_limits<int>::max();
242 for (int i = 0; i < fStyles.count(); ++i) {
243 SkFontStyle style = this->style(i);
244 int score = match_score(pattern, style);
245 if (score < minScore) {
246 closest = fStyles[i];
247 minScore = score;
248 }
249 }
250 return SkRef(closest);
251 }
252
253private:
254 SkFontStyle style(int index) {
bungeman4b86bac2014-11-04 10:54:31 -0800255 return fStyles[index]->fontStyle();
bungeman8d84c992014-07-24 08:05:09 -0700256 }
257 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) {
258 int score = 0;
bungemanf20488b2015-07-29 11:49:40 -0700259 score += SkTAbs((pattern.width() - candidate.width()) * 100);
260 score += SkTAbs((pattern.isItalic() == candidate.isItalic()) ? 0 : 1000);
261 score += SkTAbs(pattern.weight() - candidate.weight());
bungeman8d84c992014-07-24 08:05:09 -0700262 return score;
263 }
264
bungeman65fcd3d2014-08-06 11:12:20 -0700265 SkTArray<SkAutoTUnref<SkTypeface_AndroidSystem>, true> fStyles;
bungeman8d84c992014-07-24 08:05:09 -0700266
267 friend struct NameToFamily;
268 friend class SkFontMgr_Android;
269
270 typedef SkFontStyleSet INHERITED;
271};
272
273/** On Android a single family can have many names, but our API assumes unique names.
274 * Map names to the back end so that all names for a given family refer to the same
275 * (non-replicated) set of typefaces.
276 * SkTDict<> doesn't let us do index-based lookup, so we write our own mapping.
277 */
278struct NameToFamily {
279 SkString name;
280 SkFontStyleSet_Android* styleSet;
281};
282
283class SkFontMgr_Android : public SkFontMgr {
284public:
bungeman7fa87cd2015-02-06 07:59:19 -0800285 SkFontMgr_Android(const SkFontMgr_Android_CustomFonts* custom) {
286 SkTDArray<FontFamily*> families;
287 if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem != custom->fSystemFontUse) {
288 SkString base(custom->fBasePath);
bungemanc5308542015-06-23 13:25:46 -0700289 SkFontMgr_Android_Parser::GetCustomFontFamilies(
290 families, base, custom->fFontsXml, custom->fFallbackFontsXml);
bungeman7fa87cd2015-02-06 07:59:19 -0800291 }
292 if (!custom ||
293 (custom && SkFontMgr_Android_CustomFonts::kOnlyCustom != custom->fSystemFontUse))
294 {
bungemanc5308542015-06-23 13:25:46 -0700295 SkFontMgr_Android_Parser::GetSystemFontFamilies(families);
bungeman7fa87cd2015-02-06 07:59:19 -0800296 }
297 if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem == custom->fSystemFontUse) {
298 SkString base(custom->fBasePath);
bungemanc5308542015-06-23 13:25:46 -0700299 SkFontMgr_Android_Parser::GetCustomFontFamilies(
300 families, base, custom->fFontsXml, custom->fFallbackFontsXml);
bungeman7fa87cd2015-02-06 07:59:19 -0800301 }
khushalsagarebc465b2016-02-12 12:42:48 -0800302 this->buildNameToFamilyMap(families, custom ? custom->fIsolated : false);
bungeman4e3523c2014-08-08 12:06:51 -0700303 this->findDefaultFont();
bungeman7fa87cd2015-02-06 07:59:19 -0800304 families.deleteAll();
bungeman8d84c992014-07-24 08:05:09 -0700305 }
306
307protected:
308 /** Returns not how many families we have, but how many unique names
309 * exist among the families.
310 */
mtklein36352bf2015-03-25 18:17:31 -0700311 int onCountFamilies() const override {
bungeman8d84c992014-07-24 08:05:09 -0700312 return fNameToFamilyMap.count();
313 }
314
mtklein36352bf2015-03-25 18:17:31 -0700315 void onGetFamilyName(int index, SkString* familyName) const override {
bungeman8d84c992014-07-24 08:05:09 -0700316 if (index < 0 || fNameToFamilyMap.count() <= index) {
317 familyName->reset();
318 return;
319 }
320 familyName->set(fNameToFamilyMap[index].name);
321 }
322
mtklein36352bf2015-03-25 18:17:31 -0700323 SkFontStyleSet* onCreateStyleSet(int index) const override {
bungeman8d84c992014-07-24 08:05:09 -0700324 if (index < 0 || fNameToFamilyMap.count() <= index) {
halcanary96fcdcc2015-08-27 07:41:13 -0700325 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700326 }
327 return SkRef(fNameToFamilyMap[index].styleSet);
328 }
329
mtklein36352bf2015-03-25 18:17:31 -0700330 SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
bungeman8d84c992014-07-24 08:05:09 -0700331 if (!familyName) {
halcanary96fcdcc2015-08-27 07:41:13 -0700332 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700333 }
334 SkAutoAsciiToLC tolc(familyName);
335 for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
336 if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
337 return SkRef(fNameToFamilyMap[i].styleSet);
338 }
339 }
bungeman65fcd3d2014-08-06 11:12:20 -0700340 // TODO: eventually we should not need to name fallback families.
341 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
342 if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) {
343 return SkRef(fFallbackNameToFamilyMap[i].styleSet);
344 }
345 }
halcanary96fcdcc2015-08-27 07:41:13 -0700346 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700347 }
348
349 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
mtklein36352bf2015-03-25 18:17:31 -0700350 const SkFontStyle& style) const override {
bungeman8d84c992014-07-24 08:05:09 -0700351 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
352 return sset->matchStyle(style);
353 }
354
355 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
mtklein36352bf2015-03-25 18:17:31 -0700356 const SkFontStyle& style) const override {
bungeman8d84c992014-07-24 08:05:09 -0700357 for (int i = 0; i < fFontStyleSets.count(); ++i) {
358 for (int j = 0; j < fFontStyleSets[i]->fStyles.count(); ++j) {
359 if (fFontStyleSets[i]->fStyles[j] == typeface) {
360 return fFontStyleSets[i]->matchStyle(style);
361 }
362 }
363 }
halcanary96fcdcc2015-08-27 07:41:13 -0700364 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700365 }
366
bungemanc9232dc2014-11-10 13:29:33 -0800367 static SkTypeface_AndroidSystem* find_family_style_character(
368 const SkTDArray<NameToFamily>& fallbackNameToFamilyMap,
369 const SkFontStyle& style, bool elegant,
370 const SkString& langTag, SkUnichar character)
371 {
372 for (int i = 0; i < fallbackNameToFamilyMap.count(); ++i) {
373 SkFontStyleSet_Android* family = fallbackNameToFamilyMap[i].styleSet;
374 SkAutoTUnref<SkTypeface_AndroidSystem> face(family->matchStyle(style));
bungemanc20386e2014-10-23 07:08:05 -0700375
bungemanc9232dc2014-11-10 13:29:33 -0800376 if (!langTag.isEmpty() && !face->fLang.getTag().startsWith(langTag.c_str())) {
377 continue;
378 }
379
380 if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) {
381 continue;
382 }
383
bungeman24a104d2015-07-30 10:31:57 -0700384 SkPaint paint;
385 paint.setTypeface(face);
386 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
387
388 uint16_t glyphID;
389 paint.textToGlyphs(&character, sizeof(character), &glyphID);
390 if (glyphID != 0) {
mtklein18300a32016-03-16 13:53:35 -0700391 return face.release();
bungemanc9232dc2014-11-10 13:29:33 -0800392 }
bungemanc20386e2014-10-23 07:08:05 -0700393 }
halcanary96fcdcc2015-08-27 07:41:13 -0700394 return nullptr;
bungemanc20386e2014-10-23 07:08:05 -0700395 }
bungemanc9232dc2014-11-10 13:29:33 -0800396
bungeman65fcd3d2014-08-06 11:12:20 -0700397 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
398 const SkFontStyle& style,
bungemanc20386e2014-10-23 07:08:05 -0700399 const char* bcp47[],
400 int bcp47Count,
mtklein36352bf2015-03-25 18:17:31 -0700401 SkUnichar character) const override
bungeman65fcd3d2014-08-06 11:12:20 -0700402 {
403 // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascent/descent'.
404 // The variant 'default' means 'compact and elegant'.
405 // As a result, it is not possible to know the variant context from the font alone.
406 // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request.
407
bungemanc20386e2014-10-23 07:08:05 -0700408 // The first time match anything elegant, second time anything not elegant.
409 for (int elegant = 2; elegant --> 0;) {
410 for (int bcp47Index = bcp47Count; bcp47Index --> 0;) {
411 SkLanguage lang(bcp47[bcp47Index]);
412 while (!lang.getTag().isEmpty()) {
413 SkTypeface_AndroidSystem* matchingTypeface =
414 find_family_style_character(fFallbackNameToFamilyMap,
415 style, SkToBool(elegant),
416 lang.getTag(), character);
417 if (matchingTypeface) {
418 return matchingTypeface;
bungeman65fcd3d2014-08-06 11:12:20 -0700419 }
420
bungemanc20386e2014-10-23 07:08:05 -0700421 lang = lang.getParent();
bungeman65fcd3d2014-08-06 11:12:20 -0700422 }
bungemanc20386e2014-10-23 07:08:05 -0700423 }
424 SkTypeface_AndroidSystem* matchingTypeface =
425 find_family_style_character(fFallbackNameToFamilyMap,
426 style, SkToBool(elegant),
427 SkString(), character);
428 if (matchingTypeface) {
429 return matchingTypeface;
430 }
bungeman65fcd3d2014-08-06 11:12:20 -0700431 }
halcanary96fcdcc2015-08-27 07:41:13 -0700432 return nullptr;
bungeman65fcd3d2014-08-06 11:12:20 -0700433 }
434
mtklein36352bf2015-03-25 18:17:31 -0700435 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
scroggoa1193e42015-01-21 12:09:53 -0800436 return this->createFromStream(new SkMemoryStream(data), ttcIndex);
bungeman8d84c992014-07-24 08:05:09 -0700437 }
438
mtklein36352bf2015-03-25 18:17:31 -0700439 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
bungeman5f213d92015-01-27 05:39:10 -0800440 SkAutoTDelete<SkStreamAsset> stream(SkStream::NewFromFile(path));
mtklein18300a32016-03-16 13:53:35 -0700441 return stream.get() ? this->createFromStream(stream.release(), ttcIndex) : nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700442 }
443
mtklein36352bf2015-03-25 18:17:31 -0700444 SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override {
bungeman5f213d92015-01-27 05:39:10 -0800445 SkAutoTDelete<SkStreamAsset> stream(bareStream);
bungeman8d84c992014-07-24 08:05:09 -0700446 bool isFixedPitch;
bungemana4c4a2d2014-10-20 13:33:19 -0700447 SkFontStyle style;
bungeman8d84c992014-07-24 08:05:09 -0700448 SkString name;
halcanary96fcdcc2015-08-27 07:41:13 -0700449 if (!fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch, nullptr)) {
450 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700451 }
mtklein18300a32016-03-16 13:53:35 -0700452 SkFontData* data(new SkFontData(stream.release(), ttcIndex, nullptr, 0));
halcanary385fe4d2015-08-26 13:07:48 -0700453 return new SkTypeface_AndroidStream(data, style, isFixedPitch, name);
bungeman41868fe2015-05-20 09:21:04 -0700454 }
455
bungemanf6c71072016-01-21 14:17:47 -0800456 SkTypeface* onCreateFromStream(SkStreamAsset* s, const FontParameters& params) const override {
457 using Scanner = SkTypeface_FreeType::Scanner;
458 SkAutoTDelete<SkStreamAsset> stream(s);
459 bool isFixedPitch;
460 SkFontStyle style;
461 SkString name;
462 Scanner::AxisDefinitions axisDefinitions;
463 if (!fScanner.scanFont(stream, params.getCollectionIndex(), &name, &style, &isFixedPitch,
464 &axisDefinitions))
465 {
466 return nullptr;
467 }
468
469 int paramAxisCount;
470 const FontParameters::Axis* paramAxes = params.getAxes(&paramAxisCount);
471 SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
472 Scanner::computeAxisValues(axisDefinitions, paramAxes, paramAxisCount, axisValues, name);
473
mtklein18300a32016-03-16 13:53:35 -0700474 SkFontData* data(new SkFontData(stream.release(), params.getCollectionIndex(),
bungemanf6c71072016-01-21 14:17:47 -0800475 axisValues.get(), axisDefinitions.count()));
476 return new SkTypeface_AndroidStream(data, style, isFixedPitch, name);
477 }
478
bungeman41868fe2015-05-20 09:21:04 -0700479 SkTypeface* onCreateFromFontData(SkFontData* data) const override {
480 SkStreamAsset* stream(data->getStream());
481 bool isFixedPitch;
482 SkFontStyle style;
483 SkString name;
halcanary96fcdcc2015-08-27 07:41:13 -0700484 if (!fScanner.scanFont(stream, data->getIndex(), &name, &style, &isFixedPitch, nullptr)) {
485 return nullptr;
bungeman41868fe2015-05-20 09:21:04 -0700486 }
halcanary385fe4d2015-08-26 13:07:48 -0700487 return new SkTypeface_AndroidStream(data, style, isFixedPitch, name);
bungeman8d84c992014-07-24 08:05:09 -0700488 }
489
490
491 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
mtklein36352bf2015-03-25 18:17:31 -0700492 unsigned styleBits) const override {
bungemana4c4a2d2014-10-20 13:33:19 -0700493 SkFontStyle style = SkFontStyle(styleBits);
bungeman8d84c992014-07-24 08:05:09 -0700494
bsalomon49f085d2014-09-05 13:34:00 -0700495 if (familyName) {
halcanary96fcdcc2015-08-27 07:41:13 -0700496 // On Android, we must return nullptr when we can't find the requested
bungeman8d84c992014-07-24 08:05:09 -0700497 // named typeface so that the system/app can provide their own recovery
498 // mechanism. On other platforms we'd provide a typeface from the
499 // default family instead.
bungeman07cfb202014-07-30 11:05:22 -0700500 return this->onMatchFamilyStyle(familyName, style);
bungeman8d84c992014-07-24 08:05:09 -0700501 }
bungeman07cfb202014-07-30 11:05:22 -0700502 return fDefaultFamily->matchStyle(style);
bungeman8d84c992014-07-24 08:05:09 -0700503 }
504
505
506private:
507
bungeman14df8332014-10-28 15:07:23 -0700508 SkTypeface_FreeType::Scanner fScanner;
509
bungeman8d84c992014-07-24 08:05:09 -0700510 SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets;
511 SkFontStyleSet* fDefaultFamily;
512 SkTypeface* fDefaultTypeface;
513
514 SkTDArray<NameToFamily> fNameToFamilyMap;
bungeman65fcd3d2014-08-06 11:12:20 -0700515 SkTDArray<NameToFamily> fFallbackNameToFamilyMap;
bungeman8d84c992014-07-24 08:05:09 -0700516
khushalsagarebc465b2016-02-12 12:42:48 -0800517 void buildNameToFamilyMap(SkTDArray<FontFamily*> families, const bool isolated) {
bungeman8d84c992014-07-24 08:05:09 -0700518 for (int i = 0; i < families.count(); i++) {
bungeman65fcd3d2014-08-06 11:12:20 -0700519 FontFamily& family = *families[i];
520
521 SkTDArray<NameToFamily>* nameToFamily = &fNameToFamilyMap;
522 if (family.fIsFallbackFont) {
523 nameToFamily = &fFallbackNameToFamilyMap;
524
525 if (0 == family.fNames.count()) {
526 SkString& fallbackName = family.fNames.push_back();
527 fallbackName.printf("%.2x##fallback", i);
528 }
529 }
530
khushalsagarebc465b2016-02-12 12:42:48 -0800531 SkFontStyleSet_Android* newSet = new SkFontStyleSet_Android(family, fScanner, isolated);
bungeman65fcd3d2014-08-06 11:12:20 -0700532 if (0 == newSet->count()) {
halcanary385fe4d2015-08-26 13:07:48 -0700533 delete newSet;
bungeman65fcd3d2014-08-06 11:12:20 -0700534 continue;
535 }
536 fFontStyleSets.push_back().reset(newSet);
537
538 for (int j = 0; j < family.fNames.count(); j++) {
539 NameToFamily* nextEntry = nameToFamily->append();
halcanary385fe4d2015-08-26 13:07:48 -0700540 new (&nextEntry->name) SkString(family.fNames[j]);
bungeman65fcd3d2014-08-06 11:12:20 -0700541 nextEntry->styleSet = newSet;
bungeman8d84c992014-07-24 08:05:09 -0700542 }
543 }
544 }
545
546 void findDefaultFont() {
547 SkASSERT(!fFontStyleSets.empty());
548
549 static const char* gDefaultNames[] = { "sans-serif" };
550 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
551 SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]);
halcanary96fcdcc2015-08-27 07:41:13 -0700552 if (nullptr == set) {
bungeman8d84c992014-07-24 08:05:09 -0700553 continue;
554 }
555 SkTypeface* tf = set->matchStyle(SkFontStyle());
halcanary96fcdcc2015-08-27 07:41:13 -0700556 if (nullptr == tf) {
bungeman8d84c992014-07-24 08:05:09 -0700557 continue;
558 }
559 fDefaultFamily = set;
560 fDefaultTypeface = tf;
561 break;
562 }
halcanary96fcdcc2015-08-27 07:41:13 -0700563 if (nullptr == fDefaultTypeface) {
bungeman8d84c992014-07-24 08:05:09 -0700564 fDefaultFamily = fFontStyleSets[0];
565 fDefaultTypeface = fDefaultFamily->createTypeface(0);
566 }
567 SkASSERT(fDefaultFamily);
568 SkASSERT(fDefaultTypeface);
569 }
570
571 typedef SkFontMgr INHERITED;
572};
573
bungeman7fa87cd2015-02-06 07:59:19 -0800574#ifdef SK_DEBUG
575static char const * const gSystemFontUseStrings[] = {
576 "OnlyCustom", "PreferCustom", "PreferSystem"
577};
578#endif
579SkFontMgr* SkFontMgr_New_Android(const SkFontMgr_Android_CustomFonts* custom) {
580 if (custom) {
581 SkASSERT(0 <= custom->fSystemFontUse);
582 SkASSERT(custom->fSystemFontUse < SK_ARRAY_COUNT(gSystemFontUseStrings));
583 SkDEBUGF(("SystemFontUse: %s BasePath: %s Fonts: %s FallbackFonts: %s\n",
584 gSystemFontUseStrings[custom->fSystemFontUse],
585 custom->fBasePath,
586 custom->fFontsXml,
587 custom->fFallbackFontsXml));
bungeman4e3523c2014-08-08 12:06:51 -0700588 }
589
halcanary385fe4d2015-08-26 13:07:48 -0700590 return new SkFontMgr_Android(custom);
bungeman8d84c992014-07-24 08:05:09 -0700591}