mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Back out "Back out "[RN][CSS] Wire up native box shadow parsing"" (#49376)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/49376 We can reland this now that D69520832 update feature flags infra. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D69548370 fbshipit-source-id: ec1187dffdca4d9d4064235e9ef6336e66521d26
This commit is contained in:
committed by
Facebook GitHub Bot
parent
1d8021d821
commit
1663dc1978
@@ -10,6 +10,7 @@
|
||||
|
||||
import type {PartialViewConfigWithoutName} from './PlatformBaseViewConfig';
|
||||
|
||||
import * as ReactNativeFeatureFlags from '../../src/private/featureflags/ReactNativeFeatureFlags';
|
||||
import ReactNativeStyleAttributes from '../Components/View/ReactNativeStyleAttributes';
|
||||
import {DynamicallyInjectedByGestureHandler} from './ViewConfigIgnore';
|
||||
|
||||
@@ -170,7 +171,9 @@ const validAttributesForNonEventProps = {
|
||||
process: require('../StyleSheet/processBackgroundImage').default,
|
||||
},
|
||||
boxShadow: {
|
||||
process: require('../StyleSheet/processBoxShadow').default,
|
||||
process: ReactNativeFeatureFlags.enableNativeCSSParsing()
|
||||
? undefined
|
||||
: require('../StyleSheet/processBoxShadow').default,
|
||||
},
|
||||
filter: {
|
||||
process: require('../StyleSheet/processFilter').default,
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
import type {PartialViewConfigWithoutName} from './PlatformBaseViewConfig';
|
||||
|
||||
import * as ReactNativeFeatureFlags from '../../src/private/featureflags/ReactNativeFeatureFlags';
|
||||
import ReactNativeStyleAttributes from '../Components/View/ReactNativeStyleAttributes';
|
||||
import {
|
||||
ConditionallyIgnoredEventHandlers,
|
||||
@@ -229,7 +230,9 @@ const validAttributesForNonEventProps = {
|
||||
process: require('../StyleSheet/processFilter').default,
|
||||
},
|
||||
boxShadow: {
|
||||
process: require('../StyleSheet/processBoxShadow').default,
|
||||
process: ReactNativeFeatureFlags.enableNativeCSSParsing()
|
||||
? undefined
|
||||
: require('../StyleSheet/processBoxShadow').default,
|
||||
},
|
||||
mixBlendMode: true,
|
||||
isolation: true,
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include <react/featureflags/ReactNativeFeatureFlags.h>
|
||||
#include <react/renderer/components/view/BoxShadowPropsConversions.h>
|
||||
#include <react/renderer/components/view/conversions.h>
|
||||
#include <react/renderer/components/view/primitives.h>
|
||||
#include <react/renderer/components/view/propsConversions.h>
|
||||
|
||||
+310
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
* 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 <glog/logging.h>
|
||||
#include <react/debug/react_native_expect.h>
|
||||
#include <react/featureflags/ReactNativeFeatureFlags.h>
|
||||
#include <react/renderer/components/view/primitives.h>
|
||||
#include <react/renderer/core/PropsParserContext.h>
|
||||
#include <react/renderer/core/RawProps.h>
|
||||
#include <react/renderer/core/graphicsConversions.h>
|
||||
#include <react/renderer/css/CSSShadow.h>
|
||||
#include <react/renderer/css/CSSValueParser.h>
|
||||
#include <react/renderer/graphics/BoxShadow.h>
|
||||
#include <react/renderer/graphics/PlatformColorParser.h>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
inline void parseProcessedBoxShadow(
|
||||
const PropsParserContext& context,
|
||||
const RawValue& value,
|
||||
std::vector<BoxShadow>& result) {
|
||||
react_native_expect(value.hasType<std::vector<RawValue>>());
|
||||
if (!value.hasType<std::vector<RawValue>>()) {
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<BoxShadow> boxShadows{};
|
||||
auto rawBoxShadows = static_cast<std::vector<RawValue>>(value);
|
||||
for (const auto& rawBoxShadow : rawBoxShadows) {
|
||||
bool isMap =
|
||||
rawBoxShadow.hasType<std::unordered_map<std::string, RawValue>>();
|
||||
react_native_expect(isMap);
|
||||
if (!isMap) {
|
||||
// If any box shadow is malformed then we should not apply any of them
|
||||
// which is the web behavior.
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
|
||||
auto rawBoxShadowMap =
|
||||
static_cast<std::unordered_map<std::string, RawValue>>(rawBoxShadow);
|
||||
BoxShadow boxShadow{};
|
||||
auto offsetX = rawBoxShadowMap.find("offsetX");
|
||||
react_native_expect(offsetX != rawBoxShadowMap.end());
|
||||
if (offsetX == rawBoxShadowMap.end()) {
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
react_native_expect(offsetX->second.hasType<Float>());
|
||||
if (!offsetX->second.hasType<Float>()) {
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
boxShadow.offsetX = (Float)offsetX->second;
|
||||
|
||||
auto offsetY = rawBoxShadowMap.find("offsetY");
|
||||
react_native_expect(offsetY != rawBoxShadowMap.end());
|
||||
if (offsetY == rawBoxShadowMap.end()) {
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
react_native_expect(offsetY->second.hasType<Float>());
|
||||
if (!offsetY->second.hasType<Float>()) {
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
boxShadow.offsetY = (Float)offsetY->second;
|
||||
|
||||
auto blurRadius = rawBoxShadowMap.find("blurRadius");
|
||||
if (blurRadius != rawBoxShadowMap.end()) {
|
||||
react_native_expect(blurRadius->second.hasType<Float>());
|
||||
if (!blurRadius->second.hasType<Float>()) {
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
boxShadow.blurRadius = (Float)blurRadius->second;
|
||||
}
|
||||
|
||||
auto spreadDistance = rawBoxShadowMap.find("spreadDistance");
|
||||
if (spreadDistance != rawBoxShadowMap.end()) {
|
||||
react_native_expect(spreadDistance->second.hasType<Float>());
|
||||
if (!spreadDistance->second.hasType<Float>()) {
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
boxShadow.spreadDistance = (Float)spreadDistance->second;
|
||||
}
|
||||
|
||||
auto inset = rawBoxShadowMap.find("inset");
|
||||
if (inset != rawBoxShadowMap.end()) {
|
||||
react_native_expect(inset->second.hasType<bool>());
|
||||
if (!inset->second.hasType<bool>()) {
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
boxShadow.inset = (bool)inset->second;
|
||||
}
|
||||
|
||||
auto color = rawBoxShadowMap.find("color");
|
||||
if (color != rawBoxShadowMap.end()) {
|
||||
fromRawValue(
|
||||
context.contextContainer,
|
||||
context.surfaceId,
|
||||
color->second,
|
||||
boxShadow.color);
|
||||
}
|
||||
|
||||
boxShadows.push_back(boxShadow);
|
||||
}
|
||||
|
||||
result = boxShadows;
|
||||
}
|
||||
|
||||
inline SharedColor fromCSSColor(const CSSColor& cssColor) {
|
||||
return hostPlatformColorFromRGBA(
|
||||
cssColor.r, cssColor.g, cssColor.b, cssColor.a);
|
||||
}
|
||||
|
||||
inline std::optional<BoxShadow> fromCSSShadow(const CSSShadow& cssShadow) {
|
||||
// TODO: handle non-px values
|
||||
if (cssShadow.offsetX.unit != CSSLengthUnit::Px ||
|
||||
cssShadow.offsetY.unit != CSSLengthUnit::Px ||
|
||||
cssShadow.blurRadius.unit != CSSLengthUnit::Px ||
|
||||
cssShadow.spreadDistance.unit != CSSLengthUnit::Px) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return BoxShadow{
|
||||
.offsetX = cssShadow.offsetX.value,
|
||||
.offsetY = cssShadow.offsetY.value,
|
||||
.blurRadius = cssShadow.blurRadius.value,
|
||||
.spreadDistance = cssShadow.spreadDistance.value,
|
||||
.color = fromCSSColor(cssShadow.color),
|
||||
};
|
||||
}
|
||||
|
||||
inline void parseUnprocessedBoxShadowString(
|
||||
std::string&& value,
|
||||
std::vector<BoxShadow>& result) {
|
||||
auto boxShadowList = parseCSSProperty<CSSShadowList>((std::string)value);
|
||||
if (!std::holds_alternative<CSSShadowList>(boxShadowList)) {
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& cssShadow : std::get<CSSShadowList>(boxShadowList)) {
|
||||
if (auto boxShadow = fromCSSShadow(cssShadow)) {
|
||||
result.push_back(*boxShadow);
|
||||
} else {
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline std::optional<Float> coerceLength(const RawValue& value) {
|
||||
if (value.hasType<Float>()) {
|
||||
return (Float)value;
|
||||
}
|
||||
|
||||
if (value.hasType<std::string>()) {
|
||||
auto len = parseCSSProperty<CSSLength>((std::string)value);
|
||||
if (!std::holds_alternative<CSSLength>(len)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto cssLen = std::get<CSSLength>(len);
|
||||
if (cssLen.unit != CSSLengthUnit::Px) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return cssLen.value;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
inline std::optional<BoxShadow> parseBoxShadowRawValue(
|
||||
const PropsParserContext& context,
|
||||
const RawValue& value) {
|
||||
if (!value.hasType<std::unordered_map<std::string, RawValue>>()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto boxShadow = std::unordered_map<std::string, RawValue>(value);
|
||||
auto rawOffsetX = boxShadow.find("offsetX");
|
||||
if (rawOffsetX == boxShadow.end()) {
|
||||
return {};
|
||||
}
|
||||
auto offsetX = coerceLength(rawOffsetX->second);
|
||||
if (!offsetX.has_value()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto rawOffsetY = boxShadow.find("offsetY");
|
||||
if (rawOffsetY == boxShadow.end()) {
|
||||
return {};
|
||||
}
|
||||
auto offsetY = coerceLength(rawOffsetY->second);
|
||||
if (!offsetY.has_value()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
Float blurRadius = 0;
|
||||
auto rawBlurRadius = boxShadow.find("blurRadius");
|
||||
if (rawBlurRadius != boxShadow.end()) {
|
||||
if (auto blurRadiusValue = coerceLength(rawBlurRadius->second)) {
|
||||
blurRadius = *blurRadiusValue;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
Float spreadDistance = 0;
|
||||
auto rawSpreadDistance = boxShadow.find("spreadDistance");
|
||||
if (rawSpreadDistance != boxShadow.end()) {
|
||||
if (auto spreadDistanceValue = coerceLength(rawSpreadDistance->second)) {
|
||||
spreadDistance = *spreadDistanceValue;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
bool inset = false;
|
||||
auto rawInset = boxShadow.find("inset");
|
||||
if (rawInset != boxShadow.end()) {
|
||||
if (rawInset->second.hasType<bool>()) {
|
||||
inset = (bool)rawInset->second;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
SharedColor color;
|
||||
auto rawColor = boxShadow.find("color");
|
||||
if (rawColor != boxShadow.end()) {
|
||||
const auto& rawColorValue = rawColor->second;
|
||||
if (rawColorValue.hasType<std::string>()) {
|
||||
auto cssColor = parseCSSProperty<CSSColor>((std::string)rawColorValue);
|
||||
if (!std::holds_alternative<CSSColor>(cssColor)) {
|
||||
return {};
|
||||
}
|
||||
color = fromCSSColor(std::get<CSSColor>(cssColor));
|
||||
} else {
|
||||
fromRawValue(
|
||||
context.contextContainer, context.surfaceId, rawColor->second, color);
|
||||
if (!color) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BoxShadow{
|
||||
.offsetX = *offsetX,
|
||||
.offsetY = *offsetY,
|
||||
.blurRadius = blurRadius,
|
||||
.spreadDistance = spreadDistance,
|
||||
.color = color,
|
||||
.inset = inset};
|
||||
}
|
||||
|
||||
inline void parseUnprocessedBoxShadowList(
|
||||
const PropsParserContext& context,
|
||||
std::vector<RawValue>&& value,
|
||||
std::vector<BoxShadow>& result) {
|
||||
for (const auto& rawValue : value) {
|
||||
if (auto boxShadow = parseBoxShadowRawValue(context, rawValue)) {
|
||||
result.push_back(*boxShadow);
|
||||
} else {
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void parseUnprocessedBoxShadow(
|
||||
const PropsParserContext& context,
|
||||
const RawValue& value,
|
||||
std::vector<BoxShadow>& result) {
|
||||
if (value.hasType<std::string>()) {
|
||||
parseUnprocessedBoxShadowString((std::string)value, result);
|
||||
} else if (value.hasType<std::vector<RawValue>>()) {
|
||||
parseUnprocessedBoxShadowList(
|
||||
context, (std::vector<RawValue>)value, result);
|
||||
} else {
|
||||
result = {};
|
||||
}
|
||||
}
|
||||
|
||||
inline void fromRawValue(
|
||||
const PropsParserContext& context,
|
||||
const RawValue& value,
|
||||
std::vector<BoxShadow>& result) {
|
||||
if (ReactNativeFeatureFlags::enableNativeCSSParsing()) {
|
||||
parseUnprocessedBoxShadow(context, value, result);
|
||||
} else {
|
||||
parseProcessedBoxShadow(context, value, result);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
@@ -16,7 +16,6 @@
|
||||
#include <react/renderer/core/graphicsConversions.h>
|
||||
#include <react/renderer/graphics/BackgroundImage.h>
|
||||
#include <react/renderer/graphics/BlendMode.h>
|
||||
#include <react/renderer/graphics/BoxShadow.h>
|
||||
#include <react/renderer/graphics/Filter.h>
|
||||
#include <react/renderer/graphics/Isolation.h>
|
||||
#include <react/renderer/graphics/LinearGradient.h>
|
||||
@@ -1053,102 +1052,6 @@ inline void fromRawValue(
|
||||
}
|
||||
}
|
||||
|
||||
inline void fromRawValue(
|
||||
const PropsParserContext& context,
|
||||
const RawValue& value,
|
||||
std::vector<BoxShadow>& result) {
|
||||
react_native_expect(value.hasType<std::vector<RawValue>>());
|
||||
if (!value.hasType<std::vector<RawValue>>()) {
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<BoxShadow> boxShadows{};
|
||||
auto rawBoxShadows = static_cast<std::vector<RawValue>>(value);
|
||||
for (const auto& rawBoxShadow : rawBoxShadows) {
|
||||
bool isMap =
|
||||
rawBoxShadow.hasType<std::unordered_map<std::string, RawValue>>();
|
||||
react_native_expect(isMap);
|
||||
if (!isMap) {
|
||||
// If any box shadow is malformed then we should not apply any of them
|
||||
// which is the web behavior.
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
|
||||
auto rawBoxShadowMap =
|
||||
static_cast<std::unordered_map<std::string, RawValue>>(rawBoxShadow);
|
||||
BoxShadow boxShadow{};
|
||||
auto offsetX = rawBoxShadowMap.find("offsetX");
|
||||
react_native_expect(offsetX != rawBoxShadowMap.end());
|
||||
if (offsetX == rawBoxShadowMap.end()) {
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
react_native_expect(offsetX->second.hasType<Float>());
|
||||
if (!offsetX->second.hasType<Float>()) {
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
boxShadow.offsetX = (Float)offsetX->second;
|
||||
|
||||
auto offsetY = rawBoxShadowMap.find("offsetY");
|
||||
react_native_expect(offsetY != rawBoxShadowMap.end());
|
||||
if (offsetY == rawBoxShadowMap.end()) {
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
react_native_expect(offsetY->second.hasType<Float>());
|
||||
if (!offsetY->second.hasType<Float>()) {
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
boxShadow.offsetY = (Float)offsetY->second;
|
||||
|
||||
auto blurRadius = rawBoxShadowMap.find("blurRadius");
|
||||
if (blurRadius != rawBoxShadowMap.end()) {
|
||||
react_native_expect(blurRadius->second.hasType<Float>());
|
||||
if (!blurRadius->second.hasType<Float>()) {
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
boxShadow.blurRadius = (Float)blurRadius->second;
|
||||
}
|
||||
|
||||
auto spreadDistance = rawBoxShadowMap.find("spreadDistance");
|
||||
if (spreadDistance != rawBoxShadowMap.end()) {
|
||||
react_native_expect(spreadDistance->second.hasType<Float>());
|
||||
if (!spreadDistance->second.hasType<Float>()) {
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
boxShadow.spreadDistance = (Float)spreadDistance->second;
|
||||
}
|
||||
|
||||
auto inset = rawBoxShadowMap.find("inset");
|
||||
if (inset != rawBoxShadowMap.end()) {
|
||||
react_native_expect(inset->second.hasType<bool>());
|
||||
if (!inset->second.hasType<bool>()) {
|
||||
result = {};
|
||||
return;
|
||||
}
|
||||
boxShadow.inset = (bool)inset->second;
|
||||
}
|
||||
|
||||
auto color = rawBoxShadowMap.find("color");
|
||||
if (color != rawBoxShadowMap.end()) {
|
||||
fromRawValue(
|
||||
context.contextContainer,
|
||||
context.surfaceId,
|
||||
color->second,
|
||||
boxShadow.color);
|
||||
}
|
||||
|
||||
boxShadows.push_back(boxShadow);
|
||||
}
|
||||
|
||||
result = boxShadows;
|
||||
}
|
||||
inline void fromRawValue(
|
||||
const PropsParserContext& context,
|
||||
const RawValue& value,
|
||||
|
||||
Reference in New Issue
Block a user