From baae3602723a1d66cb1542d7aee4dfa2ec473de3 Mon Sep 17 00:00:00 2001 From: Jorge Cabiedes Acosta Date: Fri, 23 Aug 2024 11:43:21 -0700 Subject: [PATCH] Fix dropShadow not creating stacking context (#46143) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/46143 Before `drop-shadow` was not creating a stacking context causing its children to get flattened and not receive the shadow effect. This was due to incorrect parsing on C++. We didn't notice since we don't support `drop-shadow` on iOS and Android gets the parsed prop directly Changelog: [Internal] Reviewed By: NickGerleman, joevilches Differential Revision: D61617699 fbshipit-source-id: a8bfbb0043fcd2b2867923eb937a6be8e9004f13 --- .../View/RCTViewComponentView.mm | 10 +-- .../renderer/components/view/conversions.h | 63 +++++++++++++++++-- .../react/renderer/graphics/Filter.h | 15 ++++- 3 files changed, 78 insertions(+), 10 deletions(-) diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 646a91082c7..766c3e41878 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -844,10 +844,12 @@ static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle) if (!_props->filter.empty()) { float multiplicativeBrightness = 1; for (const auto &primitive : _props->filter) { - if (primitive.type == FilterType::Brightness) { - multiplicativeBrightness *= primitive.amount; - } else if (primitive.type == FilterType::Opacity) { - self.layer.opacity *= primitive.amount; + if (std::holds_alternative(primitive.parameters)) { + if (primitive.type == FilterType::Brightness) { + multiplicativeBrightness *= std::get(primitive.parameters); + } else if (primitive.type == FilterType::Opacity) { + self.layer.opacity *= std::get(primitive.parameters); + } } } diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h index 6681c69dfeb..e91ed7246d3 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h @@ -1032,7 +1032,7 @@ inline void fromRawValue( result = boxShadows; } inline void fromRawValue( - const PropsParserContext& /*context*/, + const PropsParserContext& context, const RawValue& value, std::vector& result) { react_native_expect(value.hasType>()); @@ -1054,14 +1054,69 @@ inline void fromRawValue( return; } - auto rawFilterPrimitiveMap = + auto rawFilterFunction = static_cast>( rawFilterPrimitive); FilterFunction filterFunction{}; try { filterFunction.type = - filterTypeFromString(rawFilterPrimitiveMap.begin()->first); - filterFunction.amount = (float)rawFilterPrimitiveMap.begin()->second; + filterTypeFromString(rawFilterFunction.begin()->first); + if (filterFunction.type == FilterType::DropShadow) { + auto rawDropShadow = + static_cast>( + rawFilterFunction.begin()->second); + DropShadowParams dropShadowParams{}; + + auto offsetX = rawDropShadow.find("offsetX"); + react_native_expect(offsetX != rawDropShadow.end()); + if (offsetX == rawDropShadow.end()) { + result = {}; + return; + } + + react_native_expect(offsetX->second.hasType()); + if (!offsetX->second.hasType()) { + result = {}; + return; + } + dropShadowParams.offsetX = (Float)offsetX->second; + + auto offsetY = rawDropShadow.find("offsetY"); + react_native_expect(offsetY != rawDropShadow.end()); + if (offsetY == rawDropShadow.end()) { + result = {}; + return; + } + react_native_expect(offsetY->second.hasType()); + if (!offsetY->second.hasType()) { + result = {}; + return; + } + dropShadowParams.offsetY = (Float)offsetY->second; + + auto standardDeviation = rawDropShadow.find("standardDeviation"); + if (standardDeviation != rawDropShadow.end()) { + react_native_expect(standardDeviation->second.hasType()); + if (!standardDeviation->second.hasType()) { + result = {}; + return; + } + dropShadowParams.standardDeviation = (Float)standardDeviation->second; + } + + auto color = rawDropShadow.find("color"); + if (color != rawDropShadow.end()) { + fromRawValue( + context.contextContainer, + context.surfaceId, + color->second, + dropShadowParams.color); + } + + filterFunction.parameters = dropShadowParams; + } else { + filterFunction.parameters = (float)rawFilterFunction.begin()->second; + } filter.push_back(std::move(filterFunction)); } catch (const std::exception& e) { LOG(ERROR) << "Could not parse FilterFunction: " << e.what(); diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/Filter.h b/packages/react-native/ReactCommon/react/renderer/graphics/Filter.h index 967afc843ad..fdfbda6d27d 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/Filter.h +++ b/packages/react-native/ReactCommon/react/renderer/graphics/Filter.h @@ -7,10 +7,12 @@ #pragma once +#include #include #include #include +#include #include namespace facebook::react { @@ -28,11 +30,20 @@ enum class FilterType { DropShadow }; +struct DropShadowParams { + bool operator==(const DropShadowParams& other) const = default; + + Float offsetX{}; + Float offsetY{}; + Float standardDeviation{}; + SharedColor color{}; +}; + struct FilterFunction { bool operator==(const FilterFunction& other) const = default; - FilterType type; - Float amount; + FilterType type{}; + std::variant parameters{}; }; inline FilterType filterTypeFromString(std::string_view filterName) {