Flutter Engine
The Flutter Engine
SkFontMgr_mac_ct.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2006 The Android Open Source Project
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
9#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
10
11#ifdef SK_BUILD_FOR_MAC
12#import <ApplicationServices/ApplicationServices.h>
13#endif
14
15#ifdef SK_BUILD_FOR_IOS
16#include <CoreText/CoreText.h>
17#include <CoreText/CTFontManager.h>
18#include <CoreGraphics/CoreGraphics.h>
19#include <CoreFoundation/CoreFoundation.h>
20#include <dlfcn.h>
21#endif
22
23#include "include/core/SkData.h"
36#include "src/base/SkUTF.h"
39
40#include <string.h>
41#include <memory>
42
43using namespace skia_private;
44
45#if (defined(SK_BUILD_FOR_IOS) && defined(__IPHONE_14_0) && \
46 __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_14_0) || \
47 (defined(SK_BUILD_FOR_MAC) && defined(__MAC_11_0) && \
48 __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_11_0)
49
50static uint32_t SkGetCoreTextVersion() {
51 // If compiling for iOS 14.0+ or macOS 11.0+, the CoreText version number
52 // must be derived from the OS version number.
53 static const uint32_t kCoreTextVersionNEWER = 0x000D0000;
54 return kCoreTextVersionNEWER;
55}
56
57#else
58
59static uint32_t SkGetCoreTextVersion() {
60 // Check for CoreText availability before calling CTGetCoreTextVersion().
61 static const bool kCoreTextIsAvailable = (&CTGetCoreTextVersion != nullptr);
62 if (kCoreTextIsAvailable) {
63 return CTGetCoreTextVersion();
64 }
65
66 // Default to a value that's smaller than any known CoreText version.
67 static const uint32_t kCoreTextVersionUNKNOWN = 0;
68 return kCoreTextVersionUNKNOWN;
69}
70
71#endif
72
73static SkUniqueCFRef<CFStringRef> make_CFString(const char s[]) {
74 return SkUniqueCFRef<CFStringRef>(CFStringCreateWithCString(nullptr, s, kCFStringEncodingUTF8));
75}
76
77/** Creates a typeface from a descriptor, searching the cache. */
78static sk_sp<SkTypeface> create_from_desc(CTFontDescriptorRef desc) {
79 SkUniqueCFRef<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc, 0, nullptr));
80 if (!ctFont) {
81 return nullptr;
82 }
83
84 return SkTypeface_Mac::Make(std::move(ctFont), OpszVariation(), nullptr);
85}
86
87static SkUniqueCFRef<CTFontDescriptorRef> create_descriptor(const char familyName[],
88 const SkFontStyle& style) {
89 SkUniqueCFRef<CFMutableDictionaryRef> cfAttributes(
90 CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
91 &kCFTypeDictionaryKeyCallBacks,
92 &kCFTypeDictionaryValueCallBacks));
93
94 SkUniqueCFRef<CFMutableDictionaryRef> cfTraits(
95 CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
96 &kCFTypeDictionaryKeyCallBacks,
97 &kCFTypeDictionaryValueCallBacks));
98
99 if (!cfAttributes || !cfTraits) {
100 return nullptr;
101 }
102
103 // TODO(crbug.com/1018581) Some CoreText versions have errant behavior when
104 // certain traits set. Temporary workaround to omit specifying trait for those
105 // versions.
106 // Long term solution will involve serializing typefaces instead of relying upon
107 // this to match between processes.
108 //
109 // Compare CoreText.h in an up to date SDK for where these values come from.
110 static const uint32_t kSkiaLocalCTVersionNumber10_14 = 0x000B0000;
111 static const uint32_t kSkiaLocalCTVersionNumber10_15 = 0x000C0000;
112
113 // CTFontTraits (symbolic)
114 // macOS 14 and iOS 12 seem to behave badly when kCTFontSymbolicTrait is set.
115 // macOS 15 yields LastResort font instead of a good default font when
116 // kCTFontSymbolicTrait is set.
117 if (SkGetCoreTextVersion() < kSkiaLocalCTVersionNumber10_14) {
118 CTFontSymbolicTraits ctFontTraits = 0;
119 if (style.weight() >= SkFontStyle::kBold_Weight) {
120 ctFontTraits |= kCTFontBoldTrait;
121 }
122 if (style.slant() != SkFontStyle::kUpright_Slant) {
123 ctFontTraits |= kCTFontItalicTrait;
124 }
125 SkUniqueCFRef<CFNumberRef> cfFontTraits(
126 CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTraits));
127 if (cfFontTraits) {
128 CFDictionaryAddValue(cfTraits.get(), kCTFontSymbolicTrait, cfFontTraits.get());
129 }
130 }
131
132 // CTFontTraits (weight)
133 CGFloat ctWeight = SkCTFontCTWeightForCSSWeight(style.weight());
134 SkUniqueCFRef<CFNumberRef> cfFontWeight(
135 CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctWeight));
136 if (cfFontWeight) {
137 CFDictionaryAddValue(cfTraits.get(), kCTFontWeightTrait, cfFontWeight.get());
138 }
139 // CTFontTraits (width)
140 CGFloat ctWidth = SkCTFontCTWidthForCSSWidth(style.width());
141 SkUniqueCFRef<CFNumberRef> cfFontWidth(
142 CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctWidth));
143 if (cfFontWidth) {
144 CFDictionaryAddValue(cfTraits.get(), kCTFontWidthTrait, cfFontWidth.get());
145 }
146 // CTFontTraits (slant)
147 // macOS 15 behaves badly when kCTFontSlantTrait is set.
148 if (SkGetCoreTextVersion() != kSkiaLocalCTVersionNumber10_15) {
149 CGFloat ctSlant = style.slant() == SkFontStyle::kUpright_Slant ? 0 : 1;
150 SkUniqueCFRef<CFNumberRef> cfFontSlant(
151 CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctSlant));
152 if (cfFontSlant) {
153 CFDictionaryAddValue(cfTraits.get(), kCTFontSlantTrait, cfFontSlant.get());
154 }
155 }
156 // CTFontTraits
157 CFDictionaryAddValue(cfAttributes.get(), kCTFontTraitsAttribute, cfTraits.get());
158
159 // CTFontFamilyName
160 if (familyName) {
161 SkUniqueCFRef<CFStringRef> cfFontName = make_CFString(familyName);
162 if (cfFontName) {
163 CFDictionaryAddValue(cfAttributes.get(), kCTFontFamilyNameAttribute, cfFontName.get());
164 }
165 }
166
167 return SkUniqueCFRef<CTFontDescriptorRef>(
168 CTFontDescriptorCreateWithAttributes(cfAttributes.get()));
169}
170
171// Same as the above function except style is included so we can
172// compare whether the created font conforms to the style. If not, we need
173// to recreate the font with symbolic traits. This is needed due to MacOS 10.11
174// font creation problem https://bugs.chromium.org/p/skia/issues/detail?id=8447.
175static sk_sp<SkTypeface> create_from_desc_and_style(CTFontDescriptorRef desc,
176 const SkFontStyle& style) {
177 SkUniqueCFRef<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc, 0, nullptr));
178 if (!ctFont) {
179 return nullptr;
180 }
181
182 const CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ctFont.get());
183 CTFontSymbolicTraits expected_traits = traits;
184 if (style.slant() != SkFontStyle::kUpright_Slant) {
185 expected_traits |= kCTFontItalicTrait;
186 }
187 if (style.weight() >= SkFontStyle::kBold_Weight) {
188 expected_traits |= kCTFontBoldTrait;
189 }
190
191 if (expected_traits != traits) {
192 SkUniqueCFRef<CTFontRef> ctNewFont(CTFontCreateCopyWithSymbolicTraits(
193 ctFont.get(), 0, nullptr, expected_traits, expected_traits));
194 if (ctNewFont) {
195 ctFont = std::move(ctNewFont);
196 }
197 }
198
199 return SkTypeface_Mac::Make(std::move(ctFont), OpszVariation(), nullptr);
200}
201
202/** Creates a typeface from a name, searching the cache. */
203static sk_sp<SkTypeface> create_from_name(const char familyName[], const SkFontStyle& style) {
204 SkUniqueCFRef<CTFontDescriptorRef> desc = create_descriptor(familyName, style);
205 if (!desc) {
206 return nullptr;
207 }
208 return create_from_desc_and_style(desc.get(), style);
209}
210
211static const char* map_css_names(const char* name) {
212 static const struct {
213 const char* fFrom; // name the caller specified
214 const char* fTo; // "canonical" name we map to
215 } gPairs[] = {
216 { "sans-serif", "Helvetica" },
217 { "serif", "Times" },
218 { "monospace", "Courier" }
219 };
220
221 for (size_t i = 0; i < std::size(gPairs); i++) {
222 if (strcmp(name, gPairs[i].fFrom) == 0) {
223 return gPairs[i].fTo;
224 }
225 }
226 return name; // no change
227}
228
229namespace {
230
231static bool find_desc_str(CTFontDescriptorRef desc, CFStringRef name, SkString* value) {
232 SkUniqueCFRef<CFStringRef> ref((CFStringRef)CTFontDescriptorCopyAttribute(desc, name));
233 if (!ref) {
234 return false;
235 }
236 SkStringFromCFString(ref.get(), value);
237 return true;
238}
239
240static inline int sqr(int value) {
241 SkASSERT(SkAbs32(value) < 0x7FFF); // check for overflow
242 return value * value;
243}
244
245// We normalize each axis (weight, width, italic) to be base-900
246static int compute_metric(const SkFontStyle& a, const SkFontStyle& b) {
247 return sqr(a.weight() - b.weight()) +
248 sqr((a.width() - b.width()) * 100) +
249 sqr((a.slant() != b.slant()) * 900);
250}
251
252static SkUniqueCFRef<CFSetRef> name_required() {
253 CFStringRef set_values[] = {kCTFontFamilyNameAttribute};
254 return SkUniqueCFRef<CFSetRef>(CFSetCreate(kCFAllocatorDefault,
255 reinterpret_cast<const void**>(set_values), std::size(set_values),
256 &kCFTypeSetCallBacks));
257}
258
259class SkFontStyleSet_Mac : public SkFontStyleSet {
260public:
261 SkFontStyleSet_Mac(CTFontDescriptorRef desc)
262 : fArray(CTFontDescriptorCreateMatchingFontDescriptors(desc, name_required().get()))
263 , fCount(0)
264 {
265 if (!fArray) {
266 fArray.reset(CFArrayCreate(nullptr, nullptr, 0, nullptr));
267 }
268 fCount = SkToInt(CFArrayGetCount(fArray.get()));
269 }
270
271 int count() override {
272 return fCount;
273 }
274
275 void getStyle(int index, SkFontStyle* style, SkString* name) override {
276 SkASSERT((unsigned)index < (unsigned)fCount);
277 CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), index);
278 if (style) {
279 *style = SkCTFontDescriptorGetSkFontStyle(desc, false);
280 }
281 if (name) {
282 if (!find_desc_str(desc, kCTFontStyleNameAttribute, name)) {
283 name->reset();
284 }
285 }
286 }
287
288 sk_sp<SkTypeface> createTypeface(int index) override {
289 SkASSERT((unsigned)index < (unsigned)CFArrayGetCount(fArray.get()));
290 CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), index);
291
292 return create_from_desc(desc);
293 }
294
295 sk_sp<SkTypeface> matchStyle(const SkFontStyle& pattern) override {
296 if (0 == fCount) {
297 return nullptr;
298 }
299 return create_from_desc(findMatchingDesc(pattern));
300 }
301
302private:
303 SkUniqueCFRef<CFArrayRef> fArray;
304 int fCount;
305
306 CTFontDescriptorRef findMatchingDesc(const SkFontStyle& pattern) const {
307 int bestMetric = SK_MaxS32;
308 CTFontDescriptorRef bestDesc = nullptr;
309
310 for (int i = 0; i < fCount; ++i) {
311 CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), i);
312 int metric = compute_metric(pattern, SkCTFontDescriptorGetSkFontStyle(desc, false));
313 if (0 == metric) {
314 return desc;
315 }
316 if (metric < bestMetric) {
317 bestMetric = metric;
318 bestDesc = desc;
319 }
320 }
321 SkASSERT(bestDesc);
322 return bestDesc;
323 }
324};
325
326SkUniqueCFRef<CFArrayRef> SkCopyAvailableFontFamilyNames(CTFontCollectionRef collection) {
327 // Create a CFArray of all available font descriptors.
328 SkUniqueCFRef<CFArrayRef> descriptors(
329 CTFontCollectionCreateMatchingFontDescriptors(collection));
330
331 // Copy the font family names of the font descriptors into a CFSet.
332 auto addDescriptorFamilyNameToSet = [](const void* value, void* context) -> void {
333 CTFontDescriptorRef descriptor = static_cast<CTFontDescriptorRef>(value);
334 CFMutableSetRef familyNameSet = static_cast<CFMutableSetRef>(context);
335 SkUniqueCFRef<CFTypeRef> familyName(
336 CTFontDescriptorCopyAttribute(descriptor, kCTFontFamilyNameAttribute));
337 if (familyName) {
338 CFSetAddValue(familyNameSet, familyName.get());
339 }
340 };
341 SkUniqueCFRef<CFMutableSetRef> familyNameSet(
342 CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks));
343 CFArrayApplyFunction(descriptors.get(), CFRangeMake(0, CFArrayGetCount(descriptors.get())),
344 addDescriptorFamilyNameToSet, familyNameSet.get());
345
346 // Get the set of family names into an array; this does not retain.
347 CFIndex count = CFSetGetCount(familyNameSet.get());
348 std::unique_ptr<const void*[]> familyNames(new const void*[count]);
349 CFSetGetValues(familyNameSet.get(), familyNames.get());
350
351 // Sort the array of family names (to match CTFontManagerCopyAvailableFontFamilyNames).
352 std::sort(familyNames.get(), familyNames.get() + count, [](const void* a, const void* b){
353 return CFStringCompare((CFStringRef)a, (CFStringRef)b, 0) == kCFCompareLessThan;
354 });
355
356 // Copy family names into a CFArray; this does retain.
357 return SkUniqueCFRef<CFArrayRef>(
358 CFArrayCreate(kCFAllocatorDefault, familyNames.get(), count, &kCFTypeArrayCallBacks));
359}
360
361/** Use CTFontManagerCopyAvailableFontFamilyNames if available, simulate if not. */
362SkUniqueCFRef<CFArrayRef> SkCTFontManagerCopyAvailableFontFamilyNames() {
363#ifdef SK_BUILD_FOR_IOS
364 using CTFontManagerCopyAvailableFontFamilyNamesProc = CFArrayRef (*)(void);
365 CTFontManagerCopyAvailableFontFamilyNamesProc ctFontManagerCopyAvailableFontFamilyNames;
366 *(void**)(&ctFontManagerCopyAvailableFontFamilyNames) =
367 dlsym(RTLD_DEFAULT, "CTFontManagerCopyAvailableFontFamilyNames");
368 if (ctFontManagerCopyAvailableFontFamilyNames) {
369 return SkUniqueCFRef<CFArrayRef>(ctFontManagerCopyAvailableFontFamilyNames());
370 }
371 SkUniqueCFRef<CTFontCollectionRef> collection(
372 CTFontCollectionCreateFromAvailableFonts(nullptr));
373 return SkUniqueCFRef<CFArrayRef>(SkCopyAvailableFontFamilyNames(collection.get()));
374#else
375 return SkUniqueCFRef<CFArrayRef>(CTFontManagerCopyAvailableFontFamilyNames());
376#endif
377}
378
379} // namespace
380
381class SkFontMgr_Mac : public SkFontMgr {
382 SkUniqueCFRef<CFArrayRef> fNames;
383 int fCount;
384
385 CFStringRef getFamilyNameAt(int index) const {
386 SkASSERT((unsigned)index < (unsigned)fCount);
387 return (CFStringRef)CFArrayGetValueAtIndex(fNames.get(), index);
388 }
389
390 static sk_sp<SkFontStyleSet> CreateSet(CFStringRef cfFamilyName) {
391 SkUniqueCFRef<CFMutableDictionaryRef> cfAttr(
392 CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
393 &kCFTypeDictionaryKeyCallBacks,
394 &kCFTypeDictionaryValueCallBacks));
395
396 CFDictionaryAddValue(cfAttr.get(), kCTFontFamilyNameAttribute, cfFamilyName);
397
398 SkUniqueCFRef<CTFontDescriptorRef> desc(
399 CTFontDescriptorCreateWithAttributes(cfAttr.get()));
400 return sk_sp<SkFontStyleSet>(new SkFontStyleSet_Mac(desc.get()));
401 }
402
403public:
404 SkUniqueCFRef<CTFontCollectionRef> fFontCollection;
405 SkFontMgr_Mac(CTFontCollectionRef fontCollection)
406 : fNames(fontCollection ? SkCopyAvailableFontFamilyNames(fontCollection)
407 : SkCTFontManagerCopyAvailableFontFamilyNames())
408 , fCount(fNames ? SkToInt(CFArrayGetCount(fNames.get())) : 0)
409 , fFontCollection(fontCollection ? (CTFontCollectionRef)CFRetain(fontCollection)
410 : CTFontCollectionCreateFromAvailableFonts(nullptr))
411 {}
412
413protected:
414 int onCountFamilies() const override {
415 return fCount;
416 }
417
418 void onGetFamilyName(int index, SkString* familyName) const override {
419 if ((unsigned)index < (unsigned)fCount) {
420 SkStringFromCFString(this->getFamilyNameAt(index), familyName);
421 } else {
422 familyName->reset();
423 }
424 }
425
426 sk_sp<SkFontStyleSet> onCreateStyleSet(int index) const override {
427 if ((unsigned)index >= (unsigned)fCount) {
428 return nullptr;
429 }
430 return CreateSet(this->getFamilyNameAt(index));
431 }
432
433 sk_sp<SkFontStyleSet> onMatchFamily(const char familyName[]) const override {
434 if (!familyName) {
435 return nullptr;
436 }
437 SkUniqueCFRef<CFStringRef> cfName = make_CFString(familyName);
438 return CreateSet(cfName.get());
439 }
440
441 sk_sp<SkTypeface> onMatchFamilyStyle(const char familyName[],
442 const SkFontStyle& style) const override {
443 SkUniqueCFRef<CTFontDescriptorRef> reqDesc = create_descriptor(familyName, style);
444 if (!familyName) {
445 return create_from_desc(reqDesc.get());
446 }
447 SkUniqueCFRef<CTFontDescriptorRef> resolvedDesc(
448 CTFontDescriptorCreateMatchingFontDescriptor(reqDesc.get(), name_required().get()));
449 if (!resolvedDesc) {
450 return nullptr;
451 }
452 return create_from_desc(resolvedDesc.get());
453 }
454
455 sk_sp<SkTypeface> onMatchFamilyStyleCharacter(const char familyName[],
456 const SkFontStyle& style,
457 const char* bcp47[], int bcp47Count,
458 SkUnichar character) const override {
459 SkUniqueCFRef<CTFontDescriptorRef> desc = create_descriptor(familyName, style);
460 SkUniqueCFRef<CTFontRef> familyFont(CTFontCreateWithFontDescriptor(desc.get(), 0, nullptr));
461
462 // kCFStringEncodingUTF32 is BE unless there is a BOM.
463 // Since there is no machine endian option, explicitly state machine endian.
464#ifdef SK_CPU_LENDIAN
465 constexpr CFStringEncoding encoding = kCFStringEncodingUTF32LE;
466#else
467 constexpr CFStringEncoding encoding = kCFStringEncodingUTF32BE;
468#endif
469 SkUniqueCFRef<CFStringRef> string(CFStringCreateWithBytes(
470 kCFAllocatorDefault, reinterpret_cast<const UInt8 *>(&character), sizeof(character),
471 encoding, false));
472 // If 0xD800 <= codepoint <= 0xDFFF || 0x10FFFF < codepoint 'string' may be nullptr.
473 // No font should be covering such codepoints (even the magic fallback font).
474 if (!string) {
475 return nullptr;
476 }
477 CFRange range = CFRangeMake(0, CFStringGetLength(string.get())); // in UniChar units.
478 SkUniqueCFRef<CTFontRef> fallbackFont(
479 CTFontCreateForString(familyFont.get(), string.get(), range));
480 return SkTypeface_Mac::Make(std::move(fallbackFont), OpszVariation(), nullptr);
481 }
482
483 sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData> data, int ttcIndex) const override {
484 return this->makeFromStream(
485 std::unique_ptr<SkStreamAsset>(new SkMemoryStream(std::move(data))), ttcIndex);
486 }
487
488 sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,
489 int ttcIndex) const override {
490 return this->makeFromStream(std::move(stream),
491 SkFontArguments().setCollectionIndex(ttcIndex));
492 }
493
494 sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,
495 const SkFontArguments& args) const override {
496 return SkTypeface_Mac::MakeFromStream(std::move(stream), args);
497 }
498
499 sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override {
501 if (!data) {
502 return nullptr;
503 }
504
505 return this->onMakeFromData(std::move(data), ttcIndex);
506 }
507
508 sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle style) const override {
509 if (familyName) {
510 familyName = map_css_names(familyName);
511 }
512
513 sk_sp<SkTypeface> face = create_from_name(familyName, style);
514 if (face) {
515 return face;
516 }
517
518 static SkTypeface* gDefaultFace;
519 static SkOnce lookupDefault;
520 static const char FONT_DEFAULT_NAME[] = "Lucida Sans";
521 lookupDefault([]{
522 gDefaultFace = create_from_name(FONT_DEFAULT_NAME, SkFontStyle()).release();
523 });
524 return sk_ref_sp(gDefaultFace);
525 }
526};
527
528sk_sp<SkFontMgr> SkFontMgr_New_CoreText(CTFontCollectionRef fontCollection) {
529 return sk_make_sp<SkFontMgr_Mac>(fontCollection);
530}
531
532#endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
static const Pair gPairs[]
int count
Definition: FontMgrTest.cpp:50
#define SkASSERT(cond)
Definition: SkAssert.h:116
SK_API sk_sp< SkFontMgr > SkFontMgr_New_CoreText(CTFontCollectionRef)
static constexpr int32_t SK_MaxS32
Definition: SkMath.h:21
static std::vector< SkPDFIndirectReference > sort(const THashSet< SkPDFIndirectReference > &src)
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
static int32_t SkAbs32(int32_t value)
Definition: SkSafe32.h:41
constexpr int SkToInt(S x)
Definition: SkTo.h:29
int32_t SkUnichar
Definition: SkTypes.h:175
static sk_sp< SkData > MakeFromFileName(const char path[])
Definition: SkData.cpp:148
virtual void onGetFamilyName(int index, SkString *familyName) const =0
sk_sp< SkTypeface > makeFromStream(std::unique_ptr< SkStreamAsset >, int ttcIndex=0) const
Definition: SkFontMgr.cpp:127
virtual sk_sp< SkTypeface > onMakeFromData(sk_sp< SkData >, int ttcIndex) const =0
virtual sk_sp< SkFontStyleSet > onCreateStyleSet(int index) const =0
virtual sk_sp< SkTypeface > onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle &, const char *bcp47[], int bcp47Count, SkUnichar character) const =0
virtual sk_sp< SkFontStyleSet > onMatchFamily(const char familyName[]) const =0
virtual sk_sp< SkTypeface > onMakeFromStreamIndex(std::unique_ptr< SkStreamAsset >, int ttcIndex) const =0
virtual sk_sp< SkTypeface > onMakeFromStreamArgs(std::unique_ptr< SkStreamAsset >, const SkFontArguments &) const =0
virtual sk_sp< SkTypeface > onMatchFamilyStyle(const char familyName[], const SkFontStyle &) const =0
virtual sk_sp< SkTypeface > onLegacyMakeTypeface(const char familyName[], SkFontStyle) const =0
virtual sk_sp< SkTypeface > onMakeFromFile(const char path[], int ttcIndex) const =0
virtual int onCountFamilies() const =0
virtual sk_sp< SkTypeface > createTypeface(int index)=0
virtual sk_sp< SkTypeface > matchStyle(const SkFontStyle &pattern)=0
virtual int count()=0
virtual void getStyle(int index, SkFontStyle *, SkString *style)=0
Slant slant() const
Definition: SkFontStyle.h:64
int width() const
Definition: SkFontStyle.h:63
int weight() const
Definition: SkFontStyle.h:62
Definition: SkOnce.h:22
void reset()
Definition: SkString.cpp:358
static bool b
struct MyStruct s
struct MyStruct a[10]
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
uint8_t value
std::unique_ptr< SkCodec > MakeFromStream(std::unique_ptr< SkStream > stream, SkCodec::SelectionPolicy selectionPolicy, SkCodec::Result *result)
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
const myers::Point & get(const myers::Segment &)
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63