From b5683a7516ef185aa4a8482fee34d092ba055ee5 Mon Sep 17 00:00:00 2001 From: Zeya Peng Date: Tue, 25 Jun 2024 16:04:56 -0700 Subject: [PATCH] Create util functions to convert Color <-> uint8_t RGBA values (#45139) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45139 ## Changelog Sometimes we pass down int RGBA values in [0, 255] to represent color components in ReactNative; and other times we use float. Since we introduce display P3, we probably want to use color depth more than 8bit In the first case, when RGBA are passed down as uint8_t, we can directly calculate Color/SharedColor without normalizing them to [0,1] and scale back to [0, 255] as `colorFromComponents` does; otherwise there could be some precision loss.. So here I'm adding some new utils for that purpose: see `colorFromRGBA`, `redFromColor`, `greenFromColor`, etc [Internal] Examples in codebase: * rgba in [0, 255]: https://www.internalfb.com/code/fbsource/[67148a47147b0e15f0f0748003394040611c2bc2]/xplat/js/react-native-github/packages/react-native/ReactCommon/react/renderer/graphics/fromRawValueShared.h?lines=28-35 * rgba in [0, 1]: https://www.internalfb.com/code/fbsource/[67148a47147b0e15f0f0748003394040611c2bc2]/xplat/js/react-native-github/packages/react-native/ReactCommon/react/renderer/graphics/fromRawValueShared.h?lines=37-45 https://www.internalfb.com/code/fbsource/[67148a47147b0e15f0f0748003394040611c2bc2]/xplat/js/react-native-github/packages/react-native/ReactCommon/react/renderer/graphics/fromRawValueShared.h?lines=47-64 Reviewed By: rshest Differential Revision: D58872165 fbshipit-source-id: 748a12a99591c895fed65cda6deeaa2a3e0c3cf5 --- .../react/renderer/graphics/Color.cpp | 2 + .../renderer/graphics/HostPlatformColor.h | 39 +++++++++++++++---- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/Color.cpp b/packages/react-native/ReactCommon/react/renderer/graphics/Color.cpp index 8a2db873151..6c18ade1853 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/Color.cpp +++ b/packages/react-native/ReactCommon/react/renderer/graphics/Color.cpp @@ -17,10 +17,12 @@ bool isColorMeaningful(const SharedColor& color) noexcept { return colorComponentsFromColor(color).alpha > 0; } +// Create Color from float RGBA values in [0, 1] range SharedColor colorFromComponents(ColorComponents components) { return {hostPlatformColorFromComponents(components)}; } +// Read Color components in [0, 1] range ColorComponents colorComponentsFromColor(SharedColor sharedColor) { return colorComponentsFromHostPlatformColor(*sharedColor); } 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 6ea3c571ac5..c79b7abd0a8 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 @@ -9,6 +9,7 @@ #include #include +#include namespace facebook::react { @@ -19,21 +20,43 @@ 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)std::round(components.alpha * ratio) & 0xff) << 24 | - ((int)std::round(components.red * ratio) & 0xff) << 16 | - ((int)std::round(components.green * ratio) & 0xff) << 8 | - ((int)std::round(components.blue * ratio) & 0xff); + return hostPlatformColorFromRGBA( + static_cast(std::round(components.red * ratio)), + static_cast(std::round(components.green * ratio)), + static_cast(std::round(components.blue * ratio)), + static_cast(std::round(components.alpha * ratio))); +} + +inline uint8_t alphaFromHostPlatformColor(Color color) { + return static_cast((color >> 24) & 0xff); +} + +inline uint8_t redFromHostPlatformColor(Color color) { + return static_cast((color >> 16) & 0xff); +} + +inline uint8_t greenFromHostPlatformColor(Color color) { + return static_cast((color >> 8) & 0xff); +} + +inline uint8_t blueFromHostPlatformColor(Color color) { + return static_cast((color >> 0) & 0xff); } inline ColorComponents colorComponentsFromHostPlatformColor(Color color) { float ratio = 255; return ColorComponents{ - (float)((color >> 16) & 0xff) / ratio, - (float)((color >> 8) & 0xff) / ratio, - (float)((color >> 0) & 0xff) / ratio, - (float)((color >> 24) & 0xff) / ratio}; + static_cast(redFromHostPlatformColor(color)) / ratio, + static_cast(greenFromHostPlatformColor(color)) / ratio, + static_cast(blueFromHostPlatformColor(color)) / ratio, + static_cast(alphaFromHostPlatformColor(color)) / ratio}; } } // namespace facebook::react