-
Notifications
You must be signed in to change notification settings - Fork 997
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixes crash in
STPColorUtils.perceivedBrightnessForColor
This is used for deciding whether to use light/dark scroll bars & status bar indicators, and choosing which color should be used for the switch in `STPSwitchTableViewCell`. This code assumed the color was always in the RGB color space, which is incorrect. It would reliably crash with Address Sanitization turned on, and give inconsistent answers with it turned off. Now using the `UIColor` `getRed:green:blue:alpha:` method to convert the color to RGB before calculating the luma value. Also added some links to documentation for why this calculation is interesting. Added tests for `STPColorUtils colorIsBright:` This also tests `perceivedBrightnessForColor:`, but does so by checking something that's more meaningful to me, rather than testing for specific luma numbers
- Loading branch information
1 parent
3881229
commit f9eb0b9
Showing
3 changed files
with
158 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
// | ||
// STPColorUtilsTest.m | ||
// StripeiOS Tests | ||
// | ||
// Created by Daniel Jackson on 5/29/18. | ||
// Copyright © 2018 Stripe, Inc. All rights reserved. | ||
// | ||
|
||
@import XCTest; | ||
|
||
#import "STPColorUtils.h" | ||
|
||
@interface STPColorUtilsTest : XCTestCase | ||
@end | ||
|
||
@implementation STPColorUtilsTest | ||
|
||
- (void)testGrayscaleColorsIsBright { | ||
CGColorSpaceRef space = CGColorSpaceCreateDeviceGray(); | ||
CGFloat components[2] = {0.0, 1.0}; | ||
|
||
// Using 0.3 as the cutoff from bright/non-bright because that's what | ||
// the current implementation does. | ||
|
||
for (CGFloat white = 0.0; white < 0.3; white += 0.05) { | ||
components[0] = white; | ||
CGColorRef cgcolor = CGColorCreate(space, components); | ||
UIColor *color = [UIColor colorWithCGColor:cgcolor]; | ||
|
||
XCTAssertFalse([STPColorUtils colorIsBright:color], @"colorWithWhite: %f", white); | ||
CGColorRelease(cgcolor); | ||
} | ||
|
||
for (CGFloat white = 0.3001; white < 2; white += 0.1) { | ||
components[0] = white; | ||
CGColorRef cgcolor = CGColorCreate(space, components); | ||
UIColor *color = [UIColor colorWithCGColor:cgcolor]; | ||
|
||
XCTAssertTrue([STPColorUtils colorIsBright:color], @"colorWithWhite: %f", white); | ||
CGColorRelease(cgcolor); | ||
} | ||
CGColorSpaceRelease(space); | ||
} | ||
|
||
- (void)testBuiltinColorsIsBright { | ||
// This is primarily to document what colors are considered bright/dark | ||
NSArray<UIColor *> *brightColors = @[ | ||
[UIColor brownColor], | ||
[UIColor cyanColor], | ||
[UIColor darkGrayColor], | ||
[UIColor grayColor], | ||
[UIColor greenColor], | ||
[UIColor lightGrayColor], | ||
[UIColor magentaColor], | ||
[UIColor orangeColor], | ||
[UIColor whiteColor], | ||
[UIColor yellowColor], | ||
]; | ||
NSArray<UIColor *> *darkColors = @[ | ||
[UIColor blackColor], | ||
[UIColor blueColor], | ||
[UIColor clearColor], | ||
[UIColor purpleColor], | ||
[UIColor redColor], | ||
]; | ||
|
||
for (UIColor *color in brightColors) { | ||
XCTAssertTrue([STPColorUtils colorIsBright:color], @"%@", color); | ||
} | ||
|
||
for (UIColor *color in darkColors) { | ||
XCTAssertFalse([STPColorUtils colorIsBright:color], @"%@", color); | ||
} | ||
} | ||
|
||
- (void)testAllColorSpaces { | ||
// block to create & check brightness of color in a given color space | ||
void (^testColorSpace)(const CFStringRef, BOOL) = ^(const CFStringRef colorSpaceName, BOOL expectedToBeBright) { | ||
// this a bright color in almost all color spaces | ||
CGFloat components[] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; | ||
|
||
UIColor *color = nil; | ||
CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(colorSpaceName); | ||
|
||
if (colorSpace) { | ||
CGColorRef cgcolor = CGColorCreate(colorSpace, components); | ||
|
||
if (cgcolor) { | ||
color = [UIColor colorWithCGColor:cgcolor]; | ||
} | ||
CGColorRelease(cgcolor); | ||
} | ||
CGColorSpaceRelease(colorSpace); | ||
|
||
if (color) { | ||
if (expectedToBeBright) { | ||
XCTAssertTrue([STPColorUtils colorIsBright:color], @"%@", color); | ||
} else { | ||
XCTAssertFalse([STPColorUtils colorIsBright:color], @"%@", color); | ||
} | ||
} else { | ||
XCTFail(@"Could not create color for %@", colorSpaceName); | ||
} | ||
}; | ||
|
||
CFStringRef colorSpaceNames[] = { | ||
kCGColorSpaceSRGB, | ||
kCGColorSpaceDCIP3, | ||
kCGColorSpaceROMMRGB, | ||
kCGColorSpaceITUR_709, | ||
kCGColorSpaceDisplayP3, | ||
kCGColorSpaceITUR_2020, | ||
kCGColorSpaceGenericRGB, | ||
kCGColorSpaceGenericXYZ, | ||
kCGColorSpaceLinearGray, | ||
kCGColorSpaceLinearSRGB, | ||
kCGColorSpaceGenericCMYK, | ||
kCGColorSpaceGenericGray, | ||
kCGColorSpaceACESCGLinear, | ||
kCGColorSpaceAdobeRGB1998, | ||
kCGColorSpaceExtendedGray, | ||
kCGColorSpaceExtendedSRGB, | ||
kCGColorSpaceGenericRGBLinear, | ||
kCGColorSpaceExtendedLinearGray, | ||
kCGColorSpaceExtendedLinearSRGB, | ||
kCGColorSpaceGenericGrayGamma2_2, | ||
}; | ||
|
||
int colorSpaceCount = sizeof(colorSpaceNames) / sizeof(colorSpaceNames[0]); | ||
for (int i = 0; i < colorSpaceCount; ++i) { | ||
// CMYK is the only one where all 1's results in a dark color | ||
testColorSpace(colorSpaceNames[i], colorSpaceNames[i] != kCGColorSpaceGenericCMYK); | ||
} | ||
|
||
if (@available(iOS 11.0, *)) { | ||
// in LAB all 1's is dark | ||
testColorSpace(kCGColorSpaceGenericLab, NO); | ||
} | ||
} | ||
|
||
@end |