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