Fix styling of system fonts

Summary:
When you call `-[RCTConvert UIFont:withFamily:...]` with a non-nil font object, we'll try to use the existing font object for system information. On iOS9+ which uses the San Francisco font, `[UIFont fontNamesForFamilyName:]` doesn't return anything useful, so we need to make sure that we detect this as a system font and use the appropriate methods. This issues is made worse by the fact that RCTTextView and friends recreate the font property for every attribute that is set (pretty horrible perf-wise).

This fixes https://github.com/facebook/react-native/issues/2140

Reviewed By: sahrens

Differential Revision: D3662751

fbshipit-source-id: c528e8945ed361a922c03f861d3c0b584658573b
This commit is contained in:
Pieter De Baets 2016-08-05 12:29:15 -07:00 committed by Facebook Github Bot 2
parent 8f75d7346f
commit e30327cb13
1 changed files with 18 additions and 37 deletions

View File

@ -481,24 +481,6 @@ RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[
return [self UIColor:json].CGColor; return [self UIColor:json].CGColor;
} }
#if !defined(__IPHONE_8_2) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_2
// These constants are defined in iPhone SDK 8.2, but the app cannot run on
// iOS < 8.2 unless we redefine them here. If you target iOS 8.2 or above
// as a base target, the standard constants will be used instead.
#define UIFontWeightUltraLight -0.8
#define UIFontWeightThin -0.6
#define UIFontWeightLight -0.4
#define UIFontWeightRegular 0
#define UIFontWeightMedium 0.23
#define UIFontWeightSemibold 0.3
#define UIFontWeightBold 0.4
#define UIFontWeightHeavy 0.56
#define UIFontWeightBlack 0.62
#endif
typedef CGFloat RCTFontWeight; typedef CGFloat RCTFontWeight;
RCT_ENUM_CONVERTER(RCTFontWeight, (@{ RCT_ENUM_CONVERTER(RCTFontWeight, (@{
@"normal": @(UIFontWeightRegular), @"normal": @(UIFontWeightRegular),
@ -575,27 +557,27 @@ static BOOL RCTFontIsCondensed(UIFont *font)
size:json[@"fontSize"] size:json[@"fontSize"]
weight:json[@"fontWeight"] weight:json[@"fontWeight"]
style:json[@"fontStyle"] style:json[@"fontStyle"]
scaleMultiplier:1.0f]; scaleMultiplier:1];
} }
+ (UIFont *)UIFont:(UIFont *)font withSize:(id)json + (UIFont *)UIFont:(UIFont *)font withSize:(id)json
{ {
return [self UIFont:font withFamily:nil size:json weight:nil style:nil scaleMultiplier:1.0]; return [self UIFont:font withFamily:nil size:json weight:nil style:nil scaleMultiplier:1];
} }
+ (UIFont *)UIFont:(UIFont *)font withWeight:(id)json + (UIFont *)UIFont:(UIFont *)font withWeight:(id)json
{ {
return [self UIFont:font withFamily:nil size:nil weight:json style:nil scaleMultiplier:1.0]; return [self UIFont:font withFamily:nil size:nil weight:json style:nil scaleMultiplier:1];
} }
+ (UIFont *)UIFont:(UIFont *)font withStyle:(id)json + (UIFont *)UIFont:(UIFont *)font withStyle:(id)json
{ {
return [self UIFont:font withFamily:nil size:nil weight:nil style:json scaleMultiplier:1.0]; return [self UIFont:font withFamily:nil size:nil weight:nil style:json scaleMultiplier:1];
} }
+ (UIFont *)UIFont:(UIFont *)font withFamily:(id)json + (UIFont *)UIFont:(UIFont *)font withFamily:(id)json
{ {
return [self UIFont:font withFamily:json size:nil weight:nil style:nil scaleMultiplier:1.0]; return [self UIFont:font withFamily:json size:nil weight:nil style:nil scaleMultiplier:1];
} }
+ (UIFont *)UIFont:(UIFont *)font withFamily:(id)family + (UIFont *)UIFont:(UIFont *)font withFamily:(id)family
@ -603,21 +585,24 @@ static BOOL RCTFontIsCondensed(UIFont *font)
scaleMultiplier:(CGFloat)scaleMultiplier scaleMultiplier:(CGFloat)scaleMultiplier
{ {
// Defaults // Defaults
NSString *const RCTDefaultFontFamily = @"System"; static NSString *defaultFontFamily;
NSString *const RCTIOS8SystemFontFamily = @"Helvetica Neue"; static dispatch_once_t onceToken;
const RCTFontWeight RCTDefaultFontWeight = UIFontWeightRegular; dispatch_once(&onceToken, ^{
const CGFloat RCTDefaultFontSize = 14; defaultFontFamily = [UIFont systemFontOfSize:14].familyName;
});
const RCTFontWeight defaultFontWeight = UIFontWeightRegular;
const CGFloat defaultFontSize = 14;
// Initialize properties to defaults // Initialize properties to defaults
CGFloat fontSize = RCTDefaultFontSize; CGFloat fontSize = defaultFontSize;
RCTFontWeight fontWeight = RCTDefaultFontWeight; RCTFontWeight fontWeight = defaultFontWeight;
NSString *familyName = RCTDefaultFontFamily; NSString *familyName = defaultFontFamily;
BOOL isItalic = NO; BOOL isItalic = NO;
BOOL isCondensed = NO; BOOL isCondensed = NO;
if (font) { if (font) {
familyName = font.familyName ?: RCTDefaultFontFamily; familyName = font.familyName ?: defaultFontFamily;
fontSize = font.pointSize ?: RCTDefaultFontSize; fontSize = font.pointSize ?: defaultFontSize;
fontWeight = RCTWeightOfFont(font); fontWeight = RCTWeightOfFont(font);
isItalic = RCTFontIsItalic(font); isItalic = RCTFontIsItalic(font);
isCondensed = RCTFontIsCondensed(font); isCondensed = RCTFontIsCondensed(font);
@ -634,7 +619,7 @@ static BOOL RCTFontIsCondensed(UIFont *font)
// Handle system font as special case. This ensures that we preserve // Handle system font as special case. This ensures that we preserve
// the specific metrics of the standard system font as closely as possible. // the specific metrics of the standard system font as closely as possible.
if ([familyName isEqual:RCTDefaultFontFamily]) { if ([familyName isEqual:defaultFontFamily] || [familyName isEqualToString:@"System"]) {
if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) { if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) {
font = [UIFont systemFontOfSize:fontSize weight:fontWeight]; font = [UIFont systemFontOfSize:fontSize weight:fontWeight];
if (isItalic || isCondensed) { if (isItalic || isCondensed) {
@ -650,10 +635,6 @@ static BOOL RCTFontIsCondensed(UIFont *font)
font = [UIFont fontWithDescriptor:fontDescriptor size:fontSize]; font = [UIFont fontWithDescriptor:fontDescriptor size:fontSize];
} }
return font; return font;
} else {
// systemFontOfSize:weight: isn't available prior to iOS 8.2, so we
// fall back to finding the correct font manually, by linear search.
familyName = RCTIOS8SystemFontFamily;
} }
} }