1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2006 The Android Open Source Project 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkTypes.h" 9cb93a386Sopenharmony_ci#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_MAC 12cb93a386Sopenharmony_ci#import <ApplicationServices/ApplicationServices.h> 13cb93a386Sopenharmony_ci#endif 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_IOS 16cb93a386Sopenharmony_ci#include <CoreText/CoreText.h> 17cb93a386Sopenharmony_ci#include <CoreText/CTFontManager.h> 18cb93a386Sopenharmony_ci#include <CoreGraphics/CoreGraphics.h> 19cb93a386Sopenharmony_ci#include <CoreFoundation/CoreFoundation.h> 20cb93a386Sopenharmony_ci#include <dlfcn.h> 21cb93a386Sopenharmony_ci#endif 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_ci#include "include/core/SkData.h" 24cb93a386Sopenharmony_ci#include "include/core/SkFontArguments.h" 25cb93a386Sopenharmony_ci#include "include/core/SkFontMgr.h" 26cb93a386Sopenharmony_ci#include "include/core/SkFontStyle.h" 27cb93a386Sopenharmony_ci#include "include/core/SkStream.h" 28cb93a386Sopenharmony_ci#include "include/core/SkString.h" 29cb93a386Sopenharmony_ci#include "include/core/SkTypeface.h" 30cb93a386Sopenharmony_ci#include "include/ports/SkFontMgr_mac_ct.h" 31cb93a386Sopenharmony_ci#include "include/private/SkFixed.h" 32cb93a386Sopenharmony_ci#include "include/private/SkOnce.h" 33cb93a386Sopenharmony_ci#include "include/private/SkTPin.h" 34cb93a386Sopenharmony_ci#include "include/private/SkTemplates.h" 35cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 36cb93a386Sopenharmony_ci#include "src/core/SkFontDescriptor.h" 37cb93a386Sopenharmony_ci#include "src/ports/SkTypeface_mac_ct.h" 38cb93a386Sopenharmony_ci#include "src/utils/SkUTF.h" 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_ci#include <string.h> 41cb93a386Sopenharmony_ci#include <memory> 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_ci#if (defined(SK_BUILD_FOR_IOS) && defined(__IPHONE_14_0) && \ 44cb93a386Sopenharmony_ci __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_14_0) || \ 45cb93a386Sopenharmony_ci (defined(SK_BUILD_FOR_MAC) && defined(__MAC_11_0) && \ 46cb93a386Sopenharmony_ci __MAC_OS_VERSION_MIN_REQUIRED >= __MAC_11_0) 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_cistatic uint32_t SkGetCoreTextVersion() { 49cb93a386Sopenharmony_ci // If compiling for iOS 14.0+ or macOS 11.0+, the CoreText version number 50cb93a386Sopenharmony_ci // must be derived from the OS version number. 51cb93a386Sopenharmony_ci static const uint32_t kCoreTextVersionNEWER = 0x000D0000; 52cb93a386Sopenharmony_ci return kCoreTextVersionNEWER; 53cb93a386Sopenharmony_ci} 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_ci#else 56cb93a386Sopenharmony_ci 57cb93a386Sopenharmony_cistatic uint32_t SkGetCoreTextVersion() { 58cb93a386Sopenharmony_ci // Check for CoreText availability before calling CTGetCoreTextVersion(). 59cb93a386Sopenharmony_ci if (&CTGetCoreTextVersion) { 60cb93a386Sopenharmony_ci return CTGetCoreTextVersion(); 61cb93a386Sopenharmony_ci } 62cb93a386Sopenharmony_ci 63cb93a386Sopenharmony_ci // Default to a value that's smaller than any known CoreText version. 64cb93a386Sopenharmony_ci static const uint32_t kCoreTextVersionUNKNOWN = 0; 65cb93a386Sopenharmony_ci return kCoreTextVersionUNKNOWN; 66cb93a386Sopenharmony_ci} 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ci#endif 69cb93a386Sopenharmony_ci 70cb93a386Sopenharmony_cistatic SkUniqueCFRef<CFStringRef> make_CFString(const char s[]) { 71cb93a386Sopenharmony_ci return SkUniqueCFRef<CFStringRef>(CFStringCreateWithCString(nullptr, s, kCFStringEncodingUTF8)); 72cb93a386Sopenharmony_ci} 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_ci/** Creates a typeface from a descriptor, searching the cache. */ 75cb93a386Sopenharmony_cistatic sk_sp<SkTypeface> create_from_desc(CTFontDescriptorRef desc) { 76cb93a386Sopenharmony_ci SkUniqueCFRef<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc, 0, nullptr)); 77cb93a386Sopenharmony_ci if (!ctFont) { 78cb93a386Sopenharmony_ci return nullptr; 79cb93a386Sopenharmony_ci } 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ci return SkTypeface_Mac::Make(std::move(ctFont), OpszVariation(), nullptr); 82cb93a386Sopenharmony_ci} 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_cistatic SkUniqueCFRef<CTFontDescriptorRef> create_descriptor(const char familyName[], 85cb93a386Sopenharmony_ci const SkFontStyle& style) { 86cb93a386Sopenharmony_ci SkUniqueCFRef<CFMutableDictionaryRef> cfAttributes( 87cb93a386Sopenharmony_ci CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 88cb93a386Sopenharmony_ci &kCFTypeDictionaryKeyCallBacks, 89cb93a386Sopenharmony_ci &kCFTypeDictionaryValueCallBacks)); 90cb93a386Sopenharmony_ci 91cb93a386Sopenharmony_ci SkUniqueCFRef<CFMutableDictionaryRef> cfTraits( 92cb93a386Sopenharmony_ci CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 93cb93a386Sopenharmony_ci &kCFTypeDictionaryKeyCallBacks, 94cb93a386Sopenharmony_ci &kCFTypeDictionaryValueCallBacks)); 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ci if (!cfAttributes || !cfTraits) { 97cb93a386Sopenharmony_ci return nullptr; 98cb93a386Sopenharmony_ci } 99cb93a386Sopenharmony_ci 100cb93a386Sopenharmony_ci // TODO(crbug.com/1018581) Some CoreText versions have errant behavior when 101cb93a386Sopenharmony_ci // certain traits set. Temporary workaround to omit specifying trait for those 102cb93a386Sopenharmony_ci // versions. 103cb93a386Sopenharmony_ci // Long term solution will involve serializing typefaces instead of relying upon 104cb93a386Sopenharmony_ci // this to match between processes. 105cb93a386Sopenharmony_ci // 106cb93a386Sopenharmony_ci // Compare CoreText.h in an up to date SDK for where these values come from. 107cb93a386Sopenharmony_ci static const uint32_t kSkiaLocalCTVersionNumber10_14 = 0x000B0000; 108cb93a386Sopenharmony_ci static const uint32_t kSkiaLocalCTVersionNumber10_15 = 0x000C0000; 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_ci // CTFontTraits (symbolic) 111cb93a386Sopenharmony_ci // macOS 14 and iOS 12 seem to behave badly when kCTFontSymbolicTrait is set. 112cb93a386Sopenharmony_ci // macOS 15 yields LastResort font instead of a good default font when 113cb93a386Sopenharmony_ci // kCTFontSymbolicTrait is set. 114cb93a386Sopenharmony_ci if (SkGetCoreTextVersion() < kSkiaLocalCTVersionNumber10_14) { 115cb93a386Sopenharmony_ci CTFontSymbolicTraits ctFontTraits = 0; 116cb93a386Sopenharmony_ci if (style.weight() >= SkFontStyle::kBold_Weight) { 117cb93a386Sopenharmony_ci ctFontTraits |= kCTFontBoldTrait; 118cb93a386Sopenharmony_ci } 119cb93a386Sopenharmony_ci if (style.slant() != SkFontStyle::kUpright_Slant) { 120cb93a386Sopenharmony_ci ctFontTraits |= kCTFontItalicTrait; 121cb93a386Sopenharmony_ci } 122cb93a386Sopenharmony_ci SkUniqueCFRef<CFNumberRef> cfFontTraits( 123cb93a386Sopenharmony_ci CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTraits)); 124cb93a386Sopenharmony_ci if (cfFontTraits) { 125cb93a386Sopenharmony_ci CFDictionaryAddValue(cfTraits.get(), kCTFontSymbolicTrait, cfFontTraits.get()); 126cb93a386Sopenharmony_ci } 127cb93a386Sopenharmony_ci } 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_ci // CTFontTraits (weight) 130cb93a386Sopenharmony_ci CGFloat ctWeight = SkCTFontCTWeightForCSSWeight(style.weight()); 131cb93a386Sopenharmony_ci SkUniqueCFRef<CFNumberRef> cfFontWeight( 132cb93a386Sopenharmony_ci CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctWeight)); 133cb93a386Sopenharmony_ci if (cfFontWeight) { 134cb93a386Sopenharmony_ci CFDictionaryAddValue(cfTraits.get(), kCTFontWeightTrait, cfFontWeight.get()); 135cb93a386Sopenharmony_ci } 136cb93a386Sopenharmony_ci // CTFontTraits (width) 137cb93a386Sopenharmony_ci CGFloat ctWidth = SkCTFontCTWidthForCSSWidth(style.width()); 138cb93a386Sopenharmony_ci SkUniqueCFRef<CFNumberRef> cfFontWidth( 139cb93a386Sopenharmony_ci CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctWidth)); 140cb93a386Sopenharmony_ci if (cfFontWidth) { 141cb93a386Sopenharmony_ci CFDictionaryAddValue(cfTraits.get(), kCTFontWidthTrait, cfFontWidth.get()); 142cb93a386Sopenharmony_ci } 143cb93a386Sopenharmony_ci // CTFontTraits (slant) 144cb93a386Sopenharmony_ci // macOS 15 behaves badly when kCTFontSlantTrait is set. 145cb93a386Sopenharmony_ci if (SkGetCoreTextVersion() != kSkiaLocalCTVersionNumber10_15) { 146cb93a386Sopenharmony_ci CGFloat ctSlant = style.slant() == SkFontStyle::kUpright_Slant ? 0 : 1; 147cb93a386Sopenharmony_ci SkUniqueCFRef<CFNumberRef> cfFontSlant( 148cb93a386Sopenharmony_ci CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctSlant)); 149cb93a386Sopenharmony_ci if (cfFontSlant) { 150cb93a386Sopenharmony_ci CFDictionaryAddValue(cfTraits.get(), kCTFontSlantTrait, cfFontSlant.get()); 151cb93a386Sopenharmony_ci } 152cb93a386Sopenharmony_ci } 153cb93a386Sopenharmony_ci // CTFontTraits 154cb93a386Sopenharmony_ci CFDictionaryAddValue(cfAttributes.get(), kCTFontTraitsAttribute, cfTraits.get()); 155cb93a386Sopenharmony_ci 156cb93a386Sopenharmony_ci // CTFontFamilyName 157cb93a386Sopenharmony_ci if (familyName) { 158cb93a386Sopenharmony_ci SkUniqueCFRef<CFStringRef> cfFontName = make_CFString(familyName); 159cb93a386Sopenharmony_ci if (cfFontName) { 160cb93a386Sopenharmony_ci CFDictionaryAddValue(cfAttributes.get(), kCTFontFamilyNameAttribute, cfFontName.get()); 161cb93a386Sopenharmony_ci } 162cb93a386Sopenharmony_ci } 163cb93a386Sopenharmony_ci 164cb93a386Sopenharmony_ci return SkUniqueCFRef<CTFontDescriptorRef>( 165cb93a386Sopenharmony_ci CTFontDescriptorCreateWithAttributes(cfAttributes.get())); 166cb93a386Sopenharmony_ci} 167cb93a386Sopenharmony_ci 168cb93a386Sopenharmony_ci// Same as the above function except style is included so we can 169cb93a386Sopenharmony_ci// compare whether the created font conforms to the style. If not, we need 170cb93a386Sopenharmony_ci// to recreate the font with symbolic traits. This is needed due to MacOS 10.11 171cb93a386Sopenharmony_ci// font creation problem https://bugs.chromium.org/p/skia/issues/detail?id=8447. 172cb93a386Sopenharmony_cistatic sk_sp<SkTypeface> create_from_desc_and_style(CTFontDescriptorRef desc, 173cb93a386Sopenharmony_ci const SkFontStyle& style) { 174cb93a386Sopenharmony_ci SkUniqueCFRef<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc, 0, nullptr)); 175cb93a386Sopenharmony_ci if (!ctFont) { 176cb93a386Sopenharmony_ci return nullptr; 177cb93a386Sopenharmony_ci } 178cb93a386Sopenharmony_ci 179cb93a386Sopenharmony_ci const CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ctFont.get()); 180cb93a386Sopenharmony_ci CTFontSymbolicTraits expected_traits = traits; 181cb93a386Sopenharmony_ci if (style.slant() != SkFontStyle::kUpright_Slant) { 182cb93a386Sopenharmony_ci expected_traits |= kCTFontItalicTrait; 183cb93a386Sopenharmony_ci } 184cb93a386Sopenharmony_ci if (style.weight() >= SkFontStyle::kBold_Weight) { 185cb93a386Sopenharmony_ci expected_traits |= kCTFontBoldTrait; 186cb93a386Sopenharmony_ci } 187cb93a386Sopenharmony_ci 188cb93a386Sopenharmony_ci if (expected_traits != traits) { 189cb93a386Sopenharmony_ci SkUniqueCFRef<CTFontRef> ctNewFont(CTFontCreateCopyWithSymbolicTraits( 190cb93a386Sopenharmony_ci ctFont.get(), 0, nullptr, expected_traits, expected_traits)); 191cb93a386Sopenharmony_ci if (ctNewFont) { 192cb93a386Sopenharmony_ci ctFont = std::move(ctNewFont); 193cb93a386Sopenharmony_ci } 194cb93a386Sopenharmony_ci } 195cb93a386Sopenharmony_ci 196cb93a386Sopenharmony_ci return SkTypeface_Mac::Make(std::move(ctFont), OpszVariation(), nullptr); 197cb93a386Sopenharmony_ci} 198cb93a386Sopenharmony_ci 199cb93a386Sopenharmony_ci/** Creates a typeface from a name, searching the cache. */ 200cb93a386Sopenharmony_cistatic sk_sp<SkTypeface> create_from_name(const char familyName[], const SkFontStyle& style) { 201cb93a386Sopenharmony_ci SkUniqueCFRef<CTFontDescriptorRef> desc = create_descriptor(familyName, style); 202cb93a386Sopenharmony_ci if (!desc) { 203cb93a386Sopenharmony_ci return nullptr; 204cb93a386Sopenharmony_ci } 205cb93a386Sopenharmony_ci return create_from_desc_and_style(desc.get(), style); 206cb93a386Sopenharmony_ci} 207cb93a386Sopenharmony_ci 208cb93a386Sopenharmony_cistatic const char* map_css_names(const char* name) { 209cb93a386Sopenharmony_ci static const struct { 210cb93a386Sopenharmony_ci const char* fFrom; // name the caller specified 211cb93a386Sopenharmony_ci const char* fTo; // "canonical" name we map to 212cb93a386Sopenharmony_ci } gPairs[] = { 213cb93a386Sopenharmony_ci { "sans-serif", "Helvetica" }, 214cb93a386Sopenharmony_ci { "serif", "Times" }, 215cb93a386Sopenharmony_ci { "monospace", "Courier" } 216cb93a386Sopenharmony_ci }; 217cb93a386Sopenharmony_ci 218cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) { 219cb93a386Sopenharmony_ci if (strcmp(name, gPairs[i].fFrom) == 0) { 220cb93a386Sopenharmony_ci return gPairs[i].fTo; 221cb93a386Sopenharmony_ci } 222cb93a386Sopenharmony_ci } 223cb93a386Sopenharmony_ci return name; // no change 224cb93a386Sopenharmony_ci} 225cb93a386Sopenharmony_ci 226cb93a386Sopenharmony_cinamespace { 227cb93a386Sopenharmony_ci 228cb93a386Sopenharmony_cistatic sk_sp<SkData> skdata_from_skstreamasset(std::unique_ptr<SkStreamAsset> stream) { 229cb93a386Sopenharmony_ci size_t size = stream->getLength(); 230cb93a386Sopenharmony_ci if (const void* base = stream->getMemoryBase()) { 231cb93a386Sopenharmony_ci return SkData::MakeWithProc(base, size, 232cb93a386Sopenharmony_ci [](const void*, void* ctx) -> void { 233cb93a386Sopenharmony_ci delete (SkStreamAsset*)ctx; 234cb93a386Sopenharmony_ci }, stream.release()); 235cb93a386Sopenharmony_ci } 236cb93a386Sopenharmony_ci return SkData::MakeFromStream(stream.get(), size); 237cb93a386Sopenharmony_ci} 238cb93a386Sopenharmony_ci 239cb93a386Sopenharmony_cistatic SkUniqueCFRef<CFDataRef> cfdata_from_skdata(sk_sp<SkData> data) { 240cb93a386Sopenharmony_ci void const * const addr = data->data(); 241cb93a386Sopenharmony_ci size_t const size = data->size(); 242cb93a386Sopenharmony_ci 243cb93a386Sopenharmony_ci CFAllocatorContext ctx = { 244cb93a386Sopenharmony_ci 0, // CFIndex version 245cb93a386Sopenharmony_ci data.release(), // void* info 246cb93a386Sopenharmony_ci nullptr, // const void *(*retain)(const void *info); 247cb93a386Sopenharmony_ci nullptr, // void (*release)(const void *info); 248cb93a386Sopenharmony_ci nullptr, // CFStringRef (*copyDescription)(const void *info); 249cb93a386Sopenharmony_ci nullptr, // void * (*allocate)(CFIndex size, CFOptionFlags hint, void *info); 250cb93a386Sopenharmony_ci nullptr, // void*(*reallocate)(void* ptr,CFIndex newsize,CFOptionFlags hint,void* info); 251cb93a386Sopenharmony_ci [](void*,void* info) -> void { // void (*deallocate)(void *ptr, void *info); 252cb93a386Sopenharmony_ci SkASSERT(info); 253cb93a386Sopenharmony_ci ((SkData*)info)->unref(); 254cb93a386Sopenharmony_ci }, 255cb93a386Sopenharmony_ci nullptr, // CFIndex (*preferredSize)(CFIndex size, CFOptionFlags hint, void *info); 256cb93a386Sopenharmony_ci }; 257cb93a386Sopenharmony_ci SkUniqueCFRef<CFAllocatorRef> alloc(CFAllocatorCreate(kCFAllocatorDefault, &ctx)); 258cb93a386Sopenharmony_ci return SkUniqueCFRef<CFDataRef>(CFDataCreateWithBytesNoCopy( 259cb93a386Sopenharmony_ci kCFAllocatorDefault, (const UInt8 *)addr, size, alloc.get())); 260cb93a386Sopenharmony_ci} 261cb93a386Sopenharmony_ci 262cb93a386Sopenharmony_cistatic SkUniqueCFRef<CTFontRef> ctfont_from_skdata(sk_sp<SkData> data, int ttcIndex) { 263cb93a386Sopenharmony_ci // TODO: Use CTFontManagerCreateFontDescriptorsFromData when available. 264cb93a386Sopenharmony_ci if (ttcIndex != 0) { 265cb93a386Sopenharmony_ci return nullptr; 266cb93a386Sopenharmony_ci } 267cb93a386Sopenharmony_ci 268cb93a386Sopenharmony_ci SkUniqueCFRef<CFDataRef> cfData(cfdata_from_skdata(std::move(data))); 269cb93a386Sopenharmony_ci 270cb93a386Sopenharmony_ci SkUniqueCFRef<CTFontDescriptorRef> desc( 271cb93a386Sopenharmony_ci CTFontManagerCreateFontDescriptorFromData(cfData.get())); 272cb93a386Sopenharmony_ci if (!desc) { 273cb93a386Sopenharmony_ci return nullptr; 274cb93a386Sopenharmony_ci } 275cb93a386Sopenharmony_ci return SkUniqueCFRef<CTFontRef>(CTFontCreateWithFontDescriptor(desc.get(), 0, nullptr)); 276cb93a386Sopenharmony_ci} 277cb93a386Sopenharmony_ci 278cb93a386Sopenharmony_cistatic bool find_desc_str(CTFontDescriptorRef desc, CFStringRef name, SkString* value) { 279cb93a386Sopenharmony_ci SkUniqueCFRef<CFStringRef> ref((CFStringRef)CTFontDescriptorCopyAttribute(desc, name)); 280cb93a386Sopenharmony_ci if (!ref) { 281cb93a386Sopenharmony_ci return false; 282cb93a386Sopenharmony_ci } 283cb93a386Sopenharmony_ci SkStringFromCFString(ref.get(), value); 284cb93a386Sopenharmony_ci return true; 285cb93a386Sopenharmony_ci} 286cb93a386Sopenharmony_ci 287cb93a386Sopenharmony_cistatic inline int sqr(int value) { 288cb93a386Sopenharmony_ci SkASSERT(SkAbs32(value) < 0x7FFF); // check for overflow 289cb93a386Sopenharmony_ci return value * value; 290cb93a386Sopenharmony_ci} 291cb93a386Sopenharmony_ci 292cb93a386Sopenharmony_ci// We normalize each axis (weight, width, italic) to be base-900 293cb93a386Sopenharmony_cistatic int compute_metric(const SkFontStyle& a, const SkFontStyle& b) { 294cb93a386Sopenharmony_ci return sqr(a.weight() - b.weight()) + 295cb93a386Sopenharmony_ci sqr((a.width() - b.width()) * 100) + 296cb93a386Sopenharmony_ci sqr((a.slant() != b.slant()) * 900); 297cb93a386Sopenharmony_ci} 298cb93a386Sopenharmony_ci 299cb93a386Sopenharmony_ciclass SkFontStyleSet_Mac : public SkFontStyleSet { 300cb93a386Sopenharmony_cipublic: 301cb93a386Sopenharmony_ci SkFontStyleSet_Mac(CTFontDescriptorRef desc) 302cb93a386Sopenharmony_ci : fArray(CTFontDescriptorCreateMatchingFontDescriptors(desc, nullptr)) 303cb93a386Sopenharmony_ci , fCount(0) 304cb93a386Sopenharmony_ci { 305cb93a386Sopenharmony_ci if (!fArray) { 306cb93a386Sopenharmony_ci fArray.reset(CFArrayCreate(nullptr, nullptr, 0, nullptr)); 307cb93a386Sopenharmony_ci } 308cb93a386Sopenharmony_ci fCount = SkToInt(CFArrayGetCount(fArray.get())); 309cb93a386Sopenharmony_ci } 310cb93a386Sopenharmony_ci 311cb93a386Sopenharmony_ci int count() override { 312cb93a386Sopenharmony_ci return fCount; 313cb93a386Sopenharmony_ci } 314cb93a386Sopenharmony_ci 315cb93a386Sopenharmony_ci void getStyle(int index, SkFontStyle* style, SkString* name) override { 316cb93a386Sopenharmony_ci SkASSERT((unsigned)index < (unsigned)fCount); 317cb93a386Sopenharmony_ci CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), index); 318cb93a386Sopenharmony_ci if (style) { 319cb93a386Sopenharmony_ci *style = SkCTFontDescriptorGetSkFontStyle(desc, false); 320cb93a386Sopenharmony_ci } 321cb93a386Sopenharmony_ci if (name) { 322cb93a386Sopenharmony_ci if (!find_desc_str(desc, kCTFontStyleNameAttribute, name)) { 323cb93a386Sopenharmony_ci name->reset(); 324cb93a386Sopenharmony_ci } 325cb93a386Sopenharmony_ci } 326cb93a386Sopenharmony_ci } 327cb93a386Sopenharmony_ci 328cb93a386Sopenharmony_ci SkTypeface* createTypeface(int index) override { 329cb93a386Sopenharmony_ci SkASSERT((unsigned)index < (unsigned)CFArrayGetCount(fArray.get())); 330cb93a386Sopenharmony_ci CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), index); 331cb93a386Sopenharmony_ci 332cb93a386Sopenharmony_ci return create_from_desc(desc).release(); 333cb93a386Sopenharmony_ci } 334cb93a386Sopenharmony_ci 335cb93a386Sopenharmony_ci SkTypeface* matchStyle(const SkFontStyle& pattern) override { 336cb93a386Sopenharmony_ci if (0 == fCount) { 337cb93a386Sopenharmony_ci return nullptr; 338cb93a386Sopenharmony_ci } 339cb93a386Sopenharmony_ci return create_from_desc(findMatchingDesc(pattern)).release(); 340cb93a386Sopenharmony_ci } 341cb93a386Sopenharmony_ci 342cb93a386Sopenharmony_ciprivate: 343cb93a386Sopenharmony_ci SkUniqueCFRef<CFArrayRef> fArray; 344cb93a386Sopenharmony_ci int fCount; 345cb93a386Sopenharmony_ci 346cb93a386Sopenharmony_ci CTFontDescriptorRef findMatchingDesc(const SkFontStyle& pattern) const { 347cb93a386Sopenharmony_ci int bestMetric = SK_MaxS32; 348cb93a386Sopenharmony_ci CTFontDescriptorRef bestDesc = nullptr; 349cb93a386Sopenharmony_ci 350cb93a386Sopenharmony_ci for (int i = 0; i < fCount; ++i) { 351cb93a386Sopenharmony_ci CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), i); 352cb93a386Sopenharmony_ci int metric = compute_metric(pattern, SkCTFontDescriptorGetSkFontStyle(desc, false)); 353cb93a386Sopenharmony_ci if (0 == metric) { 354cb93a386Sopenharmony_ci return desc; 355cb93a386Sopenharmony_ci } 356cb93a386Sopenharmony_ci if (metric < bestMetric) { 357cb93a386Sopenharmony_ci bestMetric = metric; 358cb93a386Sopenharmony_ci bestDesc = desc; 359cb93a386Sopenharmony_ci } 360cb93a386Sopenharmony_ci } 361cb93a386Sopenharmony_ci SkASSERT(bestDesc); 362cb93a386Sopenharmony_ci return bestDesc; 363cb93a386Sopenharmony_ci } 364cb93a386Sopenharmony_ci}; 365cb93a386Sopenharmony_ci 366cb93a386Sopenharmony_ciSkUniqueCFRef<CFArrayRef> SkCopyAvailableFontFamilyNames(CTFontCollectionRef collection) { 367cb93a386Sopenharmony_ci // Create a CFArray of all available font descriptors. 368cb93a386Sopenharmony_ci SkUniqueCFRef<CFArrayRef> descriptors( 369cb93a386Sopenharmony_ci CTFontCollectionCreateMatchingFontDescriptors(collection)); 370cb93a386Sopenharmony_ci 371cb93a386Sopenharmony_ci // Copy the font family names of the font descriptors into a CFSet. 372cb93a386Sopenharmony_ci auto addDescriptorFamilyNameToSet = [](const void* value, void* context) -> void { 373cb93a386Sopenharmony_ci CTFontDescriptorRef descriptor = static_cast<CTFontDescriptorRef>(value); 374cb93a386Sopenharmony_ci CFMutableSetRef familyNameSet = static_cast<CFMutableSetRef>(context); 375cb93a386Sopenharmony_ci SkUniqueCFRef<CFTypeRef> familyName( 376cb93a386Sopenharmony_ci CTFontDescriptorCopyAttribute(descriptor, kCTFontFamilyNameAttribute)); 377cb93a386Sopenharmony_ci if (familyName) { 378cb93a386Sopenharmony_ci CFSetAddValue(familyNameSet, familyName.get()); 379cb93a386Sopenharmony_ci } 380cb93a386Sopenharmony_ci }; 381cb93a386Sopenharmony_ci SkUniqueCFRef<CFMutableSetRef> familyNameSet( 382cb93a386Sopenharmony_ci CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks)); 383cb93a386Sopenharmony_ci CFArrayApplyFunction(descriptors.get(), CFRangeMake(0, CFArrayGetCount(descriptors.get())), 384cb93a386Sopenharmony_ci addDescriptorFamilyNameToSet, familyNameSet.get()); 385cb93a386Sopenharmony_ci 386cb93a386Sopenharmony_ci // Get the set of family names into an array; this does not retain. 387cb93a386Sopenharmony_ci CFIndex count = CFSetGetCount(familyNameSet.get()); 388cb93a386Sopenharmony_ci std::unique_ptr<const void*[]> familyNames(new const void*[count]); 389cb93a386Sopenharmony_ci CFSetGetValues(familyNameSet.get(), familyNames.get()); 390cb93a386Sopenharmony_ci 391cb93a386Sopenharmony_ci // Sort the array of family names (to match CTFontManagerCopyAvailableFontFamilyNames). 392cb93a386Sopenharmony_ci std::sort(familyNames.get(), familyNames.get() + count, [](const void* a, const void* b){ 393cb93a386Sopenharmony_ci return CFStringCompare((CFStringRef)a, (CFStringRef)b, 0) == kCFCompareLessThan; 394cb93a386Sopenharmony_ci }); 395cb93a386Sopenharmony_ci 396cb93a386Sopenharmony_ci // Copy family names into a CFArray; this does retain. 397cb93a386Sopenharmony_ci return SkUniqueCFRef<CFArrayRef>( 398cb93a386Sopenharmony_ci CFArrayCreate(kCFAllocatorDefault, familyNames.get(), count, &kCFTypeArrayCallBacks)); 399cb93a386Sopenharmony_ci} 400cb93a386Sopenharmony_ci 401cb93a386Sopenharmony_ci/** Use CTFontManagerCopyAvailableFontFamilyNames if available, simulate if not. */ 402cb93a386Sopenharmony_ciSkUniqueCFRef<CFArrayRef> SkCTFontManagerCopyAvailableFontFamilyNames() { 403cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_IOS 404cb93a386Sopenharmony_ci using CTFontManagerCopyAvailableFontFamilyNamesProc = CFArrayRef (*)(void); 405cb93a386Sopenharmony_ci CTFontManagerCopyAvailableFontFamilyNamesProc ctFontManagerCopyAvailableFontFamilyNames; 406cb93a386Sopenharmony_ci *(void**)(&ctFontManagerCopyAvailableFontFamilyNames) = 407cb93a386Sopenharmony_ci dlsym(RTLD_DEFAULT, "CTFontManagerCopyAvailableFontFamilyNames"); 408cb93a386Sopenharmony_ci if (ctFontManagerCopyAvailableFontFamilyNames) { 409cb93a386Sopenharmony_ci return SkUniqueCFRef<CFArrayRef>(ctFontManagerCopyAvailableFontFamilyNames()); 410cb93a386Sopenharmony_ci } 411cb93a386Sopenharmony_ci SkUniqueCFRef<CTFontCollectionRef> collection( 412cb93a386Sopenharmony_ci CTFontCollectionCreateFromAvailableFonts(nullptr)); 413cb93a386Sopenharmony_ci return SkUniqueCFRef<CFArrayRef>(SkCopyAvailableFontFamilyNames(collection.get())); 414cb93a386Sopenharmony_ci#else 415cb93a386Sopenharmony_ci return SkUniqueCFRef<CFArrayRef>(CTFontManagerCopyAvailableFontFamilyNames()); 416cb93a386Sopenharmony_ci#endif 417cb93a386Sopenharmony_ci} 418cb93a386Sopenharmony_ci 419cb93a386Sopenharmony_ci} // namespace 420cb93a386Sopenharmony_ci 421cb93a386Sopenharmony_ciclass SkFontMgr_Mac : public SkFontMgr { 422cb93a386Sopenharmony_ci SkUniqueCFRef<CFArrayRef> fNames; 423cb93a386Sopenharmony_ci int fCount; 424cb93a386Sopenharmony_ci 425cb93a386Sopenharmony_ci CFStringRef getFamilyNameAt(int index) const { 426cb93a386Sopenharmony_ci SkASSERT((unsigned)index < (unsigned)fCount); 427cb93a386Sopenharmony_ci return (CFStringRef)CFArrayGetValueAtIndex(fNames.get(), index); 428cb93a386Sopenharmony_ci } 429cb93a386Sopenharmony_ci 430cb93a386Sopenharmony_ci static SkFontStyleSet* CreateSet(CFStringRef cfFamilyName) { 431cb93a386Sopenharmony_ci SkUniqueCFRef<CFMutableDictionaryRef> cfAttr( 432cb93a386Sopenharmony_ci CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 433cb93a386Sopenharmony_ci &kCFTypeDictionaryKeyCallBacks, 434cb93a386Sopenharmony_ci &kCFTypeDictionaryValueCallBacks)); 435cb93a386Sopenharmony_ci 436cb93a386Sopenharmony_ci CFDictionaryAddValue(cfAttr.get(), kCTFontFamilyNameAttribute, cfFamilyName); 437cb93a386Sopenharmony_ci 438cb93a386Sopenharmony_ci SkUniqueCFRef<CTFontDescriptorRef> desc( 439cb93a386Sopenharmony_ci CTFontDescriptorCreateWithAttributes(cfAttr.get())); 440cb93a386Sopenharmony_ci return new SkFontStyleSet_Mac(desc.get()); 441cb93a386Sopenharmony_ci } 442cb93a386Sopenharmony_ci 443cb93a386Sopenharmony_cipublic: 444cb93a386Sopenharmony_ci SkUniqueCFRef<CTFontCollectionRef> fFontCollection; 445cb93a386Sopenharmony_ci SkFontMgr_Mac(CTFontCollectionRef fontCollection) 446cb93a386Sopenharmony_ci : fNames(fontCollection ? SkCopyAvailableFontFamilyNames(fontCollection) 447cb93a386Sopenharmony_ci : SkCTFontManagerCopyAvailableFontFamilyNames()) 448cb93a386Sopenharmony_ci , fCount(fNames ? SkToInt(CFArrayGetCount(fNames.get())) : 0) 449cb93a386Sopenharmony_ci , fFontCollection(fontCollection ? (CTFontCollectionRef)CFRetain(fontCollection) 450cb93a386Sopenharmony_ci : CTFontCollectionCreateFromAvailableFonts(nullptr)) 451cb93a386Sopenharmony_ci {} 452cb93a386Sopenharmony_ci 453cb93a386Sopenharmony_ciprotected: 454cb93a386Sopenharmony_ci int onCountFamilies() const override { 455cb93a386Sopenharmony_ci return fCount; 456cb93a386Sopenharmony_ci } 457cb93a386Sopenharmony_ci 458cb93a386Sopenharmony_ci void onGetFamilyName(int index, SkString* familyName) const override { 459cb93a386Sopenharmony_ci if ((unsigned)index < (unsigned)fCount) { 460cb93a386Sopenharmony_ci SkStringFromCFString(this->getFamilyNameAt(index), familyName); 461cb93a386Sopenharmony_ci } else { 462cb93a386Sopenharmony_ci familyName->reset(); 463cb93a386Sopenharmony_ci } 464cb93a386Sopenharmony_ci } 465cb93a386Sopenharmony_ci 466cb93a386Sopenharmony_ci SkFontStyleSet* onCreateStyleSet(int index) const override { 467cb93a386Sopenharmony_ci if ((unsigned)index >= (unsigned)fCount) { 468cb93a386Sopenharmony_ci return nullptr; 469cb93a386Sopenharmony_ci } 470cb93a386Sopenharmony_ci return CreateSet(this->getFamilyNameAt(index)); 471cb93a386Sopenharmony_ci } 472cb93a386Sopenharmony_ci 473cb93a386Sopenharmony_ci SkFontStyleSet* onMatchFamily(const char familyName[]) const override { 474cb93a386Sopenharmony_ci if (!familyName) { 475cb93a386Sopenharmony_ci return nullptr; 476cb93a386Sopenharmony_ci } 477cb93a386Sopenharmony_ci SkUniqueCFRef<CFStringRef> cfName = make_CFString(familyName); 478cb93a386Sopenharmony_ci return CreateSet(cfName.get()); 479cb93a386Sopenharmony_ci } 480cb93a386Sopenharmony_ci 481cb93a386Sopenharmony_ci SkTypeface* onMatchFamilyStyle(const char familyName[], 482cb93a386Sopenharmony_ci const SkFontStyle& style) const override { 483cb93a386Sopenharmony_ci SkUniqueCFRef<CTFontDescriptorRef> desc = create_descriptor(familyName, style); 484cb93a386Sopenharmony_ci return create_from_desc(desc.get()).release(); 485cb93a386Sopenharmony_ci } 486cb93a386Sopenharmony_ci 487cb93a386Sopenharmony_ci SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], 488cb93a386Sopenharmony_ci const SkFontStyle& style, 489cb93a386Sopenharmony_ci const char* bcp47[], int bcp47Count, 490cb93a386Sopenharmony_ci SkUnichar character) const override { 491cb93a386Sopenharmony_ci SkUniqueCFRef<CTFontDescriptorRef> desc = create_descriptor(familyName, style); 492cb93a386Sopenharmony_ci SkUniqueCFRef<CTFontRef> familyFont(CTFontCreateWithFontDescriptor(desc.get(), 0, nullptr)); 493cb93a386Sopenharmony_ci 494cb93a386Sopenharmony_ci // kCFStringEncodingUTF32 is BE unless there is a BOM. 495cb93a386Sopenharmony_ci // Since there is no machine endian option, explicitly state machine endian. 496cb93a386Sopenharmony_ci#ifdef SK_CPU_LENDIAN 497cb93a386Sopenharmony_ci constexpr CFStringEncoding encoding = kCFStringEncodingUTF32LE; 498cb93a386Sopenharmony_ci#else 499cb93a386Sopenharmony_ci constexpr CFStringEncoding encoding = kCFStringEncodingUTF32BE; 500cb93a386Sopenharmony_ci#endif 501cb93a386Sopenharmony_ci SkUniqueCFRef<CFStringRef> string(CFStringCreateWithBytes( 502cb93a386Sopenharmony_ci kCFAllocatorDefault, reinterpret_cast<const UInt8 *>(&character), sizeof(character), 503cb93a386Sopenharmony_ci encoding, false)); 504cb93a386Sopenharmony_ci // If 0xD800 <= codepoint <= 0xDFFF || 0x10FFFF < codepoint 'string' may be nullptr. 505cb93a386Sopenharmony_ci // No font should be covering such codepoints (even the magic fallback font). 506cb93a386Sopenharmony_ci if (!string) { 507cb93a386Sopenharmony_ci return nullptr; 508cb93a386Sopenharmony_ci } 509cb93a386Sopenharmony_ci CFRange range = CFRangeMake(0, CFStringGetLength(string.get())); // in UniChar units. 510cb93a386Sopenharmony_ci SkUniqueCFRef<CTFontRef> fallbackFont( 511cb93a386Sopenharmony_ci CTFontCreateForString(familyFont.get(), string.get(), range)); 512cb93a386Sopenharmony_ci return SkTypeface_Mac::Make(std::move(fallbackFont), OpszVariation(), nullptr).release(); 513cb93a386Sopenharmony_ci } 514cb93a386Sopenharmony_ci 515cb93a386Sopenharmony_ci sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData> data, int ttcIndex) const override { 516cb93a386Sopenharmony_ci if (ttcIndex != 0) { 517cb93a386Sopenharmony_ci return nullptr; 518cb93a386Sopenharmony_ci } 519cb93a386Sopenharmony_ci 520cb93a386Sopenharmony_ci SkUniqueCFRef<CTFontRef> ct = ctfont_from_skdata(data, ttcIndex); 521cb93a386Sopenharmony_ci if (!ct) { 522cb93a386Sopenharmony_ci return nullptr; 523cb93a386Sopenharmony_ci } 524cb93a386Sopenharmony_ci 525cb93a386Sopenharmony_ci return SkTypeface_Mac::Make(std::move(ct), OpszVariation(), 526cb93a386Sopenharmony_ci SkMemoryStream::Make(std::move(data))); 527cb93a386Sopenharmony_ci } 528cb93a386Sopenharmony_ci 529cb93a386Sopenharmony_ci sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream, 530cb93a386Sopenharmony_ci int ttcIndex) const override { 531cb93a386Sopenharmony_ci if (ttcIndex != 0) { 532cb93a386Sopenharmony_ci return nullptr; 533cb93a386Sopenharmony_ci } 534cb93a386Sopenharmony_ci 535cb93a386Sopenharmony_ci sk_sp<SkData> data = skdata_from_skstreamasset(stream->duplicate()); 536cb93a386Sopenharmony_ci if (!data) { 537cb93a386Sopenharmony_ci return nullptr; 538cb93a386Sopenharmony_ci } 539cb93a386Sopenharmony_ci SkUniqueCFRef<CTFontRef> ct = ctfont_from_skdata(std::move(data), ttcIndex); 540cb93a386Sopenharmony_ci if (!ct) { 541cb93a386Sopenharmony_ci return nullptr; 542cb93a386Sopenharmony_ci } 543cb93a386Sopenharmony_ci 544cb93a386Sopenharmony_ci return SkTypeface_Mac::Make(std::move(ct), OpszVariation(), std::move(stream)); 545cb93a386Sopenharmony_ci } 546cb93a386Sopenharmony_ci 547cb93a386Sopenharmony_ci sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream, 548cb93a386Sopenharmony_ci const SkFontArguments& args) const override 549cb93a386Sopenharmony_ci { 550cb93a386Sopenharmony_ci // TODO: Use CTFontManagerCreateFontDescriptorsFromData when available. 551cb93a386Sopenharmony_ci int ttcIndex = args.getCollectionIndex(); 552cb93a386Sopenharmony_ci if (ttcIndex != 0) { 553cb93a386Sopenharmony_ci return nullptr; 554cb93a386Sopenharmony_ci } 555cb93a386Sopenharmony_ci 556cb93a386Sopenharmony_ci sk_sp<SkData> data = skdata_from_skstreamasset(stream->duplicate()); 557cb93a386Sopenharmony_ci if (!data) { 558cb93a386Sopenharmony_ci return nullptr; 559cb93a386Sopenharmony_ci } 560cb93a386Sopenharmony_ci SkUniqueCFRef<CTFontRef> ct = ctfont_from_skdata(std::move(data), ttcIndex); 561cb93a386Sopenharmony_ci if (!ct) { 562cb93a386Sopenharmony_ci return nullptr; 563cb93a386Sopenharmony_ci } 564cb93a386Sopenharmony_ci 565cb93a386Sopenharmony_ci CTFontVariation ctVariation = SkCTVariationFromSkFontArguments(ct.get(), args); 566cb93a386Sopenharmony_ci 567cb93a386Sopenharmony_ci SkUniqueCFRef<CTFontRef> ctVariant; 568cb93a386Sopenharmony_ci if (ctVariation.variation) { 569cb93a386Sopenharmony_ci SkUniqueCFRef<CFMutableDictionaryRef> attributes( 570cb93a386Sopenharmony_ci CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 571cb93a386Sopenharmony_ci &kCFTypeDictionaryKeyCallBacks, 572cb93a386Sopenharmony_ci &kCFTypeDictionaryValueCallBacks)); 573cb93a386Sopenharmony_ci CFDictionaryAddValue(attributes.get(), 574cb93a386Sopenharmony_ci kCTFontVariationAttribute, ctVariation.variation.get()); 575cb93a386Sopenharmony_ci SkUniqueCFRef<CTFontDescriptorRef> varDesc( 576cb93a386Sopenharmony_ci CTFontDescriptorCreateWithAttributes(attributes.get())); 577cb93a386Sopenharmony_ci ctVariant.reset(CTFontCreateCopyWithAttributes(ct.get(), 0, nullptr, varDesc.get())); 578cb93a386Sopenharmony_ci } else { 579cb93a386Sopenharmony_ci ctVariant.reset(ct.release()); 580cb93a386Sopenharmony_ci } 581cb93a386Sopenharmony_ci if (!ctVariant) { 582cb93a386Sopenharmony_ci return nullptr; 583cb93a386Sopenharmony_ci } 584cb93a386Sopenharmony_ci 585cb93a386Sopenharmony_ci return SkTypeface_Mac::Make(std::move(ctVariant), ctVariation.opsz, std::move(stream)); 586cb93a386Sopenharmony_ci } 587cb93a386Sopenharmony_ci 588cb93a386Sopenharmony_ci sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override { 589cb93a386Sopenharmony_ci if (ttcIndex != 0) { 590cb93a386Sopenharmony_ci return nullptr; 591cb93a386Sopenharmony_ci } 592cb93a386Sopenharmony_ci 593cb93a386Sopenharmony_ci sk_sp<SkData> data = SkData::MakeFromFileName(path); 594cb93a386Sopenharmony_ci if (!data) { 595cb93a386Sopenharmony_ci return nullptr; 596cb93a386Sopenharmony_ci } 597cb93a386Sopenharmony_ci 598cb93a386Sopenharmony_ci return this->onMakeFromData(std::move(data), ttcIndex); 599cb93a386Sopenharmony_ci } 600cb93a386Sopenharmony_ci 601cb93a386Sopenharmony_ci sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle style) const override { 602cb93a386Sopenharmony_ci if (familyName) { 603cb93a386Sopenharmony_ci familyName = map_css_names(familyName); 604cb93a386Sopenharmony_ci } 605cb93a386Sopenharmony_ci 606cb93a386Sopenharmony_ci sk_sp<SkTypeface> face = create_from_name(familyName, style); 607cb93a386Sopenharmony_ci if (face) { 608cb93a386Sopenharmony_ci return face; 609cb93a386Sopenharmony_ci } 610cb93a386Sopenharmony_ci 611cb93a386Sopenharmony_ci static SkTypeface* gDefaultFace; 612cb93a386Sopenharmony_ci static SkOnce lookupDefault; 613cb93a386Sopenharmony_ci static const char FONT_DEFAULT_NAME[] = "Lucida Sans"; 614cb93a386Sopenharmony_ci lookupDefault([]{ 615cb93a386Sopenharmony_ci gDefaultFace = create_from_name(FONT_DEFAULT_NAME, SkFontStyle()).release(); 616cb93a386Sopenharmony_ci }); 617cb93a386Sopenharmony_ci return sk_ref_sp(gDefaultFace); 618cb93a386Sopenharmony_ci } 619cb93a386Sopenharmony_ci}; 620cb93a386Sopenharmony_ci 621cb93a386Sopenharmony_cisk_sp<SkFontMgr> SkFontMgr_New_CoreText(CTFontCollectionRef fontCollection) { 622cb93a386Sopenharmony_ci return sk_make_sp<SkFontMgr_Mac>(fontCollection); 623cb93a386Sopenharmony_ci} 624cb93a386Sopenharmony_ci 625cb93a386Sopenharmony_ci#endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) 626