mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-28 12:15:37 +08:00
Fabric: Proper way to represent (and parse) borders in ViewProps
Summary: @public Previously, ViewProps class coundn't represent whole spectre of possible values of border metrics (e.g. the border color was unified). Now it's complete and direction-specific. Reviewed By: sahrens Differential Revision: D9628361 fbshipit-source-id: 6d3b3d4d7e3008e2168cbca732ff99fe5ea595e8
This commit is contained in:
committed by
Facebook Github Bot
parent
6e7ffff4a5
commit
ca1e9032a4
@@ -137,10 +137,10 @@ using namespace facebook::react;
|
|||||||
|
|
||||||
// `border`
|
// `border`
|
||||||
if (
|
if (
|
||||||
oldViewProps.borderWidth != newViewProps.borderWidth ||
|
oldViewProps.borderWidths != newViewProps.borderWidths ||
|
||||||
oldViewProps.borderStyle != newViewProps.borderStyle ||
|
oldViewProps.borderStyles != newViewProps.borderStyles ||
|
||||||
oldViewProps.borderRadius != newViewProps.borderRadius ||
|
oldViewProps.borderRadii != newViewProps.borderRadii ||
|
||||||
oldViewProps.borderColor != newViewProps.borderColor
|
oldViewProps.borderColors != newViewProps.borderColors
|
||||||
) {
|
) {
|
||||||
[self invalidateBorder];
|
[self invalidateBorder];
|
||||||
}
|
}
|
||||||
@@ -174,10 +174,15 @@ using namespace facebook::react;
|
|||||||
{
|
{
|
||||||
const auto &props = *std::dynamic_pointer_cast<const ViewProps>(_props);
|
const auto &props = *std::dynamic_pointer_cast<const ViewProps>(_props);
|
||||||
|
|
||||||
bool useCoreAnimationBorderRendering =
|
const auto borderMetrics =
|
||||||
props.borderStyle == BorderStyle::Solid &&
|
props.resolveBorderMetrics(_layoutMetrics.layoutDirection == LayoutDirection::RightToLeft);
|
||||||
props.borderWidth.isUniform() &&
|
|
||||||
props.borderRadius.isUniform();
|
const bool useCoreAnimationBorderRendering =
|
||||||
|
borderMetrics.borderColors.isUniform() &&
|
||||||
|
borderMetrics.borderWidths.isUniform() &&
|
||||||
|
borderMetrics.borderStyles.isUniform() &&
|
||||||
|
borderMetrics.borderRadii.isUniform() &&
|
||||||
|
borderMetrics.borderStyles.left == BorderStyle::Solid;
|
||||||
|
|
||||||
CALayer *layer = self.layer;
|
CALayer *layer = self.layer;
|
||||||
if (_isCoreAnimationBorderRenderingEnabled != useCoreAnimationBorderRendering) {
|
if (_isCoreAnimationBorderRenderingEnabled != useCoreAnimationBorderRendering) {
|
||||||
@@ -190,11 +195,10 @@ using namespace facebook::react;
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (useCoreAnimationBorderRendering) {
|
if (useCoreAnimationBorderRendering) {
|
||||||
layer.borderWidth = (CGFloat)props.borderWidth.left;
|
layer.borderWidth = (CGFloat)borderMetrics.borderWidths.left;
|
||||||
layer.borderColor = RCTCGColorRefFromSharedColor(props.borderColor);
|
layer.borderColor = RCTCGColorRefFromSharedColor(borderMetrics.borderColors.left);
|
||||||
layer.cornerRadius = (CGFloat)props.borderRadius.topLeft;
|
layer.cornerRadius = (CGFloat)borderMetrics.borderRadii.topLeft;
|
||||||
_contentView.layer.cornerRadius = (CGFloat)props.borderRadius.topLeft;
|
_contentView.layer.cornerRadius = (CGFloat)borderMetrics.borderRadii.topLeft;
|
||||||
_contentView.layer.masksToBounds = YES;
|
|
||||||
} else {
|
} else {
|
||||||
// Not supported yet.
|
// Not supported yet.
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "ViewProps.h"
|
#include "ViewProps.h"
|
||||||
|
|
||||||
#include <fabric/components/view/conversions.h>
|
#include <fabric/components/view/conversions.h>
|
||||||
|
#include <fabric/components/view/propsConversions.h>
|
||||||
#include <fabric/core/propsConversions.h>
|
#include <fabric/core/propsConversions.h>
|
||||||
#include <fabric/debug/debugStringConvertibleUtils.h>
|
#include <fabric/debug/debugStringConvertibleUtils.h>
|
||||||
#include <fabric/graphics/conversions.h>
|
#include <fabric/graphics/conversions.h>
|
||||||
@@ -24,10 +25,10 @@ ViewProps::ViewProps(const ViewProps &sourceProps, const RawProps &rawProps):
|
|||||||
opacity(convertRawProp(rawProps, "opacity", sourceProps.opacity, (Float)1.0)),
|
opacity(convertRawProp(rawProps, "opacity", sourceProps.opacity, (Float)1.0)),
|
||||||
foregroundColor(convertRawProp(rawProps, "foregroundColor", sourceProps.foregroundColor)),
|
foregroundColor(convertRawProp(rawProps, "foregroundColor", sourceProps.foregroundColor)),
|
||||||
backgroundColor(convertRawProp(rawProps, "backgroundColor", sourceProps.backgroundColor)),
|
backgroundColor(convertRawProp(rawProps, "backgroundColor", sourceProps.backgroundColor)),
|
||||||
borderWidth(convertRawProp(rawProps, "borderWidth", sourceProps.borderWidth)),
|
borderWidths(convertRawProp(rawProps, "border", "Width", sourceProps.borderWidths)),
|
||||||
borderRadius(convertRawProp(rawProps, "borderRadius", sourceProps.borderRadius)),
|
borderRadii(convertRawProp(rawProps, "border", "Radius", sourceProps.borderRadii)),
|
||||||
borderColor(convertRawProp(rawProps, "borderColor", sourceProps.borderColor)),
|
borderColors(convertRawProp(rawProps, "border", "Color", sourceProps.borderColors)),
|
||||||
borderStyle(convertRawProp(rawProps, "borderStyle", sourceProps.borderStyle)),
|
borderStyles(convertRawProp(rawProps, "border", "Style", sourceProps.borderStyles)),
|
||||||
shadowColor(convertRawProp(rawProps, "shadowColor", sourceProps.shadowColor)),
|
shadowColor(convertRawProp(rawProps, "shadowColor", sourceProps.shadowColor)),
|
||||||
shadowOffset(convertRawProp(rawProps, "shadowOffset", sourceProps.shadowOffset)),
|
shadowOffset(convertRawProp(rawProps, "shadowOffset", sourceProps.shadowOffset)),
|
||||||
shadowOpacity(convertRawProp(rawProps, "shadowOpacity", sourceProps.shadowOpacity)),
|
shadowOpacity(convertRawProp(rawProps, "shadowOpacity", sourceProps.shadowOpacity)),
|
||||||
@@ -40,6 +41,17 @@ ViewProps::ViewProps(const ViewProps &sourceProps, const RawProps &rawProps):
|
|||||||
hitSlop(convertRawProp(rawProps, "hitSlop", sourceProps.hitSlop)),
|
hitSlop(convertRawProp(rawProps, "hitSlop", sourceProps.hitSlop)),
|
||||||
onLayout(convertRawProp(rawProps, "onLayout", sourceProps.onLayout)) {};
|
onLayout(convertRawProp(rawProps, "onLayout", sourceProps.onLayout)) {};
|
||||||
|
|
||||||
|
#pragma mark - Convenience Methods
|
||||||
|
|
||||||
|
BorderMetrics ViewProps::resolveBorderMetrics(bool isRTL) const {
|
||||||
|
return {
|
||||||
|
.borderColors = borderColors.resolve(isRTL, {}),
|
||||||
|
.borderWidths = borderWidths.resolve(isRTL, 0),
|
||||||
|
.borderRadii = borderRadii.resolve(isRTL, 0),
|
||||||
|
.borderStyles = borderStyles.resolve(isRTL, BorderStyle::Solid)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - DebugStringConvertible
|
#pragma mark - DebugStringConvertible
|
||||||
|
|
||||||
SharedDebugStringConvertibleList ViewProps::getDebugProps() const {
|
SharedDebugStringConvertibleList ViewProps::getDebugProps() const {
|
||||||
|
|||||||
@@ -39,10 +39,10 @@ public:
|
|||||||
const SharedColor backgroundColor {};
|
const SharedColor backgroundColor {};
|
||||||
|
|
||||||
// Borders
|
// Borders
|
||||||
const EdgeInsets borderWidth {};
|
const CascadedBorderWidths borderWidths {};
|
||||||
const CornerInsets borderRadius {};
|
const CascadedBorderRadii borderRadii {};
|
||||||
const SharedColor borderColor {};
|
const CascadedBorderColors borderColors {};
|
||||||
const BorderStyle borderStyle {};
|
const CascadedBorderStyles borderStyles {};
|
||||||
|
|
||||||
// Shadow
|
// Shadow
|
||||||
const SharedColor shadowColor {};
|
const SharedColor shadowColor {};
|
||||||
@@ -61,6 +61,10 @@ public:
|
|||||||
const EdgeInsets hitSlop {};
|
const EdgeInsets hitSlop {};
|
||||||
const bool onLayout {};
|
const bool onLayout {};
|
||||||
|
|
||||||
|
#pragma mark - Convenience Methods
|
||||||
|
|
||||||
|
BorderMetrics resolveBorderMetrics(bool isRTL) const;
|
||||||
|
|
||||||
#pragma mark - DebugStringConvertible
|
#pragma mark - DebugStringConvertible
|
||||||
|
|
||||||
SharedDebugStringConvertibleList getDebugProps() const override;
|
SharedDebugStringConvertibleList getDebugProps() const override;
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <fabric/graphics/Color.h>
|
||||||
#include <fabric/graphics/Geometry.h>
|
#include <fabric/graphics/Geometry.h>
|
||||||
|
#include <folly/Optional.h>
|
||||||
|
|
||||||
namespace facebook {
|
namespace facebook {
|
||||||
namespace react {
|
namespace react {
|
||||||
@@ -157,5 +159,112 @@ enum class BorderStyle {
|
|||||||
Dashed
|
Dashed
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct CascadedRectangleEdges {
|
||||||
|
using Counterpart = RectangleEdges<T>;
|
||||||
|
using OptionalT = folly::Optional<T>;
|
||||||
|
|
||||||
|
OptionalT left {};
|
||||||
|
OptionalT top {};
|
||||||
|
OptionalT right {};
|
||||||
|
OptionalT bottom {};
|
||||||
|
OptionalT start {};
|
||||||
|
OptionalT end {};
|
||||||
|
OptionalT horizontal {};
|
||||||
|
OptionalT vertical {};
|
||||||
|
OptionalT all {};
|
||||||
|
|
||||||
|
Counterpart resolve(bool isRTL, T defaults) const {
|
||||||
|
const auto leading = isRTL ? end : start;
|
||||||
|
const auto trailing = isRTL ? start : end;
|
||||||
|
const auto horizontalOrAllOrDefault = horizontal.value_or(all.value_or(defaults));
|
||||||
|
const auto verticalOrAllOrDefault = vertical.value_or(all.value_or(defaults));
|
||||||
|
|
||||||
|
return Counterpart {
|
||||||
|
.left = left.value_or(leading.value_or(horizontalOrAllOrDefault)),
|
||||||
|
.right = right.value_or(trailing.value_or(horizontalOrAllOrDefault)),
|
||||||
|
.top = top.value_or(verticalOrAllOrDefault),
|
||||||
|
.bottom = bottom.value_or(verticalOrAllOrDefault)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const CascadedRectangleEdges<T> &rhs) const {
|
||||||
|
return
|
||||||
|
std::tie(this->left, this->top, this->right, this->bottom, this->start, this->end, this->horizontal, this->vertical, this->all) ==
|
||||||
|
std::tie(rhs.left, rhs.top, rhs.right, rhs.bottom, rhs.start, rhs.end, rhs.horizontal, rhs.vertical, rhs.all);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const CascadedRectangleEdges<T> &rhs) const {
|
||||||
|
return !(*this == rhs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct CascadedRectangleCorners {
|
||||||
|
using Counterpart = RectangleCorners<T>;
|
||||||
|
using OptionalT = folly::Optional<T>;
|
||||||
|
|
||||||
|
OptionalT topLeft {};
|
||||||
|
OptionalT topRight {};
|
||||||
|
OptionalT bottomLeft {};
|
||||||
|
OptionalT bottomRight {};
|
||||||
|
OptionalT topStart {};
|
||||||
|
OptionalT topEnd {};
|
||||||
|
OptionalT bottomStart {};
|
||||||
|
OptionalT bottomEnd {};
|
||||||
|
OptionalT all {};
|
||||||
|
|
||||||
|
Counterpart resolve(bool isRTL, T defaults) const {
|
||||||
|
const auto topLeading = isRTL ? topEnd : topStart;
|
||||||
|
const auto topTrailing = isRTL ? topStart : topEnd;
|
||||||
|
const auto bottomLeading = isRTL ? bottomEnd : bottomStart;
|
||||||
|
const auto bottomTrailing = isRTL ? bottomStart : bottomEnd;
|
||||||
|
|
||||||
|
return Counterpart {
|
||||||
|
.topLeft = topLeft.value_or(topLeading.value_or(all.value_or(defaults))),
|
||||||
|
.topRight = topRight.value_or(topTrailing.value_or(all.value_or(defaults))),
|
||||||
|
.bottomLeft = bottomLeft.value_or(topLeading.value_or(all.value_or(defaults))),
|
||||||
|
.bottomRight = bottomRight.value_or(topTrailing.value_or(all.value_or(defaults)))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const CascadedRectangleCorners<T> &rhs) const {
|
||||||
|
return
|
||||||
|
std::tie(this->topLeft, this->topRight, this->bottomLeft, this->bottomRight, this->topStart, this->topEnd, this->bottomStart, this->bottomEnd, this->all) ==
|
||||||
|
std::tie(rhs.topLeft, rhs.topRight, rhs.bottomLeft, rhs.bottomRight, rhs.topStart, rhs.topEnd, rhs.bottomStart, rhs.bottomEnd, rhs.all);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const CascadedRectangleCorners<T> &rhs) const {
|
||||||
|
return !(*this == rhs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using BorderWidths = RectangleEdges<Float>;
|
||||||
|
using BorderStyles = RectangleEdges<BorderStyle>;
|
||||||
|
using BorderColors = RectangleEdges<SharedColor>;
|
||||||
|
using BorderRadii = RectangleCorners<Float>;
|
||||||
|
|
||||||
|
using CascadedBorderWidths = CascadedRectangleEdges<Float>;
|
||||||
|
using CascadedBorderStyles = CascadedRectangleEdges<BorderStyle>;
|
||||||
|
using CascadedBorderColors = CascadedRectangleEdges<SharedColor>;
|
||||||
|
using CascadedBorderRadii = CascadedRectangleCorners<Float>;
|
||||||
|
|
||||||
|
struct BorderMetrics {
|
||||||
|
BorderColors borderColors {};
|
||||||
|
BorderWidths borderWidths {};
|
||||||
|
BorderRadii borderRadii {};
|
||||||
|
BorderStyles borderStyles {};
|
||||||
|
|
||||||
|
bool operator==(const BorderMetrics &rhs) const {
|
||||||
|
return
|
||||||
|
std::tie(this->borderColors, this->borderWidths, this->borderRadii, this->borderStyles) ==
|
||||||
|
std::tie(rhs.borderColors, rhs.borderWidths, rhs.borderRadii, rhs.borderStyles);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const BorderMetrics &rhs) const {
|
||||||
|
return !(*this == rhs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace react
|
} // namespace react
|
||||||
} // namespace facebook
|
} // namespace facebook
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
namespace facebook {
|
namespace facebook {
|
||||||
namespace react {
|
namespace react {
|
||||||
|
|
||||||
static std::array<YGValue, 2> convertRawProp(
|
static inline std::array<YGValue, 2> convertRawProp(
|
||||||
const RawProps &rawProps,
|
const RawProps &rawProps,
|
||||||
const std::string &widthName,
|
const std::string &widthName,
|
||||||
const std::string &heightName,
|
const std::string &heightName,
|
||||||
@@ -26,7 +26,7 @@ static std::array<YGValue, 2> convertRawProp(
|
|||||||
return dimentions;
|
return dimentions;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::array<YGValue, YGEdgeCount> convertRawProp(
|
static inline std::array<YGValue, YGEdgeCount> convertRawProp(
|
||||||
const RawProps &rawProps,
|
const RawProps &rawProps,
|
||||||
const std::string &prefix,
|
const std::string &prefix,
|
||||||
const std::string &suffix,
|
const std::string &suffix,
|
||||||
@@ -46,7 +46,7 @@ static std::array<YGValue, YGEdgeCount> convertRawProp(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::array<YGValue, YGEdgeCount> convertRawProp(
|
static inline std::array<YGValue, YGEdgeCount> convertRawProp(
|
||||||
const RawProps &rawProps,
|
const RawProps &rawProps,
|
||||||
const std::array<YGValue, YGEdgeCount> &sourceValue,
|
const std::array<YGValue, YGEdgeCount> &sourceValue,
|
||||||
const std::array<YGValue, YGEdgeCount> &defaultValue
|
const std::array<YGValue, YGEdgeCount> &defaultValue
|
||||||
@@ -61,7 +61,7 @@ static std::array<YGValue, YGEdgeCount> convertRawProp(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static YGStyle convertRawProp(const RawProps &rawProps, const YGStyle &sourceValue) {
|
static inline YGStyle convertRawProp(const RawProps &rawProps, const YGStyle &sourceValue) {
|
||||||
YGStyle yogaStyle;
|
YGStyle yogaStyle;
|
||||||
yogaStyle.direction = convertRawProp(rawProps, "direction", sourceValue.direction, yogaStyle.direction);
|
yogaStyle.direction = convertRawProp(rawProps, "direction", sourceValue.direction, yogaStyle.direction);
|
||||||
yogaStyle.flexDirection = convertRawProp(rawProps, "flexDirection", sourceValue.flexDirection, yogaStyle.flexDirection);
|
yogaStyle.flexDirection = convertRawProp(rawProps, "flexDirection", sourceValue.flexDirection, yogaStyle.flexDirection);
|
||||||
@@ -88,5 +88,53 @@ static YGStyle convertRawProp(const RawProps &rawProps, const YGStyle &sourceVal
|
|||||||
return yogaStyle;
|
return yogaStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static inline CascadedRectangleCorners<T> convertRawProp(
|
||||||
|
const RawProps &rawProps,
|
||||||
|
const std::string &prefix,
|
||||||
|
const std::string &suffix,
|
||||||
|
const CascadedRectangleCorners<T> &sourceValue
|
||||||
|
) {
|
||||||
|
CascadedRectangleCorners<T> result;
|
||||||
|
|
||||||
|
result.topLeft = convertRawProp(rawProps, prefix + "TopLeft" + suffix, sourceValue.topLeft);
|
||||||
|
result.topRight = convertRawProp(rawProps, prefix + "TopRight" + suffix, sourceValue.topRight);
|
||||||
|
result.bottomLeft = convertRawProp(rawProps, prefix + "BottomLeft" + suffix, sourceValue.bottomLeft);
|
||||||
|
result.bottomRight = convertRawProp(rawProps, prefix + "BottomRight" + suffix, sourceValue.bottomRight);
|
||||||
|
|
||||||
|
result.topStart = convertRawProp(rawProps, prefix + "TopStart" + suffix, sourceValue.topStart);
|
||||||
|
result.topEnd = convertRawProp(rawProps, prefix + "TopEnd" + suffix, sourceValue.topEnd);
|
||||||
|
result.bottomStart = convertRawProp(rawProps, prefix + "BottomStart" + suffix, sourceValue.bottomStart);
|
||||||
|
result.bottomEnd = convertRawProp(rawProps, prefix + "BottomEnd" + suffix, sourceValue.bottomEnd);
|
||||||
|
|
||||||
|
result.all = convertRawProp(rawProps, prefix + suffix, sourceValue.all);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static inline CascadedRectangleEdges<T> convertRawProp(
|
||||||
|
const RawProps &rawProps,
|
||||||
|
const std::string &prefix,
|
||||||
|
const std::string &suffix,
|
||||||
|
const CascadedRectangleEdges<T> &sourceValue
|
||||||
|
) {
|
||||||
|
CascadedRectangleEdges<T> result;
|
||||||
|
|
||||||
|
result.left = convertRawProp(rawProps, prefix + "Left" + suffix, sourceValue.left);
|
||||||
|
result.right = convertRawProp(rawProps, prefix + "Right" + suffix, sourceValue.right);
|
||||||
|
result.top = convertRawProp(rawProps, prefix + "Top" + suffix, sourceValue.top);
|
||||||
|
result.bottom = convertRawProp(rawProps, prefix + "Bottom" + suffix, sourceValue.bottom);
|
||||||
|
|
||||||
|
result.start = convertRawProp(rawProps, prefix + "Start" + suffix, sourceValue.start);
|
||||||
|
result.end = convertRawProp(rawProps, prefix + "End" + suffix, sourceValue.end);
|
||||||
|
result.horizontal = convertRawProp(rawProps, prefix + "Horizontal" + suffix, sourceValue.horizontal);
|
||||||
|
result.vertical = convertRawProp(rawProps, prefix + "Vertical" + suffix, sourceValue.vertical);
|
||||||
|
|
||||||
|
result.all = convertRawProp(rawProps, prefix + suffix, sourceValue.all);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace react
|
} // namespace react
|
||||||
} // namespace facebook
|
} // namespace facebook
|
||||||
|
|||||||
Reference in New Issue
Block a user