Add HSL/HSLA support
This commit is contained in:
parent
0f14933948
commit
96277ca3f5
|
@ -54,6 +54,7 @@
|
|||
3578590A1B28D2CF00341EDB /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 357859011B28D2C500341EDB /* libRCTLinking.a */; };
|
||||
834C36EC1AF8DED70019C93C /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 834C36D21AF8DA610019C93C /* libRCTSettings.a */; };
|
||||
83636F8F1B53F22C009F943E /* RCTUIManagerScenarioTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 83636F8E1B53F22C009F943E /* RCTUIManagerScenarioTests.m */; };
|
||||
83A936C81B7E0F08005B9C36 /* RCTConvert_UIColorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 83A936C71B7E0F08005B9C36 /* RCTConvert_UIColorTests.m */; };
|
||||
D85B829E1AB6D5D7003F4FE2 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D85B829C1AB6D5CE003F4FE2 /* libRCTVibration.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
|
@ -216,6 +217,7 @@
|
|||
357858F81B28D2C400341EDB /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = ../../Libraries/LinkingIOS/RCTLinking.xcodeproj; sourceTree = "<group>"; };
|
||||
58005BE41ABA80530062E044 /* RCTTest.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTTest.xcodeproj; path = ../../Libraries/RCTTest/RCTTest.xcodeproj; sourceTree = "<group>"; };
|
||||
83636F8E1B53F22C009F943E /* RCTUIManagerScenarioTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTUIManagerScenarioTests.m; sourceTree = "<group>"; };
|
||||
83A936C71B7E0F08005B9C36 /* RCTConvert_UIColorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTConvert_UIColorTests.m; sourceTree = "<group>"; };
|
||||
D85B82911AB6D5CE003F4FE2 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = ../../Libraries/Vibration/RCTVibration.xcodeproj; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
|
@ -359,6 +361,7 @@
|
|||
138D6A151B53CD440074A87E /* RCTCacheTests.m */,
|
||||
1497CFA61B21F5E400C1F8F2 /* RCTContextExecutorTests.m */,
|
||||
1497CFA71B21F5E400C1F8F2 /* RCTConvert_NSURLTests.m */,
|
||||
83A936C71B7E0F08005B9C36 /* RCTConvert_UIColorTests.m */,
|
||||
1497CFA81B21F5E400C1F8F2 /* RCTConvert_UIFontTests.m */,
|
||||
1497CFA91B21F5E400C1F8F2 /* RCTEventDispatcherTests.m */,
|
||||
1300627E1B59179B0043FE5A /* RCTGzipTests.m */,
|
||||
|
@ -805,6 +808,7 @@
|
|||
138D6A171B53CD440074A87E /* RCTCacheTests.m in Sources */,
|
||||
13DB03481B5D2ED500C27245 /* RCTJSONTests.m in Sources */,
|
||||
1497CFAC1B21F5E400C1F8F2 /* RCTAllocationTests.m in Sources */,
|
||||
83A936C81B7E0F08005B9C36 /* RCTConvert_UIColorTests.m in Sources */,
|
||||
13DF61B61B67A45000EDB188 /* RCTMethodArgumentTests.m in Sources */,
|
||||
138D6A181B53CD440074A87E /* RCTShadowViewTests.m in Sources */,
|
||||
);
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "RCTConvert.h"
|
||||
|
||||
@interface RCTConvert_UIColorTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTConvert_UIColorTests
|
||||
|
||||
#define XCTAssertEqualColors(color1, color2) do { \
|
||||
CGFloat r1, g1, b1, a1; \
|
||||
CGFloat r2, g2, b2, a2; \
|
||||
XCTAssertTrue([(color1) getRed:&r1 green:&g1 blue:&b1 alpha:&a1] && \
|
||||
[(color2) getRed:&r2 green:&g2 blue:&b2 alpha:&a2] && \
|
||||
r1 == r2 && g1 == g2 && b1 == b2 && a1 == a2, \
|
||||
@"rgba(%d, %d, %d, %.3f) != rgba(%d, %d, %d, %.3f)", \
|
||||
(int)(r1 * 255), (int)(g1 * 255), (int)(b1 * 255), a1, \
|
||||
(int)(r2 * 255), (int)(g2 * 255), (int)(b2 * 255), a2 \
|
||||
); \
|
||||
} while (0)
|
||||
|
||||
- (void)testHex3
|
||||
{
|
||||
UIColor *color = [RCTConvert UIColor:@"#333"];
|
||||
UIColor *expected = [UIColor colorWithWhite:0.2 alpha:1.0];
|
||||
XCTAssertEqualColors(color, expected);
|
||||
}
|
||||
|
||||
- (void)testHex6
|
||||
{
|
||||
UIColor *color = [RCTConvert UIColor:@"#666"];
|
||||
UIColor *expected = [UIColor colorWithWhite:0.4 alpha:1.0];
|
||||
XCTAssertEqualColors(color, expected);
|
||||
}
|
||||
|
||||
- (void)testRGB
|
||||
{
|
||||
UIColor *color = [RCTConvert UIColor:@"rgb(51, 102, 153)"];
|
||||
UIColor *expected = [UIColor colorWithRed:0.2 green:0.4 blue:0.6 alpha:1.0];
|
||||
XCTAssertEqualColors(color, expected);
|
||||
}
|
||||
|
||||
- (void)testRGBA
|
||||
{
|
||||
UIColor *color = [RCTConvert UIColor:@"rgba(51, 102, 153, 0.5)"];
|
||||
UIColor *expected = [UIColor colorWithRed:0.2 green:0.4 blue:0.6 alpha:0.5];
|
||||
XCTAssertEqualColors(color, expected);
|
||||
}
|
||||
|
||||
- (void)testHSL
|
||||
{
|
||||
UIColor *color = [RCTConvert UIColor:@"hsl(30, 50%, 50%)"];
|
||||
UIColor *expected = [UIColor colorWithHue:30.0 / 360.0 saturation:0.5 brightness:0.5 alpha:1.0];
|
||||
XCTAssertEqualColors(color, expected);
|
||||
}
|
||||
|
||||
- (void)testHSLA
|
||||
{
|
||||
UIColor *color = [RCTConvert UIColor:@"hsla(30, 50%, 50%, 0.5)"];
|
||||
UIColor *expected = [UIColor colorWithHue:30.0 / 360.0 saturation:0.5 brightness:0.5 alpha:0.5];
|
||||
XCTAssertEqualColors(color, expected);
|
||||
}
|
||||
|
||||
@end
|
|
@ -559,37 +559,66 @@ RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[
|
|||
}
|
||||
|
||||
// Parse color
|
||||
double red = 0, green = 0, blue = 0;
|
||||
double alpha = 1.0;
|
||||
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
|
||||
red = redInt | (redInt << 4);
|
||||
green = greenInt | (greenInt << 4);
|
||||
blue = blueInt | (blueInt << 4);
|
||||
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);
|
||||
red = redInt;
|
||||
green = greenInt;
|
||||
blue = 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);
|
||||
alpha = -1;
|
||||
components.a = -1;
|
||||
}
|
||||
} else if ([colorString hasPrefix:@"rgba("]) {
|
||||
sscanf(colorString.UTF8String, "rgba(%lf,%lf,%lf,%lf)", &red, &green, &blue, &alpha);
|
||||
} else if ([colorString hasPrefix:@"rgb("]) {
|
||||
sscanf(colorString.UTF8String, "rgb(%lf,%lf,%lf)", &red, &green, &blue);
|
||||
} 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);
|
||||
alpha = -1;
|
||||
components.a = -1;
|
||||
}
|
||||
if (alpha < 0) {
|
||||
if (components.a < 0) {
|
||||
RCTLogError(@"Invalid color string '%@'", colorString);
|
||||
} else {
|
||||
color = [UIColor colorWithRed:red / 255.0 green:green / 255.0 blue:blue / 255.0 alpha:alpha];
|
||||
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]]) {
|
||||
|
@ -608,10 +637,19 @@ RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[
|
|||
} else if ([json isKindOfClass:[NSDictionary class]]) {
|
||||
|
||||
// Color dictionary
|
||||
color = [UIColor colorWithRed:[self CGFloat:json[@"r"]]
|
||||
green:[self CGFloat:json[@"g"]]
|
||||
blue:[self CGFloat:json[@"b"]]
|
||||
alpha:[self CGFloat:json[@"a"] ?: @1]];
|
||||
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");
|
||||
|
|
Loading…
Reference in New Issue