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.gr...@cib.de> AuthorDate: Thu Jul 7 10:16:02 2016 +0200 Commit: Armin Le Grand <armin.le.gr...@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.gr...@cib.de> AuthorDate: Fri Jul 1 15:10:00 2016 +0200 Commit: Armin Le Grand <armin.le.gr...@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.gr...@cib.de> AuthorDate: Fri Jul 1 14:50:00 2016 +0200 Commit: Armin Le Grand <armin.le.gr...@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.gr...@cib.de> AuthorDate: Fri Jul 1 14:40:00 2016 +0200 Commit: Armin Le Grand <armin.le.gr...@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.gr...@cib.de> AuthorDate: Fri Jul 1 14:20:00 2016 +0200 Commit: Armin Le Grand <armin.le.gr...@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 ) _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits