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@collabora.com>
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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"));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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: */
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user