blob: a67c6814eaa0b56b1bff8385548786ecae3bc1b5 [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
8#include "SkFontConfigParser_android.h"
9#include "SkFontDescriptor.h"
10#include "SkFontHost_FreeType_common.h"
11#include "SkFontMgr.h"
bungeman7fa87cd2015-02-06 07:59:19 -080012#include "SkFontMgr_android.h"
bungeman8d84c992014-07-24 08:05:09 -070013#include "SkFontStyle.h"
14#include "SkStream.h"
15#include "SkTDArray.h"
16#include "SkTSearch.h"
17#include "SkTypeface.h"
bungeman4e3523c2014-08-08 12:06:51 -070018#include "SkTypeface_android.h"
bungeman8d84c992014-07-24 08:05:09 -070019#include "SkTypefaceCache.h"
20
21#include <limits>
bungeman8d84c992014-07-24 08:05:09 -070022
tomhudsonc7733902014-08-13 10:41:25 -070023// For test only.
bungeman7fa87cd2015-02-06 07:59:19 -080024static const char* gTestFontsXml = NULL;
25static const char* gTestFallbackFontsXml = NULL;
26static const char* gTestBasePath = NULL;
tomhudsonc7733902014-08-13 10:41:25 -070027
bungeman8d84c992014-07-24 08:05:09 -070028class SkTypeface_Android : public SkTypeface_FreeType {
29public:
bungeman05773ed2015-05-13 10:57:09 -070030 SkTypeface_Android(const SkFontStyle& style,
bungeman8d84c992014-07-24 08:05:09 -070031 bool isFixedPitch,
bungeman4b86bac2014-11-04 10:54:31 -080032 const SkString& familyName)
bungeman8d84c992014-07-24 08:05:09 -070033 : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch)
bungeman05773ed2015-05-13 10:57:09 -070034 , fFamilyName(familyName)
35 { }
bungeman8d84c992014-07-24 08:05:09 -070036
bungeman8d84c992014-07-24 08:05:09 -070037protected:
mtklein36352bf2015-03-25 18:17:31 -070038 void onGetFamilyName(SkString* familyName) const override {
bungemanb374d6a2014-09-17 07:48:59 -070039 *familyName = fFamilyName;
40 }
41
bungeman8d84c992014-07-24 08:05:09 -070042 SkString fFamilyName;
43
44private:
45 typedef SkTypeface_FreeType INHERITED;
46};
47
48class SkTypeface_AndroidSystem : public SkTypeface_Android {
49public:
bungeman4b86bac2014-11-04 10:54:31 -080050 SkTypeface_AndroidSystem(const SkString& pathName,
bungeman8d84c992014-07-24 08:05:09 -070051 int index,
bungeman05773ed2015-05-13 10:57:09 -070052 const SkFixed* axes, int axesCount,
bungemana4c4a2d2014-10-20 13:33:19 -070053 const SkFontStyle& style,
bungeman8d84c992014-07-24 08:05:09 -070054 bool isFixedPitch,
bungeman4b86bac2014-11-04 10:54:31 -080055 const SkString& familyName,
bungeman65fcd3d2014-08-06 11:12:20 -070056 const SkLanguage& lang,
djsollen3b625542014-08-14 06:29:02 -070057 FontVariant variantStyle)
bungeman05773ed2015-05-13 10:57:09 -070058 : INHERITED(style, isFixedPitch, familyName)
bungeman65fcd3d2014-08-06 11:12:20 -070059 , fPathName(pathName)
bungeman05773ed2015-05-13 10:57:09 -070060 , fIndex(index)
61 , fAxes(axes, axesCount)
bungeman65fcd3d2014-08-06 11:12:20 -070062 , fLang(lang)
63 , fVariantStyle(variantStyle) { }
bungeman8d84c992014-07-24 08:05:09 -070064
bungeman05773ed2015-05-13 10:57:09 -070065 virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
bungeman8d84c992014-07-24 08:05:09 -070066 SkASSERT(desc);
67 SkASSERT(serialize);
68 desc->setFamilyName(fFamilyName.c_str());
bungeman8d84c992014-07-24 08:05:09 -070069 *serialize = false;
70 }
mtklein36352bf2015-03-25 18:17:31 -070071 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
bungeman8d84c992014-07-24 08:05:09 -070072 *ttcIndex = fIndex;
73 return SkStream::NewFromFile(fPathName.c_str());
74 }
bungeman05773ed2015-05-13 10:57:09 -070075 SkFontData* onCreateFontData() const override {
76 return new SkFontData(SkStream::NewFromFile(fPathName.c_str()), fIndex,
77 fAxes.begin(), fAxes.count());
78 }
bungeman8d84c992014-07-24 08:05:09 -070079
bungeman65fcd3d2014-08-06 11:12:20 -070080 const SkString fPathName;
bungeman05773ed2015-05-13 10:57:09 -070081 int fIndex;
82 const SkSTArray<4, SkFixed, true> fAxes;
bungeman65fcd3d2014-08-06 11:12:20 -070083 const SkLanguage fLang;
djsollen3b625542014-08-14 06:29:02 -070084 const FontVariant fVariantStyle;
bungeman8d84c992014-07-24 08:05:09 -070085
86 typedef SkTypeface_Android INHERITED;
87};
88
89class SkTypeface_AndroidStream : public SkTypeface_Android {
90public:
bungeman05773ed2015-05-13 10:57:09 -070091 SkTypeface_AndroidStream(SkFontData* data,
bungemana4c4a2d2014-10-20 13:33:19 -070092 const SkFontStyle& style,
bungeman8d84c992014-07-24 08:05:09 -070093 bool isFixedPitch,
bungeman4b86bac2014-11-04 10:54:31 -080094 const SkString& familyName)
bungeman05773ed2015-05-13 10:57:09 -070095 : INHERITED(style, isFixedPitch, familyName)
96 , fData(data)
97 { }
bungeman8d84c992014-07-24 08:05:09 -070098
99 virtual void onGetFontDescriptor(SkFontDescriptor* desc,
mtklein36352bf2015-03-25 18:17:31 -0700100 bool* serialize) const override {
bungeman8d84c992014-07-24 08:05:09 -0700101 SkASSERT(desc);
102 SkASSERT(serialize);
103 desc->setFamilyName(fFamilyName.c_str());
bungeman8d84c992014-07-24 08:05:09 -0700104 *serialize = true;
105 }
106
mtklein36352bf2015-03-25 18:17:31 -0700107 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
bungeman05773ed2015-05-13 10:57:09 -0700108 *ttcIndex = fData->getIndex();
109 return fData->duplicateStream();
110 }
111
112 SkFontData* onCreateFontData() const override {
113 return new SkFontData(*fData.get());
bungeman8d84c992014-07-24 08:05:09 -0700114 }
115
116private:
bungeman05773ed2015-05-13 10:57:09 -0700117 const SkAutoTDelete<const SkFontData> fData;
bungeman8d84c992014-07-24 08:05:09 -0700118 typedef SkTypeface_Android INHERITED;
119};
120
bungeman8d84c992014-07-24 08:05:09 -0700121class SkFontStyleSet_Android : public SkFontStyleSet {
bungeman05773ed2015-05-13 10:57:09 -0700122 typedef SkTypeface_FreeType::Scanner Scanner;
123
bungeman8d84c992014-07-24 08:05:09 -0700124public:
bungeman05773ed2015-05-13 10:57:09 -0700125 explicit SkFontStyleSet_Android(const FontFamily& family, const Scanner& scanner) {
bungeman65fcd3d2014-08-06 11:12:20 -0700126 const SkString* cannonicalFamilyName = NULL;
127 if (family.fNames.count() > 0) {
128 cannonicalFamilyName = &family.fNames[0];
129 }
bungeman8d84c992014-07-24 08:05:09 -0700130 // TODO? make this lazy
tomhudsond3ddea22014-08-11 11:28:00 -0700131 for (int i = 0; i < family.fFonts.count(); ++i) {
132 const FontFileInfo& fontFile = family.fFonts[i];
bungeman8d84c992014-07-24 08:05:09 -0700133
bungeman7fa87cd2015-02-06 07:59:19 -0800134 SkString pathName(family.fBasePath);
135 pathName.append(fontFile.fFileName);
bungeman8d84c992014-07-24 08:05:09 -0700136
scroggoa1193e42015-01-21 12:09:53 -0800137 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(pathName.c_str()));
bungeman8d84c992014-07-24 08:05:09 -0700138 if (!stream.get()) {
bungeman7fa87cd2015-02-06 07:59:19 -0800139 SkDEBUGF(("Requested font file %s does not exist or cannot be opened.\n",
140 pathName.c_str()));
bungeman8d84c992014-07-24 08:05:09 -0700141 continue;
142 }
143
bungeman65fcd3d2014-08-06 11:12:20 -0700144 const int ttcIndex = fontFile.fIndex;
145 SkString familyName;
bungemana4c4a2d2014-10-20 13:33:19 -0700146 SkFontStyle style;
bungeman8d84c992014-07-24 08:05:09 -0700147 bool isFixedWidth;
bungeman05773ed2015-05-13 10:57:09 -0700148 Scanner::AxisDefinitions axisDefinitions;
149 if (!scanner.scanFont(stream.get(), ttcIndex,
150 &familyName, &style, &isFixedWidth, &axisDefinitions))
151 {
bungeman7fa87cd2015-02-06 07:59:19 -0800152 SkDEBUGF(("Requested font file %s exists, but is not a valid font.\n",
153 pathName.c_str()));
bungeman8d84c992014-07-24 08:05:09 -0700154 continue;
155 }
156
bungemane85a7542015-04-17 13:51:08 -0700157 int weight = fontFile.fWeight != 0 ? fontFile.fWeight : style.weight();
158 SkFontStyle::Slant slant = style.slant();
159 switch (fontFile.fStyle) {
160 case FontFileInfo::Style::kAuto: slant = style.slant(); break;
161 case FontFileInfo::Style::kNormal: slant = SkFontStyle::kUpright_Slant; break;
162 case FontFileInfo::Style::kItalic: slant = SkFontStyle::kItalic_Slant; break;
163 default: SkASSERT(false); break;
bungeman4b86bac2014-11-04 10:54:31 -0800164 }
bungemane85a7542015-04-17 13:51:08 -0700165 style = SkFontStyle(weight, style.width(), slant);
bungeman4b86bac2014-11-04 10:54:31 -0800166
djsollen3b625542014-08-14 06:29:02 -0700167 const SkLanguage& lang = family.fLanguage;
168 uint32_t variant = family.fVariant;
169 if (kDefault_FontVariant == variant) {
170 variant = kCompact_FontVariant | kElegant_FontVariant;
bungeman65fcd3d2014-08-06 11:12:20 -0700171 }
172
173 // The first specified family name overrides the family name found in the font.
174 // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return
175 // all of the specified family names in addition to the names found in the font.
176 if (cannonicalFamilyName != NULL) {
177 familyName = *cannonicalFamilyName;
178 }
179
bungeman05773ed2015-05-13 10:57:09 -0700180 SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
181 for (int i = 0; i < axisDefinitions.count(); ++i) {
182 const Scanner::AxisDefinition& axisDefinition = axisDefinitions[i];
183 axisValues[i] = axisDefinition.fDefault;
184 for (int j = 0; j < fontFile.fAxes.count(); ++j) {
185 const FontFileInfo::Axis& axisSpecified = fontFile.fAxes[j];
186 if (axisDefinition.fTag == axisSpecified.fTag) {
187 axisValues[i] = SkTPin(axisSpecified.fValue, axisDefinition.fMinimum,
188 axisDefinition.fMaximum);
189 if (axisValues[i] != axisSpecified.fValue) {
190 SkDEBUGF(("Requested font axis value out of range: "
191 "%s '%c%c%c%c' %f; pinned to %f.\n",
192 familyName.c_str(),
193 (axisDefinition.fTag >> 24) & 0xFF,
194 (axisDefinition.fTag >> 16) & 0xFF,
195 (axisDefinition.fTag >> 8) & 0xFF,
196 (axisDefinition.fTag ) & 0xFF,
197 SkFixedToDouble(axisSpecified.fValue),
198 SkFixedToDouble(axisValues[i])));
199 }
200 break;
201 }
202 }
203 // TODO: warn on defaulted axis?
204 }
205
206 SkDEBUGCODE (
207 // Check for axis specified, but not matched in font.
208 for (int i = 0; i < fontFile.fAxes.count(); ++i) {
209 SkFourByteTag skTag = fontFile.fAxes[i].fTag;
210 bool found = false;
211 for (int j = 0; j < axisDefinitions.count(); ++j) {
212 if (skTag == axisDefinitions[j].fTag) {
213 found = true;
214 break;
215 }
216 }
217 if (!found) {
218 SkDEBUGF(("Requested font axis not found: %s '%c%c%c%c'\n",
219 familyName.c_str(),
220 (skTag >> 24) & 0xFF,
221 (skTag >> 16) & 0xFF,
222 (skTag >> 8) & 0xFF,
223 (skTag ) & 0xFF));
224 }
225 }
226 )
227
bungeman8d84c992014-07-24 08:05:09 -0700228 fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem,
bungeman07cfb202014-07-30 11:05:22 -0700229 (pathName, ttcIndex,
bungeman05773ed2015-05-13 10:57:09 -0700230 axisValues.get(), axisDefinitions.count(),
bungeman65fcd3d2014-08-06 11:12:20 -0700231 style, isFixedWidth, familyName,
232 lang, variant)));
bungeman8d84c992014-07-24 08:05:09 -0700233 }
234 }
235
mtklein36352bf2015-03-25 18:17:31 -0700236 int count() override {
bungeman8d84c992014-07-24 08:05:09 -0700237 return fStyles.count();
238 }
mtklein36352bf2015-03-25 18:17:31 -0700239 void getStyle(int index, SkFontStyle* style, SkString* name) override {
bungeman8d84c992014-07-24 08:05:09 -0700240 if (index < 0 || fStyles.count() <= index) {
241 return;
242 }
243 if (style) {
244 *style = this->style(index);
245 }
246 if (name) {
247 name->reset();
248 }
249 }
mtklein36352bf2015-03-25 18:17:31 -0700250 SkTypeface_AndroidSystem* createTypeface(int index) override {
bungeman8d84c992014-07-24 08:05:09 -0700251 if (index < 0 || fStyles.count() <= index) {
252 return NULL;
253 }
254 return SkRef(fStyles[index].get());
255 }
256
257 /** Find the typeface in this style set that most closely matches the given pattern.
258 * TODO: consider replacing with SkStyleSet_Indirect::matchStyle();
259 * this simpler version using match_score() passes all our tests.
260 */
mtklein36352bf2015-03-25 18:17:31 -0700261 SkTypeface_AndroidSystem* matchStyle(const SkFontStyle& pattern) override {
bungeman8d84c992014-07-24 08:05:09 -0700262 if (0 == fStyles.count()) {
263 return NULL;
264 }
bungeman65fcd3d2014-08-06 11:12:20 -0700265 SkTypeface_AndroidSystem* closest = fStyles[0];
bungeman8d84c992014-07-24 08:05:09 -0700266 int minScore = std::numeric_limits<int>::max();
267 for (int i = 0; i < fStyles.count(); ++i) {
268 SkFontStyle style = this->style(i);
269 int score = match_score(pattern, style);
270 if (score < minScore) {
271 closest = fStyles[i];
272 minScore = score;
273 }
274 }
275 return SkRef(closest);
276 }
277
278private:
279 SkFontStyle style(int index) {
bungeman4b86bac2014-11-04 10:54:31 -0800280 return fStyles[index]->fontStyle();
bungeman8d84c992014-07-24 08:05:09 -0700281 }
282 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) {
283 int score = 0;
284 score += abs((pattern.width() - candidate.width()) * 100);
285 score += abs((pattern.isItalic() == candidate.isItalic()) ? 0 : 1000);
286 score += abs(pattern.weight() - candidate.weight());
287 return score;
288 }
289
bungeman65fcd3d2014-08-06 11:12:20 -0700290 SkTArray<SkAutoTUnref<SkTypeface_AndroidSystem>, true> fStyles;
bungeman8d84c992014-07-24 08:05:09 -0700291
292 friend struct NameToFamily;
293 friend class SkFontMgr_Android;
294
295 typedef SkFontStyleSet INHERITED;
296};
297
298/** On Android a single family can have many names, but our API assumes unique names.
299 * Map names to the back end so that all names for a given family refer to the same
300 * (non-replicated) set of typefaces.
301 * SkTDict<> doesn't let us do index-based lookup, so we write our own mapping.
302 */
303struct NameToFamily {
304 SkString name;
305 SkFontStyleSet_Android* styleSet;
306};
307
308class SkFontMgr_Android : public SkFontMgr {
309public:
bungeman7fa87cd2015-02-06 07:59:19 -0800310 SkFontMgr_Android(const SkFontMgr_Android_CustomFonts* custom) {
311 SkTDArray<FontFamily*> families;
312 if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem != custom->fSystemFontUse) {
313 SkString base(custom->fBasePath);
314 SkFontConfigParser::GetCustomFontFamilies(families, base,
315 custom->fFontsXml, custom->fFallbackFontsXml);
316 }
317 if (!custom ||
318 (custom && SkFontMgr_Android_CustomFonts::kOnlyCustom != custom->fSystemFontUse))
319 {
320 SkFontConfigParser::GetSystemFontFamilies(families);
321 }
322 if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem == custom->fSystemFontUse) {
323 SkString base(custom->fBasePath);
324 SkFontConfigParser::GetCustomFontFamilies(families, base,
325 custom->fFontsXml, custom->fFallbackFontsXml);
326 }
327 this->buildNameToFamilyMap(families);
bungeman4e3523c2014-08-08 12:06:51 -0700328 this->findDefaultFont();
bungeman7fa87cd2015-02-06 07:59:19 -0800329 families.deleteAll();
bungeman8d84c992014-07-24 08:05:09 -0700330 }
331
332protected:
333 /** Returns not how many families we have, but how many unique names
334 * exist among the families.
335 */
mtklein36352bf2015-03-25 18:17:31 -0700336 int onCountFamilies() const override {
bungeman8d84c992014-07-24 08:05:09 -0700337 return fNameToFamilyMap.count();
338 }
339
mtklein36352bf2015-03-25 18:17:31 -0700340 void onGetFamilyName(int index, SkString* familyName) const override {
bungeman8d84c992014-07-24 08:05:09 -0700341 if (index < 0 || fNameToFamilyMap.count() <= index) {
342 familyName->reset();
343 return;
344 }
345 familyName->set(fNameToFamilyMap[index].name);
346 }
347
mtklein36352bf2015-03-25 18:17:31 -0700348 SkFontStyleSet* onCreateStyleSet(int index) const override {
bungeman8d84c992014-07-24 08:05:09 -0700349 if (index < 0 || fNameToFamilyMap.count() <= index) {
350 return NULL;
351 }
352 return SkRef(fNameToFamilyMap[index].styleSet);
353 }
354
mtklein36352bf2015-03-25 18:17:31 -0700355 SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
bungeman8d84c992014-07-24 08:05:09 -0700356 if (!familyName) {
357 return NULL;
358 }
359 SkAutoAsciiToLC tolc(familyName);
360 for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
361 if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
362 return SkRef(fNameToFamilyMap[i].styleSet);
363 }
364 }
bungeman65fcd3d2014-08-06 11:12:20 -0700365 // TODO: eventually we should not need to name fallback families.
366 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
367 if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) {
368 return SkRef(fFallbackNameToFamilyMap[i].styleSet);
369 }
370 }
bungeman8d84c992014-07-24 08:05:09 -0700371 return NULL;
372 }
373
374 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
mtklein36352bf2015-03-25 18:17:31 -0700375 const SkFontStyle& style) const override {
bungeman8d84c992014-07-24 08:05:09 -0700376 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
377 return sset->matchStyle(style);
378 }
379
380 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
mtklein36352bf2015-03-25 18:17:31 -0700381 const SkFontStyle& style) const override {
bungeman8d84c992014-07-24 08:05:09 -0700382 for (int i = 0; i < fFontStyleSets.count(); ++i) {
383 for (int j = 0; j < fFontStyleSets[i]->fStyles.count(); ++j) {
384 if (fFontStyleSets[i]->fStyles[j] == typeface) {
385 return fFontStyleSets[i]->matchStyle(style);
386 }
387 }
388 }
389 return NULL;
390 }
391
bungemanc9232dc2014-11-10 13:29:33 -0800392 static SkTypeface_AndroidSystem* find_family_style_character(
393 const SkTDArray<NameToFamily>& fallbackNameToFamilyMap,
394 const SkFontStyle& style, bool elegant,
395 const SkString& langTag, SkUnichar character)
396 {
397 for (int i = 0; i < fallbackNameToFamilyMap.count(); ++i) {
398 SkFontStyleSet_Android* family = fallbackNameToFamilyMap[i].styleSet;
399 SkAutoTUnref<SkTypeface_AndroidSystem> face(family->matchStyle(style));
bungemanc20386e2014-10-23 07:08:05 -0700400
bungemanc9232dc2014-11-10 13:29:33 -0800401 if (!langTag.isEmpty() && !face->fLang.getTag().startsWith(langTag.c_str())) {
402 continue;
403 }
404
405 if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) {
406 continue;
407 }
408
409 SkPaint paint;
410 paint.setTypeface(face);
411 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
412
413 uint16_t glyphID;
414 paint.textToGlyphs(&character, sizeof(character), &glyphID);
415 if (glyphID != 0) {
416 return face.detach();
417 }
bungemanc20386e2014-10-23 07:08:05 -0700418 }
bungemanc9232dc2014-11-10 13:29:33 -0800419 return NULL;
bungemanc20386e2014-10-23 07:08:05 -0700420 }
bungemanc9232dc2014-11-10 13:29:33 -0800421
bungeman65fcd3d2014-08-06 11:12:20 -0700422 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
423 const SkFontStyle& style,
bungemanc20386e2014-10-23 07:08:05 -0700424 const char* bcp47[],
425 int bcp47Count,
mtklein36352bf2015-03-25 18:17:31 -0700426 SkUnichar character) const override
bungeman65fcd3d2014-08-06 11:12:20 -0700427 {
428 // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascent/descent'.
429 // The variant 'default' means 'compact and elegant'.
430 // As a result, it is not possible to know the variant context from the font alone.
431 // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request.
432
bungemanc20386e2014-10-23 07:08:05 -0700433 // The first time match anything elegant, second time anything not elegant.
434 for (int elegant = 2; elegant --> 0;) {
435 for (int bcp47Index = bcp47Count; bcp47Index --> 0;) {
436 SkLanguage lang(bcp47[bcp47Index]);
437 while (!lang.getTag().isEmpty()) {
438 SkTypeface_AndroidSystem* matchingTypeface =
439 find_family_style_character(fFallbackNameToFamilyMap,
440 style, SkToBool(elegant),
441 lang.getTag(), character);
442 if (matchingTypeface) {
443 return matchingTypeface;
bungeman65fcd3d2014-08-06 11:12:20 -0700444 }
445
bungemanc20386e2014-10-23 07:08:05 -0700446 lang = lang.getParent();
bungeman65fcd3d2014-08-06 11:12:20 -0700447 }
bungemanc20386e2014-10-23 07:08:05 -0700448 }
449 SkTypeface_AndroidSystem* matchingTypeface =
450 find_family_style_character(fFallbackNameToFamilyMap,
451 style, SkToBool(elegant),
452 SkString(), character);
453 if (matchingTypeface) {
454 return matchingTypeface;
455 }
bungeman65fcd3d2014-08-06 11:12:20 -0700456 }
457 return NULL;
458 }
459
mtklein36352bf2015-03-25 18:17:31 -0700460 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
scroggoa1193e42015-01-21 12:09:53 -0800461 return this->createFromStream(new SkMemoryStream(data), ttcIndex);
bungeman8d84c992014-07-24 08:05:09 -0700462 }
463
mtklein36352bf2015-03-25 18:17:31 -0700464 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
bungeman5f213d92015-01-27 05:39:10 -0800465 SkAutoTDelete<SkStreamAsset> stream(SkStream::NewFromFile(path));
scroggoa1193e42015-01-21 12:09:53 -0800466 return stream.get() ? this->createFromStream(stream.detach(), ttcIndex) : NULL;
bungeman8d84c992014-07-24 08:05:09 -0700467 }
468
mtklein36352bf2015-03-25 18:17:31 -0700469 SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override {
bungeman5f213d92015-01-27 05:39:10 -0800470 SkAutoTDelete<SkStreamAsset> stream(bareStream);
bungeman8d84c992014-07-24 08:05:09 -0700471 bool isFixedPitch;
bungemana4c4a2d2014-10-20 13:33:19 -0700472 SkFontStyle style;
bungeman8d84c992014-07-24 08:05:09 -0700473 SkString name;
bungeman05773ed2015-05-13 10:57:09 -0700474 if (!fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch, NULL)) {
bungeman8d84c992014-07-24 08:05:09 -0700475 return NULL;
476 }
bungeman05773ed2015-05-13 10:57:09 -0700477 SkFontData* data(new SkFontData(stream.detach(), ttcIndex, NULL, 0));
478 return SkNEW_ARGS(SkTypeface_AndroidStream, (data, style, isFixedPitch, name));
479 }
480
481 SkTypeface* onCreateFromFontData(SkFontData* data) const override {
482 SkStreamAsset* stream(data->getStream());
483 bool isFixedPitch;
484 SkFontStyle style;
485 SkString name;
486 if (!fScanner.scanFont(stream, data->getIndex(), &name, &style, &isFixedPitch, NULL)) {
487 return NULL;
488 }
489 return SkNEW_ARGS(SkTypeface_AndroidStream, (data, style, isFixedPitch, name));
bungeman8d84c992014-07-24 08:05:09 -0700490 }
491
492
493 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
mtklein36352bf2015-03-25 18:17:31 -0700494 unsigned styleBits) const override {
bungemana4c4a2d2014-10-20 13:33:19 -0700495 SkFontStyle style = SkFontStyle(styleBits);
bungeman8d84c992014-07-24 08:05:09 -0700496
bsalomon49f085d2014-09-05 13:34:00 -0700497 if (familyName) {
bungeman8d84c992014-07-24 08:05:09 -0700498 // On Android, we must return NULL when we can't find the requested
499 // named typeface so that the system/app can provide their own recovery
500 // mechanism. On other platforms we'd provide a typeface from the
501 // default family instead.
bungeman07cfb202014-07-30 11:05:22 -0700502 return this->onMatchFamilyStyle(familyName, style);
bungeman8d84c992014-07-24 08:05:09 -0700503 }
bungeman07cfb202014-07-30 11:05:22 -0700504 return fDefaultFamily->matchStyle(style);
bungeman8d84c992014-07-24 08:05:09 -0700505 }
506
507
508private:
509
bungeman14df8332014-10-28 15:07:23 -0700510 SkTypeface_FreeType::Scanner fScanner;
511
bungeman8d84c992014-07-24 08:05:09 -0700512 SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets;
513 SkFontStyleSet* fDefaultFamily;
514 SkTypeface* fDefaultTypeface;
515
516 SkTDArray<NameToFamily> fNameToFamilyMap;
bungeman65fcd3d2014-08-06 11:12:20 -0700517 SkTDArray<NameToFamily> fFallbackNameToFamilyMap;
bungeman8d84c992014-07-24 08:05:09 -0700518
bungeman7fa87cd2015-02-06 07:59:19 -0800519 void buildNameToFamilyMap(SkTDArray<FontFamily*> families) {
bungeman8d84c992014-07-24 08:05:09 -0700520 for (int i = 0; i < families.count(); i++) {
bungeman65fcd3d2014-08-06 11:12:20 -0700521 FontFamily& family = *families[i];
522
523 SkTDArray<NameToFamily>* nameToFamily = &fNameToFamilyMap;
524 if (family.fIsFallbackFont) {
525 nameToFamily = &fFallbackNameToFamilyMap;
526
527 if (0 == family.fNames.count()) {
528 SkString& fallbackName = family.fNames.push_back();
529 fallbackName.printf("%.2x##fallback", i);
530 }
531 }
532
bungeman14df8332014-10-28 15:07:23 -0700533 SkFontStyleSet_Android* newSet =
bungeman7fa87cd2015-02-06 07:59:19 -0800534 SkNEW_ARGS(SkFontStyleSet_Android, (family, fScanner));
bungeman65fcd3d2014-08-06 11:12:20 -0700535 if (0 == newSet->count()) {
536 SkDELETE(newSet);
537 continue;
538 }
539 fFontStyleSets.push_back().reset(newSet);
540
541 for (int j = 0; j < family.fNames.count(); j++) {
542 NameToFamily* nextEntry = nameToFamily->append();
543 SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (family.fNames[j]));
544 nextEntry->styleSet = newSet;
bungeman8d84c992014-07-24 08:05:09 -0700545 }
546 }
547 }
548
549 void findDefaultFont() {
550 SkASSERT(!fFontStyleSets.empty());
551
552 static const char* gDefaultNames[] = { "sans-serif" };
553 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
554 SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]);
555 if (NULL == set) {
556 continue;
557 }
558 SkTypeface* tf = set->matchStyle(SkFontStyle());
559 if (NULL == tf) {
560 continue;
561 }
562 fDefaultFamily = set;
563 fDefaultTypeface = tf;
564 break;
565 }
566 if (NULL == fDefaultTypeface) {
567 fDefaultFamily = fFontStyleSets[0];
568 fDefaultTypeface = fDefaultFamily->createTypeface(0);
569 }
570 SkASSERT(fDefaultFamily);
571 SkASSERT(fDefaultTypeface);
572 }
573
574 typedef SkFontMgr INHERITED;
575};
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}
tomhudsonc7733902014-08-13 10:41:25 -0700596
bungeman7fa87cd2015-02-06 07:59:19 -0800597SkFontMgr* SkFontMgr::Factory() {
598 // These globals exist so that Chromium can override the environment.
599 // TODO: these globals need to be removed, and Chromium use SkFontMgr_New_Android instead.
600 if ((gTestFontsXml || gTestFallbackFontsXml) && gTestBasePath) {
601 SkFontMgr_Android_CustomFonts custom = {
602 SkFontMgr_Android_CustomFonts::kOnlyCustom,
603 gTestBasePath,
604 gTestFontsXml,
605 gTestFallbackFontsXml
606 };
607 return SkFontMgr_New_Android(&custom);
608 }
609
610 return SkFontMgr_New_Android(NULL);
tomhudsonc7733902014-08-13 10:41:25 -0700611}
612
bungeman7fa87cd2015-02-06 07:59:19 -0800613void SkUseTestFontConfigFile(const char* fontsXml, const char* fallbackFontsXml,
614 const char* basePath)
615{
616 gTestFontsXml = fontsXml;
617 gTestFallbackFontsXml = fallbackFontsXml;
618 gTestBasePath = basePath;
619 SkASSERT(gTestFontsXml);
620 SkASSERT(gTestFallbackFontsXml);
621 SkASSERT(gTestBasePath);
622 SkDEBUGF(("Test BasePath: %s Fonts: %s FallbackFonts: %s\n",
623 gTestBasePath, gTestFontsXml, gTestFallbackFontsXml));
tomhudsonc7733902014-08-13 10:41:25 -0700624}