[Libreoffice-commits] core.git: Branch 'distro/lhm/libreoffice-5-2+backports' - 5 commits - drawinglayer/source include/drawinglayer svx/source sw/inc sw/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Thu Aug 9 11:24:00 UTC 2018


 drawinglayer/source/primitive2d/textlayoutdevice.cxx  |    4 
 include/drawinglayer/primitive2d/textlayoutdevice.hxx |    2 
 svx/source/svdraw/svdotextdecomposition.cxx           |    5 
 sw/inc/ndole.hxx                                      |   17 +
 sw/source/core/doc/notxtfrm.cxx                       |   37 +-
 sw/source/core/ole/ndole.cxx                          |  234 +++++++++++++++++-
 6 files changed, 270 insertions(+), 29 deletions(-)

New commits:
commit 949ecd96e8bec1709b89bca6177a1fbba6cc6f94
Author:     Armin Le Grand <Armin.Le.Grand at cib.de>
AuthorDate: Thu Jul 7 10:16:02 2016 +0200
Commit:     Armin Le Grand <Armin.Le.Grand at cib.de>
CommitDate: Thu Aug 9 13:20:02 2018 +0200

    Related: tdf#50613 use an own instance of ThreadPool
    
    Using the global ThreadPool (getSharedOptimalPool()) can lead to
    problems when more than one usage executes and one of them
    already calls waitUntilEmpty() what of course influences the
    other usage. Thus I added an own instance of ThreadPool for
    async loading of chart models in writer
    
    Change-Id: I4bea64af0d36e87081abec95c75574966d0fe5b9

diff --git a/sw/source/core/ole/ndole.cxx b/sw/source/core/ole/ndole.cxx
index 903d96814bc1..1be81749133e 100644
--- a/sw/source/core/ole/ndole.cxx
+++ b/sw/source/core/ole/ndole.cxx
@@ -676,7 +676,36 @@ void SwOLENode::SetChanged()
     }
 }
 //////////////////////////////////////////////////////////////////////////////
+// due to some problems in test cases with the SharedOptimalPool, use
+// an own instance of comphelper::ThreadPool. Problem is that other
+// usages of getSharedOptimalPool() may interfere if more than one
+// pool user calls waitUntilEmpty().
+//
+// It gets created on-demand and will be available during LO's
+// lifetime for loading chart models used in writer in parallel.  It
+// would be possible to add a usage count, then trigger a timer and
+// clean it up (due to lifetime issues), but that's probably overkill.
+// It gets created on demand, is ready for global reuse and makes no
+// harm (not much ressources needed)
+static comphelper::ThreadPool* pLocalPool = 0;
+
+comphelper::ThreadPool* getLocalThreadPool()
+{
+    if (pLocalPool)
+    {
+        return pLocalPool;
+    }
+
+    if (0 == comphelper::ThreadPool::getSharedOptimalPool().getWorkerCount())
+    {
+        return nullptr;
+    }
+
+    pLocalPool = new comphelper::ThreadPool(comphelper::ThreadPool::getSharedOptimalPool().getWorkerCount());
+    return pLocalPool;
+}
 
+/// Holder for local data for a parallely-executed task to load a chart model
 class DeflateData
 {
 private:
@@ -734,8 +763,7 @@ public:
     }
 };
 
-//////////////////////////////////////////////////////////////////////////////
-
+/// Task for parallely-executed task to load a chart model
 class DeflateThread : public comphelper::ThreadTask
 {
     // the data to work on
@@ -1080,11 +1108,14 @@ drawinglayer::primitive2d::Primitive2DContainer SwOLEObj::tryToGetChartContentAs
 
         if(aXModel.is())
         {
+            // loaded using own instance of comphelper::ThreadPool,
+            // see getLocalThreadPool(). Disable via bool below if
+            // trouble surfaces somewhere
             static bool bAnynchronousLoadingAllowed = true;
 
             if(bSynchron ||
                 !bAnynchronousLoadingAllowed ||
-                0 == comphelper::ThreadPool::getSharedOptimalPool().getWorkerCount())
+                nullptr == getLocalThreadPool())
             {
                 // load chart synchron in this Thread
                 m_aPrimitive2DSequence = ChartHelper::tryToGetChartContentAsPrimitive2DSequence(
@@ -1100,7 +1131,7 @@ drawinglayer::primitive2d::Primitive2DContainer SwOLEObj::tryToGetChartContentAs
                 {
                     m_pDeflateData = new DeflateData(aXModel);
                     DeflateThread* pNew = new DeflateThread(*m_pDeflateData);
-                    comphelper::ThreadPool::getSharedOptimalPool().pushTask(pNew);
+                    getLocalThreadPool()->pushTask(pNew);
                 }
             }
         }
commit 2f91c89baae9b0cf9e11cff02cf56338ebdda177
Author:     Armin Le Grand <Armin.Le.Grand at cib.de>
AuthorDate: Fri Jul 1 15:10:00 2016 +0200
Commit:     Armin Le Grand <Armin.Le.Grand at cib.de>
CommitDate: Thu Aug 9 13:19:52 2018 +0200

    sw: tdf#50613 fix async chart load handling
    
    Especially if synchronous loading is requested, an async worker is on the way
    and we would need to 'wait' for the data.
    
    Change-Id: I20f9938738c1b46bda6b9a7f5a761e82153aed3b

diff --git a/sw/inc/ndole.hxx b/sw/inc/ndole.hxx
index b6af9fb81b59..9f90c7ddad46 100644
--- a/sw/inc/ndole.hxx
+++ b/sw/inc/ndole.hxx
@@ -45,7 +45,7 @@ class SW_DLLPUBLIC SwOLEObj
     // eventually buffered data if it is a chart OLE
     drawinglayer::primitive2d::Primitive2DContainer     m_aPrimitive2DSequence;
     basegfx::B2DRange                                   m_aRange;
-    class DeflateData*                                  m_aDeflateData;
+    class DeflateData*                                  m_pDeflateData;
 
     SwOLEObj( const SwOLEObj& rObj ) = delete;
 
diff --git a/sw/source/core/ole/ndole.cxx b/sw/source/core/ole/ndole.cxx
index d9cee6150602..903d96814bc1 100644
--- a/sw/source/core/ole/ndole.cxx
+++ b/sw/source/core/ole/ndole.cxx
@@ -681,18 +681,27 @@ class DeflateData
 {
 private:
     friend class DeflateThread;
+    friend class SwOLEObj;
 
-    const uno::Reference< frame::XModel >               maXModel;
+    uno::Reference< frame::XModel >                     maXModel;
     drawinglayer::primitive2d::Primitive2DContainer     maPrimitive2DSequence;
     basegfx::B2DRange                                   maRange;
+
+    // set from the WorkerThread when done
     std::atomic< bool>                                  mbFinished;
 
+    // evtl.set from the SwOLEObj destructor when a WorkerThread is still active
+    // since it is not possible to kill it - let it terminate and delete the
+    // data working on itself
+    std::atomic< bool>                                  mbKilled;
+
 public:
     DeflateData(const uno::Reference< frame::XModel >& rXModel)
     :   maXModel(rXModel),
         maPrimitive2DSequence(),
         maRange(),
-        mbFinished(false)
+        mbFinished(false),
+        mbKilled(false)
     {
     }
 
@@ -713,11 +722,14 @@ public:
 
     void waitFinished()
     {
-        const TimeValue aTimeValue(0, 100000); // 1/10th second
-
-        while(!mbFinished)
+        while(!mbFinished && !mbKilled)
         {
-            osl_waitThread(&aTimeValue);
+            // need to wait until the load in progress is finished.
+            // to do so, Application::Yield() is needed since the execution
+            // here means that the SolarMutex is locked, but the
+            // WorkerThreads need it to be able to continue and finish
+            // the running import
+            Application::Yield();
         }
     }
 };
@@ -726,6 +738,7 @@ public:
 
 class DeflateThread : public comphelper::ThreadTask
 {
+    // the data to work on
     DeflateData&            mrDeflateData;
 
 public:
@@ -739,14 +752,24 @@ private:
     {
         try
         {
+            // load the chart data and get the primitives
             mrDeflateData.maPrimitive2DSequence = ChartHelper::tryToGetChartContentAsPrimitive2DSequence(
                 mrDeflateData.maXModel,
                 mrDeflateData.maRange);
+
+            // model no longer needed and done
+            mrDeflateData.maXModel.clear();
             mrDeflateData.mbFinished = true;
         }
         catch (const uno::Exception&)
         {
         }
+
+        if(mrDeflateData.mbKilled)
+        {
+            // need to cleanup myself - data will not be used
+            delete &mrDeflateData;
+        }
     }
 };
 
@@ -758,7 +781,7 @@ SwOLEObj::SwOLEObj( const svt::EmbeddedObjectRef& xObj ) :
     xOLERef( xObj ),
     m_aPrimitive2DSequence(),
     m_aRange(),
-    m_aDeflateData(nullptr)
+    m_pDeflateData(nullptr)
 {
     xOLERef.Lock();
     if ( xObj.is() )
@@ -775,7 +798,7 @@ SwOLEObj::SwOLEObj( const OUString &rString, sal_Int64 nAspect ) :
     aName( rString ),
     m_aPrimitive2DSequence(),
     m_aRange(),
-    m_aDeflateData(nullptr)
+    m_pDeflateData(nullptr)
 {
     xOLERef.Lock();
     xOLERef.SetViewAspect( nAspect );
@@ -783,10 +806,12 @@ SwOLEObj::SwOLEObj( const OUString &rString, sal_Int64 nAspect ) :
 
 SwOLEObj::~SwOLEObj()
 {
-    if(m_aDeflateData)
+    if(m_pDeflateData)
     {
-        m_aDeflateData->waitFinished();
-        delete m_aDeflateData;
+        // set flag so that the worker thread will delete m_pDeflateData
+        // when finished and forget about it
+        m_pDeflateData->mbKilled = true;
+        m_pDeflateData = nullptr;
     }
 
     if( pListener )
@@ -1030,19 +1055,22 @@ drawinglayer::primitive2d::Primitive2DContainer SwOLEObj::tryToGetChartContentAs
     basegfx::B2DRange& rRange,
     bool bSynchron)
 {
-    if(m_aDeflateData)
+    if(m_pDeflateData)
     {
         if(bSynchron)
         {
-            m_aDeflateData->waitFinished();
+            // data in high quality is requested, wait until the data is available
+            // since a WorkerThread was already started to load it
+            m_pDeflateData->waitFinished();
         }
 
-        if(m_aDeflateData->isFinished())
+        if(m_pDeflateData->isFinished())
         {
-            m_aPrimitive2DSequence = m_aDeflateData->getSequence();
-            m_aRange = m_aDeflateData->getRange();
-            delete m_aDeflateData;
-            m_aDeflateData = nullptr;
+            // copy the result data and cleanup
+            m_aPrimitive2DSequence = m_pDeflateData->getSequence();
+            m_aRange = m_pDeflateData->getRange();
+            delete m_pDeflateData;
+            m_pDeflateData = nullptr;
         }
     }
 
@@ -1054,18 +1082,24 @@ drawinglayer::primitive2d::Primitive2DContainer SwOLEObj::tryToGetChartContentAs
         {
             static bool bAnynchronousLoadingAllowed = true;
 
-            if(bSynchron || !bAnynchronousLoadingAllowed)
+            if(bSynchron ||
+                !bAnynchronousLoadingAllowed ||
+                0 == comphelper::ThreadPool::getSharedOptimalPool().getWorkerCount())
             {
+                // load chart synchron in this Thread
                 m_aPrimitive2DSequence = ChartHelper::tryToGetChartContentAsPrimitive2DSequence(
                     aXModel,
                     m_aRange);
             }
             else
             {
-                if(!m_aDeflateData)
+                // if not yet setup, initiate and start a WorkerThread to load the chart
+                // and it's primitives asynchron. If it already works, returning nothing
+                // is okay (preview will be reused)
+                if(!m_pDeflateData)
                 {
-                    m_aDeflateData = new DeflateData(aXModel);
-                    DeflateThread* pNew = new DeflateThread(*m_aDeflateData);
+                    m_pDeflateData = new DeflateData(aXModel);
+                    DeflateThread* pNew = new DeflateThread(*m_pDeflateData);
                     comphelper::ThreadPool::getSharedOptimalPool().pushTask(pNew);
                 }
             }
@@ -1074,6 +1108,7 @@ drawinglayer::primitive2d::Primitive2DContainer SwOLEObj::tryToGetChartContentAs
 
     if(!m_aPrimitive2DSequence.empty() && !m_aRange.isEmpty())
     {
+        // when we have data, also copy the buffered Range data as output
         rRange = m_aRange;
     }
 
@@ -1085,11 +1120,12 @@ void SwOLEObj::resetBufferedData()
     m_aPrimitive2DSequence = drawinglayer::primitive2d::Primitive2DContainer();
     m_aRange.reset();
 
-    if(m_aDeflateData)
+    if(m_pDeflateData)
     {
-        m_aDeflateData->waitFinished();
-        delete m_aDeflateData;
-        m_aDeflateData = nullptr;
+        // load is in progress, wait until finished and cleanup without using it
+        m_pDeflateData->waitFinished();
+        delete m_pDeflateData;
+        m_pDeflateData = nullptr;
     }
 }
 
commit 6296e5ff06acb09b61ce731c6f820f35a695ee8a
Author:     Armin Le Grand <Armin.Le.Grand at cib.de>
AuthorDate: Fri Jul 1 14:50:00 2016 +0200
Commit:     Armin Le Grand <Armin.Le.Grand at cib.de>
CommitDate: Thu Aug 9 13:19:43 2018 +0200

    sw: tdf#50613 fix waitFinished into a loop
    
    Change-Id: Ic8a720657c326d8d51bb3a73688b8f02b7096488

diff --git a/sw/source/core/ole/ndole.cxx b/sw/source/core/ole/ndole.cxx
index 1e006320ece7..d9cee6150602 100644
--- a/sw/source/core/ole/ndole.cxx
+++ b/sw/source/core/ole/ndole.cxx
@@ -713,9 +713,10 @@ public:
 
     void waitFinished()
     {
-        if(!mbFinished)
+        const TimeValue aTimeValue(0, 100000); // 1/10th second
+
+        while(!mbFinished)
         {
-            const TimeValue aTimeValue(0, 100000); // 1/10th second
             osl_waitThread(&aTimeValue);
         }
     }
commit 385bba95ec2c5bc87aac4e2b2d2b458b05f68dd7
Author:     Armin Le Grand <Armin.Le.Grand at cib.de>
AuthorDate: Fri Jul 1 14:40:00 2016 +0200
Commit:     Armin Le Grand <Armin.Le.Grand at cib.de>
CommitDate: Thu Aug 9 13:19:33 2018 +0200

    tdf#50613 add support to load charts asynchronously
    
    Generating primitives for chart visualisation can be moved to a
    paralell executed task that loads the chart, thus speeding up
    initial visualization. This is not possible for e.g. PDF or print
    targets, only for edit visualization. On fallback, the replacement
    images of the charts are used which are metafiles and have less
    quality as primitives, but load quicker.
    
    Change-Id: I68caa9e1bec50832bce535b5f54633d53cdef037

diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
index 74067efb9569..7bbfdfaf3b6b 100644
--- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx
+++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
@@ -85,7 +85,6 @@ namespace
     ImpTimedRefDev::~ImpTimedRefDev()
     {
         OSL_ENSURE(0L == mnUseCount, "destruction of a still used ImpTimedRefDev (!)");
-        const SolarMutexGuard aGuard;
         mpVirDev.disposeAndClear();
     }
 
@@ -152,7 +151,8 @@ namespace drawinglayer
         }
 
         TextLayouterDevice::TextLayouterDevice()
-        :   mrDevice(acquireGlobalVirtualDevice())
+        :   maSolarGuard(),
+            mrDevice(acquireGlobalVirtualDevice())
         {
         }
 
diff --git a/include/drawinglayer/primitive2d/textlayoutdevice.hxx b/include/drawinglayer/primitive2d/textlayoutdevice.hxx
index e606f099a607..5761d3a03a9d 100644
--- a/include/drawinglayer/primitive2d/textlayoutdevice.hxx
+++ b/include/drawinglayer/primitive2d/textlayoutdevice.hxx
@@ -26,6 +26,7 @@
 #include <vector>
 #include <com/sun/star/lang/Locale.hpp>
 #include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <vcl/svapp.hxx>
 
 // predefines
 class VirtualDevice;
@@ -57,6 +58,7 @@ namespace drawinglayer
         class DRAWINGLAYER_DLLPUBLIC TextLayouterDevice
         {
             /// internally used VirtualDevice
+            SolarMutexGuard                 maSolarGuard;
             VirtualDevice&                  mrDevice;
 
         public:
diff --git a/svx/source/svdraw/svdotextdecomposition.cxx b/svx/source/svdraw/svdotextdecomposition.cxx
index c571f2a26ba8..efa1ea221b6f 100644
--- a/svx/source/svdraw/svdotextdecomposition.cxx
+++ b/svx/source/svdraw/svdotextdecomposition.cxx
@@ -694,6 +694,7 @@ void SdrTextObj::impDecomposeContourTextPrimitive(
     aPolyPolygon.transform(basegfx::tools::createScaleB2DHomMatrix(fabs(aScale.getX()), fabs(aScale.getY())));
 
     // prepare outliner
+    SolarMutexGuard aSolarGuard;
     SdrOutliner& rOutliner = ImpGetDrawOutliner();
     const Size aNullSize;
     rOutliner.SetPaperSize(aNullSize);
@@ -745,6 +746,7 @@ void SdrTextObj::impDecomposeAutoFitTextPrimitive(
 
     // prepare outliner
     const SfxItemSet& rTextItemSet = rSdrAutofitTextPrimitive.getSdrText()->GetItemSet();
+    SolarMutexGuard aSolarGuard;
     SdrOutliner& rOutliner = ImpGetDrawOutliner();
     SdrTextVertAdjust eVAdj = GetTextVerticalAdjust(rTextItemSet);
     SdrTextHorzAdjust eHAdj = GetTextHorizontalAdjust(rTextItemSet);
@@ -879,6 +881,7 @@ void SdrTextObj::impDecomposeBlockTextPrimitive(
 
     // prepare outliner
     const bool bIsCell(rSdrBlockTextPrimitive.getCellText());
+    SolarMutexGuard aSolarGuard;
     SdrOutliner& rOutliner = ImpGetDrawOutliner();
     SdrTextHorzAdjust eHAdj = rSdrBlockTextPrimitive.getSdrTextHorzAdjust();
     SdrTextVertAdjust eVAdj = rSdrBlockTextPrimitive.getSdrTextVertAdjust();
@@ -1127,6 +1130,7 @@ void SdrTextObj::impDecomposeStretchTextPrimitive(
     aAnchorTextRange.expand(aTranslate + aScale);
 
     // prepare outliner
+    SolarMutexGuard aSolarGuard;
     SdrOutliner& rOutliner = ImpGetDrawOutliner();
     const EEControlBits nOriginalControlWord(rOutliner.GetControlWord());
     const Size aNullSize;
@@ -1486,6 +1490,7 @@ void SdrTextObj::impDecomposeChainedTextPrimitive(
 
     // prepare outliner
     const SfxItemSet& rTextItemSet = rSdrChainedTextPrimitive.getSdrText()->GetItemSet();
+    SolarMutexGuard aSolarGuard;
     SdrOutliner& rOutliner = ImpGetDrawOutliner();
 
     SdrTextVertAdjust eVAdj = GetTextVerticalAdjust(rTextItemSet);
diff --git a/sw/inc/ndole.hxx b/sw/inc/ndole.hxx
index 53de1090f94b..b6af9fb81b59 100644
--- a/sw/inc/ndole.hxx
+++ b/sw/inc/ndole.hxx
@@ -20,15 +20,16 @@
 #define INCLUDED_SW_INC_NDOLE_HXX
 
 #include <ndnotxt.hxx>
-
 #include <svtools/embedhlp.hxx>
+#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
 
 class SwGrfFormatColl;
 class SwDoc;
 class SwOLENode;
-
 class SwOLEListener_Impl;
 class SwEmbedObjectLink;
+class DeflateData;
+
 class SW_DLLPUBLIC SwOLEObj
 {
     friend class SwOLENode;
@@ -44,6 +45,7 @@ class SW_DLLPUBLIC SwOLEObj
     // eventually buffered data if it is a chart OLE
     drawinglayer::primitive2d::Primitive2DContainer     m_aPrimitive2DSequence;
     basegfx::B2DRange                                   m_aRange;
+    class DeflateData*                                  m_aDeflateData;
 
     SwOLEObj( const SwOLEObj& rObj ) = delete;
 
@@ -69,7 +71,9 @@ public:
 
     // try to get OLE visualization in form of a Primitive2DSequence
     // and the corresponding B2DRange. This data may be locally buffered
-    drawinglayer::primitive2d::Primitive2DContainer tryToGetChartContentAsPrimitive2DSequence(basegfx::B2DRange& rRange);
+    drawinglayer::primitive2d::Primitive2DContainer tryToGetChartContentAsPrimitive2DSequence(
+        basegfx::B2DRange& rRange,
+        bool bSynchron);
     void resetBufferedData();
 };
 
diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx
index 555fd46bd69d..d5544d3928f0 100644
--- a/sw/source/core/doc/notxtfrm.cxx
+++ b/sw/source/core/doc/notxtfrm.cxx
@@ -1036,7 +1036,8 @@ void SwNoTextFrame::PaintPicture( vcl::RenderContext* pOut, const SwRect &rGrfAr
             basegfx::B2DRange aSourceRange;
             const drawinglayer::primitive2d::Primitive2DContainer aSequence(
                 pOLENd->GetOLEObj().tryToGetChartContentAsPrimitive2DSequence(
-                    aSourceRange));
+                    aSourceRange,
+                    bPrn));
 
             if(!aSequence.empty() && !aSourceRange.isEmpty())
             {
diff --git a/sw/source/core/ole/ndole.cxx b/sw/source/core/ole/ndole.cxx
index 354c3404b427..1e006320ece7 100644
--- a/sw/source/core/ole/ndole.cxx
+++ b/sw/source/core/ole/ndole.cxx
@@ -58,7 +58,8 @@
 #include <vcl/graphicfilter.hxx>
 #include <comcore.hrc>
 #include <svx/charthelper.hxx>
-
+#include <comphelper/threadpool.hxx>
+#include <atomic>
 #include <deque>
 
 using namespace utl;
@@ -674,13 +675,89 @@ void SwOLENode::SetChanged()
         }
     }
 }
+//////////////////////////////////////////////////////////////////////////////
+
+class DeflateData
+{
+private:
+    friend class DeflateThread;
+
+    const uno::Reference< frame::XModel >               maXModel;
+    drawinglayer::primitive2d::Primitive2DContainer     maPrimitive2DSequence;
+    basegfx::B2DRange                                   maRange;
+    std::atomic< bool>                                  mbFinished;
+
+public:
+    DeflateData(const uno::Reference< frame::XModel >& rXModel)
+    :   maXModel(rXModel),
+        maPrimitive2DSequence(),
+        maRange(),
+        mbFinished(false)
+    {
+    }
+
+    const drawinglayer::primitive2d::Primitive2DContainer& getSequence() const
+    {
+        return maPrimitive2DSequence;
+    }
+
+    const basegfx::B2DRange& getRange() const
+    {
+        return maRange;
+    }
+
+    bool isFinished() const
+    {
+        return mbFinished;
+    }
+
+    void waitFinished()
+    {
+        if(!mbFinished)
+        {
+            const TimeValue aTimeValue(0, 100000); // 1/10th second
+            osl_waitThread(&aTimeValue);
+        }
+    }
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+class DeflateThread : public comphelper::ThreadTask
+{
+    DeflateData&            mrDeflateData;
+
+public:
+    DeflateThread(DeflateData& rDeflateData)
+    :   mrDeflateData(rDeflateData)
+    {
+    }
+
+private:
+    virtual void doWork() override
+    {
+        try
+        {
+            mrDeflateData.maPrimitive2DSequence = ChartHelper::tryToGetChartContentAsPrimitive2DSequence(
+                mrDeflateData.maXModel,
+                mrDeflateData.maRange);
+            mrDeflateData.mbFinished = true;
+        }
+        catch (const uno::Exception&)
+        {
+        }
+    }
+};
+
+//////////////////////////////////////////////////////////////////////////////
 
 SwOLEObj::SwOLEObj( const svt::EmbeddedObjectRef& xObj ) :
     pOLENd( nullptr ),
     pListener( nullptr ),
     xOLERef( xObj ),
     m_aPrimitive2DSequence(),
-    m_aRange()
+    m_aRange(),
+    m_aDeflateData(nullptr)
 {
     xOLERef.Lock();
     if ( xObj.is() )
@@ -696,7 +773,8 @@ SwOLEObj::SwOLEObj( const OUString &rString, sal_Int64 nAspect ) :
     pListener( nullptr ),
     aName( rString ),
     m_aPrimitive2DSequence(),
-    m_aRange()
+    m_aRange(),
+    m_aDeflateData(nullptr)
 {
     xOLERef.Lock();
     xOLERef.SetViewAspect( nAspect );
@@ -704,6 +782,12 @@ SwOLEObj::SwOLEObj( const OUString &rString, sal_Int64 nAspect ) :
 
 SwOLEObj::~SwOLEObj()
 {
+    if(m_aDeflateData)
+    {
+        m_aDeflateData->waitFinished();
+        delete m_aDeflateData;
+    }
+
     if( pListener )
     {
         if ( xOLERef.is() )
@@ -941,17 +1025,49 @@ OUString SwOLEObj::GetDescription()
     return SW_RESSTR(STR_OLE);
 }
 
-drawinglayer::primitive2d::Primitive2DContainer SwOLEObj::tryToGetChartContentAsPrimitive2DSequence(basegfx::B2DRange& rRange)
+drawinglayer::primitive2d::Primitive2DContainer SwOLEObj::tryToGetChartContentAsPrimitive2DSequence(
+    basegfx::B2DRange& rRange,
+    bool bSynchron)
 {
+    if(m_aDeflateData)
+    {
+        if(bSynchron)
+        {
+            m_aDeflateData->waitFinished();
+        }
+
+        if(m_aDeflateData->isFinished())
+        {
+            m_aPrimitive2DSequence = m_aDeflateData->getSequence();
+            m_aRange = m_aDeflateData->getRange();
+            delete m_aDeflateData;
+            m_aDeflateData = nullptr;
+        }
+    }
+
     if(m_aPrimitive2DSequence.empty() && m_aRange.isEmpty() && xOLERef.is() && xOLERef.IsChart())
     {
         const uno::Reference< frame::XModel > aXModel(xOLERef->getComponent(), uno::UNO_QUERY);
 
         if(aXModel.is())
         {
-            m_aPrimitive2DSequence = ChartHelper::tryToGetChartContentAsPrimitive2DSequence(
-                aXModel,
-                m_aRange);
+            static bool bAnynchronousLoadingAllowed = true;
+
+            if(bSynchron || !bAnynchronousLoadingAllowed)
+            {
+                m_aPrimitive2DSequence = ChartHelper::tryToGetChartContentAsPrimitive2DSequence(
+                    aXModel,
+                    m_aRange);
+            }
+            else
+            {
+                if(!m_aDeflateData)
+                {
+                    m_aDeflateData = new DeflateData(aXModel);
+                    DeflateThread* pNew = new DeflateThread(*m_aDeflateData);
+                    comphelper::ThreadPool::getSharedOptimalPool().pushTask(pNew);
+                }
+            }
         }
     }
 
@@ -967,6 +1083,13 @@ void SwOLEObj::resetBufferedData()
 {
     m_aPrimitive2DSequence = drawinglayer::primitive2d::Primitive2DContainer();
     m_aRange.reset();
+
+    if(m_aDeflateData)
+    {
+        m_aDeflateData->waitFinished();
+        delete m_aDeflateData;
+        m_aDeflateData = nullptr;
+    }
 }
 
 SwOLELRUCache::SwOLELRUCache()
commit fd80334e0d9b6a0351278175e640659c779a93da
Author:     Armin Le Grand <Armin.Le.Grand at cib.de>
AuthorDate: Fri Jul 1 14:20:00 2016 +0200
Commit:     Armin Le Grand <Armin.Le.Grand at cib.de>
CommitDate: Thu Aug 9 13:19:23 2018 +0200

    tdf#50613 buffer OLE primitives for charts
    
    If OLE is a chart, buffer the primitives used for presentation as
    info at the SwOLEObj, after getting them the first time using the
    ChartHelper.
    
    Change-Id: I6d7486185f6eac450de9328d37ea800f424f351b

diff --git a/sw/inc/ndole.hxx b/sw/inc/ndole.hxx
index a1f25902d0ed..53de1090f94b 100644
--- a/sw/inc/ndole.hxx
+++ b/sw/inc/ndole.hxx
@@ -41,6 +41,10 @@ class SW_DLLPUBLIC SwOLEObj
     svt::EmbeddedObjectRef xOLERef;
     OUString aName;
 
+    // eventually buffered data if it is a chart OLE
+    drawinglayer::primitive2d::Primitive2DContainer     m_aPrimitive2DSequence;
+    basegfx::B2DRange                                   m_aRange;
+
     SwOLEObj( const SwOLEObj& rObj ) = delete;
 
     void SetNode( SwOLENode* pNode );
@@ -62,6 +66,11 @@ public:
     const OUString& GetCurrentPersistName() const { return aName; }
     OUString GetStyleString();
     bool IsOleRef() const;  ///< To avoid unnecessary loading of object.
+
+    // try to get OLE visualization in form of a Primitive2DSequence
+    // and the corresponding B2DRange. This data may be locally buffered
+    drawinglayer::primitive2d::Primitive2DContainer tryToGetChartContentAsPrimitive2DSequence(basegfx::B2DRange& rRange);
+    void resetBufferedData();
 };
 
 // SwOLENode
diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx
index ebb083ac2741..555fd46bd69d 100644
--- a/sw/source/core/doc/notxtfrm.cxx
+++ b/sw/source/core/doc/notxtfrm.cxx
@@ -69,7 +69,6 @@
 #include <com/sun/star/embed/EmbedMisc.hpp>
 #include <com/sun/star/embed/EmbedStates.hpp>
 #include <svtools/embedhlp.hxx>
-#include <svx/charthelper.hxx>
 #include <dview.hxx>
 #include <basegfx/matrix/b2dhommatrix.hxx>
 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
@@ -1034,29 +1033,22 @@ void SwNoTextFrame::PaintPicture( vcl::RenderContext* pOut, const SwRect &rGrfAr
 
         if(bIsChart)
         {
-            const uno::Reference< frame::XModel > aXModel(pOLENd->GetOLEObj().GetOleRef()->getComponent(), uno::UNO_QUERY);
+            basegfx::B2DRange aSourceRange;
+            const drawinglayer::primitive2d::Primitive2DContainer aSequence(
+                pOLENd->GetOLEObj().tryToGetChartContentAsPrimitive2DSequence(
+                    aSourceRange));
 
-            if(aXModel.is())
+            if(!aSequence.empty() && !aSourceRange.isEmpty())
             {
-                basegfx::B2DRange aSourceRange;
-
-                const drawinglayer::primitive2d::Primitive2DContainer aSequence(
-                    ChartHelper::tryToGetChartContentAsPrimitive2DSequence(
-                        aXModel,
-                        aSourceRange));
-
-                if(!aSequence.empty() && !aSourceRange.isEmpty())
-                {
-                    const basegfx::B2DRange aTargetRange(
-                        aAlignedGrfArea.Left(), aAlignedGrfArea.Top(),
-                        aAlignedGrfArea.Right(), aAlignedGrfArea.Bottom());
-
-                    bDone = paintUsingPrimitivesHelper(
-                        *pOut,
-                        aSequence,
-                        aSourceRange,
-                        aTargetRange);
-                }
+                const basegfx::B2DRange aTargetRange(
+                    aAlignedGrfArea.Left(), aAlignedGrfArea.Top(),
+                    aAlignedGrfArea.Right(), aAlignedGrfArea.Bottom());
+
+                bDone = paintUsingPrimitivesHelper(
+                    *pOut,
+                    aSequence,
+                    aSourceRange,
+                    aTargetRange);
             }
         }
 
diff --git a/sw/source/core/ole/ndole.cxx b/sw/source/core/ole/ndole.cxx
index c9f26b9b2156..354c3404b427 100644
--- a/sw/source/core/ole/ndole.cxx
+++ b/sw/source/core/ole/ndole.cxx
@@ -57,6 +57,7 @@
 #include <unotools/ucbstreamhelper.hxx>
 #include <vcl/graphicfilter.hxx>
 #include <comcore.hrc>
+#include <svx/charthelper.hxx>
 
 #include <deque>
 
@@ -125,6 +126,10 @@ void SAL_CALL SwOLEListener_Impl::stateChanged( const lang::EventObject&, ::sal_
         if (g_pOLELRU_Cache)
             g_pOLELRU_Cache->RemoveObj( *mpObj );
     }
+    else if(mpObj && nNewState == embed::EmbedStates::RUNNING)
+    {
+        mpObj->resetBufferedData();
+    }
 }
 
 void SwOLEListener_Impl::Release()
@@ -673,7 +678,9 @@ void SwOLENode::SetChanged()
 SwOLEObj::SwOLEObj( const svt::EmbeddedObjectRef& xObj ) :
     pOLENd( nullptr ),
     pListener( nullptr ),
-    xOLERef( xObj )
+    xOLERef( xObj ),
+    m_aPrimitive2DSequence(),
+    m_aRange()
 {
     xOLERef.Lock();
     if ( xObj.is() )
@@ -687,7 +694,9 @@ SwOLEObj::SwOLEObj( const svt::EmbeddedObjectRef& xObj ) :
 SwOLEObj::SwOLEObj( const OUString &rString, sal_Int64 nAspect ) :
     pOLENd( nullptr ),
     pListener( nullptr ),
-    aName( rString )
+    aName( rString ),
+    m_aPrimitive2DSequence(),
+    m_aRange()
 {
     xOLERef.Lock();
     xOLERef.SetViewAspect( nAspect );
@@ -932,6 +941,34 @@ OUString SwOLEObj::GetDescription()
     return SW_RESSTR(STR_OLE);
 }
 
+drawinglayer::primitive2d::Primitive2DContainer SwOLEObj::tryToGetChartContentAsPrimitive2DSequence(basegfx::B2DRange& rRange)
+{
+    if(m_aPrimitive2DSequence.empty() && m_aRange.isEmpty() && xOLERef.is() && xOLERef.IsChart())
+    {
+        const uno::Reference< frame::XModel > aXModel(xOLERef->getComponent(), uno::UNO_QUERY);
+
+        if(aXModel.is())
+        {
+            m_aPrimitive2DSequence = ChartHelper::tryToGetChartContentAsPrimitive2DSequence(
+                aXModel,
+                m_aRange);
+        }
+    }
+
+    if(!m_aPrimitive2DSequence.empty() && !m_aRange.isEmpty())
+    {
+        rRange = m_aRange;
+    }
+
+    return m_aPrimitive2DSequence;
+}
+
+void SwOLEObj::resetBufferedData()
+{
+    m_aPrimitive2DSequence = drawinglayer::primitive2d::Primitive2DContainer();
+    m_aRange.reset();
+}
+
 SwOLELRUCache::SwOLELRUCache()
     : utl::ConfigItem(OUString("Office.Common/Cache"))
     , m_nLRU_InitSize( 20 )


More information about the Libreoffice-commits mailing list