From 7f88fb6ffa99fc92239b20e6d2060eb3000819fd Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Sat, 18 May 2024 20:51:38 +0400 Subject: [PATCH] Refactoring --- .../Sources/SoftwareLottieRenderer.mm | 14 ++- .../PublicHeaders/LottieCpp/RenderTreeNode.h | 14 ++- .../CompLayers/ShapeCompositionLayer.cpp | 114 +++++++----------- 3 files changed, 63 insertions(+), 79 deletions(-) diff --git a/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/SoftwareLottieRenderer.mm b/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/SoftwareLottieRenderer.mm index 738a4c02b5..9053ea3fa2 100644 --- a/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/SoftwareLottieRenderer.mm +++ b/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/SoftwareLottieRenderer.mm @@ -18,7 +18,7 @@ struct TransformedPath { } }; -static lottie::CGRect collectPathBoundingBoxes(std::shared_ptr item, size_t subItemLimit, lottie::CATransform3D const &parentTransform, bool skipApplyTransform) { +static lottie::CGRect collectPathBoundingBoxes(std::shared_ptr item, size_t subItemLimit, lottie::CATransform3D const &parentTransform, bool skipApplyTransform, lottie::BezierPathsBoundingBoxContext &bezierPathsBoundingBoxContext) { //TODO:remove skipApplyTransform lottie::CATransform3D effectiveTransform = parentTransform; if (!skipApplyTransform && item->isGroup) { @@ -29,13 +29,17 @@ static lottie::CGRect collectPathBoundingBoxes(std::shared_ptrpath) { - boundingBox = item->pathBoundingBox.applyingTransform(effectiveTransform); + if (item->path->needsBoundsRecalculation) { + item->path->bounds = lottie::bezierPathsBoundingBoxParallel(bezierPathsBoundingBoxContext, item->path->path); + item->path->needsBoundsRecalculation = false; + } + boundingBox = item->path->bounds.applyingTransform(effectiveTransform); } for (size_t i = 0; i < maxSubitem; i++) { auto &subItem = item->subItems[i]; - lottie::CGRect subItemBoundingBox = collectPathBoundingBoxes(subItem, INT32_MAX, effectiveTransform, false); + lottie::CGRect subItemBoundingBox = collectPathBoundingBoxes(subItem, INT32_MAX, effectiveTransform, false, bezierPathsBoundingBoxContext); if (boundingBox.empty()) { boundingBox = subItemBoundingBox; @@ -59,7 +63,7 @@ static std::vector collectPaths(std::shared_ptrsubItems.size(), subItemLimit); if (item->path) { - mappedPaths.emplace_back(item->path.value(), effectiveTransform); + mappedPaths.emplace_back(item->path->path, effectiveTransform); } assert(!item->trimParams); @@ -96,7 +100,7 @@ static void processRenderContentItem(std::shared_ptr int drawContentDescendants = 0; for (const auto &shadingVariant : contentItem->shadings) { - lottie::CGRect shapeBounds = collectPathBoundingBoxes(contentItem, shadingVariant->subItemLimit, lottie::CATransform3D::identity(), true); + lottie::CGRect shapeBounds = collectPathBoundingBoxes(contentItem, shadingVariant->subItemLimit, lottie::CATransform3D::identity(), true, bezierPathsBoundingBoxContext); if (shadingVariant->stroke) { shapeBounds = shapeBounds.insetBy(-shadingVariant->stroke->lineWidth / 2.0, -shadingVariant->stroke->lineWidth / 2.0); diff --git a/submodules/TelegramUI/Components/LottieCpp/PublicHeaders/LottieCpp/RenderTreeNode.h b/submodules/TelegramUI/Components/LottieCpp/PublicHeaders/LottieCpp/RenderTreeNode.h index a19f2a9d10..e504de3175 100644 --- a/submodules/TelegramUI/Components/LottieCpp/PublicHeaders/LottieCpp/RenderTreeNode.h +++ b/submodules/TelegramUI/Components/LottieCpp/PublicHeaders/LottieCpp/RenderTreeNode.h @@ -309,6 +309,17 @@ public: class RenderTreeNodeContentShadingVariant; +struct RenderTreeNodeContentPath { +public: + explicit RenderTreeNodeContentPath(BezierPath path_) : + path(path_) { + } + + BezierPath path; + CGRect bounds = CGRect(0.0, 0.0, 0.0, 0.0); + bool needsBoundsRecalculation = true; +}; + class RenderTreeNodeContentItem { public: enum class ShadingType { @@ -423,8 +434,7 @@ public: CATransform3D transform = CATransform3D::identity(); float alpha = 0.0; std::optional trimParams; - std::optional path; - CGRect pathBoundingBox = CGRect(0.0, 0.0, 0.0, 0.0); + std::shared_ptr path; std::vector> shadings; std::vector> subItems; diff --git a/submodules/TelegramUI/Components/LottieCpp/Sources/Lottie/Private/MainThread/LayerContainers/CompLayers/ShapeCompositionLayer.cpp b/submodules/TelegramUI/Components/LottieCpp/Sources/Lottie/Private/MainThread/LayerContainers/CompLayers/ShapeCompositionLayer.cpp index 1c63b5b6c5..f0973a1f09 100644 --- a/submodules/TelegramUI/Components/LottieCpp/Sources/Lottie/Private/MainThread/LayerContainers/CompLayers/ShapeCompositionLayer.cpp +++ b/submodules/TelegramUI/Components/LottieCpp/Sources/Lottie/Private/MainThread/LayerContainers/CompLayers/ShapeCompositionLayer.cpp @@ -506,60 +506,44 @@ public: } virtual ~PathOutput() = default; - virtual void update(AnimationFrameTime frameTime, BezierPathsBoundingBoxContext &boundingBoxContext) = 0; - virtual BezierPath const *currentPath() = 0; - virtual CGRect const ¤tPathBounds() = 0; + virtual void update(AnimationFrameTime frameTime) = 0; + virtual std::shared_ptr ¤tPath() = 0; }; class StaticPathOutput : public PathOutput { public: explicit StaticPathOutput(BezierPath const &path) : - resolvedPath(path) { + resolvedPath(std::make_shared(path)) { } - virtual void update(AnimationFrameTime frameTime, BezierPathsBoundingBoxContext &boundingBoxContext) override { - if (!isPathBoundsResolved) { - resolvedPathBounds = bezierPathsBoundingBoxParallel(boundingBoxContext, resolvedPath); - isPathBoundsResolved = true; - } + virtual void update(AnimationFrameTime frameTime) override { } - virtual BezierPath const *currentPath() override { - return &resolvedPath; - } - - virtual CGRect const ¤tPathBounds() override { - return resolvedPathBounds; + virtual std::shared_ptr ¤tPath() override { + return resolvedPath; } private: - BezierPath resolvedPath; - - bool isPathBoundsResolved = false; - CGRect resolvedPathBounds = CGRect(0.0, 0.0, 0.0, 0.0); + std::shared_ptr resolvedPath; }; class ShapePathOutput : public PathOutput { public: explicit ShapePathOutput(Shape const &shape) : - path(shape.path.keyframes) { + path(shape.path.keyframes), + resolvedPath(std::make_shared(BezierPath())) { } - virtual void update(AnimationFrameTime frameTime, BezierPathsBoundingBoxContext &boundingBoxContext) override { + virtual void update(AnimationFrameTime frameTime) override { if (!hasValidData || path.hasUpdate(frameTime)) { - path.update(frameTime, resolvedPath); - resolvedPathBounds = bezierPathsBoundingBoxParallel(boundingBoxContext, resolvedPath); + path.update(frameTime, resolvedPath->path); + resolvedPath->needsBoundsRecalculation = true; } - hasValidData = true; } - virtual BezierPath const *currentPath() override { - return &resolvedPath; - } - - virtual CGRect const ¤tPathBounds() override { - return resolvedPathBounds; + virtual std::shared_ptr ¤tPath() override { + return resolvedPath; } private: @@ -567,8 +551,7 @@ public: BezierPathKeyframeInterpolator path; - BezierPath resolvedPath; - CGRect resolvedPathBounds = CGRect(0.0, 0.0, 0.0, 0.0); + std::shared_ptr resolvedPath; }; class RectanglePathOutput : public PathOutput { @@ -577,10 +560,11 @@ public: direction(rectangle.direction.value_or(PathDirection::Clockwise)), position(rectangle.position.keyframes), size(rectangle.size.keyframes), - cornerRadius(rectangle.cornerRadius.keyframes) { + cornerRadius(rectangle.cornerRadius.keyframes), + resolvedPath(std::make_shared(BezierPath())) { } - virtual void update(AnimationFrameTime frameTime, BezierPathsBoundingBoxContext &boundingBoxContext) override { + virtual void update(AnimationFrameTime frameTime) override { bool hasUpdates = false; if (!hasValidData || position.hasUpdate(frameTime)) { @@ -597,19 +581,15 @@ public: } if (hasUpdates) { - ValueInterpolator::setInplace(makeRectangleBezierPath(Vector2D(positionValue.x, positionValue.y), Vector2D(sizeValue.x, sizeValue.y), cornerRadiusValue, direction), resolvedPath); - resolvedPathBounds = bezierPathsBoundingBoxParallel(boundingBoxContext, resolvedPath); + ValueInterpolator::setInplace(makeRectangleBezierPath(Vector2D(positionValue.x, positionValue.y), Vector2D(sizeValue.x, sizeValue.y), cornerRadiusValue, direction), resolvedPath->path); + resolvedPath->needsBoundsRecalculation = true; } hasValidData = true; } - virtual BezierPath const *currentPath() override { - return &resolvedPath; - } - - virtual CGRect const ¤tPathBounds() override { - return resolvedPathBounds; + virtual std::shared_ptr ¤tPath() override { + return resolvedPath; } private: @@ -626,8 +606,7 @@ public: KeyframeInterpolator cornerRadius; float cornerRadiusValue = 0.0; - BezierPath resolvedPath; - CGRect resolvedPathBounds = CGRect(0.0, 0.0, 0.0, 0.0); + std::shared_ptr resolvedPath; }; class EllipsePathOutput : public PathOutput { @@ -635,10 +614,11 @@ public: explicit EllipsePathOutput(Ellipse const &ellipse) : direction(ellipse.direction.value_or(PathDirection::Clockwise)), position(ellipse.position.keyframes), - size(ellipse.size.keyframes) { + size(ellipse.size.keyframes), + resolvedPath(std::make_shared(BezierPath())) { } - virtual void update(AnimationFrameTime frameTime, BezierPathsBoundingBoxContext &boundingBoxContext) override { + virtual void update(AnimationFrameTime frameTime) override { bool hasUpdates = false; if (!hasValidData || position.hasUpdate(frameTime)) { @@ -651,19 +631,15 @@ public: } if (hasUpdates) { - ValueInterpolator::setInplace(makeEllipseBezierPath(Vector2D(sizeValue.x, sizeValue.y), Vector2D(positionValue.x, positionValue.y), direction), resolvedPath); - resolvedPathBounds = bezierPathsBoundingBoxParallel(boundingBoxContext, resolvedPath); + ValueInterpolator::setInplace(makeEllipseBezierPath(Vector2D(sizeValue.x, sizeValue.y), Vector2D(positionValue.x, positionValue.y), direction), resolvedPath->path); + resolvedPath->needsBoundsRecalculation = true; } hasValidData = true; } - virtual BezierPath const *currentPath() override { - return &resolvedPath; - } - - virtual CGRect const ¤tPathBounds() override { - return resolvedPathBounds; + virtual std::shared_ptr ¤tPath() override { + return resolvedPath; } private: @@ -677,8 +653,7 @@ public: KeyframeInterpolator size; Vector3D sizeValue = Vector3D(0.0, 0.0, 0.0); - BezierPath resolvedPath; - CGRect resolvedPathBounds = CGRect(0.0, 0.0, 0.0, 0.0); + std::shared_ptr resolvedPath; }; class StarPathOutput : public PathOutput { @@ -689,7 +664,8 @@ public: outerRadius(star.outerRadius.keyframes), outerRoundedness(star.outerRoundness.keyframes), rotation(star.rotation.keyframes), - points(star.points.keyframes) { + points(star.points.keyframes), + resolvedPath(std::make_shared(BezierPath())) { if (star.innerRadius.has_value()) { innerRadius = std::make_unique>(std::make_shared>(star.innerRadius->keyframes)); } else { @@ -703,7 +679,7 @@ public: } } - virtual void update(AnimationFrameTime frameTime, BezierPathsBoundingBoxContext &boundingBoxContext) override { + virtual void update(AnimationFrameTime frameTime) override { bool hasUpdates = false; if (!hasValidData || position.hasUpdate(frameTime)) { @@ -744,19 +720,15 @@ public: } if (hasUpdates) { - ValueInterpolator::setInplace(makeStarBezierPath(Vector2D(positionValue.x, positionValue.y), outerRadiusValue, innerRadiusValue, outerRoundednessValue, innerRoundednessValue, pointsValue, rotationValue, direction), resolvedPath); - resolvedPathBounds = bezierPathsBoundingBoxParallel(boundingBoxContext, resolvedPath); + ValueInterpolator::setInplace(makeStarBezierPath(Vector2D(positionValue.x, positionValue.y), outerRadiusValue, innerRadiusValue, outerRoundednessValue, innerRoundednessValue, pointsValue, rotationValue, direction), resolvedPath->path); + resolvedPath->needsBoundsRecalculation = true; } hasValidData = true; } - virtual BezierPath const *currentPath() override { - return &resolvedPath; - } - - virtual CGRect const ¤tPathBounds() override { - return resolvedPathBounds; + virtual std::shared_ptr ¤tPath() override { + return resolvedPath; } private: @@ -785,8 +757,7 @@ public: KeyframeInterpolator points; float pointsValue = 0.0; - BezierPath resolvedPath; - CGRect resolvedPathBounds = CGRect(0.0, 0.0, 0.0, 0.0); + std::shared_ptr resolvedPath; }; class TransformOutput { @@ -951,7 +922,7 @@ public: size_t maxSubitem = std::min(subItems.size(), subItemLimit); if (_contentItem->path) { - mappedPaths.emplace_back(_contentItem->path.value(), effectiveTransform); + mappedPaths.emplace_back(_contentItem->path->path, effectiveTransform); } for (size_t i = 0; i < maxSubitem; i++) { @@ -1012,7 +983,7 @@ public: _contentItem->isGroup = isGroup; if (path) { - _contentItem->path = *path->currentPath(); + _contentItem->path = path->currentPath(); } if (!shadings.empty()) { @@ -1052,8 +1023,7 @@ public: } if (path) { - path->update(frameTime, boundingBoxContext); - _contentItem->pathBoundingBox = path->currentPathBounds(); + path->update(frameTime); } for (const auto &trim : trims) { trim->update(frameTime);