• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/ports/SkFontMgr_fuchsia.h"
9 
10 #include <fuchsia/fonts/cpp/fidl.h>
11 #include <lib/zx/vmar.h>
12 #include <strings.h>
13 #include <memory>
14 #include <unordered_map>
15 
16 #include "src/core/SkFontDescriptor.h"
17 #include "src/ports/SkFontMgr_custom.h"
18 
19 #include "include/core/SkFontMgr.h"
20 #include "include/core/SkStream.h"
21 #include "include/core/SkTypeface.h"
22 #include "include/private/base/SkThreadAnnotations.h"
23 #include "src/core/SkTypefaceCache.h"
24 
25 using namespace skia_private;
26 
27 // SkFuchsiaFontDataCache keep track of SkData created from `fuchsia::mem::Buffer` where each buffer
28 // is identified with a unique identifier. It allows to share the same SkData instances between all
29 // SkTypeface instances created from the same buffer.
30 class SkFuchsiaFontDataCache : public SkRefCnt {
31 public:
32     SkFuchsiaFontDataCache() = default;
~SkFuchsiaFontDataCache()33     ~SkFuchsiaFontDataCache() { SkASSERT(fBuffers.empty()); }
34 
35     sk_sp<SkData> GetOrCreateSkData(int bufferId, const fuchsia::mem::Buffer& buffer);
36 
37 private:
38     struct ReleaseSkDataContext {
39         sk_sp<SkFuchsiaFontDataCache> fCache;
40         int fBufferId;
41     };
42 
43     static void ReleaseSkData(const void* buffer, void* context);
44     void OnBufferDeleted(int bufferId);
45 
46     SkMutex fMutex;
47     std::unordered_map<int, SkData*> fBuffers SK_GUARDED_BY(fMutex);
48 };
49 
GetOrCreateSkData(int bufferId,const fuchsia::mem::Buffer & buffer)50 sk_sp<SkData> SkFuchsiaFontDataCache::GetOrCreateSkData(int bufferId,
51                                                         const fuchsia::mem::Buffer& buffer) {
52     SkAutoMutexExclusive mutexLock(fMutex);
53 
54     auto iter = fBuffers.find(bufferId);
55     if (iter != fBuffers.end()) {
56         return sk_ref_sp(iter->second);
57     }
58     auto font_mgr = sk_ref_sp(this);
59 
60     uint64_t size = buffer.size;
61     uintptr_t mapped_addr = 0;
62     zx_status_t status =
63             zx::vmar::root_self()->map(ZX_VM_PERM_READ, 0, buffer.vmo, 0, size, &mapped_addr);
64     if (status != ZX_OK) return nullptr;
65 
66     auto context = new ReleaseSkDataContext{sk_ref_sp(this), bufferId};
67     auto data = SkData::MakeWithProc(
68             reinterpret_cast<void*>(mapped_addr), size, ReleaseSkData, context);
69     SkASSERT(data);
70 
71     fBuffers[bufferId] = data.get();
72     return data;
73 }
74 
OnBufferDeleted(int bufferId)75 void SkFuchsiaFontDataCache::OnBufferDeleted(int bufferId) {
76     zx_vaddr_t unmap_addr;
77     size_t unmap_size;
78     {
79         SkAutoMutexExclusive mutexLock(fMutex);
80         auto it = fBuffers.find(bufferId);
81         SkASSERT(it != fBuffers.end());
82         unmap_addr = reinterpret_cast<zx_vaddr_t>(it->second->data());
83         unmap_size = it->second->size();
84         fBuffers.erase(it);
85     }
86 
87     zx::vmar::root_self()->unmap(unmap_addr, unmap_size);
88 }
89 
90 // static
ReleaseSkData(const void * buffer,void * context)91 void SkFuchsiaFontDataCache::ReleaseSkData(const void* buffer, void* context) {
92     auto releaseSkDataContext = reinterpret_cast<ReleaseSkDataContext*>(context);
93     releaseSkDataContext->fCache->OnBufferDeleted(releaseSkDataContext->fBufferId);
94     delete releaseSkDataContext;
95 }
96 
SkToFuchsiaSlant(SkFontStyle::Slant slant)97 fuchsia::fonts::Slant SkToFuchsiaSlant(SkFontStyle::Slant slant) {
98     switch (slant) {
99         case SkFontStyle::kOblique_Slant:
100             return fuchsia::fonts::Slant::OBLIQUE;
101         case SkFontStyle::kItalic_Slant:
102             return fuchsia::fonts::Slant::ITALIC;
103         case SkFontStyle::kUpright_Slant:
104         default:
105             return fuchsia::fonts::Slant::UPRIGHT;
106     }
107 }
108 
FuchsiaToSkSlant(fuchsia::fonts::Slant slant)109 SkFontStyle::Slant FuchsiaToSkSlant(fuchsia::fonts::Slant slant) {
110     switch (slant) {
111         case fuchsia::fonts::Slant::OBLIQUE:
112             return SkFontStyle::kOblique_Slant;
113         case fuchsia::fonts::Slant::ITALIC:
114             return SkFontStyle::kItalic_Slant;
115         case fuchsia::fonts::Slant::UPRIGHT:
116         default:
117             return SkFontStyle::kUpright_Slant;
118     }
119 }
120 
SkToFuchsiaWidth(SkFontStyle::Width width)121 fuchsia::fonts::Width SkToFuchsiaWidth(SkFontStyle::Width width) {
122     switch (width) {
123         case SkFontStyle::Width::kUltraCondensed_Width:
124             return fuchsia::fonts::Width::ULTRA_CONDENSED;
125         case SkFontStyle::Width::kExtraCondensed_Width:
126             return fuchsia::fonts::Width::EXTRA_CONDENSED;
127         case SkFontStyle::Width::kCondensed_Width:
128             return fuchsia::fonts::Width::CONDENSED;
129         case SkFontStyle::Width::kSemiCondensed_Width:
130             return fuchsia::fonts::Width::SEMI_CONDENSED;
131         case SkFontStyle::Width::kNormal_Width:
132             return fuchsia::fonts::Width::NORMAL;
133         case SkFontStyle::Width::kSemiExpanded_Width:
134             return fuchsia::fonts::Width::SEMI_EXPANDED;
135         case SkFontStyle::Width::kExpanded_Width:
136             return fuchsia::fonts::Width::EXPANDED;
137         case SkFontStyle::Width::kExtraExpanded_Width:
138             return fuchsia::fonts::Width::EXTRA_EXPANDED;
139         case SkFontStyle::Width::kUltraExpanded_Width:
140             return fuchsia::fonts::Width::ULTRA_EXPANDED;
141     }
142 }
143 
144 // Tries to convert the given integer Skia style width value to the Fuchsia equivalent.
145 //
146 // On success, returns true. On failure, returns false, and `outFuchsiaWidth` is left untouched.
SkToFuchsiaWidth(int skWidth,fuchsia::fonts::Width * outFuchsiaWidth)147 bool SkToFuchsiaWidth(int skWidth, fuchsia::fonts::Width* outFuchsiaWidth) {
148     if (skWidth < SkFontStyle::Width::kUltraCondensed_Width ||
149         skWidth > SkFontStyle::Width::kUltraExpanded_Width) {
150         return false;
151     }
152     auto typedSkWidth = static_cast<SkFontStyle::Width>(skWidth);
153     *outFuchsiaWidth = SkToFuchsiaWidth(typedSkWidth);
154     return true;
155 }
156 
FuchsiaToSkWidth(fuchsia::fonts::Width width)157 SkFontStyle::Width FuchsiaToSkWidth(fuchsia::fonts::Width width) {
158     switch (width) {
159         case fuchsia::fonts::Width::ULTRA_CONDENSED:
160             return SkFontStyle::Width::kUltraCondensed_Width;
161         case fuchsia::fonts::Width::EXTRA_CONDENSED:
162             return SkFontStyle::Width::kExtraCondensed_Width;
163         case fuchsia::fonts::Width::CONDENSED:
164             return SkFontStyle::Width::kCondensed_Width;
165         case fuchsia::fonts::Width::SEMI_CONDENSED:
166             return SkFontStyle::Width::kSemiCondensed_Width;
167         case fuchsia::fonts::Width::NORMAL:
168             return SkFontStyle::Width::kNormal_Width;
169         case fuchsia::fonts::Width::SEMI_EXPANDED:
170             return SkFontStyle::Width::kSemiExpanded_Width;
171         case fuchsia::fonts::Width::EXPANDED:
172             return SkFontStyle::Width::kExpanded_Width;
173         case fuchsia::fonts::Width::EXTRA_EXPANDED:
174             return SkFontStyle::Width::kExtraExpanded_Width;
175         case fuchsia::fonts::Width::ULTRA_EXPANDED:
176             return SkFontStyle::Width::kUltraExpanded_Width;
177     }
178 }
179 
SkToFuchsiaStyle(const SkFontStyle & style)180 fuchsia::fonts::Style2 SkToFuchsiaStyle(const SkFontStyle& style) {
181     fuchsia::fonts::Style2 fuchsiaStyle;
182     fuchsiaStyle.set_slant(SkToFuchsiaSlant(style.slant())).set_weight(style.weight());
183 
184     fuchsia::fonts::Width fuchsiaWidth = fuchsia::fonts::Width::NORMAL;
185     if (SkToFuchsiaWidth(style.width(), &fuchsiaWidth)) {
186         fuchsiaStyle.set_width(fuchsiaWidth);
187     }
188 
189     return fuchsiaStyle;
190 }
191 
192 constexpr struct {
193     const char* fName;
194     fuchsia::fonts::GenericFontFamily fGenericFontFamily;
195 } kGenericFontFamiliesByName[] = {{"serif", fuchsia::fonts::GenericFontFamily::SERIF},
196                                   {"sans", fuchsia::fonts::GenericFontFamily::SANS_SERIF},
197                                   {"sans-serif", fuchsia::fonts::GenericFontFamily::SANS_SERIF},
198                                   {"mono", fuchsia::fonts::GenericFontFamily::MONOSPACE},
199                                   {"monospace", fuchsia::fonts::GenericFontFamily::MONOSPACE},
200                                   {"cursive", fuchsia::fonts::GenericFontFamily::CURSIVE},
201                                   {"fantasy", fuchsia::fonts::GenericFontFamily::FANTASY},
202                                   {"system-ui", fuchsia::fonts::GenericFontFamily::SYSTEM_UI},
203                                   {"emoji", fuchsia::fonts::GenericFontFamily::EMOJI},
204                                   {"math", fuchsia::fonts::GenericFontFamily::MATH},
205                                   {"fangsong", fuchsia::fonts::GenericFontFamily::FANGSONG}};
206 
207 // Tries to find a generic font family with the given name. If none is found, returns false.
GetGenericFontFamilyByName(const char * name,fuchsia::fonts::GenericFontFamily * outGenericFamily)208 bool GetGenericFontFamilyByName(const char* name,
209                                 fuchsia::fonts::GenericFontFamily* outGenericFamily) {
210     if (!name) return false;
211     for (auto& genericFamily : kGenericFontFamiliesByName) {
212         if (strcasecmp(genericFamily.fName, name) == 0) {
213             *outGenericFamily = genericFamily.fGenericFontFamily;
214             return true;
215         }
216     }
217     return false;
218 }
219 
220 struct TypefaceId {
221     uint32_t bufferId;
222     uint32_t ttcIndex;
223 
operator ==TypefaceId224     bool operator==(TypefaceId& other) {
225         return std::tie(bufferId, ttcIndex) == std::tie(other.bufferId, other.ttcIndex);
226     }
227 }
228 
229 constexpr kNullTypefaceId = {0xFFFFFFFF, 0xFFFFFFFF};
230 
231 class SkTypeface_Fuchsia : public SkTypeface_FreeTypeStream {
232 public:
SkTypeface_Fuchsia(std::unique_ptr<SkFontData> fontData,const SkFontStyle & style,bool isFixedPitch,const SkString familyName,TypefaceId id)233     SkTypeface_Fuchsia(std::unique_ptr<SkFontData> fontData, const SkFontStyle& style,
234                        bool isFixedPitch, const SkString familyName, TypefaceId id)
235             : SkTypeface_FreeTypeStream(std::move(fontData), familyName, style, isFixedPitch)
236             , fId(id) {}
237 
id()238     TypefaceId id() { return fId; }
239 
240 private:
241     TypefaceId fId;
242 };
243 
CreateTypefaceFromSkStream(std::unique_ptr<SkStreamAsset> stream,const SkFontArguments & args,TypefaceId id)244 sk_sp<SkTypeface> CreateTypefaceFromSkStream(std::unique_ptr<SkStreamAsset> stream,
245                                              const SkFontArguments& args, TypefaceId id) {
246     using Scanner = SkTypeface_FreeType::Scanner;
247     Scanner scanner;
248     bool isFixedPitch;
249     SkFontStyle style;
250     SkString name;
251     Scanner::AxisDefinitions axisDefinitions;
252     if (!scanner.scanFont(stream.get(), args.getCollectionIndex(), &name, &style, &isFixedPitch,
253                           &axisDefinitions)) {
254         return nullptr;
255     }
256 
257     const SkFontArguments::VariationPosition position = args.getVariationDesignPosition();
258     AutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.size());
259     Scanner::computeAxisValues(axisDefinitions, position, axisValues, name);
260 
261     auto fontData = std::make_unique<SkFontData>(
262         std::move(stream), args.getCollectionIndex(), args.getPalette().index,
263         axisValues.get(), axisDefinitions.size(),
264         args.getPalette().overrides, args.getPalette().overrideCount);
265     return sk_make_sp<SkTypeface_Fuchsia>(std::move(fontData), style, isFixedPitch, name, id);
266 }
267 
CreateTypefaceFromSkData(sk_sp<SkData> data,TypefaceId id)268 sk_sp<SkTypeface> CreateTypefaceFromSkData(sk_sp<SkData> data, TypefaceId id) {
269     return CreateTypefaceFromSkStream(std::make_unique<SkMemoryStream>(std::move(data)),
270                                       SkFontArguments().setCollectionIndex(id.ttcIndex), id);
271 }
272 
273 class SkFontMgr_Fuchsia final : public SkFontMgr {
274 public:
275     SkFontMgr_Fuchsia(fuchsia::fonts::ProviderSyncPtr provider);
276     ~SkFontMgr_Fuchsia() override;
277 
278 protected:
279     // SkFontMgr overrides.
280     int onCountFamilies() const override;
281     void onGetFamilyName(int index, SkString* familyName) const override;
282     SkFontStyleSet* onMatchFamily(const char familyName[]) const override;
283     SkFontStyleSet* onCreateStyleSet(int index) const override;
284     SkTypeface* onMatchFamilyStyle(const char familyName[], const SkFontStyle&) const override;
285     SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
286                                             const char* bcp47[], int bcp47Count,
287                                             SkUnichar character) const override;
288     sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int ttcIndex) const override;
289     sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>,
290                                             int ttcIndex) const override;
291     sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>,
292                                            const SkFontArguments&) const override;
293     sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override;
294     sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle) const override;
295 
296 private:
297     friend class SkFontStyleSet_Fuchsia;
298 
299     sk_sp<SkTypeface> FetchTypeface(const char familyName[], const SkFontStyle& style,
300                                     const char* bcp47[], int bcp47Count, SkUnichar character,
301                                     bool allow_fallback, bool exact_style_match) const;
302 
303     sk_sp<SkTypeface> GetOrCreateTypeface(TypefaceId id, const fuchsia::mem::Buffer& buffer) const;
304 
305     mutable fuchsia::fonts::ProviderSyncPtr fFontProvider;
306 
307     sk_sp<SkFuchsiaFontDataCache> fBufferCache;
308 
309     mutable SkMutex fCacheMutex;
310     mutable SkTypefaceCache fTypefaceCache SK_GUARDED_BY(fCacheMutex);
311 };
312 
313 class SkFontStyleSet_Fuchsia : public SkFontStyleSet {
314 public:
SkFontStyleSet_Fuchsia(sk_sp<SkFontMgr_Fuchsia> font_manager,std::string familyName,std::vector<SkFontStyle> styles)315     SkFontStyleSet_Fuchsia(sk_sp<SkFontMgr_Fuchsia> font_manager, std::string familyName,
316                  std::vector<SkFontStyle> styles)
317             : fFontManager(font_manager), fFamilyName(familyName), fStyles(styles) {}
318 
319     ~SkFontStyleSet_Fuchsia() override = default;
320 
count()321     int count() override { return fStyles.size(); }
322 
getStyle(int index,SkFontStyle * style,SkString * styleName)323     void getStyle(int index, SkFontStyle* style, SkString* styleName) override {
324         SkASSERT(index >= 0 && index < static_cast<int>(fStyles.size()));
325         if (style) *style = fStyles[index];
326 
327         // We don't have style names. Return an empty name.
328         if (styleName) styleName->reset();
329     }
330 
createTypeface(int index)331     SkTypeface* createTypeface(int index) override {
332         SkASSERT(index >= 0 && index < static_cast<int>(fStyles.size()));
333 
334         if (fTypefaces.empty()) fTypefaces.resize(fStyles.size());
335 
336         if (!fTypefaces[index]) {
337             fTypefaces[index] = fFontManager->FetchTypeface(
338                     fFamilyName.c_str(), fStyles[index], /*bcp47=*/nullptr,
339                     /*bcp47Count=*/0, /*character=*/0,
340                     /*allow_fallback=*/false, /*exact_style_match=*/true);
341         }
342 
343         return SkSafeRef(fTypefaces[index].get());
344     }
345 
matchStyle(const SkFontStyle & pattern)346     SkTypeface* matchStyle(const SkFontStyle& pattern) override { return matchStyleCSS3(pattern); }
347 
348 private:
349     sk_sp<SkFontMgr_Fuchsia> fFontManager;
350     std::string fFamilyName;
351     std::vector<SkFontStyle> fStyles;
352     std::vector<sk_sp<SkTypeface>> fTypefaces;
353 };
354 
SkFontMgr_Fuchsia(fuchsia::fonts::ProviderSyncPtr provider)355 SkFontMgr_Fuchsia::SkFontMgr_Fuchsia(fuchsia::fonts::ProviderSyncPtr provider)
356         : fFontProvider(std::move(provider)), fBufferCache(sk_make_sp<SkFuchsiaFontDataCache>()) {}
357 
358 SkFontMgr_Fuchsia::~SkFontMgr_Fuchsia() = default;
359 
onCountFamilies() const360 int SkFontMgr_Fuchsia::onCountFamilies() const {
361     // Family enumeration is not supported.
362     return 0;
363 }
364 
onGetFamilyName(int index,SkString * familyName) const365 void SkFontMgr_Fuchsia::onGetFamilyName(int index, SkString* familyName) const {
366     // Family enumeration is not supported.
367     familyName->reset();
368 }
369 
onCreateStyleSet(int index) const370 SkFontStyleSet* SkFontMgr_Fuchsia::onCreateStyleSet(int index) const {
371     // Family enumeration is not supported.
372     return nullptr;
373 }
374 
onMatchFamily(const char familyName[]) const375 SkFontStyleSet* SkFontMgr_Fuchsia::onMatchFamily(const char familyName[]) const {
376     fuchsia::fonts::FamilyName typedFamilyName;
377     typedFamilyName.name = familyName;
378 
379     fuchsia::fonts::FontFamilyInfo familyInfo;
380     int result = fFontProvider->GetFontFamilyInfo(typedFamilyName, &familyInfo);
381     if (result != ZX_OK || !familyInfo.has_styles() || familyInfo.styles().empty()) return nullptr;
382 
383     std::vector<SkFontStyle> styles;
384     for (auto& style : familyInfo.styles()) {
385         styles.push_back(SkFontStyle(style.weight(), FuchsiaToSkWidth(style.width()),
386                                      FuchsiaToSkSlant(style.slant())));
387     }
388 
389     return new SkFontStyleSet_Fuchsia(sk_ref_sp(this), familyInfo.name().name, std::move(styles));
390 }
391 
onMatchFamilyStyle(const char familyName[],const SkFontStyle & style) const392 SkTypeface* SkFontMgr_Fuchsia::onMatchFamilyStyle(const char familyName[],
393                                                   const SkFontStyle& style) const {
394     sk_sp<SkTypeface> typeface =
395             FetchTypeface(familyName, style, /*bcp47=*/nullptr,
396                           /*bcp47Count=*/0, /*character=*/0,
397                           /*allow_fallback=*/false, /*exact_style_match=*/false);
398     return typeface.release();
399 }
400 
onMatchFamilyStyleCharacter(const char familyName[],const SkFontStyle & style,const char * bcp47[],int bcp47Count,SkUnichar character) const401 SkTypeface* SkFontMgr_Fuchsia::onMatchFamilyStyleCharacter(const char familyName[],
402                                                            const SkFontStyle& style,
403                                                            const char* bcp47[], int bcp47Count,
404                                                            SkUnichar character) const {
405     sk_sp<SkTypeface> typeface =
406             FetchTypeface(familyName, style, bcp47, bcp47Count, character, /*allow_fallback=*/true,
407                           /*exact_style_match=*/false);
408     return typeface.release();
409 }
410 
onMakeFromData(sk_sp<SkData> data,int ttcIndex) const411 sk_sp<SkTypeface> SkFontMgr_Fuchsia::onMakeFromData(sk_sp<SkData> data, int ttcIndex) const {
412     return makeFromStream(std::make_unique<SkMemoryStream>(std::move(data)), ttcIndex);
413 }
414 
onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> asset,int ttcIndex) const415 sk_sp<SkTypeface> SkFontMgr_Fuchsia::onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> asset,
416                                                            int ttcIndex) const {
417     return makeFromStream(std::move(asset), SkFontArguments().setCollectionIndex(ttcIndex));
418 }
419 
onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> asset,const SkFontArguments & args) const420 sk_sp<SkTypeface> SkFontMgr_Fuchsia::onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> asset,
421                                                           const SkFontArguments& args) const {
422     return CreateTypefaceFromSkStream(std::move(asset), args, kNullTypefaceId);
423 }
424 
onMakeFromFile(const char path[],int ttcIndex) const425 sk_sp<SkTypeface> SkFontMgr_Fuchsia::onMakeFromFile(const char path[], int ttcIndex) const {
426     return makeFromStream(std::make_unique<SkFILEStream>(path), ttcIndex);
427 }
428 
onLegacyMakeTypeface(const char familyName[],SkFontStyle style) const429 sk_sp<SkTypeface> SkFontMgr_Fuchsia::onLegacyMakeTypeface(const char familyName[],
430                                                           SkFontStyle style) const {
431     return sk_sp<SkTypeface>(matchFamilyStyle(familyName, style));
432 }
433 
FetchTypeface(const char familyName[],const SkFontStyle & style,const char * bcp47[],int bcp47Count,SkUnichar character,bool allow_fallback,bool exact_style_match) const434 sk_sp<SkTypeface> SkFontMgr_Fuchsia::FetchTypeface(const char familyName[],
435                                                    const SkFontStyle& style, const char* bcp47[],
436                                                    int bcp47Count, SkUnichar character,
437                                                    bool allow_fallback,
438                                                    bool exact_style_match) const {
439     fuchsia::fonts::TypefaceQuery query;
440     query.set_style(SkToFuchsiaStyle(style));
441 
442     if (bcp47Count > 0) {
443         std::vector<fuchsia::intl::LocaleId> languages{};
444         for (int i = 0; i < bcp47Count; i++) {
445             fuchsia::intl::LocaleId localeId;
446             localeId.id = bcp47[i];
447             languages.push_back(localeId);
448         }
449         query.set_languages(std::move(languages));
450     }
451 
452     if (character) {
453         query.set_code_points({static_cast<uint32_t>(character)});
454     }
455 
456     // If family name is not specified or is a generic family name (e.g. "serif"), then enable
457     // fallback; otherwise, pass the family name as is.
458     fuchsia::fonts::GenericFontFamily genericFontFamily =
459             fuchsia::fonts::GenericFontFamily::SANS_SERIF;
460     bool isGenericFontFamily = GetGenericFontFamilyByName(familyName, &genericFontFamily);
461     if (!familyName || *familyName == '\0' || isGenericFontFamily) {
462         if (isGenericFontFamily) {
463             query.set_fallback_family(genericFontFamily);
464         }
465         allow_fallback = true;
466     } else {
467         fuchsia::fonts::FamilyName typedFamilyName{};
468         typedFamilyName.name = familyName;
469         query.set_family(typedFamilyName);
470     }
471 
472     fuchsia::fonts::TypefaceRequestFlags flags{};
473     if (!allow_fallback) flags |= fuchsia::fonts::TypefaceRequestFlags::EXACT_FAMILY;
474     if (exact_style_match) flags |= fuchsia::fonts::TypefaceRequestFlags::EXACT_STYLE;
475 
476     fuchsia::fonts::TypefaceRequest request;
477     request.set_query(std::move(query));
478     request.set_flags(flags);
479 
480     fuchsia::fonts::TypefaceResponse response;
481     int result = fFontProvider->GetTypeface(std::move(request), &response);
482     if (result != ZX_OK) return nullptr;
483 
484     // The service may return an empty response if there is no font matching the request.
485     if (response.IsEmpty()) return nullptr;
486 
487     return GetOrCreateTypeface(TypefaceId{response.buffer_id(), response.font_index()},
488                                response.buffer());
489 }
490 
FindByTypefaceId(SkTypeface * cachedTypeface,void * ctx)491 static bool FindByTypefaceId(SkTypeface* cachedTypeface, void* ctx) {
492     SkTypeface_Fuchsia* cachedFuchsiaTypeface = static_cast<SkTypeface_Fuchsia*>(cachedTypeface);
493     TypefaceId* id = static_cast<TypefaceId*>(ctx);
494 
495     return cachedFuchsiaTypeface->id() == *id;
496 }
497 
GetOrCreateTypeface(TypefaceId id,const fuchsia::mem::Buffer & buffer) const498 sk_sp<SkTypeface> SkFontMgr_Fuchsia::GetOrCreateTypeface(TypefaceId id,
499                                                          const fuchsia::mem::Buffer& buffer) const {
500     SkAutoMutexExclusive mutexLock(fCacheMutex);
501 
502     sk_sp<SkTypeface> cached = fTypefaceCache.findByProcAndRef(FindByTypefaceId, &id);
503     if (cached) return cached;
504 
505     sk_sp<SkData> data = fBufferCache->GetOrCreateSkData(id.bufferId, buffer);
506     if (!data) return nullptr;
507 
508     auto result = CreateTypefaceFromSkData(std::move(data), id);
509     fTypefaceCache.add(result);
510     return result;
511 }
512 
SkFontMgr_New_Fuchsia(fuchsia::fonts::ProviderSyncPtr provider)513 SK_API sk_sp<SkFontMgr> SkFontMgr_New_Fuchsia(fuchsia::fonts::ProviderSyncPtr provider) {
514     return sk_make_sp<SkFontMgr_Fuchsia>(std::move(provider));
515 }
516