You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
6.7 KiB
197 lines
6.7 KiB
#import "RNSVGFontData.h"
|
|
#import "RNSVGNode.h"
|
|
#import "RNSVGPropHelper.h"
|
|
#import "RNSVGTextProperties.h"
|
|
|
|
#define RNSVG_DEFAULT_KERNING 0.0
|
|
#define RNSVG_DEFAULT_WORD_SPACING 0.0
|
|
#define RNSVG_DEFAULT_LETTER_SPACING 0.0
|
|
static NSString *KERNING = @"kerning";
|
|
static NSString *FONT_SIZE = @"fontSize";
|
|
static NSString *FONT_DATA = @"fontData";
|
|
static NSString *FONT_STYLE = @"fontStyle";
|
|
static NSString *FONT_WEIGHT = @"fontWeight";
|
|
static NSString *FONT_FAMILY = @"fontFamily";
|
|
static NSString *TEXT_ANCHOR = @"textAnchor";
|
|
static NSString *WORD_SPACING = @"wordSpacing";
|
|
static NSString *LETTER_SPACING = @"letterSpacing";
|
|
static NSString *TEXT_DECORATION = @"textDecoration";
|
|
static NSString *FONT_FEATURE_SETTINGS = @"fontFeatureSettings";
|
|
static NSString *FONT_VARIANT_LIGATURES = @"fontVariantLigatures";
|
|
|
|
RNSVGFontData *RNSVGFontData_Defaults;
|
|
|
|
@implementation RNSVGFontData
|
|
|
|
+ (instancetype)Defaults
|
|
{
|
|
if (!RNSVGFontData_Defaults) {
|
|
RNSVGFontData *self = [RNSVGFontData alloc];
|
|
self->fontData = nil;
|
|
self->fontFamily = @"";
|
|
self->fontStyle = RNSVGFontStyleNormal;
|
|
self->fontWeight = RNSVGFontWeightNormal;
|
|
self->absoluteFontWeight = 400;
|
|
self->fontFeatureSettings = @"";
|
|
self->fontVariantLigatures = RNSVGFontVariantLigaturesNormal;
|
|
self->textAnchor = RNSVGTextAnchorStart;
|
|
self->textDecoration = RNSVGTextDecorationNone;
|
|
self->manualKerning = false;
|
|
self->kerning = RNSVG_DEFAULT_KERNING;
|
|
self->fontSize = RNSVG_DEFAULT_FONT_SIZE;
|
|
self->wordSpacing = RNSVG_DEFAULT_WORD_SPACING;
|
|
self->letterSpacing = RNSVG_DEFAULT_LETTER_SPACING;
|
|
RNSVGFontData_Defaults = self;
|
|
}
|
|
return RNSVGFontData_Defaults;
|
|
}
|
|
|
|
+ (CGFloat)toAbsoluteWithNSString:(NSString *)string fontSize:(CGFloat)fontSize
|
|
{
|
|
return [RNSVGPropHelper fromRelativeWithNSString:string relative:0 fontSize:fontSize];
|
|
}
|
|
|
|
- (void)setInheritedWeight:(RNSVGFontData *)parent
|
|
{
|
|
absoluteFontWeight = parent->absoluteFontWeight;
|
|
fontWeight = parent->fontWeight;
|
|
}
|
|
|
|
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];
|
|
CGFloat parentFontSize = parent->fontSize;
|
|
if ([font objectForKey:FONT_SIZE]) {
|
|
id fontSize = [font objectForKey:FONT_SIZE];
|
|
if ([fontSize isKindOfClass:NSNumber.class]) {
|
|
NSNumber *fs = fontSize;
|
|
data->fontSize = (CGFloat)[fs doubleValue];
|
|
} else {
|
|
data->fontSize = [RNSVGPropHelper fromRelativeWithNSString:fontSize
|
|
relative:parentFontSize
|
|
fontSize:parentFontSize];
|
|
}
|
|
} 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((RNSVGFontWeight)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 *feature = [font objectForKey:FONT_FEATURE_SETTINGS];
|
|
data->fontFeatureSettings = feature ? [font objectForKey:FONT_FEATURE_SETTINGS] : parent->fontFeatureSettings;
|
|
NSString *variant = [font objectForKey:FONT_VARIANT_LIGATURES];
|
|
data->fontVariantLigatures = variant ? RNSVGFontVariantLigaturesFromString(variant) : parent->fontVariantLigatures;
|
|
NSString *anchor = [font objectForKey:TEXT_ANCHOR];
|
|
data->textAnchor = anchor ? RNSVGTextAnchorFromString(anchor) : parent->textAnchor;
|
|
NSString *decoration = [font objectForKey:TEXT_DECORATION];
|
|
data->textDecoration = decoration ? RNSVGTextDecorationFromString(decoration) : parent->textDecoration;
|
|
|
|
CGFloat fontSize = data->fontSize;
|
|
id kerning = [font objectForKey:KERNING];
|
|
data->manualKerning = (kerning || parent->manualKerning);
|
|
if ([kerning isKindOfClass:NSNumber.class]) {
|
|
NSNumber *kern = kerning;
|
|
data->kerning = (CGFloat)[kern doubleValue];
|
|
} else {
|
|
data->kerning = kerning ? [RNSVGFontData toAbsoluteWithNSString:kerning fontSize:fontSize] : parent->kerning;
|
|
}
|
|
|
|
id wordSpacing = [font objectForKey:WORD_SPACING];
|
|
if ([wordSpacing isKindOfClass:NSNumber.class]) {
|
|
NSNumber *ws = wordSpacing;
|
|
data->wordSpacing = (CGFloat)[ws doubleValue];
|
|
} else {
|
|
data->wordSpacing =
|
|
wordSpacing ? [RNSVGFontData toAbsoluteWithNSString:wordSpacing fontSize:fontSize] : parent->wordSpacing;
|
|
}
|
|
|
|
id letterSpacing = [font objectForKey:LETTER_SPACING];
|
|
if ([letterSpacing isKindOfClass:NSNumber.class]) {
|
|
NSNumber *ls = letterSpacing;
|
|
data->wordSpacing = (CGFloat)[ls doubleValue];
|
|
} else {
|
|
data->letterSpacing =
|
|
letterSpacing ? [RNSVGFontData toAbsoluteWithNSString:letterSpacing fontSize:fontSize] : parent->letterSpacing;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
@end
|