mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-27 19:25:11 +08:00
Move color processing to JS
Reviewed By: @vjeux Differential Revision: D2346353
This commit is contained in:
committed by
facebook-github-bot-7
parent
6078a4f865
commit
9a2d05d9b2
@@ -379,292 +379,21 @@ RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[
|
||||
|
||||
+ (UIColor *)UIColor:(id)json
|
||||
{
|
||||
// Check color cache
|
||||
static RCTCache *colorCache = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
colorCache = [RCTCache new];
|
||||
colorCache.countLimit = 128;
|
||||
});
|
||||
UIColor *color = colorCache[json];
|
||||
if (color) {
|
||||
return color;
|
||||
if ([json isKindOfClass:[NSArray class]]) {
|
||||
NSArray *components = [self NSNumberArray:json];
|
||||
CGFloat alpha = components.count > 3 ? [self CGFloat:components[3]] : 1.0;
|
||||
return [UIColor colorWithRed:[self CGFloat:components[0]]
|
||||
green:[self CGFloat:components[1]]
|
||||
blue:[self CGFloat:components[2]]
|
||||
alpha:alpha];
|
||||
} else {
|
||||
NSUInteger argb = [self NSUInteger:json];
|
||||
CGFloat a = ((argb >> 24) & 0xFF) / 255.0;
|
||||
CGFloat r = ((argb >> 16) & 0xFF) / 255.0;
|
||||
CGFloat g = ((argb >> 8) & 0xFF) / 255.0;
|
||||
CGFloat b = (argb & 0xFF) / 255.0;
|
||||
return [UIColor colorWithRed:r green:g blue:b alpha:a];
|
||||
}
|
||||
|
||||
if ([json isKindOfClass:[NSString class]]) {
|
||||
|
||||
// Check named colors
|
||||
static NSDictionary *namedColors = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
namedColors = @{
|
||||
|
||||
// CSS colors
|
||||
@"aliceblue": @"#f0f8ff",
|
||||
@"antiquewhite": @"#faebd7",
|
||||
@"aqua": @"#00ffff",
|
||||
@"aquamarine": @"#7fffd4",
|
||||
@"azure": @"#f0ffff",
|
||||
@"beige": @"#f5f5dc",
|
||||
@"bisque": @"#ffe4c4",
|
||||
@"black": @"#000000",
|
||||
@"blanchedalmond": @"#ffebcd",
|
||||
@"blue": @"#0000ff",
|
||||
@"blueviolet": @"#8a2be2",
|
||||
@"brown": @"#a52a2a",
|
||||
@"burlywood": @"#deb887",
|
||||
@"cadetblue": @"#5f9ea0",
|
||||
@"chartreuse": @"#7fff00",
|
||||
@"chocolate": @"#d2691e",
|
||||
@"coral": @"#ff7f50",
|
||||
@"cornflowerblue": @"#6495ed",
|
||||
@"cornsilk": @"#fff8dc",
|
||||
@"crimson": @"#dc143c",
|
||||
@"cyan": @"#00ffff",
|
||||
@"darkblue": @"#00008b",
|
||||
@"darkcyan": @"#008b8b",
|
||||
@"darkgoldenrod": @"#b8860b",
|
||||
@"darkgray": @"#a9a9a9",
|
||||
@"darkgrey": @"#a9a9a9",
|
||||
@"darkgreen": @"#006400",
|
||||
@"darkkhaki": @"#bdb76b",
|
||||
@"darkmagenta": @"#8b008b",
|
||||
@"darkolivegreen": @"#556b2f",
|
||||
@"darkorange": @"#ff8c00",
|
||||
@"darkorchid": @"#9932cc",
|
||||
@"darkred": @"#8b0000",
|
||||
@"darksalmon": @"#e9967a",
|
||||
@"darkseagreen": @"#8fbc8f",
|
||||
@"darkslateblue": @"#483d8b",
|
||||
@"darkslategray": @"#2f4f4f",
|
||||
@"darkslategrey": @"#2f4f4f",
|
||||
@"darkturquoise": @"#00ced1",
|
||||
@"darkviolet": @"#9400d3",
|
||||
@"deeppink": @"#ff1493",
|
||||
@"deepskyblue": @"#00bfff",
|
||||
@"dimgray": @"#696969",
|
||||
@"dimgrey": @"#696969",
|
||||
@"dodgerblue": @"#1e90ff",
|
||||
@"firebrick": @"#b22222",
|
||||
@"floralwhite": @"#fffaf0",
|
||||
@"forestgreen": @"#228b22",
|
||||
@"fuchsia": @"#ff00ff",
|
||||
@"gainsboro": @"#dcdcdc",
|
||||
@"ghostwhite": @"#f8f8ff",
|
||||
@"gold": @"#ffd700",
|
||||
@"goldenrod": @"#daa520",
|
||||
@"gray": @"#808080",
|
||||
@"grey": @"#808080",
|
||||
@"green": @"#008000",
|
||||
@"greenyellow": @"#adff2f",
|
||||
@"honeydew": @"#f0fff0",
|
||||
@"hotpink": @"#ff69b4",
|
||||
@"indianred": @"#cd5c5c",
|
||||
@"indigo": @"#4b0082",
|
||||
@"ivory": @"#fffff0",
|
||||
@"khaki": @"#f0e68c",
|
||||
@"lavender": @"#e6e6fa",
|
||||
@"lavenderblush": @"#fff0f5",
|
||||
@"lawngreen": @"#7cfc00",
|
||||
@"lemonchiffon": @"#fffacd",
|
||||
@"lightblue": @"#add8e6",
|
||||
@"lightcoral": @"#f08080",
|
||||
@"lightcyan": @"#e0ffff",
|
||||
@"lightgoldenrodyellow": @"#fafad2",
|
||||
@"lightgray": @"#d3d3d3",
|
||||
@"lightgrey": @"#d3d3d3",
|
||||
@"lightgreen": @"#90ee90",
|
||||
@"lightpink": @"#ffb6c1",
|
||||
@"lightsalmon": @"#ffa07a",
|
||||
@"lightseagreen": @"#20b2aa",
|
||||
@"lightskyblue": @"#87cefa",
|
||||
@"lightslategray": @"#778899",
|
||||
@"lightslategrey": @"#778899",
|
||||
@"lightsteelblue": @"#b0c4de",
|
||||
@"lightyellow": @"#ffffe0",
|
||||
@"lime": @"#00ff00",
|
||||
@"limegreen": @"#32cd32",
|
||||
@"linen": @"#faf0e6",
|
||||
@"magenta": @"#ff00ff",
|
||||
@"maroon": @"#800000",
|
||||
@"mediumaquamarine": @"#66cdaa",
|
||||
@"mediumblue": @"#0000cd",
|
||||
@"mediumorchid": @"#ba55d3",
|
||||
@"mediumpurple": @"#9370db",
|
||||
@"mediumseagreen": @"#3cb371",
|
||||
@"mediumslateblue": @"#7b68ee",
|
||||
@"mediumspringgreen": @"#00fa9a",
|
||||
@"mediumturquoise": @"#48d1cc",
|
||||
@"mediumvioletred": @"#c71585",
|
||||
@"midnightblue": @"#191970",
|
||||
@"mintcream": @"#f5fffa",
|
||||
@"mistyrose": @"#ffe4e1",
|
||||
@"moccasin": @"#ffe4b5",
|
||||
@"navajowhite": @"#ffdead",
|
||||
@"navy": @"#000080",
|
||||
@"oldlace": @"#fdf5e6",
|
||||
@"olive": @"#808000",
|
||||
@"olivedrab": @"#6b8e23",
|
||||
@"orange": @"#ffa500",
|
||||
@"orangered": @"#ff4500",
|
||||
@"orchid": @"#da70d6",
|
||||
@"palegoldenrod": @"#eee8aa",
|
||||
@"palegreen": @"#98fb98",
|
||||
@"paleturquoise": @"#afeeee",
|
||||
@"palevioletred": @"#db7093",
|
||||
@"papayawhip": @"#ffefd5",
|
||||
@"peachpuff": @"#ffdab9",
|
||||
@"peru": @"#cd853f",
|
||||
@"pink": @"#ffc0cb",
|
||||
@"plum": @"#dda0dd",
|
||||
@"powderblue": @"#b0e0e6",
|
||||
@"purple": @"#800080",
|
||||
@"rebeccapurple": @"#663399",
|
||||
@"red": @"#ff0000",
|
||||
@"rosybrown": @"#bc8f8f",
|
||||
@"royalblue": @"#4169e1",
|
||||
@"saddlebrown": @"#8b4513",
|
||||
@"salmon": @"#fa8072",
|
||||
@"sandybrown": @"#f4a460",
|
||||
@"seagreen": @"#2e8b57",
|
||||
@"seashell": @"#fff5ee",
|
||||
@"sienna": @"#a0522d",
|
||||
@"silver": @"#c0c0c0",
|
||||
@"skyblue": @"#87ceeb",
|
||||
@"slateblue": @"#6a5acd",
|
||||
@"slategray": @"#708090",
|
||||
@"slategrey": @"#708090",
|
||||
@"snow": @"#fffafa",
|
||||
@"springgreen": @"#00ff7f",
|
||||
@"steelblue": @"#4682b4",
|
||||
@"tan": @"#d2b48c",
|
||||
@"teal": @"#008080",
|
||||
@"thistle": @"#d8bfd8",
|
||||
@"tomato": @"#ff6347",
|
||||
@"turquoise": @"#40e0d0",
|
||||
@"violet": @"#ee82ee",
|
||||
@"wheat": @"#f5deb3",
|
||||
@"white": @"#ffffff",
|
||||
@"whitesmoke": @"#f5f5f5",
|
||||
@"yellow": @"#ffff00",
|
||||
@"yellowgreen": @"#9acd32",
|
||||
|
||||
// Nonstandard color extensions
|
||||
@"transparent": @"rgba(0,0,0,0)",
|
||||
};
|
||||
});
|
||||
NSString *colorString = namedColors[json];
|
||||
if (!colorString) {
|
||||
colorString = json;
|
||||
}
|
||||
|
||||
// Parse color
|
||||
enum {
|
||||
MODE_RGB = 0,
|
||||
MODE_HSB = 1,
|
||||
};
|
||||
struct {
|
||||
union {
|
||||
struct {
|
||||
double r, g, b;
|
||||
} rgb;
|
||||
struct {
|
||||
double h, s, b;
|
||||
} hsb;
|
||||
};
|
||||
double a;
|
||||
unsigned int mode: 1;
|
||||
} components = {
|
||||
.a = 1.0,
|
||||
.mode = MODE_RGB,
|
||||
};
|
||||
|
||||
if ([colorString hasPrefix:@"#"]) {
|
||||
uint32_t redInt = 0, greenInt = 0, blueInt = 0;
|
||||
if (colorString.length == 4) { // 3 digit hex
|
||||
sscanf(colorString.UTF8String, "#%01x%01x%01x", &redInt, &greenInt, &blueInt);
|
||||
// expand to 6 digit hex
|
||||
components.rgb.r = redInt / 15.0;
|
||||
components.rgb.g = greenInt / 15.0;
|
||||
components.rgb.b = blueInt / 15.0;
|
||||
} else if (colorString.length == 7) { // 6 digit hex
|
||||
sscanf(colorString.UTF8String, "#%02x%02x%02x", &redInt, &greenInt, &blueInt);
|
||||
components.rgb.r = redInt / 255.0;
|
||||
components.rgb.g = greenInt / 255.0;
|
||||
components.rgb.b = blueInt / 255.0;
|
||||
} else {
|
||||
RCTLogError(@"Invalid hex color %@. Hex colors should be 3 or 6 digits long.", colorString);
|
||||
components.a = -1;
|
||||
}
|
||||
} else if (4 == sscanf(colorString.UTF8String, "rgba(%lf,%lf,%lf,%lf)", &components.rgb.r, &components.rgb.g, &components.rgb.b, &components.a) ||
|
||||
3 == sscanf(colorString.UTF8String, "rgb(%lf,%lf,%lf)", &components.rgb.r, &components.rgb.g, &components.rgb.b)) {
|
||||
components.rgb.r /= 255.0;
|
||||
components.rgb.g /= 255.0;
|
||||
components.rgb.b /= 255.0;
|
||||
} else if (4 == sscanf(colorString.UTF8String, "hsla(%lf,%lf%%,%lf%%,%lf)", &components.hsb.h, &components.hsb.s, &components.hsb.b, &components.a) ||
|
||||
3 == sscanf(colorString.UTF8String, "hsl(%lf,%lf%%,%lf%%)", &components.hsb.h, &components.hsb.s, &components.hsb.b)) {
|
||||
components.hsb.h /= 360.0;
|
||||
components.hsb.s /= 100.0;
|
||||
components.hsb.b /= 100.0;
|
||||
components.mode = MODE_HSB;
|
||||
} else {
|
||||
RCTLogError(@"Unrecognized color format '%@', must be one of #hex|rgba|rgb or a valid CSS color name.", colorString);
|
||||
components.a = -1;
|
||||
}
|
||||
if (components.a < 0) {
|
||||
RCTLogError(@"Invalid color string '%@'", colorString);
|
||||
} else {
|
||||
if (components.mode == MODE_RGB) {
|
||||
color = [UIColor colorWithRed:components.rgb.r green:components.rgb.g blue:components.rgb.b alpha:components.a];
|
||||
} else {
|
||||
color = [UIColor colorWithHue:components.hsb.h saturation:components.hsb.s brightness:components.hsb.b alpha:components.a];
|
||||
}
|
||||
}
|
||||
|
||||
} else if ([json isKindOfClass:[NSArray class]]) {
|
||||
|
||||
if ([json count] < 3 || [json count] > 4) {
|
||||
RCTLogError(@"Expected array with count 3 or 4, but count is %zd: %@", [json count], json);
|
||||
} else {
|
||||
|
||||
// Color array
|
||||
color = [UIColor colorWithRed:[self CGFloat:json[0]]
|
||||
green:[self CGFloat:json[1]]
|
||||
blue:[self CGFloat:json[2]]
|
||||
alpha:[json count] > 3 ? [self CGFloat:json[3]] : 1];
|
||||
}
|
||||
|
||||
} else if ([json isKindOfClass:[NSDictionary class]]) {
|
||||
|
||||
// Color dictionary
|
||||
if (json[@"r"]) {
|
||||
color = [UIColor colorWithRed:[self CGFloat:json[@"r"]]
|
||||
green:[self CGFloat:json[@"g"]]
|
||||
blue:[self CGFloat:json[@"b"]]
|
||||
alpha:[self CGFloat:json[@"a"] ?: @1]];
|
||||
} else if (json[@"h"]) {
|
||||
color = [UIColor colorWithHue:[self CGFloat:json[@"h"]]
|
||||
saturation:[self CGFloat:json[@"s"]]
|
||||
brightness:[self CGFloat:json[@"b"]]
|
||||
alpha:[self CGFloat:json[@"a"] ?: @1]];
|
||||
} else {
|
||||
RCTLogError(@"Expected dictionary with keys {r,g,b} or {h,s,b}, got: %@", [json allKeys]);
|
||||
}
|
||||
|
||||
} else if (json) {
|
||||
RCTLogConvertError(json, @"a color");
|
||||
}
|
||||
|
||||
// Default color
|
||||
if (!color) {
|
||||
color = [UIColor whiteColor];
|
||||
}
|
||||
|
||||
// Cache and return
|
||||
if (json) {
|
||||
colorCache[json] = color;
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
+ (CGColorRef)CGColor:(id)json
|
||||
|
||||
Reference in New Issue
Block a user