blob: dc89d91931b965033932967075e2dd3a6df93132 [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
bungemanf20488b2015-07-29 11:49:40 -07008#include "SkFixed.h"
bungeman8d84c992014-07-24 08:05:09 -07009#include "SkFontDescriptor.h"
10#include "SkFontHost_FreeType_common.h"
11#include "SkFontMgr.h"
bungeman7fa87cd2015-02-06 07:59:19 -080012#include "SkFontMgr_android.h"
bungemanc5308542015-06-23 13:25:46 -070013#include "SkFontMgr_android_parser.h"
bungeman8d84c992014-07-24 08:05:09 -070014#include "SkFontStyle.h"
bungeman24a104d2015-07-30 10:31:57 -070015#include "SkPaint.h"
bungemanf20488b2015-07-29 11:49:40 -070016#include "SkRefCnt.h"
17#include "SkString.h"
bungeman8d84c992014-07-24 08:05:09 -070018#include "SkStream.h"
bungemanf20488b2015-07-29 11:49:40 -070019#include "SkTArray.h"
bungeman8d84c992014-07-24 08:05:09 -070020#include "SkTDArray.h"
21#include "SkTSearch.h"
bungemanf20488b2015-07-29 11:49:40 -070022#include "SkTemplates.h"
bungeman8d84c992014-07-24 08:05:09 -070023#include "SkTypefaceCache.h"
24
25#include <limits>
bungeman8d84c992014-07-24 08:05:09 -070026
bungemanf20488b2015-07-29 11:49:40 -070027class SkData;
28
bungeman8d84c992014-07-24 08:05:09 -070029class SkTypeface_Android : public SkTypeface_FreeType {
30public:
bungeman41868fe2015-05-20 09:21:04 -070031 SkTypeface_Android(const SkFontStyle& style,
bungeman8d84c992014-07-24 08:05:09 -070032 bool isFixedPitch,
bungeman4b86bac2014-11-04 10:54:31 -080033 const SkString& familyName)
bungeman8d84c992014-07-24 08:05:09 -070034 : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch)
bungeman41868fe2015-05-20 09:21:04 -070035 , fFamilyName(familyName)
36 { }
bungeman8d84c992014-07-24 08:05:09 -070037
bungeman8d84c992014-07-24 08:05:09 -070038protected:
mtklein36352bf2015-03-25 18:17:31 -070039 void onGetFamilyName(SkString* familyName) const override {
bungemanb374d6a2014-09-17 07:48:59 -070040 *familyName = fFamilyName;
41 }
42
bungeman8d84c992014-07-24 08:05:09 -070043 SkString fFamilyName;
44
45private:
46 typedef SkTypeface_FreeType INHERITED;
47};
48
49class SkTypeface_AndroidSystem : public SkTypeface_Android {
50public:
bungeman4b86bac2014-11-04 10:54:31 -080051 SkTypeface_AndroidSystem(const SkString& pathName,
bungeman8d84c992014-07-24 08:05:09 -070052 int index,
bungeman41868fe2015-05-20 09:21:04 -070053 const SkFixed* axes, int axesCount,
bungemana4c4a2d2014-10-20 13:33:19 -070054 const SkFontStyle& style,
bungeman8d84c992014-07-24 08:05:09 -070055 bool isFixedPitch,
bungeman4b86bac2014-11-04 10:54:31 -080056 const SkString& familyName,
bungeman65fcd3d2014-08-06 11:12:20 -070057 const SkLanguage& lang,
djsollen3b625542014-08-14 06:29:02 -070058 FontVariant variantStyle)
bungeman41868fe2015-05-20 09:21:04 -070059 : INHERITED(style, isFixedPitch, familyName)
bungeman65fcd3d2014-08-06 11:12:20 -070060 , fPathName(pathName)
bungeman41868fe2015-05-20 09:21:04 -070061 , fIndex(index)
62 , fAxes(axes, axesCount)
bungeman65fcd3d2014-08-06 11:12:20 -070063 , fLang(lang)
64 , fVariantStyle(variantStyle) { }
bungeman8d84c992014-07-24 08:05:09 -070065
bungeman41868fe2015-05-20 09:21:04 -070066 virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
bungeman8d84c992014-07-24 08:05:09 -070067 SkASSERT(desc);
68 SkASSERT(serialize);
69 desc->setFamilyName(fFamilyName.c_str());
bungeman8d84c992014-07-24 08:05:09 -070070 *serialize = false;
71 }
mtklein36352bf2015-03-25 18:17:31 -070072 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
bungeman8d84c992014-07-24 08:05:09 -070073 *ttcIndex = fIndex;
74 return SkStream::NewFromFile(fPathName.c_str());
75 }
bungeman41868fe2015-05-20 09:21:04 -070076 SkFontData* onCreateFontData() const override {
77 return new SkFontData(SkStream::NewFromFile(fPathName.c_str()), fIndex,
78 fAxes.begin(), fAxes.count());
79 }
bungeman8d84c992014-07-24 08:05:09 -070080
bungeman65fcd3d2014-08-06 11:12:20 -070081 const SkString fPathName;
bungeman41868fe2015-05-20 09:21:04 -070082 int fIndex;
83 const SkSTArray<4, SkFixed, true> fAxes;
bungeman65fcd3d2014-08-06 11:12:20 -070084 const SkLanguage fLang;
djsollen3b625542014-08-14 06:29:02 -070085 const FontVariant fVariantStyle;
bungeman8d84c992014-07-24 08:05:09 -070086
87 typedef SkTypeface_Android INHERITED;
88};
89
90class SkTypeface_AndroidStream : public SkTypeface_Android {
91public:
bungeman41868fe2015-05-20 09:21:04 -070092 SkTypeface_AndroidStream(SkFontData* data,
bungemana4c4a2d2014-10-20 13:33:19 -070093 const SkFontStyle& style,
bungeman8d84c992014-07-24 08:05:09 -070094 bool isFixedPitch,
bungeman4b86bac2014-11-04 10:54:31 -080095 const SkString& familyName)
bungeman41868fe2015-05-20 09:21:04 -070096 : INHERITED(style, isFixedPitch, familyName)
97 , fData(data)
98 { }
bungeman8d84c992014-07-24 08:05:09 -070099
100 virtual void onGetFontDescriptor(SkFontDescriptor* desc,
mtklein36352bf2015-03-25 18:17:31 -0700101 bool* serialize) const override {
bungeman8d84c992014-07-24 08:05:09 -0700102 SkASSERT(desc);
103 SkASSERT(serialize);
104 desc->setFamilyName(fFamilyName.c_str());
bungeman8d84c992014-07-24 08:05:09 -0700105 *serialize = true;
106 }
107
mtklein36352bf2015-03-25 18:17:31 -0700108 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
bungeman41868fe2015-05-20 09:21:04 -0700109 *ttcIndex = fData->getIndex();
110 return fData->duplicateStream();
111 }
112
113 SkFontData* onCreateFontData() const override {
114 return new SkFontData(*fData.get());
bungeman8d84c992014-07-24 08:05:09 -0700115 }
116
117private:
bungeman41868fe2015-05-20 09:21:04 -0700118 const SkAutoTDelete<const SkFontData> fData;
bungeman8d84c992014-07-24 08:05:09 -0700119 typedef SkTypeface_Android INHERITED;
120};
121
bungeman8d84c992014-07-24 08:05:09 -0700122class SkFontStyleSet_Android : public SkFontStyleSet {
bungeman41868fe2015-05-20 09:21:04 -0700123 typedef SkTypeface_FreeType::Scanner Scanner;
124
bungeman8d84c992014-07-24 08:05:09 -0700125public:
bungeman41868fe2015-05-20 09:21:04 -0700126 explicit SkFontStyleSet_Android(const FontFamily& family, const Scanner& scanner) {
bungeman65fcd3d2014-08-06 11:12:20 -0700127 const SkString* cannonicalFamilyName = NULL;
128 if (family.fNames.count() > 0) {
129 cannonicalFamilyName = &family.fNames[0];
130 }
bungeman8d84c992014-07-24 08:05:09 -0700131 // TODO? make this lazy
tomhudsond3ddea22014-08-11 11:28:00 -0700132 for (int i = 0; i < family.fFonts.count(); ++i) {
133 const FontFileInfo& fontFile = family.fFonts[i];
bungeman8d84c992014-07-24 08:05:09 -0700134
bungeman7fa87cd2015-02-06 07:59:19 -0800135 SkString pathName(family.fBasePath);
136 pathName.append(fontFile.fFileName);
bungeman8d84c992014-07-24 08:05:09 -0700137
scroggoa1193e42015-01-21 12:09:53 -0800138 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(pathName.c_str()));
bungeman8d84c992014-07-24 08:05:09 -0700139 if (!stream.get()) {
bungeman7fa87cd2015-02-06 07:59:19 -0800140 SkDEBUGF(("Requested font file %s does not exist or cannot be opened.\n",
141 pathName.c_str()));
bungeman8d84c992014-07-24 08:05:09 -0700142 continue;
143 }
144
bungeman65fcd3d2014-08-06 11:12:20 -0700145 const int ttcIndex = fontFile.fIndex;
146 SkString familyName;
bungemana4c4a2d2014-10-20 13:33:19 -0700147 SkFontStyle style;
bungeman8d84c992014-07-24 08:05:09 -0700148 bool isFixedWidth;
bungeman41868fe2015-05-20 09:21:04 -0700149 Scanner::AxisDefinitions axisDefinitions;
150 if (!scanner.scanFont(stream.get(), ttcIndex,
151 &familyName, &style, &isFixedWidth, &axisDefinitions))
152 {
bungeman7fa87cd2015-02-06 07:59:19 -0800153 SkDEBUGF(("Requested font file %s exists, but is not a valid font.\n",
154 pathName.c_str()));
bungeman8d84c992014-07-24 08:05:09 -0700155 continue;
156 }
157
bungemane85a7542015-04-17 13:51:08 -0700158 int weight = fontFile.fWeight != 0 ? fontFile.fWeight : style.weight();
159 SkFontStyle::Slant slant = style.slant();
160 switch (fontFile.fStyle) {
161 case FontFileInfo::Style::kAuto: slant = style.slant(); break;
162 case FontFileInfo::Style::kNormal: slant = SkFontStyle::kUpright_Slant; break;
163 case FontFileInfo::Style::kItalic: slant = SkFontStyle::kItalic_Slant; break;
164 default: SkASSERT(false); break;
bungeman4b86bac2014-11-04 10:54:31 -0800165 }
bungemane85a7542015-04-17 13:51:08 -0700166 style = SkFontStyle(weight, style.width(), slant);
bungeman4b86bac2014-11-04 10:54:31 -0800167
djsollen3b625542014-08-14 06:29:02 -0700168 const SkLanguage& lang = family.fLanguage;
169 uint32_t variant = family.fVariant;
170 if (kDefault_FontVariant == variant) {
171 variant = kCompact_FontVariant | kElegant_FontVariant;
bungeman65fcd3d2014-08-06 11:12:20 -0700172 }
173
174 // The first specified family name overrides the family name found in the font.
175 // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return
176 // all of the specified family names in addition to the names found in the font.
177 if (cannonicalFamilyName != NULL) {
178 familyName = *cannonicalFamilyName;
179 }
180
bungeman41868fe2015-05-20 09:21:04 -0700181 SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
182 for (int i = 0; i < axisDefinitions.count(); ++i) {
183 const Scanner::AxisDefinition& axisDefinition = axisDefinitions[i];
184 axisValues[i] = axisDefinition.fDefault;
185 for (int j = 0; j < fontFile.fAxes.count(); ++j) {
186 const FontFileInfo::Axis& axisSpecified = fontFile.fAxes[j];
187 if (axisDefinition.fTag == axisSpecified.fTag) {
188 axisValues[i] = SkTPin(axisSpecified.fValue, axisDefinition.fMinimum,
189 axisDefinition.fMaximum);
190 if (axisValues[i] != axisSpecified.fValue) {
191 SkDEBUGF(("Requested font axis value out of range: "
192 "%s '%c%c%c%c' %f; pinned to %f.\n",
193 familyName.c_str(),
194 (axisDefinition.fTag >> 24) & 0xFF,
195 (axisDefinition.fTag >> 16) & 0xFF,
196 (axisDefinition.fTag >> 8) & 0xFF,
197 (axisDefinition.fTag ) & 0xFF,
198 SkFixedToDouble(axisSpecified.fValue),
199 SkFixedToDouble(axisValues[i])));
200 }
201 break;
202 }
203 }
204 // TODO: warn on defaulted axis?
205 }
206
halcanary385fe4d2015-08-26 13:07:48 -0700207 SkDEBUGCODE(
208 // Check for axis specified, but not matched in font.
209 for (int i = 0; i < fontFile.fAxes.count(); ++i) {
210 SkFourByteTag skTag = fontFile.fAxes[i].fTag;
211 bool found = false;
212 for (int j = 0; j < axisDefinitions.count(); ++j) {
213 if (skTag == axisDefinitions[j].fTag) {
214 found = true;
215 break;
216 }
bungeman41868fe2015-05-20 09:21:04 -0700217 }
halcanary385fe4d2015-08-26 13:07:48 -0700218 if (!found) {
219 SkDEBUGF(("Requested font axis not found: %s '%c%c%c%c'\n",
220 familyName.c_str(), (skTag >> 24) & 0xFF,
221 (skTag >> 16) & 0xFF, (skTag >> 8) & 0xFF, (skTag)&0xFF));
222 }
223 })
bungeman41868fe2015-05-20 09:21:04 -0700224
halcanary385fe4d2015-08-26 13:07:48 -0700225 fStyles.push_back().reset(new SkTypeface_AndroidSystem(
226 pathName, ttcIndex, axisValues.get(), axisDefinitions.count(), style,
227 isFixedWidth, familyName, lang, variant));
bungeman8d84c992014-07-24 08:05:09 -0700228 }
229 }
230
mtklein36352bf2015-03-25 18:17:31 -0700231 int count() override {
bungeman8d84c992014-07-24 08:05:09 -0700232 return fStyles.count();
233 }
mtklein36352bf2015-03-25 18:17:31 -0700234 void getStyle(int index, SkFontStyle* style, SkString* name) override {
bungeman8d84c992014-07-24 08:05:09 -0700235 if (index < 0 || fStyles.count() <= index) {
236 return;
237 }
238 if (style) {
239 *style = this->style(index);
240 }
241 if (name) {
242 name->reset();
243 }
244 }
mtklein36352bf2015-03-25 18:17:31 -0700245 SkTypeface_AndroidSystem* createTypeface(int index) override {
bungeman8d84c992014-07-24 08:05:09 -0700246 if (index < 0 || fStyles.count() <= index) {
247 return NULL;
248 }
249 return SkRef(fStyles[index].get());
250 }
251
252 /** Find the typeface in this style set that most closely matches the given pattern.
253 * TODO: consider replacing with SkStyleSet_Indirect::matchStyle();
254 * this simpler version using match_score() passes all our tests.
255 */
mtklein36352bf2015-03-25 18:17:31 -0700256 SkTypeface_AndroidSystem* matchStyle(const SkFontStyle& pattern) override {
bungeman8d84c992014-07-24 08:05:09 -0700257 if (0 == fStyles.count()) {
258 return NULL;
259 }
bungeman65fcd3d2014-08-06 11:12:20 -0700260 SkTypeface_AndroidSystem* closest = fStyles[0];
bungeman8d84c992014-07-24 08:05:09 -0700261 int minScore = std::numeric_limits<int>::max();
262 for (int i = 0; i < fStyles.count(); ++i) {
263 SkFontStyle style = this->style(i);
264 int score = match_score(pattern, style);
265 if (score < minScore) {
266 closest = fStyles[i];
267 minScore = score;
268 }
269 }
270 return SkRef(closest);
271 }
272
273private:
274 SkFontStyle style(int index) {
bungeman4b86bac2014-11-04 10:54:31 -0800275 return fStyles[index]->fontStyle();
bungeman8d84c992014-07-24 08:05:09 -0700276 }
277 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) {
278 int score = 0;
bungemanf20488b2015-07-29 11:49:40 -0700279 score += SkTAbs((pattern.width() - candidate.width()) * 100);
280 score += SkTAbs((pattern.isItalic() == candidate.isItalic()) ? 0 : 1000);
281 score += SkTAbs(pattern.weight() - candidate.weight());
bungeman8d84c992014-07-24 08:05:09 -0700282 return score;
283 }
284
bungeman65fcd3d2014-08-06 11:12:20 -0700285 SkTArray<SkAutoTUnref<SkTypeface_AndroidSystem>, true> fStyles;
bungeman8d84c992014-07-24 08:05:09 -0700286
287 friend struct NameToFamily;
288 friend class SkFontMgr_Android;
289
290 typedef SkFontStyleSet INHERITED;
291};
292
293/** On Android a single family can have many names, but our API assumes unique names.
294 * Map names to the back end so that all names for a given family refer to the same
295 * (non-replicated) set of typefaces.
296 * SkTDict<> doesn't let us do index-based lookup, so we write our own mapping.
297 */
298struct NameToFamily {
299 SkString name;
300 SkFontStyleSet_Android* styleSet;
301};
302
303class SkFontMgr_Android : public SkFontMgr {
304public:
bungeman7fa87cd2015-02-06 07:59:19 -0800305 SkFontMgr_Android(const SkFontMgr_Android_CustomFonts* custom) {
306 SkTDArray<FontFamily*> families;
307 if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem != custom->fSystemFontUse) {
308 SkString base(custom->fBasePath);
bungemanc5308542015-06-23 13:25:46 -0700309 SkFontMgr_Android_Parser::GetCustomFontFamilies(
310 families, base, custom->fFontsXml, custom->fFallbackFontsXml);
bungeman7fa87cd2015-02-06 07:59:19 -0800311 }
312 if (!custom ||
313 (custom && SkFontMgr_Android_CustomFonts::kOnlyCustom != custom->fSystemFontUse))
314 {
bungemanc5308542015-06-23 13:25:46 -0700315 SkFontMgr_Android_Parser::GetSystemFontFamilies(families);
bungeman7fa87cd2015-02-06 07:59:19 -0800316 }
317 if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem == custom->fSystemFontUse) {
318 SkString base(custom->fBasePath);
bungemanc5308542015-06-23 13:25:46 -0700319 SkFontMgr_Android_Parser::GetCustomFontFamilies(
320 families, base, custom->fFontsXml, custom->fFallbackFontsXml);
bungeman7fa87cd2015-02-06 07:59:19 -0800321 }
322 this->buildNameToFamilyMap(families);
bungeman4e3523c2014-08-08 12:06:51 -0700323 this->findDefaultFont();
bungeman7fa87cd2015-02-06 07:59:19 -0800324 families.deleteAll();
bungeman8d84c992014-07-24 08:05:09 -0700325 }
326
327protected:
328 /** Returns not how many families we have, but how many unique names
329 * exist among the families.
330 */
mtklein36352bf2015-03-25 18:17:31 -0700331 int onCountFamilies() const override {
bungeman8d84c992014-07-24 08:05:09 -0700332 return fNameToFamilyMap.count();
333 }
334
mtklein36352bf2015-03-25 18:17:31 -0700335 void onGetFamilyName(int index, SkString* familyName) const override {
bungeman8d84c992014-07-24 08:05:09 -0700336 if (index < 0 || fNameToFamilyMap.count() <= index) {
337 familyName->reset();
338 return;
339 }
340 familyName->set(fNameToFamilyMap[index].name);
341 }
342
mtklein36352bf2015-03-25 18:17:31 -0700343 SkFontStyleSet* onCreateStyleSet(int index) const override {
bungeman8d84c992014-07-24 08:05:09 -0700344 if (index < 0 || fNameToFamilyMap.count() <= index) {
345 return NULL;
346 }
347 return SkRef(fNameToFamilyMap[index].styleSet);
348 }
349
mtklein36352bf2015-03-25 18:17:31 -0700350 SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
bungeman8d84c992014-07-24 08:05:09 -0700351 if (!familyName) {
352 return NULL;
353 }
354 SkAutoAsciiToLC tolc(familyName);
355 for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
356 if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
357 return SkRef(fNameToFamilyMap[i].styleSet);
358 }
359 }
bungeman65fcd3d2014-08-06 11:12:20 -0700360 // TODO: eventually we should not need to name fallback families.
361 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
362 if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) {
363 return SkRef(fFallbackNameToFamilyMap[i].styleSet);
364 }
365 }
bungeman8d84c992014-07-24 08:05:09 -0700366 return NULL;
367 }
368
369 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
mtklein36352bf2015-03-25 18:17:31 -0700370 const SkFontStyle& style) const override {
bungeman8d84c992014-07-24 08:05:09 -0700371 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
372 return sset->matchStyle(style);
373 }
374
375 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
mtklein36352bf2015-03-25 18:17:31 -0700376 const SkFontStyle& style) const override {
bungeman8d84c992014-07-24 08:05:09 -0700377 for (int i = 0; i < fFontStyleSets.count(); ++i) {
378 for (int j = 0; j < fFontStyleSets[i]->fStyles.count(); ++j) {
379 if (fFontStyleSets[i]->fStyles[j] == typeface) {
380 return fFontStyleSets[i]->matchStyle(style);
381 }
382 }
383 }
384 return NULL;
385 }
386
bungemanc9232dc2014-11-10 13:29:33 -0800387 static SkTypeface_AndroidSystem* find_family_style_character(
388 const SkTDArray<NameToFamily>& fallbackNameToFamilyMap,
389 const SkFontStyle& style, bool elegant,
390 const SkString& langTag, SkUnichar character)
391 {
392 for (int i = 0; i < fallbackNameToFamilyMap.count(); ++i) {
393 SkFontStyleSet_Android* family = fallbackNameToFamilyMap[i].styleSet;
394 SkAutoTUnref<SkTypeface_AndroidSystem> face(family->matchStyle(style));
bungemanc20386e2014-10-23 07:08:05 -0700395
bungemanc9232dc2014-11-10 13:29:33 -0800396 if (!langTag.isEmpty() && !face->fLang.getTag().startsWith(langTag.c_str())) {
397 continue;
398 }
399
400 if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) {
401 continue;
402 }
403
bungeman24a104d2015-07-30 10:31:57 -0700404 SkPaint paint;
405 paint.setTypeface(face);
406 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
407
408 uint16_t glyphID;
409 paint.textToGlyphs(&character, sizeof(character), &glyphID);
410 if (glyphID != 0) {
bungemanc9232dc2014-11-10 13:29:33 -0800411 return face.detach();
412 }
bungemanc20386e2014-10-23 07:08:05 -0700413 }
bungemanc9232dc2014-11-10 13:29:33 -0800414 return NULL;
bungemanc20386e2014-10-23 07:08:05 -0700415 }
bungemanc9232dc2014-11-10 13:29:33 -0800416
bungeman65fcd3d2014-08-06 11:12:20 -0700417 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
418 const SkFontStyle& style,
bungemanc20386e2014-10-23 07:08:05 -0700419 const char* bcp47[],
420 int bcp47Count,
mtklein36352bf2015-03-25 18:17:31 -0700421 SkUnichar character) const override
bungeman65fcd3d2014-08-06 11:12:20 -0700422 {
423 // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascent/descent'.
424 // The variant 'default' means 'compact and elegant'.
425 // As a result, it is not possible to know the variant context from the font alone.
426 // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request.
427
bungemanc20386e2014-10-23 07:08:05 -0700428 // The first time match anything elegant, second time anything not elegant.
429 for (int elegant = 2; elegant --> 0;) {
430 for (int bcp47Index = bcp47Count; bcp47Index --> 0;) {
431 SkLanguage lang(bcp47[bcp47Index]);
432 while (!lang.getTag().isEmpty()) {
433 SkTypeface_AndroidSystem* matchingTypeface =
434 find_family_style_character(fFallbackNameToFamilyMap,
435 style, SkToBool(elegant),
436 lang.getTag(), character);
437 if (matchingTypeface) {
438 return matchingTypeface;
bungeman65fcd3d2014-08-06 11:12:20 -0700439 }
440
bungemanc20386e2014-10-23 07:08:05 -0700441 lang = lang.getParent();
bungeman65fcd3d2014-08-06 11:12:20 -0700442 }
bungemanc20386e2014-10-23 07:08:05 -0700443 }
444 SkTypeface_AndroidSystem* matchingTypeface =
445 find_family_style_character(fFallbackNameToFamilyMap,
446 style, SkToBool(elegant),
447 SkString(), character);
448 if (matchingTypeface) {
449 return matchingTypeface;
450 }
bungeman65fcd3d2014-08-06 11:12:20 -0700451 }
452 return NULL;
453 }
454
mtklein36352bf2015-03-25 18:17:31 -0700455 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
scroggoa1193e42015-01-21 12:09:53 -0800456 return this->createFromStream(new SkMemoryStream(data), ttcIndex);
bungeman8d84c992014-07-24 08:05:09 -0700457 }
458
mtklein36352bf2015-03-25 18:17:31 -0700459 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
bungeman5f213d92015-01-27 05:39:10 -0800460 SkAutoTDelete<SkStreamAsset> stream(SkStream::NewFromFile(path));
scroggoa1193e42015-01-21 12:09:53 -0800461 return stream.get() ? this->createFromStream(stream.detach(), ttcIndex) : NULL;
bungeman8d84c992014-07-24 08:05:09 -0700462 }
463
mtklein36352bf2015-03-25 18:17:31 -0700464 SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override {
bungeman5f213d92015-01-27 05:39:10 -0800465 SkAutoTDelete<SkStreamAsset> stream(bareStream);
bungeman8d84c992014-07-24 08:05:09 -0700466 bool isFixedPitch;
bungemana4c4a2d2014-10-20 13:33:19 -0700467 SkFontStyle style;
bungeman8d84c992014-07-24 08:05:09 -0700468 SkString name;
bungeman41868fe2015-05-20 09:21:04 -0700469 if (!fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch, NULL)) {
bungeman8d84c992014-07-24 08:05:09 -0700470 return NULL;
471 }
bungeman41868fe2015-05-20 09:21:04 -0700472 SkFontData* data(new SkFontData(stream.detach(), ttcIndex, NULL, 0));
halcanary385fe4d2015-08-26 13:07:48 -0700473 return new SkTypeface_AndroidStream(data, style, isFixedPitch, name);
bungeman41868fe2015-05-20 09:21:04 -0700474 }
475
476 SkTypeface* onCreateFromFontData(SkFontData* data) const override {
477 SkStreamAsset* stream(data->getStream());
478 bool isFixedPitch;
479 SkFontStyle style;
480 SkString name;
481 if (!fScanner.scanFont(stream, data->getIndex(), &name, &style, &isFixedPitch, NULL)) {
482 return NULL;
483 }
halcanary385fe4d2015-08-26 13:07:48 -0700484 return new SkTypeface_AndroidStream(data, style, isFixedPitch, name);
bungeman8d84c992014-07-24 08:05:09 -0700485 }
486
487
488 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
mtklein36352bf2015-03-25 18:17:31 -0700489 unsigned styleBits) const override {
bungemana4c4a2d2014-10-20 13:33:19 -0700490 SkFontStyle style = SkFontStyle(styleBits);
bungeman8d84c992014-07-24 08:05:09 -0700491
bsalomon49f085d2014-09-05 13:34:00 -0700492 if (familyName) {
bungeman8d84c992014-07-24 08:05:09 -0700493 // On Android, we must return NULL when we can't find the requested
494 // named typeface so that the system/app can provide their own recovery
495 // mechanism. On other platforms we'd provide a typeface from the
496 // default family instead.
bungeman07cfb202014-07-30 11:05:22 -0700497 return this->onMatchFamilyStyle(familyName, style);
bungeman8d84c992014-07-24 08:05:09 -0700498 }
bungeman07cfb202014-07-30 11:05:22 -0700499 return fDefaultFamily->matchStyle(style);
bungeman8d84c992014-07-24 08:05:09 -0700500 }
501
502
503private:
504
bungeman14df8332014-10-28 15:07:23 -0700505 SkTypeface_FreeType::Scanner fScanner;
506
bungeman8d84c992014-07-24 08:05:09 -0700507 SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets;
508 SkFontStyleSet* fDefaultFamily;
509 SkTypeface* fDefaultTypeface;
510
511 SkTDArray<NameToFamily> fNameToFamilyMap;
bungeman65fcd3d2014-08-06 11:12:20 -0700512 SkTDArray<NameToFamily> fFallbackNameToFamilyMap;
bungeman8d84c992014-07-24 08:05:09 -0700513
bungeman7fa87cd2015-02-06 07:59:19 -0800514 void buildNameToFamilyMap(SkTDArray<FontFamily*> families) {
bungeman8d84c992014-07-24 08:05:09 -0700515 for (int i = 0; i < families.count(); i++) {
bungeman65fcd3d2014-08-06 11:12:20 -0700516 FontFamily& family = *families[i];
517
518 SkTDArray<NameToFamily>* nameToFamily = &fNameToFamilyMap;
519 if (family.fIsFallbackFont) {
520 nameToFamily = &fFallbackNameToFamilyMap;
521
522 if (0 == family.fNames.count()) {
523 SkString& fallbackName = family.fNames.push_back();
524 fallbackName.printf("%.2x##fallback", i);
525 }
526 }
527
halcanary385fe4d2015-08-26 13:07:48 -0700528 SkFontStyleSet_Android* newSet = new SkFontStyleSet_Android(family, fScanner);
bungeman65fcd3d2014-08-06 11:12:20 -0700529 if (0 == newSet->count()) {
halcanary385fe4d2015-08-26 13:07:48 -0700530 delete newSet;
bungeman65fcd3d2014-08-06 11:12:20 -0700531 continue;
532 }
533 fFontStyleSets.push_back().reset(newSet);
534
535 for (int j = 0; j < family.fNames.count(); j++) {
536 NameToFamily* nextEntry = nameToFamily->append();
halcanary385fe4d2015-08-26 13:07:48 -0700537 new (&nextEntry->name) SkString(family.fNames[j]);
bungeman65fcd3d2014-08-06 11:12:20 -0700538 nextEntry->styleSet = newSet;
bungeman8d84c992014-07-24 08:05:09 -0700539 }
540 }
541 }
542
543 void findDefaultFont() {
544 SkASSERT(!fFontStyleSets.empty());
545
546 static const char* gDefaultNames[] = { "sans-serif" };
547 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
548 SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]);
549 if (NULL == set) {
550 continue;
551 }
552 SkTypeface* tf = set->matchStyle(SkFontStyle());
553 if (NULL == tf) {
554 continue;
555 }
556 fDefaultFamily = set;
557 fDefaultTypeface = tf;
558 break;
559 }
560 if (NULL == fDefaultTypeface) {
561 fDefaultFamily = fFontStyleSets[0];
562 fDefaultTypeface = fDefaultFamily->createTypeface(0);
563 }
564 SkASSERT(fDefaultFamily);
565 SkASSERT(fDefaultTypeface);
566 }
567
568 typedef SkFontMgr INHERITED;
569};
570
bungeman7fa87cd2015-02-06 07:59:19 -0800571#ifdef SK_DEBUG
572static char const * const gSystemFontUseStrings[] = {
573 "OnlyCustom", "PreferCustom", "PreferSystem"
574};
575#endif
576SkFontMgr* SkFontMgr_New_Android(const SkFontMgr_Android_CustomFonts* custom) {
577 if (custom) {
578 SkASSERT(0 <= custom->fSystemFontUse);
579 SkASSERT(custom->fSystemFontUse < SK_ARRAY_COUNT(gSystemFontUseStrings));
580 SkDEBUGF(("SystemFontUse: %s BasePath: %s Fonts: %s FallbackFonts: %s\n",
581 gSystemFontUseStrings[custom->fSystemFontUse],
582 custom->fBasePath,
583 custom->fFontsXml,
584 custom->fFallbackFontsXml));
bungeman4e3523c2014-08-08 12:06:51 -0700585 }
586
halcanary385fe4d2015-08-26 13:07:48 -0700587 return new SkFontMgr_Android(custom);
bungeman8d84c992014-07-24 08:05:09 -0700588}