include/svx/sdr/animation/animationstate.hxx | 2 + svx/source/sdr/animation/animationstate.cxx | 6 +++ svx/source/sdr/contact/viewobjectcontact.cxx | 49 +++++++++++++++++---------- 3 files changed, 40 insertions(+), 17 deletions(-)
New commits: commit 12baba92e0a581866c6dedea428e888dd0934d78 Author: Noel Grandin <[email protected]> AuthorDate: Tue Nov 25 08:19:54 2025 +0200 Commit: Noel Grandin <[email protected]> CommitDate: Tue Nov 25 11:52:46 2025 +0100 tdf#169656 Crash upon starting animated GIF this is caused by freeing an object that is currently on the callstack. I dont have a complete fix here, this will fix it 99% of the time. regression from commit e6a8c40e5051363d5825bd09131b86cf8a2b659b Author: Noel Grandin <[email protected]> Date: Tue Sep 30 14:54:37 2025 +0200 tdf#116975 Laggy behavior when clicking between table cells in impress but only because it made it more obvious, this has been a lurking problem. Change-Id: I4f2f56a54a74f2a51e7ca05421d3db82de47f2ca Reviewed-on: https://gerrit.libreoffice.org/c/core/+/194502 Tested-by: Noel Grandin <[email protected]> Tested-by: Jenkins Code-Style: Noel Grandin <[email protected]> Reviewed-by: Noel Grandin <[email protected]> diff --git a/include/svx/sdr/animation/animationstate.hxx b/include/svx/sdr/animation/animationstate.hxx index a2e079725df3..ad41a592666b 100644 --- a/include/svx/sdr/animation/animationstate.hxx +++ b/include/svx/sdr/animation/animationstate.hxx @@ -47,6 +47,8 @@ namespace sdr::animation // destructor virtual ~PrimitiveAnimation() override; + void SetPrimitives(drawinglayer::primitive2d::Primitive2DContainer&&); + // execute event, from base class Event virtual void Trigger(sal_uInt32 nTime) override; }; diff --git a/svx/source/sdr/animation/animationstate.cxx b/svx/source/sdr/animation/animationstate.cxx index 375bccaf0975..9690e25591dc 100644 --- a/svx/source/sdr/animation/animationstate.cxx +++ b/svx/source/sdr/animation/animationstate.cxx @@ -122,6 +122,12 @@ namespace sdr::animation prepareNextEvent(); } + void PrimitiveAnimation::SetPrimitives(drawinglayer::primitive2d::Primitive2DContainer&& rAnimatedPrimitives) + { + // called from ViewObjectContact::checkForPrimitive2DAnimations + maAnimatedPrimitives = std::move(rAnimatedPrimitives); + } + } // end of namespace /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sdr/contact/viewobjectcontact.cxx b/svx/source/sdr/contact/viewobjectcontact.cxx index beb2163d4f0f..b1bef068102f 100644 --- a/svx/source/sdr/contact/viewobjectcontact.cxx +++ b/svx/source/sdr/contact/viewobjectcontact.cxx @@ -287,30 +287,45 @@ void ViewObjectContact::ActionChildInserted(ViewContact& rChild) // GetObjectContact().InvalidatePartOfView(rChildVOC.getObjectRange()); } +// Check for animated primitives. void ViewObjectContact::checkForPrimitive2DAnimations() { - // remove old one - mpPrimitiveAnimation.reset(); - - // check for animated primitives - if(mxPrimitive2DSequence.empty()) - return; - - const bool bTextAnimationAllowed(GetObjectContact().IsTextAnimationAllowed()); - const bool bGraphicAnimationAllowed(GetObjectContact().IsGraphicAnimationAllowed()); - - if(bTextAnimationAllowed || bGraphicAnimationAllowed) + // Somewhat odd structure here, because we are trying to avoid deleting and re-allocating the mpPrimitiveAnimation + // object, because we might be inside a call from the Scheduler, in which case we will be deleting an object + // on the call stack. + // Yes, this does still leave a possible situation where the user could turn animations off while we are + // animating and we could crash. I dont have a better solution right now. + // + drawinglayer::primitive2d::Primitive2DContainer aNewAnimatedPrimitives; + if(!mxPrimitive2DSequence.empty()) { - AnimatedExtractingProcessor2D aAnimatedExtractor(GetObjectContact().getViewInformation2D(), - bTextAnimationAllowed, bGraphicAnimationAllowed); - aAnimatedExtractor.process(mxPrimitive2DSequence); + const bool bTextAnimationAllowed(GetObjectContact().IsTextAnimationAllowed()); + const bool bGraphicAnimationAllowed(GetObjectContact().IsGraphicAnimationAllowed()); - if(!aAnimatedExtractor.getPrimitive2DSequence().empty()) + if(bTextAnimationAllowed || bGraphicAnimationAllowed) { - // derived primitiveList is animated, setup new PrimitiveAnimation - mpPrimitiveAnimation.reset( new sdr::animation::PrimitiveAnimation(*this, aAnimatedExtractor.extractPrimitive2DSequence()) ); + AnimatedExtractingProcessor2D aAnimatedExtractor(GetObjectContact().getViewInformation2D(), + bTextAnimationAllowed, bGraphicAnimationAllowed); + aAnimatedExtractor.process(mxPrimitive2DSequence); + + if(!aAnimatedExtractor.getPrimitive2DSequence().empty()) + { + // derived primitiveList is animated, setup new PrimitiveAnimation + aNewAnimatedPrimitives = aAnimatedExtractor.extractPrimitive2DSequence(); + } } } + if (!aNewAnimatedPrimitives.empty()) + { + // derived primitiveList is animated, setup new PrimitiveAnimation + if (mpPrimitiveAnimation) + mpPrimitiveAnimation->SetPrimitives(std::move(aNewAnimatedPrimitives)); + else + mpPrimitiveAnimation.reset( new sdr::animation::PrimitiveAnimation(*this, std::move(aNewAnimatedPrimitives)) ); + } + else + // remove old one + mpPrimitiveAnimation.reset(); } void ViewObjectContact::createPrimitive2DSequence(const DisplayInfo& rDisplayInfo, drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) const
