Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
#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
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
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
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
const char * name
Definition fuchsia.cc:50
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switches.h:41
const myers::Point & get(const myers::Segment &)