diff options
-rw-r--r-- | include/svx/svdograf.hxx | 4 | ||||
-rw-r--r-- | include/vcl/GraphicObject.hxx | 23 | ||||
-rw-r--r-- | include/vcl/gfxlink.hxx | 10 | ||||
-rw-r--r-- | include/vcl/graph.hxx | 3 | ||||
-rw-r--r-- | include/vcl/graphicfilter.hxx | 3 | ||||
-rw-r--r-- | include/vcl/salctype.hxx | 3 | ||||
-rw-r--r-- | sc/qa/extras/anchor.cxx | 10 | ||||
-rw-r--r-- | sc/qa/unit/subsequent_export-test.cxx | 2 | ||||
-rw-r--r-- | sd/qa/unit/data/xml/fdo64586_0.xml | 4 | ||||
-rw-r--r-- | sd/qa/unit/data/xml/n758621_0.xml | 4 | ||||
-rw-r--r-- | sd/qa/unit/data/xml/n758621_1.xml | 4 | ||||
-rw-r--r-- | sd/qa/unit/data/xml/n819614_0.xml | 2 | ||||
-rw-r--r-- | sd/qa/unit/export-tests.cxx | 4 | ||||
-rw-r--r-- | svx/source/svdraw/svdograf.cxx | 6 | ||||
-rw-r--r-- | svx/source/xml/xmlgrhlp.cxx | 15 | ||||
-rw-r--r-- | sw/qa/extras/globalfilter/globalfilter.cxx | 5 | ||||
-rw-r--r-- | vcl/inc/graphic/Manager.hxx | 2 | ||||
-rw-r--r-- | vcl/inc/impgraph.hxx | 15 | ||||
-rw-r--r-- | vcl/source/filter/graphicfilter.cxx | 227 | ||||
-rw-r--r-- | vcl/source/gdi/gfxlink.cxx | 65 | ||||
-rw-r--r-- | vcl/source/gdi/graph.cxx | 10 | ||||
-rw-r--r-- | vcl/source/gdi/impgraph.cxx | 165 | ||||
-rw-r--r-- | vcl/source/graphic/GraphicObject.cxx | 55 | ||||
-rw-r--r-- | vcl/source/graphic/Manager.cxx | 21 |
24 files changed, 526 insertions, 136 deletions
diff --git a/include/svx/svdograf.hxx b/include/svx/svdograf.hxx index f3b0b1946564..9b1a4631b376 100644 --- a/include/svx/svdograf.hxx +++ b/include/svx/svdograf.hxx @@ -156,8 +156,8 @@ public: bool IsEPS() const; bool IsSwappedOut() const; - const MapMode& GetGrafPrefMapMode() const; - const Size& GetGrafPrefSize() const; + MapMode GetGrafPrefMapMode() const; + Size GetGrafPrefSize() const; void SetGrafStreamURL( const OUString& rGraphicStreamURL ); OUString const & GetGrafStreamURL() const; diff --git a/include/vcl/GraphicObject.hxx b/include/vcl/GraphicObject.hxx index 140ea7402540..d9f60e49598d 100644 --- a/include/vcl/GraphicObject.hxx +++ b/include/vcl/GraphicObject.hxx @@ -172,19 +172,9 @@ class VCL_DLLPUBLIC GraphicObject private: Graphic maGraphic; GraphicAttr maAttr; - Size maPrefSize; - MapMode maPrefMapMode; - sal_uLong mnSizeBytes; - GraphicType meType; OUString maUserData; std::unique_ptr<GrfSimpleCacheObj> mxSimpleCache; - sal_uInt32 mnAnimationLoopCount; - bool mbTransparent : 1; - bool mbAnimated : 1; - bool mbEPS : 1; - - void VCL_DLLPRIVATE ImplAssignGraphicData(); bool VCL_DLLPRIVATE ImplGetCropParams( OutputDevice const * pOut, Point& rPt, @@ -342,13 +332,12 @@ public: OString GetUniqueID() const; - GraphicType GetType() const { return meType; } - const Size& GetPrefSize() const { return maPrefSize; } - const MapMode& GetPrefMapMode() const { return maPrefMapMode; } - sal_uLong GetSizeBytes() const { return mnSizeBytes; } - bool IsTransparent() const { return mbTransparent; } - bool IsAnimated() const { return mbAnimated; } - bool IsEPS() const { return mbEPS; } + GraphicType GetType() const; + Size GetPrefSize() const; + MapMode GetPrefMapMode() const; + bool IsTransparent() const; + bool IsAnimated() const; + bool IsEPS() const; bool Draw( OutputDevice* pOut, diff --git a/include/vcl/gfxlink.hxx b/include/vcl/gfxlink.hxx index 2d84fd293e4f..054ab2cf2dca 100644 --- a/include/vcl/gfxlink.hxx +++ b/include/vcl/gfxlink.hxx @@ -64,17 +64,17 @@ private: }; - GfxLinkType meType = GfxLinkType::NONE; - sal_uInt32 mnUserId = 0; + GfxLinkType meType; + sal_uInt32 mnUserId; std::shared_ptr<sal_uInt8> mpSwapInData; std::shared_ptr<SwapOutData> mpSwapOutData; - sal_uInt32 mnSwapInDataSize = 0; + sal_uInt32 mnSwapInDataSize; MapMode maPrefMapMode; Size maPrefSize; - bool mbPrefMapModeValid = false; - bool mbPrefSizeValid = false; + bool mbPrefMapModeValid; + bool mbPrefSizeValid; SAL_DLLPRIVATE std::shared_ptr<sal_uInt8> GetSwapInData() const; public: diff --git a/include/vcl/graph.hxx b/include/vcl/graph.hxx index d69b9e8538b0..8406686c6e09 100644 --- a/include/vcl/graph.hxx +++ b/include/vcl/graph.hxx @@ -144,6 +144,9 @@ public: bool IsAnimated() const; bool IsEPS() const; + bool isAvailable() const; + bool makeAvailable(); + // #i102089# Access of Bitmap potentially will have to rasterconvert the Graphic // if it is a MetaFile. To be able to control this conversion it is necessary to // allow giving parameters which control AntiAliasing and LineSnapping of the diff --git a/include/vcl/graphicfilter.hxx b/include/vcl/graphicfilter.hxx index bc218851f412..adf308914837 100644 --- a/include/vcl/graphicfilter.hxx +++ b/include/vcl/graphicfilter.hxx @@ -98,6 +98,7 @@ namespace o3tl #define WMF_SHORTNAME "WMF" #define EMF_SHORTNAME "EMF" #define SVG_SHORTNAME "SVG" +#define PDF_SHORTNAME "PDF" // Info class for all supported file formats @@ -289,6 +290,8 @@ public: css::uno::Sequence< css::beans::PropertyValue >* pFilterData, WmfExternal const *pExtHeader = nullptr ); + Graphic ImportUnloadedGraphic(SvStream& rIStream); + const FilterErrorEx& GetLastError() const { return *pErrorEx;} void ResetLastError(); diff --git a/include/vcl/salctype.hxx b/include/vcl/salctype.hxx index 409fc5a79993..893adb4d47e4 100644 --- a/include/vcl/salctype.hxx +++ b/include/vcl/salctype.hxx @@ -37,7 +37,8 @@ enum class ConvertDataFormat TIF, WMF, EMF, - SVG + SVG, + PDF }; class SvStream; diff --git a/sc/qa/extras/anchor.cxx b/sc/qa/extras/anchor.cxx index 1407b784fa9e..133b1bdae043 100644 --- a/sc/qa/extras/anchor.cxx +++ b/sc/qa/extras/anchor.cxx @@ -87,7 +87,7 @@ void ScAnchorTest::testUndoAnchor() const GraphicObject& rGraphicObj = pObject->GetGraphicObject(true); CPPUNIT_ASSERT_EQUAL(int(GraphicType::Bitmap), int(rGraphicObj.GetGraphic().GetType())); - CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj.GetSizeBytes()); + CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj.GetGraphic().GetSizeBytes()); // Get the document controller ScTabViewShell* pViewShell = pDocSh->GetBestViewShell(false); @@ -121,14 +121,14 @@ void ScAnchorTest::testUndoAnchor() // Check anchor type CPPUNIT_ASSERT_EQUAL(oldType, ScDrawLayer::GetAnchorType(*pObject)); CPPUNIT_ASSERT_EQUAL(int(GraphicType::Bitmap), int(rGraphicObj.GetGraphic().GetType())); - CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj.GetSizeBytes()); + CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj.GetGraphic().GetSizeBytes()); pUndoMgr->Redo(); // Check anchor type CPPUNIT_ASSERT_EQUAL(newType, ScDrawLayer::GetAnchorType(*pObject)); CPPUNIT_ASSERT_EQUAL(int(GraphicType::Bitmap), int(rGraphicObj.GetGraphic().GetType())); - CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj.GetSizeBytes()); + CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj.GetGraphic().GetSizeBytes()); ScDrawLayer::SetPageAnchored(*pObject); // Check state @@ -146,14 +146,14 @@ void ScAnchorTest::testUndoAnchor() // Check anchor type CPPUNIT_ASSERT_EQUAL(oldType, ScDrawLayer::GetAnchorType(*pObject)); CPPUNIT_ASSERT_EQUAL(int(GraphicType::Bitmap), int(rGraphicObj.GetGraphic().GetType())); - CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj.GetSizeBytes()); + CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj.GetGraphic().GetSizeBytes()); pUndoMgr->Redo(); // Check anchor type CPPUNIT_ASSERT_EQUAL(newType, ScDrawLayer::GetAnchorType(*pObject)); CPPUNIT_ASSERT_EQUAL(int(GraphicType::Bitmap), int(rGraphicObj.GetGraphic().GetType())); - CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj.GetSizeBytes()); + CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj.GetGraphic().GetSizeBytes()); xComponent->dispose(); } diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx index 1339274f5ddd..2a7a76e244a8 100644 --- a/sc/qa/unit/subsequent_export-test.cxx +++ b/sc/qa/unit/subsequent_export-test.cxx @@ -3253,7 +3253,7 @@ void ScExportTest::testLinkedGraphicRT() const GraphicObject& rGraphicObj = pObject->GetGraphicObject(true); CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), int(GraphicType::Bitmap), int(rGraphicObj.GetGraphic().GetType())); - CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), sal_uLong(864900), rGraphicObj.GetSizeBytes()); + CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), sal_uLong(864900), rGraphicObj.GetGraphic().GetSizeBytes()); xDocSh2->DoClose(); } diff --git a/sd/qa/unit/data/xml/fdo64586_0.xml b/sd/qa/unit/data/xml/fdo64586_0.xml index a2487832299c..4ba0afe041a5 100644 --- a/sd/qa/unit/data/xml/fdo64586_0.xml +++ b/sd/qa/unit/data/xml/fdo64586_0.xml @@ -4,7 +4,7 @@ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/> <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/> <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/> - <FillBitmap/> + <FillBitmap width="32" height="32"/> <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/> <LineStart/> <LineEnd/> @@ -18,7 +18,7 @@ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/> <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/> <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/> - <FillBitmap/> + <FillBitmap width="32" height="32"/> <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/> <LineStart/> <LineEnd/> diff --git a/sd/qa/unit/data/xml/n758621_0.xml b/sd/qa/unit/data/xml/n758621_0.xml index 754be1d41ed1..dc3e0935cc3e 100644 --- a/sd/qa/unit/data/xml/n758621_0.xml +++ b/sd/qa/unit/data/xml/n758621_0.xml @@ -4,7 +4,7 @@ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/> <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/> <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/> - <FillBitmap/> + <FillBitmap width="32" height="32"/> <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/> <LineStart/> <LineEnd/> @@ -18,7 +18,7 @@ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/> <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/> <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/> - <FillBitmap/> + <FillBitmap width="32" height="32"/> <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/> <LineStart/> <LineEnd/> diff --git a/sd/qa/unit/data/xml/n758621_1.xml b/sd/qa/unit/data/xml/n758621_1.xml index 0f71931585bb..0b826248fdc9 100644 --- a/sd/qa/unit/data/xml/n758621_1.xml +++ b/sd/qa/unit/data/xml/n758621_1.xml @@ -4,7 +4,7 @@ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/> <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/> <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/> - <FillBitmap/> + <FillBitmap width="32" height="32"/> <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/> <LineStart/> <LineEnd/> @@ -18,7 +18,7 @@ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/> <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/> <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/> - <FillBitmap/> + <FillBitmap width="32" height="32"/> <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/> <LineStart/> <LineEnd/> diff --git a/sd/qa/unit/data/xml/n819614_0.xml b/sd/qa/unit/data/xml/n819614_0.xml index 368a2fafcd2b..e51b520d3130 100644 --- a/sd/qa/unit/data/xml/n819614_0.xml +++ b/sd/qa/unit/data/xml/n819614_0.xml @@ -4,7 +4,7 @@ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/> <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/> <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/> - <FillBitmap/> + <FillBitmap width="32" height="32"/> <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/> <LineStart/> <LineEnd/> diff --git a/sd/qa/unit/export-tests.cxx b/sd/qa/unit/export-tests.cxx index fca7018e836d..f5c7c4e97d15 100644 --- a/sd/qa/unit/export-tests.cxx +++ b/sd/qa/unit/export-tests.cxx @@ -590,7 +590,7 @@ void SdExportTest::testLinkedGraphicRT() const GraphicObject& rGraphicObj = pObject->GetGraphicObject(true); CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedImportMessage.getStr(), int(GraphicType::Bitmap), int(rGraphicObj.GetGraphic().GetType())); - CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedImportMessage.getStr(), sal_uLong(864900), rGraphicObj.GetSizeBytes()); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedImportMessage.getStr(), sal_uLong(864900), rGraphicObj.GetGraphic().GetSizeBytes()); } // Save and reload @@ -615,7 +615,7 @@ void SdExportTest::testLinkedGraphicRT() const GraphicObject& rGraphicObj = pObject->GetGraphicObject(true); CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), int(GraphicType::Bitmap), int(rGraphicObj.GetGraphic().GetType())); - CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), sal_uLong(864900), rGraphicObj.GetSizeBytes()); + CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), sal_uLong(864900), rGraphicObj.GetGraphic().GetSizeBytes()); } xDocShRef->DoClose(); diff --git a/svx/source/svdraw/svdograf.cxx b/svx/source/svdraw/svdograf.cxx index 018aef7e018b..48949649e8f5 100644 --- a/svx/source/svdraw/svdograf.cxx +++ b/svx/source/svdraw/svdograf.cxx @@ -282,7 +282,7 @@ sdr::contact::ViewContact* SdrGrafObj::CreateObjectSpecificViewContact() void SdrGrafObj::onGraphicChanged() { - if (!mpGraphicObject) // don't force swap-in for this + if (!mpGraphicObject || !mpGraphicObject->GetGraphic().isAvailable()) return; const VectorGraphicDataPtr& rVectorGraphicDataPtr = mpGraphicObject->GetGraphic().getVectorGraphicData(); @@ -551,12 +551,12 @@ bool SdrGrafObj::IsSwappedOut() const return false; } -const MapMode& SdrGrafObj::GetGrafPrefMapMode() const +MapMode SdrGrafObj::GetGrafPrefMapMode() const { return mpGraphicObject->GetPrefMapMode(); } -const Size& SdrGrafObj::GetGrafPrefSize() const +Size SdrGrafObj::GetGrafPrefSize() const { return mpGraphicObject->GetPrefSize(); } diff --git a/svx/source/xml/xmlgrhlp.cxx b/svx/source/xml/xmlgrhlp.cxx index e420cc103274..971402aea6b0 100644 --- a/svx/source/xml/xmlgrhlp.cxx +++ b/svx/source/xml/xmlgrhlp.cxx @@ -493,15 +493,20 @@ OUString SvXMLGraphicHelper::ImplGetGraphicMimeType( const OUString& rFileName ) Graphic SvXMLGraphicHelper::ImplReadGraphic( const OUString& rPictureStorageName, const OUString& rPictureStreamName ) { - Graphic aGraphic; + Graphic aReturnGraphic; SvxGraphicHelperStream_Impl aStream( ImplGetGraphicStream( rPictureStorageName, rPictureStreamName ) ); - if( aStream.xStream.is() ) + if (aStream.xStream.is()) { - std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream( aStream.xStream )); - GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic, "", *pStream ); + GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter(); + std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(aStream.xStream)); + Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(*pStream); + if (aGraphic) + aReturnGraphic = aGraphic; + else + rGraphicFilter.ImportGraphic(aReturnGraphic, "", *pStream); } - return aGraphic; + return aReturnGraphic; } void SvXMLGraphicHelper::Init( const uno::Reference < embed::XStorage >& rXMLStorage, diff --git a/sw/qa/extras/globalfilter/globalfilter.cxx b/sw/qa/extras/globalfilter/globalfilter.cxx index 66b0d72d31b3..2145eb9fde55 100644 --- a/sw/qa/extras/globalfilter/globalfilter.cxx +++ b/sw/qa/extras/globalfilter/globalfilter.cxx @@ -184,8 +184,9 @@ void Test::testLinkedGraphicRT() CPPUNIT_ASSERT(pGrfNode); const GraphicObject& rGraphicObj = pGrfNode->GetGrfObj(true); - CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), int(GraphicType::Bitmap), int(rGraphicObj.GetType())); - CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), static_cast<sal_uLong>(864900), rGraphicObj.GetSizeBytes()); + const Graphic& rGraphic = rGraphicObj.GetGraphic(); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(GraphicType::Bitmap), int(rGraphic.GetType())); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_uLong(864900), rGraphic.GetSizeBytes()); bImageFound = true; } } 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 |