blob: feb22c82625cb872b6e733281eb2094480c1211f [file] [log] [blame]
bungeman8d84c992014-07-24 08:05:09 -07001/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
mtklein1ee76512015-11-02 10:20:27 -08008#include "SkTypes.h"
mtklein1ee76512015-11-02 10:20:27 -08009
khushalsagarebc465b2016-02-12 12:42:48 -080010#include "SkData.h"
bungemanf20488b2015-07-29 11:49:40 -070011#include "SkFixed.h"
bungeman8d84c992014-07-24 08:05:09 -070012#include "SkFontDescriptor.h"
13#include "SkFontHost_FreeType_common.h"
14#include "SkFontMgr.h"
bungeman7fa87cd2015-02-06 07:59:19 -080015#include "SkFontMgr_android.h"
bungemanc5308542015-06-23 13:25:46 -070016#include "SkFontMgr_android_parser.h"
bungeman8d84c992014-07-24 08:05:09 -070017#include "SkFontStyle.h"
bungemanf93d7112016-09-16 06:24:20 -070018#include "SkMakeUnique.h"
khushalsagarebc465b2016-02-12 12:42:48 -080019#include "SkOSFile.h"
bungeman24a104d2015-07-30 10:31:57 -070020#include "SkPaint.h"
bungemanf20488b2015-07-29 11:49:40 -070021#include "SkRefCnt.h"
22#include "SkString.h"
bungeman8d84c992014-07-24 08:05:09 -070023#include "SkStream.h"
bungemanf20488b2015-07-29 11:49:40 -070024#include "SkTArray.h"
bungeman8d84c992014-07-24 08:05:09 -070025#include "SkTDArray.h"
26#include "SkTSearch.h"
bungemanf20488b2015-07-29 11:49:40 -070027#include "SkTemplates.h"
bungeman8d84c992014-07-24 08:05:09 -070028#include "SkTypefaceCache.h"
29
Ben Wagneraee878d2017-08-10 13:49:41 -040030#include <algorithm>
bungeman8d84c992014-07-24 08:05:09 -070031#include <limits>
bungeman8d84c992014-07-24 08:05:09 -070032
bungemanf20488b2015-07-29 11:49:40 -070033class SkData;
34
bungeman8d84c992014-07-24 08:05:09 -070035class SkTypeface_Android : public SkTypeface_FreeType {
36public:
bungeman41868fe2015-05-20 09:21:04 -070037 SkTypeface_Android(const SkFontStyle& style,
bungeman8d84c992014-07-24 08:05:09 -070038 bool isFixedPitch,
bungeman4b86bac2014-11-04 10:54:31 -080039 const SkString& familyName)
bungemane3aea102016-07-13 05:16:58 -070040 : INHERITED(style, isFixedPitch)
bungeman41868fe2015-05-20 09:21:04 -070041 , fFamilyName(familyName)
42 { }
bungeman8d84c992014-07-24 08:05:09 -070043
bungeman8d84c992014-07-24 08:05:09 -070044protected:
mtklein36352bf2015-03-25 18:17:31 -070045 void onGetFamilyName(SkString* familyName) const override {
bungemanb374d6a2014-09-17 07:48:59 -070046 *familyName = fFamilyName;
47 }
48
bungeman8d84c992014-07-24 08:05:09 -070049 SkString fFamilyName;
50
51private:
52 typedef SkTypeface_FreeType INHERITED;
53};
54
55class SkTypeface_AndroidSystem : public SkTypeface_Android {
56public:
bungeman4b86bac2014-11-04 10:54:31 -080057 SkTypeface_AndroidSystem(const SkString& pathName,
khushalsagarebc465b2016-02-12 12:42:48 -080058 const bool cacheFontFiles,
bungeman8d84c992014-07-24 08:05:09 -070059 int index,
bungeman41868fe2015-05-20 09:21:04 -070060 const SkFixed* axes, int axesCount,
bungemana4c4a2d2014-10-20 13:33:19 -070061 const SkFontStyle& style,
bungeman8d84c992014-07-24 08:05:09 -070062 bool isFixedPitch,
bungeman4b86bac2014-11-04 10:54:31 -080063 const SkString& familyName,
Ben Wagneraee878d2017-08-10 13:49:41 -040064 const SkTArray<SkLanguage, true>& lang,
djsollen3b625542014-08-14 06:29:02 -070065 FontVariant variantStyle)
bungeman41868fe2015-05-20 09:21:04 -070066 : INHERITED(style, isFixedPitch, familyName)
bungeman65fcd3d2014-08-06 11:12:20 -070067 , fPathName(pathName)
bungeman41868fe2015-05-20 09:21:04 -070068 , fIndex(index)
69 , fAxes(axes, axesCount)
bungeman65fcd3d2014-08-06 11:12:20 -070070 , fLang(lang)
khushalsagarebc465b2016-02-12 12:42:48 -080071 , fVariantStyle(variantStyle)
72 , fFile(cacheFontFiles ? sk_fopen(fPathName.c_str(), kRead_SkFILE_Flag) : nullptr) {
73 if (cacheFontFiles) {
74 SkASSERT(fFile);
75 }
76 }
77
bungemanf93d7112016-09-16 06:24:20 -070078 std::unique_ptr<SkStreamAsset> makeStream() const {
khushalsagarebc465b2016-02-12 12:42:48 -080079 if (fFile) {
bungeman38d909e2016-08-02 14:40:46 -070080 sk_sp<SkData> data(SkData::MakeFromFILE(fFile));
bungemanf93d7112016-09-16 06:24:20 -070081 return data ? skstd::make_unique<SkMemoryStream>(std::move(data)) : nullptr;
khushalsagarebc465b2016-02-12 12:42:48 -080082 }
bungemanf93d7112016-09-16 06:24:20 -070083 return SkStream::MakeFromFile(fPathName.c_str());
khushalsagarebc465b2016-02-12 12:42:48 -080084 }
bungeman8d84c992014-07-24 08:05:09 -070085
bungeman41868fe2015-05-20 09:21:04 -070086 virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
bungeman8d84c992014-07-24 08:05:09 -070087 SkASSERT(desc);
88 SkASSERT(serialize);
89 desc->setFamilyName(fFamilyName.c_str());
bungemanb8113782016-07-25 16:54:59 -070090 desc->setStyle(this->fontStyle());
bungeman8d84c992014-07-24 08:05:09 -070091 *serialize = false;
92 }
mtklein36352bf2015-03-25 18:17:31 -070093 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
bungeman8d84c992014-07-24 08:05:09 -070094 *ttcIndex = fIndex;
bungemanf93d7112016-09-16 06:24:20 -070095 return this->makeStream().release();
bungeman8d84c992014-07-24 08:05:09 -070096 }
bungemanf93d7112016-09-16 06:24:20 -070097 std::unique_ptr<SkFontData> onMakeFontData() const override {
98 return skstd::make_unique<SkFontData>(this->makeStream(), fIndex,
99 fAxes.begin(), fAxes.count());
bungeman41868fe2015-05-20 09:21:04 -0700100 }
Bruce Wang37b61092018-06-20 16:43:02 -0400101 sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
102 std::unique_ptr<SkFontData> data = this->cloneFontData(args);
103 if (!data) {
104 return nullptr;
105 }
106 return sk_make_sp<SkTypeface_AndroidSystem>(fPathName,
107 fFile,
108 fIndex,
109 data->getAxis(),
110 data->getAxisCount(),
111 this->fontStyle(),
112 this->isFixedPitch(),
113 fFamilyName,
114 fLang,
115 fVariantStyle);
116 }
bungeman8d84c992014-07-24 08:05:09 -0700117
bungeman65fcd3d2014-08-06 11:12:20 -0700118 const SkString fPathName;
bungeman41868fe2015-05-20 09:21:04 -0700119 int fIndex;
120 const SkSTArray<4, SkFixed, true> fAxes;
Ben Wagneraee878d2017-08-10 13:49:41 -0400121 const SkSTArray<4, SkLanguage, true> fLang;
djsollen3b625542014-08-14 06:29:02 -0700122 const FontVariant fVariantStyle;
khushalsagarebc465b2016-02-12 12:42:48 -0800123 SkAutoTCallVProc<FILE, sk_fclose> fFile;
bungeman8d84c992014-07-24 08:05:09 -0700124
125 typedef SkTypeface_Android INHERITED;
126};
127
128class SkTypeface_AndroidStream : public SkTypeface_Android {
129public:
bungemanf93d7112016-09-16 06:24:20 -0700130 SkTypeface_AndroidStream(std::unique_ptr<SkFontData> data,
bungemana4c4a2d2014-10-20 13:33:19 -0700131 const SkFontStyle& style,
bungeman8d84c992014-07-24 08:05:09 -0700132 bool isFixedPitch,
bungeman4b86bac2014-11-04 10:54:31 -0800133 const SkString& familyName)
bungeman41868fe2015-05-20 09:21:04 -0700134 : INHERITED(style, isFixedPitch, familyName)
bungemanf93d7112016-09-16 06:24:20 -0700135 , fData(std::move(data))
bungeman41868fe2015-05-20 09:21:04 -0700136 { }
bungeman8d84c992014-07-24 08:05:09 -0700137
138 virtual void onGetFontDescriptor(SkFontDescriptor* desc,
mtklein36352bf2015-03-25 18:17:31 -0700139 bool* serialize) const override {
bungeman8d84c992014-07-24 08:05:09 -0700140 SkASSERT(desc);
141 SkASSERT(serialize);
142 desc->setFamilyName(fFamilyName.c_str());
bungeman8d84c992014-07-24 08:05:09 -0700143 *serialize = true;
144 }
145
mtklein36352bf2015-03-25 18:17:31 -0700146 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
bungeman41868fe2015-05-20 09:21:04 -0700147 *ttcIndex = fData->getIndex();
Mike Reed98c5d922017-09-15 21:39:47 -0400148 return fData->getStream()->duplicate().release();
bungeman41868fe2015-05-20 09:21:04 -0700149 }
150
bungemanf93d7112016-09-16 06:24:20 -0700151 std::unique_ptr<SkFontData> onMakeFontData() const override {
152 return skstd::make_unique<SkFontData>(*fData);
bungeman8d84c992014-07-24 08:05:09 -0700153 }
154
Bruce Wangebf0cf52018-06-18 14:04:19 -0400155 sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
156 std::unique_ptr<SkFontData> data = this->cloneFontData(args);
157 if (!data) {
158 return nullptr;
159 }
160 return sk_make_sp<SkTypeface_AndroidStream>(std::move(data),
161 this->fontStyle(),
162 this->isFixedPitch(),
163 fFamilyName);
164 }
165
bungeman8d84c992014-07-24 08:05:09 -0700166private:
bungemanf93d7112016-09-16 06:24:20 -0700167 const std::unique_ptr<const SkFontData> fData;
bungeman8d84c992014-07-24 08:05:09 -0700168 typedef SkTypeface_Android INHERITED;
169};
170
bungeman8d84c992014-07-24 08:05:09 -0700171class SkFontStyleSet_Android : public SkFontStyleSet {
bungeman41868fe2015-05-20 09:21:04 -0700172 typedef SkTypeface_FreeType::Scanner Scanner;
173
bungeman8d84c992014-07-24 08:05:09 -0700174public:
khushalsagarebc465b2016-02-12 12:42:48 -0800175 explicit SkFontStyleSet_Android(const FontFamily& family, const Scanner& scanner,
176 const bool cacheFontFiles) {
halcanary96fcdcc2015-08-27 07:41:13 -0700177 const SkString* cannonicalFamilyName = nullptr;
bungeman65fcd3d2014-08-06 11:12:20 -0700178 if (family.fNames.count() > 0) {
179 cannonicalFamilyName = &family.fNames[0];
180 }
bungeman8d84c992014-07-24 08:05:09 -0700181 // TODO? make this lazy
tomhudsond3ddea22014-08-11 11:28:00 -0700182 for (int i = 0; i < family.fFonts.count(); ++i) {
183 const FontFileInfo& fontFile = family.fFonts[i];
bungeman8d84c992014-07-24 08:05:09 -0700184
bungeman7fa87cd2015-02-06 07:59:19 -0800185 SkString pathName(family.fBasePath);
186 pathName.append(fontFile.fFileName);
bungeman8d84c992014-07-24 08:05:09 -0700187
bungemanf93d7112016-09-16 06:24:20 -0700188 std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(pathName.c_str());
189 if (!stream) {
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400190 SkDEBUGF("Requested font file %s does not exist or cannot be opened.\n",
191 pathName.c_str());
bungeman8d84c992014-07-24 08:05:09 -0700192 continue;
193 }
194
bungeman65fcd3d2014-08-06 11:12:20 -0700195 const int ttcIndex = fontFile.fIndex;
196 SkString familyName;
bungemana4c4a2d2014-10-20 13:33:19 -0700197 SkFontStyle style;
bungeman8d84c992014-07-24 08:05:09 -0700198 bool isFixedWidth;
bungeman41868fe2015-05-20 09:21:04 -0700199 Scanner::AxisDefinitions axisDefinitions;
200 if (!scanner.scanFont(stream.get(), ttcIndex,
201 &familyName, &style, &isFixedWidth, &axisDefinitions))
202 {
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400203 SkDEBUGF("Requested font file %s exists, but is not a valid font.\n",
204 pathName.c_str());
bungeman8d84c992014-07-24 08:05:09 -0700205 continue;
206 }
207
bungemane85a7542015-04-17 13:51:08 -0700208 int weight = fontFile.fWeight != 0 ? fontFile.fWeight : style.weight();
209 SkFontStyle::Slant slant = style.slant();
210 switch (fontFile.fStyle) {
211 case FontFileInfo::Style::kAuto: slant = style.slant(); break;
212 case FontFileInfo::Style::kNormal: slant = SkFontStyle::kUpright_Slant; break;
213 case FontFileInfo::Style::kItalic: slant = SkFontStyle::kItalic_Slant; break;
214 default: SkASSERT(false); break;
bungeman4b86bac2014-11-04 10:54:31 -0800215 }
bungemane85a7542015-04-17 13:51:08 -0700216 style = SkFontStyle(weight, style.width(), slant);
bungeman4b86bac2014-11-04 10:54:31 -0800217
djsollen3b625542014-08-14 06:29:02 -0700218 uint32_t variant = family.fVariant;
219 if (kDefault_FontVariant == variant) {
220 variant = kCompact_FontVariant | kElegant_FontVariant;
bungeman65fcd3d2014-08-06 11:12:20 -0700221 }
222
223 // The first specified family name overrides the family name found in the font.
224 // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return
225 // all of the specified family names in addition to the names found in the font.
halcanary96fcdcc2015-08-27 07:41:13 -0700226 if (cannonicalFamilyName != nullptr) {
bungeman65fcd3d2014-08-06 11:12:20 -0700227 familyName = *cannonicalFamilyName;
228 }
229
bungeman41868fe2015-05-20 09:21:04 -0700230 SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
Ben Wagnerfc497342017-02-24 11:15:26 -0500231 SkFontArguments::VariationPosition position = {
232 fontFile.fVariationDesignPosition.begin(),
233 fontFile.fVariationDesignPosition.count()
234 };
235 Scanner::computeAxisValues(axisDefinitions, position,
bungeman47a1e962016-02-25 11:20:01 -0800236 axisValues, familyName);
bungeman41868fe2015-05-20 09:21:04 -0700237
bungemanf6c71072016-01-21 14:17:47 -0800238 fStyles.push_back().reset(new SkTypeface_AndroidSystem(
khushalsagarebc465b2016-02-12 12:42:48 -0800239 pathName, cacheFontFiles, ttcIndex, axisValues.get(), axisDefinitions.count(),
Ben Wagneraee878d2017-08-10 13:49:41 -0400240 style, isFixedWidth, familyName, family.fLanguages, variant));
bungeman8d84c992014-07-24 08:05:09 -0700241 }
242 }
243
mtklein36352bf2015-03-25 18:17:31 -0700244 int count() override {
bungeman8d84c992014-07-24 08:05:09 -0700245 return fStyles.count();
246 }
mtklein36352bf2015-03-25 18:17:31 -0700247 void getStyle(int index, SkFontStyle* style, SkString* name) override {
bungeman8d84c992014-07-24 08:05:09 -0700248 if (index < 0 || fStyles.count() <= index) {
249 return;
250 }
251 if (style) {
bungeman03675682016-08-18 14:36:02 -0700252 *style = fStyles[index]->fontStyle();
bungeman8d84c992014-07-24 08:05:09 -0700253 }
254 if (name) {
255 name->reset();
256 }
257 }
mtklein36352bf2015-03-25 18:17:31 -0700258 SkTypeface_AndroidSystem* createTypeface(int index) override {
bungeman8d84c992014-07-24 08:05:09 -0700259 if (index < 0 || fStyles.count() <= index) {
halcanary96fcdcc2015-08-27 07:41:13 -0700260 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700261 }
262 return SkRef(fStyles[index].get());
263 }
264
mtklein36352bf2015-03-25 18:17:31 -0700265 SkTypeface_AndroidSystem* matchStyle(const SkFontStyle& pattern) override {
bungeman03675682016-08-18 14:36:02 -0700266 return static_cast<SkTypeface_AndroidSystem*>(this->matchStyleCSS3(pattern));
bungeman8d84c992014-07-24 08:05:09 -0700267 }
268
269private:
Hal Canary67b39de2016-11-07 11:47:44 -0500270 SkTArray<sk_sp<SkTypeface_AndroidSystem>, true> fStyles;
bungeman8d84c992014-07-24 08:05:09 -0700271
272 friend struct NameToFamily;
273 friend class SkFontMgr_Android;
274
275 typedef SkFontStyleSet INHERITED;
276};
277
278/** On Android a single family can have many names, but our API assumes unique names.
279 * Map names to the back end so that all names for a given family refer to the same
280 * (non-replicated) set of typefaces.
281 * SkTDict<> doesn't let us do index-based lookup, so we write our own mapping.
282 */
283struct NameToFamily {
284 SkString name;
285 SkFontStyleSet_Android* styleSet;
286};
287
288class SkFontMgr_Android : public SkFontMgr {
289public:
bungeman7fa87cd2015-02-06 07:59:19 -0800290 SkFontMgr_Android(const SkFontMgr_Android_CustomFonts* custom) {
291 SkTDArray<FontFamily*> families;
292 if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem != custom->fSystemFontUse) {
293 SkString base(custom->fBasePath);
bungemanc5308542015-06-23 13:25:46 -0700294 SkFontMgr_Android_Parser::GetCustomFontFamilies(
295 families, base, custom->fFontsXml, custom->fFallbackFontsXml);
bungeman7fa87cd2015-02-06 07:59:19 -0800296 }
297 if (!custom ||
298 (custom && SkFontMgr_Android_CustomFonts::kOnlyCustom != custom->fSystemFontUse))
299 {
bungemanc5308542015-06-23 13:25:46 -0700300 SkFontMgr_Android_Parser::GetSystemFontFamilies(families);
bungeman7fa87cd2015-02-06 07:59:19 -0800301 }
302 if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem == custom->fSystemFontUse) {
303 SkString base(custom->fBasePath);
bungemanc5308542015-06-23 13:25:46 -0700304 SkFontMgr_Android_Parser::GetCustomFontFamilies(
305 families, base, custom->fFontsXml, custom->fFallbackFontsXml);
bungeman7fa87cd2015-02-06 07:59:19 -0800306 }
khushalsagarebc465b2016-02-12 12:42:48 -0800307 this->buildNameToFamilyMap(families, custom ? custom->fIsolated : false);
bungeman83b24ff2016-08-19 05:03:26 -0700308 this->findDefaultStyleSet();
bungeman7fa87cd2015-02-06 07:59:19 -0800309 families.deleteAll();
bungeman8d84c992014-07-24 08:05:09 -0700310 }
311
312protected:
313 /** Returns not how many families we have, but how many unique names
314 * exist among the families.
315 */
mtklein36352bf2015-03-25 18:17:31 -0700316 int onCountFamilies() const override {
bungeman8d84c992014-07-24 08:05:09 -0700317 return fNameToFamilyMap.count();
318 }
319
mtklein36352bf2015-03-25 18:17:31 -0700320 void onGetFamilyName(int index, SkString* familyName) const override {
bungeman8d84c992014-07-24 08:05:09 -0700321 if (index < 0 || fNameToFamilyMap.count() <= index) {
322 familyName->reset();
323 return;
324 }
325 familyName->set(fNameToFamilyMap[index].name);
326 }
327
mtklein36352bf2015-03-25 18:17:31 -0700328 SkFontStyleSet* onCreateStyleSet(int index) const override {
bungeman8d84c992014-07-24 08:05:09 -0700329 if (index < 0 || fNameToFamilyMap.count() <= index) {
halcanary96fcdcc2015-08-27 07:41:13 -0700330 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700331 }
332 return SkRef(fNameToFamilyMap[index].styleSet);
333 }
334
mtklein36352bf2015-03-25 18:17:31 -0700335 SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
bungeman8d84c992014-07-24 08:05:09 -0700336 if (!familyName) {
halcanary96fcdcc2015-08-27 07:41:13 -0700337 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700338 }
339 SkAutoAsciiToLC tolc(familyName);
340 for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
341 if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
342 return SkRef(fNameToFamilyMap[i].styleSet);
343 }
344 }
bungeman65fcd3d2014-08-06 11:12:20 -0700345 // TODO: eventually we should not need to name fallback families.
346 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
347 if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) {
348 return SkRef(fFallbackNameToFamilyMap[i].styleSet);
349 }
350 }
halcanary96fcdcc2015-08-27 07:41:13 -0700351 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700352 }
353
354 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
mtklein36352bf2015-03-25 18:17:31 -0700355 const SkFontStyle& style) const override {
Hal Canary67b39de2016-11-07 11:47:44 -0500356 sk_sp<SkFontStyleSet> sset(this->matchFamily(familyName));
bungeman8d84c992014-07-24 08:05:09 -0700357 return sset->matchStyle(style);
358 }
359
360 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
mtklein36352bf2015-03-25 18:17:31 -0700361 const SkFontStyle& style) const override {
bungeman83b24ff2016-08-19 05:03:26 -0700362 for (int i = 0; i < fStyleSets.count(); ++i) {
363 for (int j = 0; j < fStyleSets[i]->fStyles.count(); ++j) {
Hal Canary67b39de2016-11-07 11:47:44 -0500364 if (fStyleSets[i]->fStyles[j].get() == typeface) {
bungeman83b24ff2016-08-19 05:03:26 -0700365 return fStyleSets[i]->matchStyle(style);
bungeman8d84c992014-07-24 08:05:09 -0700366 }
367 }
368 }
halcanary96fcdcc2015-08-27 07:41:13 -0700369 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700370 }
371
bungeman13b9c952016-05-12 10:09:30 -0700372 static sk_sp<SkTypeface_AndroidSystem> find_family_style_character(
bungeman83b24ff2016-08-19 05:03:26 -0700373 const SkTArray<NameToFamily, true>& fallbackNameToFamilyMap,
bungemanc9232dc2014-11-10 13:29:33 -0800374 const SkFontStyle& style, bool elegant,
375 const SkString& langTag, SkUnichar character)
376 {
377 for (int i = 0; i < fallbackNameToFamilyMap.count(); ++i) {
378 SkFontStyleSet_Android* family = fallbackNameToFamilyMap[i].styleSet;
bungeman13b9c952016-05-12 10:09:30 -0700379 sk_sp<SkTypeface_AndroidSystem> face(family->matchStyle(style));
bungemanc20386e2014-10-23 07:08:05 -0700380
Ben Wagneraee878d2017-08-10 13:49:41 -0400381 if (!langTag.isEmpty() &&
382 std::none_of(face->fLang.begin(), face->fLang.end(), [&](SkLanguage lang){
383 return lang.getTag().startsWith(langTag.c_str());
384 }))
385 {
bungemanc9232dc2014-11-10 13:29:33 -0800386 continue;
387 }
388
389 if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) {
390 continue;
391 }
392
bungeman24a104d2015-07-30 10:31:57 -0700393 SkPaint paint;
394 paint.setTypeface(face);
395 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
396
397 uint16_t glyphID;
398 paint.textToGlyphs(&character, sizeof(character), &glyphID);
scroggo9a9a7b22016-05-12 06:22:30 -0700399 if (glyphID != 0) {
bungeman13b9c952016-05-12 10:09:30 -0700400 return face;
scroggo9a9a7b22016-05-12 06:22:30 -0700401 }
bungemanc20386e2014-10-23 07:08:05 -0700402 }
halcanary96fcdcc2015-08-27 07:41:13 -0700403 return nullptr;
bungemanc20386e2014-10-23 07:08:05 -0700404 }
bungemanc9232dc2014-11-10 13:29:33 -0800405
bungeman65fcd3d2014-08-06 11:12:20 -0700406 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
407 const SkFontStyle& style,
bungemanc20386e2014-10-23 07:08:05 -0700408 const char* bcp47[],
409 int bcp47Count,
mtklein36352bf2015-03-25 18:17:31 -0700410 SkUnichar character) const override
bungeman65fcd3d2014-08-06 11:12:20 -0700411 {
412 // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascent/descent'.
413 // The variant 'default' means 'compact and elegant'.
414 // As a result, it is not possible to know the variant context from the font alone.
415 // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request.
416
bungemanc20386e2014-10-23 07:08:05 -0700417 // The first time match anything elegant, second time anything not elegant.
418 for (int elegant = 2; elegant --> 0;) {
419 for (int bcp47Index = bcp47Count; bcp47Index --> 0;) {
420 SkLanguage lang(bcp47[bcp47Index]);
421 while (!lang.getTag().isEmpty()) {
bungeman13b9c952016-05-12 10:09:30 -0700422 sk_sp<SkTypeface_AndroidSystem> matchingTypeface =
bungemanc20386e2014-10-23 07:08:05 -0700423 find_family_style_character(fFallbackNameToFamilyMap,
424 style, SkToBool(elegant),
425 lang.getTag(), character);
426 if (matchingTypeface) {
bungeman13b9c952016-05-12 10:09:30 -0700427 return matchingTypeface.release();
bungeman65fcd3d2014-08-06 11:12:20 -0700428 }
429
bungemanc20386e2014-10-23 07:08:05 -0700430 lang = lang.getParent();
bungeman65fcd3d2014-08-06 11:12:20 -0700431 }
bungemanc20386e2014-10-23 07:08:05 -0700432 }
bungeman13b9c952016-05-12 10:09:30 -0700433 sk_sp<SkTypeface_AndroidSystem> matchingTypeface =
bungemanc20386e2014-10-23 07:08:05 -0700434 find_family_style_character(fFallbackNameToFamilyMap,
435 style, SkToBool(elegant),
436 SkString(), character);
437 if (matchingTypeface) {
bungeman13b9c952016-05-12 10:09:30 -0700438 return matchingTypeface.release();
bungemanc20386e2014-10-23 07:08:05 -0700439 }
bungeman65fcd3d2014-08-06 11:12:20 -0700440 }
halcanary96fcdcc2015-08-27 07:41:13 -0700441 return nullptr;
bungeman65fcd3d2014-08-06 11:12:20 -0700442 }
443
Mike Reed59227392017-09-26 09:46:08 -0400444 sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData> data, int ttcIndex) const override {
445 return this->makeFromStream(std::unique_ptr<SkStreamAsset>(new SkMemoryStream(std::move(data))),
446 ttcIndex);
bungeman8d84c992014-07-24 08:05:09 -0700447 }
448
Mike Reed59227392017-09-26 09:46:08 -0400449 sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override {
bungemanf93d7112016-09-16 06:24:20 -0700450 std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(path);
Mike Reed59227392017-09-26 09:46:08 -0400451 return stream.get() ? this->makeFromStream(std::move(stream), ttcIndex) : nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700452 }
453
Mike Reed59227392017-09-26 09:46:08 -0400454 sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,
455 int ttcIndex) const override {
bungeman8d84c992014-07-24 08:05:09 -0700456 bool isFixedPitch;
bungemana4c4a2d2014-10-20 13:33:19 -0700457 SkFontStyle style;
bungeman8d84c992014-07-24 08:05:09 -0700458 SkString name;
bungemanf93d7112016-09-16 06:24:20 -0700459 if (!fScanner.scanFont(stream.get(), ttcIndex, &name, &style, &isFixedPitch, nullptr)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700460 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700461 }
bungemanf93d7112016-09-16 06:24:20 -0700462 auto data = skstd::make_unique<SkFontData>(std::move(stream), ttcIndex, nullptr, 0);
Mike Reed59227392017-09-26 09:46:08 -0400463 return sk_sp<SkTypeface>(new SkTypeface_AndroidStream(std::move(data),
464 style, isFixedPitch, name));
bungeman41868fe2015-05-20 09:21:04 -0700465 }
466
Mike Reed59227392017-09-26 09:46:08 -0400467 sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,
468 const SkFontArguments& args) const override {
bungemanf6c71072016-01-21 14:17:47 -0800469 using Scanner = SkTypeface_FreeType::Scanner;
bungemanf6c71072016-01-21 14:17:47 -0800470 bool isFixedPitch;
471 SkFontStyle style;
472 SkString name;
473 Scanner::AxisDefinitions axisDefinitions;
Ben Wagnerfc497342017-02-24 11:15:26 -0500474 if (!fScanner.scanFont(stream.get(), args.getCollectionIndex(),
bungemanf93d7112016-09-16 06:24:20 -0700475 &name, &style, &isFixedPitch, &axisDefinitions))
bungemanf6c71072016-01-21 14:17:47 -0800476 {
477 return nullptr;
478 }
479
bungemanf6c71072016-01-21 14:17:47 -0800480 SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
Ben Wagnerfc497342017-02-24 11:15:26 -0500481 Scanner::computeAxisValues(axisDefinitions, args.getVariationDesignPosition(),
482 axisValues, name);
bungemanf6c71072016-01-21 14:17:47 -0800483
Ben Wagnerfc497342017-02-24 11:15:26 -0500484 auto data = skstd::make_unique<SkFontData>(std::move(stream), args.getCollectionIndex(),
bungemanf93d7112016-09-16 06:24:20 -0700485 axisValues.get(), axisDefinitions.count());
Mike Reed59227392017-09-26 09:46:08 -0400486 return sk_sp<SkTypeface>(new SkTypeface_AndroidStream(std::move(data),
487 style, isFixedPitch, name));
bungemanf6c71072016-01-21 14:17:47 -0800488 }
489
Mike Reed59227392017-09-26 09:46:08 -0400490 sk_sp<SkTypeface> onMakeFromFontData(std::unique_ptr<SkFontData> data) const override {
bungeman41868fe2015-05-20 09:21:04 -0700491 SkStreamAsset* stream(data->getStream());
492 bool isFixedPitch;
493 SkFontStyle style;
494 SkString name;
halcanary96fcdcc2015-08-27 07:41:13 -0700495 if (!fScanner.scanFont(stream, data->getIndex(), &name, &style, &isFixedPitch, nullptr)) {
496 return nullptr;
bungeman41868fe2015-05-20 09:21:04 -0700497 }
Mike Reed59227392017-09-26 09:46:08 -0400498 return sk_sp<SkTypeface>(new SkTypeface_AndroidStream(std::move(data),
499 style, isFixedPitch, name));
bungeman8d84c992014-07-24 08:05:09 -0700500 }
501
Mike Reed59227392017-09-26 09:46:08 -0400502 sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle style) const override {
bsalomon49f085d2014-09-05 13:34:00 -0700503 if (familyName) {
halcanary96fcdcc2015-08-27 07:41:13 -0700504 // On Android, we must return nullptr when we can't find the requested
bungeman8d84c992014-07-24 08:05:09 -0700505 // named typeface so that the system/app can provide their own recovery
506 // mechanism. On other platforms we'd provide a typeface from the
507 // default family instead.
Mike Reed59227392017-09-26 09:46:08 -0400508 return sk_sp<SkTypeface>(this->onMatchFamilyStyle(familyName, style));
bungeman8d84c992014-07-24 08:05:09 -0700509 }
Mike Reed59227392017-09-26 09:46:08 -0400510 return sk_sp<SkTypeface>(fDefaultStyleSet->matchStyle(style));
bungeman8d84c992014-07-24 08:05:09 -0700511 }
512
513
514private:
515
bungeman14df8332014-10-28 15:07:23 -0700516 SkTypeface_FreeType::Scanner fScanner;
517
bungeman83b24ff2016-08-19 05:03:26 -0700518 SkTArray<sk_sp<SkFontStyleSet_Android>, true> fStyleSets;
519 sk_sp<SkFontStyleSet> fDefaultStyleSet;
bungeman8d84c992014-07-24 08:05:09 -0700520
bungeman83b24ff2016-08-19 05:03:26 -0700521 SkTArray<NameToFamily, true> fNameToFamilyMap;
522 SkTArray<NameToFamily, true> fFallbackNameToFamilyMap;
bungeman8d84c992014-07-24 08:05:09 -0700523
khushalsagarebc465b2016-02-12 12:42:48 -0800524 void buildNameToFamilyMap(SkTDArray<FontFamily*> families, const bool isolated) {
bungeman8d84c992014-07-24 08:05:09 -0700525 for (int i = 0; i < families.count(); i++) {
bungeman65fcd3d2014-08-06 11:12:20 -0700526 FontFamily& family = *families[i];
527
bungeman83b24ff2016-08-19 05:03:26 -0700528 SkTArray<NameToFamily, true>* nameToFamily = &fNameToFamilyMap;
bungeman65fcd3d2014-08-06 11:12:20 -0700529 if (family.fIsFallbackFont) {
530 nameToFamily = &fFallbackNameToFamilyMap;
531
532 if (0 == family.fNames.count()) {
533 SkString& fallbackName = family.fNames.push_back();
534 fallbackName.printf("%.2x##fallback", i);
535 }
536 }
537
bungeman83b24ff2016-08-19 05:03:26 -0700538 sk_sp<SkFontStyleSet_Android> newSet =
539 sk_make_sp<SkFontStyleSet_Android>(family, fScanner, isolated);
bungeman65fcd3d2014-08-06 11:12:20 -0700540 if (0 == newSet->count()) {
bungeman65fcd3d2014-08-06 11:12:20 -0700541 continue;
542 }
bungeman65fcd3d2014-08-06 11:12:20 -0700543
bungeman83b24ff2016-08-19 05:03:26 -0700544 for (const SkString& name : family.fNames) {
545 nameToFamily->emplace_back(NameToFamily{name, newSet.get()});
bungeman8d84c992014-07-24 08:05:09 -0700546 }
bungeman83b24ff2016-08-19 05:03:26 -0700547 fStyleSets.emplace_back(std::move(newSet));
bungeman8d84c992014-07-24 08:05:09 -0700548 }
549 }
550
bungeman83b24ff2016-08-19 05:03:26 -0700551 void findDefaultStyleSet() {
552 SkASSERT(!fStyleSets.empty());
bungeman8d84c992014-07-24 08:05:09 -0700553
bungeman83b24ff2016-08-19 05:03:26 -0700554 static const char* defaultNames[] = { "sans-serif" };
555 for (const char* defaultName : defaultNames) {
556 fDefaultStyleSet.reset(this->onMatchFamily(defaultName));
557 if (fDefaultStyleSet) {
558 break;
bungeman8d84c992014-07-24 08:05:09 -0700559 }
bungeman8d84c992014-07-24 08:05:09 -0700560 }
bungeman83b24ff2016-08-19 05:03:26 -0700561 if (nullptr == fDefaultStyleSet) {
562 fDefaultStyleSet = fStyleSets[0];
bungeman8d84c992014-07-24 08:05:09 -0700563 }
bungeman83b24ff2016-08-19 05:03:26 -0700564 SkASSERT(fDefaultStyleSet);
bungeman8d84c992014-07-24 08:05:09 -0700565 }
566
567 typedef SkFontMgr INHERITED;
568};
569
bungeman7fa87cd2015-02-06 07:59:19 -0800570#ifdef SK_DEBUG
571static char const * const gSystemFontUseStrings[] = {
572 "OnlyCustom", "PreferCustom", "PreferSystem"
573};
574#endif
Ben Wagner20d031a2017-01-11 13:54:39 -0500575
Ben Wagner3546ff12017-01-03 13:32:36 -0500576sk_sp<SkFontMgr> SkFontMgr_New_Android(const SkFontMgr_Android_CustomFonts* custom) {
bungeman7fa87cd2015-02-06 07:59:19 -0800577 if (custom) {
578 SkASSERT(0 <= custom->fSystemFontUse);
579 SkASSERT(custom->fSystemFontUse < SK_ARRAY_COUNT(gSystemFontUseStrings));
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400580 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 }
Ben Wagner3546ff12017-01-03 13:32:36 -0500586 return sk_make_sp<SkFontMgr_Android>(custom);
bungeman8d84c992014-07-24 08:05:09 -0700587}