summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2018-04-14 15:13:05 +0900
committerTomaž Vajngerl <quikee@gmail.com>2018-04-20 09:15:22 +0200
commit7b355669c6ddeab2e6cec692d6afdff41c61d0fb (patch)
tree46c55326bccfa68a2bb5fad6d637e0f4576c8d68 /vcl
parent663fd3d6e1f93ec989dc289e688d5dbfe434cbca (diff)
Function to load graphic swapped out (loaded on demand)
When a document is loaded it takes a lot of time and memory to load the graphic that are in the documet, so avoid that and just store the compressed graphic into a temporary file (handeled by GfxLink) and load when we really need to show the graphic. GraphicObject cached some attributes from Graphic, but this attributes now aren't available immediately so this attributes are removed form GraphicObject and now delegate to the Graphic itself. GetSizeBytes attribute however was removed as it is only used in some tests. GfxLink initial values were moved to the constructor and are not set in the header file anymore (as it is the recommended way to do it). The SdImportTest::testDocumentLayout failed as it looks like the dump sometimes didn't include the width and height of the null bitmap (which is set to 32x32) of the FillBitmap in some situations, but then in other situations it did include this attributes. With this change the width and height are always included for the FillBitmap which looks like it is more correct. Change-Id: Ia1218f93b1735402b7828404f65660e2d4acf32f Reviewed-on: https://gerrit.libreoffice.org/53016 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/inc/graphic/Manager.hxx2
-rw-r--r--vcl/inc/impgraph.hxx15
-rw-r--r--vcl/source/filter/graphicfilter.cxx227
-rw-r--r--vcl/source/gdi/gfxlink.cxx65
-rw-r--r--vcl/source/gdi/graph.cxx10
-rw-r--r--vcl/source/gdi/impgraph.cxx165
-rw-r--r--vcl/source/graphic/GraphicObject.cxx55
-rw-r--r--vcl/source/graphic/Manager.cxx21
8 files changed, 474 insertions, 86 deletions
diff --git a/vcl/inc/graphic/Manager.hxx b/vcl/inc/graphic/Manager.hxx
index 4b4585203639..6dd88a5a4c1c 100644
--- a/vcl/inc/graphic/Manager.hxx
+++ b/vcl/inc/graphic/Manager.hxx
@@ -46,6 +46,8 @@ private:
DECL_LINK(SwapOutTimerHandler, Timer*, void);
+ static sal_Int64 getGraphicSizeBytes(const ImpGraphic* pImpGraphic);
+
public:
static Manager& get();
diff --git a/vcl/inc/impgraph.hxx b/vcl/inc/impgraph.hxx
index 814f9feed6f5..660fdfce81cd 100644
--- a/vcl/inc/impgraph.hxx
+++ b/vcl/inc/impgraph.hxx
@@ -27,6 +27,13 @@ struct ImpSwapInfo
{
MapMode maPrefMapMode;
Size maPrefSize;
+
+ bool mbIsAnimated;
+ bool mbIsEPS;
+ bool mbIsTransparent;
+ bool mbIsAlpha;
+
+ sal_uInt32 mnAnimationLoopCount;
};
class OutputDevice;
@@ -85,6 +92,7 @@ private:
GraphicExternalLink maGraphicExternalLink;
std::chrono::high_resolution_clock::time_point maLastUsed;
+ bool mbPrepared;
public:
ImpGraphic();
@@ -98,6 +106,8 @@ public:
ImpGraphic( const GDIMetaFile& rMtf );
~ImpGraphic();
+ void ImplSetPrepared();
+
private:
ImpGraphic& operator=( const ImpGraphic& rImpGraphic );
@@ -135,6 +145,9 @@ private:
bool ImplIsAnimated() const;
bool ImplIsEPS() const;
+ bool isAvailable() const;
+ bool makeAvailable();
+
Bitmap ImplGetBitmap(const GraphicConversionParameters& rParameters) const;
BitmapEx ImplGetBitmapEx(const GraphicConversionParameters& rParameters) const;
/// Gives direct access to the contained BitmapEx.
@@ -203,6 +216,8 @@ private:
void setPdfData(const css::uno::Sequence<sal_Int8>& rPdfData);
bool ensureAvailable () const;
+
+ bool loadPrepared();
};
#endif // INCLUDED_VCL_INC_IMPGRAPH_HXX
diff --git a/vcl/source/filter/graphicfilter.cxx b/vcl/source/filter/graphicfilter.cxx
index 79c6e484fdc4..023c07ecb9a2 100644
--- a/vcl/source/filter/graphicfilter.cxx
+++ b/vcl/source/filter/graphicfilter.cxx
@@ -37,6 +37,7 @@
#include <vcl/pngwrite.hxx>
#include <vcl/vectorgraphicdata.hxx>
#include <vcl/virdev.hxx>
+#include <impgraph.hxx>
#include <vcl/svapp.hxx>
#include <osl/file.hxx>
#include <vcl/graphicfilter.hxx>
@@ -1441,6 +1442,231 @@ void GraphicFilter::ImportGraphics(std::vector< std::shared_ptr<Graphic> >& rGra
}
}
+Graphic GraphicFilter::ImportUnloadedGraphic(SvStream& rIStream)
+{
+ Graphic aGraphic;
+ sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW;
+ GfxLinkType eLinkType = GfxLinkType::NONE;
+
+ ResetLastError();
+
+ const sal_uLong nStreamBegin = rIStream.Tell();
+
+ rIStream.Seek(nStreamBegin);
+
+ ErrCode nStatus = ImpTestOrFindFormat("", rIStream, nFormat);
+
+ rIStream.Seek(nStreamBegin);
+ const sal_uInt32 nStreamLength(rIStream.Seek(STREAM_SEEK_TO_END) - nStreamBegin);
+
+ OUString aFilterName = pConfig->GetImportFilterName(nFormat);
+ OUString aExternalFilterName = pConfig->GetExternalFilterName(nFormat, false);
+
+ std::unique_ptr<sal_uInt8[]> pGraphicContent;
+ sal_Int32 nGraphicContentSize = 0;
+
+ // read graphic
+ if (pConfig->IsImportInternalFilter(nFormat))
+ {
+ if (aFilterName.equalsIgnoreAsciiCase(IMP_GIF))
+ {
+ eLinkType = GfxLinkType::NativeGif;
+ }
+ else if (aFilterName.equalsIgnoreAsciiCase(IMP_PNG))
+ {
+ vcl::PNGReader aPNGReader(rIStream);
+
+ // check if this PNG contains a GIF chunk!
+ const std::vector<vcl::PNGReader::ChunkData>& rChunkData = aPNGReader.GetChunks();
+ for (auto const& chunk : rChunkData)
+ {
+ // Microsoft Office is storing Animated GIFs in following chunk
+ if (chunk.nType == PMGCHUNG_msOG)
+ {
+ sal_uInt32 nChunkSize = chunk.aData.size();
+
+ if (nChunkSize > 11)
+ {
+ const std::vector<sal_uInt8>& rData = chunk.aData;
+ nGraphicContentSize = nChunkSize - 11;
+ SvMemoryStream aIStrm(const_cast<sal_uInt8*>(&rData[11]), nGraphicContentSize, StreamMode::READ);
+ pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
+ sal_uInt64 aCurrentPosition = aIStrm.Tell();
+ aIStrm.ReadBytes(pGraphicContent.get(), nGraphicContentSize);
+ aIStrm.Seek(aCurrentPosition);
+ eLinkType = GfxLinkType::NativeGif;
+ break;
+ }
+ }
+ }
+ if (eLinkType == GfxLinkType::NONE)
+ {
+ eLinkType = GfxLinkType::NativePng;
+ }
+ }
+ else if (aFilterName.equalsIgnoreAsciiCase(IMP_JPEG))
+ {
+ eLinkType = GfxLinkType::NativeJpg;
+ }
+ else if (aFilterName.equalsIgnoreAsciiCase(IMP_SVG))
+ {
+ bool bOkay(false);
+
+ if (nStreamLength > 0)
+ {
+ std::vector<sal_uInt8> aTwoBytes(2);
+ rIStream.ReadBytes(aTwoBytes.data(), 2);
+ rIStream.Seek(nStreamBegin);
+
+ if (aTwoBytes[0] == 0x1F && aTwoBytes[1] == 0x8B)
+ {
+ SvMemoryStream aMemStream;
+ ZCodec aCodec;
+ long nMemoryLength;
+
+ aCodec.BeginCompression(ZCODEC_DEFAULT_COMPRESSION, false, true);
+ nMemoryLength = aCodec.Decompress(rIStream, aMemStream);
+ aCodec.EndCompression();
+
+ if (!rIStream.GetError() && nMemoryLength >= 0)
+ {
+ nGraphicContentSize = nMemoryLength;
+ pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
+
+ aMemStream.Seek(STREAM_SEEK_TO_BEGIN);
+ aMemStream.ReadBytes(pGraphicContent.get(), nGraphicContentSize);
+
+ bOkay = true;
+ }
+ }
+ else
+ {
+ nGraphicContentSize = nStreamLength;
+ pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
+ rIStream.ReadBytes(pGraphicContent.get(), nStreamLength);
+
+ bOkay = true;
+ }
+ }
+
+ if (bOkay)
+ {
+ eLinkType = GfxLinkType::NativeSvg;
+ }
+ else
+ {
+ nStatus = ERRCODE_GRFILTER_FILTERERROR;
+ }
+ }
+ else if (aFilterName.equalsIgnoreAsciiCase(IMP_BMP))
+ {
+ eLinkType = GfxLinkType::NativeBmp;
+ }
+ else if (aFilterName.equalsIgnoreAsciiCase(IMP_MOV))
+ {
+ eLinkType = GfxLinkType::NativeMov;
+ }
+ else if (aFilterName.equalsIgnoreAsciiCase(IMP_WMF) ||
+ aFilterName.equalsIgnoreAsciiCase(IMP_EMF))
+ {
+ nGraphicContentSize = nStreamLength;
+ pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
+
+ rIStream.ReadBytes(pGraphicContent.get(), nStreamLength);
+
+ if (!rIStream.GetError())
+ {
+ eLinkType = GfxLinkType::NativeWmf;
+ }
+ else
+ {
+ nStatus = ERRCODE_GRFILTER_FILTERERROR;
+ }
+ }
+ else if (aFilterName == IMP_PDF)
+ {
+ eLinkType = GfxLinkType::NativePdf;
+ }
+ else
+ {
+ nStatus = ERRCODE_GRFILTER_FILTERERROR;
+ }
+ }
+ else
+ {
+ ImpFilterLibCacheEntry* pFilter = nullptr;
+
+ // find first filter in filter paths
+ sal_Int32 i, nTokenCount = getTokenCount(aFilterPath, ';');
+ ImpFilterLibCache &rCache = Cache::get();
+ for( i = 0; ( i < nTokenCount ) && ( pFilter == nullptr ); i++ )
+ pFilter = rCache.GetFilter(aFilterPath.getToken(i, ';'), aFilterName, aExternalFilterName);
+ if( !pFilter )
+ nStatus = ERRCODE_GRFILTER_FILTERERROR;
+ else
+ {
+ PFilterCall pFunc = pFilter->GetImportFunction();
+
+ if (!pFunc)
+ nStatus = ERRCODE_GRFILTER_FILTERERROR;
+ else
+ {
+ OUString aShortName;
+ if (nFormat != GRFILTER_FORMAT_DONTKNOW)
+ aShortName = GetImportFormatShortName(nFormat).toAsciiUpperCase();
+
+ if (aShortName.startsWith(TIF_SHORTNAME))
+ eLinkType = GfxLinkType::NativeTif;
+ else if( aShortName.startsWith(MET_SHORTNAME))
+ eLinkType = GfxLinkType::NativeMet;
+ else if( aShortName.startsWith(PCT_SHORTNAME))
+ eLinkType = GfxLinkType::NativePct;
+ }
+ }
+ }
+
+ if (nStatus == ERRCODE_NONE && eLinkType != GfxLinkType::NONE)
+ {
+ if (!pGraphicContent)
+ {
+ nGraphicContentSize = nStreamLength;
+
+ if (nGraphicContentSize > 0)
+ {
+ try
+ {
+ pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
+ }
+ catch (const std::bad_alloc&)
+ {
+ nStatus = ERRCODE_GRFILTER_TOOBIG;
+ }
+
+ if (nStatus == ERRCODE_NONE)
+ {
+ rIStream.Seek(nStreamBegin);
+ rIStream.ReadBytes(pGraphicContent.get(), nGraphicContentSize);
+ }
+ }
+ }
+
+ if( nStatus == ERRCODE_NONE )
+ {
+ aGraphic.SetGfxLink(GfxLink(std::move(pGraphicContent), nGraphicContentSize, eLinkType));
+ aGraphic.ImplGetImpGraphic()->ImplSetPrepared();
+ }
+ }
+
+ // Set error code or try to set native buffer
+ if(nStatus != ERRCODE_NONE)
+ {
+ ImplSetError(nStatus, &rIStream);
+ rIStream.Seek(nStreamBegin);
+ }
+
+ return aGraphic;
+}
+
ErrCode GraphicFilter::ImportGraphic( Graphic& rGraphic, const OUString& rPath, SvStream& rIStream,
sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat, GraphicFilterImportFlags nImportFlags,
css::uno::Sequence< css::beans::PropertyValue >* pFilterData,
@@ -2272,6 +2498,7 @@ IMPL_LINK( GraphicFilter, FilterCallback, ConvertData&, rData, bool )
case ConvertDataFormat::WMF: aShortName = WMF_SHORTNAME; break;
case ConvertDataFormat::EMF: aShortName = EMF_SHORTNAME; break;
case ConvertDataFormat::SVG: aShortName = SVG_SHORTNAME; break;
+ case ConvertDataFormat::PDF: aShortName = PDF_SHORTNAME; break;
default:
break;
diff --git a/vcl/source/gdi/gfxlink.cxx b/vcl/source/gdi/gfxlink.cxx
index c1b0cd4bd5df..885385cb51b0 100644
--- a/vcl/source/gdi/gfxlink.cxx
+++ b/vcl/source/gdi/gfxlink.cxx
@@ -24,21 +24,28 @@
#include <vcl/graph.hxx>
#include <vcl/gfxlink.hxx>
#include <vcl/cvtgrf.hxx>
+#include <vcl/graphicfilter.hxx>
#include <memory>
#include <o3tl/make_shared.hxx>
GfxLink::GfxLink()
+ : meType(GfxLinkType::NONE)
+ , mnUserId(0)
+ , mnSwapInDataSize(0)
+ , mbPrefMapModeValid(false)
+ , mbPrefSizeValid(false)
{
}
-GfxLink::GfxLink( std::unique_ptr<sal_uInt8[]> pBuf, sal_uInt32 nSize, GfxLinkType nType )
+GfxLink::GfxLink(std::unique_ptr<sal_uInt8[]> pBuf, sal_uInt32 nSize, GfxLinkType nType)
+ : meType(nType)
+ , mnUserId(0)
+ , mpSwapInData(std::shared_ptr<sal_uInt8>(pBuf.release(), pBuf.get_deleter())) // std::move(pBuf) does not compile on Jenkins MacOSX (24 May 2016)
+ , mnSwapInDataSize(nSize)
+ , mbPrefMapModeValid(false)
+ , mbPrefSizeValid(false)
{
- SAL_WARN_IF( pBuf == nullptr || !nSize, "vcl",
- "GfxLink::GfxLink(): empty/NULL buffer given" );
-
- meType = nType;
- mnSwapInDataSize = nSize;
- mpSwapInData = std::shared_ptr<sal_uInt8>(pBuf.release(), pBuf.get_deleter()); // std::move(pBuf) does not compile on Jenkins MacOSX (24 May 2016)
+ SAL_WARN_IF(mpSwapInData.get() == nullptr || mnSwapInDataSize <= 0, "vcl", "GfxLink::GfxLink(): empty/NULL buffer given");
}
bool GfxLink::operator==( const GfxLink& rGfxLink ) const
@@ -98,31 +105,33 @@ bool GfxLink::LoadNative( Graphic& rGraphic )
if( IsNative() && mnSwapInDataSize )
{
const sal_uInt8* pData = GetData();
-
- if( pData )
+ if (pData)
{
- SvMemoryStream aMemStm;
- ConvertDataFormat nCvtType;
-
- aMemStm.SetBuffer( const_cast<sal_uInt8*>(pData), mnSwapInDataSize, mnSwapInDataSize );
+ SvMemoryStream aMemoryStream(const_cast<sal_uInt8*>(pData), mnSwapInDataSize, StreamMode::READ | StreamMode::WRITE);
+ OUString aShortName;
- switch( meType )
+ switch (meType)
{
- case GfxLinkType::NativeGif: nCvtType = ConvertDataFormat::GIF; break;
- case GfxLinkType::NativeBmp: nCvtType = ConvertDataFormat::BMP; break;
- case GfxLinkType::NativeJpg: nCvtType = ConvertDataFormat::JPG; break;
- case GfxLinkType::NativePng: nCvtType = ConvertDataFormat::PNG; break;
- case GfxLinkType::NativeTif: nCvtType = ConvertDataFormat::TIF; break;
- case GfxLinkType::NativeWmf: nCvtType = ConvertDataFormat::WMF; break;
- case GfxLinkType::NativeMet: nCvtType = ConvertDataFormat::MET; break;
- case GfxLinkType::NativePct: nCvtType = ConvertDataFormat::PCT; break;
- case GfxLinkType::NativeSvg: nCvtType = ConvertDataFormat::SVG; break;
-
- default: nCvtType = ConvertDataFormat::Unknown; break;
+ case GfxLinkType::NativeGif: aShortName = GIF_SHORTNAME; break;
+ case GfxLinkType::NativeJpg: aShortName = JPG_SHORTNAME; break;
+ case GfxLinkType::NativePng: aShortName = PNG_SHORTNAME; break;
+ case GfxLinkType::NativeTif: aShortName = TIF_SHORTNAME; break;
+ case GfxLinkType::NativeWmf: aShortName = WMF_SHORTNAME; break;
+ case GfxLinkType::NativeMet: aShortName = MET_SHORTNAME; break;
+ case GfxLinkType::NativePct: aShortName = PCT_SHORTNAME; break;
+ case GfxLinkType::NativeSvg: aShortName = SVG_SHORTNAME; break;
+ case GfxLinkType::NativeBmp: aShortName = BMP_SHORTNAME; break;
+ case GfxLinkType::NativePdf: aShortName = PDF_SHORTNAME; break;
+ default: break;
+ }
+ if (!aShortName.isEmpty())
+ {
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ sal_uInt16 nFormat = rFilter.GetImportFormatNumberForShortName(aShortName);
+ ErrCode nResult = rFilter.ImportGraphic(rGraphic, OUString(), aMemoryStream, nFormat);
+ if (nResult == ERRCODE_NONE)
+ bRet = true;
}
-
- if( nCvtType != ConvertDataFormat::Unknown && ( GraphicConverter::Import( aMemStm, rGraphic, nCvtType ) == ERRCODE_NONE ) )
- bRet = true;
}
}
diff --git a/vcl/source/gdi/graph.cxx b/vcl/source/gdi/graph.cxx
index 91dcad7e4ae5..9ba35ddd7366 100644
--- a/vcl/source/gdi/graph.cxx
+++ b/vcl/source/gdi/graph.cxx
@@ -257,6 +257,16 @@ void Graphic::ImplTestRefCount()
}
}
+bool Graphic::isAvailable() const
+{
+ return mxImpGraphic->isAvailable();
+}
+
+bool Graphic::makeAvailable()
+{
+ return mxImpGraphic->makeAvailable();
+}
+
Graphic& Graphic::operator=( const Graphic& rGraphic )
{
if( &rGraphic != this )
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
index c4ef749ec6da..9cd9bbb11717 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -30,6 +30,7 @@
#include <unotools/ucbstreamhelper.hxx>
#include <unotools/tempfile.hxx>
#include <vcl/outdev.hxx>
+#include <vcl/graphicfilter.hxx>
#include <vcl/virdev.hxx>
#include <vcl/gfxlink.hxx>
#include <vcl/cvtgrf.hxx>
@@ -103,6 +104,8 @@ Size GraphicReader::GetPreviewSize() const
GraphicID::GraphicID(ImpGraphic const & rGraphic)
{
+ rGraphic.ensureAvailable();
+
mnID1 = static_cast<sal_uLong>(rGraphic.ImplGetType()) << 28;
mnID2 = mnID3 = mnID4 = 0;
@@ -176,7 +179,8 @@ ImpGraphic::ImpGraphic() :
mnSizeBytes ( 0 ),
mbSwapOut ( false ),
mbDummyContext ( false ),
- maLastUsed (std::chrono::high_resolution_clock::now())
+ maLastUsed (std::chrono::high_resolution_clock::now()),
+ mbPrepared ( false )
{
}
@@ -194,6 +198,7 @@ ImpGraphic::ImpGraphic(const ImpGraphic& rImpGraphic)
, maPdfData(rImpGraphic.maPdfData)
, maGraphicExternalLink(rImpGraphic.maGraphicExternalLink)
, maLastUsed (std::chrono::high_resolution_clock::now())
+ , mbPrepared (rImpGraphic.mbPrepared)
{
if( rImpGraphic.mpGfxLink )
mpGfxLink = o3tl::make_unique<GfxLink>( *rImpGraphic.mpGfxLink );
@@ -221,6 +226,7 @@ ImpGraphic::ImpGraphic(ImpGraphic&& rImpGraphic)
, maPdfData(std::move(rImpGraphic.maPdfData))
, maGraphicExternalLink(rImpGraphic.maGraphicExternalLink)
, maLastUsed (std::chrono::high_resolution_clock::now())
+ , mbPrepared (rImpGraphic.mbPrepared)
{
rImpGraphic.ImplClear();
rImpGraphic.mbDummyContext = false;
@@ -232,7 +238,8 @@ ImpGraphic::ImpGraphic(GraphicExternalLink const & rGraphicExternalLink) :
mbSwapOut ( false ),
mbDummyContext ( false ),
maGraphicExternalLink(rGraphicExternalLink),
- maLastUsed (std::chrono::high_resolution_clock::now())
+ maLastUsed (std::chrono::high_resolution_clock::now()),
+ mbPrepared (false)
{
}
@@ -242,7 +249,8 @@ ImpGraphic::ImpGraphic( const Bitmap& rBitmap ) :
mnSizeBytes ( 0 ),
mbSwapOut ( false ),
mbDummyContext ( false ),
- maLastUsed (std::chrono::high_resolution_clock::now())
+ maLastUsed (std::chrono::high_resolution_clock::now()),
+ mbPrepared (false)
{
}
@@ -252,7 +260,8 @@ ImpGraphic::ImpGraphic( const BitmapEx& rBitmapEx ) :
mnSizeBytes ( 0 ),
mbSwapOut ( false ),
mbDummyContext ( false ),
- maLastUsed (std::chrono::high_resolution_clock::now())
+ maLastUsed (std::chrono::high_resolution_clock::now()),
+ mbPrepared (false)
{
}
@@ -262,7 +271,8 @@ ImpGraphic::ImpGraphic(const VectorGraphicDataPtr& rVectorGraphicDataPtr)
mbSwapOut( false ),
mbDummyContext ( false ),
maVectorGraphicData(rVectorGraphicDataPtr),
- maLastUsed (std::chrono::high_resolution_clock::now())
+ maLastUsed (std::chrono::high_resolution_clock::now()),
+ mbPrepared (false)
{
}
@@ -273,7 +283,8 @@ ImpGraphic::ImpGraphic( const Animation& rAnimation ) :
mnSizeBytes ( 0 ),
mbSwapOut ( false ),
mbDummyContext ( false ),
- maLastUsed (std::chrono::high_resolution_clock::now())
+ maLastUsed (std::chrono::high_resolution_clock::now()),
+ mbPrepared (false)
{
}
@@ -283,7 +294,8 @@ ImpGraphic::ImpGraphic( const GDIMetaFile& rMtf ) :
mnSizeBytes ( 0 ),
mbSwapOut ( false ),
mbDummyContext ( false ),
- maLastUsed (std::chrono::high_resolution_clock::now())
+ maLastUsed (std::chrono::high_resolution_clock::now()),
+ mbPrepared (false)
{
}
@@ -321,6 +333,7 @@ ImpGraphic& ImpGraphic::operator=( const ImpGraphic& rImpGraphic )
mbSwapOut = rImpGraphic.mbSwapOut;
mpSwapFile = rImpGraphic.mpSwapFile;
+ mbPrepared = rImpGraphic.mbPrepared;
mpGfxLink.reset();
@@ -355,6 +368,7 @@ ImpGraphic& ImpGraphic::operator=(ImpGraphic&& rImpGraphic)
maVectorGraphicData = std::move(rImpGraphic.maVectorGraphicData);
maPdfData = std::move(rImpGraphic.maPdfData);
maGraphicExternalLink = rImpGraphic.maGraphicExternalLink;
+ mbPrepared = rImpGraphic.mbPrepared;
rImpGraphic.ImplClear();
rImpGraphic.mbDummyContext = false;
@@ -371,7 +385,11 @@ bool ImpGraphic::operator==( const ImpGraphic& rImpGraphic ) const
if( this == &rImpGraphic )
bRet = true;
- else if( !ImplIsSwapOut() && ( rImpGraphic.meType == meType ) )
+ else if (mbPrepared && rImpGraphic.mbPrepared)
+ {
+ bRet = (*mpGfxLink == *rImpGraphic.mpGfxLink);
+ }
+ else if (isAvailable() && rImpGraphic.isAvailable())
{
switch( meType )
{
@@ -427,16 +445,22 @@ bool ImpGraphic::operator==( const ImpGraphic& rImpGraphic ) const
const VectorGraphicDataPtr& ImpGraphic::getVectorGraphicData() const
{
+ ensureAvailable();
+
return maVectorGraphicData;
}
void ImpGraphic::setPdfData(const uno::Sequence<sal_Int8>& rPdfData)
{
+ ensureAvailable();
+
maPdfData = rPdfData;
}
const uno::Sequence<sal_Int8>& ImpGraphic::getPdfData() const
{
+ ensureAvailable();
+
return maPdfData;
}
@@ -446,6 +470,11 @@ void ImpGraphic::ImplCreateSwapInfo()
{
maSwapInfo.maPrefMapMode = ImplGetPrefMapMode();
maSwapInfo.maPrefSize = ImplGetPrefSize();
+ maSwapInfo.mbIsAnimated = ImplIsAnimated();
+ maSwapInfo.mbIsEPS = ImplIsEPS();
+ maSwapInfo.mbIsTransparent = ImplIsTransparent();
+ maSwapInfo.mbIsAlpha = ImplIsAlpha();
+ maSwapInfo.mnAnimationLoopCount = ImplGetAnimationLoopCount();
}
}
@@ -483,10 +512,37 @@ ImpSwapFile::~ImpSwapFile()
}
}
+void ImpGraphic::ImplSetPrepared()
+{
+ mbPrepared = true;
+ mbSwapOut = true;
+ meType = GraphicType::Bitmap;
+
+ SvMemoryStream aMemoryStream(const_cast<sal_uInt8*>(mpGfxLink->GetData()), mpGfxLink->GetDataSize(), StreamMode::READ | StreamMode::WRITE);
+
+ GraphicDescriptor aDescriptor(aMemoryStream, nullptr);
+ if (aDescriptor.Detect(true))
+ {
+ maSwapInfo.maPrefSize = aDescriptor.GetSizePixel();
+ maSwapInfo.maPrefMapMode = MapMode(MapUnit::MapPixel);
+ }
+ maSwapInfo.mnAnimationLoopCount = 0;
+ maSwapInfo.mbIsAnimated = false;
+ maSwapInfo.mbIsEPS = false;
+ maSwapInfo.mbIsTransparent = false;
+ maSwapInfo.mbIsAlpha = false;
+
+ if (mpGfxLink->GetType() == GfxLinkType::NativeGif)
+ {
+ maSwapInfo.mbIsAnimated = true;
+ }
+}
+
void ImpGraphic::ImplClear()
{
mpSwapFile.reset();
mbSwapOut = false;
+ mbPrepared = false;
// cleanup
ImplClearGraphics();
@@ -512,11 +568,13 @@ bool ImpGraphic::ImplIsTransparent() const
{
bool bRet(true);
- ensureAvailable();
-
- if( meType == GraphicType::Bitmap && !maVectorGraphicData.get())
+ if (mbSwapOut)
+ {
+ bRet = maSwapInfo.mbIsTransparent;
+ }
+ else if (meType == GraphicType::Bitmap && !maVectorGraphicData.get())
{
- bRet = ( mpAnimation ? mpAnimation->IsTransparent() : maEx.IsTransparent() );
+ bRet = mpAnimation ? mpAnimation->IsTransparent() : maEx.IsTransparent();
}
return bRet;
@@ -526,15 +584,17 @@ bool ImpGraphic::ImplIsAlpha() const
{
bool bRet(false);
- ensureAvailable();
-
- if(maVectorGraphicData.get())
+ if (mbSwapOut)
+ {
+ bRet = maSwapInfo.mbIsAlpha;
+ }
+ else if (maVectorGraphicData.get())
{
bRet = true;
}
- else if( meType == GraphicType::Bitmap )
+ else if (meType == GraphicType::Bitmap)
{
- bRet = ( nullptr == mpAnimation ) && maEx.IsAlpha();
+ bRet = (nullptr == mpAnimation && maEx.IsAlpha());
}
return bRet;
@@ -542,19 +602,29 @@ bool ImpGraphic::ImplIsAlpha() const
bool ImpGraphic::ImplIsAnimated() const
{
- ensureAvailable();
- return( mpAnimation != nullptr );
+ return mbSwapOut ? maSwapInfo.mbIsAnimated : mpAnimation != nullptr;
}
bool ImpGraphic::ImplIsEPS() const
{
- ensureAvailable();
+ if (mbSwapOut)
+ return maSwapInfo.mbIsEPS;
return( ( meType == GraphicType::GdiMetafile ) &&
( maMetaFile.GetActionSize() > 0 ) &&
( maMetaFile.GetAction( 0 )->GetType() == MetaActionType::EPS ) );
}
+bool ImpGraphic::isAvailable() const
+{
+ return !mbPrepared && !mbSwapOut;
+}
+
+bool ImpGraphic::makeAvailable()
+{
+ return ensureAvailable();
+}
+
Bitmap ImpGraphic::ImplGetBitmap(const GraphicConversionParameters& rParameters) const
{
Bitmap aRetBmp;
@@ -790,8 +860,10 @@ Size ImpGraphic::ImplGetPrefSize() const
{
Size aSize;
- if( ImplIsSwapOut() )
+ if (ImplIsSwapOut())
+ {
aSize = maSwapInfo.maPrefSize;
+ }
else
{
switch( meType )
@@ -835,6 +907,8 @@ Size ImpGraphic::ImplGetPrefSize() const
void ImpGraphic::ImplSetPrefSize( const Size& rPrefSize )
{
+ ensureAvailable();
+
switch( meType )
{
case GraphicType::NONE:
@@ -875,8 +949,10 @@ MapMode ImpGraphic::ImplGetPrefMapMode() const
{
MapMode aMapMode;
- if( ImplIsSwapOut() )
+ if (ImplIsSwapOut())
+ {
aMapMode = maSwapInfo.maPrefMapMode;
+ }
else
{
switch( meType )
@@ -916,6 +992,8 @@ MapMode ImpGraphic::ImplGetPrefMapMode() const
void ImpGraphic::ImplSetPrefMapMode( const MapMode& rPrefMapMode )
{
+ ensureAvailable();
+
switch( meType )
{
case GraphicType::NONE:
@@ -956,6 +1034,9 @@ sal_uLong ImpGraphic::ImplGetSizeBytes() const
{
if( 0 == mnSizeBytes )
{
+ if (mbPrepared)
+ ensureAvailable();
+
if( meType == GraphicType::Bitmap )
{
if(maVectorGraphicData.get())
@@ -1070,12 +1151,16 @@ void ImpGraphic::ImplStartAnimation( OutputDevice* pOutDev, const Point& rDestPt
void ImpGraphic::ImplStopAnimation( OutputDevice* pOutDev, long nExtraData )
{
+ ensureAvailable();
+
if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation )
mpAnimation->Stop( pOutDev, nExtraData );
}
void ImpGraphic::ImplSetAnimationNotifyHdl( const Link<Animation*,void>& rLink )
{
+ ensureAvailable();
+
if( mpAnimation )
mpAnimation->SetNotifyHdl( rLink );
}
@@ -1084,6 +1169,8 @@ Link<Animation*,void> ImpGraphic::ImplGetAnimationNotifyHdl() const
{
Link<Animation*,void> aLink;
+ ensureAvailable();
+
if( mpAnimation )
aLink = mpAnimation->GetNotifyHdl();
@@ -1092,8 +1179,10 @@ Link<Animation*,void> ImpGraphic::ImplGetAnimationNotifyHdl() const
sal_uInt32 ImpGraphic::ImplGetAnimationLoopCount() const
{
- ensureAvailable();
- return( mpAnimation ? mpAnimation->GetLoopCount() : 0 );
+ if (mbSwapOut)
+ return maSwapInfo.mnAnimationLoopCount;
+
+ return mpAnimation ? mpAnimation->GetLoopCount() : 0;
}
void ImpGraphic::ImplSetContext( const std::shared_ptr<GraphicReader>& pReader )
@@ -1104,6 +1193,8 @@ void ImpGraphic::ImplSetContext( const std::shared_ptr<GraphicReader>& pReader )
bool ImpGraphic::ImplReadEmbedded( SvStream& rIStm )
{
+ ensureAvailable();
+
MapMode aMapMode;
Size aSize;
sal_uInt32 nId;
@@ -1405,17 +1496,37 @@ bool ImpGraphic::ImplSwapOut( SvStream* xOStm )
bool ImpGraphic::ensureAvailable() const
{
auto pThis = const_cast<ImpGraphic*>(this);
- pThis->maLastUsed = std::chrono::high_resolution_clock::now();
+
if (ImplIsSwapOut())
return pThis->ImplSwapIn();
+
+ pThis->maLastUsed = std::chrono::high_resolution_clock::now();
return true;
}
+bool ImpGraphic::loadPrepared()
+{
+ Graphic aGraphic;
+ if (mpGfxLink->LoadNative(aGraphic))
+ {
+ *this = *aGraphic.ImplGetImpGraphic();
+ return true;
+ }
+ return false;
+}
+
bool ImpGraphic::ImplSwapIn()
{
bool bRet = false;
- if( ImplIsSwapOut() )
+ if (!ImplIsSwapOut())
+ return bRet;
+
+ if (mbPrepared)
+ {
+ bRet = loadPrepared();
+ }
+ else
{
OUString aSwapURL;
@@ -1763,6 +1874,8 @@ void WriteImpGraphic(SvStream& rOStm, const ImpGraphic& rImpGraphic)
if (rOStm.GetError())
return;
+ rImpGraphic.ensureAvailable();
+
if (rImpGraphic.ImplIsSwapOut())
{
rOStm.SetError( SVSTREAM_GENERALERROR );
diff --git a/vcl/source/graphic/GraphicObject.cxx b/vcl/source/graphic/GraphicObject.cxx
index b3f6a52f6b0b..c855c901b27c 100644
--- a/vcl/source/graphic/GraphicObject.cxx
+++ b/vcl/source/graphic/GraphicObject.cxx
@@ -303,27 +303,17 @@ struct GrfSimpleCacheObj
GraphicObject::GraphicObject()
{
- ImplAssignGraphicData();
}
GraphicObject::GraphicObject(const Graphic& rGraphic)
: maGraphic(rGraphic)
{
- ImplAssignGraphicData();
}
GraphicObject::GraphicObject(const GraphicObject& rGraphicObj)
: maGraphic(rGraphicObj.GetGraphic())
, maAttr(rGraphicObj.maAttr)
- , maPrefSize(rGraphicObj.maPrefSize)
- , maPrefMapMode(rGraphicObj.maPrefMapMode)
- , mnSizeBytes(rGraphicObj.mnSizeBytes)
- , meType(rGraphicObj.meType)
, maUserData(rGraphicObj.maUserData)
- , mnAnimationLoopCount(rGraphicObj.mnAnimationLoopCount)
- , mbTransparent(rGraphicObj.mbTransparent)
- , mbAnimated(rGraphicObj.mbAnimated)
- , mbEPS(rGraphicObj.mbEPS)
{
}
@@ -331,16 +321,34 @@ GraphicObject::~GraphicObject()
{
}
-void GraphicObject::ImplAssignGraphicData()
+GraphicType GraphicObject::GetType() const
{
- maPrefSize = maGraphic.GetPrefSize();
- maPrefMapMode = maGraphic.GetPrefMapMode();
- mnSizeBytes = maGraphic.GetSizeBytes();
- meType = maGraphic.GetType();
- mbTransparent = maGraphic.IsTransparent();
- mbAnimated = maGraphic.IsAnimated();
- mbEPS = maGraphic.IsEPS();
- mnAnimationLoopCount = ( mbAnimated ? maGraphic.GetAnimationLoopCount() : 0 );
+ return maGraphic.GetType();
+}
+
+Size GraphicObject::GetPrefSize() const
+{
+ return maGraphic.GetPrefSize();
+}
+
+MapMode GraphicObject::GetPrefMapMode() const
+{
+ return maGraphic.GetPrefMapMode();
+}
+
+bool GraphicObject::IsTransparent() const
+{
+ return maGraphic.IsTransparent();
+}
+
+bool GraphicObject::IsAnimated() const
+{
+ return maGraphic.IsAnimated();
+}
+
+bool GraphicObject::IsEPS() const
+{
+ return maGraphic.IsEPS();
}
bool GraphicObject::ImplGetCropParams( OutputDevice const * pOut, Point& rPt, Size& rSz, const GraphicAttr* pAttr,
@@ -420,7 +428,6 @@ GraphicObject& GraphicObject::operator=( const GraphicObject& rGraphicObj )
maGraphic = rGraphicObj.GetGraphic();
maAttr = rGraphicObj.maAttr;
maUserData = rGraphicObj.maUserData;
- ImplAssignGraphicData();
}
return *this;
@@ -551,10 +558,9 @@ bool GraphicObject::StartAnimation( OutputDevice* pOut, const Point& rPt, const
GetGraphic();
-
const GraphicAttr aAttr( GetAttr() );
- if( mbAnimated )
+ if (IsAnimated())
{
Point aPt( rPt );
Size aSz( rSz );
@@ -610,7 +616,6 @@ const Graphic& GraphicObject::GetGraphic() const
void GraphicObject::SetGraphic( const Graphic& rGraphic, const GraphicObject* /*pCopyObj*/)
{
maGraphic = rGraphic;
- ImplAssignGraphicData();
}
void GraphicObject::SetGraphic( const Graphic& rGraphic, const OUString& /*rLink*/ )
@@ -862,7 +867,7 @@ Graphic GraphicObject::GetTransformedGraphic( const GraphicAttr* pAttr ) const
{
Animation aAnimation( maGraphic.GetAnimation() );
lclImplAdjust( aAnimation, aAttr, GraphicAdjustmentFlags::ALL );
- aAnimation.SetLoopCount( mnAnimationLoopCount );
+ aAnimation.SetLoopCount(maGraphic.GetAnimationLoopCount());
aGraphic = aAnimation;
}
else
@@ -884,7 +889,7 @@ Graphic GraphicObject::GetTransformedGraphic( const GraphicAttr* pAttr ) const
if( ( GetType() == GraphicType::Bitmap ) && IsAnimated() )
{
Animation aAnimation( maGraphic.GetAnimation() );
- aAnimation.SetLoopCount( mnAnimationLoopCount );
+ aAnimation.SetLoopCount(maGraphic.GetAnimationLoopCount());
aGraphic = aAnimation;
}
else
diff --git a/vcl/source/graphic/Manager.cxx b/vcl/source/graphic/Manager.cxx
index 549b9c6d6add..106677cc0db4 100644
--- a/vcl/source/graphic/Manager.cxx
+++ b/vcl/source/graphic/Manager.cxx
@@ -71,7 +71,7 @@ void Manager::reduceGraphicMemory()
if (mnUsedSize < mnTotalCacheSize * 0.7)
return;
- sal_Int64 nCurrentGraphicSize = pEachImpGraphic->ImplGetSizeBytes();
+ sal_Int64 nCurrentGraphicSize = getGraphicSizeBytes(pEachImpGraphic);
if (!pEachImpGraphic->ImplIsSwapOut() && nCurrentGraphicSize > 1000000)
{
if (!pEachImpGraphic->mpContext)
@@ -87,6 +87,13 @@ void Manager::reduceGraphicMemory()
}
}
+sal_Int64 Manager::getGraphicSizeBytes(const ImpGraphic* pImpGraphic)
+{
+ if (!pImpGraphic->isAvailable())
+ return 0;
+ return pImpGraphic->ImplGetSizeBytes();
+}
+
IMPL_LINK(Manager, SwapOutTimerHandler, Timer*, pTimer, void)
{
pTimer->Stop();
@@ -102,7 +109,7 @@ void Manager::registerGraphic(std::shared_ptr<ImpGraphic>& pImpGraphic,
reduceGraphicMemory();
// Insert and update the used size (bytes)
- mnUsedSize += pImpGraphic->ImplGetSizeBytes();
+ mnUsedSize += getGraphicSizeBytes(pImpGraphic.get());
m_pImpGraphicList.insert(pImpGraphic.get());
// calculate size of the graphic set
@@ -111,7 +118,7 @@ void Manager::registerGraphic(std::shared_ptr<ImpGraphic>& pImpGraphic,
{
if (!pEachImpGraphic->ImplIsSwapOut())
{
- calculatedSize += pEachImpGraphic->ImplGetSizeBytes();
+ calculatedSize += getGraphicSizeBytes(pEachImpGraphic);
}
}
@@ -126,7 +133,7 @@ void Manager::registerGraphic(std::shared_ptr<ImpGraphic>& pImpGraphic,
void Manager::unregisterGraphic(ImpGraphic* pImpGraphic)
{
- mnUsedSize -= pImpGraphic->ImplGetSizeBytes();
+ mnUsedSize -= getGraphicSizeBytes(pImpGraphic);
m_pImpGraphicList.erase(pImpGraphic);
}
@@ -188,18 +195,18 @@ std::shared_ptr<ImpGraphic> Manager::newInstance(const GraphicExternalLink& rGra
void Manager::swappedIn(const ImpGraphic* pImpGraphic)
{
- mnUsedSize += pImpGraphic->ImplGetSizeBytes();
+ mnUsedSize += getGraphicSizeBytes(pImpGraphic);
}
void Manager::swappedOut(const ImpGraphic* pImpGraphic)
{
- mnUsedSize -= pImpGraphic->ImplGetSizeBytes();
+ mnUsedSize -= getGraphicSizeBytes(pImpGraphic);
}
void Manager::changeExisting(const ImpGraphic* pImpGraphic, sal_Int64 nOldSizeBytes)
{
mnUsedSize -= nOldSizeBytes;
- mnUsedSize += pImpGraphic->ImplGetSizeBytes();
+ mnUsedSize += getGraphicSizeBytes(pImpGraphic);
}
}
} // end vcl::graphic