blob: 6518b2aa46671ebf6818d21783938d696d289fb7 [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 }
Ben Wagner9f0d8c22018-11-15 17:14:41 -0500181 fFallbackFor = family.fFallbackFor;
182
bungeman8d84c992014-07-24 08:05:09 -0700183 // TODO? make this lazy
tomhudsond3ddea22014-08-11 11:28:00 -0700184 for (int i = 0; i < family.fFonts.count(); ++i) {
185 const FontFileInfo& fontFile = family.fFonts[i];
bungeman8d84c992014-07-24 08:05:09 -0700186
bungeman7fa87cd2015-02-06 07:59:19 -0800187 SkString pathName(family.fBasePath);
188 pathName.append(fontFile.fFileName);
bungeman8d84c992014-07-24 08:05:09 -0700189
bungemanf93d7112016-09-16 06:24:20 -0700190 std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(pathName.c_str());
191 if (!stream) {
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400192 SkDEBUGF("Requested font file %s does not exist or cannot be opened.\n",
193 pathName.c_str());
bungeman8d84c992014-07-24 08:05:09 -0700194 continue;
195 }
196
bungeman65fcd3d2014-08-06 11:12:20 -0700197 const int ttcIndex = fontFile.fIndex;
198 SkString familyName;
bungemana4c4a2d2014-10-20 13:33:19 -0700199 SkFontStyle style;
bungeman8d84c992014-07-24 08:05:09 -0700200 bool isFixedWidth;
bungeman41868fe2015-05-20 09:21:04 -0700201 Scanner::AxisDefinitions axisDefinitions;
202 if (!scanner.scanFont(stream.get(), ttcIndex,
203 &familyName, &style, &isFixedWidth, &axisDefinitions))
204 {
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400205 SkDEBUGF("Requested font file %s exists, but is not a valid font.\n",
206 pathName.c_str());
bungeman8d84c992014-07-24 08:05:09 -0700207 continue;
208 }
209
bungemane85a7542015-04-17 13:51:08 -0700210 int weight = fontFile.fWeight != 0 ? fontFile.fWeight : style.weight();
211 SkFontStyle::Slant slant = style.slant();
212 switch (fontFile.fStyle) {
213 case FontFileInfo::Style::kAuto: slant = style.slant(); break;
214 case FontFileInfo::Style::kNormal: slant = SkFontStyle::kUpright_Slant; break;
215 case FontFileInfo::Style::kItalic: slant = SkFontStyle::kItalic_Slant; break;
216 default: SkASSERT(false); break;
bungeman4b86bac2014-11-04 10:54:31 -0800217 }
bungemane85a7542015-04-17 13:51:08 -0700218 style = SkFontStyle(weight, style.width(), slant);
bungeman4b86bac2014-11-04 10:54:31 -0800219
djsollen3b625542014-08-14 06:29:02 -0700220 uint32_t variant = family.fVariant;
221 if (kDefault_FontVariant == variant) {
222 variant = kCompact_FontVariant | kElegant_FontVariant;
bungeman65fcd3d2014-08-06 11:12:20 -0700223 }
224
225 // The first specified family name overrides the family name found in the font.
226 // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return
227 // all of the specified family names in addition to the names found in the font.
halcanary96fcdcc2015-08-27 07:41:13 -0700228 if (cannonicalFamilyName != nullptr) {
bungeman65fcd3d2014-08-06 11:12:20 -0700229 familyName = *cannonicalFamilyName;
230 }
231
bungeman41868fe2015-05-20 09:21:04 -0700232 SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
Ben Wagnerfc497342017-02-24 11:15:26 -0500233 SkFontArguments::VariationPosition position = {
234 fontFile.fVariationDesignPosition.begin(),
235 fontFile.fVariationDesignPosition.count()
236 };
237 Scanner::computeAxisValues(axisDefinitions, position,
bungeman47a1e962016-02-25 11:20:01 -0800238 axisValues, familyName);
bungeman41868fe2015-05-20 09:21:04 -0700239
bungemanf6c71072016-01-21 14:17:47 -0800240 fStyles.push_back().reset(new SkTypeface_AndroidSystem(
khushalsagarebc465b2016-02-12 12:42:48 -0800241 pathName, cacheFontFiles, ttcIndex, axisValues.get(), axisDefinitions.count(),
Ben Wagneraee878d2017-08-10 13:49:41 -0400242 style, isFixedWidth, familyName, family.fLanguages, variant));
bungeman8d84c992014-07-24 08:05:09 -0700243 }
244 }
245
mtklein36352bf2015-03-25 18:17:31 -0700246 int count() override {
bungeman8d84c992014-07-24 08:05:09 -0700247 return fStyles.count();
248 }
mtklein36352bf2015-03-25 18:17:31 -0700249 void getStyle(int index, SkFontStyle* style, SkString* name) override {
bungeman8d84c992014-07-24 08:05:09 -0700250 if (index < 0 || fStyles.count() <= index) {
251 return;
252 }
253 if (style) {
bungeman03675682016-08-18 14:36:02 -0700254 *style = fStyles[index]->fontStyle();
bungeman8d84c992014-07-24 08:05:09 -0700255 }
256 if (name) {
257 name->reset();
258 }
259 }
mtklein36352bf2015-03-25 18:17:31 -0700260 SkTypeface_AndroidSystem* createTypeface(int index) override {
bungeman8d84c992014-07-24 08:05:09 -0700261 if (index < 0 || fStyles.count() <= index) {
halcanary96fcdcc2015-08-27 07:41:13 -0700262 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700263 }
264 return SkRef(fStyles[index].get());
265 }
266
mtklein36352bf2015-03-25 18:17:31 -0700267 SkTypeface_AndroidSystem* matchStyle(const SkFontStyle& pattern) override {
bungeman03675682016-08-18 14:36:02 -0700268 return static_cast<SkTypeface_AndroidSystem*>(this->matchStyleCSS3(pattern));
bungeman8d84c992014-07-24 08:05:09 -0700269 }
270
271private:
Brian Salomon343553a2018-09-05 15:41:23 -0400272 SkTArray<sk_sp<SkTypeface_AndroidSystem>> fStyles;
Ben Wagner9f0d8c22018-11-15 17:14:41 -0500273 SkString fFallbackFor;
bungeman8d84c992014-07-24 08:05:09 -0700274
275 friend struct NameToFamily;
276 friend class SkFontMgr_Android;
277
278 typedef SkFontStyleSet INHERITED;
279};
280
281/** On Android a single family can have many names, but our API assumes unique names.
282 * Map names to the back end so that all names for a given family refer to the same
283 * (non-replicated) set of typefaces.
284 * SkTDict<> doesn't let us do index-based lookup, so we write our own mapping.
285 */
286struct NameToFamily {
287 SkString name;
288 SkFontStyleSet_Android* styleSet;
289};
290
291class SkFontMgr_Android : public SkFontMgr {
292public:
bungeman7fa87cd2015-02-06 07:59:19 -0800293 SkFontMgr_Android(const SkFontMgr_Android_CustomFonts* custom) {
294 SkTDArray<FontFamily*> families;
295 if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem != custom->fSystemFontUse) {
296 SkString base(custom->fBasePath);
bungemanc5308542015-06-23 13:25:46 -0700297 SkFontMgr_Android_Parser::GetCustomFontFamilies(
298 families, base, custom->fFontsXml, custom->fFallbackFontsXml);
bungeman7fa87cd2015-02-06 07:59:19 -0800299 }
300 if (!custom ||
301 (custom && SkFontMgr_Android_CustomFonts::kOnlyCustom != custom->fSystemFontUse))
302 {
bungemanc5308542015-06-23 13:25:46 -0700303 SkFontMgr_Android_Parser::GetSystemFontFamilies(families);
bungeman7fa87cd2015-02-06 07:59:19 -0800304 }
305 if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem == custom->fSystemFontUse) {
306 SkString base(custom->fBasePath);
bungemanc5308542015-06-23 13:25:46 -0700307 SkFontMgr_Android_Parser::GetCustomFontFamilies(
308 families, base, custom->fFontsXml, custom->fFallbackFontsXml);
bungeman7fa87cd2015-02-06 07:59:19 -0800309 }
khushalsagarebc465b2016-02-12 12:42:48 -0800310 this->buildNameToFamilyMap(families, custom ? custom->fIsolated : false);
bungeman83b24ff2016-08-19 05:03:26 -0700311 this->findDefaultStyleSet();
bungeman7fa87cd2015-02-06 07:59:19 -0800312 families.deleteAll();
bungeman8d84c992014-07-24 08:05:09 -0700313 }
314
315protected:
316 /** Returns not how many families we have, but how many unique names
317 * exist among the families.
318 */
mtklein36352bf2015-03-25 18:17:31 -0700319 int onCountFamilies() const override {
bungeman8d84c992014-07-24 08:05:09 -0700320 return fNameToFamilyMap.count();
321 }
322
mtklein36352bf2015-03-25 18:17:31 -0700323 void onGetFamilyName(int index, SkString* familyName) const override {
bungeman8d84c992014-07-24 08:05:09 -0700324 if (index < 0 || fNameToFamilyMap.count() <= index) {
325 familyName->reset();
326 return;
327 }
328 familyName->set(fNameToFamilyMap[index].name);
329 }
330
mtklein36352bf2015-03-25 18:17:31 -0700331 SkFontStyleSet* onCreateStyleSet(int index) const override {
bungeman8d84c992014-07-24 08:05:09 -0700332 if (index < 0 || fNameToFamilyMap.count() <= index) {
halcanary96fcdcc2015-08-27 07:41:13 -0700333 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700334 }
335 return SkRef(fNameToFamilyMap[index].styleSet);
336 }
337
mtklein36352bf2015-03-25 18:17:31 -0700338 SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
bungeman8d84c992014-07-24 08:05:09 -0700339 if (!familyName) {
halcanary96fcdcc2015-08-27 07:41:13 -0700340 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700341 }
342 SkAutoAsciiToLC tolc(familyName);
343 for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
344 if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
345 return SkRef(fNameToFamilyMap[i].styleSet);
346 }
347 }
bungeman65fcd3d2014-08-06 11:12:20 -0700348 // TODO: eventually we should not need to name fallback families.
349 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
350 if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) {
351 return SkRef(fFallbackNameToFamilyMap[i].styleSet);
352 }
353 }
halcanary96fcdcc2015-08-27 07:41:13 -0700354 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700355 }
356
357 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
mtklein36352bf2015-03-25 18:17:31 -0700358 const SkFontStyle& style) const override {
Hal Canary67b39de2016-11-07 11:47:44 -0500359 sk_sp<SkFontStyleSet> sset(this->matchFamily(familyName));
bungeman8d84c992014-07-24 08:05:09 -0700360 return sset->matchStyle(style);
361 }
362
363 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
mtklein36352bf2015-03-25 18:17:31 -0700364 const SkFontStyle& style) const override {
bungeman83b24ff2016-08-19 05:03:26 -0700365 for (int i = 0; i < fStyleSets.count(); ++i) {
366 for (int j = 0; j < fStyleSets[i]->fStyles.count(); ++j) {
Hal Canary67b39de2016-11-07 11:47:44 -0500367 if (fStyleSets[i]->fStyles[j].get() == typeface) {
bungeman83b24ff2016-08-19 05:03:26 -0700368 return fStyleSets[i]->matchStyle(style);
bungeman8d84c992014-07-24 08:05:09 -0700369 }
370 }
371 }
halcanary96fcdcc2015-08-27 07:41:13 -0700372 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700373 }
374
bungeman13b9c952016-05-12 10:09:30 -0700375 static sk_sp<SkTypeface_AndroidSystem> find_family_style_character(
Ben Wagner9f0d8c22018-11-15 17:14:41 -0500376 const SkString& familyName,
bungeman83b24ff2016-08-19 05:03:26 -0700377 const SkTArray<NameToFamily, true>& fallbackNameToFamilyMap,
bungemanc9232dc2014-11-10 13:29:33 -0800378 const SkFontStyle& style, bool elegant,
379 const SkString& langTag, SkUnichar character)
380 {
381 for (int i = 0; i < fallbackNameToFamilyMap.count(); ++i) {
382 SkFontStyleSet_Android* family = fallbackNameToFamilyMap[i].styleSet;
Ben Wagner9f0d8c22018-11-15 17:14:41 -0500383 if (familyName != family->fFallbackFor) {
384 continue;
385 }
bungeman13b9c952016-05-12 10:09:30 -0700386 sk_sp<SkTypeface_AndroidSystem> face(family->matchStyle(style));
bungemanc20386e2014-10-23 07:08:05 -0700387
Ben Wagneraee878d2017-08-10 13:49:41 -0400388 if (!langTag.isEmpty() &&
389 std::none_of(face->fLang.begin(), face->fLang.end(), [&](SkLanguage lang){
390 return lang.getTag().startsWith(langTag.c_str());
391 }))
392 {
bungemanc9232dc2014-11-10 13:29:33 -0800393 continue;
394 }
395
396 if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) {
397 continue;
398 }
399
Mike Reed65528ab2019-01-02 13:44:39 -0500400 if (face->unicharToGlyph(character) != 0) {
bungeman13b9c952016-05-12 10:09:30 -0700401 return face;
scroggo9a9a7b22016-05-12 06:22:30 -0700402 }
bungemanc20386e2014-10-23 07:08:05 -0700403 }
halcanary96fcdcc2015-08-27 07:41:13 -0700404 return nullptr;
bungemanc20386e2014-10-23 07:08:05 -0700405 }
bungemanc9232dc2014-11-10 13:29:33 -0800406
bungeman65fcd3d2014-08-06 11:12:20 -0700407 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
408 const SkFontStyle& style,
bungemanc20386e2014-10-23 07:08:05 -0700409 const char* bcp47[],
410 int bcp47Count,
mtklein36352bf2015-03-25 18:17:31 -0700411 SkUnichar character) const override
bungeman65fcd3d2014-08-06 11:12:20 -0700412 {
413 // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascent/descent'.
414 // The variant 'default' means 'compact and elegant'.
415 // As a result, it is not possible to know the variant context from the font alone.
416 // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request.
417
Ben Wagner9f0d8c22018-11-15 17:14:41 -0500418 SkString familyNameString(familyName);
419 for (const SkString& currentFamilyName : { familyNameString, SkString() }) {
420 // The first time match anything elegant, second time anything not elegant.
421 for (int elegant = 2; elegant --> 0;) {
422 for (int bcp47Index = bcp47Count; bcp47Index --> 0;) {
423 SkLanguage lang(bcp47[bcp47Index]);
424 while (!lang.getTag().isEmpty()) {
425 sk_sp<SkTypeface_AndroidSystem> matchingTypeface =
426 find_family_style_character(currentFamilyName, fFallbackNameToFamilyMap,
427 style, SkToBool(elegant),
428 lang.getTag(), character);
429 if (matchingTypeface) {
430 return matchingTypeface.release();
431 }
bungeman65fcd3d2014-08-06 11:12:20 -0700432
Ben Wagner9f0d8c22018-11-15 17:14:41 -0500433 lang = lang.getParent();
434 }
bungeman65fcd3d2014-08-06 11:12:20 -0700435 }
Ben Wagner9f0d8c22018-11-15 17:14:41 -0500436 sk_sp<SkTypeface_AndroidSystem> matchingTypeface =
437 find_family_style_character(currentFamilyName, fFallbackNameToFamilyMap,
438 style, SkToBool(elegant),
439 SkString(), character);
440 if (matchingTypeface) {
441 return matchingTypeface.release();
442 }
bungemanc20386e2014-10-23 07:08:05 -0700443 }
bungeman65fcd3d2014-08-06 11:12:20 -0700444 }
halcanary96fcdcc2015-08-27 07:41:13 -0700445 return nullptr;
bungeman65fcd3d2014-08-06 11:12:20 -0700446 }
447
Mike Reed59227392017-09-26 09:46:08 -0400448 sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData> data, int ttcIndex) const override {
449 return this->makeFromStream(std::unique_ptr<SkStreamAsset>(new SkMemoryStream(std::move(data))),
450 ttcIndex);
bungeman8d84c992014-07-24 08:05:09 -0700451 }
452
Mike Reed59227392017-09-26 09:46:08 -0400453 sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override {
bungemanf93d7112016-09-16 06:24:20 -0700454 std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(path);
Mike Reed59227392017-09-26 09:46:08 -0400455 return stream.get() ? this->makeFromStream(std::move(stream), ttcIndex) : nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700456 }
457
Mike Reed59227392017-09-26 09:46:08 -0400458 sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,
459 int ttcIndex) const override {
bungeman8d84c992014-07-24 08:05:09 -0700460 bool isFixedPitch;
bungemana4c4a2d2014-10-20 13:33:19 -0700461 SkFontStyle style;
bungeman8d84c992014-07-24 08:05:09 -0700462 SkString name;
bungemanf93d7112016-09-16 06:24:20 -0700463 if (!fScanner.scanFont(stream.get(), ttcIndex, &name, &style, &isFixedPitch, nullptr)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700464 return nullptr;
bungeman8d84c992014-07-24 08:05:09 -0700465 }
bungemanf93d7112016-09-16 06:24:20 -0700466 auto data = skstd::make_unique<SkFontData>(std::move(stream), ttcIndex, nullptr, 0);
Mike Reed59227392017-09-26 09:46:08 -0400467 return sk_sp<SkTypeface>(new SkTypeface_AndroidStream(std::move(data),
468 style, isFixedPitch, name));
bungeman41868fe2015-05-20 09:21:04 -0700469 }
470
Mike Reed59227392017-09-26 09:46:08 -0400471 sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,
472 const SkFontArguments& args) const override {
bungemanf6c71072016-01-21 14:17:47 -0800473 using Scanner = SkTypeface_FreeType::Scanner;
bungemanf6c71072016-01-21 14:17:47 -0800474 bool isFixedPitch;
475 SkFontStyle style;
476 SkString name;
477 Scanner::AxisDefinitions axisDefinitions;
Ben Wagnerfc497342017-02-24 11:15:26 -0500478 if (!fScanner.scanFont(stream.get(), args.getCollectionIndex(),
bungemanf93d7112016-09-16 06:24:20 -0700479 &name, &style, &isFixedPitch, &axisDefinitions))
bungemanf6c71072016-01-21 14:17:47 -0800480 {
481 return nullptr;
482 }
483
bungemanf6c71072016-01-21 14:17:47 -0800484 SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
Ben Wagnerfc497342017-02-24 11:15:26 -0500485 Scanner::computeAxisValues(axisDefinitions, args.getVariationDesignPosition(),
486 axisValues, name);
bungemanf6c71072016-01-21 14:17:47 -0800487
Ben Wagnerfc497342017-02-24 11:15:26 -0500488 auto data = skstd::make_unique<SkFontData>(std::move(stream), args.getCollectionIndex(),
bungemanf93d7112016-09-16 06:24:20 -0700489 axisValues.get(), axisDefinitions.count());
Mike Reed59227392017-09-26 09:46:08 -0400490 return sk_sp<SkTypeface>(new SkTypeface_AndroidStream(std::move(data),
491 style, isFixedPitch, name));
bungemanf6c71072016-01-21 14:17:47 -0800492 }
493
Mike Reed59227392017-09-26 09:46:08 -0400494 sk_sp<SkTypeface> onMakeFromFontData(std::unique_ptr<SkFontData> data) const override {
bungeman41868fe2015-05-20 09:21:04 -0700495 SkStreamAsset* stream(data->getStream());
496 bool isFixedPitch;
497 SkFontStyle style;
498 SkString name;
halcanary96fcdcc2015-08-27 07:41:13 -0700499 if (!fScanner.scanFont(stream, data->getIndex(), &name, &style, &isFixedPitch, nullptr)) {
500 return nullptr;
bungeman41868fe2015-05-20 09:21:04 -0700501 }
Mike Reed59227392017-09-26 09:46:08 -0400502 return sk_sp<SkTypeface>(new SkTypeface_AndroidStream(std::move(data),
503 style, isFixedPitch, name));
bungeman8d84c992014-07-24 08:05:09 -0700504 }
505
Mike Reed59227392017-09-26 09:46:08 -0400506 sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle style) const override {
bsalomon49f085d2014-09-05 13:34:00 -0700507 if (familyName) {
halcanary96fcdcc2015-08-27 07:41:13 -0700508 // On Android, we must return nullptr when we can't find the requested
bungeman8d84c992014-07-24 08:05:09 -0700509 // named typeface so that the system/app can provide their own recovery
510 // mechanism. On other platforms we'd provide a typeface from the
511 // default family instead.
Mike Reed59227392017-09-26 09:46:08 -0400512 return sk_sp<SkTypeface>(this->onMatchFamilyStyle(familyName, style));
bungeman8d84c992014-07-24 08:05:09 -0700513 }
Mike Reed59227392017-09-26 09:46:08 -0400514 return sk_sp<SkTypeface>(fDefaultStyleSet->matchStyle(style));
bungeman8d84c992014-07-24 08:05:09 -0700515 }
516
517
518private:
519
bungeman14df8332014-10-28 15:07:23 -0700520 SkTypeface_FreeType::Scanner fScanner;
521
Brian Salomon343553a2018-09-05 15:41:23 -0400522 SkTArray<sk_sp<SkFontStyleSet_Android>> fStyleSets;
bungeman83b24ff2016-08-19 05:03:26 -0700523 sk_sp<SkFontStyleSet> fDefaultStyleSet;
bungeman8d84c992014-07-24 08:05:09 -0700524
bungeman83b24ff2016-08-19 05:03:26 -0700525 SkTArray<NameToFamily, true> fNameToFamilyMap;
526 SkTArray<NameToFamily, true> fFallbackNameToFamilyMap;
bungeman8d84c992014-07-24 08:05:09 -0700527
Ben Wagner9f0d8c22018-11-15 17:14:41 -0500528 void addFamily(FontFamily& family, const bool isolated, int familyIndex) {
529 SkTArray<NameToFamily, true>* nameToFamily = &fNameToFamilyMap;
530 if (family.fIsFallbackFont) {
531 nameToFamily = &fFallbackNameToFamilyMap;
532
533 if (0 == family.fNames.count()) {
534 SkString& fallbackName = family.fNames.push_back();
535 fallbackName.printf("%.2x##fallback", familyIndex);
536 }
537 }
538
539 sk_sp<SkFontStyleSet_Android> newSet =
540 sk_make_sp<SkFontStyleSet_Android>(family, fScanner, isolated);
541 if (0 == newSet->count()) {
542 return;
543 }
544
545 for (const SkString& name : family.fNames) {
546 nameToFamily->emplace_back(NameToFamily{name, newSet.get()});
547 }
548 fStyleSets.emplace_back(std::move(newSet));
549 }
khushalsagarebc465b2016-02-12 12:42:48 -0800550 void buildNameToFamilyMap(SkTDArray<FontFamily*> families, const bool isolated) {
Ben Wagner9f0d8c22018-11-15 17:14:41 -0500551 int familyIndex = 0;
552 for (FontFamily* family : families) {
553 addFamily(*family, isolated, familyIndex++);
554 family->fallbackFamilies.foreach([this, isolated, &familyIndex]
555 (SkString, std::unique_ptr<FontFamily>* fallbackFamily) {
556 addFamily(*(*fallbackFamily).get(), isolated, familyIndex++);
bungeman65fcd3d2014-08-06 11:12:20 -0700557 }
Ben Wagner9f0d8c22018-11-15 17:14:41 -0500558 );
bungeman8d84c992014-07-24 08:05:09 -0700559 }
560 }
561
bungeman83b24ff2016-08-19 05:03:26 -0700562 void findDefaultStyleSet() {
563 SkASSERT(!fStyleSets.empty());
bungeman8d84c992014-07-24 08:05:09 -0700564
bungeman83b24ff2016-08-19 05:03:26 -0700565 static const char* defaultNames[] = { "sans-serif" };
566 for (const char* defaultName : defaultNames) {
567 fDefaultStyleSet.reset(this->onMatchFamily(defaultName));
568 if (fDefaultStyleSet) {
569 break;
bungeman8d84c992014-07-24 08:05:09 -0700570 }
bungeman8d84c992014-07-24 08:05:09 -0700571 }
bungeman83b24ff2016-08-19 05:03:26 -0700572 if (nullptr == fDefaultStyleSet) {
573 fDefaultStyleSet = fStyleSets[0];
bungeman8d84c992014-07-24 08:05:09 -0700574 }
bungeman83b24ff2016-08-19 05:03:26 -0700575 SkASSERT(fDefaultStyleSet);
bungeman8d84c992014-07-24 08:05:09 -0700576 }
577
578 typedef SkFontMgr INHERITED;
579};
580
bungeman7fa87cd2015-02-06 07:59:19 -0800581#ifdef SK_DEBUG
582static char const * const gSystemFontUseStrings[] = {
583 "OnlyCustom", "PreferCustom", "PreferSystem"
584};
585#endif
Ben Wagner20d031a2017-01-11 13:54:39 -0500586
Ben Wagner3546ff12017-01-03 13:32:36 -0500587sk_sp<SkFontMgr> SkFontMgr_New_Android(const SkFontMgr_Android_CustomFonts* custom) {
bungeman7fa87cd2015-02-06 07:59:19 -0800588 if (custom) {
589 SkASSERT(0 <= custom->fSystemFontUse);
590 SkASSERT(custom->fSystemFontUse < SK_ARRAY_COUNT(gSystemFontUseStrings));
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400591 SkDEBUGF("SystemFontUse: %s BasePath: %s Fonts: %s FallbackFonts: %s\n",
592 gSystemFontUseStrings[custom->fSystemFontUse],
593 custom->fBasePath,
594 custom->fFontsXml,
595 custom->fFallbackFontsXml);
bungeman4e3523c2014-08-08 12:06:51 -0700596 }
Ben Wagner3546ff12017-01-03 13:32:36 -0500597 return sk_make_sp<SkFontMgr_Android>(custom);
bungeman8d84c992014-07-24 08:05:09 -0700598}