• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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  * 2021.9.9 SkFontMgr on previewer of ohos.
7  *           Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved.
8  */
9 
10 #include "src/ports/SkFontMgr_preview.h"
11 
12 #include "src/base/SkTSearch.h"
13 #include "include/private/base/SkTDArray.h"
14 #include "src/ports/SkFontScanner_FreeType_priv.h"
15 
SkFontMgr_Preview()16 SkFontMgr_Preview::SkFontMgr_Preview()
17 {
18     SkTDArray<FontFamily*> families;
19     SkFontMgr_Config_Parser::GetInstance().GetSystemFontFamilies(families);
20     this->buildNameToFamilyMap(families);
21     this->findDefaultStyleSet();
22     families.reset();
23 }
24 
onCountFamilies() const25 int SkFontMgr_Preview::onCountFamilies() const
26 {
27     return fNameToFamilyMap.size();
28 }
29 
onGetFamilyName(int index,SkString * familyName) const30 void SkFontMgr_Preview::onGetFamilyName(int index, SkString* familyName) const
31 {
32     if (index < 0 || fNameToFamilyMap.size() <= index) {
33         familyName->reset();
34         return;
35     }
36     familyName->set(fNameToFamilyMap[index].name);
37 }
38 
onCreateStyleSet(int index) const39 sk_sp<SkFontStyleSet> SkFontMgr_Preview::onCreateStyleSet(int index) const
40 {
41     if (index < 0 || fNameToFamilyMap.size() <= index) {
42         return nullptr;
43     }
44     return static_cast<sk_sp<SkFontStyleSet>>(SkRef(fNameToFamilyMap[index].styleSet));
45 }
46 
onMatchFamily(const char familyName[]) const47 sk_sp<SkFontStyleSet> SkFontMgr_Preview::onMatchFamily(const char familyName[]) const
48 {
49     if (!familyName) {
50         return nullptr;
51     }
52     SkAutoAsciiToLC tolc(familyName);
53     for (int i = 0; i < fNameToFamilyMap.size(); ++i) {
54         if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
55             return static_cast<sk_sp<SkFontStyleSet>>(SkRef(fNameToFamilyMap[i].styleSet));
56         }
57     }
58     // TODO: eventually we should not need to name fallback families.
59     for (int i = 0; i < fFallbackNameToFamilyMap.size(); ++i) {
60         if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) {
61             return static_cast<sk_sp<SkFontStyleSet>>(SkRef(fFallbackNameToFamilyMap[i].styleSet));
62         }
63     }
64     return nullptr;
65 }
66 
onMatchFamilyStyle(const char familyName[],const SkFontStyle & style) const67 sk_sp<SkTypeface> SkFontMgr_Preview::onMatchFamilyStyle(const char familyName[], const SkFontStyle& style) const
68 {
69     sk_sp<SkFontStyleSet> sset(this->matchFamily(familyName));
70     return sset->matchStyle(style);
71 }
72 
onMatchFaceStyle(const SkTypeface * typeface,const SkFontStyle & style) const73 sk_sp<SkTypeface> SkFontMgr_Preview::onMatchFaceStyle(const SkTypeface* typeface, const SkFontStyle& style) const
74 {
75     for (int i = 0; i < fStyleSets.size(); ++i) {
76         for (int j = 0; j < fStyleSets[i]->fStyles.size(); ++j) {
77             if (fStyleSets[i]->fStyles[j].get() == typeface) {
78                 return fStyleSets[i]->matchStyle(style);
79             }
80         }
81     }
82     return nullptr;
83 }
84 
find_family_style_character(const SkString & familyName,const skia_private::TArray<NameToFamily,true> & fallbackNameToFamilyMap,const SkFontStyle & style,bool elegant,const SkString & langTag,SkUnichar character)85 sk_sp<SkTypeface_PreviewSystem> SkFontMgr_Preview::find_family_style_character(
86     const SkString& familyName,
87     const skia_private::TArray<NameToFamily, true>& fallbackNameToFamilyMap,
88     const SkFontStyle& style, bool elegant,
89     const SkString& langTag, SkUnichar character)
90 {
91     for (int i = 0; i < fallbackNameToFamilyMap.size(); ++i) {
92         SkFontStyleSet_Preview* family = fallbackNameToFamilyMap[i].styleSet;
93         if (familyName != family->fFallbackFor) {
94             continue;
95         }
96         sk_sp<SkTypeface_PreviewSystem> face(static_cast<SkTypeface_PreviewSystem*>(SkRef(family->matchStyle(style).get())));
97 
98         if (!langTag.isEmpty() &&
99             std::none_of(face->fLang.begin(), face->fLang.end(), [&](SkLanguage lang) {
100                 return lang.getTag().startsWith(langTag.c_str()); })) {
101             continue;
102         }
103 
104         if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) {
105             continue;
106         }
107 
108         if (face->unicharToGlyph(character) != 0) {
109             return face;
110         }
111     }
112     return nullptr;
113 }
114 
onMatchFamilyStyleCharacter(const char familyName[],const SkFontStyle & style,const char * bcp47[],int bcp47Count,SkUnichar character) const115 sk_sp<SkTypeface> SkFontMgr_Preview::onMatchFamilyStyleCharacter(const char familyName[],
116                                                        const SkFontStyle& style,
117                                                        const char* bcp47[],
118                                                        int bcp47Count,
119                                                        SkUnichar character) const
120 {
121     // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascent/descent'.
122     // The variant 'default' means 'compact and elegant'.
123     // As a result, it is not possible to know the variant context from the font alone.
124     // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request.
125     SkString familyNameString(familyName);
126     for (const SkString& currentFamilyName : { familyNameString, SkString() }) {
127         // The first time match anything elegant, second time anything not elegant.
128         for (int elegant = 2; elegant-- > 0;) {
129             for (int bcp47Index = bcp47Count; bcp47Index-- > 0;) {
130                 SkLanguage lang(bcp47[bcp47Index]);
131                 while (!lang.getTag().isEmpty()) {
132                     sk_sp<SkTypeface_PreviewSystem> matchingTypeface =
133                         find_family_style_character(currentFamilyName, fFallbackNameToFamilyMap,
134                                                     style, SkToBool(elegant),
135                                                     lang.getTag(), character);
136                     if (matchingTypeface) {
137                         return static_cast<sk_sp<SkTypeface>>(matchingTypeface.release());
138                     }
139                     lang = lang.getParent();
140                 }
141             }
142             sk_sp<SkTypeface_PreviewSystem> matchingTypeface =
143                 find_family_style_character(currentFamilyName, fFallbackNameToFamilyMap,
144                                             style, SkToBool(elegant),
145                                             SkString(), character);
146             if (matchingTypeface) {
147                 return static_cast<sk_sp<SkTypeface>>(matchingTypeface.release());
148             }
149         }
150     }
151     return nullptr;
152 }
153 
onMakeFromData(sk_sp<SkData> data,int ttcIndex) const154 sk_sp<SkTypeface> SkFontMgr_Preview::onMakeFromData(sk_sp<SkData> data, int ttcIndex) const
155 {
156     return this->makeFromStream(std::unique_ptr<SkStreamAsset>(new SkMemoryStream(std::move(data))),
157                                 ttcIndex);
158 }
159 
onMakeFromFile(const char path[],int ttcIndex) const160 sk_sp<SkTypeface> SkFontMgr_Preview::onMakeFromFile(const char path[], int ttcIndex) const
161 {
162     std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(path);
163     return stream.get() ? this->makeFromStream(std::move(stream), ttcIndex) : nullptr;
164 }
165 
onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,int ttcIndex) const166 sk_sp<SkTypeface> SkFontMgr_Preview::onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream, int ttcIndex) const
167 {
168     bool isFixedPitch;
169     SkFontStyle style;
170     SkString name;
171     if (!fScanner.scanFont(stream.get(), ttcIndex, &name, &style, &isFixedPitch, nullptr)) {
172         return nullptr;
173     }
174     auto data = std::make_unique<SkFontData>(std::move(stream), ttcIndex, 0, nullptr, 0, nullptr, 0);
175     return sk_sp<SkTypeface>(new SkTypeface_PreviewStream(std::move(data), style, isFixedPitch, name));
176 }
177 
onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,const SkFontArguments & args) const178 sk_sp<SkTypeface> SkFontMgr_Preview::onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,
179                                                       const SkFontArguments& args) const
180 {
181     using Scanner = SkFontScanner_FreeType;
182     bool isFixedPitch;
183     SkFontStyle style;
184     SkString name;
185     Scanner::AxisDefinitions axisDefinitions;
186     if (!fScanner.scanFont(stream.get(), args.getCollectionIndex(),
187                            &name, &style, &isFixedPitch, &axisDefinitions)) {
188         return nullptr;
189     }
190     SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.size());
191     SkFontScanner::VariationPosition current;
192     const SkFontArguments::VariationPosition currentPos{current.data(), current.size()};
193     Scanner::computeAxisValues(axisDefinitions, currentPos, args.getVariationDesignPosition(),
194                                axisValues, name, &style);
195     auto data = std::make_unique<SkFontData>(std::move(stream), args.getCollectionIndex(), 0,
196                                              axisValues.get(), axisDefinitions.size(), nullptr, 0);
197     return sk_sp<SkTypeface>(new SkTypeface_PreviewStream(std::move(data), style, isFixedPitch, name));
198 }
199 
onLegacyMakeTypeface(const char familyName[],SkFontStyle style) const200 sk_sp<SkTypeface> SkFontMgr_Preview::onLegacyMakeTypeface(const char familyName[], SkFontStyle style) const
201 {
202     if (familyName) {
203         return sk_sp<SkTypeface>(this->onMatchFamilyStyle(familyName, style));
204     }
205     return sk_sp<SkTypeface>(fDefaultStyleSet->matchStyle(style));
206 }
207 
addFamily(FontFamily & family,int familyIndex)208 void SkFontMgr_Preview::addFamily(FontFamily& family, int familyIndex)
209 {
210     skia_private::TArray<NameToFamily, true>* nameToFamily = &fNameToFamilyMap;
211     if (family.fIsFallbackFont) {
212         nameToFamily = &fFallbackNameToFamilyMap;
213         if (0 == family.fNames.size()) {
214             SkString& fallbackName = family.fNames.push_back();
215             fallbackName.printf("%.2x##fallback", familyIndex);
216         }
217     }
218     sk_sp<SkFontStyleSet_Preview> newSet =
219         sk_make_sp<SkFontStyleSet_Preview>(family, fScanner);
220     if (0 == newSet->count()) {
221         return;
222     }
223     for (const SkString& name : family.fNames) {
224         nameToFamily->emplace_back(NameToFamily { name, newSet.get() });
225     }
226     fStyleSets.emplace_back(std::move(newSet));
227 }
228 
buildNameToFamilyMap(SkTDArray<FontFamily * > families)229 void SkFontMgr_Preview::buildNameToFamilyMap(SkTDArray<FontFamily*> families)
230 {
231     int familyIndex = 0;
232     for (FontFamily* family : families) {
233         addFamily(*family, familyIndex++);
234         family->fallbackFamilies.foreach([this, &familyIndex]
235             (SkString, std::unique_ptr<FontFamily>* fallbackFamily) {
236                 addFamily(*(*fallbackFamily).get(), familyIndex++);
237             }
238         );
239     }
240 }
241 
findDefaultStyleSet()242 void SkFontMgr_Preview::findDefaultStyleSet()
243 {
244     SkASSERT(!fStyleSets.empty());
245     static const char* defaultNames[] = { "sans-serif" };
246     for (const char* defaultName : defaultNames) {
247         fDefaultStyleSet = this->onMatchFamily(defaultName);
248         if (fDefaultStyleSet) {
249             break;
250         }
251     }
252     if (nullptr == fDefaultStyleSet) {
253         fDefaultStyleSet = fStyleSets[0];
254     }
255     SkASSERT(fDefaultStyleSet);
256 }
257 
SkFontMgr_New_Preview()258 sk_sp<SkFontMgr> SkFontMgr_New_Preview()
259 {
260     return sk_make_sp<SkFontMgr_Preview>();
261 }