diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/Color.cpp b/packages/react-native/ReactCommon/react/renderer/graphics/Color.cpp index 6c18ade185355a..b1e9c9cc791825 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/Color.cpp +++ b/packages/react-native/ReactCommon/react/renderer/graphics/Color.cpp @@ -27,6 +27,31 @@ ColorComponents colorComponentsFromColor(SharedColor sharedColor) { return colorComponentsFromHostPlatformColor(*sharedColor); } +// Read alpha channel in [0, 255] range +float alphaFromColor(SharedColor color) { + return alphaFromHostPlatformColor(*color); +} + +// Read red channel in [0, 255] range +float redFromColor(SharedColor color) { + return redFromHostPlatformColor(*color); +} + +// Read green channel in [0, 255] range +float greenFromColor(SharedColor color) { + return greenFromHostPlatformColor(*color); +} + +// Read blue channel in [0, 255] range +float blueFromColor(SharedColor color) { + return blueFromHostPlatformColor(*color); +} + +// Create Color with RGBA values in [0, 255] range +SharedColor colorFromRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { + return {hostPlatformColorFromRGBA(r, g, b, a)}; +} + SharedColor clearColor() { static SharedColor color = colorFromComponents(ColorComponents{0, 0, 0, 0}); return color; diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/Color.h b/packages/react-native/ReactCommon/react/renderer/graphics/Color.h index 0197dd127ea087..c63dacae164047 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/Color.h +++ b/packages/react-native/ReactCommon/react/renderer/graphics/Color.h @@ -57,6 +57,12 @@ bool isColorMeaningful(const SharedColor& color) noexcept; SharedColor colorFromComponents(ColorComponents components); ColorComponents colorComponentsFromColor(SharedColor color); +float alphaFromColor(SharedColor color); +float redFromColor(SharedColor color); +float greenFromColor(SharedColor color); +float blueFromColor(SharedColor color); +SharedColor colorFromRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a); + SharedColor clearColor(); SharedColor blackColor(); SharedColor whiteColor(); diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/android/react/renderer/graphics/HostPlatformColor.h b/packages/react-native/ReactCommon/react/renderer/graphics/platform/android/react/renderer/graphics/HostPlatformColor.h index 0dd7abe08f05d0..7f242fc88c28d1 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/platform/android/react/renderer/graphics/HostPlatformColor.h +++ b/packages/react-native/ReactCommon/react/renderer/graphics/platform/android/react/renderer/graphics/HostPlatformColor.h @@ -19,6 +19,11 @@ static const facebook::react::Color UndefinedColor = std::numeric_limits::max(); } +inline Color +hostPlatformColorFromRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { + return (a & 0xff) << 24 | (r & 0xff) << 16 | (g & 0xff) << 8 | (b & 0xff); +} + inline Color hostPlatformColorFromComponents(ColorComponents components) { float ratio = 255; return ((int)round(components.alpha * ratio) & 0xff) << 24 | @@ -36,4 +41,20 @@ inline ColorComponents colorComponentsFromHostPlatformColor(Color color) { (float)((color >> 24) & 0xff) / ratio}; } +inline float alphaFromHostPlatformColor(Color color) { + return static_cast((color >> 24) & 0xff); +} + +inline float redFromHostPlatformColor(Color color) { + return static_cast((color >> 16) & 0xff); +} + +inline float greenFromHostPlatformColor(Color color) { + return static_cast((color >> 8) & 0xff); +} + +inline float blueFromHostPlatformColor(Color color) { + return static_cast((color >> 0) & 0xff); +} + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/cxx/react/renderer/graphics/HostPlatformColor.h b/packages/react-native/ReactCommon/react/renderer/graphics/platform/cxx/react/renderer/graphics/HostPlatformColor.h index c79b7abd0a8986..5c6e5021f56f2b 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/platform/cxx/react/renderer/graphics/HostPlatformColor.h +++ b/packages/react-native/ReactCommon/react/renderer/graphics/platform/cxx/react/renderer/graphics/HostPlatformColor.h @@ -34,19 +34,19 @@ inline Color hostPlatformColorFromComponents(ColorComponents components) { static_cast(std::round(components.alpha * ratio))); } -inline uint8_t alphaFromHostPlatformColor(Color color) { - return static_cast((color >> 24) & 0xff); +inline float alphaFromHostPlatformColor(Color color) { + return static_cast((color >> 24) & 0xff); } -inline uint8_t redFromHostPlatformColor(Color color) { - return static_cast((color >> 16) & 0xff); +inline float redFromHostPlatformColor(Color color) { + return static_cast((color >> 16) & 0xff); } -inline uint8_t greenFromHostPlatformColor(Color color) { - return static_cast((color >> 8) & 0xff); +inline float greenFromHostPlatformColor(Color color) { + return static_cast((color >> 8) & 0xff); } -inline uint8_t blueFromHostPlatformColor(Color color) { +inline float blueFromHostPlatformColor(Color color) { return static_cast((color >> 0) & 0xff); } diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.h b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.h index 64c26bc7461019..377e9aac6dbbe6 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.h +++ b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.h @@ -29,6 +29,9 @@ struct Color { std::shared_ptr getUIColor() const { return uiColor_; } + + float getChannel(int channelId) const; + ColorComponents getColorComponents() const { float ratio = 255; int32_t primitiveColor = getColor(); @@ -59,6 +62,18 @@ namespace HostPlatformColor { NO_DESTROY static const facebook::react::Color UndefinedColor = Color(nullptr); } // namespace HostPlatformColor +inline Color +hostPlatformColorFromRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { + float ratio = 255; + const auto colorComponents = ColorComponents{ + .red = r / ratio, + .green = g / ratio, + .blue = b / ratio, + .alpha = a / ratio, + }; + return Color(colorComponents); +} + inline Color hostPlatformColorFromComponents(ColorComponents components) { return Color(components); } @@ -67,6 +82,22 @@ inline ColorComponents colorComponentsFromHostPlatformColor(Color color) { return color.getColorComponents(); } +inline float alphaFromHostPlatformColor(Color color) { + return color.getChannel(3) * 255; +} + +inline float redFromHostPlatformColor(Color color) { + return color.getChannel(0) * 255; +} + +inline float greenFromHostPlatformColor(Color color) { + return color.getChannel(1) * 255; +} + +inline float blueFromHostPlatformColor(Color color) { + return color.getChannel(2) * 255; +} + } // namespace facebook::react template <> diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm index 3d1040f1542569..4e7293b1c2ddec 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm +++ b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm @@ -133,6 +133,15 @@ int32_t ColorFromUIColor(const std::shared_ptr &uiColor) { return ColorFromUIColor(uiColor_); } + +float Color::getChannel(int channelId) const +{ + CGFloat rgba[4]; + UIColor *color = (__bridge UIColor *)getUIColor().get(); + [color getRed:&rgba[0] green:&rgba[1] blue:&rgba[2] alpha:&rgba[3]]; + return static_cast(rgba[channelId]); +} + } // namespace facebook::react NS_ASSUME_NONNULL_END diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/tests/ColorTest.cpp b/packages/react-native/ReactCommon/react/renderer/graphics/tests/ColorTest.cpp new file mode 100644 index 00000000000000..1e29701ec3f43c --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/graphics/tests/ColorTest.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +#include + +TEST(ColorTest, testColorConversion) { + using namespace facebook::react; + { + auto color = colorFromRGBA(255, 0, 15, 17); + + EXPECT_EQ(alphaFromColor(color), 17); + EXPECT_EQ(redFromColor(color), 255); + EXPECT_EQ(greenFromColor(color), 0); + EXPECT_EQ(blueFromColor(color), 15); + } + + { + auto color = colorFromComponents( + {.red = 0.1f, .green = 0.2f, .blue = 0, .alpha = 0.3f}); + + EXPECT_EQ(alphaFromColor(color), std::round(255 * 0.3f)); + EXPECT_EQ(redFromColor(color), std::round(255 * 0.1f)); + EXPECT_EQ(greenFromColor(color), 255 * 0.2f); + EXPECT_EQ(blueFromColor(color), 0.f); + + auto colorComponents = colorComponentsFromColor(color); + EXPECT_EQ(std::round(colorComponents.alpha * 10) / 10.f, 0.3f); + EXPECT_EQ(std::round(colorComponents.red * 10) / 10.f, 0.1f); + EXPECT_EQ(std::round(colorComponents.green * 10) / 10.f, 0.2f); + EXPECT_EQ(std::round(colorComponents.blue * 10) / 10.f, 0); + } +}