Files
react-native/ReactCommon/react/renderer/components/view/viewPropConversions.h
T
Ruslan Shestopalyuk 110b191b14 Refactor ViewPropsMapBuffer -> general MapBuffer props mechanism
Summary:
Previously, ViewPropsMapBuffer conversions were hardcoded deep in Android infrastructrue. I've generalized this into a different mechanism to allow any Props struct to support MapBuffer props.

There are still some things that need to be cleaned up and this should be treated as experimental. One thing we likely want to do is remove the hardcoded IDs (fine for codegen'd code; less so for handwritten) and use compile-time-hashed IDs instead with human-readable string names.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D38708719

fbshipit-source-id: 64603dee7f21828be31346c555d99862dab304ea
2022-10-03 04:11:02 -07:00

199 lines
6.2 KiB
C++

/*
* 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/components/view/ViewProps.h>
#include <react/renderer/components/view/ViewPropsMapBuffer.h>
#include <react/renderer/components/view/conversions.h>
#include <react/renderer/graphics/conversions.h>
#include <react/renderer/mapbuffer/MapBuffer.h>
#include <react/renderer/mapbuffer/MapBufferBuilder.h>
#include <optional>
namespace facebook {
namespace react {
namespace {
constexpr MapBuffer::Key EDGE_TOP = 0;
constexpr MapBuffer::Key EDGE_LEFT = 1;
constexpr MapBuffer::Key EDGE_RIGHT = 2;
constexpr MapBuffer::Key EDGE_BOTTOM = 3;
constexpr MapBuffer::Key EDGE_START = 4;
constexpr MapBuffer::Key EDGE_END = 5;
constexpr MapBuffer::Key EDGE_ALL = 6;
constexpr MapBuffer::Key CORNER_TOP_LEFT = 0;
constexpr MapBuffer::Key CORNER_TOP_RIGHT = 1;
constexpr MapBuffer::Key CORNER_BOTTOM_RIGHT = 2;
constexpr MapBuffer::Key CORNER_BOTTOM_LEFT = 3;
constexpr MapBuffer::Key CORNER_TOP_START = 4;
constexpr MapBuffer::Key CORNER_TOP_END = 5;
constexpr MapBuffer::Key CORNER_BOTTOM_END = 6;
constexpr MapBuffer::Key CORNER_BOTTOM_START = 7;
constexpr MapBuffer::Key CORNER_ALL = 8;
inline void putOptionalFloat(
MapBufferBuilder &builder,
MapBuffer::Key key,
std::optional<Float> const &value) {
builder.putDouble(key, value.value_or(NAN));
}
inline std::optional<Float> optionalFromValue(
std::optional<BorderCurve> const &value) {
if (!value) {
return {};
}
return {value.value() == BorderCurve::Circular ? 1 : 2};
}
inline std::optional<Float> optionalFromValue(
std::optional<Float> const &value) {
return value;
}
inline std::optional<Float> optionalFromValue(
std::optional<BorderStyle> const &value) {
if (!value) {
return {};
}
int intValue = -1;
switch (value.value()) {
case BorderStyle::Solid:
intValue = 0;
break;
case BorderStyle::Dotted:
intValue = 1;
break;
case BorderStyle::Dashed:
intValue = 2;
break;
}
return {intValue};
}
inline void putOptionalColor(
MapBufferBuilder &builder,
MapBuffer::Key key,
std::optional<SharedColor> const &color) {
builder.putInt(key, color.has_value() ? toAndroidRepr(color.value()) : -1);
}
inline MapBuffer convertBorderColors(CascadedBorderColors const &colors) {
MapBufferBuilder builder(7);
putOptionalColor(builder, EDGE_TOP, colors.top);
putOptionalColor(builder, EDGE_RIGHT, colors.right);
putOptionalColor(builder, EDGE_BOTTOM, colors.bottom);
putOptionalColor(builder, EDGE_LEFT, colors.left);
putOptionalColor(builder, EDGE_START, colors.start);
putOptionalColor(builder, EDGE_END, colors.end);
putOptionalColor(builder, EDGE_ALL, colors.all);
return builder.build();
}
template <typename T>
MapBuffer convertCascadedEdges(CascadedRectangleEdges<T> const &edges) {
MapBufferBuilder builder(7);
putOptionalFloat(builder, EDGE_TOP, optionalFromValue(edges.top));
putOptionalFloat(builder, EDGE_RIGHT, optionalFromValue(edges.right));
putOptionalFloat(builder, EDGE_BOTTOM, optionalFromValue(edges.bottom));
putOptionalFloat(builder, EDGE_LEFT, optionalFromValue(edges.left));
putOptionalFloat(builder, EDGE_START, optionalFromValue(edges.start));
putOptionalFloat(builder, EDGE_END, optionalFromValue(edges.end));
putOptionalFloat(builder, EDGE_ALL, optionalFromValue(edges.all));
return builder.build();
}
template <typename T>
MapBuffer convertCascadedCorners(CascadedRectangleCorners<T> const &corners) {
MapBufferBuilder builder(9);
putOptionalFloat(
builder, CORNER_TOP_LEFT, optionalFromValue(corners.topLeft));
putOptionalFloat(
builder, CORNER_TOP_RIGHT, optionalFromValue(corners.topRight));
putOptionalFloat(
builder, CORNER_BOTTOM_RIGHT, optionalFromValue(corners.bottomRight));
putOptionalFloat(
builder, CORNER_BOTTOM_LEFT, optionalFromValue(corners.bottomLeft));
putOptionalFloat(
builder, CORNER_TOP_START, optionalFromValue(corners.topStart));
putOptionalFloat(builder, CORNER_TOP_END, optionalFromValue(corners.topEnd));
putOptionalFloat(
builder, CORNER_BOTTOM_END, optionalFromValue(corners.bottomEnd));
putOptionalFloat(
builder, CORNER_BOTTOM_START, optionalFromValue(corners.bottomStart));
putOptionalFloat(builder, CORNER_ALL, optionalFromValue(corners.all));
return builder.build();
}
inline MapBuffer convertEdgeInsets(EdgeInsets const &insets) {
MapBufferBuilder builder(4);
builder.putDouble(EDGE_TOP, insets.top);
builder.putDouble(EDGE_RIGHT, insets.right);
builder.putDouble(EDGE_BOTTOM, insets.bottom);
builder.putDouble(EDGE_LEFT, insets.left);
return builder.build();
}
#ifdef ANDROID
constexpr MapBuffer::Key NATIVE_DRAWABLE_KIND = 0;
constexpr MapBuffer::Key NATIVE_DRAWABLE_ATTRIBUTE = 1;
constexpr MapBuffer::Key NATIVE_DRAWABLE_COLOR = 2;
constexpr MapBuffer::Key NATIVE_DRAWABLE_BORDERLESS = 3;
constexpr MapBuffer::Key NATIVE_DRAWABLE_RIPPLE_RADIUS = 4;
inline MapBuffer convertNativeBackground(
std::optional<NativeDrawable> const &value) {
if (!value.has_value()) {
return MapBufferBuilder::EMPTY();
}
auto const &drawable = value.value();
MapBufferBuilder builder(4);
switch (drawable.kind) {
case NativeDrawable::Kind::ThemeAttr:
builder.putInt(NATIVE_DRAWABLE_KIND, 0);
builder.putString(NATIVE_DRAWABLE_ATTRIBUTE, drawable.themeAttr);
break;
case NativeDrawable::Kind::Ripple:
builder.putInt(NATIVE_DRAWABLE_KIND, 1);
if (drawable.ripple.color.has_value()) {
builder.putInt(NATIVE_DRAWABLE_COLOR, drawable.ripple.color.value());
}
builder.putBool(NATIVE_DRAWABLE_BORDERLESS, drawable.ripple.borderless);
if (drawable.ripple.rippleRadius.has_value()) {
builder.putDouble(
NATIVE_DRAWABLE_RIPPLE_RADIUS,
drawable.ripple.rippleRadius.value());
}
break;
}
return builder.build();
}
#endif
inline MapBuffer convertTransform(Transform const &transform) {
MapBufferBuilder builder(16);
for (int32_t i = 0; i < transform.matrix.size(); i++) {
builder.putDouble(i, transform.matrix[i]);
}
return builder.build();
}
} // namespace
} // namespace react
} // namespace facebook