From f340e6e575628f92b94e0b8e81f786148ca43e35 Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Wed, 8 May 2024 13:39:09 -0700 Subject: [PATCH] Parse raw filter props (#44455) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/44455 Title says it all. Right now this ignores drop-shadow as that will be implemented later. Some of this code will need to be adjusted as it is the one filter that takes multiple amounts. But I feel that can be amended later when we get there - after all the `amount` parsing code is just casting to a float at the moment, so we are not locking ourselves into anything. Changelog: [Internal] Reviewed By: NickGerleman Differential Revision: D54640629 fbshipit-source-id: c8e1206ab46accab3c99614241b8bd9aa252e12c --- .../components/view/BaseViewProps.cpp | 8 +++ .../renderer/components/view/BaseViewProps.h | 4 ++ .../renderer/components/view/conversions.h | 43 +++++++++++++ .../react/renderer/graphics/Filter.h | 61 +++++++++++++++++++ 4 files changed, 116 insertions(+) create mode 100644 packages/react-native/ReactCommon/react/renderer/graphics/Filter.h diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp index 6081a4cc4db..ffd92fbb15b 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp @@ -150,6 +150,14 @@ BaseViewProps::BaseViewProps( "cursor", sourceProps.cursor, {})), + filter( + CoreFeatures::enablePropIteratorSetter ? sourceProps.filter + : convertRawProp( + context, + rawProps, + "experimental_filter", + sourceProps.filter, + {})), transform( CoreFeatures::enablePropIteratorSetter ? sourceProps.transform : convertRawProp( diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h index ee639abf78a..21c569e5ea4 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -54,6 +55,9 @@ class BaseViewProps : public YogaStylableProps, public AccessibilityProps { Cursor cursor{}; + // Filter + std::vector filter{}; + // Transform Transform transform{}; TransformOrigin transformOrigin{ 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 866a0c12628..f10bcbb9cbb 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -761,6 +762,48 @@ inline void fromRawValue( react_native_expect(false); } +inline void fromRawValue( + const PropsParserContext& /*context*/, + const RawValue& value, + std::vector& result) { + react_native_expect(value.hasType>()); + if (!value.hasType>()) { + result = {}; + return; + } + + std::vector filter{}; + auto rawFilter = static_cast>(value); + for (const auto& rawFilterPrimitive : rawFilter) { + bool isMap = + rawFilterPrimitive.hasType>(); + react_native_expect(isMap); + if (!isMap) { + // If a filter is malformed then we should not apply any of them which + // is the web behavior. + result = {}; + return; + } + + auto rawFilterPrimitiveMap = + static_cast>( + rawFilterPrimitive); + FilterPrimitive filterPrimitive{}; + try { + filterPrimitive.type = + filterTypeFromString(rawFilterPrimitiveMap.begin()->first); + filterPrimitive.amount = (float)rawFilterPrimitiveMap.begin()->second; + filter.push_back(filterPrimitive); + } catch (const std::exception& e) { + LOG(ERROR) << "Could not parse FilterPrimitive: " << e.what(); + filter = {}; + return; + } + } + + result = filter; +} + template inline std::string toString(const std::array vec) { std::string s; diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/Filter.h b/packages/react-native/ReactCommon/react/renderer/graphics/Filter.h new file mode 100644 index 00000000000..406fffd4efd --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/graphics/Filter.h @@ -0,0 +1,61 @@ +/* + * 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 + +#include +#include +#include + +namespace facebook::react { + +enum class FilterType { + Blur, + Brightness, + Contrast, + Grayscale, + HueRotate, + Invert, + Opacity, + Saturate, + Sepia +}; + +struct FilterPrimitive { + bool operator==(const FilterPrimitive& other) const = default; + + FilterType type; + Float amount; +}; + +inline FilterType filterTypeFromString(std::string_view filterName) { + if (filterName == "blur") { + return FilterType::Blur; + } else if (filterName == "brightness") { + return FilterType::Brightness; + } else if (filterName == "contrast") { + return FilterType::Contrast; + } else if (filterName == "grayscale") { + return FilterType::Grayscale; + } else if (filterName == "hueRotate") { + return FilterType::HueRotate; + } else if (filterName == "invert") { + return FilterType::Invert; + } else if (filterName == "opacity") { + return FilterType::Opacity; + } else if (filterName == "saturate") { + return FilterType::Saturate; + } else if (filterName == "sepia") { + return FilterType::Sepia; + } else { + throw std::invalid_argument(std::string(filterName)); + } +} + +} // namespace facebook::react