Skip to content

Commit

Permalink
Make Color hold UIColor directly
Browse files Browse the repository at this point in the history
  • Loading branch information
zhongwuzw committed Jan 12, 2024
1 parent 3dae53a commit e1c41be
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 160 deletions.
45 changes: 2 additions & 43 deletions packages/react-native/React/Fabric/RCTConversions.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#import <react/renderer/graphics/Color.h>
#import <react/renderer/graphics/RCTPlatformColorUtils.h>
#import <react/renderer/graphics/Transform.h>
#include <react/utils/ManagedObjectWrapper.h>

NS_ASSUME_NONNULL_BEGIN

Expand All @@ -36,43 +37,6 @@ inline std::string RCTStringFromNSString(NSString *string)
return std::string{string.UTF8String ?: ""};
}

inline UIColor *_Nullable RCTUIColorFromDynamicColor(const facebook::react::Color &color)
{
auto dynamicColor = color.getDynamicColor();
int32_t light = dynamicColor.lightColor;
int32_t dark = dynamicColor.darkColor;
int32_t highContrastLight = dynamicColor.highContrastLightColor;
int32_t highContrastDark = dynamicColor.highContrastDarkColor;

UIColor *lightColor = [RCTConvert UIColor:@(light)];
UIColor *darkColor = [RCTConvert UIColor:@(dark)];
UIColor *highContrastLightColor = [RCTConvert UIColor:@(highContrastLight)];
UIColor *highContrastDarkColor = [RCTConvert UIColor:@(highContrastDark)];

if (lightColor != nil && darkColor != nil) {
UIColor *color = [UIColor colorWithDynamicProvider:^UIColor *_Nonnull(UITraitCollection *_Nonnull collection) {
if (collection.userInterfaceStyle == UIUserInterfaceStyleDark) {
if (collection.accessibilityContrast == UIAccessibilityContrastHigh && highContrastDarkColor != nil) {
return highContrastDarkColor;
} else {
return darkColor;
}
} else {
if (collection.accessibilityContrast == UIAccessibilityContrastHigh && highContrastLightColor != nil) {
return highContrastLightColor;
} else {
return lightColor;
}
}
}];
return color;
} else {
return nil;
}

return nil;
}

inline UIColor *_Nullable RCTUIColorFromSharedColor(const facebook::react::SharedColor &sharedColor)
{
if (!sharedColor) {
Expand All @@ -92,12 +56,7 @@ inline UIColor *_Nullable RCTUIColorFromSharedColor(const facebook::react::Share
}

facebook::react::Color color = *sharedColor;
if (color.getKind() == facebook::react::DynamicKind) {
return RCTUIColorFromDynamicColor(color);
}

auto components = facebook::react::colorComponentsFromColor(sharedColor);
return [UIColor colorWithRed:components.red green:components.green blue:components.blue alpha:components.alpha];
return (UIColor *)facebook::react::unwrapManagedObject(color.getUIColor());
}

inline CF_RETURNS_RETAINED CGColorRef _Nullable RCTCreateCGColorRefFromSharedColor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,39 +14,20 @@

namespace facebook::react {

enum ColorKind { ComponentsKind, DynamicKind };

struct DynamicColor {
int32_t lightColor = 0;
int32_t darkColor = 0;
int32_t highContrastLightColor = 0;
int32_t highContrastDarkColor = 0;

bool operator==(const DynamicColor& other) const {
return lightColor == other.lightColor && darkColor == other.darkColor &&
highContrastLightColor == other.highContrastLightColor &&
highContrastDarkColor == other.highContrastDarkColor;
}
};

class Color {
public:
Color(int32_t color) : kind_(ComponentsKind), color_(color) {}
Color(DynamicColor dynamicColor) : kind_(DynamicKind), color_(dynamicColor) {}
Color(ColorComponents components) {
float ratio = 255;
kind_ = ComponentsKind;
color_ = ((int)round(components.alpha * ratio) & 0xff) << 24 |
((int)round(components.red * ratio) & 0xff) << 16 |
((int)round(components.green * ratio) & 0xff) << 8 |
((int)round(components.blue * ratio) & 0xff);
}
struct Color {
Color(int32_t color);
Color(DynamicColor dynamicColor);
Color(ColorComponents components);
int32_t getColor() const;
ColorKind getKind() const {
return kind_;
}
DynamicColor getDynamicColor() const {
return std::get<DynamicColor>(color_);
std::shared_ptr<void> getUIColor() const {
return uiColor_;
}
ColorComponents getColorComponents() const {
float ratio = 255;
Expand All @@ -57,20 +38,14 @@ class Color {
(float)((primitiveColor >> 0) & 0xff) / ratio,
(float)((primitiveColor >> 24) & 0xff) / ratio};
}
bool operator==(const Color& other) const {
return kind_ == other.kind_ && color_ == other.color_;
}
bool operator!=(const Color& other) const {
return kind_ != other.kind_ || color_ != other.color_;
}
bool operator==(const Color& other) const;
bool operator!=(const Color& other) const;
operator int32_t() const {
return getColor();
}

private:
Color(ColorKind kind) : kind_(kind), color_(0) {}
ColorKind kind_;
std::variant<int32_t, DynamicColor> color_;
std::shared_ptr<void> uiColor_;
};

namespace HostPlatformColor {
Expand All @@ -92,24 +67,7 @@ template <>
struct std::hash<facebook::react::Color> {
size_t operator()(facebook::react::Color color) const {
auto seed = size_t{0};
facebook::react::hash_combine(seed, color.getKind(), color.getColor());
if (color.getKind() == facebook::react::DynamicKind) {
facebook::react::hash_combine(seed, color.getDynamicColor());
}
return seed;
}
};

template <>
struct std::hash<facebook::react::DynamicColor> {
size_t operator()(facebook::react::DynamicColor dynamicColor) const {
auto seed = size_t{0};
facebook::react::hash_combine(
seed,
dynamicColor.lightColor,
dynamicColor.darkColor,
dynamicColor.highContrastLightColor,
dynamicColor.highContrastDarkColor);
facebook::react::hash_combine(seed, color.getColor());
return seed;
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
#import "HostPlatformColor.h"

#import <Foundation/Foundation.h>
#import <React/RCTConvert.h>
#import <UIKit/UIKit.h>
#include <react/utils/ManagedObjectWrapper.h>
#include <string>

using namespace facebook::react;
Expand All @@ -17,34 +19,96 @@

namespace facebook::react {

int32_t RCTPlatformColorGetCurrentColorFromDynamicColor(facebook::react::DynamicColor dynamicColor)
{
int32_t lightColor = dynamicColor.lightColor;
int32_t darkColor = dynamicColor.darkColor;
int32_t highContrastLightColor = dynamicColor.highContrastLightColor;
int32_t highContrastDarkColor = dynamicColor.highContrastDarkColor;
UITraitCollection *currentTraitCollection = [UITraitCollection currentTraitCollection];
if (currentTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
if (currentTraitCollection.accessibilityContrast == UIAccessibilityContrastHigh && highContrastDarkColor) {
return highContrastDarkColor;
} else {
return darkColor;
}
inline UIColor *_Nullable RCTUIColorFromDynamicColor(const facebook::react::DynamicColor &dynamicColor)
{
int32_t light = dynamicColor.lightColor;
int32_t dark = dynamicColor.darkColor;
int32_t highContrastLight = dynamicColor.highContrastLightColor;
int32_t highContrastDark = dynamicColor.highContrastDarkColor;

UIColor *lightColor = [RCTConvert UIColor:@(light)];
UIColor *darkColor = [RCTConvert UIColor:@(dark)];
UIColor *highContrastLightColor = [RCTConvert UIColor:@(highContrastLight)];
UIColor *highContrastDarkColor = [RCTConvert UIColor:@(highContrastDark)];

if (lightColor != nil && darkColor != nil) {
UIColor *color = [UIColor colorWithDynamicProvider:^UIColor *_Nonnull(UITraitCollection *_Nonnull collection) {
if (collection.userInterfaceStyle == UIUserInterfaceStyleDark) {
if (collection.accessibilityContrast == UIAccessibilityContrastHigh && highContrastDarkColor != nil) {
return highContrastDarkColor;
} else {
return darkColor;
}
} else {
if (collection.accessibilityContrast == UIAccessibilityContrastHigh && highContrastLightColor != nil) {
return highContrastLightColor;
} else {
return lightColor;
}
}
}];
return color;
} else {
if (currentTraitCollection.accessibilityContrast == UIAccessibilityContrastHigh && highContrastLightColor) {
return highContrastLightColor;
} else {
return lightColor;
}
return nil;
}

return nil;
}

int32_t Color::getColor() const
static inline int32_t _ColorFromUIColor(UIColor *color)
{
float ratio = 255;
CGFloat rgba[4];
[color getRed:&rgba[0] green:&rgba[1] blue:&rgba[2] alpha:&rgba[3]];
return ((int32_t)round((float)rgba[3] * ratio) & 0xff) << 24 | ((int)round((float)rgba[0] * ratio) & 0xff) << 16 |
((int)round((float)rgba[1] * ratio) & 0xff) << 8 | ((int)round((float)rgba[2] * ratio) & 0xff);
}

int32_t RCTPlatformColorGetColorFromUIColor(const std::shared_ptr<void> uiColor)
{
if (kind_ == DynamicKind) {
return RCTPlatformColorGetCurrentColorFromDynamicColor(getDynamicColor());
UIColor *color = (UIColor *)unwrapManagedObject(uiColor);
if (color) {
UITraitCollection *currentTraitCollection = [UITraitCollection currentTraitCollection];
color = [color resolvedColorWithTraitCollection:currentTraitCollection];
return _ColorFromUIColor(color);
}
return std::get<int32_t>(color_);

return 0;
}

inline UIColor *_Nullable RCTUIColorFromComponentsColor(const facebook::react::ColorComponents &components)
{
return [UIColor colorWithRed:components.red green:components.green blue:components.blue alpha:components.alpha];
}

Color::Color(int32_t color)
{
uiColor_ = wrapManagedObject([RCTConvert UIColor:@(color)]);
}

Color::Color(DynamicColor dynamicColor)
{
uiColor_ = wrapManagedObject(RCTUIColorFromDynamicColor(dynamicColor));
}

Color::Color(ColorComponents components)
{
uiColor_ = wrapManagedObject(RCTUIColorFromComponentsColor(components));
}

bool Color::operator==(const Color &other) const
{
return [unwrapManagedObject(getUIColor()) isEqual:unwrapManagedObject(other.getUIColor())];
}

bool Color::operator!=(const Color &other) const
{
return ![unwrapManagedObject(getUIColor()) isEqual:unwrapManagedObject(other.getUIColor())];
}

int32_t Color::getColor() const
{
return RCTPlatformColorGetColorFromUIColor(uiColor_);
}
} // namespace facebook::react

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#import <React/RCTConvert.h>
#include <react/renderer/textlayoutmanager/RCTFontProperties.h>
#include <react/renderer/textlayoutmanager/RCTFontUtils.h>
#include <react/utils/ManagedObjectWrapper.h>

inline static NSTextAlignment RCTNSTextAlignmentFromTextAlignment(facebook::react::TextAlignment textAlignment)
{
Expand Down Expand Up @@ -95,43 +96,6 @@ inline static NSUnderlineStyle RCTNSUnderlineStyleFromTextDecorationStyle(
}
}

inline UIColor *_Nullable RCTUIColorFromDynamicColor(const facebook::react::Color &color)
{
auto dynamicColor = color.getDynamicColor();
int32_t light = dynamicColor.lightColor;
int32_t dark = dynamicColor.darkColor;
int32_t highContrastLight = dynamicColor.highContrastLightColor;
int32_t highContrastDark = dynamicColor.highContrastDarkColor;

UIColor *lightColor = [RCTConvert UIColor:@(light)];
UIColor *darkColor = [RCTConvert UIColor:@(dark)];
UIColor *highContrastLightColor = [RCTConvert UIColor:@(highContrastLight)];
UIColor *highContrastDarkColor = [RCTConvert UIColor:@(highContrastDark)];

if (lightColor != nil && darkColor != nil) {
UIColor *color = [UIColor colorWithDynamicProvider:^UIColor *_Nonnull(UITraitCollection *_Nonnull collection) {
if (collection.userInterfaceStyle == UIUserInterfaceStyleDark) {
if (collection.accessibilityContrast == UIAccessibilityContrastHigh && highContrastDarkColor != nil) {
return highContrastDarkColor;
} else {
return darkColor;
}
} else {
if (collection.accessibilityContrast == UIAccessibilityContrastHigh && highContrastLightColor != nil) {
return highContrastLightColor;
} else {
return lightColor;
}
}
}];
return color;
} else {
return nil;
}

return nil;
}

// TODO: this file has some duplicates method, we can remove it
inline static UIColor *_Nullable RCTUIColorFromSharedColor(const facebook::react::SharedColor &sharedColor)
{
Expand All @@ -152,10 +116,5 @@ inline static UIColor *_Nullable RCTUIColorFromSharedColor(const facebook::react
}

facebook::react::Color color = *sharedColor;
if (color.getKind() == facebook::react::DynamicKind) {
return RCTUIColorFromDynamicColor(color);
}

auto components = facebook::react::colorComponentsFromColor(sharedColor);
return [UIColor colorWithRed:components.red green:components.green blue:components.blue alpha:components.alpha];
return (UIColor *)facebook::react::unwrapManagedObject(color.getUIColor());
}

0 comments on commit e1c41be

Please sign in to comment.