blob: 45c787a930220974d885f7c36908c04849121c4f [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
207 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 }
217 }
218 if (!found) {
219 SkDEBUGF(("Requested font axis not found: %s '%c%c%c%c'\n",
220 familyName.c_str(),
221 (skTag >> 24) & 0xFF,
222 (skTag >> 16) & 0xFF,
223 (skTag >> 8) & 0xFF,
224 (skTag ) & 0xFF));
225 }
226 }
227 )
228
bungeman8d84c992014-07-24 08:05:09 -0700229 fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem,
bungeman07cfb202014-07-30 11:05:22 -0700230 (pathName, ttcIndex,
bungeman41868fe2015-05-20 09:21:04 -0700231 axisValues.get(), axisDefinitions.count(),
bungeman65fcd3d2014-08-06 11:12:20 -0700232 style, isFixedWidth, familyName,
233 lang, variant)));
bungeman8d84c992014-07-24 08:05:09 -0700234 }
235 }
236
mtklein36352bf2015-03-25 18:17:31 -0700237 int count() override {
bungeman8d84c992014-07-24 08:05:09 -0700238 return fStyles.count();
239 }
mtklein36352bf2015-03-25 18:17:31 -0700240 void getStyle(int index, SkFontStyle* style, SkString* name) override {
bungeman8d84c992014-07-24 08:05:09 -0700241 if (index < 0 || fStyles.count() <= index) {
242 return;
243 }
244 if (style) {
245 *style = this->style(index);
246 }
247 if (name) {
248 name->reset();
249 }
250 }
mtklein36352bf2015-03-25 18:17:31 -0700251 SkTypeface_AndroidSystem* createTypeface(int index) override {
bungeman8d84c992014-07-24 08:05:09 -0700252 if (index < 0 || fStyles.count() <= index) {
253 return NULL;
254 }
255 return SkRef(fStyles[index].get());
256 }
257
258 /** Find the typeface in this style set that most closely matches the given pattern.
259 * TODO: consider replacing with SkStyleSet_Indirect::matchStyle();
260 * this simpler version using match_score() passes all our tests.
261 */
mtklein36352bf2015-03-25 18:17:31 -0700262 SkTypeface_AndroidSystem* matchStyle(const SkFontStyle& pattern) override {
bungeman8d84c992014-07-24 08:05:09 -0700263 if (0 == fStyles.count()) {
264 return NULL;
265 }
bungeman65fcd3d2014-08-06 11:12:20 -0700266 SkTypeface_AndroidSystem* closest = fStyles[0];
bungeman8d84c992014-07-24 08:05:09 -0700267 int minScore = std::numeric_limits<int>::max();
268 for (int i = 0; i < fStyles.count(); ++i) {
269 SkFontStyle style = this->style(i);
270 int score = match_score(pattern, style);
271 if (score < minScore) {
272 closest = fStyles[i];
273 minScore = score;
274 }
275 }
276 return SkRef(closest);
277 }
278
279private:
280 SkFontStyle style(int index) {
bungeman4b86bac2014-11-04 10:54:31 -0800281 return fStyles[index]->fontStyle();
bungeman8d84c992014-07-24 08:05:09 -0700282 }
283 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) {
284 int score = 0;
bungemanf20488b2015-07-29 11:49:40 -0700285 score += SkTAbs((pattern.width() - candidate.width()) * 100);
286 score += SkTAbs((pattern.isItalic() == candidate.isItalic()) ? 0 : 1000);
287 score += SkTAbs(pattern.weight() - candidate.weight());
bungeman8d84c992014-07-24 08:05:09 -0700288 return score;
289 }
290
bungeman65fcd3d2014-08-06 11:12:20 -0700291 SkTArray<SkAutoTUnref<SkTypeface_AndroidSystem>, true> fStyles;
bungeman8d84c992014-07-24 08:05:09 -0700292
293 friend struct NameToFamily;
294 friend class SkFontMgr_Android;
295
296 typedef SkFontStyleSet INHERITED;
297};
298
299/** On Android a single family can have many names, but our API assumes unique names.
300 * Map names to the back end so that all names for a given family refer to the same
301 * (non-replicated) set of typefaces.
302 * SkTDict<> doesn't let us do index-based lookup, so we write our own mapping.
303 */
304struct NameToFamily {
305 SkString name;
306 SkFontStyleSet_Android* styleSet;
307};
308
309class SkFontMgr_Android : public SkFontMgr {
310public:
bungeman7fa87cd2015-02-06 07:59:19 -0800311 SkFontMgr_Android(const SkFontMgr_Android_CustomFonts* custom) {
312 SkTDArray<FontFamily*> families;
313 if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem != custom->fSystemFontUse) {
314 SkString base(custom->fBasePath);
bungemanc5308542015-06-23 13:25:46 -0700315 SkFontMgr_Android_Parser::GetCustomFontFamilies(
316 families, base, custom->fFontsXml, custom->fFallbackFontsXml);
bungeman7fa87cd2015-02-06 07:59:19 -0800317 }
318 if (!custom ||
319 (custom && SkFontMgr_Android_CustomFonts::kOnlyCustom != custom->fSystemFontUse))
320 {
bungemanc5308542015-06-23 13:25:46 -0700321 SkFontMgr_Android_Parser::GetSystemFontFamilies(families);
bungeman7fa87cd2015-02-06 07:59:19 -0800322 }
323 if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem == custom->fSystemFontUse) {
324 SkString base(custom->fBasePath);
bungemanc5308542015-06-23 13:25:46 -0700325 SkFontMgr_Android_Parser::GetCustomFontFamilies(
326 families, base, custom->fFontsXml, custom->fFallbackFontsXml);
bungeman7fa87cd2015-02-06 07:59:19 -0800327 }
328 this->buildNameToFamilyMap(families);
bungeman4e3523c2014-08-08 12:06:51 -0700329 this->findDefaultFont();
bungeman7fa87cd2015-02-06 07:59:19 -0800330 families.deleteAll();
bungeman8d84c992014-07-24 08:05:09 -0700331 }
332
333protected:
334 /** Returns not how many families we have, but how many unique names
335 * exist among the families.
336 */
mtklein36352bf2015-03-25 18:17:31 -0700337 int onCountFamilies() const override {
bungeman8d84c992014-07-24 08:05:09 -0700338 return fNameToFamilyMap.count();
339 }
340
mtklein36352bf2015-03-25 18:17:31 -0700341 void onGetFamilyName(int index, SkString* familyName) const override {
bungeman8d84c992014-07-24 08:05:09 -0700342 if (index < 0 || fNameToFamilyMap.count() <= index) {
343 familyName->reset();
344 return;
345 }
346 familyName->set(fNameToFamilyMap[index].name);
347 }
348
mtklein36352bf2015-03-25 18:17:31 -0700349 SkFontStyleSet* onCreateStyleSet(int index) const override {
bungeman8d84c992014-07-24 08:05:09 -0700350 if (index < 0 || fNameToFamilyMap.count() <= index) {
351 return NULL;
352 }
353 return SkRef(fNameToFamilyMap[index].styleSet);
354 }
355
mtklein36352bf2015-03-25 18:17:31 -0700356 SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
bungeman8d84c992014-07-24 08:05:09 -0700357 if (!familyName) {
358 return NULL;
359 }
360 SkAutoAsciiToLC tolc(familyName);
361 for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
362 if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
363 return SkRef(fNameToFamilyMap[i].styleSet);
364 }
365 }
bungeman65fcd3d2014-08-06 11:12:20 -0700366 // TODO: eventually we should not need to name fallback families.
367 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
368 if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) {
369 return SkRef(fFallbackNameToFamilyMap[i].styleSet);
370 }
371 }
bungeman8d84c992014-07-24 08:05:09 -0700372 return NULL;
373 }
374
375 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
mtklein36352bf2015-03-25 18:17:31 -0700376 const SkFontStyle& style) const override {
bungeman8d84c992014-07-24 08:05:09 -0700377 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
378 return sset->matchStyle(style);
379 }
380
381 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
mtklein36352bf2015-03-25 18:17:31 -0700382 const SkFontStyle& style) const override {
bungeman8d84c992014-07-24 08:05:09 -0700383 for (int i = 0; i < fFontStyleSets.count(); ++i) {
384 for (int j = 0; j < fFontStyleSets[i]->fStyles.count(); ++j) {
385 if (fFontStyleSets[i]->fStyles[j] == typeface) {
386 return fFontStyleSets[i]->matchStyle(style);
387 }
388 }
389 }
390 return NULL;
391 }
392
bungemanc9232dc2014-11-10 13:29:33 -0800393 static SkTypeface_AndroidSystem* find_family_style_character(
394 const SkTDArray<NameToFamily>& fallbackNameToFamilyMap,
395 const SkFontStyle& style, bool elegant,
396 const SkString& langTag, SkUnichar character)
397 {
398 for (int i = 0; i < fallbackNameToFamilyMap.count(); ++i) {
399 SkFontStyleSet_Android* family = fallbackNameToFamilyMap[i].styleSet;
400 SkAutoTUnref<SkTypeface_AndroidSystem> face(family->matchStyle(style));
bungemanc20386e2014-10-23 07:08:05 -0700401
bungemanc9232dc2014-11-10 13:29:33 -0800402 if (!langTag.isEmpty() && !face->fLang.getTag().startsWith(langTag.c_str())) {
403 continue;
404 }
405
406 if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) {
407 continue;
408 }
409
bungeman24a104d2015-07-30 10:31:57 -0700410 SkPaint paint;
411 paint.setTypeface(face);
412 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
413
414 uint16_t glyphID;
415 paint.textToGlyphs(&character, sizeof(character), &glyphID);
416 if (glyphID != 0) {
bungemanc9232dc2014-11-10 13:29:33 -0800417 return face.detach();
418 }
bungemanc20386e2014-10-23 07:08:05 -0700419 }
bungemanc9232dc2014-11-10 13:29:33 -0800420 return NULL;
bungemanc20386e2014-10-23 07:08:05 -0700421 }
bungemanc9232dc2014-11-10 13:29:33 -0800422
bungeman65fcd3d2014-08-06 11:12:20 -0700423 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
424 const SkFontStyle& style,
bungemanc20386e2014-10-23 07:08:05 -0700425 const char* bcp47[],
426 int bcp47Count,
mtklein36352bf2015-03-25 18:17:31 -0700427 SkUnichar character) const override
bungeman65fcd3d2014-08-06 11:12:20 -0700428 {
429 // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascent/descent'.
430 // The variant 'default' means 'compact and elegant'.
431 // As a result, it is not possible to know the variant context from the font alone.
432 // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request.
433
bungemanc20386e2014-10-23 07:08:05 -0700434 // The first time match anything elegant, second time anything not elegant.
435 for (int elegant = 2; elegant --> 0;) {
436 for (int bcp47Index = bcp47Count; bcp47Index --> 0;) {
437 SkLanguage lang(bcp47[bcp47Index]);
438 while (!lang.getTag().isEmpty()) {
439 SkTypeface_AndroidSystem* matchingTypeface =
440 find_family_style_character(fFallbackNameToFamilyMap,
441 style, SkToBool(elegant),
442 lang.getTag(), character);
443 if (matchingTypeface) {
444 return matchingTypeface;
bungeman65fcd3d2014-08-06 11:12:20 -0700445 }
446
bungemanc20386e2014-10-23 07:08:05 -0700447 lang = lang.getParent();
bungeman65fcd3d2014-08-06 11:12:20 -0700448 }
bungemanc20386e2014-10-23 07:08:05 -0700449 }
450 SkTypeface_AndroidSystem* matchingTypeface =
451 find_family_style_character(fFallbackNameToFamilyMap,
452 style, SkToBool(elegant),
453 SkString(), character);
454 if (matchingTypeface) {
455 return matchingTypeface;
456 }
bungeman65fcd3d2014-08-06 11:12:20 -0700457 }
458 return NULL;
459 }
460
mtklein36352bf2015-03-25 18:17:31 -0700461 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
scroggoa1193e42015-01-21 12:09:53 -0800462 return this->createFromStream(new SkMemoryStream(data), ttcIndex);
bungeman8d84c992014-07-24 08:05:09 -0700463 }
464
mtklein36352bf2015-03-25 18:17:31 -0700465 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
bungeman5f213d92015-01-27 05:39:10 -0800466 SkAutoTDelete<SkStreamAsset> stream(SkStream::NewFromFile(path));
scroggoa1193e42015-01-21 12:09:53 -0800467 return stream.get() ? this->createFromStream(stream.detach(), ttcIndex) : NULL;
bungeman8d84c992014-07-24 08:05:09 -0700468 }
469
mtklein36352bf2015-03-25 18:17:31 -0700470 SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override {
bungeman5f213d92015-01-27 05:39:10 -0800471 SkAutoTDelete<SkStreamAsset> stream(bareStream);
bungeman8d84c992014-07-24 08:05:09 -0700472 bool isFixedPitch;
bungemana4c4a2d2014-10-20 13:33:19 -0700473 SkFontStyle style;
bungeman8d84c992014-07-24 08:05:09 -0700474 SkString name;
bungeman41868fe2015-05-20 09:21:04 -0700475 if (!fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch, NULL)) {
bungeman8d84c992014-07-24 08:05:09 -0700476 return NULL;
477 }
bungeman41868fe2015-05-20 09:21:04 -0700478 SkFontData* data(new SkFontData(stream.detach(), ttcIndex, NULL, 0));
479 return SkNEW_ARGS(SkTypeface_AndroidStream, (data, style, isFixedPitch, name));
480 }
481
482 SkTypeface* onCreateFromFontData(SkFontData* data) const override {
483 SkStreamAsset* stream(data->getStream());
484 bool isFixedPitch;
485 SkFontStyle style;
486 SkString name;
487 if (!fScanner.scanFont(stream, data->getIndex(), &name, &style, &isFixedPitch, NULL)) {
488 return NULL;
489 }
490 return SkNEW_ARGS(SkTypeface_AndroidStream, (data, style, isFixedPitch, name));
bungeman8d84c992014-07-24 08:05:09 -0700491 }
492
493
494 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
mtklein36352bf2015-03-25 18:17:31 -0700495 unsigned styleBits) const override {
bungemana4c4a2d2014-10-20 13:33:19 -0700496 SkFontStyle style = SkFontStyle(styleBits);
bungeman8d84c992014-07-24 08:05:09 -0700497
bsalomon49f085d2014-09-05 13:34:00 -0700498 if (familyName) {
bungeman8d84c992014-07-24 08:05:09 -0700499 // On Android, we must return NULL when we can't find the requested
500 // named typeface so that the system/app can provide their own recovery
501 // mechanism. On other platforms we'd provide a typeface from the
502 // default family instead.
bungeman07cfb202014-07-30 11:05:22 -0700503 return this->onMatchFamilyStyle(familyName, style);
bungeman8d84c992014-07-24 08:05:09 -0700504 }
bungeman07cfb202014-07-30 11:05:22 -0700505 return fDefaultFamily->matchStyle(style);
bungeman8d84c992014-07-24 08:05:09 -0700506 }
507
508
509private:
510
bungeman14df8332014-10-28 15:07:23 -0700511 SkTypeface_FreeType::Scanner fScanner;
512
bungeman8d84c992014-07-24 08:05:09 -0700513 SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets;
514 SkFontStyleSet* fDefaultFamily;
515 SkTypeface* fDefaultTypeface;
516
517 SkTDArray<NameToFamily> fNameToFamilyMap;
bungeman65fcd3d2014-08-06 11:12:20 -0700518 SkTDArray<NameToFamily> fFallbackNameToFamilyMap;
bungeman8d84c992014-07-24 08:05:09 -0700519
bungeman7fa87cd2015-02-06 07:59:19 -0800520 void buildNameToFamilyMap(SkTDArray<FontFamily*> families) {
bungeman8d84c992014-07-24 08:05:09 -0700521 for (int i = 0; i < families.count(); i++) {
bungeman65fcd3d2014-08-06 11:12:20 -0700522 FontFamily& family = *families[i];
523
524 SkTDArray<NameToFamily>* nameToFamily = &fNameToFamilyMap;
525 if (family.fIsFallbackFont) {
526 nameToFamily = &fFallbackNameToFamilyMap;
527
528 if (0 == family.fNames.count()) {
529 SkString& fallbackName = family.fNames.push_back();
530 fallbackName.printf("%.2x##fallback", i);
531 }
532 }
533
bungeman14df8332014-10-28 15:07:23 -0700534 SkFontStyleSet_Android* newSet =
bungeman7fa87cd2015-02-06 07:59:19 -0800535 SkNEW_ARGS(SkFontStyleSet_Android, (family, fScanner));
bungeman65fcd3d2014-08-06 11:12:20 -0700536 if (0 == newSet->count()) {
537 SkDELETE(newSet);
538 continue;
539 }
540 fFontStyleSets.push_back().reset(newSet);
541
542 for (int j = 0; j < family.fNames.count(); j++) {
543 NameToFamily* nextEntry = nameToFamily->append();
544 SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (family.fNames[j]));
545 nextEntry->styleSet = newSet;
bungeman8d84c992014-07-24 08:05:09 -0700546 }
547 }
548 }
549
550 void findDefaultFont() {
551 SkASSERT(!fFontStyleSets.empty());
552
553 static const char* gDefaultNames[] = { "sans-serif" };
554 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
555 SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]);
556 if (NULL == set) {
557 continue;
558 }
559 SkTypeface* tf = set->matchStyle(SkFontStyle());
560 if (NULL == tf) {
561 continue;
562 }
563 fDefaultFamily = set;
564 fDefaultTypeface = tf;
565 break;
566 }
567 if (NULL == fDefaultTypeface) {
568 fDefaultFamily = fFontStyleSets[0];
569 fDefaultTypeface = fDefaultFamily->createTypeface(0);
570 }
571 SkASSERT(fDefaultFamily);
572 SkASSERT(fDefaultTypeface);
573 }
574
575 typedef SkFontMgr INHERITED;
576};
577
bungeman7fa87cd2015-02-06 07:59:19 -0800578#ifdef SK_DEBUG
579static char const * const gSystemFontUseStrings[] = {
580 "OnlyCustom", "PreferCustom", "PreferSystem"
581};
582#endif
583SkFontMgr* SkFontMgr_New_Android(const SkFontMgr_Android_CustomFonts* custom) {
584 if (custom) {
585 SkASSERT(0 <= custom->fSystemFontUse);
586 SkASSERT(custom->fSystemFontUse < SK_ARRAY_COUNT(gSystemFontUseStrings));
587 SkDEBUGF(("SystemFontUse: %s BasePath: %s Fonts: %s FallbackFonts: %s\n",
588 gSystemFontUseStrings[custom->fSystemFontUse],
589 custom->fBasePath,
590 custom->fFontsXml,
591 custom->fFallbackFontsXml));
bungeman4e3523c2014-08-08 12:06:51 -0700592 }
593
bungeman7fa87cd2015-02-06 07:59:19 -0800594 return SkNEW_ARGS(SkFontMgr_Android, (custom));
bungeman8d84c992014-07-24 08:05:09 -0700595}