[Libreoffice-commits] core.git: include/vcl sd/inc sd/source slideshow/source vcl/inc vcl/source

Luboš Luňák (via logerrit) logerrit at kemper.freedesktop.org
Fri Oct 16 08:11:39 UTC 2020


 include/vcl/graphicfilter.hxx                     |    6 ++++
 sd/inc/sdpage.hxx                                 |    7 ++++
 sd/source/core/sdpage2.cxx                        |   11 +++++++
 sd/source/ui/slidesorter/view/SlideSorterView.cxx |   14 +++++++++
 slideshow/source/engine/slide/slideimpl.cxx       |   20 +++++++++++++
 vcl/inc/impgraph.hxx                              |    2 +
 vcl/source/filter/graphicfilter.cxx               |   33 ++++++++++++++++++++++
 vcl/source/gdi/impgraph.cxx                       |   11 ++++---
 8 files changed, 99 insertions(+), 5 deletions(-)

New commits:
commit 8062e88e73acd8d1f9a62b0bd519b499693285e3
Author:     Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Tue Oct 6 20:23:46 2020 +0200
Commit:     Luboš Luňák <l.lunak at collabora.com>
CommitDate: Fri Oct 16 10:10:53 2020 +0200

    try to make available all slide images using threads
    
    Graphic::makeAvailable() is not thread-safe, but the jpeg loader
    is capable of that, and the graphic can be loaded using the stream
    data (which is what ultimately makeAvailable() will do anyway).
    This loads all images faster using threads instead of them being
    loaded one by one on-demand.
    
    Change-Id: Ifc39a2757834a9fb0dbafa61f13f5454e69af330
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104082
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <l.lunak at collabora.com>

diff --git a/include/vcl/graphicfilter.hxx b/include/vcl/graphicfilter.hxx
index 7ce85fd8773a..83db7db95fb8 100644
--- a/include/vcl/graphicfilter.hxx
+++ b/include/vcl/graphicfilter.hxx
@@ -294,6 +294,12 @@ public:
     /// The resulting graphic is added to rGraphics on success, nullptr is added on failure.
     void ImportGraphics(std::vector< std::shared_ptr<Graphic> >& rGraphics, std::vector< std::unique_ptr<SvStream> > vStreams);
 
+    /**
+     Tries to ensure all Graphic objects are available (Graphic::isAvailable()). Only an optimization, may
+     not process all items.
+    */
+    void MakeGraphicsAvailableThreaded(std::vector< Graphic* >& rGraphics);
+
     ErrCode             ImportGraphic( Graphic& rGraphic, const OUString& rPath,
                                    SvStream& rStream,
                                    sal_uInt16 nFormat,
diff --git a/sd/inc/sdpage.hxx b/sd/inc/sdpage.hxx
index 4c4c3b9ca88a..a70fbf61be8a 100644
--- a/sd/inc/sdpage.hxx
+++ b/sd/inc/sdpage.hxx
@@ -48,6 +48,7 @@ class SfxItemSet;
 class Paragraph;
 class Outliner;
 class SdStyleSheet;
+class Graphic;
 
 namespace sd
 {
@@ -377,6 +378,12 @@ public:
     virtual void dumpAsXml(xmlTextWriterPtr pWriter) const override;
     sal_uInt16 getPageId() const { return mnPageId; }
 
+    /**
+     Returns graphics objects from the page that can be prefetched before it's painted.
+     The pointers are temporary and should not be kept.
+    */
+    void getGraphicsForPrefetch(std::vector<Graphic*>& graphics) const;
+
     static sal_uInt16 mnLastPageId;
 
 private:
diff --git a/sd/source/core/sdpage2.cxx b/sd/source/core/sdpage2.cxx
index 2f8f36c2b682..089712ab2693 100644
--- a/sd/source/core/sdpage2.cxx
+++ b/sd/source/core/sdpage2.cxx
@@ -29,6 +29,7 @@
 #include <tools/debug.hxx>
 #include <svx/svddef.hxx>
 #include <rtl/math.hxx>
+#include <svx/svdograf.hxx>
 
 #include <Annotation.hxx>
 #include <notifydocumentevent.hxx>
@@ -609,6 +610,16 @@ void SdPage::removeAnnotation( const Reference< XAnnotation >& xAnnotation )
         Reference<XInterface>( xAnnotation, UNO_QUERY ) );
 }
 
+void SdPage::getGraphicsForPrefetch(std::vector<Graphic*>& graphics) const
+{
+    for( size_t i = 0; i < GetObjCount(); ++i)
+    {
+        if( SdrGrafObj* grafObj = dynamic_cast<SdrGrafObj*>(GetObj(i)))
+            if(!grafObj->GetGraphic().isAvailable())
+                graphics.push_back( const_cast<Graphic*>(&grafObj->GetGraphic()));
+    }
+}
+
 void SdPage::dumpAsXml(xmlTextWriterPtr pWriter) const
 {
     xmlTextWriterStartElement(pWriter, BAD_CAST("SdPage"));
diff --git a/sd/source/ui/slidesorter/view/SlideSorterView.cxx b/sd/source/ui/slidesorter/view/SlideSorterView.cxx
index 46f1c00435ce..f6a6a1786e05 100644
--- a/sd/source/ui/slidesorter/view/SlideSorterView.cxx
+++ b/sd/source/ui/slidesorter/view/SlideSorterView.cxx
@@ -45,6 +45,7 @@
 #include <vcl/svapp.hxx>
 #include <vcl/scrbar.hxx>
 #include <vcl/settings.hxx>
+#include <vcl/graphicfilter.hxx>
 
 #include <algorithm>
 
@@ -644,6 +645,19 @@ void SlideSorterView::Paint (
     // Paint all page objects that are fully or partially inside the
     // repaint region.
     const Range aRange (mpLayouter->GetRangeOfVisiblePageObjects(rRepaintArea));
+    // Try to prefetch all graphics from the pages to paint. This will be done
+    // in threads to be more efficient than loading them on-demand one by one.
+    std::vector<Graphic*> graphics;
+    for (long nIndex=aRange.Min(); nIndex<=aRange.Max(); ++nIndex)
+    {
+        model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
+        if (!pDescriptor || ! pDescriptor->HasState(PageDescriptor::ST_Visible))
+            continue;
+        pDescriptor->GetPage()->getGraphicsForPrefetch(graphics);
+    }
+    if(graphics.size() > 1) // threading does not help with loading just one
+        GraphicFilter::GetGraphicFilter().MakeGraphicsAvailableThreaded(graphics);
+
     for (long nIndex=aRange.Min(); nIndex<=aRange.Max(); ++nIndex)
     {
         model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
diff --git a/slideshow/source/engine/slide/slideimpl.cxx b/slideshow/source/engine/slide/slideimpl.cxx
index 569b7fea09a9..4adc0ce37e7c 100644
--- a/slideshow/source/engine/slide/slideimpl.cxx
+++ b/slideshow/source/engine/slide/slideimpl.cxx
@@ -48,6 +48,9 @@
 #include "targetpropertiescreator.hxx"
 #include <tools.hxx>
 #include <box2dtools.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <svx/svdograf.hxx>
+#include <svx/unoshape.hxx>
 
 using namespace ::com::sun::star;
 
@@ -387,6 +390,23 @@ void SlideImpl::prefetch()
     if( !mxRootNode.is() )
         return;
 
+    // Try to prefetch all graphics from the page. This will be done
+    // in threads to be more efficient than loading them on-demand one by one.
+    std::vector<Graphic*> graphics;
+    for (sal_Int32 i = 0; i < mxDrawPage->getCount(); i++)
+    {
+        com::sun::star::uno::Reference<com::sun::star::drawing::XShape> xShape(mxDrawPage->getByIndex(i), com::sun::star::uno::UNO_QUERY_THROW);
+        SvxShape* pShape = comphelper::getUnoTunnelImplementation<SvxShape>(xShape);
+        SdrObject* pObj = pShape ? pShape->GetSdrObject() : nullptr;
+        if (!pObj)
+            continue;
+        if( SdrGrafObj* grafObj = dynamic_cast<SdrGrafObj*>(pObj))
+            if( !grafObj->GetGraphic().isAvailable())
+                graphics.push_back( const_cast<Graphic*>(&grafObj->GetGraphic()));
+    }
+    if(graphics.size() > 1) // threading does not help with loading just one
+        GraphicFilter::GetGraphicFilter().MakeGraphicsAvailableThreaded( graphics );
+
     applyInitialShapeAttributes(mxRootNode);
 }
 
diff --git a/vcl/inc/impgraph.hxx b/vcl/inc/impgraph.hxx
index aee0d1839b31..211a2ecd56ea 100644
--- a/vcl/inc/impgraph.hxx
+++ b/vcl/inc/impgraph.hxx
@@ -207,6 +207,8 @@ public:
     bool swapOut();
     bool isSwappedOut() const { return mbSwapOut; }
     OUString getSwapFileURL() const;
+    // public only because of use in GraphicFilter
+    void updateFromLoadedGraphic(ImpGraphic* graphic);
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/graphicfilter.cxx b/vcl/source/filter/graphicfilter.cxx
index d2b23edb627d..ba38ec00964e 100644
--- a/vcl/source/filter/graphicfilter.cxx
+++ b/vcl/source/filter/graphicfilter.cxx
@@ -1143,6 +1143,39 @@ void GraphicFilter::ImportGraphics(std::vector< std::shared_ptr<Graphic> >& rGra
     }
 }
 
+void GraphicFilter::MakeGraphicsAvailableThreaded(std::vector<Graphic*>& graphics)
+{
+    // Graphic::makeAvailable() is not thread-safe. Only the jpeg loader is, so here
+    // we process only jpeg images that also have their stream data, load new Graphic's
+    // from them and then update the passed objects using them.
+    std::vector< Graphic* > toLoad;
+    for(auto graphic : graphics)
+    {
+        // Need to use GetSharedGfxLink, to access the pointer without copying.
+        if(!graphic->isAvailable() && graphic->IsGfxLink()
+            && graphic->GetSharedGfxLink()->GetType() == GfxLinkType::NativeJpg
+            && graphic->GetSharedGfxLink()->GetDataSize() != 0 )
+            toLoad.push_back( graphic );
+    }
+    if( toLoad.empty())
+        return;
+    std::vector< std::unique_ptr<SvStream>> streams;
+    for( auto graphic : toLoad )
+    {
+        streams.push_back( std::make_unique<SvMemoryStream>( const_cast<sal_uInt8*>(graphic->GetSharedGfxLink()->GetData()),
+            graphic->GetSharedGfxLink()->GetDataSize(), StreamMode::READ | StreamMode::WRITE));
+    }
+    std::vector< std::shared_ptr<Graphic>> loadedGraphics;
+    ImportGraphics(loadedGraphics, std::move(streams));
+    assert(loadedGraphics.size() == toLoad.size());
+    for( size_t i = 0; i < toLoad.size(); ++i )
+    {
+        if(loadedGraphics[ i ] != nullptr)
+            toLoad[ i ]->ImplGetImpGraphic()->updateFromLoadedGraphic(loadedGraphics[ i ]->ImplGetImpGraphic());
+    }
+}
+
+
 Graphic GraphicFilter::ImportUnloadedGraphic(SvStream& rIStream, sal_uInt64 sizeLimit,
                                              const Size* pSizeHint)
 {
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
index f9afa788973e..39f797a69245 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -1429,22 +1429,23 @@ bool ImpGraphic::loadPrepared()
     Graphic aGraphic;
     if (!mpGfxLink->LoadNative(aGraphic))
         return false;
+    updateFromLoadedGraphic(aGraphic.ImplGetImpGraphic());
+    return true;
+}
 
+void ImpGraphic::updateFromLoadedGraphic(ImpGraphic* graphic)
+{
     GraphicExternalLink aLink = maGraphicExternalLink;
-
     Size aPrefSize = maSwapInfo.maPrefSize;
     MapMode aPrefMapMode = maSwapInfo.maPrefMapMode;
-    *this = *aGraphic.ImplGetImpGraphic();
+    *this = *graphic;
     if (aPrefSize.getWidth() && aPrefSize.getHeight() && aPrefMapMode == ImplGetPrefMapMode())
     {
         // Use custom preferred size if it was set when the graphic was still unloaded.
         // Only set the size in case the unloaded and loaded unit matches.
         ImplSetPrefSize(aPrefSize);
     }
-
     maGraphicExternalLink = aLink;
-
-    return true;
 }
 
 bool ImpGraphic::swapIn()


More information about the Libreoffice-commits mailing list