diff --git a/ReactCommon/fabric/components/text/paragraph/ParagraphComponentDescriptor.h b/ReactCommon/fabric/components/text/paragraph/ParagraphComponentDescriptor.h index d360c93d33..0ec89c5683 100644 --- a/ReactCommon/fabric/components/text/paragraph/ParagraphComponentDescriptor.h +++ b/ReactCommon/fabric/components/text/paragraph/ParagraphComponentDescriptor.h @@ -9,6 +9,7 @@ #include "ParagraphShadowNode.h" +#include #include #include #include @@ -30,6 +31,18 @@ class ParagraphComponentDescriptor final textLayoutManager_ = std::make_shared(contextContainer_); } + virtual SharedProps interpolateProps( + float animationProgress, + const SharedProps &props, + const SharedProps &newProps) const override { + SharedProps interpolatedPropsShared = cloneProps(newProps, {}); + + interpolateViewProps( + animationProgress, props, newProps, interpolatedPropsShared); + + return interpolatedPropsShared; + }; + protected: void adopt(UnsharedShadowNode shadowNode) const override { ConcreteComponentDescriptor::adopt(shadowNode); diff --git a/ReactCommon/fabric/components/view/ViewComponentDescriptor.h b/ReactCommon/fabric/components/view/ViewComponentDescriptor.h index 9eaacaaa77..006081daf3 100644 --- a/ReactCommon/fabric/components/view/ViewComponentDescriptor.h +++ b/ReactCommon/fabric/components/view/ViewComponentDescriptor.h @@ -10,6 +10,7 @@ #include #include #include "ViewProps.h" +#include "ViewPropsInterpolation.h" namespace facebook { namespace react { @@ -24,34 +25,10 @@ class ViewComponentDescriptor float animationProgress, const SharedProps &props, const SharedProps &newProps) const override { - ViewProps const *oldViewProps = - dynamic_cast(props.get()); - ViewProps const *newViewProps = - dynamic_cast(newProps.get()); - SharedProps interpolatedPropsShared = cloneProps(newProps, {}); - ViewProps *interpolatedProps = const_cast( - dynamic_cast(interpolatedPropsShared.get())); - interpolatedProps->opacity = oldViewProps->opacity + - (newViewProps->opacity - oldViewProps->opacity) * animationProgress; - - interpolatedProps->transform = Transform::Interpolate( - animationProgress, oldViewProps->transform, newViewProps->transform); - - // Android uses RawProps, not props, to update props on the platform... - // Since interpolated props don't interpolate at all using RawProps, we need - // to "re-hydrate" raw props after interpolating. This is what actually gets - // sent to the mounting layer. This is a temporary hack, only for platforms - // that use RawProps/folly::dynamic instead of concrete props on the - // mounting layer. Once we can remove this, we should change `rawProps` to - // be const again. -#ifdef ANDROID - interpolatedProps->rawProps["opacity"] = interpolatedProps->opacity; - - interpolatedProps->rawProps["transform"] = - (folly::dynamic)interpolatedProps->transform; -#endif + interpolateViewProps( + animationProgress, props, newProps, interpolatedPropsShared); return interpolatedPropsShared; }; diff --git a/ReactCommon/fabric/components/view/ViewPropsInterpolation.h b/ReactCommon/fabric/components/view/ViewPropsInterpolation.h new file mode 100644 index 0000000000..0470d696d5 --- /dev/null +++ b/ReactCommon/fabric/components/view/ViewPropsInterpolation.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) Facebook, Inc. and its 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 "ViewProps.h" + +namespace facebook { +namespace react { + +/** + * Given animation progress, old props, new props, and an "interpolated" shared + * props struct, this will mutate the "interpolated" struct in-place to give it + * values interpolated between the old and new props. + */ +static inline void interpolateViewProps( + Float animationProgress, + const SharedProps &oldPropsShared, + const SharedProps &newPropsShared, + SharedProps &interpolatedPropsShared) { + ViewProps const *oldViewProps = + dynamic_cast(oldPropsShared.get()); + ViewProps const *newViewProps = + dynamic_cast(newPropsShared.get()); + ViewProps *interpolatedProps = const_cast( + dynamic_cast(interpolatedPropsShared.get())); + + assert( + oldViewProps != nullptr && newViewProps != nullptr && + interpolatedProps != nullptr); + + interpolatedProps->opacity = oldViewProps->opacity + + (newViewProps->opacity - oldViewProps->opacity) * animationProgress; + + interpolatedProps->transform = Transform::Interpolate( + animationProgress, oldViewProps->transform, newViewProps->transform); + + // Android uses RawProps, not props, to update props on the platform... + // Since interpolated props don't interpolate at all using RawProps, we need + // to "re-hydrate" raw props after interpolating. This is what actually gets + // sent to the mounting layer. This is a temporary hack, only for platforms + // that use RawProps/folly::dynamic instead of concrete props on the + // mounting layer. Once we can remove this, we should change `rawProps` to + // be const again. +#ifdef ANDROID + interpolatedProps->rawProps["opacity"] = interpolatedProps->opacity; + + interpolatedProps->rawProps["transform"] = + (folly::dynamic)interpolatedProps->transform; +#endif +} + +} // namespace react +} // namespace facebook