diff options
-rw-r--r-- | include/svx/sdr/contact/viewobjectcontact.hxx | 3 | ||||
-rw-r--r-- | include/svx/svdmodel.hxx | 4 | ||||
-rw-r--r-- | sc/source/core/data/drwlayer.cxx | 2 | ||||
-rw-r--r-- | sd/source/core/drawdoc.cxx | 2 | ||||
-rw-r--r-- | svx/source/sdr/contact/viewobjectcontact.cxx | 34 | ||||
-rw-r--r-- | svx/source/svdraw/svdmodel.cxx | 1 |
6 files changed, 40 insertions, 6 deletions
diff --git a/include/svx/sdr/contact/viewobjectcontact.hxx b/include/svx/sdr/contact/viewobjectcontact.hxx index f13f247e55c2..1be4cac81052 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 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/include/svx/svdmodel.hxx b/include/svx/svdmodel.hxx index 831201de4d60..2170f78907ed 100644 --- a/include/svx/svdmodel.hxx +++ b/include/svx/svdmodel.hxx @@ -210,6 +210,7 @@ protected: bool m_bPasteResize:1; // Objects are being resized due to Paste with different MapMode bool m_bStarDrawPreviewMode:1; bool mbDisableTextEditUsesCommonUndoManager:1; + bool mbVOCInvalidationIsReliable:1; // does the app reliably invalidate the VOC, or do we need to rebuild the primitives on every render? sal_uInt16 m_nDefaultTabulator; sal_uInt32 m_nMaxUndoCount; @@ -612,6 +613,9 @@ public: virtual sal_Int32 getImagePreferredDPI() const { return 0; } virtual void dumpAsXml(xmlTextWriterPtr pWriter) const; + + bool IsVOCInvalidationIsReliable() const { return mbVOCInvalidationIsReliable; } + void SetVOCInvalidationIsReliable(bool b) { mbVOCInvalidationIsReliable = b; } }; /* diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx index 3503ae9cd949..e5a11b57555e 100644 --- a/sc/source/core/data/drwlayer.cxx +++ b/sc/source/core/data/drwlayer.cxx @@ -239,6 +239,8 @@ ScDrawLayer::ScDrawLayer( ScDocument* pDocument, const OUString& rName ) : bAdjustEnabled( true ), bHyphenatorSet( false ) { + SetVOCInvalidationIsReliable(true); + pGlobalDrawPersist = nullptr; // Only use once SfxObjectShell* pObjSh = pDocument ? pDocument->GetDocumentShell() : nullptr; diff --git a/sd/source/core/drawdoc.cxx b/sd/source/core/drawdoc.cxx index d765e3639288..0e7ad9dabd44 100644 --- a/sd/source/core/drawdoc.cxx +++ b/sd/source/core/drawdoc.cxx @@ -139,6 +139,8 @@ SdDrawDocument::SdDrawDocument(DocumentType eType, SfxObjectShell* pDrDocSh) , mbEmbedFontScriptComplex(true) , mnImagePreferredDPI(0) { + SetVOCInvalidationIsReliable(true); + mpDrawPageListWatcher.reset(new ImpDrawPageListWatcher(*this)); mpMasterPageListWatcher.reset(new ImpMasterPageListWatcher(*this)); diff --git a/svx/source/sdr/contact/viewobjectcontact.cxx b/svx/source/sdr/contact/viewobjectcontact.cxx index 1dd8fef29415..6577b784f446 100644 --- a/svx/source/sdr/contact/viewobjectcontact.cxx +++ b/svx/source/sdr/contact/viewobjectcontact.cxx @@ -29,6 +29,8 @@ #include <drawinglayer/processor2d/baseprocessor2d.hxx> #include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx> #include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdmodel.hxx> using namespace com::sun::star; @@ -147,6 +149,7 @@ ViewObjectContact::ViewObjectContact(ObjectContact& rObjectContact, ViewContact& : mrObjectContact(rObjectContact), mrViewContact(rViewContact), maGridOffset(0.0, 0.0), + mnActionChangedCount(0), mbLazyInvalidate(false) { // make the ViewContact remember me @@ -193,7 +196,7 @@ const basegfx::B2DRange& ViewObjectContact::getObjectRange() const { // if range is not computed (new or LazyInvalidate objects), force it const DisplayInfo aDisplayInfo; - const drawinglayer::primitive2d::Primitive2DContainer xSequence(getPrimitive2DSequence(aDisplayInfo)); + const drawinglayer::primitive2d::Primitive2DContainer& xSequence(getPrimitive2DSequence(aDisplayInfo)); if(!xSequence.empty()) { @@ -208,6 +211,10 @@ const basegfx::B2DRange& ViewObjectContact::getObjectRange() const void ViewObjectContact::ActionChanged() { + // clear cached primitives + mxPrimitive2DSequence.clear(); + ++mnActionChangedCount; + if(mbLazyInvalidate) return; @@ -330,6 +337,14 @@ void ViewObjectContact::createPrimitive2DSequence(const DisplayInfo& rDisplayInf drawinglayer::primitive2d::Primitive2DContainer const & ViewObjectContact::getPrimitive2DSequence(const DisplayInfo& rDisplayInfo) const { + // only some of the top-level apps are any good at reliably invalidating us (e.g. writer is not) + if (SdrObject* pSdrObj = mrViewContact.TryToGetSdrObject()) + if (pSdrObj->getSdrModelFromSdrObject().IsVOCInvalidationIsReliable()) + { + if (!mxPrimitive2DSequence.empty()) + return mxPrimitive2DSequence; + } + /** This method is weird because (1) we have to re-walk the primitive tree because the flushing is unreliable @@ -415,21 +430,28 @@ void ViewObjectContact::getPrimitive2DSequenceHierarchy(DisplayInfo& rDisplayInf if(!isPrimitiveVisible(rDisplayInfo)) return; - drawinglayer::primitive2d::Primitive2DContainer xRetval = getPrimitive2DSequence(rDisplayInfo); - if(xRetval.empty()) + getPrimitive2DSequence(rDisplayInfo); + if(mxPrimitive2DSequence.empty()) return; // get ranges const drawinglayer::geometry::ViewInformation2D& rViewInformation2D(GetObjectContact().getViewInformation2D()); - const basegfx::B2DRange aObjectRange(xRetval.getB2DRange(rViewInformation2D)); const basegfx::B2DRange& aViewRange(rViewInformation2D.getViewport()); // check geometrical visibility - bool bVisible = aViewRange.isEmpty() || aViewRange.overlaps(aObjectRange); + bool bVisible = aViewRange.isEmpty() || aViewRange.overlaps(maObjectRange); if(!bVisible) return; - rVisitor.visit(std::move(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 diff --git a/svx/source/svdraw/svdmodel.cxx b/svx/source/svdraw/svdmodel.cxx index 8a19ce2b27a7..e8d69ab8412a 100644 --- a/svx/source/svdraw/svdmodel.cxx +++ b/svx/source/svdraw/svdmodel.cxx @@ -121,6 +121,7 @@ SdrModel::SdrModel(SfxItemPool* pPool, comphelper::IEmbeddedHelper* pEmbeddedHel , m_bPasteResize(false) , m_bStarDrawPreviewMode(false) , mbDisableTextEditUsesCommonUndoManager(false) + , mbVOCInvalidationIsReliable(false) , m_nDefaultTabulator(0) , m_nMaxUndoCount(16) , m_pTextChain(new TextChain) |