include/svx/sdr/contact/viewobjectcontact.hxx | 3 +++ svx/source/sdr/contact/viewobjectcontact.cxx | 18 ++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-)
New commits: commit b33a4d3c4acc37b9284c611caaaa661d2fe34db8 Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Fri Dec 17 10:54:59 2021 +0200 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Fri Dec 17 11:21:25 2021 +0100 fix for crash converting ooo31011-1.sxw and tdf#146132 ./instdir/program/soffice.bin --headless --convert-to odt ./ooo31011-1.sxw regression from commit 681e10eecf67a1a01bdec2cc9b834e0345e25206 Author: Noel Grandin <noel.gran...@collabora.co.uk> Date: Thu Dec 9 11:12:49 2021 +0200 tdf#146137 tdf#146132 image redrawing It is because we cache high-level primitives, and then during paint, we decompose those high-level primitives, and that triggers layout, which triggers an invalidate i.e. an ActionChanged(), which blows away the cached data we are iterating over. Change-Id: Id18e47b6c2b71a5404f24b075a43d2040a5e3509 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126995 Tested-by: Noel Grandin <noel.gran...@collabora.co.uk> Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/include/svx/sdr/contact/viewobjectcontact.hxx b/include/svx/sdr/contact/viewobjectcontact.hxx index f13f247e55c2..7cee496afdb2 100644 --- a/include/svx/sdr/contact/viewobjectcontact.hxx +++ b/include/svx/sdr/contact/viewobjectcontact.hxx @@ -59,6 +59,9 @@ private: // possible on-demand calculated GridOffset for non-linear ViewToDevice transformation (calc) basegfx::B2DVector maGridOffset; + // used to to detect ActionChanged() during primitive construction + int mnActionChangedCount; + // This bool gets set when the object gets invalidated by ActionChanged() and // can be used from the OC to late-invalidates bool mbLazyInvalidate : 1; diff --git a/svx/source/sdr/contact/viewobjectcontact.cxx b/svx/source/sdr/contact/viewobjectcontact.cxx index 9dcac9eb153c..8b8f0c3250d7 100644 --- a/svx/source/sdr/contact/viewobjectcontact.cxx +++ b/svx/source/sdr/contact/viewobjectcontact.cxx @@ -147,6 +147,7 @@ ViewObjectContact::ViewObjectContact(ObjectContact& rObjectContact, ViewContact& : mrObjectContact(rObjectContact), mrViewContact(rViewContact), maGridOffset(0.0, 0.0), + mnActionChangedCount(0), mbLazyInvalidate(false) { // make the ViewContact remember me @@ -210,6 +211,7 @@ void ViewObjectContact::ActionChanged() { // clear cached primitives mxPrimitive2DSequence.clear(); + ++mnActionChangedCount; if(mbLazyInvalidate) return; @@ -345,7 +347,7 @@ drawinglayer::primitive2d::Primitive2DContainer const & ViewObjectContact::getPr drawinglayer::primitive2d::Primitive2DContainer xNewPrimitiveSequence; // take care of redirectors and create new list - ViewObjectContactRedirector* pRedirector = GetObjectContact().GetViewObjectContactRedirector(); + ViewObjectContactRedirector* pRedirector = GetObjectContact().GetViewObjectContactRedirector();\ if(pRedirector) { @@ -421,8 +423,8 @@ void ViewObjectContact::getPrimitive2DSequenceHierarchy(DisplayInfo& rDisplayInf if(!isPrimitiveVisible(rDisplayInfo)) return; - const drawinglayer::primitive2d::Primitive2DContainer& xRetval = getPrimitive2DSequence(rDisplayInfo); - if(xRetval.empty()) + getPrimitive2DSequence(rDisplayInfo); + if(mxPrimitive2DSequence.empty()) return; // get ranges @@ -434,7 +436,15 @@ void ViewObjectContact::getPrimitive2DSequenceHierarchy(DisplayInfo& rDisplayInf if(!bVisible) return; - rVisitor.visit(xRetval); + // temporarily take over the mxPrimitive2DSequence, in case it gets invalidated while we want to iterate over it + auto tmp = std::move(const_cast<ViewObjectContact*>(this)->mxPrimitive2DSequence); + int nPrevCount = mnActionChangedCount; + + rVisitor.visit(tmp); + + // if we received ActionChanged() calls while walking the primitives, then leave it empty, otherwise move it back + if (mnActionChangedCount == nPrevCount) + const_cast<ViewObjectContact*>(this)->mxPrimitive2DSequence = std::move(tmp); } void ViewObjectContact::getPrimitive2DSequenceSubHierarchy(DisplayInfo& rDisplayInfo, drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) const