mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-24 04:16:00 +08:00
Add iOS support for CSS property font-variant, accepting tabular-nums…
Summary: Ground work for allowing `font-variant`s. Currently allows switching between `tabular-nums` and `proportional-nums`. I will need guidance on how to test this, and a few pointers on code style (new to Objective C, and had to make one or two hacks). Closes https://github.com/facebook/react-native/pull/9045 Reviewed By: majak Differential Revision: D3664338 Pulled By: javache fbshipit-source-id: 032f326c37ee6150348da2b33b6a3fc1988e8920
This commit is contained in:
committed by
Facebook Github Bot 1
parent
ced272d906
commit
f951da912d
@@ -232,7 +232,7 @@ RCT_CUSTOM_CONVERTER(type, type, [RCT_DEBUG ? [self NSNumber:json] : json getter
|
||||
* This macro is used for creating converter functions for typed arrays.
|
||||
*/
|
||||
#define RCT_ARRAY_CONVERTER(type) \
|
||||
+ (NSArray<id> *)type##Array:(id)json \
|
||||
+ (NSArray<type *> *)type##Array:(id)json \
|
||||
{ \
|
||||
return RCTConvertArrayValue(@selector(type:), json); \
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <CoreText/CoreText.h>
|
||||
|
||||
#import "RCTConvert.h"
|
||||
|
||||
#import <objc/message.h>
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
size:(NSNumber *)size
|
||||
weight:(NSString *)weight
|
||||
style:(NSString *)style
|
||||
variant:(NSArray<NSString *> *)variant
|
||||
scaleMultiplier:(CGFloat)scaleMultiplier;
|
||||
|
||||
+ (UIFont *)updateFont:(UIFont *)font withFamily:(NSString *)family;
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
*/
|
||||
|
||||
#import "RCTFont.h"
|
||||
#import "RCTLog.h"
|
||||
|
||||
#import <CoreText/CoreText.h>
|
||||
|
||||
#import <mutex>
|
||||
|
||||
@@ -127,6 +130,7 @@ static UIFont *cachedSystemFont(CGFloat size, RCTFontWeight weight)
|
||||
size:[RCTConvert NSNumber:json[@"fontSize"]]
|
||||
weight:[RCTConvert NSString:json[@"fontWeight"]]
|
||||
style:[RCTConvert NSString:json[@"fontStyle"]]
|
||||
variant:[RCTConvert NSStringArray:json[@"fontVariant"]]
|
||||
scaleMultiplier:1];
|
||||
}
|
||||
|
||||
@@ -151,6 +155,45 @@ RCT_ENUM_CONVERTER(RCTFontStyle, (@{
|
||||
@"oblique": @YES,
|
||||
}), NO, boolValue)
|
||||
|
||||
typedef NSDictionary RCTFontVariantDescriptor;
|
||||
+ (RCTFontVariantDescriptor *)RCTFontVariantDescriptor:(id)json
|
||||
{
|
||||
static NSDictionary *mapping;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
mapping = @{
|
||||
@"small-caps": @{
|
||||
UIFontFeatureTypeIdentifierKey: @(kLowerCaseType),
|
||||
UIFontFeatureSelectorIdentifierKey: @(kLowerCaseSmallCapsSelector),
|
||||
},
|
||||
@"oldstyle-nums": @{
|
||||
UIFontFeatureTypeIdentifierKey: @(kNumberCaseType),
|
||||
UIFontFeatureSelectorIdentifierKey: @(kLowerCaseNumbersSelector),
|
||||
},
|
||||
@"lining-nums": @{
|
||||
UIFontFeatureTypeIdentifierKey: @(kNumberCaseType),
|
||||
UIFontFeatureSelectorIdentifierKey: @(kUpperCaseNumbersSelector),
|
||||
},
|
||||
@"tabular-nums": @{
|
||||
UIFontFeatureTypeIdentifierKey: @(kNumberSpacingType),
|
||||
UIFontFeatureSelectorIdentifierKey: @(kMonospacedNumbersSelector),
|
||||
},
|
||||
@"proportional-nums": @{
|
||||
UIFontFeatureTypeIdentifierKey: @(kNumberSpacingType),
|
||||
UIFontFeatureSelectorIdentifierKey: @(kProportionalNumbersSelector),
|
||||
},
|
||||
};
|
||||
});
|
||||
RCTFontVariantDescriptor *value = mapping[json];
|
||||
if (RCT_DEBUG && !value && [json description].length > 0) {
|
||||
RCTLogError(@"Invalid RCTFontVariantDescriptor '%@'. should be one of: %@", json,
|
||||
[[mapping allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
RCT_ARRAY_CONVERTER(RCTFontVariantDescriptor)
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTFont
|
||||
@@ -160,6 +203,7 @@ RCT_ENUM_CONVERTER(RCTFontStyle, (@{
|
||||
size:(NSNumber *)size
|
||||
weight:(NSString *)weight
|
||||
style:(NSString *)style
|
||||
variant:(NSArray<RCTFontVariantDescriptor *> *)variant
|
||||
scaleMultiplier:(CGFloat)scaleMultiplier
|
||||
{
|
||||
// Defaults
|
||||
@@ -195,11 +239,15 @@ RCT_ENUM_CONVERTER(RCTFontStyle, (@{
|
||||
isItalic = style ? [RCTConvert RCTFontStyle:style] : isItalic;
|
||||
fontWeight = weight ? [RCTConvert RCTFontWeight:weight] : fontWeight;
|
||||
|
||||
BOOL didFindFont = NO;
|
||||
|
||||
// Handle system font as special case. This ensures that we preserve
|
||||
// the specific metrics of the standard system font as closely as possible.
|
||||
if ([familyName isEqual:defaultFontFamily] || [familyName isEqualToString:@"System"]) {
|
||||
font = cachedSystemFont(fontSize, fontWeight);
|
||||
if (font) {
|
||||
didFindFont = YES;
|
||||
|
||||
if (isItalic || isCondensed) {
|
||||
UIFontDescriptor *fontDescriptor = [font fontDescriptor];
|
||||
UIFontDescriptorSymbolicTraits symbolicTraits = fontDescriptor.symbolicTraits;
|
||||
@@ -212,13 +260,12 @@ RCT_ENUM_CONVERTER(RCTFontStyle, (@{
|
||||
fontDescriptor = [fontDescriptor fontDescriptorWithSymbolicTraits:symbolicTraits];
|
||||
font = [UIFont fontWithDescriptor:fontDescriptor size:fontSize];
|
||||
}
|
||||
return font;
|
||||
}
|
||||
}
|
||||
|
||||
// Gracefully handle being given a font name rather than font family, for
|
||||
// example: "Helvetica Light Oblique" rather than just "Helvetica".
|
||||
if ([UIFont fontNamesForFamilyName:familyName].count == 0) {
|
||||
if (!didFindFont && [UIFont fontNamesForFamilyName:familyName].count == 0) {
|
||||
font = [UIFont fontWithName:familyName size:fontSize];
|
||||
if (font) {
|
||||
// It's actually a font name, not a font family name,
|
||||
@@ -241,7 +288,6 @@ RCT_ENUM_CONVERTER(RCTFontStyle, (@{
|
||||
}
|
||||
|
||||
// Get the closest font that matches the given weight for the fontFamily
|
||||
UIFont *bestMatch = font;
|
||||
CGFloat closestWeight = INFINITY;
|
||||
for (NSString *name in [UIFont fontNamesForFamilyName:familyName]) {
|
||||
UIFont *match = [UIFont fontWithName:name size:fontSize];
|
||||
@@ -249,33 +295,42 @@ RCT_ENUM_CONVERTER(RCTFontStyle, (@{
|
||||
isCondensed == isCondensedFont(match)) {
|
||||
CGFloat testWeight = weightOfFont(match);
|
||||
if (ABS(testWeight - fontWeight) < ABS(closestWeight - fontWeight)) {
|
||||
bestMatch = match;
|
||||
font = match;
|
||||
closestWeight = testWeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bestMatch;
|
||||
// Apply font variants to font object
|
||||
if (variant) {
|
||||
NSArray *fontFeatures = [RCTConvert RCTFontVariantDescriptorArray:variant];
|
||||
UIFontDescriptor *fontDescriptor = [font.fontDescriptor fontDescriptorByAddingAttributes:@{
|
||||
UIFontDescriptorFeatureSettingsAttribute: fontFeatures
|
||||
}];
|
||||
font = [UIFont fontWithDescriptor:fontDescriptor size:fontSize];
|
||||
}
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
+ (UIFont *)updateFont:(UIFont *)font withFamily:(NSString *)family
|
||||
{
|
||||
return [self updateFont:font withFamily:family size:nil weight:nil style:nil scaleMultiplier:1];
|
||||
return [self updateFont:font withFamily:family size:nil weight:nil style:nil variant:nil scaleMultiplier:1];
|
||||
}
|
||||
|
||||
+ (UIFont *)updateFont:(UIFont *)font withSize:(NSNumber *)size
|
||||
{
|
||||
return [self updateFont:font withFamily:nil size:size weight:nil style:nil scaleMultiplier:1];
|
||||
return [self updateFont:font withFamily:nil size:size weight:nil style:nil variant:nil scaleMultiplier:1];
|
||||
}
|
||||
|
||||
+ (UIFont *)updateFont:(UIFont *)font withWeight:(NSString *)weight
|
||||
{
|
||||
return [self updateFont:font withFamily:nil size:nil weight:weight style:nil scaleMultiplier:1];
|
||||
return [self updateFont:font withFamily:nil size:nil weight:weight style:nil variant:nil scaleMultiplier:1];
|
||||
}
|
||||
|
||||
+ (UIFont *)updateFont:(UIFont *)font withStyle:(NSString *)style
|
||||
{
|
||||
return [self updateFont:font withFamily:nil size:nil weight:nil style:style scaleMultiplier:1];
|
||||
return [self updateFont:font withFamily:nil size:nil weight:nil style:style variant:nil scaleMultiplier:1];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user