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