mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-06-07 08:45:00 +00:00
[ios] support numeric, relative and animated font-weight
optimize enum conversion handling for null and empty string
This commit is contained in:
+1
-1
@@ -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
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
enum RNSVGFontStyle fontStyle;
|
||||
NSDictionary * fontData;
|
||||
enum RNSVGFontWeight fontWeight;
|
||||
int absoluteFontWeight;
|
||||
NSString *fontFeatureSettings;
|
||||
enum RNSVGFontVariantLigatures fontVariantLigatures;
|
||||
enum RNSVGTextAnchor textAnchor;
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
@@ -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]]) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user