// 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.
// The fallbackFont has the character but there may be a better style match since familyName // may have had different weights available than the fallbackFont's family. // Check to see if there is a better match with the fallbackFont's family name.
// This is a good example of why fallback must be collection and not font based. // Being font based requires that fallback start from a font which, because it is resolved, // has lost request information. When fallback is on the collection then the request can be // made directly.
// Because collection fallback does not appear to exist in CoreText and there is no direct // notion of families, it appears one must pretend like the family name is the family key // and try to make that work. This is generally very bad idea (one should never take the // family name from a font and then do a lookup based on it) but in this case there appears // to be no good work-around. Use of CTFontCreateCopyWithAttributes will do the match with // the font name (PostScript name) and so never find a different font. In any event, there // is a known backup (just return fallbackFont) if the lookup by family name does not work // or the result doesn't actually cover the character.
SkUniqueCFRef<CFStringRef> fallbackFamilyName(CTFontCopyFamilyName(fallbackFont.get())); if (fallbackFamilyName &&
CFStringGetLength(fallbackFamilyName.get()) > 0 &&
CFStringGetCharacterAtIndex(fallbackFamilyName.get(), 0) != '.')
{
SkUniqueCFRef<CTFontDescriptorRef> styledFallbackDesc =
create_descriptor(fallbackFamilyName.get(), style); if (styledFallbackDesc) {
SkUniqueCFRef<CTFontRef> styledFallbackFont(
CTFontCreateWithFontDescriptor(styledFallbackDesc.get(), 0, nullptr)); if (styledFallbackFont && has_character(styledFallbackFont.get(), character)) {
fallbackFont = std::move(styledFallbackFont);
}
}
}
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.