Merge commit '4ac42d88ef60ae3fed7319851d47b93e98ac9afa' into 0.67-merge-latest

This commit is contained in:
Adam Gleitman 2022-04-25 13:42:18 -07:00
Родитель fc187699ce 4ac42d88ef
Коммит eae4af0916
3 изменённых файлов: 59 добавлений и 47 удалений

1
BUCK
Просмотреть файл

@ -376,6 +376,7 @@ rn_xplat_cxx_library2(
"$SDKROOT/System/Library/Frameworks/CFNetwork.framework",
"$SDKROOT/System/Library/Frameworks/CoreGraphics.framework",
"$SDKROOT/System/Library/Frameworks/CoreLocation.framework",
"$SDKROOT/System/Library/Frameworks/CoreText.framework",
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
"$SDKROOT/System/Library/Frameworks/MapKit.framework",
"$SDKROOT/System/Library/Frameworks/QuartzCore.framework",

Просмотреть файл

@ -11,18 +11,16 @@
#import <CoreText/CoreText.h>
#import <mutex>
typedef CGFloat RCTFontWeight;
static RCTFontWeight weightOfFont(UIFont *font)
{
static NSArray *fontNames;
static NSArray *fontWeights;
static NSArray<NSString *> *weightSuffixes;
static NSArray<NSNumber *> *fontWeights;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// We use two arrays instead of one map because
// the order is important for suffix matching.
fontNames = @[
weightSuffixes = @[
@"normal",
@"ultralight",
@"thin",
@ -54,28 +52,29 @@ static RCTFontWeight weightOfFont(UIFont *font)
];
});
for (NSInteger i = 0; i < 0 || i < (unsigned)fontNames.count; i++) {
if ([font.fontName.lowercaseString hasSuffix:fontNames[i]]) {
return (RCTFontWeight)[fontWeights[i] doubleValue];
NSString *fontName = font.fontName;
NSInteger i = 0;
for (NSString *suffix in weightSuffixes) {
// CFStringFind is much faster than any variant of rangeOfString: because it does not use a locale.
auto options = kCFCompareCaseInsensitive | kCFCompareAnchored | kCFCompareBackwards;
if (CFStringFind((CFStringRef)fontName, (CFStringRef)suffix, options).location != kCFNotFound) {
return (RCTFontWeight)fontWeights[i].doubleValue;
}
i++;
}
NSDictionary *traits = [font.fontDescriptor objectForKey:UIFontDescriptorTraitsAttribute];
auto traits = (__bridge_transfer NSDictionary *)CTFontCopyTraits((CTFontRef)font);
return (RCTFontWeight)[traits[UIFontWeightTrait] doubleValue];
}
static BOOL isItalicFont(UIFont *font)
{
NSDictionary *traits = [font.fontDescriptor objectForKey:UIFontDescriptorTraitsAttribute];
UIFontDescriptorSymbolicTraits symbolicTraits = [traits[UIFontSymbolicTrait] unsignedIntValue];
return (symbolicTraits & UIFontDescriptorTraitItalic) != 0;
return (CTFontGetSymbolicTraits((CTFontRef)font) & kCTFontTraitItalic) != 0;
}
static BOOL isCondensedFont(UIFont *font)
{
NSDictionary *traits = [font.fontDescriptor objectForKey:UIFontDescriptorTraitsAttribute];
UIFontDescriptorSymbolicTraits symbolicTraits = [traits[UIFontSymbolicTrait] unsignedIntValue];
return (symbolicTraits & UIFontDescriptorTraitCondensed) != 0;
return (CTFontGetSymbolicTraits((CTFontRef)font) & kCTFontTraitCondensed) != 0;
}
static RCTFontHandler defaultFontHandler;
@ -130,18 +129,16 @@ static NSString *FontWeightDescriptionFromUIFontWeight(UIFontWeight fontWeight)
static UIFont *cachedSystemFont(CGFloat size, RCTFontWeight weight)
{
static NSCache *fontCache;
static std::mutex *fontCacheMutex = new std::mutex;
static NSCache<NSValue *, UIFont *> *fontCache = [NSCache new];
NSString *cacheKey = [NSString stringWithFormat:@"%.1f/%.2f", size, weight];
UIFont *font;
{
std::lock_guard<std::mutex> lock(*fontCacheMutex);
if (!fontCache) {
fontCache = [NSCache new];
}
font = [fontCache objectForKey:cacheKey];
}
struct __attribute__((__packed__)) CacheKey {
CGFloat size;
RCTFontWeight weight;
};
CacheKey key{size, weight};
NSValue *cacheKey = [[NSValue alloc] initWithBytes:&key objCType:@encode(CacheKey)];
UIFont *font = [fontCache objectForKey:cacheKey];
if (!font) {
if (defaultFontHandler) {
@ -157,27 +154,43 @@ static UIFont *cachedSystemFont(CGFloat size, RCTFontWeight weight)
font = [UIFont systemFontOfSize:size weight:weight];
}
{
std::lock_guard<std::mutex> lock(*fontCacheMutex);
[fontCache setObject:font forKey:cacheKey];
}
}
return font;
}
static NSArray<NSString *> *fontNamesForFamilyName(NSString *familyName) // [TODO(macOS GH#774)
// Caching wrapper around expensive +[UIFont fontNamesForFamilyName:]
static NSArray<NSString *> *fontNamesForFamilyName(NSString *familyName)
{
#if !TARGET_OS_OSX
return [UIFont fontNamesForFamilyName:familyName];
static NSCache<NSString *, NSArray<NSString *> *> *cache;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
cache = [NSCache new];
[NSNotificationCenter.defaultCenter
addObserverForName:(NSNotificationName)kCTFontManagerRegisteredFontsChangedNotification
object:nil
queue:nil
usingBlock:^(NSNotification *) {
[cache removeAllObjects];
}];
});
auto names = [cache objectForKey:familyName];
if (!names) {
#if !TARGET_OS_OSX // [TODO(macOS GH#774)
names = [UIFont fontNamesForFamilyName:familyName];
#else
NSMutableArray<NSString *> *fontNames = [NSMutableArray array];
for (NSArray *fontSettings in [[NSFontManager sharedFontManager] availableMembersOfFontFamily:familyName]) {
[fontNames addObject:fontSettings[0]];
}
return fontNames;
#endif
} // ]TODO(macOS GH#774)
names = fontNames;
#endif // ]TODO(macOS GH#774)
[cache setObject:names forKey:familyName];
}
return names;
}
@implementation RCTConvert (RCTFont)
@ -334,7 +347,7 @@ RCT_ARRAY_CONVERTER(RCTFontVariantDescriptor)
// Gracefully handle being given a font name rather than font family, for
// example: "Helvetica Light Oblique" rather than just "Helvetica".
if (!didFindFont && fontNamesForFamilyName(familyName).count == 0) { // TODO(macOS GH#774)
if (!didFindFont && fontNamesForFamilyName(familyName).count == 0) {
font = [UIFont fontWithName:familyName size:fontSize];
if (font) {
// It's actually a font name, not a font family name,
@ -361,7 +374,8 @@ RCT_ARRAY_CONVERTER(RCTFontVariantDescriptor)
// Get the closest font that matches the given weight for the fontFamily
CGFloat closestWeight = INFINITY;
for (NSString *name in fontNamesForFamilyName(familyName)) { // TODO(macOS GH#774)
NSArray<NSString *> *names = fontNamesForFamilyName(familyName);
for (NSString *name in names) {
UIFont *match = [UIFont fontWithName:name size:fontSize];
if (isItalic == isItalicFont(match) && isCondensed == isCondensedFont(match)) {
CGFloat testWeight = weightOfFont(match);
@ -374,12 +388,9 @@ RCT_ARRAY_CONVERTER(RCTFontVariantDescriptor)
// If we still don't have a match at least return the first font in the fontFamily
// This is to support built-in font Zapfino and other custom single font families like Impact
if (!font) {
NSArray *names = fontNamesForFamilyName(familyName); // TODO(macOS GH#774)
if (names.count > 0) {
if (!font && names.count > 0) {
font = [UIFont fontWithName:names[0] size:fontSize];
}
}
// Apply font variants to font object
if (variant) {

Просмотреть файл

@ -20,7 +20,7 @@
// will be different objects, but the same font, so this macro now explicitly
// checks that fontName (which includes the style) and pointSize are equal.
#define RCTAssertEqualFonts(font1, font2) { \
XCTAssertTrue([font1.fontName isEqualToString:font2.fontName]); \
XCTAssertEqualObjects(font1.fontName, font2.fontName); \
XCTAssertEqual(font1.pointSize,font2.pointSize); \
}