/* * Copyright 2006 The Android Open Source Project * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file.
*/
static uint32_t SkGetCoreTextVersion() { // If compiling for iOS 14.0+ or macOS 11.0+, the CoreText version number // must be derived from the OS version number. staticconst uint32_t kCoreTextVersionNEWER = 0x000D0000; return kCoreTextVersionNEWER;
}
#else
static uint32_t SkGetCoreTextVersion() { // Check for CoreText availability before calling CTGetCoreTextVersion(). staticconstbool kCoreTextIsAvailable = (&CTGetCoreTextVersion != nullptr); if (kCoreTextIsAvailable) { return CTGetCoreTextVersion();
}
// Default to a value that's smaller than any known CoreText version. staticconst uint32_t kCoreTextVersionUNKNOWN = 0; return kCoreTextVersionUNKNOWN;
}
if (!cfAttributes || !cfTraits) { return nullptr;
}
// TODO(crbug.com/1018581) Some CoreText versions have errant behavior when // certain traits set. Temporary workaround to omit specifying trait for those // versions. // Long term solution will involve serializing typefaces instead of relying upon // this to match between processes. // // Compare CoreText.h in an up to date SDK for where these values come from. staticconst uint32_t kSkiaLocalCTVersionNumber10_14 = 0x000B0000; staticconst uint32_t kSkiaLocalCTVersionNumber10_15 = 0x000C0000;
// CTFontTraits (symbolic) // macOS 14 and iOS 12 seem to behave badly when kCTFontSymbolicTrait is set. // macOS 15 yields LastResort font instead of a good default font when // kCTFontSymbolicTrait is set. if (SkGetCoreTextVersion() < kSkiaLocalCTVersionNumber10_14) {
CTFontSymbolicTraits ctFontTraits = 0; if (style.weight() >= SkFontStyle::kBold_Weight) {
ctFontTraits |= kCTFontBoldTrait;
} if (style.slant() != SkFontStyle::kUpright_Slant) {
ctFontTraits |= kCTFontItalicTrait;
}
SkUniqueCFRef<CFNumberRef> cfFontTraits(
CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTraits)); if (cfFontTraits) {
CFDictionaryAddValue(cfTraits.get(), kCTFontSymbolicTrait, cfFontTraits.get());
}
}
// Same as the above function except style is included so we can // compare whether the created font conforms to the style. If not, we need // to recreate the font with symbolic traits. This is needed due to MacOS 10.11 // font creation problem https://bugs.chromium.org/p/skia/issues/detail?id=8447. static sk_sp<SkTypeface> create_from_desc_and_style(CTFontDescriptorRef desc, const SkFontStyle& style) {
SkUniqueCFRef<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc, 0, nullptr)); if (!ctFont) { return nullptr;
}
for (int i = 0; i < fCount; ++i) {
CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), i); int metric = compute_metric(pattern, SkCTFontDescriptorGetSkFontStyle(desc, false)); if (0 == metric) { return desc;
} if (metric < bestMetric) {
bestMetric = metric;
bestDesc = desc;
}
}
SkASSERT(bestDesc); return bestDesc;
}
};
SkUniqueCFRef<CFArrayRef> SkCopyAvailableFontFamilyNames(CTFontCollectionRef collection) { // Create a CFArray of all available font descriptors.
SkUniqueCFRef<CFArrayRef> descriptors(
CTFontCollectionCreateMatchingFontDescriptors(collection));
// Copy the font family names of the font descriptors into a CFSet. auto addDescriptorFamilyNameToSet = [](constvoid* value, void* context) -> void {
CTFontDescriptorRef descriptor = static_cast<CTFontDescriptorRef>(value);
CFMutableSetRef familyNameSet = static_cast<CFMutableSetRef>(context);
SkUniqueCFRef<CFTypeRef> familyName(
CTFontDescriptorCopyAttribute(descriptor, kCTFontFamilyNameAttribute)); if (familyName) {
CFSetAddValue(familyNameSet, familyName.get());
}
};
SkUniqueCFRef<CFMutableSetRef> familyNameSet(
CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks));
CFArrayApplyFunction(descriptors.get(), CFRangeMake(0, CFArrayGetCount(descriptors.get())),
addDescriptorFamilyNameToSet, familyNameSet.get());
// Get the set of family names into an array; this does not retain.
CFIndex count = CFSetGetCount(familyNameSet.get());
std::unique_ptr<constvoid*[]> familyNames(newconstvoid*[count]);
CFSetGetValues(familyNameSet.get(), familyNames.get());
// Sort the array of family names (to match CTFontManagerCopyAvailableFontFamilyNames).
std::sort(familyNames.get(), familyNames.get() + count, [](constvoid* a, constvoid* b){ return CFStringCompare((CFStringRef)a, (CFStringRef)b, 0) == kCFCompareLessThan;
});
// Copy family names into a CFArray; this does retain. return SkUniqueCFRef<CFArrayRef>(
CFArrayCreate(kCFAllocatorDefault, familyNames.get(), count, &kCFTypeArrayCallBacks));
}
/** Use CTFontManagerCopyAvailableFontFamilyNames if available, simulate if not. */
SkUniqueCFRef<CFArrayRef> SkCTFontManagerCopyAvailableFontFamilyNames() { #ifdef SK_BUILD_FOR_IOS using CTFontManagerCopyAvailableFontFamilyNamesProc = CFArrayRef (*)(void);
CTFontManagerCopyAvailableFontFamilyNamesProc ctFontManagerCopyAvailableFontFamilyNames;
*(void**)(&ctFontManagerCopyAvailableFontFamilyNames) =
dlsym(RTLD_DEFAULT, "CTFontManagerCopyAvailableFontFamilyNames"); if (ctFontManagerCopyAvailableFontFamilyNames) { return SkUniqueCFRef<CFArrayRef>(ctFontManagerCopyAvailableFontFamilyNames());
}
SkUniqueCFRef<CTFontCollectionRef> collection(
CTFontCollectionCreateFromAvailableFonts(nullptr)); return SkUniqueCFRef<CFArrayRef>(SkCopyAvailableFontFamilyNames(collection.get())); #else return SkUniqueCFRef<CFArrayRef>(CTFontManagerCopyAvailableFontFamilyNames()); #endif
}
} // namespace
class SkFontMgr_Mac : public SkFontMgr {
SkUniqueCFRef<CFArrayRef> fNames; int fCount;
// kCFStringEncodingUTF32 is BE unless there is a BOM. // Since there is no machine endian option, explicitly state machine endian. #ifdef SK_CPU_LENDIAN
constexpr CFStringEncoding encoding = kCFStringEncodingUTF32LE; #else
constexpr CFStringEncoding encoding = kCFStringEncodingUTF32BE; #endif
SkUniqueCFRef<CFStringRef> string(CFStringCreateWithBytes(
kCFAllocatorDefault, reinterpret_cast<const UInt8 *>(&character), sizeof(character),
encoding, false)); // If 0xD800 <= codepoint <= 0xDFFF || 0x10FFFF < codepoint 'string' may be nullptr. // No font should be covering such codepoints (even the magic fallback font). if (!string) { return nullptr;
}
CFRange range = CFRangeMake(0, CFStringGetLength(string.get())); // in UniChar units.
SkUniqueCFRef<CTFontRef> fallbackFont(
CTFontCreateForString(familyFont.get(), string.get(), range)); return SkTypeface_Mac::Make(std::move(fallbackFont), OpszVariation(), nullptr);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.