From 62e598644fcb134d6601adb5b6d33539eab990d4 Mon Sep 17 00:00:00 2001 From: Armin Le Grand Date: Fri, 1 Jul 2016 14:40:00 +0200 Subject: 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 --- .../source/primitive2d/textlayoutdevice.cxx | 4 +- .../drawinglayer/primitive2d/textlayoutdevice.hxx | 2 + svx/source/svdraw/svdotextdecomposition.cxx | 5 + sw/inc/ndole.hxx | 10 +- sw/source/core/doc/notxtfrm.cxx | 3 +- sw/source/core/ole/ndole.cxx | 138 +++++++++++++++++++-- 6 files changed, 149 insertions(+), 13 deletions(-) diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx index e249ddd84044..a7eb74947faa 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 #include #include +#include // 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 63bfcdd53bdb..8a6a74182d9e 100644 --- a/svx/source/svdraw/svdotextdecomposition.cxx +++ b/svx/source/svdraw/svdotextdecomposition.cxx @@ -686,6 +686,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); @@ -737,6 +738,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); @@ -871,6 +873,7 @@ void SdrTextObj::impDecomposeBlockTextPrimitive( // prepare outliner const bool bIsCell(rSdrBlockTextPrimitive.getCellText()); + SolarMutexGuard aSolarGuard; SdrOutliner& rOutliner = ImpGetDrawOutliner(); SdrTextHorzAdjust eHAdj = rSdrBlockTextPrimitive.getSdrTextHorzAdjust(); SdrTextVertAdjust eVAdj = rSdrBlockTextPrimitive.getSdrTextVertAdjust(); @@ -1122,6 +1125,7 @@ void SdrTextObj::impDecomposeStretchTextPrimitive( aAnchorTextRange.expand(aTranslate + aScale); // prepare outliner + SolarMutexGuard aSolarGuard; SdrOutliner& rOutliner = ImpGetDrawOutliner(); const EEControlBits nOriginalControlWord(rOutliner.GetControlWord()); const Size aNullSize; @@ -1481,6 +1485,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 ec901a69ab16..9f3a320f4a9b 100644 --- a/sw/inc/ndole.hxx +++ b/sw/inc/ndole.hxx @@ -20,15 +20,16 @@ #define INCLUDED_SW_INC_NDOLE_HXX #include - #include +#include 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 e58f646d639a..08517a1a7694 100644 --- a/sw/source/core/doc/notxtfrm.cxx +++ b/sw/source/core/doc/notxtfrm.cxx @@ -1001,7 +1001,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 cef1f47e0730..a1766b4846b8 100644 --- a/sw/source/core/ole/ndole.cxx +++ b/sw/source/core/ole/ndole.cxx @@ -57,7 +57,8 @@ #include #include #include - +#include +#include #include using namespace utl; @@ -642,12 +643,89 @@ bool SwOLENode::IsChart() const return bIsChart; } +////////////////////////////////////////////////////////////////////////////// + +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() ) @@ -663,7 +741,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 ); @@ -671,6 +750,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() ) @@ -908,17 +993,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); + } + } } } @@ -934,6 +1051,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() -- cgit