diff --git a/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/SoftwareLottieRenderer.mm b/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/SoftwareLottieRenderer.mm index dfe2fbafbf..8a63baf5a7 100644 --- a/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/SoftwareLottieRenderer.mm +++ b/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/SoftwareLottieRenderer.mm @@ -58,18 +58,6 @@ static void processRenderTree(std::shared_ptr const &node, Vecto } } } - /*if (node->content()) { - RenderTreeNodeContent *shapeContent = node->content().get(); - - CGRect shapeBounds = bezierPathsBoundingBoxParallel(bezierPathsBoundingBoxContext, shapeContent->paths); - - if (shapeContent->stroke) { - shapeBounds = shapeBounds.insetBy(-shapeContent->stroke->lineWidth / 2.0, -shapeContent->stroke->lineWidth / 2.0); - effectiveLocalBounds = shapeBounds; - } else if (shapeContent->fill) { - effectiveLocalBounds = shapeBounds; - } - }*/ bool isInvertedMatte = isInvertedMask; if (isInvertedMatte) { @@ -95,7 +83,7 @@ static void processRenderTree(std::shared_ptr const &node, Vecto if (item->renderData.isValid) { drawContentDescendants += item->renderData.drawContentDescendants; - if (item->content() || item->_contentItem) { + if (item->_contentItem) { drawContentDescendants += 1; } @@ -200,167 +188,6 @@ static void processRenderTree(std::shared_ptr const &node, Vecto namespace { -static void drawLottieRenderableItem(std::shared_ptr context, std::shared_ptr item) { - if (item->paths.empty()) { - return; - } - - std::shared_ptr path = lottie::CGPath::makePath(); - - const auto iterate = [&](LottiePathItem const *pathItem) { - switch (pathItem->type) { - case LottiePathItemTypeMoveTo: { - path->moveTo(lottie::Vector2D(pathItem->points[0].x, pathItem->points[0].y)); - break; - } - case LottiePathItemTypeLineTo: { - path->addLineTo(lottie::Vector2D(pathItem->points[0].x, pathItem->points[0].y)); - break; - } - case LottiePathItemTypeCurveTo: { - path->addCurveTo(lottie::Vector2D(pathItem->points[2].x, pathItem->points[2].y), lottie::Vector2D(pathItem->points[0].x, pathItem->points[0].y), lottie::Vector2D(pathItem->points[1].x, pathItem->points[1].y)); - break; - } - case LottiePathItemTypeClose: { - path->closeSubpath(); - break; - } - default: { - break; - } - } - }; - - LottiePathItem pathItem; - for (const auto &path : item->paths) { - std::optional previousElement; - for (const auto &element : path.elements()) { - if (previousElement.has_value()) { - if (previousElement->vertex.outTangentRelative().isZero() && element.vertex.inTangentRelative().isZero()) { - pathItem.type = LottiePathItemTypeLineTo; - pathItem.points[0] = CGPointMake(element.vertex.point.x, element.vertex.point.y); - iterate(&pathItem); - } else { - pathItem.type = LottiePathItemTypeCurveTo; - pathItem.points[2] = CGPointMake(element.vertex.point.x, element.vertex.point.y); - pathItem.points[1] = CGPointMake(element.vertex.inTangent.x, element.vertex.inTangent.y); - pathItem.points[0] = CGPointMake(previousElement->vertex.outTangent.x, previousElement->vertex.outTangent.y); - iterate(&pathItem); - } - } else { - pathItem.type = LottiePathItemTypeMoveTo; - pathItem.points[0] = CGPointMake(element.vertex.point.x, element.vertex.point.y); - iterate(&pathItem); - } - previousElement = element; - } - if (path.closed().value_or(true)) { - pathItem.type = LottiePathItemTypeClose; - iterate(&pathItem); - } - } - - if (item->stroke) { - if (item->stroke->shading->type() == lottie::RenderTreeNodeContent::ShadingType::Solid) { - lottie::RenderTreeNodeContent::SolidShading *solidShading = (lottie::RenderTreeNodeContent::SolidShading *)item->stroke->shading.get(); - - lottieRendering::LineJoin lineJoin = lottieRendering::LineJoin::Bevel; - switch (item->stroke->lineJoin) { - case lottie::LineJoin::Bevel: { - lineJoin = lottieRendering::LineJoin::Bevel; - break; - } - case lottie::LineJoin::Round: { - lineJoin = lottieRendering::LineJoin::Round; - break; - } - case lottie::LineJoin::Miter: { - lineJoin = lottieRendering::LineJoin::Miter; - break; - } - default: { - break; - } - } - - lottieRendering::LineCap lineCap = lottieRendering::LineCap::Square; - switch (item->stroke->lineCap) { - case lottie::LineCap::Butt: { - lineCap = lottieRendering::LineCap::Butt; - break; - } - case lottie::LineCap::Round: { - lineCap = lottieRendering::LineCap::Round; - break; - } - case lottie::LineCap::Square: { - lineCap = lottieRendering::LineCap::Square; - break; - } - default: { - break; - } - } - - std::vector dashPattern; - if (!item->stroke->dashPattern.empty()) { - dashPattern = item->stroke->dashPattern; - } - - context->strokePath(path, item->stroke->lineWidth, lineJoin, lineCap, item->stroke->dashPhase, dashPattern, lottieRendering::Color(solidShading->color.r, solidShading->color.g, solidShading->color.b, solidShading->color.a * solidShading->opacity)); - } else if (item->stroke->shading->type() == lottie::RenderTreeNodeContent::ShadingType::Gradient) { - //TODO:gradient stroke - } - } else if (item->fill) { - lottieRendering::FillRule rule = lottieRendering::FillRule::NonZeroWinding; - switch (item->fill->rule) { - case lottie::FillRule::EvenOdd: { - rule = lottieRendering::FillRule::EvenOdd; - break; - } - case lottie::FillRule::NonZeroWinding: { - rule = lottieRendering::FillRule::NonZeroWinding; - break; - } - default: { - break; - } - } - - if (item->fill->shading->type() == lottie::RenderTreeNodeContent::ShadingType::Solid) { - lottie::RenderTreeNodeContent::SolidShading *solidShading = (lottie::RenderTreeNodeContent::SolidShading *)item->fill->shading.get(); - context->fillPath(path, rule, lottieRendering::Color(solidShading->color.r, solidShading->color.g, solidShading->color.b, solidShading->color.a * solidShading->opacity)); - } else if (item->fill->shading->type() == lottie::RenderTreeNodeContent::ShadingType::Gradient) { - lottie::RenderTreeNodeContent::GradientShading *gradientShading = (lottie::RenderTreeNodeContent::GradientShading *)item->fill->shading.get(); - - std::vector colors; - std::vector locations; - for (const auto &color : gradientShading->colors) { - colors.push_back(lottieRendering::Color(color.r, color.g, color.b, color.a * gradientShading->opacity)); - } - locations = gradientShading->locations; - - lottieRendering::Gradient gradient(colors, locations); - lottie::Vector2D start(gradientShading->start.x, gradientShading->start.y); - lottie::Vector2D end(gradientShading->end.x, gradientShading->end.y); - - switch (gradientShading->gradientType) { - case lottie::GradientType::Linear: { - context->linearGradientFillPath(path, rule, gradient, start, end); - break; - } - case lottie::GradientType::Radial: { - context->radialGradientFillPath(path, rule, gradient, start, 0.0, start, start.distanceTo(end)); - break; - } - default: { - break; - } - } - } - } -} - static void drawLottieContentItem(std::shared_ptr context, std::shared_ptr item) { if (item->shadings.empty()) { return; @@ -427,8 +254,8 @@ static void drawLottieContentItem(std::shared_ptr conte } if (shading->stroke) { - if (shading->stroke->shading->type() == lottie::RenderTreeNodeContent::ShadingType::Solid) { - lottie::RenderTreeNodeContent::SolidShading *solidShading = (lottie::RenderTreeNodeContent::SolidShading *)shading->stroke->shading.get(); + if (shading->stroke->shading->type() == lottie::RenderTreeNodeContentItem::ShadingType::Solid) { + lottie::RenderTreeNodeContentItem::SolidShading *solidShading = (lottie::RenderTreeNodeContentItem::SolidShading *)shading->stroke->shading.get(); if (solidShading->opacity != 0.0) { lottieRendering::LineJoin lineJoin = lottieRendering::LineJoin::Bevel; @@ -475,7 +302,7 @@ static void drawLottieContentItem(std::shared_ptr conte } context->strokePath(path, shading->stroke->lineWidth, lineJoin, lineCap, shading->stroke->dashPhase, dashPattern, lottieRendering::Color(solidShading->color.r, solidShading->color.g, solidShading->color.b, solidShading->color.a * solidShading->opacity)); - } else if (shading->stroke->shading->type() == lottie::RenderTreeNodeContent::ShadingType::Gradient) { + } else if (shading->stroke->shading->type() == lottie::RenderTreeNodeContentItem::ShadingType::Gradient) { //TODO:gradient stroke } } @@ -495,13 +322,13 @@ static void drawLottieContentItem(std::shared_ptr conte } } - if (shading->fill->shading->type() == lottie::RenderTreeNodeContent::ShadingType::Solid) { - lottie::RenderTreeNodeContent::SolidShading *solidShading = (lottie::RenderTreeNodeContent::SolidShading *)shading->fill->shading.get(); + if (shading->fill->shading->type() == lottie::RenderTreeNodeContentItem::ShadingType::Solid) { + lottie::RenderTreeNodeContentItem::SolidShading *solidShading = (lottie::RenderTreeNodeContentItem::SolidShading *)shading->fill->shading.get(); if (solidShading->opacity != 0.0) { context->fillPath(path, rule, lottieRendering::Color(solidShading->color.r, solidShading->color.g, solidShading->color.b, solidShading->color.a * solidShading->opacity)); } - } else if (shading->fill->shading->type() == lottie::RenderTreeNodeContent::ShadingType::Gradient) { - lottie::RenderTreeNodeContent::GradientShading *gradientShading = (lottie::RenderTreeNodeContent::GradientShading *)shading->fill->shading.get(); + } else if (shading->fill->shading->type() == lottie::RenderTreeNodeContentItem::ShadingType::Gradient) { + lottie::RenderTreeNodeContentItem::GradientShading *gradientShading = (lottie::RenderTreeNodeContentItem::GradientShading *)shading->fill->shading.get(); if (gradientShading->opacity != 0.0) { std::vector colors; @@ -600,10 +427,7 @@ static void renderLottieRenderNode(std::shared_ptr node, currentContext->setAlpha(renderAlpha); - if (node->content() && (int64_t)"" < 0) { - drawLottieRenderableItem(currentContext, node->content()); - } - if (node->_contentItem) {//} && (int64_t)"" < 0) { + if (node->_contentItem) { drawLottieContentItem(currentContext, node->_contentItem); } diff --git a/submodules/TelegramUI/Components/LottieCpp/PublicHeaders/LottieCpp/RenderTreeNode.h b/submodules/TelegramUI/Components/LottieCpp/PublicHeaders/LottieCpp/RenderTreeNode.h index 0581fdbaa6..0b45e421e7 100644 --- a/submodules/TelegramUI/Components/LottieCpp/PublicHeaders/LottieCpp/RenderTreeNode.h +++ b/submodules/TelegramUI/Components/LottieCpp/PublicHeaders/LottieCpp/RenderTreeNode.h @@ -231,9 +231,9 @@ public: CGRect bounds; }; -class RenderTreeNodeContentItem; +class RenderTreeNodeContentShadingVariant; -class RenderTreeNodeContent { +class RenderTreeNodeContentItem { public: enum class ShadingType { Solid, @@ -339,20 +339,12 @@ public: }; public: - RenderTreeNodeContent( - std::vector paths_, - std::shared_ptr stroke_, - std::shared_ptr fill_ - ) : - paths(paths_), - stroke(stroke_), - fill(fill_) { + RenderTreeNodeContentItem() { } public: - std::vector paths; - std::shared_ptr stroke; - std::shared_ptr fill; + bool isGroup = false; + std::vector> shadings; }; class RenderTreeNodeContentShadingVariant { @@ -361,24 +353,14 @@ public: } public: - std::shared_ptr stroke; - std::shared_ptr fill; + std::shared_ptr stroke; + std::shared_ptr fill; std::optional> explicitPath; size_t subItemLimit = 0; bool isGroup = false; }; -class RenderTreeNodeContentItem { -public: - RenderTreeNodeContentItem() { - } - -public: - bool isGroup = false; - std::vector> shadings; -}; - class ProcessedRenderTreeNodeData { public: struct LayerParams { @@ -468,7 +450,6 @@ public: double alpha_, bool masksToBounds_, bool isHidden_, - std::shared_ptr content_, std::vector> subnodes_, std::shared_ptr mask_, bool invertMask_ @@ -479,7 +460,6 @@ public: _alpha(alpha_), _masksToBounds(masksToBounds_), _isHidden(isHidden_), - _content(content_), _subnodes(subnodes_), _mask(mask_), _invertMask(invertMask_) { @@ -513,10 +493,6 @@ public: return _isHidden; } - std::shared_ptr const &content() const { - return _content; - } - std::vector> const &subnodes() const { return _subnodes; } @@ -536,7 +512,6 @@ public: double _alpha = 1.0; bool _masksToBounds = false; bool _isHidden = false; - std::shared_ptr _content; std::shared_ptr _contentItem; std::vector> _subnodes; std::shared_ptr _mask; diff --git a/submodules/TelegramUI/Components/LottieCpp/Sources/Lottie/Private/MainThread/LayerContainers/CompLayers/PreCompositionLayer.hpp b/submodules/TelegramUI/Components/LottieCpp/Sources/Lottie/Private/MainThread/LayerContainers/CompLayers/PreCompositionLayer.hpp index 6242d289d1..5b310c8571 100644 --- a/submodules/TelegramUI/Components/LottieCpp/Sources/Lottie/Private/MainThread/LayerContainers/CompLayers/PreCompositionLayer.hpp +++ b/submodules/TelegramUI/Components/LottieCpp/Sources/Lottie/Private/MainThread/LayerContainers/CompLayers/PreCompositionLayer.hpp @@ -109,7 +109,6 @@ public: 1.0, false, false, - nullptr, std::vector>(), nullptr, false @@ -134,7 +133,6 @@ public: 1.0, false, false, - nullptr, subnodes, maskNode, invertMask @@ -165,7 +163,6 @@ public: 1.0, false, false, - nullptr, renderTreeSubnodes, nullptr, false 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 bd638add70..01298b9809 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 @@ -25,7 +25,7 @@ public: ~FillOutput() = default; virtual void update(AnimationFrameTime frameTime) = 0; - virtual std::shared_ptr fill() = 0; + virtual std::shared_ptr fill() = 0; }; class SolidFillOutput : public FillOutput { @@ -34,6 +34,11 @@ public: rule(fill.fillRule.value_or(FillRule::NonZeroWinding)), color(fill.color.keyframes), opacity(fill.opacity.keyframes) { + auto solid = std::make_shared(Color(0.0, 0.0, 0.0, 0.0), 0.0); + _fill = std::make_shared( + solid, + rule + ); } virtual ~SolidFillOutput() = default; @@ -51,16 +56,14 @@ public: opacityValue = opacity.value(frameTime).value; } - if (!_fill || hasUpdates) { - auto solid = std::make_shared(colorValue, opacityValue * 0.01); - _fill = std::make_shared( - solid, - rule - ); + if (hasUpdates) { + RenderTreeNodeContentItem::SolidShading *solid = (RenderTreeNodeContentItem::SolidShading *)_fill->shading.get(); + solid->color = colorValue; + solid->opacity = opacityValue * 0.01; } } - virtual std::shared_ptr fill() override { + virtual std::shared_ptr fill() override { return _fill; } @@ -73,7 +76,7 @@ public: KeyframeInterpolator opacity; double opacityValue = 0.0; - std::shared_ptr _fill; + std::shared_ptr _fill; }; class GradientFillOutput : public FillOutput { @@ -86,6 +89,18 @@ public: startPoint(gradientFill.startPoint.keyframes), endPoint(gradientFill.endPoint.keyframes), opacity(gradientFill.opacity.keyframes) { + auto gradient = std::make_shared( + 0.0, + gradientType, + std::vector(), + std::vector(), + Vector2D(0.0, 0.0), + Vector2D(0.0, 0.0) + ); + _fill = std::make_shared( + gradient, + rule + ); } virtual ~GradientFillOutput() = default; @@ -113,27 +128,21 @@ public: opacityValue = opacity.value(frameTime).value; } - if (!_fill || hasUpdates) { + if (hasUpdates) { std::vector colors; std::vector locations; getGradientParameters(numberOfColors, colorsValue, colors, locations); - auto gradient = std::make_shared( - opacityValue * 0.01, - gradientType, - colors, - locations, - Vector2D(startPointValue.x, startPointValue.y), - Vector2D(endPointValue.x, endPointValue.y) - ); - _fill = std::make_shared( - gradient, - rule - ); + RenderTreeNodeContentItem::GradientShading *gradient = ((RenderTreeNodeContentItem::GradientShading *)_fill->shading.get()); + gradient->opacity = opacityValue * 0.01; + gradient->colors = colors; + gradient->locations = locations; + gradient->start = Vector2D(startPointValue.x, startPointValue.y); + gradient->end = Vector2D(endPointValue.x, endPointValue.y); } } - virtual std::shared_ptr fill() override { + virtual std::shared_ptr fill() override { return _fill; } @@ -154,7 +163,7 @@ public: KeyframeInterpolator opacity; double opacityValue = 0.0; - std::shared_ptr _fill; + std::shared_ptr _fill; }; class StrokeOutput { @@ -164,7 +173,7 @@ public: ~StrokeOutput() = default; virtual void update(AnimationFrameTime frameTime) = 0; - virtual std::shared_ptr stroke() = 0; + virtual std::shared_ptr stroke() = 0; }; class SolidStrokeOutput : public StrokeOutput { @@ -184,6 +193,17 @@ public: dashPhase = std::make_unique>(dashConfiguration.dashPhase); } } + + auto solid = std::make_shared(Color(0.0, 0.0, 0.0, 0.0), 0.0); + _stroke = std::make_shared( + solid, + 0.0, + lineJoin, + lineCap, + miterLimit, + 0.0, + std::vector() + ); } virtual ~SolidStrokeOutput() = default; @@ -220,7 +240,7 @@ public: } } - if (!_stroke || hasUpdates) { + if (hasUpdates) { bool hasNonZeroDashes = false; if (!dashPatternValue.values.empty()) { for (const auto &value : dashPatternValue.values) { @@ -231,20 +251,17 @@ public: } } - auto solid = std::make_shared(colorValue, opacityValue * 0.01); - _stroke = std::make_shared( - solid, - widthValue, - lineJoin, - lineCap, - miterLimit, - hasNonZeroDashes ? dashPhaseValue : 0.0, - hasNonZeroDashes ? dashPatternValue.values : std::vector() - ); + RenderTreeNodeContentItem::SolidShading *solid = (RenderTreeNodeContentItem::SolidShading *)_stroke->shading.get(); + solid->color = colorValue; + solid->opacity = opacityValue * 0.01; + + _stroke->lineWidth = widthValue; + _stroke->dashPhase = hasNonZeroDashes ? dashPhaseValue : 0.0; + _stroke->dashPattern = hasNonZeroDashes ? dashPatternValue.values : std::vector(); } } - virtual std::shared_ptr stroke() override { + virtual std::shared_ptr stroke() override { return _stroke; } @@ -268,7 +285,7 @@ public: std::unique_ptr> dashPhase; double dashPhaseValue = 0.0; - std::shared_ptr _stroke; + std::shared_ptr _stroke; }; class GradientStrokeOutput : public StrokeOutput { @@ -292,6 +309,24 @@ public: dashPhase = std::make_unique>(dashConfiguration.dashPhase); } } + + auto gradient = std::make_shared( + 0.0, + gradientType, + std::vector(), + std::vector(), + Vector2D(0.0, 0.0), + Vector2D(0.0, 0.0) + ); + _stroke = std::make_shared( + gradient, + 0.0, + lineJoin, + lineCap, + miterLimit, + 0.0, + std::vector() + ); } virtual ~GradientStrokeOutput() = default; @@ -338,7 +373,7 @@ public: } } - if (!_stroke || hasUpdates) { + if (hasUpdates) { bool hasNonZeroDashes = false; if (!dashPatternValue.values.empty()) { for (const auto &value : dashPatternValue.values) { @@ -353,27 +388,20 @@ public: std::vector locations; getGradientParameters(numberOfColors, colorsValue, colors, locations); - auto gradient = std::make_shared( - opacityValue * 0.01, - gradientType, - colors, - locations, - Vector2D(startPointValue.x, startPointValue.y), - Vector2D(endPointValue.x, endPointValue.y) - ); - _stroke = std::make_shared( - gradient, - widthValue, - lineJoin, - lineCap, - miterLimit, - hasNonZeroDashes ? dashPhaseValue : 0.0, - hasNonZeroDashes ? dashPatternValue.values : std::vector() - ); + RenderTreeNodeContentItem::GradientShading *gradient = ((RenderTreeNodeContentItem::GradientShading *)_stroke->shading.get()); + gradient->opacity = opacityValue * 0.01; + gradient->colors = colors; + gradient->locations = locations; + gradient->start = Vector2D(startPointValue.x, startPointValue.y); + gradient->end = Vector2D(endPointValue.x, endPointValue.y); + + _stroke->lineWidth = widthValue; + _stroke->dashPhase = hasNonZeroDashes ? dashPhaseValue : 0.0; + _stroke->dashPattern = hasNonZeroDashes ? dashPatternValue.values : std::vector(); } } - virtual std::shared_ptr stroke() override { + virtual std::shared_ptr stroke() override { return _stroke; } @@ -406,7 +434,7 @@ public: std::unique_ptr> dashPhase; double dashPhaseValue = 0.0; - std::shared_ptr _stroke; + std::shared_ptr _stroke; }; struct TrimParams { @@ -478,8 +506,6 @@ public: std::shared_ptr fill; std::shared_ptr stroke; size_t subItemLimit = 0; - - std::shared_ptr renderTree; }; struct TransformedPath { @@ -981,7 +1007,6 @@ public: 1.0, false, false, - nullptr, std::vector>(), nullptr, false @@ -998,38 +1023,12 @@ public: continue; } - auto shadingRenderTree = std::make_shared( - CGRect(0.0, 0.0, 0.0, 0.0), - Vector2D(0.0, 0.0), - CATransform3D::identity(), - 1.0, - false, - false, - nullptr, - std::vector>(), - nullptr, - false - ); - shadingVariant.renderTree = shadingRenderTree; - //_renderTree->_subnodes.push_back(shadingRenderTree); - auto itemShadingVariant = std::make_shared(); if (shadingVariant.fill) { - itemShadingVariant->fill = std::make_shared( - nullptr, - FillRule::NonZeroWinding - ); + itemShadingVariant->fill = shadingVariant.fill->fill(); } if (shadingVariant.stroke) { - itemShadingVariant->stroke = std::make_shared( - nullptr, - 0.0, - LineJoin::Bevel, - LineCap::Round, - 0.0, - 0.0, - std::vector() - ); + itemShadingVariant->stroke = shadingVariant.stroke->stroke(); } itemShadingVariant->subItemLimit = shadingVariant.subItemLimit; @@ -1052,7 +1051,6 @@ public: 1.0, false, false, - nullptr, subItemNodes, nullptr, false @@ -1126,28 +1124,6 @@ public: resultPaths.push_back(path); } - std::shared_ptr content; - - std::shared_ptr fill; - if (shadingVariant.fill) { - fill = shadingVariant.fill->fill(); - } - - std::shared_ptr stroke; - if (shadingVariant.stroke) { - stroke = shadingVariant.stroke->stroke(); - } - - content = std::make_shared( - resultPaths, - stroke, - fill - ); - - shadingVariant.renderTree->_content = content; - - _renderTree->_contentItem->shadings[i]->stroke = stroke; - _renderTree->_contentItem->shadings[i]->fill = fill; _renderTree->_contentItem->shadings[i]->explicitPath = resultPaths; } @@ -1358,7 +1334,6 @@ std::shared_ptr ShapeCompositionLayer::renderTreeNode() { 1.0, false, false, - nullptr, renderTreeValue, nullptr, false @@ -1383,7 +1358,6 @@ std::shared_ptr ShapeCompositionLayer::renderTreeNode() { 1.0, false, false, - nullptr, subnodes, maskNode, invertMask diff --git a/submodules/TelegramUI/Components/LottieCpp/Sources/Lottie/Private/MainThread/LayerContainers/MainThreadAnimationLayer.hpp b/submodules/TelegramUI/Components/LottieCpp/Sources/Lottie/Private/MainThread/LayerContainers/MainThreadAnimationLayer.hpp index 687be55199..c3c26a5352 100644 --- a/submodules/TelegramUI/Components/LottieCpp/Sources/Lottie/Private/MainThread/LayerContainers/MainThreadAnimationLayer.hpp +++ b/submodules/TelegramUI/Components/LottieCpp/Sources/Lottie/Private/MainThread/LayerContainers/MainThreadAnimationLayer.hpp @@ -243,7 +243,6 @@ public: 1.0, false, false, - nullptr, subnodes, nullptr, false diff --git a/submodules/TelegramUI/Components/LottieCpp/Sources/LottieAnimationContainer.mm b/submodules/TelegramUI/Components/LottieCpp/Sources/LottieAnimationContainer.mm index a1b4a8dbeb..0b874ee771 100644 --- a/submodules/TelegramUI/Components/LottieCpp/Sources/LottieAnimationContainer.mm +++ b/submodules/TelegramUI/Components/LottieCpp/Sources/LottieAnimationContainer.mm @@ -2,298 +2,8 @@ #include "Lottie/Private/MainThread/LayerContainers/MainThreadAnimationLayer.hpp" #include "LottieAnimationInternal.h" -#include "RenderNode.hpp" -#include "LottieRenderTreeInternal.h" #include -namespace lottie { - -struct RenderNodeDesc { - struct LayerParams { - CGRect _bounds; - Vector2D _position; - CATransform3D _transform; - double _opacity; - bool _masksToBounds; - bool _isHidden; - - LayerParams( - CGRect bounds_, - Vector2D position_, - CATransform3D transform_, - double opacity_, - bool masksToBounds_, - bool isHidden_ - ) : - _bounds(bounds_), - _position(position_), - _transform(transform_), - _opacity(opacity_), - _masksToBounds(masksToBounds_), - _isHidden(isHidden_) { - } - - CGRect bounds() const { - return _bounds; - } - - Vector2D position() const { - return _position; - } - - CATransform3D transform() const { - return _transform; - } - - double opacity() const { - return _opacity; - } - - bool masksToBounds() const { - return _masksToBounds; - } - - bool isHidden() const { - return _isHidden; - } - }; - - LayerParams layer; - CGRect globalRect; - CGRect localRect; - CATransform3D globalTransform; - bool drawsContent; - bool renderContent; - int drawContentDescendants; - bool isInvertedMatte; - std::shared_ptr mask; - - explicit RenderNodeDesc( - LayerParams const &layer_, - CGRect const &globalRect_, - CGRect const &localRect_, - CATransform3D const &globalTransform_, - bool drawsContent_, - bool renderContent_, - int drawContentDescendants_, - bool isInvertedMatte_ - ) : - layer(layer_), - globalRect(globalRect_), - localRect(localRect_), - globalTransform(globalTransform_), - drawsContent(drawsContent_), - renderContent(renderContent_), - drawContentDescendants(drawContentDescendants_), - isInvertedMatte(isInvertedMatte_) { - } -}; - -static std::shared_ptr convertRenderTree(std::shared_ptr const &node, Vector2D const &globalSize, CATransform3D const &parentTransform, bool isInvertedMask, BezierPathsBoundingBoxContext &bezierPathsBoundingBoxContext) { - if (node->isHidden() || node->alpha() == 0.0f) { - return nullptr; - } - - if (node->masksToBounds()) { - if (node->bounds().empty()) { - return nullptr; - } - } - - auto currentTransform = parentTransform; - - Vector2D localTranslation(node->position().x + -node->bounds().x, node->position().y + -node->bounds().y); - CATransform3D localTransform = node->transform(); - localTransform = localTransform.translated(localTranslation); - - currentTransform = localTransform * currentTransform; - - if (!currentTransform.isInvertible()) { - return nullptr; - } - - std::optional effectiveLocalBounds; - - double alpha = node->alpha(); - - if (node->content()) { - RenderTreeNodeContent *shapeContent = node->content().get(); - - CGRect shapeBounds = bezierPathsBoundingBoxParallel(bezierPathsBoundingBoxContext, shapeContent->paths); - - if (shapeContent->stroke) { - shapeBounds = shapeBounds.insetBy(-shapeContent->stroke->lineWidth / 2.0, -shapeContent->stroke->lineWidth / 2.0); - effectiveLocalBounds = shapeBounds; - - switch (shapeContent->stroke->shading->type()) { - case RenderTreeNodeContent::ShadingType::Solid: { - RenderTreeNodeContent::SolidShading *solidShading = (RenderTreeNodeContent::SolidShading *)shapeContent->stroke->shading.get(); - - alpha *= solidShading->opacity; - - break; - } - case RenderTreeNodeContent::ShadingType::Gradient: { - - break; - } - default: - break; - } - } else if (shapeContent->fill) { - effectiveLocalBounds = shapeBounds; - - switch (shapeContent->fill->shading->type()) { - case RenderTreeNodeContent::ShadingType::Solid: { - RenderTreeNodeContent::SolidShading *solidShading = (RenderTreeNodeContent::SolidShading *)shapeContent->fill->shading.get(); - - alpha *= solidShading->opacity; - - break; - } - case RenderTreeNodeContent::ShadingType::Gradient: { - RenderTreeNodeContent::GradientShading *gradientShading = (RenderTreeNodeContent::GradientShading *)shapeContent->fill->shading.get(); - - alpha *= gradientShading->opacity; - - break; - } - default: - break; - } - } - } - - bool isInvertedMatte = isInvertedMask; - if (isInvertedMatte) { - effectiveLocalBounds = node->bounds(); - } - - if (effectiveLocalBounds && effectiveLocalBounds->empty()) { - effectiveLocalBounds = std::nullopt; - } - - std::optional effectiveLocalRect; - if (effectiveLocalBounds.has_value()) { - effectiveLocalRect = effectiveLocalBounds; - } - - std::vector> subnodes; - std::optional subnodesGlobalRect; - bool masksToBounds = node->masksToBounds(); - - int drawContentDescendants = 0; - - for (const auto &item : node->subnodes()) { - if (const auto subnode = convertRenderTree(item, globalSize, currentTransform, false, bezierPathsBoundingBoxContext)) { - subnodes.push_back(subnode); - - drawContentDescendants += subnode->drawContentDescendants; - - if (subnode->renderContent) { - drawContentDescendants += 1; - } - - if (!subnode->localRect.empty()) { - if (effectiveLocalRect.has_value()) { - effectiveLocalRect = effectiveLocalRect->unionWith(subnode->localRect); - } else { - effectiveLocalRect = subnode->localRect; - } - } - - if (subnodesGlobalRect) { - subnodesGlobalRect = subnodesGlobalRect->unionWith(subnode->globalRect); - } else { - subnodesGlobalRect = subnode->globalRect; - } - } - } - - if (masksToBounds && effectiveLocalRect.has_value()) { - if (node->bounds().contains(effectiveLocalRect.value())) { - masksToBounds = false; - } - } - - std::optional fuzzyGlobalRect; - - if (effectiveLocalBounds) { - CGRect effectiveGlobalBounds = effectiveLocalBounds->applyingTransform(currentTransform); - if (fuzzyGlobalRect) { - fuzzyGlobalRect = fuzzyGlobalRect->unionWith(effectiveGlobalBounds); - } else { - fuzzyGlobalRect = effectiveGlobalBounds; - } - } - - if (subnodesGlobalRect) { - if (fuzzyGlobalRect) { - fuzzyGlobalRect = fuzzyGlobalRect->unionWith(subnodesGlobalRect.value()); - } else { - fuzzyGlobalRect = subnodesGlobalRect; - } - } - - if (!fuzzyGlobalRect) { - return nullptr; - } - - CGRect globalRect( - std::floor(fuzzyGlobalRect->x), - std::floor(fuzzyGlobalRect->y), - std::ceil(fuzzyGlobalRect->width + fuzzyGlobalRect->x - floor(fuzzyGlobalRect->x)), - std::ceil(fuzzyGlobalRect->height + fuzzyGlobalRect->y - floor(fuzzyGlobalRect->y)) - ); - - if (!CGRect(0.0, 0.0, globalSize.x, globalSize.y).intersects(globalRect)) { - return nullptr; - } - - if (masksToBounds && effectiveLocalBounds) { - CGRect effectiveGlobalBounds = effectiveLocalBounds->applyingTransform(currentTransform); - if (effectiveGlobalBounds.contains(CGRect(0.0, 0.0, globalSize.x, globalSize.y))) { - masksToBounds = false; - } - } - - std::shared_ptr maskNode; - if (node->mask()) { - if (const auto maskNodeValue = convertRenderTree(node->mask(), globalSize, currentTransform, node->invertMask(), bezierPathsBoundingBoxContext)) { - if (!maskNodeValue->globalRect.intersects(globalRect)) { - return nullptr; - } - maskNode = maskNodeValue; - } else { - return nullptr; - } - } - - CGRect localRect = effectiveLocalRect.value_or(CGRect(0.0, 0.0, 0.0, 0.0)).applyingTransform(localTransform); - - return std::make_shared( - OutputRenderNode::LayerParams( - node->bounds(), - node->position(), - node->transform(), - alpha, - masksToBounds, - node->isHidden() - ), - globalRect, - localRect, - currentTransform, - effectiveLocalBounds.has_value(), - node->content(), - drawContentDescendants, - isInvertedMatte, - subnodes, - maskNode - ); -} - -} - @interface LottieAnimationContainer () { @public std::shared_ptr _layer; @@ -326,41 +36,7 @@ static std::shared_ptr convertRenderTree(std::shared_ptrrenderTreeNode(); - if (!renderNode) { - return nil; - } - - if (size.width <= 0.0 || size.height <= 0.0) { - return nil; - } - - auto node = convertRenderTree(renderNode, lottie::Vector2D((int)size.width, (int)size.height), lottie::CATransform3D::identity().scaled(lottie::Vector2D(size.width / (double)_animation.size.width, size.height / (double)_animation.size.height)), false, *_bezierPathsBoundingBoxContext.get()); - - if (node) { - return [[LottieRenderNode alloc] initWithRenderNode:node]; - } else { - node = std::make_shared( - lottie::OutputRenderNode::LayerParams( - lottie::CGRect(0.0, 0.0, size.width, size.height), - lottie::Vector2D(0.0, 0.0), - lottie::CATransform3D::identity(), - 1.0, - false, - false - ), - lottie::CGRect(0.0, 0.0, size.width, size.height), - lottie::CGRect(0.0, 0.0, size.width, size.height), - lottie::CATransform3D::identity(), - false, - nullptr, - true, - false, - std::vector>(), - nullptr - ); - return [[LottieRenderNode alloc] initWithRenderNode:node]; - } + return nil; } - (std::shared_ptr)internalGetRootRenderTreeNode { diff --git a/submodules/TelegramUI/Components/LottieCpp/Sources/LottieRenderTree.mm b/submodules/TelegramUI/Components/LottieCpp/Sources/LottieRenderTree.mm index c92606839d..9cdf512213 100644 --- a/submodules/TelegramUI/Components/LottieCpp/Sources/LottieRenderTree.mm +++ b/submodules/TelegramUI/Components/LottieCpp/Sources/LottieRenderTree.mm @@ -1,5 +1,4 @@ #include "LottieRenderTree.h" -#include "LottieRenderTreeInternal.h" #include #include @@ -7,8 +6,6 @@ #include "Lottie/Public/Primitives/CALayer.hpp" #include -#include "RenderNode.hpp" - namespace { } @@ -192,7 +189,7 @@ static LottieColor lottieColorFromColor(lottie::Color color) { @implementation LottieRenderContentSolidShading -- (instancetype _Nonnull)initWithSolidShading:(lottie::RenderTreeNodeContent::SolidShading *)solidShading __attribute__((objc_direct)) { +- (instancetype _Nonnull)initWithSolidShading:(lottie::RenderTreeNodeContentItem::SolidShading *)solidShading __attribute__((objc_direct)) { self = [super init]; if (self != nil) { _color = lottieColorFromColor(solidShading->color); @@ -214,7 +211,7 @@ static LottieColor lottieColorFromColor(lottie::Color color) { @implementation LottieRenderContentGradientShading -- (instancetype _Nonnull)initWithGradientShading:(lottie::RenderTreeNodeContent::GradientShading *)gradientShading __attribute__((objc_direct)) { +- (instancetype _Nonnull)initWithGradientShading:(lottie::RenderTreeNodeContentItem::GradientShading *)gradientShading __attribute__((objc_direct)) { self = [super init]; if (self != nil) { _opacity = gradientShading->opacity; @@ -258,16 +255,16 @@ static LottieColor lottieColorFromColor(lottie::Color color) { @implementation LottieRenderContentFill -- (instancetype _Nonnull)initWithFill:(std::shared_ptr const &)fill __attribute__((objc_direct)) { +- (instancetype _Nonnull)initWithFill:(std::shared_ptr const &)fill __attribute__((objc_direct)) { self = [super init]; if (self != nil) { switch (fill->shading->type()) { - case lottie::RenderTreeNodeContent::ShadingType::Solid: { - _shading = [[LottieRenderContentSolidShading alloc] initWithSolidShading:(lottie::RenderTreeNodeContent::SolidShading *)fill->shading.get()]; + case lottie::RenderTreeNodeContentItem::ShadingType::Solid: { + _shading = [[LottieRenderContentSolidShading alloc] initWithSolidShading:(lottie::RenderTreeNodeContentItem::SolidShading *)fill->shading.get()]; break; } - case lottie::RenderTreeNodeContent::ShadingType::Gradient: { - _shading = [[LottieRenderContentGradientShading alloc] initWithGradientShading:(lottie::RenderTreeNodeContent::GradientShading *)fill->shading.get()]; + case lottie::RenderTreeNodeContentItem::ShadingType::Gradient: { + _shading = [[LottieRenderContentGradientShading alloc] initWithGradientShading:(lottie::RenderTreeNodeContentItem::GradientShading *)fill->shading.get()]; break; } default: { @@ -302,16 +299,16 @@ static LottieColor lottieColorFromColor(lottie::Color color) { @implementation LottieRenderContentStroke -- (instancetype _Nonnull)initWithStroke:(std::shared_ptr const &)stroke __attribute__((objc_direct)) { +- (instancetype _Nonnull)initWithStroke:(std::shared_ptr const &)stroke __attribute__((objc_direct)) { self = [super init]; if (self != nil) { switch (stroke->shading->type()) { - case lottie::RenderTreeNodeContent::ShadingType::Solid: { - _shading = [[LottieRenderContentSolidShading alloc] initWithSolidShading:(lottie::RenderTreeNodeContent::SolidShading *)stroke->shading.get()]; + case lottie::RenderTreeNodeContentItem::ShadingType::Solid: { + _shading = [[LottieRenderContentSolidShading alloc] initWithSolidShading:(lottie::RenderTreeNodeContentItem::SolidShading *)stroke->shading.get()]; break; } - case lottie::RenderTreeNodeContent::ShadingType::Gradient: { - _shading = [[LottieRenderContentGradientShading alloc] initWithGradientShading:(lottie::RenderTreeNodeContent::GradientShading *)stroke->shading.get()]; + case lottie::RenderTreeNodeContentItem::ShadingType::Gradient: { + _shading = [[LottieRenderContentGradientShading alloc] initWithGradientShading:(lottie::RenderTreeNodeContentItem::GradientShading *)stroke->shading.get()]; break; } default: { @@ -392,20 +389,6 @@ static LottieColor lottieColorFromColor(lottie::Color color) { @implementation LottieRenderContent -- (instancetype _Nonnull)initWithRenderContent:(std::shared_ptr const &)content __attribute__((objc_direct)) { - self = [super init]; - if (self != nil) { - _path = [[LottiePath alloc] initWithPaths:content->paths]; - if (content->stroke) { - _stroke = [[LottieRenderContentStroke alloc] initWithStroke:content->stroke]; - } - if (content->fill) { - _fill = [[LottieRenderContentFill alloc] initWithFill:content->fill]; - } - } - return self; -} - - (instancetype _Nonnull)initWithPath:(LottiePath * _Nonnull)path stroke:(LottieRenderContentStroke * _Nullable)stroke fill:(LottieRenderContentFill * _Nullable)fill __attribute__((objc_direct)) { self = [super init]; if (self != nil) { @@ -441,50 +424,3 @@ static LottieColor lottieColorFromColor(lottie::Color color) { } @end - -@implementation LottieRenderNode (Internal) - -- (instancetype _Nonnull)initWithRenderNode:(std::shared_ptr const &)renderNode __attribute__((objc_direct)) { - self = [super init]; - if (self != nil) { - auto position = renderNode->layer.position(); - _position = CGPointMake(position.x, position.y); - - auto bounds = renderNode->layer.bounds(); - _bounds = CGRectMake(bounds.x, bounds.y, bounds.width, bounds.height); - - _transform = lottie::nativeTransform(renderNode->layer.transform()); - _opacity = renderNode->layer.opacity(); - _masksToBounds = renderNode->layer.masksToBounds(); - _isHidden = renderNode->layer.isHidden(); - - auto globalRect = renderNode->globalRect; - _globalRect = CGRectMake(globalRect.x, globalRect.y, globalRect.width, globalRect.height); - - _globalTransform = lottie::nativeTransform(renderNode->globalTransform); - - if (renderNode->renderContent) { - _renderContent = [[LottieRenderContent alloc] initWithRenderContent:renderNode->renderContent]; - } - - _hasSimpleContents = renderNode->drawContentDescendants <= 1; - _isInvertedMatte = renderNode->isInvertedMatte; - - if (!renderNode->subnodes.empty()) { - NSMutableArray *subnodes = [[NSMutableArray alloc] init]; - for (const auto &subnode : renderNode->subnodes) { - [subnodes addObject:[[LottieRenderNode alloc] initWithRenderNode:subnode]]; - } - _subnodes = subnodes; - } else { - _subnodes = [[NSArray alloc] init]; - } - - if (renderNode->mask) { - _mask = [[LottieRenderNode alloc] initWithRenderNode:renderNode->mask]; - } - } - return self; -} - -@end diff --git a/submodules/TelegramUI/Components/LottieCpp/Sources/LottieRenderTreeInternal.h b/submodules/TelegramUI/Components/LottieCpp/Sources/LottieRenderTreeInternal.h deleted file mode 100644 index a8b93f2746..0000000000 --- a/submodules/TelegramUI/Components/LottieCpp/Sources/LottieRenderTreeInternal.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef LottieRenderTreeInternal_h -#define LottieRenderTreeInternal_h - -#include -#import "RenderNode.hpp" - -#include - -@interface LottieRenderNode (Internal) - -- (instancetype _Nonnull)initWithRenderNode:(std::shared_ptr const &)renderNode __attribute__((objc_direct)); - -@end - -#endif /* LottieRenderTreeInternal_h */ diff --git a/submodules/TelegramUI/Components/LottieCpp/Sources/RenderNode.cpp b/submodules/TelegramUI/Components/LottieCpp/Sources/RenderNode.cpp deleted file mode 100644 index 81dd5562e4..0000000000 --- a/submodules/TelegramUI/Components/LottieCpp/Sources/RenderNode.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "RenderNode.hpp" - -namespace lottie { - -OutputRenderNode::OutputRenderNode( - LayerParams const &layer_, - CGRect const &globalRect_, - CGRect const &localRect_, - CATransform3D const &globalTransform_, - bool drawsContent_, - std::shared_ptr renderContent_, - int drawContentDescendants_, - bool isInvertedMatte_, - std::vector> const &subnodes_, - std::shared_ptr const &mask_ -) : -layer(layer_), -globalRect(globalRect_), -localRect(localRect_), -globalTransform(globalTransform_), -drawsContent(drawsContent_), -renderContent(renderContent_), -drawContentDescendants(drawContentDescendants_), -isInvertedMatte(isInvertedMatte_), -subnodes(subnodes_), -mask(mask_) { -} - -} diff --git a/submodules/TelegramUI/Components/LottieCpp/Sources/RenderNode.hpp b/submodules/TelegramUI/Components/LottieCpp/Sources/RenderNode.hpp deleted file mode 100644 index 5888390c48..0000000000 --- a/submodules/TelegramUI/Components/LottieCpp/Sources/RenderNode.hpp +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef RenderNode_hpp -#define RenderNode_hpp - -#include "Lottie/Public/Primitives/CALayer.hpp" - -namespace lottie { - -struct OutputRenderNode { - struct LayerParams { - CGRect _bounds; - Vector2D _position; - CATransform3D _transform; - double _opacity; - bool _masksToBounds; - bool _isHidden; - - LayerParams( - CGRect bounds_, - Vector2D position_, - CATransform3D transform_, - double opacity_, - bool masksToBounds_, - bool isHidden_ - ) : - _bounds(bounds_), - _position(position_), - _transform(transform_), - _opacity(opacity_), - _masksToBounds(masksToBounds_), - _isHidden(isHidden_) { - } - - LayerParams(std::shared_ptr const &layer) : - _bounds(layer->bounds()), - _position(layer->position()), - _transform(layer->transform()), - _opacity(layer->opacity()), - _masksToBounds(layer->masksToBounds()), - _isHidden(layer->isHidden()) { - } - - CGRect bounds() const { - return _bounds; - } - - Vector2D position() const { - return _position; - } - - CATransform3D transform() const { - return _transform; - } - - double opacity() const { - return _opacity; - } - - bool masksToBounds() const { - return _masksToBounds; - } - - bool isHidden() const { - return _isHidden; - } - }; - - LayerParams layer; - CGRect globalRect; - CGRect localRect; - CATransform3D globalTransform; - bool drawsContent; - std::shared_ptr renderContent; - int drawContentDescendants; - bool isInvertedMatte; - std::vector> subnodes; - std::shared_ptr mask; - - explicit OutputRenderNode( - LayerParams const &layer_, - CGRect const &globalRect_, - CGRect const &localRect_, - CATransform3D const &globalTransform_, - bool drawsContent_, - std::shared_ptr renderContent_, - int drawContentDescendants_, - bool isInvertedMatte_, - std::vector> const &subnodes_, - std::shared_ptr const &mask_ - ); -}; - -} - -#endif /* RenderNode_hpp */