[ios] support numeric, relative and animated font-weight

optimize enum conversion handling for null and empty string
This commit is contained in:
Mikael Sand
2019-07-19 18:11:05 +03:00
parent 1b5e775f06
commit 0a94b1ee89
9 changed files with 187 additions and 18 deletions
+1 -1
View File
@@ -13,7 +13,7 @@
/**
* RNSVG nodes are implemented as base UIViews. They should be implementation for all basic
interfaces for all non-defination nodes.
interfaces for all non-definition nodes.
*/
@interface RNSVGNode : UIView
+1
View File
@@ -12,6 +12,7 @@
enum RNSVGFontStyle fontStyle;
NSDictionary * fontData;
enum RNSVGFontWeight fontWeight;
int absoluteFontWeight;
NSString *fontFeatureSettings;
enum RNSVGFontVariantLigatures fontVariantLigatures;
enum RNSVGTextAnchor textAnchor;
+76 -2
View File
@@ -30,6 +30,7 @@ RNSVGFontData *RNSVGFontData_Defaults;
self->fontFamily = @"";
self->fontStyle = RNSVGFontStyleNormal;
self->fontWeight = RNSVGFontWeightNormal;
self->absoluteFontWeight = 400;
self->fontFeatureSettings = @"";
self->fontVariantLigatures = RNSVGFontVariantLigaturesNormal;
self->textAnchor = RNSVGTextAnchorStart;
@@ -51,6 +52,60 @@ RNSVGFontData *RNSVGFontData_Defaults;
fontSize:fontSize];
}
- (void)setInheritedWeight:(RNSVGFontData*) parent {
fontWeight = parent->fontWeight;
absoluteFontWeight = parent->absoluteFontWeight;
}
RNSVGFontWeight nearestFontWeight(int absoluteFontWeight) {
return RNSVGFontWeights[(int)round(absoluteFontWeight / 100.0)];
}
- (void)handleNumericWeight:(RNSVGFontData*)parent weight:(double)weight {
long roundWeight = round(weight);
if (roundWeight >= 1 && roundWeight <= 1000) {
absoluteFontWeight = (int)roundWeight;
fontWeight = nearestFontWeight(absoluteFontWeight);
} else {
[self setInheritedWeight:parent];
}
}
// https://drafts.csswg.org/css-fonts-4/#relative-weights
int AbsoluteFontWeight(RNSVGFontWeight fontWeight, RNSVGFontData* parent) {
if (fontWeight == RNSVGFontWeightBolder) {
return bolder(parent->absoluteFontWeight);
} else if (fontWeight == RNSVGFontWeightLighter) {
return lighter(parent->absoluteFontWeight);
} else {
return RNSVGAbsoluteFontWeights[fontWeight];
}
}
int bolder(int inherited) {
if (inherited < 350) {
return 400;
} else if (inherited < 550) {
return 700;
} else if (inherited < 900) {
return 900;
} else {
return inherited;
}
}
int lighter(int inherited) {
if (inherited < 100) {
return inherited;
} else if (inherited < 550) {
return 100;
} else if (inherited < 750) {
return 400;
} else {
return 700;
}
}
+ (instancetype)initWithNSDictionary:(NSDictionary *)font
parent:(RNSVGFontData *)parent {
RNSVGFontData *data = [RNSVGFontData alloc];
@@ -69,12 +124,31 @@ RNSVGFontData *RNSVGFontData_Defaults;
else {
data->fontSize = parentFontSize;
}
if ([font objectForKey:FONT_WEIGHT]) {
id fontWeight = [font objectForKey:FONT_WEIGHT];
if ([fontWeight isKindOfClass:NSNumber.class]) {
[data handleNumericWeight:parent weight:[fontWeight doubleValue]];
} else {
NSString* weight = fontWeight;
NSInteger fw = RNSVGFontWeightFromString(weight);
if (fw != -1) {
data->absoluteFontWeight = AbsoluteFontWeight(fw, parent);
data->fontWeight = nearestFontWeight(data->absoluteFontWeight);
} else if ([weight length] != 0) {
[data handleNumericWeight:parent weight:[weight doubleValue]];
} else {
[data setInheritedWeight:parent];
}
}
} else {
[data setInheritedWeight:parent];
}
data->fontData = [font objectForKey:FONT_DATA] ? [font objectForKey:FONT_DATA] : parent->fontData;
data->fontFamily = [font objectForKey:FONT_FAMILY] ? [font objectForKey:FONT_FAMILY] : parent->fontFamily;
NSString* style = [font objectForKey:FONT_STYLE];
data->fontStyle = style ? RNSVGFontStyleFromString(style) : parent->fontStyle;
NSString* weight = [font objectForKey:FONT_WEIGHT];
data->fontWeight = weight ? RNSVGFontWeightFromString(weight) : parent->fontWeight;
NSString* feature = [font objectForKey:FONT_FEATURE_SETTINGS];
data->fontFeatureSettings = feature ? [font objectForKey:FONT_FEATURE_SETTINGS] : parent->fontFeatureSettings;
NSString* variant = [font objectForKey:FONT_VARIANT_LIGATURES];
+1 -1
View File
@@ -116,7 +116,7 @@
NSString *fontFamily = topFont_->fontFamily;
NSNumber * fontSize = [NSNumber numberWithDouble:topFont_->fontSize];
NSString * fontWeight = [RNSVGFontWeightToString(topFont_->fontWeight) lowercaseString];
NSString * fontWeight = RNSVGFontWeightStrings[topFont_->fontWeight];
NSString * fontStyle = RNSVGFontStyleStrings[topFont_->fontStyle];
BOOL fontFamilyFound = NO;
+26 -6
View File
@@ -137,10 +137,10 @@ static CGFloat RNSVGTSpan_radToDeg = 180 / (CGFloat)M_PI;
bool allowOptionalLigatures = letterSpacing == 0 && font->fontVariantLigatures == RNSVGFontVariantLigaturesNormal;
NSMutableDictionary *attrs = [[NSMutableDictionary alloc] init];
CFMutableDictionaryRef attributes = (__bridge CFMutableDictionaryRef)attrs;
NSNumber *lig = [NSNumber numberWithInt:allowOptionalLigatures ? 2 : 1];
attrs[NSLigatureAttributeName] = lig;
CFDictionaryRef attributes;
if (fontRef != nil) {
attrs[NSFontAttributeName] = (__bridge id)fontRef;
}
@@ -157,8 +157,18 @@ static CGFloat RNSVGTSpan_radToDeg = 180 / (CGFloat)M_PI;
{
[attrs setObject:kernAttr forKey:(id)kCTKernAttributeName];
}
attributes = (__bridge CFDictionaryRef)attrs;
int weight = font->absoluteFontWeight;
if (weight != 400) {
// https://github.com/WebKit/webkit/blob/73b06fb2cc31aaff91119718d9abdc7be703d41b/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp#L429-L444
float denormalizedWeight = (weight + 109.3) / 523.7;
CFMutableDictionaryRef variationDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
long long bitwiseTag = 'w' << 24 | 'g' << 16 | 'h' << 8 | 't';
CFNumberRef tagNumber = CFNumberCreate(kCFAllocatorDefault, kCFNumberLongLongType, &bitwiseTag);
CFNumberRef valueNumber = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &denormalizedWeight);
CFDictionarySetValue(variationDictionary, tagNumber, valueNumber);
CFDictionaryAddValue(attributes, kCTFontVariationAttribute, variationDictionary);
}
CFStringRef string = (__bridge CFStringRef)str;
CFAttributedStringRef attrString = CFAttributedStringCreate(kCFAllocatorDefault, string, attributes);
@@ -310,10 +320,10 @@ static CGFloat RNSVGTSpan_radToDeg = 180 / (CGFloat)M_PI;
// OpenType.js font data
NSDictionary * fontData = font->fontData;
NSMutableDictionary *attrs = [[NSMutableDictionary alloc] init];
CFMutableDictionaryRef attributes = (__bridge CFMutableDictionaryRef)attrs;
NSNumber *lig = [NSNumber numberWithInt:allowOptionalLigatures ? 2 : 1];
attrs[NSLigatureAttributeName] = lig;
CFDictionaryRef attributes;
if (fontRef != nil) {
attrs[NSFontAttributeName] = (__bridge id)fontRef;
}
@@ -331,8 +341,18 @@ static CGFloat RNSVGTSpan_radToDeg = 180 / (CGFloat)M_PI;
[attrs setObject:noAutoKern forKey:(id)kCTKernAttributeName];
}
}
attributes = (__bridge CFDictionaryRef)attrs;
int weight = font->absoluteFontWeight;
if (weight != 400) {
// https://github.com/WebKit/webkit/blob/73b06fb2cc31aaff91119718d9abdc7be703d41b/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp#L429-L444
float denormalizedWeight = (weight + 109.3) / 523.7;
CFMutableDictionaryRef variationDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
long long bitwiseTag = 'w' << 24 | 'g' << 16 | 'h' << 8 | 't';
CFNumberRef tagNumber = CFNumberCreate(kCFAllocatorDefault, kCFNumberLongLongType, &bitwiseTag);
CFNumberRef valueNumber = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &denormalizedWeight);
CFDictionarySetValue(variationDictionary, tagNumber, valueNumber);
CFDictionaryAddValue(attributes, kCTFontVariationAttribute, variationDictionary);
}
CFStringRef string = (__bridge CFStringRef)str;
CFAttributedStringRef attrString = CFAttributedStringCreate(kCFAllocatorDefault, string, attributes);
+20 -3
View File
@@ -86,10 +86,9 @@ NSString* RNSVGFontVariantLigaturesToString( enum RNSVGFontVariantLigatures fw )
enum RNSVGFontVariantLigatures RNSVGFontVariantLigaturesFromString( NSString* s );
typedef NS_ENUM(NSInteger, RNSVGFontWeight) {
// Absolute
RNSVGFontWeightNormal,
RNSVGFontWeightBold,
RNSVGFontWeightBolder,
RNSVGFontWeightLighter,
RNSVGFontWeight100,
RNSVGFontWeight200,
RNSVGFontWeight300,
@@ -99,11 +98,29 @@ typedef NS_ENUM(NSInteger, RNSVGFontWeight) {
RNSVGFontWeight700,
RNSVGFontWeight800,
RNSVGFontWeight900,
// Relative
RNSVGFontWeightBolder,
RNSVGFontWeightLighter,
RNSVGFontWeightDEFAULT = RNSVGFontWeightNormal,
};
static NSString* const RNSVGFontWeightStrings[] = {@"Normal", @"Bold", @"Bolder", @"Lighter", @"100", @"200", @"300", @"400", @"500", @"600", @"700", @"800", @"900", nil};
static NSString* const RNSVGFontWeightStrings[] = {@"normal", @"bold", @"100", @"200", @"300", @"400", @"500", @"600", @"700", @"800", @"900", @"bolder", @"lighter", nil};
static int const RNSVGAbsoluteFontWeights[] = {400, 700, 100, 200, 300, 400, 500, 600, 700, 800, 900};
static RNSVGFontWeight const RNSVGFontWeights[] = {
RNSVGFontWeight100,
RNSVGFontWeight100,
RNSVGFontWeight200,
RNSVGFontWeight300,
RNSVGFontWeightNormal,
RNSVGFontWeight500,
RNSVGFontWeight600,
RNSVGFontWeightBold,
RNSVGFontWeight800,
RNSVGFontWeight900,
RNSVGFontWeight900
};
NSString* RNSVGFontWeightToString( enum RNSVGFontWeight fw );
+38 -5
View File
@@ -9,6 +9,9 @@ NSString* RNSVGAlignmentBaselineToString( enum RNSVGAlignmentBaseline fw )
enum RNSVGAlignmentBaseline RNSVGAlignmentBaselineFromString( NSString* s )
{
if ([s length] == 0) {
return RNSVGAlignmentBaselineDEFAULT;
}
const NSUInteger l = sizeof(RNSVGAlignmentBaselineStrings) / sizeof(NSString*);
for (NSUInteger i = 0; i < l; i++) {
if ([s isEqualToString:RNSVGAlignmentBaselineStrings[i]]) {
@@ -27,6 +30,9 @@ NSString* RNSVGFontStyleToString( enum RNSVGFontStyle fw )
enum RNSVGFontStyle RNSVGFontStyleFromString( NSString* s )
{
if ([s length] == 0) {
return RNSVGFontStyleDEFAULT;
}
const NSUInteger l = sizeof(RNSVGFontStyleStrings) / sizeof(NSString*);
for (NSUInteger i = 0; i < l; i++) {
if ([s isEqualToString:RNSVGFontStyleStrings[i]]) {
@@ -45,6 +51,9 @@ NSString* RNSVGFontVariantLigaturesToString( enum RNSVGFontVariantLigatures fw )
enum RNSVGFontVariantLigatures RNSVGFontVariantLigaturesFromString( NSString* s )
{
if ([s length] == 0) {
return RNSVGFontVariantLigaturesDEFAULT;
}
const NSUInteger l = sizeof(RNSVGFontVariantLigaturesStrings) / sizeof(NSString*);
for (NSUInteger i = 0; i < l; i++) {
if ([s isEqualToString:RNSVGFontVariantLigaturesStrings[i]]) {
@@ -61,15 +70,18 @@ NSString* RNSVGFontWeightToString( enum RNSVGFontWeight fw )
return RNSVGFontWeightStrings[fw];
}
enum RNSVGFontWeight RNSVGFontWeightFromString( NSString* s )
NSInteger RNSVGFontWeightFromString( NSString* s )
{
const NSUInteger l = sizeof(RNSVGFontWeightStrings) / sizeof(NSString*);
for (NSUInteger i = 0; i < l; i++) {
if ([[s capitalizedString] isEqualToString:RNSVGFontWeightStrings[i]]) {
if ([s length] == 0) {
return -1;
}
const NSInteger l = sizeof(RNSVGFontWeightStrings) / sizeof(NSString*);
for (NSInteger i = 0; i < l; i++) {
if ([s isEqualToString:RNSVGFontWeightStrings[i]]) {
return i;
}
}
return RNSVGFontWeightDEFAULT;
return -1;
}
#pragma mark - RNSVGTextAnchor
@@ -81,6 +93,9 @@ NSString* RNSVGTextAnchorToString( enum RNSVGTextAnchor fw )
enum RNSVGTextAnchor RNSVGTextAnchorFromString( NSString* s )
{
if ([s length] == 0) {
return RNSVGTextAnchorDEFAULT;
}
const NSUInteger l = sizeof(RNSVGTextAnchorStrings) / sizeof(NSString*);
for (NSUInteger i = 0; i < l; i++) {
if ([s isEqualToString:RNSVGTextAnchorStrings[i]]) {
@@ -99,6 +114,9 @@ NSString* RNSVGTextDecorationToString( enum RNSVGTextDecoration fw )
enum RNSVGTextDecoration RNSVGTextDecorationFromString( NSString* s )
{
if ([s length] == 0) {
return RNSVGTextDecorationDEFAULT;
}
const NSUInteger l = sizeof(RNSVGTextDecorationStrings) / sizeof(NSString*);
for (NSUInteger i = 0; i < l; i++) {
if ([s isEqualToString:RNSVGTextDecorationStrings[i]]) {
@@ -117,6 +135,9 @@ NSString* RNSVGTextLengthAdjustToString( enum RNSVGTextLengthAdjust fw )
enum RNSVGTextLengthAdjust RNSVGTextLengthAdjustFromString( NSString* s )
{
if ([s length] == 0) {
return RNSVGTextLengthAdjustDEFAULT;
}
const NSUInteger l = sizeof(RNSVGTextLengthAdjustStrings) / sizeof(NSString*);
for (NSUInteger i = 0; i < l; i++) {
if ([s isEqualToString:RNSVGTextLengthAdjustStrings[i]]) {
@@ -135,6 +156,9 @@ NSString* RNSVGTextPathMethodToString( enum RNSVGTextPathMethod fw )
enum RNSVGTextPathMethod RNSVGTextPathMethodFromString( NSString* s )
{
if ([s length] == 0) {
return RNSVGTextPathMethodDEFAULT;
}
const NSUInteger l = sizeof(RNSVGTextPathMethodStrings) / sizeof(NSString*);
for (NSUInteger i = 0; i < l; i++) {
if ([s isEqualToString:RNSVGTextPathMethodStrings[i]]) {
@@ -153,6 +177,9 @@ NSString* RNSVGTextPathMidLineToString( enum RNSVGTextPathMidLine fw )
enum RNSVGTextPathMidLine RNSVGTextPathMidLineFromString( NSString* s )
{
if ([s length] == 0) {
return RNSVGTextPathMidLineDEFAULT;
}
const NSUInteger l = sizeof(RNSVGTextPathMidLineStrings) / sizeof(NSString*);
for (NSUInteger i = 0; i < l; i++) {
if ([s isEqualToString:RNSVGTextPathMidLineStrings[i]]) {
@@ -171,6 +198,9 @@ NSString* RNSVGTextPathSideToString( enum RNSVGTextPathSide fw )
enum RNSVGTextPathSide RNSVGTextPathSideFromString( NSString* s )
{
if ([s length] == 0) {
return RNSVGTextPathSideDEFAULT;
}
const NSUInteger l = sizeof(RNSVGTextPathSideStrings) / sizeof(NSString*);
for (NSUInteger i = 0; i < l; i++) {
if ([s isEqualToString:RNSVGTextPathSideStrings[i]]) {
@@ -189,6 +219,9 @@ NSString* RNSVGTextPathSpacingToString( enum RNSVGTextPathSpacing fw )
enum RNSVGTextPathSpacing RNSVGTextPathSpacingFromString( NSString* s )
{
if ([s length] == 0) {
return RNSVGTextPathSpacingDEFAULT;
}
const NSUInteger l = sizeof(RNSVGTextPathSpacingStrings) / sizeof(NSString*);
for (NSUInteger i = 0; i < l; i++) {
if ([s isEqualToString:RNSVGTextPathSpacingStrings[i]]) {
+12
View File
@@ -33,4 +33,16 @@ RCT_CUSTOM_VIEW_PROPERTY(fontSize, id, RNSVGGroup)
}
}
RCT_CUSTOM_VIEW_PROPERTY(fontWeight, id, RNSVGGroup)
{
if ([json isKindOfClass:[NSString class]]) {
NSString *stringValue = (NSString *)json;
view.font = @{ @"fontWeight": stringValue };
} else {
NSNumber* number = (NSNumber*)json;
double num = [number doubleValue];
view.font = @{@"fontWeight": [NSNumber numberWithDouble:num] };
}
}
@end
+12
View File
@@ -80,4 +80,16 @@ RCT_CUSTOM_VIEW_PROPERTY(fontSize, id, RNSVGGroup)
}
}
RCT_CUSTOM_VIEW_PROPERTY(fontWeight, id, RNSVGGroup)
{
if ([json isKindOfClass:[NSString class]]) {
NSString *stringValue = (NSString *)json;
view.font = @{ @"fontWeight": stringValue };
} else {
NSNumber* number = (NSNumber*)json;
double num = [number doubleValue];
view.font = @{@"fontWeight": [NSNumber numberWithDouble:num] };
}
}
@end