Skip to content

Commit

Permalink
Abstract underlying Color implementation (#38668)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #38668

On other platforms (e.g., react-native-windows), it's possible that platform colors may not be efficiently represented as int32_t values. In the case of react-native-windows, Color can either be an ARGB value or a list of fallback strings for platform colors.

This change should decouple how platforms represent color values, allowing them to manage how they are used at the point they are used.

## Changelog:
[General] [Added] - Support customization of underlying Color representation in out-of-tree platforms

Reviewed By: NickGerleman

Differential Revision: D47873465

fbshipit-source-id: 1dbb36be409c04ce87b356d75503ec0cf88f1c5b
  • Loading branch information
rozele authored and facebook-github-bot committed Jul 31, 2023
1 parent 6e3e6b5 commit 2b688f6
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ inline void fromRawValue(
colorComponents.blue = items.at(2);
colorComponents.alpha = length == 4 ? items.at(3) : 1.0f;
} else {
colorComponents = parsePlatformColor(context, value);
result = parsePlatformColor(context, value);
return;
}

result = colorFromComponents(colorComponents);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,11 @@ bool isColorMeaningful(SharedColor const &color) noexcept {
}

SharedColor colorFromComponents(ColorComponents components) {
float ratio = 255;
return {
((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)};
return {hostPlatformColorFromComponents(components)};
}

ColorComponents colorComponentsFromColor(SharedColor sharedColor) {
float ratio = 255;
Color color = *sharedColor;
return ColorComponents{
(float)((color >> 16) & 0xff) / ratio,
(float)((color >> 8) & 0xff) / ratio,
(float)((color >> 0) & 0xff) / ratio,
(float)((color >> 24) & 0xff) / ratio};
return colorComponentsFromHostPlatformColor(*sharedColor);
}

SharedColor clearColor() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,25 @@

#pragma once

#include <cmath>
#include <functional>
#include <limits>

#include <react/renderer/graphics/ColorComponents.h>
#include <react/renderer/graphics/HostPlatformColor.h>

namespace facebook::react {

using Color = int32_t;

/*
* On Android, a color can be represented as 32 bits integer, so there is no
* need to instantiate complex color objects and then pass them as shared
* pointers. Hense instead of using shared_ptr, we use a simple wrapper class
* which provides a pointer-like interface.
* which provides a pointer-like interface. On other platforms, colors may be
* represented by more complex objects that cannot be represented as 32-bits
* integers, so we hide the implementation detail in HostPlatformColor.h.
*/
class SharedColor {
public:
static const Color UndefinedColor = std::numeric_limits<Color>::max();
static const Color UndefinedColor = HostPlatformColor::UndefinedColor;

SharedColor() : color_(UndefinedColor) {}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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.
*/

#pragma once

#include <react/renderer/graphics/ColorComponents.h>
#include <cmath>

namespace facebook::react {

using Color = int32_t;

namespace HostPlatformColor {
static const facebook::react::Color UndefinedColor =
std::numeric_limits<facebook::react::Color>::max();
}

inline Color hostPlatformColorFromComponents(ColorComponents components) {
float ratio = 255;
return ((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);
}

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};
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
#include <fbjni/fbjni.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/RawProps.h>
#include <react/renderer/graphics/ColorComponents.h>
#include <react/renderer/graphics/Color.h>

namespace facebook::react {

inline ColorComponents parsePlatformColor(
inline SharedColor parsePlatformColor(
const PropsParserContext &context,
const RawValue &value) {
ColorComponents colorComponents = {0, 0, 0, 0};
Expand Down Expand Up @@ -46,7 +46,7 @@ inline ColorComponents parsePlatformColor(
colorComponents.blue = (argb & 0xFF) / ratio;
}

return colorComponents;
return {colorFromComponents(colorComponents)};
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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.
*/

#pragma once

#include <react/renderer/graphics/ColorComponents.h>
#include <cmath>

namespace facebook::react {

using Color = int32_t;

namespace HostPlatformColor {
static const facebook::react::Color UndefinedColor =
std::numeric_limits<facebook::react::Color>::max();
}

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);
}

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};
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@

#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/RawProps.h>
#include <react/renderer/graphics/ColorComponents.h>
#include <react/renderer/graphics/Color.h>

namespace facebook::react {

inline ColorComponents parsePlatformColor(
inline SharedColor parsePlatformColor(
const PropsParserContext &context,
const RawValue &value) {
float alpha = 0;
float red = 0;
float green = 0;
float blue = 0;

return {red, green, blue, alpha};
return {colorFromComponents({red, green, blue, alpha})};
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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.
*/

#pragma once

#include <react/renderer/graphics/ColorComponents.h>
#include <cmath>

namespace facebook::react {

using Color = int32_t;

namespace HostPlatformColor {
static const facebook::react::Color UndefinedColor =
std::numeric_limits<facebook::react::Color>::max();
}

inline Color hostPlatformColorFromComponents(ColorComponents components) {
float ratio = 255;
return ((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);
}

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};
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,25 @@

#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/RawProps.h>
#include <react/renderer/graphics/ColorComponents.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/RCTPlatformColorUtils.h>

namespace facebook::react {

inline ColorComponents parsePlatformColor(
inline SharedColor parsePlatformColor(
const PropsParserContext &context,
const RawValue &value) {
if (value.hasType<butter::map<std::string, RawValue>>()) {
auto items = (butter::map<std::string, RawValue>)value;
if (items.find("semantic") != items.end() &&
items.at("semantic").hasType<std::vector<std::string>>()) {
auto semanticItems = (std::vector<std::string>)items.at("semantic");
return RCTPlatformColorComponentsFromSemanticItems(semanticItems);
return {colorFromComponents(
RCTPlatformColorComponentsFromSemanticItems(semanticItems))};
}
}

return {0, 0, 0, 0};
return clearColor();
}

} // namespace facebook::react

0 comments on commit 2b688f6

Please sign in to comment.