9#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
11#ifdef SK_BUILD_FOR_MAC
12#import <ApplicationServices/ApplicationServices.h>
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>
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)
50static uint32_t SkGetCoreTextVersion() {
53 static const uint32_t kCoreTextVersionNEWER = 0x000D0000;
54 return kCoreTextVersionNEWER;
59static uint32_t SkGetCoreTextVersion() {
61 static const bool kCoreTextIsAvailable = (&CTGetCoreTextVersion !=
nullptr);
62 if (kCoreTextIsAvailable) {
63 return CTGetCoreTextVersion();
67 static const uint32_t kCoreTextVersionUNKNOWN = 0;
68 return kCoreTextVersionUNKNOWN;
73static SkUniqueCFRef<CFStringRef> make_CFString(
const char s[]) {
74 return SkUniqueCFRef<CFStringRef>(CFStringCreateWithCString(
nullptr,
s, kCFStringEncodingUTF8));
79 SkUniqueCFRef<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc, 0,
nullptr));
84 return SkTypeface_Mac::Make(std::move(ctFont), OpszVariation(),
nullptr);
87static SkUniqueCFRef<CTFontDescriptorRef> create_descriptor(
const char familyName[],
89 SkUniqueCFRef<CFMutableDictionaryRef> cfAttributes(
90 CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
91 &kCFTypeDictionaryKeyCallBacks,
92 &kCFTypeDictionaryValueCallBacks));
94 SkUniqueCFRef<CFMutableDictionaryRef> cfTraits(
95 CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
96 &kCFTypeDictionaryKeyCallBacks,
97 &kCFTypeDictionaryValueCallBacks));
99 if (!cfAttributes || !cfTraits) {
110 static const uint32_t kSkiaLocalCTVersionNumber10_14 = 0x000B0000;
111 static const uint32_t kSkiaLocalCTVersionNumber10_15 = 0x000C0000;
117 if (SkGetCoreTextVersion() < kSkiaLocalCTVersionNumber10_14) {
118 CTFontSymbolicTraits ctFontTraits = 0;
120 ctFontTraits |= kCTFontBoldTrait;
123 ctFontTraits |= kCTFontItalicTrait;
125 SkUniqueCFRef<CFNumberRef> cfFontTraits(
126 CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTraits));
128 CFDictionaryAddValue(cfTraits.get(), kCTFontSymbolicTrait, cfFontTraits.get());
133 CGFloat ctWeight = SkCTFontCTWeightForCSSWeight(style.
weight());
134 SkUniqueCFRef<CFNumberRef> cfFontWeight(
135 CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctWeight));
137 CFDictionaryAddValue(cfTraits.get(), kCTFontWeightTrait, cfFontWeight.get());
140 CGFloat ctWidth = SkCTFontCTWidthForCSSWidth(style.
width());
141 SkUniqueCFRef<CFNumberRef> cfFontWidth(
142 CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctWidth));
144 CFDictionaryAddValue(cfTraits.get(), kCTFontWidthTrait, cfFontWidth.get());
148 if (SkGetCoreTextVersion() != kSkiaLocalCTVersionNumber10_15) {
150 SkUniqueCFRef<CFNumberRef> cfFontSlant(
151 CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctSlant));
153 CFDictionaryAddValue(cfTraits.get(), kCTFontSlantTrait, cfFontSlant.get());
157 CFDictionaryAddValue(cfAttributes.get(), kCTFontTraitsAttribute, cfTraits.get());
161 SkUniqueCFRef<CFStringRef> cfFontName = make_CFString(familyName);
163 CFDictionaryAddValue(cfAttributes.get(), kCTFontFamilyNameAttribute, cfFontName.get());
167 return SkUniqueCFRef<CTFontDescriptorRef>(
168 CTFontDescriptorCreateWithAttributes(cfAttributes.get()));
177 SkUniqueCFRef<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc, 0,
nullptr));
182 const CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ctFont.get());
183 CTFontSymbolicTraits expected_traits = traits;
185 expected_traits |= kCTFontItalicTrait;
188 expected_traits |= kCTFontBoldTrait;
191 if (expected_traits != traits) {
192 SkUniqueCFRef<CTFontRef> ctNewFont(CTFontCreateCopyWithSymbolicTraits(
193 ctFont.get(), 0,
nullptr, expected_traits, expected_traits));
195 ctFont = std::move(ctNewFont);
199 return SkTypeface_Mac::Make(std::move(ctFont), OpszVariation(),
nullptr);
204 SkUniqueCFRef<CTFontDescriptorRef>
desc = create_descriptor(familyName, style);
208 return create_from_desc_and_style(
desc.get(), style);
211static const char* map_css_names(
const char*
name) {
212 static const struct {
216 {
"sans-serif",
"Helvetica" },
217 {
"serif",
"Times" },
218 {
"monospace",
"Courier" }
221 for (
size_t i = 0; i < std::size(
gPairs); i++) {
231static bool find_desc_str(CTFontDescriptorRef desc, CFStringRef
name,
SkString* value) {
232 SkUniqueCFRef<CFStringRef> ref((CFStringRef)CTFontDescriptorCopyAttribute(desc,
name));
236 SkStringFromCFString(ref.get(), value);
240static inline int sqr(
int value) {
247 return sqr(
a.weight() -
b.weight()) +
248 sqr((
a.width() -
b.width()) * 100) +
249 sqr((
a.slant() !=
b.slant()) * 900);
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));
261 SkFontStyleSet_Mac(CTFontDescriptorRef desc)
262 : fArray(CTFontDescriptorCreateMatchingFontDescriptors(
desc, name_required().
get()))
266 fArray.reset(CFArrayCreate(
nullptr,
nullptr, 0,
nullptr));
271 int count()
override {
276 SkASSERT((
unsigned)index < (
unsigned)fCount);
277 CTFontDescriptorRef
desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), index);
279 *style = SkCTFontDescriptorGetSkFontStyle(desc,
false);
282 if (!find_desc_str(desc, kCTFontStyleNameAttribute,
name)) {
289 SkASSERT((
unsigned)index < (
unsigned)CFArrayGetCount(fArray.get()));
290 CTFontDescriptorRef
desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), index);
292 return create_from_desc(desc);
299 return create_from_desc(findMatchingDesc(pattern));
303 SkUniqueCFRef<CFArrayRef> fArray;
306 CTFontDescriptorRef findMatchingDesc(
const SkFontStyle& pattern)
const {
308 CTFontDescriptorRef bestDesc =
nullptr;
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));
316 if (metric < bestMetric) {
326SkUniqueCFRef<CFArrayRef> SkCopyAvailableFontFamilyNames(CTFontCollectionRef collection) {
328 SkUniqueCFRef<CFArrayRef> descriptors(
329 CTFontCollectionCreateMatchingFontDescriptors(collection));
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));
338 CFSetAddValue(familyNameSet, familyName.get());
341 SkUniqueCFRef<CFMutableSetRef> familyNameSet(
342 CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks));
343 CFArrayApplyFunction(descriptors.get(), CFRangeMake(0, CFArrayGetCount(descriptors.get())),
344 addDescriptorFamilyNameToSet, familyNameSet.get());
347 CFIndex
count = CFSetGetCount(familyNameSet.get());
348 std::unique_ptr<const void*[]> familyNames(
new const void*[
count]);
349 CFSetGetValues(familyNameSet.get(), familyNames.get());
352 std::sort(familyNames.get(), familyNames.get() +
count, [](
const void*
a,
const void*
b){
353 return CFStringCompare((CFStringRef)a, (CFStringRef)b, 0) == kCFCompareLessThan;
357 return SkUniqueCFRef<CFArrayRef>(
358 CFArrayCreate(kCFAllocatorDefault, familyNames.get(),
count, &kCFTypeArrayCallBacks));
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());
371 SkUniqueCFRef<CTFontCollectionRef> collection(
372 CTFontCollectionCreateFromAvailableFonts(
nullptr));
373 return SkUniqueCFRef<CFArrayRef>(SkCopyAvailableFontFamilyNames(collection.get()));
375 return SkUniqueCFRef<CFArrayRef>(CTFontManagerCopyAvailableFontFamilyNames());
382 SkUniqueCFRef<CFArrayRef> fNames;
385 CFStringRef getFamilyNameAt(
int index)
const {
386 SkASSERT((
unsigned)index < (
unsigned)fCount);
387 return (CFStringRef)CFArrayGetValueAtIndex(fNames.get(), index);
391 SkUniqueCFRef<CFMutableDictionaryRef> cfAttr(
392 CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
393 &kCFTypeDictionaryKeyCallBacks,
394 &kCFTypeDictionaryValueCallBacks));
396 CFDictionaryAddValue(cfAttr.get(), kCTFontFamilyNameAttribute, cfFamilyName);
398 SkUniqueCFRef<CTFontDescriptorRef>
desc(
399 CTFontDescriptorCreateWithAttributes(cfAttr.get()));
404 SkUniqueCFRef<CTFontCollectionRef> fFontCollection;
405 SkFontMgr_Mac(CTFontCollectionRef fontCollection)
406 : fNames(fontCollection ? SkCopyAvailableFontFamilyNames(fontCollection)
407 : SkCTFontManagerCopyAvailableFontFamilyNames())
409 , fFontCollection(fontCollection ? (CTFontCollectionRef)CFRetain(fontCollection)
410 : CTFontCollectionCreateFromAvailableFonts(nullptr))
419 if ((
unsigned)index < (
unsigned)fCount) {
420 SkStringFromCFString(this->getFamilyNameAt(index), familyName);
427 if ((
unsigned)index >= (
unsigned)fCount) {
430 return CreateSet(this->getFamilyNameAt(index));
437 SkUniqueCFRef<CFStringRef> cfName = make_CFString(familyName);
438 return CreateSet(cfName.get());
443 SkUniqueCFRef<CTFontDescriptorRef> reqDesc = create_descriptor(familyName, style);
445 return create_from_desc(reqDesc.get());
447 SkUniqueCFRef<CTFontDescriptorRef> resolvedDesc(
448 CTFontDescriptorCreateMatchingFontDescriptor(reqDesc.get(), name_required().
get()));
452 return create_from_desc(resolvedDesc.get());
457 const char* bcp47[],
int bcp47Count,
459 SkUniqueCFRef<CTFontDescriptorRef>
desc = create_descriptor(familyName, style);
460 SkUniqueCFRef<CTFontRef> familyFont(CTFontCreateWithFontDescriptor(
desc.get(), 0,
nullptr));
465 constexpr CFStringEncoding encoding = kCFStringEncodingUTF32LE;
467 constexpr CFStringEncoding encoding = kCFStringEncodingUTF32BE;
469 SkUniqueCFRef<CFStringRef> string(CFStringCreateWithBytes(
477 CFRange range = CFRangeMake(0, CFStringGetLength(
string.
get()));
478 SkUniqueCFRef<CTFontRef> fallbackFont(
479 CTFontCreateForString(familyFont.get(),
string.get(), range));
480 return SkTypeface_Mac::Make(std::move(fallbackFont), OpszVariation(),
nullptr);
485 std::unique_ptr<SkStreamAsset>(
new SkMemoryStream(std::move(data))), ttcIndex);
489 int ttcIndex)
const override {
496 return SkTypeface_Mac::MakeFromStream(std::move(stream),
args);
510 familyName = map_css_names(familyName);
519 static SkOnce lookupDefault;
520 static const char FONT_DEFAULT_NAME[] =
"Lucida Sans";
522 gDefaultFace = create_from_name(FONT_DEFAULT_NAME,
SkFontStyle()).release();
529 return sk_make_sp<SkFontMgr_Mac>(fontCollection);
static const Pair gPairs[]
SK_API sk_sp< SkFontMgr > SkFontMgr_New_CoreText(CTFontCollectionRef)
static constexpr int32_t SK_MaxS32
sk_sp< T > sk_ref_sp(T *obj)
static int32_t SkAbs32(int32_t value)
constexpr int SkToInt(S x)
static sk_sp< SkData > MakeFromFileName(const char path[])
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 void getStyle(int index, SkFontStyle *, SkString *style)=0
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
const myers::Point & get(const myers::Segment &)