blob: afa78734544f685bfba82be17062e89f6b2f543b [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
bungemanf20488b2015-07-29 11:49:40 -070010#include "SkFixed.h"
bungeman8d84c992014-07-24 08:05:09 -070011#include "SkFontDescriptor.h"
12#include "SkFontHost_FreeType_common.h"
13#include "SkFontMgr.h"
bungeman7fa87cd2015-02-06 07:59:19 -080014#include "SkFontMgr_android.h"
bungemanc5308542015-06-23 13:25:46 -070015#include "SkFontMgr_android_parser.h"
bungeman8d84c992014-07-24 08:05:09 -070016#include "SkFontStyle.h"
bungeman24a104d2015-07-30 10:31:57 -070017#include "SkPaint.h"
bungemanf20488b2015-07-29 11:49:40 -070018#include "SkRefCnt.h"
19#include "SkString.h"
bungeman8d84c992014-07-24 08:05:09 -070020#include "SkStream.h"
bungemanf20488b2015-07-29 11:49:40 -070021#include "SkTArray.h"
bungeman8d84c992014-07-24 08:05:09 -070022#include "SkTDArray.h"
23#include "SkTSearch.h"
bungemanf20488b2015-07-29 11:49:40 -070024#include "SkTemplates.h"
bungeman8d84c992014-07-24 08:05:09 -070025#include "SkTypefaceCache.h"
26
27#include <limits>
bungeman8d84c992014-07-24 08:05:09 -070028
bungemanf20488b2015-07-29 11:49:40 -070029class SkData;
30
bungeman8d84c992014-07-24 08:05:09 -070031class SkTypeface_Android : public SkTypeface_FreeType {
32public:
bungeman41868fe2015-05-20 09:21:04 -070033 SkTypeface_Android(const SkFontStyle& style,
bungeman8d84c992014-07-24 08:05:09 -070034 bool isFixedPitch,
bungeman4b86bac2014-11-04 10:54:31 -080035 const SkString& familyName)
bungeman8d84c992014-07-24 08:05:09 -070036 : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch)
bungeman41868fe2015-05-20 09:21:04 -070037 , fFamilyName(familyName)
38 { }
bungeman8d84c992014-07-24 08:05:09 -070039
bungeman8d84c992014-07-24 08:05:09 -070040protected:
mtklein36352bf2015-03-25 18:17:31 -070041 void onGetFamilyName(SkString* familyName) const override {
bungemanb374d6a2014-09-17 07:48:59 -070042 *familyName = fFamilyName;
43 }
44
bungeman8d84c992014-07-24 08:05:09 -070045 SkString fFamilyName;
46
47private:
48 typedef SkTypeface_FreeType INHERITED;
49};
50
51class SkTypeface_AndroidSystem : public SkTypeface_Android {
52public:
bungeman4b86bac2014-11-04 10:54:31 -080053 SkTypeface_AndroidSystem(const SkString& pathName,
bungeman8d84c992014-07-24 08:05:09 -070054 int index,
bungeman41868fe2015-05-20 09:21:04 -070055 const SkFixed* axes, int axesCount,
bungemana4c4a2d2014-10-20 13:33:19 -070056 const SkFontStyle& style,
bungeman8d84c992014-07-24 08:05:09 -070057 bool isFixedPitch,
bungeman4b86bac2014-11-04 10:54:31 -080058 const SkString& familyName,
bungeman65fcd3d2014-08-06 11:12:20 -070059 const SkLanguage& lang,
djsollen3b625542014-08-14 06:29:02 -070060 FontVariant variantStyle)
bungeman41868fe2015-05-20 09:21:04 -070061 : INHERITED(style, isFixedPitch, familyName)
bungeman65fcd3d2014-08-06 11:12:20 -070062 , fPathName(pathName)
bungeman41868fe2015-05-20 09:21:04 -070063 , fIndex(index)
64 , fAxes(axes, axesCount)
bungeman65fcd3d2014-08-06 11:12:20 -070065 , fLang(lang)
66 , fVariantStyle(variantStyle) { }
bungeman8d84c992014-07-24 08:05:09 -070067
bungeman41868fe2015-05-20 09:21:04 -070068 virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
bungeman8d84c992014-07-24 08:05:09 -070069 SkASSERT(desc);
70 SkASSERT(serialize);
71 desc->setFamilyName(fFamilyName.c_str());
bungeman8d84c992014-07-24 08:05:09 -070072 *serialize = false;
73 }
mtklein36352bf2015-03-25 18:17:31 -070074 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
bungeman8d84c992014-07-24 08:05:09 -070075 *ttcIndex = fIndex;
76 return SkStream::NewFromFile(fPathName.c_str());
77 }
bungeman41868fe2015-05-20 09:21:04 -070078 SkFontData* onCreateFontData() const override {
79 return new SkFontData(SkStream::NewFromFile(fPathName.c_str()), fIndex,
80 fAxes.begin(), fAxes.count());
81 }
bungeman8d84c992014-07-24 08:05:09 -070082
bungeman65fcd3d2014-08-06 11:12:20 -070083 const SkString fPathName;
bungeman41868fe2015-05-20 09:21:04 -070084 int fIndex;
85 const SkSTArray<4, SkFixed, true> fAxes;
bungeman65fcd3d2014-08-06 11:12:20 -070086 const SkLanguage fLang;
djsollen3b625542014-08-14 06:29:02 -070087 const FontVariant fVariantStyle;
bungeman8d84c992014-07-24 08:05:09 -070088
89 typedef SkTypeface_Android INHERITED;
90};
91
92class SkTypeface_AndroidStream : public SkTypeface_Android {
93public:
bungeman41868fe2015-05-20 09:21:04 -070094 SkTypeface_AndroidStream(SkFontData* data,
bungemana4c4a2d2014-10-20 13:33:19 -070095 const SkFontStyle& style,
bungeman8d84c992014-07-24 08:05:09 -070096 bool isFixedPitch,
bungeman4b86bac2014-11-04 10:54:31 -080097 const SkString& familyName)
bungeman41868fe2015-05-20 09:21:04 -070098 : INHERITED(style, isFixedPitch, familyName)
99 , fData(data)
100 { }
bungeman8d84c992014-07-24 08:05:09 -0700101
102 virtual void onGetFontDescriptor(SkFontDescriptor* desc,
mtklein36352bf2015-03-25 18:17:31 -0700103 bool* serialize) const override {
bungeman8d84c992014-07-24 08:05:09 -0700104 SkASSERT(desc);
105 SkASSERT(serialize);
106 desc->setFamilyName(fFamilyName.c_str());
bungeman8d84c992014-07-24 08:05:09 -0700107 *serialize = true;
108 }
109
mtklein36352bf2015-03-25 18:17:31 -0700110 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
bungeman41868fe2015-05-20 09:21:04 -0700111 *ttcIndex = fData->getIndex();
112 return fData->duplicateStream();
113 }
114
115 SkFontData* onCreateFontData() const override {
116 return new SkFontData(*fData.get());
bungeman8d84c992014-07-24 08:05:09 -0700117 }
118
119private:
bungeman41868fe2015-05-20 09:21:04 -0700120 const SkAutoTDelete<const SkFontData> fData;
bungeman8d84c992014-07-24 08:05:09 -0700121 typedef SkTypeface_Android INHERITED;
122};
123
bungeman8d84c992014-07-24 08:05:09 -0700124class SkFontStyleSet_Android : public SkFontStyleSet {
bungeman41868fe2015-05-20 09:21:04 -0700125 typedef SkTypeface_FreeType::Scanner Scanner;
126
bungeman8d84c992014-07-24 08:05:09 -0700127public:
bungeman41868fe2015-05-20 09:21:04 -0700128 explicit SkFontStyleSet_Android(const FontFamily& family, const Scanner& scanner) {
halcanary96fcdcc2015-08-27 07:41:13 -0700129 const SkString* cannonicalFamilyName = nullptr;
bungeman65fcd3d2014-08-06 11:12:20 -0700130 if (family.fNames.count() > 0) {
131 cannonicalFamilyName = &family.fNames[0];
132 }
bungeman8d84c992014-07-24 08:05:09 -0700133 // TODO? make this lazy
tomhudsond3ddea22014-08-11 11:28:00 -0700134 for (int i = 0; i < family.fFonts.count(); ++i) {
135 const FontFileInfo& fontFile = family.fFonts[i];
bungeman8d84c992014-07-24 08:05:09 -0700136
bungeman7fa87cd2015-02-06 07:59:19 -0800137 SkString pathName(family.fBasePath);
138 pathName.append(fontFile.fFileName);
bungeman8d84c992014-07-24 08:05:09 -0700139
scroggoa1193e42015-01-21 12:09:53 -0800140 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(pathName.c_str()));
bungeman8d84c992014-07-24 08:05:09 -0700141 if (!stream.get()) {
bungeman7fa87cd2015-02-06 07:59:19 -0800142 SkDEBUGF(("Requested font file %s does not exist or cannot be opened.\n",
143 pathName.c_str()));
bungeman8d84c992014-07-24 08:05:09 -0700144 continue;
145 }
146
bungeman65fcd3d2014-08-06 11:12:20 -0700147 const int ttcIndex = fontFile.fIndex;
148 SkString familyName;
bungemana4c4a2d2014-10-20 13:33:19 -0700149 SkFontStyle style;
bungeman8d84c992014-07-24 08:05:09 -0700150 bool isFixedWidth;
bungeman41868fe2015-05-20 09:21:04 -0700151 Scanner::AxisDefinitions axisDefinitions;
152 if (!scanner.scanFont(stream.get(), ttcIndex,
153 &familyName, &style, &isFixedWidth, &axisDefinitions))
154 {
bungeman7fa87cd2015-02-06 07:59:19 -0800155 SkDEBUGF(("Requested font file %s exists, but is not a valid font.\n",
156 pathName.c_str()));
bungeman8d84c992014-07-24 08:05:09 -0700157 continue;
158 }
159
bungemane85a7542015-04-17 13:51:08 -0700160 int weight = fontFile.fWeight != 0 ? fontFile.fWeight : style.weight();
161 SkFontStyle::Slant slant = style.slant();
162 switch (fontFile.fStyle) {
163 case FontFileInfo::Style::kAuto: slant = style.slant(); break;
164 case FontFileInfo::Style::kNormal: slant = SkFontStyle::kUpright_Slant; break;
165 case FontFileInfo::Style::kItalic: slant = SkFontStyle::kItalic_Slant; break;
166 default: SkASSERT(false); break;
bungeman4b86bac2014-11-04 10:54:31 -0800167 }
bungemane85a7542015-04-17 13:51:08 -0700168 style = SkFontStyle(weight, style.width(), slant);
bungeman4b86bac2014-11-04 10:54:31 -0800169
djsollen3b625542014-08-14 06:29:02 -0700170 const SkLanguage& lang = family.fLanguage;
171 uint32_t variant = family.fVariant;
172 if (kDefault_FontVariant == variant) {
173 variant = kCompact_FontVariant | kElegant_FontVariant;
bungeman65fcd3d2014-08-06 11:12:20 -0700174 }
175
176 // The first specified family name overrides the family name found in the font.
177 // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return
178 // all of the specified family names in addition to the names found in the font.
halcanary96fcdcc2015-08-27 07:41:13 -0700179 if (cannonicalFamilyName != nullptr) {
bungeman65fcd3d2014-08-06 11:12:20 -0700180 familyName = *cannonicalFamilyName;
181 }
182
bungeman41868fe2015-05-20 09:21:04 -0700183 SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
184 for (int i = 0; i < axisDefinitions.count(); ++i) {
185 const Scanner::AxisDefinition& axisDefinition = axisDefinitions[i];
186 axisValues[i] = axisDefinition.fDefault;
187 for (int j = 0; j < fontFile.fAxes.count(); ++j) {
188 const FontFileInfo::Axis& axisSpecified = fontFile.fAxes[j];
189 if (axisDefinition.fTag == axisSpecified.fTag) {
190 axisValues[i] = SkTPin(axisSpecified.fValue, axisDefinition.fMinimum,
191 axisDefinition.fMaximum);
192 if (axisValues[i] != axisSpecified.fValue) {
193 SkDEBUGF(("Requested font axis value out of range: "
194 "%s '%c%c%c%c' %f; pinned to %f.\n",
195 familyName.c_str(),
196 (axisDefinition.fTag >> 24) & 0xFF,
197 (axisDefinition.fTag >> 16) & 0xFF,
198 (axisDefinition.fTag >> 8) & 0xFF,
199 (axisDefinition.fTag ) & 0xFF,
200 SkFixedToDouble(axisSpecified.fValue),
201 SkFixedToDouble(axisValues[i])));
202 }
203 break;
204 }
205 }
206 // TODO: warn on defaulted axis?
207 }
208
halcanary385fe4d2015-08-26 13:07:48 -0700209 SkDEBUGCODE(
bungemanf6c71072016-01-21 14:17:47 -0800210 // Check for axis specified, but not matched in font.
211 for (int i = 0; i < fontFile.fAxes.count(); ++i) {
212 SkFourByteTag skTag = fontFile.fAxes[i].fTag;
213 bool found = false;
214 for (int j = 0; j < axisDefinitions.count(); ++j) {
215 if (skTag == axisDefinitions[j].fTag) {
216 found = true;
217 break;
bungeman41868fe2015-05-20 09:21:04 -0700218 }
bungemanf6c71072016-01-21 14:17:47 -0800219 }
220 if (!found) {
221 SkDEBUGF(("Requested font axis not found: %s '%c%c%c%c'\n",
222 familyName.c_str(), (skTag >> 24) & 0xFF,
223 (skTag >> 16) & 0xFF, (skTag >> 8) & 0xFF, (skTag)&0xFF));
224 }
225 }
226 )
bungeman41868fe2015-05-20 09:21:04 -0700227
bungemanf6c71072016-01-21 14:17:47 -0800228 fStyles.push_back().reset(new SkTypeface_AndroidSystem(
229 pathName, ttcIndex, axisValues.get(), axisDefinitions.count(), style,
230 isFixedWidth, familyName, lang, variant));
bungeman8d84c992014-07-24 08:05:09 -0700231 }
232 }
233
mtklein36352bf2015-03-25 18:17:31 -0700234 int count() override {
bungeman8d84c992014-07-24 08:05:09 -0700235 return fStyles.count();
236 }
mtklein36352bf2015-03-25 18:17:31 -0700237 void getStyle(int index, SkFontStyle* style, SkString* name) override {
bungeman8d84c992014-07-24 08:05:09 -0700238 if (index < 0 || fStyles.count() <= index) {
239 return;
240 }
241 if (style) {
242 *style = this->style(index);
243 }
244 if (name) {
245 name->reset();
246 }
247 }
mtklein36352bf2015-03-25 18:17:31 -0700248 SkTypeface_AndroidSystem* createTypeface(int index) override {
bungeman8d84c992014-07-24 08:05:09 -0700249 if (index < 0 || fStyles.count() <= index) {
halcanary96fcdcc2015-08-27 07:41:13 -0700250 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700251 }
252 return SkRef(fStyles[index].get());
253 }
254
255 /** Find the typeface in this style set that most closely matches the given pattern.
256 * TODO: consider replacing with SkStyleSet_Indirect::matchStyle();
257 * this simpler version using match_score() passes all our tests.
258 */
mtklein36352bf2015-03-25 18:17:31 -0700259 SkTypeface_AndroidSystem* matchStyle(const SkFontStyle& pattern) override {
bungeman8d84c992014-07-24 08:05:09 -0700260 if (0 == fStyles.count()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700261 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700262 }
bungeman65fcd3d2014-08-06 11:12:20 -0700263 SkTypeface_AndroidSystem* closest = fStyles[0];
bungeman8d84c992014-07-24 08:05:09 -0700264 int minScore = std::numeric_limits<int>::max();
265 for (int i = 0; i < fStyles.count(); ++i) {
266 SkFontStyle style = this->style(i);
267 int score = match_score(pattern, style);
268 if (score < minScore) {
269 closest = fStyles[i];
270 minScore = score;
271 }
272 }
273 return SkRef(closest);
274 }
275
276private:
277 SkFontStyle style(int index) {
bungeman4b86bac2014-11-04 10:54:31 -0800278 return fStyles[index]->fontStyle();
bungeman8d84c992014-07-24 08:05:09 -0700279 }
280 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) {
281 int score = 0;
bungemanf20488b2015-07-29 11:49:40 -0700282 score += SkTAbs((pattern.width() - candidate.width()) * 100);
283 score += SkTAbs((pattern.isItalic() == candidate.isItalic()) ? 0 : 1000);
284 score += SkTAbs(pattern.weight() - candidate.weight());
bungeman8d84c992014-07-24 08:05:09 -0700285 return score;
286 }
287
bungeman65fcd3d2014-08-06 11:12:20 -0700288 SkTArray<SkAutoTUnref<SkTypeface_AndroidSystem>, true> fStyles;
bungeman8d84c992014-07-24 08:05:09 -0700289
290 friend struct NameToFamily;
291 friend class SkFontMgr_Android;
292
293 typedef SkFontStyleSet INHERITED;
294};
295
296/** On Android a single family can have many names, but our API assumes unique names.
297 * Map names to the back end so that all names for a given family refer to the same
298 * (non-replicated) set of typefaces.
299 * SkTDict<> doesn't let us do index-based lookup, so we write our own mapping.
300 */
301struct NameToFamily {
302 SkString name;
303 SkFontStyleSet_Android* styleSet;
304};
305
306class SkFontMgr_Android : public SkFontMgr {
307public:
bungeman7fa87cd2015-02-06 07:59:19 -0800308 SkFontMgr_Android(const SkFontMgr_Android_CustomFonts* custom) {
309 SkTDArray<FontFamily*> families;
310 if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem != custom->fSystemFontUse) {
311 SkString base(custom->fBasePath);
bungemanc5308542015-06-23 13:25:46 -0700312 SkFontMgr_Android_Parser::GetCustomFontFamilies(
313 families, base, custom->fFontsXml, custom->fFallbackFontsXml);
bungeman7fa87cd2015-02-06 07:59:19 -0800314 }
315 if (!custom ||
316 (custom && SkFontMgr_Android_CustomFonts::kOnlyCustom != custom->fSystemFontUse))
317 {
bungemanc5308542015-06-23 13:25:46 -0700318 SkFontMgr_Android_Parser::GetSystemFontFamilies(families);
bungeman7fa87cd2015-02-06 07:59:19 -0800319 }
320 if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem == custom->fSystemFontUse) {
321 SkString base(custom->fBasePath);
bungemanc5308542015-06-23 13:25:46 -0700322 SkFontMgr_Android_Parser::GetCustomFontFamilies(
323 families, base, custom->fFontsXml, custom->fFallbackFontsXml);
bungeman7fa87cd2015-02-06 07:59:19 -0800324 }
325 this->buildNameToFamilyMap(families);
bungeman4e3523c2014-08-08 12:06:51 -0700326 this->findDefaultFont();
bungeman7fa87cd2015-02-06 07:59:19 -0800327 families.deleteAll();
bungeman8d84c992014-07-24 08:05:09 -0700328 }
329
330protected:
331 /** Returns not how many families we have, but how many unique names
332 * exist among the families.
333 */
mtklein36352bf2015-03-25 18:17:31 -0700334 int onCountFamilies() const override {
bungeman8d84c992014-07-24 08:05:09 -0700335 return fNameToFamilyMap.count();
336 }
337
mtklein36352bf2015-03-25 18:17:31 -0700338 void onGetFamilyName(int index, SkString* familyName) const override {
bungeman8d84c992014-07-24 08:05:09 -0700339 if (index < 0 || fNameToFamilyMap.count() <= index) {
340 familyName->reset();
341 return;
342 }
343 familyName->set(fNameToFamilyMap[index].name);
344 }
345
mtklein36352bf2015-03-25 18:17:31 -0700346 SkFontStyleSet* onCreateStyleSet(int index) const override {
bungeman8d84c992014-07-24 08:05:09 -0700347 if (index < 0 || fNameToFamilyMap.count() <= index) {
halcanary96fcdcc2015-08-27 07:41:13 -0700348 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700349 }
350 return SkRef(fNameToFamilyMap[index].styleSet);
351 }
352
mtklein36352bf2015-03-25 18:17:31 -0700353 SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
bungeman8d84c992014-07-24 08:05:09 -0700354 if (!familyName) {
halcanary96fcdcc2015-08-27 07:41:13 -0700355 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700356 }
357 SkAutoAsciiToLC tolc(familyName);
358 for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
359 if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
360 return SkRef(fNameToFamilyMap[i].styleSet);
361 }
362 }
bungeman65fcd3d2014-08-06 11:12:20 -0700363 // TODO: eventually we should not need to name fallback families.
364 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
365 if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) {
366 return SkRef(fFallbackNameToFamilyMap[i].styleSet);
367 }
368 }
halcanary96fcdcc2015-08-27 07:41:13 -0700369 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700370 }
371
372 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
mtklein36352bf2015-03-25 18:17:31 -0700373 const SkFontStyle& style) const override {
bungeman8d84c992014-07-24 08:05:09 -0700374 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
375 return sset->matchStyle(style);
376 }
377
378 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
mtklein36352bf2015-03-25 18:17:31 -0700379 const SkFontStyle& style) const override {
bungeman8d84c992014-07-24 08:05:09 -0700380 for (int i = 0; i < fFontStyleSets.count(); ++i) {
381 for (int j = 0; j < fFontStyleSets[i]->fStyles.count(); ++j) {
382 if (fFontStyleSets[i]->fStyles[j] == typeface) {
383 return fFontStyleSets[i]->matchStyle(style);
384 }
385 }
386 }
halcanary96fcdcc2015-08-27 07:41:13 -0700387 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700388 }
389
bungemanc9232dc2014-11-10 13:29:33 -0800390 static SkTypeface_AndroidSystem* find_family_style_character(
391 const SkTDArray<NameToFamily>& fallbackNameToFamilyMap,
392 const SkFontStyle& style, bool elegant,
393 const SkString& langTag, SkUnichar character)
394 {
395 for (int i = 0; i < fallbackNameToFamilyMap.count(); ++i) {
396 SkFontStyleSet_Android* family = fallbackNameToFamilyMap[i].styleSet;
397 SkAutoTUnref<SkTypeface_AndroidSystem> face(family->matchStyle(style));
bungemanc20386e2014-10-23 07:08:05 -0700398
bungemanc9232dc2014-11-10 13:29:33 -0800399 if (!langTag.isEmpty() && !face->fLang.getTag().startsWith(langTag.c_str())) {
400 continue;
401 }
402
403 if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) {
404 continue;
405 }
406
bungeman24a104d2015-07-30 10:31:57 -0700407 SkPaint paint;
408 paint.setTypeface(face);
409 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
410
411 uint16_t glyphID;
412 paint.textToGlyphs(&character, sizeof(character), &glyphID);
413 if (glyphID != 0) {
bungemanc9232dc2014-11-10 13:29:33 -0800414 return face.detach();
415 }
bungemanc20386e2014-10-23 07:08:05 -0700416 }
halcanary96fcdcc2015-08-27 07:41:13 -0700417 return nullptr;
bungemanc20386e2014-10-23 07:08:05 -0700418 }
bungemanc9232dc2014-11-10 13:29:33 -0800419
bungeman65fcd3d2014-08-06 11:12:20 -0700420 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
421 const SkFontStyle& style,
bungemanc20386e2014-10-23 07:08:05 -0700422 const char* bcp47[],
423 int bcp47Count,
mtklein36352bf2015-03-25 18:17:31 -0700424 SkUnichar character) const override
bungeman65fcd3d2014-08-06 11:12:20 -0700425 {
426 // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascent/descent'.
427 // The variant 'default' means 'compact and elegant'.
428 // As a result, it is not possible to know the variant context from the font alone.
429 // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request.
430
bungemanc20386e2014-10-23 07:08:05 -0700431 // The first time match anything elegant, second time anything not elegant.
432 for (int elegant = 2; elegant --> 0;) {
433 for (int bcp47Index = bcp47Count; bcp47Index --> 0;) {
434 SkLanguage lang(bcp47[bcp47Index]);
435 while (!lang.getTag().isEmpty()) {
436 SkTypeface_AndroidSystem* matchingTypeface =
437 find_family_style_character(fFallbackNameToFamilyMap,
438 style, SkToBool(elegant),
439 lang.getTag(), character);
440 if (matchingTypeface) {
441 return matchingTypeface;
bungeman65fcd3d2014-08-06 11:12:20 -0700442 }
443
bungemanc20386e2014-10-23 07:08:05 -0700444 lang = lang.getParent();
bungeman65fcd3d2014-08-06 11:12:20 -0700445 }
bungemanc20386e2014-10-23 07:08:05 -0700446 }
447 SkTypeface_AndroidSystem* matchingTypeface =
448 find_family_style_character(fFallbackNameToFamilyMap,
449 style, SkToBool(elegant),
450 SkString(), character);
451 if (matchingTypeface) {
452 return matchingTypeface;
453 }
bungeman65fcd3d2014-08-06 11:12:20 -0700454 }
halcanary96fcdcc2015-08-27 07:41:13 -0700455 return nullptr;
bungeman65fcd3d2014-08-06 11:12:20 -0700456 }
457
mtklein36352bf2015-03-25 18:17:31 -0700458 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
scroggoa1193e42015-01-21 12:09:53 -0800459 return this->createFromStream(new SkMemoryStream(data), ttcIndex);
bungeman8d84c992014-07-24 08:05:09 -0700460 }
461
mtklein36352bf2015-03-25 18:17:31 -0700462 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
bungeman5f213d92015-01-27 05:39:10 -0800463 SkAutoTDelete<SkStreamAsset> stream(SkStream::NewFromFile(path));
halcanary96fcdcc2015-08-27 07:41:13 -0700464 return stream.get() ? this->createFromStream(stream.detach(), ttcIndex) : nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700465 }
466
mtklein36352bf2015-03-25 18:17:31 -0700467 SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override {
bungeman5f213d92015-01-27 05:39:10 -0800468 SkAutoTDelete<SkStreamAsset> stream(bareStream);
bungeman8d84c992014-07-24 08:05:09 -0700469 bool isFixedPitch;
bungemana4c4a2d2014-10-20 13:33:19 -0700470 SkFontStyle style;
bungeman8d84c992014-07-24 08:05:09 -0700471 SkString name;
halcanary96fcdcc2015-08-27 07:41:13 -0700472 if (!fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch, nullptr)) {
473 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700474 }
halcanary96fcdcc2015-08-27 07:41:13 -0700475 SkFontData* data(new SkFontData(stream.detach(), ttcIndex, nullptr, 0));
halcanary385fe4d2015-08-26 13:07:48 -0700476 return new SkTypeface_AndroidStream(data, style, isFixedPitch, name);
bungeman41868fe2015-05-20 09:21:04 -0700477 }
478
bungemanf6c71072016-01-21 14:17:47 -0800479 SkTypeface* onCreateFromStream(SkStreamAsset* s, const FontParameters& params) const override {
480 using Scanner = SkTypeface_FreeType::Scanner;
481 SkAutoTDelete<SkStreamAsset> stream(s);
482 bool isFixedPitch;
483 SkFontStyle style;
484 SkString name;
485 Scanner::AxisDefinitions axisDefinitions;
486 if (!fScanner.scanFont(stream, params.getCollectionIndex(), &name, &style, &isFixedPitch,
487 &axisDefinitions))
488 {
489 return nullptr;
490 }
491
492 int paramAxisCount;
493 const FontParameters::Axis* paramAxes = params.getAxes(&paramAxisCount);
494 SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
495 Scanner::computeAxisValues(axisDefinitions, paramAxes, paramAxisCount, axisValues, name);
496
497 SkFontData* data(new SkFontData(stream.detach(), params.getCollectionIndex(),
498 axisValues.get(), axisDefinitions.count()));
499 return new SkTypeface_AndroidStream(data, style, isFixedPitch, name);
500 }
501
bungeman41868fe2015-05-20 09:21:04 -0700502 SkTypeface* onCreateFromFontData(SkFontData* data) const override {
503 SkStreamAsset* stream(data->getStream());
504 bool isFixedPitch;
505 SkFontStyle style;
506 SkString name;
halcanary96fcdcc2015-08-27 07:41:13 -0700507 if (!fScanner.scanFont(stream, data->getIndex(), &name, &style, &isFixedPitch, nullptr)) {
508 return nullptr;
bungeman41868fe2015-05-20 09:21:04 -0700509 }
halcanary385fe4d2015-08-26 13:07:48 -0700510 return new SkTypeface_AndroidStream(data, style, isFixedPitch, name);
bungeman8d84c992014-07-24 08:05:09 -0700511 }
512
513
514 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
mtklein36352bf2015-03-25 18:17:31 -0700515 unsigned styleBits) const override {
bungemana4c4a2d2014-10-20 13:33:19 -0700516 SkFontStyle style = SkFontStyle(styleBits);
bungeman8d84c992014-07-24 08:05:09 -0700517
bsalomon49f085d2014-09-05 13:34:00 -0700518 if (familyName) {
halcanary96fcdcc2015-08-27 07:41:13 -0700519 // On Android, we must return nullptr when we can't find the requested
bungeman8d84c992014-07-24 08:05:09 -0700520 // named typeface so that the system/app can provide their own recovery
521 // mechanism. On other platforms we'd provide a typeface from the
522 // default family instead.
bungeman07cfb202014-07-30 11:05:22 -0700523 return this->onMatchFamilyStyle(familyName, style);
bungeman8d84c992014-07-24 08:05:09 -0700524 }
bungeman07cfb202014-07-30 11:05:22 -0700525 return fDefaultFamily->matchStyle(style);
bungeman8d84c992014-07-24 08:05:09 -0700526 }
527
528
529private:
530
bungeman14df8332014-10-28 15:07:23 -0700531 SkTypeface_FreeType::Scanner fScanner;
532
bungeman8d84c992014-07-24 08:05:09 -0700533 SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets;
534 SkFontStyleSet* fDefaultFamily;
535 SkTypeface* fDefaultTypeface;
536
537 SkTDArray<NameToFamily> fNameToFamilyMap;
bungeman65fcd3d2014-08-06 11:12:20 -0700538 SkTDArray<NameToFamily> fFallbackNameToFamilyMap;
bungeman8d84c992014-07-24 08:05:09 -0700539
bungeman7fa87cd2015-02-06 07:59:19 -0800540 void buildNameToFamilyMap(SkTDArray<FontFamily*> families) {
bungeman8d84c992014-07-24 08:05:09 -0700541 for (int i = 0; i < families.count(); i++) {
bungeman65fcd3d2014-08-06 11:12:20 -0700542 FontFamily& family = *families[i];
543
544 SkTDArray<NameToFamily>* nameToFamily = &fNameToFamilyMap;
545 if (family.fIsFallbackFont) {
546 nameToFamily = &fFallbackNameToFamilyMap;
547
548 if (0 == family.fNames.count()) {
549 SkString& fallbackName = family.fNames.push_back();
550 fallbackName.printf("%.2x##fallback", i);
551 }
552 }
553
halcanary385fe4d2015-08-26 13:07:48 -0700554 SkFontStyleSet_Android* newSet = new SkFontStyleSet_Android(family, fScanner);
bungeman65fcd3d2014-08-06 11:12:20 -0700555 if (0 == newSet->count()) {
halcanary385fe4d2015-08-26 13:07:48 -0700556 delete newSet;
bungeman65fcd3d2014-08-06 11:12:20 -0700557 continue;
558 }
559 fFontStyleSets.push_back().reset(newSet);
560
561 for (int j = 0; j < family.fNames.count(); j++) {
562 NameToFamily* nextEntry = nameToFamily->append();
halcanary385fe4d2015-08-26 13:07:48 -0700563 new (&nextEntry->name) SkString(family.fNames[j]);
bungeman65fcd3d2014-08-06 11:12:20 -0700564 nextEntry->styleSet = newSet;
bungeman8d84c992014-07-24 08:05:09 -0700565 }
566 }
567 }
568
569 void findDefaultFont() {
570 SkASSERT(!fFontStyleSets.empty());
571
572 static const char* gDefaultNames[] = { "sans-serif" };
573 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
574 SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]);
halcanary96fcdcc2015-08-27 07:41:13 -0700575 if (nullptr == set) {
bungeman8d84c992014-07-24 08:05:09 -0700576 continue;
577 }
578 SkTypeface* tf = set->matchStyle(SkFontStyle());
halcanary96fcdcc2015-08-27 07:41:13 -0700579 if (nullptr == tf) {
bungeman8d84c992014-07-24 08:05:09 -0700580 continue;
581 }
582 fDefaultFamily = set;
583 fDefaultTypeface = tf;
584 break;
585 }
halcanary96fcdcc2015-08-27 07:41:13 -0700586 if (nullptr == fDefaultTypeface) {
bungeman8d84c992014-07-24 08:05:09 -0700587 fDefaultFamily = fFontStyleSets[0];
588 fDefaultTypeface = fDefaultFamily->createTypeface(0);
589 }
590 SkASSERT(fDefaultFamily);
591 SkASSERT(fDefaultTypeface);
592 }
593
594 typedef SkFontMgr INHERITED;
595};
596
bungeman7fa87cd2015-02-06 07:59:19 -0800597#ifdef SK_DEBUG
598static char const * const gSystemFontUseStrings[] = {
599 "OnlyCustom", "PreferCustom", "PreferSystem"
600};
601#endif
602SkFontMgr* SkFontMgr_New_Android(const SkFontMgr_Android_CustomFonts* custom) {
603 if (custom) {
604 SkASSERT(0 <= custom->fSystemFontUse);
605 SkASSERT(custom->fSystemFontUse < SK_ARRAY_COUNT(gSystemFontUseStrings));
606 SkDEBUGF(("SystemFontUse: %s BasePath: %s Fonts: %s FallbackFonts: %s\n",
607 gSystemFontUseStrings[custom->fSystemFontUse],
608 custom->fBasePath,
609 custom->fFontsXml,
610 custom->fFallbackFontsXml));
bungeman4e3523c2014-08-08 12:06:51 -0700611 }
612
halcanary385fe4d2015-08-26 13:07:48 -0700613 return new SkFontMgr_Android(custom);
bungeman8d84c992014-07-24 08:05:09 -0700614}