Merge commit '4ac42d88ef60ae3fed7319851d47b93e98ac9afa' into 0.67-merge-latest
This commit is contained in:
Коммит
eae4af0916
1
BUCK
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];
|
||||
}
|
||||
[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]];
|
||||
NSMutableArray<NSString *> *fontNames = [NSMutableArray array];
|
||||
for (NSArray *fontSettings in [[NSFontManager sharedFontManager] availableMembersOfFontFamily:familyName]) {
|
||||
[fontNames addObject:fontSettings[0]];
|
||||
}
|
||||
names = fontNames;
|
||||
#endif // ]TODO(macOS GH#774)
|
||||
[cache setObject:names forKey:familyName];
|
||||
}
|
||||
return fontNames;
|
||||
#endif
|
||||
} // ]TODO(macOS GH#774)
|
||||
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,11 +388,8 @@ 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) {
|
||||
font = [UIFont fontWithName:names[0] size:fontSize];
|
||||
}
|
||||
if (!font && names.count > 0) {
|
||||
font = [UIFont fontWithName:names[0] size:fontSize];
|
||||
}
|
||||
|
||||
// Apply font variants to font object
|
||||
|
|
|
@ -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); \
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче