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