summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/svx/sdr/contact/viewobjectcontact.hxx3
-rw-r--r--include/svx/svdmodel.hxx4
-rw-r--r--sc/source/core/data/drwlayer.cxx2
-rw-r--r--sd/source/core/drawdoc.cxx2
-rw-r--r--svx/source/sdr/contact/viewobjectcontact.cxx34
-rw-r--r--svx/source/svdraw/svdmodel.cxx1
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)