diff --git a/Examples/2048/Game2048.js b/Examples/2048/Game2048.js index 9ffaf42ba..009ba34a7 100644 --- a/Examples/2048/Game2048.js +++ b/Examples/2048/Game2048.js @@ -233,7 +233,7 @@ var styles = StyleSheet.create({ tryAgainText: { color: '#ffffff', fontSize: 20, - fontWeight: 'bold', + fontWeight: '500', }, cell: { width: CELL_SIZE, @@ -259,7 +259,7 @@ var styles = StyleSheet.create({ fontSize: 24, color: '#776666', fontFamily: 'Verdana', - fontWeight: 'bold', + fontWeight: '500', }, tile2: { backgroundColor: '#eeeeee', diff --git a/Examples/Movies/MovieCell.js b/Examples/Movies/MovieCell.js index 21c90ec24..42781ec24 100644 --- a/Examples/Movies/MovieCell.js +++ b/Examples/Movies/MovieCell.js @@ -62,7 +62,7 @@ var styles = StyleSheet.create({ movieTitle: { flex: 1, fontSize: 16, - fontWeight: 'bold', + fontWeight: '500', marginBottom: 2, }, movieYear: { diff --git a/Examples/Movies/MovieScreen.js b/Examples/Movies/MovieScreen.js index 980d51065..7c3ed316b 100644 --- a/Examples/Movies/MovieScreen.js +++ b/Examples/Movies/MovieScreen.js @@ -109,7 +109,7 @@ var styles = StyleSheet.create({ movieTitle: { flex: 1, fontSize: 16, - fontWeight: 'bold', + fontWeight: '500', }, rating: { marginTop: 10, @@ -119,7 +119,7 @@ var styles = StyleSheet.create({ }, ratingValue: { fontSize: 28, - fontWeight: 'bold', + fontWeight: '500', }, mpaaWrapper: { alignSelf: 'flex-start', @@ -131,7 +131,7 @@ var styles = StyleSheet.create({ mpaaText: { fontFamily: 'Palatino', fontSize: 13, - fontWeight: 'bold', + fontWeight: '500', }, mainSection: { flexDirection: 'row', @@ -148,7 +148,7 @@ var styles = StyleSheet.create({ marginVertical: 10, }, castTitle: { - fontWeight: 'bold', + fontWeight: '500', marginBottom: 3, }, castActor: { diff --git a/Examples/UIExplorer/ActionSheetIOSExample.js b/Examples/UIExplorer/ActionSheetIOSExample.js index b6425c507..00e6830af 100644 --- a/Examples/UIExplorer/ActionSheetIOSExample.js +++ b/Examples/UIExplorer/ActionSheetIOSExample.js @@ -101,7 +101,7 @@ var ShareActionSheetExample = React.createClass({ var style = StyleSheet.create({ button: { marginBottom: 10, - fontWeight: 'bold', + fontWeight: '500', } }); diff --git a/Examples/UIExplorer/AdSupportIOSExample.js b/Examples/UIExplorer/AdSupportIOSExample.js index 3c5ada96c..952cb7c8f 100644 --- a/Examples/UIExplorer/AdSupportIOSExample.js +++ b/Examples/UIExplorer/AdSupportIOSExample.js @@ -94,6 +94,6 @@ var AdSupportIOSExample = React.createClass({ var styles = StyleSheet.create({ title: { - fontWeight: 'bold', + fontWeight: '500', }, }); diff --git a/Examples/UIExplorer/DatePickerExample.js b/Examples/UIExplorer/DatePickerExample.js index 35fa869f3..cf4fa83d9 100644 --- a/Examples/UIExplorer/DatePickerExample.js +++ b/Examples/UIExplorer/DatePickerExample.js @@ -149,14 +149,14 @@ var styles = StyleSheet.create({ paddingVertical: 2, }, label: { - fontWeight: 'bold', + fontWeight: '500', }, headingContainer: { padding: 4, backgroundColor: '#f6f7f8', }, heading: { - fontWeight: 'bold', + fontWeight: '500', fontSize: 14, }, }); diff --git a/Examples/UIExplorer/GeolocationExample.js b/Examples/UIExplorer/GeolocationExample.js index 82f1c83eb..5d49f341e 100644 --- a/Examples/UIExplorer/GeolocationExample.js +++ b/Examples/UIExplorer/GeolocationExample.js @@ -74,6 +74,6 @@ var GeolocationExample = React.createClass({ var styles = StyleSheet.create({ title: { - fontWeight: 'bold', + fontWeight: '500', }, }); diff --git a/Examples/UIExplorer/NavigatorIOSExample.js b/Examples/UIExplorer/NavigatorIOSExample.js index 56bb6ab78..fd05caf14 100644 --- a/Examples/UIExplorer/NavigatorIOSExample.js +++ b/Examples/UIExplorer/NavigatorIOSExample.js @@ -214,7 +214,7 @@ var styles = StyleSheet.create({ }, rowText: { fontSize: 17, - fontWeight: 'bold', + fontWeight: '500', }, }); diff --git a/Examples/UIExplorer/ReactNavigator/BreadcrumbNavSample.js b/Examples/UIExplorer/ReactNavigator/BreadcrumbNavSample.js index 451da6656..17be12f8d 100644 --- a/Examples/UIExplorer/ReactNavigator/BreadcrumbNavSample.js +++ b/Examples/UIExplorer/ReactNavigator/BreadcrumbNavSample.js @@ -254,7 +254,7 @@ var styles = StyleSheet.create({ fontSize: 18, color: '#666666', textAlign: 'center', - fontWeight: 'bold', + fontWeight: '500', lineHeight: 32, }, filterText: { diff --git a/Examples/UIExplorer/ReactNavigator/NavigationBarSample.js b/Examples/UIExplorer/ReactNavigator/NavigationBarSample.js index ddb225552..5096cab71 100644 --- a/Examples/UIExplorer/ReactNavigator/NavigationBarSample.js +++ b/Examples/UIExplorer/ReactNavigator/NavigationBarSample.js @@ -107,7 +107,7 @@ var styles = StyleSheet.create({ }, navBarTitleText: { color: cssVar('fbui-bluegray-60'), - fontWeight: 'bold', + fontWeight: '500', marginVertical: 9, }, navBarButtonText: { diff --git a/Examples/UIExplorer/ReactNavigator/NestedBreadcrumbNavSample.js b/Examples/UIExplorer/ReactNavigator/NestedBreadcrumbNavSample.js index 263d8b738..20d857472 100644 --- a/Examples/UIExplorer/ReactNavigator/NestedBreadcrumbNavSample.js +++ b/Examples/UIExplorer/ReactNavigator/NestedBreadcrumbNavSample.js @@ -176,7 +176,7 @@ var styles = StyleSheet.create({ fontSize: 18, color: '#666666', textAlign: 'center', - fontWeight: 'bold', + fontWeight: '500', lineHeight: 32, }, filterText: { diff --git a/Examples/UIExplorer/SliderIOSExample.js b/Examples/UIExplorer/SliderIOSExample.js index ae6aca144..13eee593a 100644 --- a/Examples/UIExplorer/SliderIOSExample.js +++ b/Examples/UIExplorer/SliderIOSExample.js @@ -47,7 +47,7 @@ var styles = StyleSheet.create({ text: { fontSize: 14, textAlign: 'center', - fontWeight: 'bold', + fontWeight: '500', margin: 10, }, }); diff --git a/Examples/UIExplorer/TextExample.ios.js b/Examples/UIExplorer/TextExample.ios.js index e29b07da4..e88bc4a0c 100644 --- a/Examples/UIExplorer/TextExample.ios.js +++ b/Examples/UIExplorer/TextExample.ios.js @@ -29,7 +29,7 @@ var Entity = React.createClass({ var AttributeToggler = React.createClass({ getInitialState: function() { - return {fontWeight: 'bold', fontSize: 15}; + return {fontWeight: '500', fontSize: 15}; }, increaseSize: function() { this.setState({ @@ -129,9 +129,37 @@ exports.examples = [ title: 'Font Weight', render: function() { return ( - - Move fast and be bold - + + + Move fast and be ultralight + + + Move fast and be light + + + Move fast and be normal + + + Move fast and be bold + + + Move fast and be ultrabold + + + ); + }, +}, { + title: 'Font Style', + render: function() { + return ( + + + Normal text + + + Italic text + + ); }, }, { @@ -279,7 +307,7 @@ var styles = StyleSheet.create({ backgroundColor: 'rgba(100, 100, 100, 0.3)' }, entity: { - fontWeight: 'bold', + fontWeight: '500', color: '#527fe4', }, }); diff --git a/Examples/UIExplorer/TouchableExample.js b/Examples/UIExplorer/TouchableExample.js index 35d86aaf8..6b3c611ed 100644 --- a/Examples/UIExplorer/TouchableExample.js +++ b/Examples/UIExplorer/TouchableExample.js @@ -187,7 +187,7 @@ var styles = StyleSheet.create({ backgroundColor: '#f9f9f9', }, textBlock: { - fontWeight: 'bold', + fontWeight: '500', color: 'blue', }, }); diff --git a/Examples/UIExplorer/UIExplorerBlock.js b/Examples/UIExplorer/UIExplorerBlock.js index 66222fd05..7d2de002f 100644 --- a/Examples/UIExplorer/UIExplorerBlock.js +++ b/Examples/UIExplorer/UIExplorerBlock.js @@ -76,7 +76,7 @@ var styles = StyleSheet.create({ }, titleText: { fontSize: 14, - fontWeight: 'bold', + fontWeight: '500', }, descriptionText: { fontSize: 14, diff --git a/Examples/UIExplorer/UIExplorerList.js b/Examples/UIExplorer/UIExplorerList.js index 73f016cdd..a13da34dc 100644 --- a/Examples/UIExplorer/UIExplorerList.js +++ b/Examples/UIExplorer/UIExplorerList.js @@ -204,7 +204,7 @@ var styles = StyleSheet.create({ backgroundColor: 'white', }, sectionHeaderTitle: { - fontWeight: 'bold', + fontWeight: '500', fontSize: 11, }, row: { @@ -220,7 +220,7 @@ var styles = StyleSheet.create({ }, rowTitleText: { fontSize: 17, - fontWeight: 'bold', + fontWeight: '500', }, rowDetailText: { fontSize: 15, diff --git a/Examples/UIExplorer/UIExplorerTitle.js b/Examples/UIExplorer/UIExplorerTitle.js index 2016ee085..7a8895413 100644 --- a/Examples/UIExplorer/UIExplorerTitle.js +++ b/Examples/UIExplorer/UIExplorerTitle.js @@ -42,7 +42,7 @@ var styles = StyleSheet.create({ }, text: { fontSize: 19, - fontWeight: 'bold', + fontWeight: '500', }, }); diff --git a/Examples/UIExplorer/WebViewExample.js b/Examples/UIExplorer/WebViewExample.js index 3dcf7c8b7..a471a7807 100644 --- a/Examples/UIExplorer/WebViewExample.js +++ b/Examples/UIExplorer/WebViewExample.js @@ -239,7 +239,7 @@ var styles = StyleSheet.create({ }, errorTextTitle: { fontSize: 15, - fontWeight: 'bold', + fontWeight: '500', marginBottom: 10, }, errorText: { diff --git a/IntegrationTests/IntegrationTestsApp.js b/IntegrationTests/IntegrationTestsApp.js index de1703528..dbb5dde83 100644 --- a/IntegrationTests/IntegrationTestsApp.js +++ b/IntegrationTests/IntegrationTestsApp.js @@ -81,7 +81,7 @@ var styles = StyleSheet.create({ padding: 10, }, testName: { - fontWeight: 'bold', + fontWeight: '500', }, separator: { height: 1, diff --git a/Libraries/Text/RCTShadowText.h b/Libraries/Text/RCTShadowText.h index 61c8f2e73..b14a623c8 100644 --- a/Libraries/Text/RCTShadowText.h +++ b/Libraries/Text/RCTShadowText.h @@ -21,6 +21,7 @@ extern NSString *const RCTReactTagAttributeName; @property (nonatomic, copy) NSString *fontFamily; @property (nonatomic, assign) CGFloat fontSize; @property (nonatomic, copy) NSString *fontWeight; +@property (nonatomic, copy) NSString *fontStyle; @property (nonatomic, assign) BOOL isHighlighted; @property (nonatomic, assign) CGFloat lineHeight; @property (nonatomic, assign) NSInteger maxNumberOfLines; diff --git a/Libraries/Text/RCTShadowText.m b/Libraries/Text/RCTShadowText.m index 8899fea87..f00350205 100644 --- a/Libraries/Text/RCTShadowText.m +++ b/Libraries/Text/RCTShadowText.m @@ -50,12 +50,14 @@ static css_dim_t RCTMeasure(void *context, float width) { return [self _attributedStringWithFontFamily:nil fontSize:0 - fontWeight:nil]; + fontWeight:nil + fontStyle:nil]; } - (NSAttributedString *)_attributedStringWithFontFamily:(NSString *)fontFamily fontSize:(CGFloat)fontSize fontWeight:(NSString *)fontWeight + fontStyle:(NSString *)fontStyle { if (![self isTextDirty] && _cachedAttributedString) { return _cachedAttributedString; @@ -67,6 +69,9 @@ static css_dim_t RCTMeasure(void *context, float width) if (_fontWeight) { fontWeight = _fontWeight; } + if (_fontStyle) { + fontStyle = _fontStyle; + } if (_fontFamily) { fontFamily = _fontFamily; } @@ -75,7 +80,7 @@ static css_dim_t RCTMeasure(void *context, float width) for (RCTShadowView *child in [self reactSubviews]) { if ([child isKindOfClass:[RCTShadowText class]]) { RCTShadowText *shadowText = (RCTShadowText *)child; - [attributedString appendAttributedString:[shadowText _attributedStringWithFontFamily:fontFamily fontSize:fontSize fontWeight:fontWeight]]; + [attributedString appendAttributedString:[shadowText _attributedStringWithFontFamily:fontFamily fontSize:fontSize fontWeight:fontWeight fontStyle:fontStyle]]; } else if ([child isKindOfClass:[RCTShadowRawText class]]) { RCTShadowRawText *shadowRawText = (RCTShadowRawText *)child; [attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:[shadowRawText text] ?: @""]]; @@ -96,7 +101,7 @@ static css_dim_t RCTMeasure(void *context, float width) [self _addAttribute:NSBackgroundColorAttributeName withValue:self.textBackgroundColor toAttributedString:attributedString]; } - _font = [RCTConvert UIFont:nil withFamily:fontFamily size:@(fontSize) weight:fontWeight]; + _font = [RCTConvert UIFont:nil withFamily:fontFamily size:@(fontSize) weight:fontWeight style:fontStyle]; [self _addAttribute:NSFontAttributeName withValue:_font toAttributedString:attributedString]; [self _addAttribute:RCTReactTagAttributeName withValue:self.reactTag toAttributedString:attributedString]; [self _setParagraphStyleOnAttributedString:attributedString]; @@ -110,7 +115,7 @@ static css_dim_t RCTMeasure(void *context, float width) - (UIFont *)font { - return _font ?: [RCTConvert UIFont:nil withFamily:_fontFamily size:@(_fontSize) weight:_fontWeight]; + return _font ?: [RCTConvert UIFont:nil withFamily:_fontFamily size:@(_fontSize) weight:_fontWeight style:_fontStyle]; } - (void)_addAttribute:(NSString *)attribute withValue:(id)attributeValue toAttributedString:(NSMutableAttributedString *)attributedString diff --git a/ReactKit/Base/RCTConvert.h b/ReactKit/Base/RCTConvert.h index f26dea827..fb4f51883 100644 --- a/ReactKit/Base/RCTConvert.h +++ b/ReactKit/Base/RCTConvert.h @@ -12,6 +12,7 @@ #import "Layout.h" #import "RCTAnimationType.h" +#import "RCTLog.h" #import "RCTPointerEvents.h" /** @@ -69,8 +70,13 @@ + (UIFont *)UIFont:(UIFont *)font withSize:(id)json; + (UIFont *)UIFont:(UIFont *)font withWeight:(id)json; ++ (UIFont *)UIFont:(UIFont *)font withStyle:(id)json; + (UIFont *)UIFont:(UIFont *)font withFamily:(id)json; -+ (UIFont *)UIFont:(UIFont *)font withFamily:(id)json size:(id)json weight:(id)json; ++ (UIFont *)UIFont:(UIFont *)font + withFamily:(id)family + size:(id)size + weight:(id)weight + style:(id)style; + (NSArray *)NSStringArray:(id)json; + (NSArray *)NSURLArray:(id)json; diff --git a/ReactKit/Base/RCTConvert.m b/ReactKit/Base/RCTConvert.m index dd46fb4af..01300e306 100644 --- a/ReactKit/Base/RCTConvert.m +++ b/ReactKit/Base/RCTConvert.m @@ -11,8 +11,6 @@ #import -#import "RCTLog.h" - @implementation RCTConvert RCT_CONVERTER(BOOL, BOOL, boolValue) @@ -135,7 +133,9 @@ RCT_CGSTRUCT_CONVERTER(CATransform3D, (@[ @"m41", @"m42", @"m43", @"m44" ]), nil) -RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty"]), nil) +RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[ + @"a", @"b", @"c", @"d", @"tx", @"ty" +]), nil) + (UIColor *)UIColor:(id)json { @@ -364,7 +364,8 @@ RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty } else if (json && ![json isKindOfClass:[NSNull class]]) { - RCTLogError(@"Expected NSArray, NSDictionary or NSString for UIColor, received %@: %@", [json class], json); + RCTLogError(@"Expected NSArray, NSDictionary or NSString for UIColor, \ + received %@: %@", [json class], json); } // Default color @@ -418,100 +419,163 @@ RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty return [self UIImage:json].CGImage; } +#ifndef __IPHONE_8_2 + +// These constants are defined in iPhone SDK 8.2 +// They'll work fine in earlier iOS versions, but the app cannot be built with +// an SDK version < 8.2 unless we redefine them here. This will be removed +// in a future version of ReactKit, once 8.2 is more widely adopted. + +static const CGFloat UIFontWeightUltraLight = -0.8; +static const CGFloat UIFontWeightThin = -0.6; +static const CGFloat UIFontWeightLight = -0.4; +static const CGFloat UIFontWeightRegular = 0; +static const CGFloat UIFontWeightMedium = 0.23; +static const CGFloat UIFontWeightSemibold = 0.3; +static const CGFloat UIFontWeightBold = 0.4; +static const CGFloat UIFontWeightHeavy = 0.56; +static const CGFloat UIFontWeightBlack = 0.62; + +#endif + +typedef CGFloat RCTFontWeight; +RCT_ENUM_CONVERTER(RCTFontWeight, (@{ + @"normal": @(UIFontWeightRegular), + @"bold": @(UIFontWeightBold), + @"100": @(UIFontWeightUltraLight), + @"200": @(UIFontWeightThin), + @"300": @(UIFontWeightLight), + @"400": @(UIFontWeightRegular), + @"500": @(UIFontWeightMedium), + @"600": @(UIFontWeightSemibold), + @"700": @(UIFontWeightBold), + @"800": @(UIFontWeightHeavy), + @"900": @(UIFontWeightBlack), +}), UIFontWeightRegular, doubleValue) + +typedef BOOL RCTFontStyle; +RCT_ENUM_CONVERTER(RCTFontStyle, (@{ + @"normal": @NO, + @"italic": @YES, + @"oblique": @YES, +}), NO, boolValue) + +static RCTFontWeight RCTWeightOfFont(UIFont *font) +{ + NSDictionary *traits = [font.fontDescriptor objectForKey:UIFontDescriptorTraitsAttribute]; + return [traits[UIFontWeightTrait] doubleValue]; +} + +static BOOL RCTFontIsItalic(UIFont *font) +{ + NSDictionary *traits = [font.fontDescriptor objectForKey:UIFontDescriptorTraitsAttribute]; + UIFontDescriptorSymbolicTraits symbolicTraits = [traits[UIFontSymbolicTrait] unsignedIntValue]; + return (symbolicTraits & UIFontDescriptorTraitItalic) != 0; +} + +static BOOL RCTFontIsCondensed(UIFont *font) +{ + NSDictionary *traits = [font.fontDescriptor objectForKey:UIFontDescriptorTraitsAttribute]; + UIFontDescriptorSymbolicTraits symbolicTraits = [traits[UIFontSymbolicTrait] unsignedIntValue]; + return (symbolicTraits & UIFontDescriptorTraitCondensed) != 0; +} + + (UIFont *)UIFont:(UIFont *)font withSize:(id)json { - return [self UIFont:font withFamily:nil size:json weight:nil]; + return [self UIFont:font withFamily:nil size:json weight:nil style:nil]; } + (UIFont *)UIFont:(UIFont *)font withWeight:(id)json { - return [self UIFont:font withFamily:nil size:nil weight:json]; + return [self UIFont:font withFamily:nil size:nil weight:json style:nil]; +} + ++ (UIFont *)UIFont:(UIFont *)font withStyle:(id)json +{ + return [self UIFont:font withFamily:nil size:nil weight:nil style:json]; } + (UIFont *)UIFont:(UIFont *)font withFamily:(id)json { - return [self UIFont:font withFamily:json size:nil weight:nil]; + return [self UIFont:font withFamily:json size:nil weight:nil style:nil]; } -+ (UIFont *)UIFont:(UIFont *)font withFamily:(id)family size:(id)size weight:(id)weight ++ (UIFont *)UIFont:(UIFont *)font + withFamily:(id)family + size:(id)size + weight:(id)weight + style:(id)style { - CGFloat const RCTDefaultFontSize = 14; - NSString *const RCTDefaultFontName = @"HelveticaNeue"; - NSString *const RCTDefaultFontWeight = @"normal"; - NSString *const RCTBoldFontWeight = @"bold"; + // Defaults + NSString *const RCTDefaultFontFamily = @"Helvetica Neue"; + const RCTFontWeight RCTDefaultFontWeight = UIFontWeightRegular; + const CGFloat RCTDefaultFontSize = 14; - // Create descriptor - UIFontDescriptor *fontDescriptor = font.fontDescriptor ?: [UIFontDescriptor fontDescriptorWithName:RCTDefaultFontName size:RCTDefaultFontSize]; - - // Get font size - CGFloat fontSize = [self CGFloat:size]; - if (fontSize && !isnan(fontSize)) { - fontDescriptor = [fontDescriptor fontDescriptorWithSize:fontSize]; - } - - // Get font family - NSString *familyName = [self NSString:family]; - if (familyName) { - if ([UIFont fontNamesForFamilyName:familyName].count == 0) { - font = [UIFont fontWithName:familyName size:fontDescriptor.pointSize]; - if (font) { - // It's actually a font name, not a font family name, - // but we'll do what was meant, not what was said. - familyName = font.familyName; - fontDescriptor = font.fontDescriptor; - } else { - // Not a valid font or family - RCTLogError(@"Unrecognized font family '%@'", familyName); - familyName = [UIFont fontWithDescriptor:fontDescriptor size:0].familyName; - } - } else { - // Set font family - fontDescriptor = [fontDescriptor fontDescriptorWithFamily:familyName]; - } - } else { - familyName = [UIFont fontWithDescriptor:fontDescriptor size:0].familyName; + // Get existing properties + BOOL isItalic = NO; + BOOL isCondensed = NO; + RCTFontWeight fontWeight = RCTDefaultFontWeight; + if (font) { + family = font.familyName; + fontWeight = RCTWeightOfFont(font); + isItalic = RCTFontIsItalic(font); + isCondensed = RCTFontIsCondensed(font); } // Get font weight - NSString *fontWeight = [self NSString:weight]; - if (fontWeight) { + if (weight) { + fontWeight = [self RCTFontWeight:weight]; + } - static NSSet *values; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - values = [NSSet setWithObjects:RCTDefaultFontWeight, RCTBoldFontWeight, nil]; - }); + // Get font style + if (style) { + isItalic = [self RCTFontStyle:style]; + } - if (fontWeight && ![values containsObject:fontWeight]) { - RCTLogError(@"Unrecognized font weight '%@', must be one of %@", fontWeight, values); - fontWeight = RCTDefaultFontWeight; + // Get font size + CGFloat fontSize = [self CGFloat:size] ?: RCTDefaultFontSize; + + // Get font family + NSString *familyName = [self NSString:family] ?: RCTDefaultFontFamily; + if ([UIFont fontNamesForFamilyName:familyName].count == 0) { + font = [UIFont fontWithName:familyName size:fontSize]; + if (font) { + // It's actually a font name, not a font family name, + // but we'll do what was meant, not what was said. + familyName = font.familyName; + NSDictionary *traits = [font.fontDescriptor objectForKey:UIFontDescriptorTraitsAttribute]; + fontWeight = [traits[UIFontWeightTrait] doubleValue]; + } else { + // Not a valid font or family + RCTLogError(@"Unrecognized font family '%@'", familyName); + familyName = RCTDefaultFontFamily; } + } - // this is hacky. we are appending the string -Medium because most fonts we currently use - // just need to have -Medium appended to get the bold we want. we're going to revamp this - // to make it easier to know which options are available in JS. t4996115 - if ([fontWeight isEqualToString:RCTBoldFontWeight]) { - font = nil; - for (NSString *fontName in [UIFont fontNamesForFamilyName:familyName]) { - if ([fontName hasSuffix:@"-Medium"]) { - font = [UIFont fontWithName:fontName size:fontDescriptor.pointSize]; - break; - } - if ([fontName hasSuffix:@"-Bold"]) { - font = [UIFont fontWithName:fontName size:fontDescriptor.pointSize]; - // But keep searching in case there's a medium option - } - } - if (font) { - fontDescriptor = font.fontDescriptor; + // Get closest match + UIFont *bestMatch = font; + CGFloat closestWeight = font ? RCTWeightOfFont(font) : INFINITY; + for (NSString *name in [UIFont fontNamesForFamilyName:familyName]) { + UIFont *match = [UIFont fontWithName:name size:fontSize]; + if (isItalic == RCTFontIsItalic(match) && + isCondensed == RCTFontIsCondensed(match)) { + CGFloat testWeight = RCTWeightOfFont(match); + if (ABS(testWeight - fontWeight) < ABS(closestWeight - fontWeight)) { + bestMatch = match; + closestWeight = testWeight; } } } - // TODO: font style + // Safety net + if (!bestMatch) { + RCTLogError(@"Could not find font with family: '%@', size: %@, \ + weight: %@, style: %@", family, size, weight, style); + bestMatch = [UIFont fontWithName:[[UIFont fontNamesForFamilyName:familyName] firstObject] + size:fontSize]; + } - // Create font - return [UIFont fontWithDescriptor:fontDescriptor size:0]; + return bestMatch; } RCT_ARRAY_CONVERTER(NSString) diff --git a/ReactKit/Base/RCTUtils.m b/ReactKit/Base/RCTUtils.m index 70ad4479a..300f6d721 100644 --- a/ReactKit/Base/RCTUtils.m +++ b/ReactKit/Base/RCTUtils.m @@ -50,11 +50,11 @@ NSString *RCTMD5Hash(NSString *string) CC_MD5(str, (CC_LONG)strlen(str), result); return [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", - result[0], result[1], result[2], result[3], - result[4], result[5], result[6], result[7], - result[8], result[9], result[10], result[11], - result[12], result[13], result[14], result[15] - ]; + result[0], result[1], result[2], result[3], + result[4], result[5], result[6], result[7], + result[8], result[9], result[10], result[11], + result[12], result[13], result[14], result[15] + ]; } CGFloat RCTScreenScale() diff --git a/ReactKit/Views/RCTTextFieldManager.m b/ReactKit/Views/RCTTextFieldManager.m index 041886e55..8418c8858 100644 --- a/ReactKit/Views/RCTTextFieldManager.m +++ b/ReactKit/Views/RCTTextFieldManager.m @@ -41,7 +41,11 @@ RCT_CUSTOM_VIEW_PROPERTY(fontSize, RCTTextField) } RCT_CUSTOM_VIEW_PROPERTY(fontWeight, RCTTextField) { - view.font = [RCTConvert UIFont:view.font withWeight:json]; // TODO: default value + view.font = [RCTConvert UIFont:view.font withWeight:json]; // defaults to normal +} +RCT_CUSTOM_VIEW_PROPERTY(fontStyle, RCTTextField) +{ + view.font = [RCTConvert UIFont:view.font withStyle:json]; // defaults to normal } RCT_CUSTOM_VIEW_PROPERTY(fontFamily, RCTTextField) {