diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2018-03-31 17:27:01 +0900 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2018-04-10 08:33:55 +0200 |
commit | ea3d755ac949c1b6dada5c341e018f8c23f5d395 (patch) | |
tree | 086b3573d3e2f64fd918df4996d1f00ad9aa863b | |
parent | 94185507ed11bf6e2e2e9fa47c247680ae1edb36 (diff) |
vcl: detach usage and remove GraphicManager and GraphicCache
Also remove some GraphicObjectTest because they call into
GraphicManager which now doesn't exist anymore.
Change-Id: Ia434736d8611df629af3e897c878a7fb8bbe4706
Reviewed-on: https://gerrit.libreoffice.org/52243
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r-- | include/vcl/GraphicObject.hxx | 143 | ||||
-rw-r--r-- | include/vcl/graph.hxx | 2 | ||||
-rw-r--r-- | solenv/clang-format/blacklist | 2 | ||||
-rw-r--r-- | svtools/qa/unit/GraphicObjectTest.cxx | 157 | ||||
-rw-r--r-- | sw/source/core/doc/notxtfrm.cxx | 23 | ||||
-rw-r--r-- | vcl/Library_vcl.mk | 1 | ||||
-rw-r--r-- | vcl/inc/impgraph.hxx | 34 | ||||
-rw-r--r-- | vcl/source/gdi/graph.cxx | 8 | ||||
-rw-r--r-- | vcl/source/gdi/impgraph.cxx | 70 | ||||
-rw-r--r-- | vcl/source/graphic/GraphicObject.cxx | 313 | ||||
-rw-r--r-- | vcl/source/graphic/GraphicObject2.cxx | 1552 | ||||
-rw-r--r-- | vcl/source/graphic/grfcache.cxx | 1221 | ||||
-rw-r--r-- | vcl/source/graphic/grfcache.hxx | 136 |
13 files changed, 317 insertions, 3345 deletions
diff --git a/include/vcl/GraphicObject.hxx b/include/vcl/GraphicObject.hxx index fbd063687e34..64f912e4876d 100644 --- a/include/vcl/GraphicObject.hxx +++ b/include/vcl/GraphicObject.hxx @@ -169,13 +169,9 @@ public: class VCL_DLLPUBLIC GraphicObject { - friend class GraphicManager; friend class SdrGrafObj; private: - - static GraphicManager* mpGlobalMgr; - Graphic maGraphic; GraphicAttr maAttr; Size maPrefSize; @@ -304,10 +300,6 @@ private: ) const; DECL_LINK( ImplAutoSwapOutHdl, Timer*, void ); - - // Handle evtl. needed AfterDataChanges, needs to be called when new - // graphic data is swapped in/added to the GraphicManager - void VCL_DLLPRIVATE ImplAfterDataChange(); protected: SvStream* GetSwapStream() const; @@ -329,20 +321,6 @@ public: void FireSwapInRequest(); void FireSwapOutRequest(); - GraphicManager& GetGraphicManager() const - { - (void)this; // avoid loplugin:staticmethods because first GraphicManager ctor creates - // mpGlobalMgr and the last GraphicManager dtor destroys it - return *mpGlobalMgr; - } - - bool IsCached( - OutputDevice const * pOut, - const Size& rSz, - const GraphicAttr* pAttr, - GraphicManagerDrawFlags nFlags = GraphicManagerDrawFlags::STANDARD - ) const; - const Graphic& GetGraphic() const; void SetGraphic( const Graphic& rGraphic, const GraphicObject* pCopyObj = nullptr); void SetGraphic( const Graphic& rGraphic, const OUString& rLink ); @@ -477,127 +455,6 @@ public: double fTopCrop, double fRightCrop, double fBottomCrop) const; - - // read access - sal_uLong GetDataChangeTimeStamp() const { return mnDataChangeTimeStamp; } -}; - -class VCL_DLLPUBLIC GraphicManager -{ - friend class GraphicObject; - friend class GraphicDisplayCacheEntry; - -private: - - std::unordered_set< GraphicObject* > maObjList; - sal_uLong mnUsedSize; // currently used memory footprint of all swapped in graphics - std::unique_ptr<GraphicCache> mpCache; - - GraphicManager( const GraphicManager& ) = delete; - GraphicManager& operator=( const GraphicManager& ) = delete; - - bool VCL_DLLPRIVATE ImplDraw( - OutputDevice* pOut, - const Point& rPt, - const Size& rSz, - GraphicObject const & rObj, - const GraphicAttr& rAttr, - bool& rCached - ); - - static bool VCL_DLLPRIVATE ImplCreateOutput( - OutputDevice* pOut, - const Point& rPt, - const Size& rSz, - const BitmapEx& rBmpEx, - const GraphicAttr& rAttr, - BitmapEx* pBmpEx = nullptr - ); - static bool VCL_DLLPRIVATE ImplCreateOutput( - OutputDevice* pOut, - const Point& rPt, - const Size& rSz, - const GDIMetaFile& rMtf, - const GraphicAttr& rAttr, - GDIMetaFile& rOutMtf, - BitmapEx& rOutBmpEx - ); - - static void VCL_DLLPRIVATE ImplAdjust( - BitmapEx& rBmpEx, - const GraphicAttr& rAttr, - GraphicAdjustmentFlags nAdjustmentFlags - ); - static void VCL_DLLPRIVATE ImplAdjust( - GDIMetaFile& rMtf, - const GraphicAttr& rAttr, - GraphicAdjustmentFlags nAdjustmentFlags - ); - static void VCL_DLLPRIVATE ImplAdjust( - Animation& rAnimation, - const GraphicAttr& rAttr, - GraphicAdjustmentFlags nAdjustmentFlags - ); - - static void VCL_DLLPRIVATE ImplDraw( - OutputDevice* pOut, - const Point& rPt, - const Size& rSz, - const GDIMetaFile& rMtf, - const GraphicAttr& rAttr - ); - - // Only used by GraphicObject's Ctor's and Dtor's - void VCL_DLLPRIVATE ImplRegisterObj( - const GraphicObject& rObj, - Graphic& rSubstitute, - const OString* pID, - const GraphicObject* pCopyObj - ); - void VCL_DLLPRIVATE ImplUnregisterObj( const GraphicObject& rObj ); - bool VCL_DLLPRIVATE ImplHasObjects() const { return !maObjList.empty(); } - - // Only used in swap case by GraphicObject - void VCL_DLLPRIVATE ImplGraphicObjectWasSwappedOut( const GraphicObject& rObj ); - void VCL_DLLPRIVATE ImplGraphicObjectWasSwappedIn( const GraphicObject& rObj ); - - OString VCL_DLLPRIVATE ImplGetUniqueID( const GraphicObject& rObj ) const; - - // This method allows to check memory footprint for all currently swapped in GraphicObjects on this GraphicManager - // which are based on Bitmaps. This is needed on 32Bit systems and only does something on those systems. The problem - // to solve is that normally the SwapOut is timer-driven, but even with short timer settings there are situations - // where this does not trigger - or in other words: A maximum limitation for GraphicManagers was not in place before. - // For 32Bit systems this leads to situations where graphics will be missing. This method will actively swap out - // the longest swapped in graphics until a maximum memory boundary (derived from user settings in tools/options/memory) - // is no longer exceeded - void VCL_DLLPRIVATE ImplCheckSizeOfSwappedInGraphics(const GraphicObject* pGraphicToIgnore); -public: - - GraphicManager( sal_uLong nCacheSize, sal_uLong nMaxObjCacheSize ); - ~GraphicManager(); - - void SetMaxCacheSize( sal_uLong nNewCacheSize ); - sal_uLong GetMaxCacheSize() const; - - void SetCacheTimeout( sal_uLong nTimeoutSeconds ); - - bool IsInCache( - OutputDevice const * pOut, - const Point& rPt, - const Size& rSz, - const GraphicObject& rObj, - const GraphicAttr& rAttr - ) const; - - bool DrawObj( - OutputDevice* pOut, - const Point& rPt, - const Size& rSz, - GraphicObject const & rObj, - const GraphicAttr& rAttr, - const GraphicManagerDrawFlags nFlags, - bool& rCached - ); }; namespace vcl diff --git a/include/vcl/graph.hxx b/include/vcl/graph.hxx index 4915fa0e347a..9be22958b446 100644 --- a/include/vcl/graph.hxx +++ b/include/vcl/graph.hxx @@ -201,6 +201,8 @@ public: OUString getOriginURL() const; void setOriginURL(OUString const & rOriginURL); + OString getUniqueID() const; + public: std::shared_ptr<GraphicReader>& GetContext(); diff --git a/solenv/clang-format/blacklist b/solenv/clang-format/blacklist index 50e828ba480e..91618660943c 100644 --- a/solenv/clang-format/blacklist +++ b/solenv/clang-format/blacklist @@ -18213,8 +18213,6 @@ vcl/source/graphic/UnoGraphicObject.cxx vcl/source/graphic/UnoGraphicProvider.cxx vcl/source/graphic/UnoGraphicTransformer.cxx vcl/source/graphic/grfattr.cxx -vcl/source/graphic/grfcache.cxx -vcl/source/graphic/grfcache.hxx vcl/source/helper/canvasbitmap.cxx vcl/source/helper/canvastools.cxx vcl/source/helper/commandinfoprovider.cxx diff --git a/svtools/qa/unit/GraphicObjectTest.cxx b/svtools/qa/unit/GraphicObjectTest.cxx index ee119e46c793..6d748b8d180d 100644 --- a/svtools/qa/unit/GraphicObjectTest.cxx +++ b/svtools/qa/unit/GraphicObjectTest.cxx @@ -38,9 +38,7 @@ class GraphicObjectTest: public test::BootstrapFixture, public unotest::MacrosTe public: void testSwap(); - void testSizeBasedAutoSwap(); void testTdf88836(); - void testTdf88935(); void testPdf(); @@ -57,9 +55,7 @@ private: private: CPPUNIT_TEST_SUITE(GraphicObjectTest); CPPUNIT_TEST(testSwap); - CPPUNIT_TEST(testSizeBasedAutoSwap); CPPUNIT_TEST(testTdf88836); - CPPUNIT_TEST(testTdf88935); CPPUNIT_TEST(testPdf); CPPUNIT_TEST_SUITE_END(); }; @@ -147,92 +143,6 @@ void GraphicObjectTest::testSwap() } } -void GraphicObjectTest::testSizeBasedAutoSwap() -{ - // Set cache size to a very small value to check what happens - { - std::shared_ptr< comphelper::ConfigurationChanges > aBatch(comphelper::ConfigurationChanges::create()); - officecfg::Office::Common::Cache::GraphicManager::TotalCacheSize::set(sal_Int32(1), aBatch); - aBatch->commit(); - } - - uno::Reference< lang::XComponent > xComponent = - loadFromDesktop(m_directories.getURLFromSrc("svtools/qa/unit/data/document_with_two_images.odt"), "com.sun.star.text.TextDocument"); - - SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(xComponent.get()); - CPPUNIT_ASSERT(pTxtDoc); - SwDoc* pDoc = pTxtDoc->GetDocShell()->GetDoc(); - CPPUNIT_ASSERT(pDoc); - SwNodes& aNodes = pDoc->GetNodes(); - - // Find images - const GraphicObject* pGrafObj1 = nullptr; - const GraphicObject* pGrafObj2 = nullptr; - for( sal_uLong nIndex = 0; nIndex < aNodes.Count(); ++nIndex) - { - if( aNodes[nIndex]->IsGrfNode() ) - { - SwGrfNode* pGrfNode = aNodes[nIndex]->GetGrfNode(); - CPPUNIT_ASSERT(pGrfNode); - if( !pGrafObj1 ) - { - pGrafObj1 = &pGrfNode->GetGrfObj(); - } - else - { - pGrafObj2 = &pGrfNode->GetGrfObj(); - } - } - } - CPPUNIT_ASSERT_MESSAGE("Missing image", pGrafObj1 != nullptr && pGrafObj2 != nullptr); - - { - // First image should be swapped out - CPPUNIT_ASSERT(pGrafObj1->IsSwappedOut()); - CPPUNIT_ASSERT_EQUAL(sal_uLong(697230), pGrafObj1->GetSizeBytes()); - - // Still swapped out: size is cached - CPPUNIT_ASSERT(pGrafObj1->IsSwappedOut()); - } - - { - // Second image should be in the memory - // Size based swap out is triggered by swap in, so the last swapped in image should be - // in the memory despite of size limit is reached. - CPPUNIT_ASSERT(!pGrafObj2->IsSwappedOut()); - CPPUNIT_ASSERT_EQUAL(sal_uLong(1620000), pGrafObj2->GetSizeBytes()); - } - - // Swap in first image -> second image will be swapped out - { - pGrafObj1->GetGraphic(); // GetGraphic calls swap in on a const object - CPPUNIT_ASSERT(!pGrafObj1->IsSwappedOut()); - CPPUNIT_ASSERT(pGrafObj2->IsSwappedOut()); - } - - // Swap in second image -> first image will be swapped out - { - pGrafObj2->GetGraphic(); // GetGraphic calls swap in on a const object - CPPUNIT_ASSERT(!pGrafObj2->IsSwappedOut()); - CPPUNIT_ASSERT(pGrafObj1->IsSwappedOut()); - } - - // Use bigger cache - { - GraphicManager& rGrfMgr = pGrafObj1->GetGraphicManager(); - rGrfMgr.SetMaxCacheSize((pGrafObj1->GetSizeBytes()+pGrafObj2->GetSizeBytes())*10); - } - // Swap in both images -> both should be swapped in - { - pGrafObj1->GetGraphic(); - pGrafObj2->GetGraphic(); - CPPUNIT_ASSERT(!pGrafObj1->IsSwappedOut()); - CPPUNIT_ASSERT(!pGrafObj2->IsSwappedOut()); - } - - xComponent->dispose(); -} - void GraphicObjectTest::testTdf88836() { // Construction with empty bitmap -> type should be GraphicType::NONE @@ -242,73 +152,6 @@ void GraphicObjectTest::testTdf88836() CPPUNIT_ASSERT_EQUAL(int(GraphicType::NONE), int(aGraphic.GetType())); } -void GraphicObjectTest::testTdf88935() -{ - // Cache size was not updated by deletion of graphic objects - - // Load a file with two images - uno::Reference< lang::XComponent > xComponent = - loadFromDesktop(m_directories.getURLFromSrc("svtools/qa/unit/data/document_with_two_images.odt"), "com.sun.star.text.TextDocument"); - SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(xComponent.get()); - CPPUNIT_ASSERT(pTxtDoc); - SwDoc* pDoc = pTxtDoc->GetDocShell()->GetDoc(); - CPPUNIT_ASSERT(pDoc); - SwNodes& aNodes = pDoc->GetNodes(); - - // Find images - const GraphicObject* pGraphObj1 = nullptr; - const GraphicObject* pGraphObj2 = nullptr; - for( sal_uLong nIndex = 0; nIndex < aNodes.Count(); ++nIndex) - { - if( aNodes[nIndex]->IsGrfNode() ) - { - SwGrfNode* pGrfNode = aNodes[nIndex]->GetGrfNode(); - CPPUNIT_ASSERT(pGrfNode); - if( !pGraphObj1 ) - { - pGraphObj1 = &pGrfNode->GetGrfObj(); - } - else - { - pGraphObj2 = &pGrfNode->GetGrfObj(); - } - } - } - CPPUNIT_ASSERT_MESSAGE("Missing image", pGraphObj1 != nullptr && pGraphObj2 != nullptr); - - // Set cache size - { - GraphicManager& rGrfMgr = pGraphObj1->GetGraphicManager(); - rGrfMgr.SetMaxCacheSize((pGraphObj1->GetSizeBytes()+pGraphObj2->GetSizeBytes())*10); - } - - // Both images fit into the cache - { - pGraphObj1->GetGraphic(); - pGraphObj2->GetGraphic(); - CPPUNIT_ASSERT(!pGraphObj1->IsSwappedOut()); - CPPUNIT_ASSERT(!pGraphObj2->IsSwappedOut()); - } - - // Create and remove some copy of the first image - for( int i = 0; i < 50; ++i ) - { - GraphicObject aGraphObj3(*pGraphObj1); - CPPUNIT_ASSERT(aGraphObj3.SwapOut()); - CPPUNIT_ASSERT(aGraphObj3.SwapIn()); - } - - // Both images fit into the cache - { - pGraphObj1->GetGraphic(); - pGraphObj2->GetGraphic(); - CPPUNIT_ASSERT(!pGraphObj1->IsSwappedOut()); - CPPUNIT_ASSERT(!pGraphObj2->IsSwappedOut()); - } - - xComponent->dispose(); -} - void GraphicObjectTest::testPdf() { #if HAVE_FEATURE_PDFIUM diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx index 4aae97a40690..6d503dce45fa 100644 --- a/sw/source/core/doc/notxtfrm.cxx +++ b/sw/source/core/doc/notxtfrm.cxx @@ -743,29 +743,8 @@ void SwNoTextFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew ) case RES_GRF_REREAD_AND_INCACHE: if( SwNodeType::Grf == GetNode()->GetNodeType() ) { + // TODO: Remove - due to GraphicObject refactoring bComplete = false; - SwGrfNode* pNd = static_cast<SwGrfNode*>( GetNode()); - - SwViewShell* pVSh = pNd->GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell(); - if( pVSh ) - { - GraphicAttr aAttr; - if( pNd->GetGrfObj().IsCached( pVSh->GetOut(), - getFramePrintArea().SSize(), &pNd->GetGraphicAttr( aAttr, this ) )) - { - for(SwViewShell& rShell : pVSh->GetRingContainer()) - { - SET_CURR_SHELL( &rShell ); - if( rShell.GetWin() ) - { - if( rShell.IsPreview() ) - ::RepaintPagePreview( &rShell, getFrameArea().SVRect() ); - else - rShell.GetWin()->Invalidate( getFrameArea().SVRect() ); - } - } - } - } } break; diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index 82971a424eb3..b6212ba959a4 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -304,7 +304,6 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/source/graphic/GraphicLoader \ vcl/source/graphic/GraphicObject \ vcl/source/graphic/GraphicObject2 \ - vcl/source/graphic/grfcache \ vcl/source/graphic/grfattr \ vcl/source/graphic/UnoGraphic \ vcl/source/graphic/UnoGraphicDescriptor \ diff --git a/vcl/inc/impgraph.hxx b/vcl/inc/impgraph.hxx index 6c76275abbb2..834113130bbe 100644 --- a/vcl/inc/impgraph.hxx +++ b/vcl/inc/impgraph.hxx @@ -31,9 +31,35 @@ class GfxLink; struct ImpSwapFile; class GraphicConversionParameters; +class GraphicID +{ +private: + sal_uInt32 mnID1; + sal_uInt32 mnID2; + sal_uInt32 mnID3; + BitmapChecksum mnID4; + +public: + GraphicID(ImpGraphic& rGraphic); + + bool operator==(const GraphicID& rID) const + { + return rID.mnID1 == mnID1 && rID.mnID2 == mnID2 && + rID.mnID3 == mnID3 && rID.mnID4 == mnID4; + } + + bool IsEmpty() const + { + return 0 == mnID4; + } + + OString getIDString() const; +}; + class ImpGraphic final { friend class Graphic; + friend class GraphicID; private: @@ -51,6 +77,7 @@ private: VectorGraphicDataPtr maVectorGraphicData; css::uno::Sequence<sal_Int8> maPdfData; OUString msOriginURL; + std::unique_ptr<GraphicID> mpGraphicID; private: @@ -81,6 +108,13 @@ private: msOriginURL = rOriginURL; } + OString getUniqueID() + { + if (!mpGraphicID) + mpGraphicID.reset(new GraphicID(*this)); + return mpGraphicID->getIDString(); + } + void ImplCreateSwapInfo(); void ImplClearGraphics(); void ImplClear(); diff --git a/vcl/source/gdi/graph.cxx b/vcl/source/gdi/graph.cxx index a444ed0d70cf..150bc049d722 100644 --- a/vcl/source/gdi/graph.cxx +++ b/vcl/source/gdi/graph.cxx @@ -612,6 +612,14 @@ void Graphic::setOriginURL(OUString const & rOriginURL) } } +OString Graphic::getUniqueID() const +{ + OString aUniqueString; + if (mxImpGraphic) + aUniqueString = mxImpGraphic->getUniqueID(); + return aUniqueString; +} + namespace { struct Id: public rtl::Static<cppu::OImplementationId, Id> {}; diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx index 3fd0c7a1d034..0a2acd9538fd 100644 --- a/vcl/source/gdi/impgraph.cxx +++ b/vcl/source/gdi/impgraph.cxx @@ -101,6 +101,76 @@ Size GraphicReader::GetPreviewSize() const return aSize; } +GraphicID::GraphicID(ImpGraphic & rGraphic) +{ + mnID1 = static_cast<sal_uLong>(rGraphic.ImplGetType()) << 28; + mnID2 = mnID3 = mnID4 = 0; + + if (rGraphic.ImplGetType() == GraphicType::Bitmap) + { + if (rGraphic.getVectorGraphicData().get()) + { + const VectorGraphicDataPtr& rVectorGraphicDataPtr = rGraphic.getVectorGraphicData(); + const basegfx::B2DRange& rRange = rVectorGraphicDataPtr->getRange(); + + mnID1 |= rVectorGraphicDataPtr->getVectorGraphicDataArrayLength(); + mnID2 = basegfx::fround(rRange.getWidth()); + mnID3 = basegfx::fround(rRange.getHeight()); + mnID4 = vcl_get_checksum(0, rVectorGraphicDataPtr->getVectorGraphicDataArray().getConstArray(), rVectorGraphicDataPtr->getVectorGraphicDataArrayLength()); + } + else if (rGraphic.ImplIsAnimated()) + { + const Animation aAnimation(rGraphic.ImplGetAnimation()); + + mnID1 |= ( aAnimation.Count() & 0x0fffffff ); + mnID2 = aAnimation.GetDisplaySizePixel().Width(); + mnID3 = aAnimation.GetDisplaySizePixel().Height(); + mnID4 = rGraphic.ImplGetChecksum(); + } + else + { + const BitmapEx aBmpEx(rGraphic.ImplGetBitmapEx(GraphicConversionParameters())); + + mnID1 |= ( ( ( static_cast<sal_uLong>(aBmpEx.GetTransparentType()) << 8 ) | ( aBmpEx.IsAlpha() ? 1 : 0 ) ) & 0x0fffffff ); + mnID2 = aBmpEx.GetSizePixel().Width(); + mnID3 = aBmpEx.GetSizePixel().Height(); + mnID4 = rGraphic.ImplGetChecksum(); + } + } + else if (rGraphic.ImplGetType() == GraphicType::GdiMetafile) + { + const GDIMetaFile& rMtf = rGraphic.ImplGetGDIMetaFile(); + + mnID1 |= ( rMtf.GetActionSize() & 0x0fffffff ); + mnID2 = rMtf.GetPrefSize().Width(); + mnID3 = rMtf.GetPrefSize().Height(); + mnID4 = rGraphic.ImplGetChecksum(); + } +} + +OString GraphicID::getIDString() const +{ + static const char aHexData[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + OStringBuffer aHexStr; + sal_Int32 nShift, nIndex = 0; + aHexStr.setLength(24 + (2 * BITMAP_CHECKSUM_SIZE)); + + for( nShift = 28; nShift >= 0; nShift -= 4 ) + aHexStr[nIndex++] = aHexData[ ( mnID1 >> static_cast<sal_uInt32>(nShift) ) & 0xf ]; + + for( nShift = 28; nShift >= 0; nShift -= 4 ) + aHexStr[nIndex++] = aHexData[ ( mnID2 >> static_cast<sal_uInt32>(nShift) ) & 0xf ]; + + for( nShift = 28; nShift >= 0; nShift -= 4 ) + aHexStr[nIndex++] = aHexData[ ( mnID3 >> static_cast<sal_uInt32>(nShift) ) & 0xf ]; + + for( nShift = ( 8 * BITMAP_CHECKSUM_SIZE ) - 4; nShift >= 0; nShift -= 4 ) + aHexStr[nIndex++] = aHexData[ ( mnID4 >> static_cast<sal_uInt32>(nShift) ) & 0xf ]; + + return aHexStr.makeStringAndClear(); +} + ImpGraphic::ImpGraphic() : meType ( GraphicType::NONE ), mnSizeBytes ( 0 ), diff --git a/vcl/source/graphic/GraphicObject.cxx b/vcl/source/graphic/GraphicObject.cxx index d302d6952877..b609608d1f67 100644 --- a/vcl/source/graphic/GraphicObject.cxx +++ b/vcl/source/graphic/GraphicObject.cxx @@ -49,6 +49,9 @@ using com::sun::star::uno::Sequence; using com::sun::star::container::XNameContainer; using com::sun::star::beans::XPropertySet; +#define WATERMARK_LUM_OFFSET 50 +#define WATERMARK_CON_OFFSET -70 + namespace vcl { namespace graphic @@ -96,7 +99,198 @@ void SearchForGraphics(uno::Reference<uno::XInterface> const & xInterface, }} // end namespace vcl::graphic -GraphicManager* GraphicObject::mpGlobalMgr = nullptr; +namespace +{ + +bool lclDrawObj( OutputDevice* pOut, const Point& rPt, const Size& rSz, + GraphicObject const & rObj, const GraphicAttr& rAttr) +{ + Point aPt( rPt ); + Size aSz( rSz ); + bool bRet = false; + + if( ( rObj.GetType() == GraphicType::Bitmap ) || ( rObj.GetType() == GraphicType::GdiMetafile ) ) + { + // simple output of transformed graphic + const Graphic aGraphic( rObj.GetTransformedGraphic( &rAttr ) ); + + if( aGraphic.IsSupportedGraphic() ) + { + const sal_uInt16 nRot10 = rAttr.GetRotation() % 3600; + + if( nRot10 ) + { + tools::Polygon aPoly( tools::Rectangle( aPt, aSz ) ); + + aPoly.Rotate( aPt, nRot10 ); + const tools::Rectangle aRotBoundRect( aPoly.GetBoundRect() ); + aPt = aRotBoundRect.TopLeft(); + aSz = aRotBoundRect.GetSize(); + } + + aGraphic.Draw( pOut, aPt, aSz ); + } + + bRet = true; + } + + return bRet; +} + +void lclImplAdjust( BitmapEx& rBmpEx, const GraphicAttr& rAttr, GraphicAdjustmentFlags nAdjustmentFlags ) +{ + GraphicAttr aAttr( rAttr ); + + if( ( nAdjustmentFlags & GraphicAdjustmentFlags::DRAWMODE ) && aAttr.IsSpecialDrawMode() ) + { + switch( aAttr.GetDrawMode() ) + { + case GraphicDrawMode::Mono: + rBmpEx.Convert( BmpConversion::N1BitThreshold ); + break; + + case GraphicDrawMode::Greys: + rBmpEx.Convert( BmpConversion::N8BitGreys ); + break; + + case GraphicDrawMode::Watermark: + { + aAttr.SetLuminance( aAttr.GetLuminance() + WATERMARK_LUM_OFFSET ); + aAttr.SetContrast( aAttr.GetContrast() + WATERMARK_CON_OFFSET ); + } + break; + + default: + break; + } + } + + if( ( nAdjustmentFlags & GraphicAdjustmentFlags::COLORS ) && aAttr.IsAdjusted() ) + { + rBmpEx.Adjust( aAttr.GetLuminance(), aAttr.GetContrast(), + aAttr.GetChannelR(), aAttr.GetChannelG(), aAttr.GetChannelB(), + aAttr.GetGamma(), aAttr.IsInvert() ); + } + + if( ( nAdjustmentFlags & GraphicAdjustmentFlags::MIRROR ) && aAttr.IsMirrored() ) + { + rBmpEx.Mirror( aAttr.GetMirrorFlags() ); + } + + if( ( nAdjustmentFlags & GraphicAdjustmentFlags::ROTATE ) && aAttr.IsRotated() ) + { + rBmpEx.Rotate( aAttr.GetRotation(), COL_TRANSPARENT ); + } + + if( ( nAdjustmentFlags & GraphicAdjustmentFlags::TRANSPARENCY ) && aAttr.IsTransparent() ) + { + rBmpEx.AdjustTransparency(aAttr.GetTransparency()); + } +} + +void lclImplAdjust( GDIMetaFile& rMtf, const GraphicAttr& rAttr, GraphicAdjustmentFlags nAdjustmentFlags ) +{ + GraphicAttr aAttr( rAttr ); + + if( ( nAdjustmentFlags & GraphicAdjustmentFlags::DRAWMODE ) && aAttr.IsSpecialDrawMode() ) + { + switch( aAttr.GetDrawMode() ) + { + case GraphicDrawMode::Mono: + rMtf.Convert( MtfConversion::N1BitThreshold ); + break; + + case GraphicDrawMode::Greys: + rMtf.Convert( MtfConversion::N8BitGreys ); + break; + + case GraphicDrawMode::Watermark: + { + aAttr.SetLuminance( aAttr.GetLuminance() + WATERMARK_LUM_OFFSET ); + aAttr.SetContrast( aAttr.GetContrast() + WATERMARK_CON_OFFSET ); + } + break; + + default: + break; + } + } + + if( ( nAdjustmentFlags & GraphicAdjustmentFlags::COLORS ) && aAttr.IsAdjusted() ) + { + rMtf.Adjust( aAttr.GetLuminance(), aAttr.GetContrast(), + aAttr.GetChannelR(), aAttr.GetChannelG(), aAttr.GetChannelB(), + aAttr.GetGamma(), aAttr.IsInvert() ); + } + + if( ( nAdjustmentFlags & GraphicAdjustmentFlags::MIRROR ) && aAttr.IsMirrored() ) + { + rMtf.Mirror( aAttr.GetMirrorFlags() ); + } + + if( ( nAdjustmentFlags & GraphicAdjustmentFlags::ROTATE ) && aAttr.IsRotated() ) + { + rMtf.Rotate( aAttr.GetRotation() ); + } + + if( ( nAdjustmentFlags & GraphicAdjustmentFlags::TRANSPARENCY ) && aAttr.IsTransparent() ) + { + OSL_FAIL( "Missing implementation: Mtf-Transparency" ); + } +} + +void lclImplAdjust( Animation& rAnimation, const GraphicAttr& rAttr, GraphicAdjustmentFlags nAdjustmentFlags ) +{ + GraphicAttr aAttr( rAttr ); + + if( ( nAdjustmentFlags & GraphicAdjustmentFlags::DRAWMODE ) && aAttr.IsSpecialDrawMode() ) + { + switch( aAttr.GetDrawMode() ) + { + case GraphicDrawMode::Mono: + rAnimation.Convert( BmpConversion::N1BitThreshold ); + break; + + case GraphicDrawMode::Greys: + rAnimation.Convert( BmpConversion::N8BitGreys ); + break; + + case GraphicDrawMode::Watermark: + { + aAttr.SetLuminance( aAttr.GetLuminance() + WATERMARK_LUM_OFFSET ); + aAttr.SetContrast( aAttr.GetContrast() + WATERMARK_CON_OFFSET ); + } + break; + + default: + break; + } + } + + if( ( nAdjustmentFlags & GraphicAdjustmentFlags::COLORS ) && aAttr.IsAdjusted() ) + { + rAnimation.Adjust( aAttr.GetLuminance(), aAttr.GetContrast(), + aAttr.GetChannelR(), aAttr.GetChannelG(), aAttr.GetChannelB(), + aAttr.GetGamma(), aAttr.IsInvert() ); + } + + if( ( nAdjustmentFlags & GraphicAdjustmentFlags::MIRROR ) && aAttr.IsMirrored() ) + { + rAnimation.Mirror( aAttr.GetMirrorFlags() ); + } + + if( ( nAdjustmentFlags & GraphicAdjustmentFlags::ROTATE ) && aAttr.IsRotated() ) + { + OSL_FAIL( "Missing implementation: Animation-Rotation" ); + } + + if( ( nAdjustmentFlags & GraphicAdjustmentFlags::TRANSPARENCY ) && aAttr.IsTransparent() ) + { + OSL_FAIL( "Missing implementation: Animation-Transparency" ); + } +} + +} // end anonymous namespace struct GrfSimpleCacheObj { @@ -107,19 +301,6 @@ struct GrfSimpleCacheObj maGraphic( rGraphic ), maAttr( rAttr ) {} }; -// unique increasing ID for being able to detect the GraphicObject with the -// oldest last data changes -static sal_uLong aIncrementingTimeOfLastDataChange = 1; - -void GraphicObject::ImplAfterDataChange() -{ - // set unique timestamp ID of last data change - mnDataChangeTimeStamp = aIncrementingTimeOfLastDataChange++; - - // check memory footprint of all GraphicObjects managed and evtl. take action - mpGlobalMgr->ImplCheckSizeOfSwappedInGraphics(this); -} - GraphicObject::GraphicObject() : mbAutoSwapped(false) , mbIsInSwapIn(false) @@ -127,7 +308,6 @@ GraphicObject::GraphicObject() { ImplEnsureGraphicManager(); ImplAssignGraphicData(); - mpGlobalMgr->ImplRegisterObj(*this, maGraphic, nullptr, nullptr); } GraphicObject::GraphicObject(const Graphic& rGraphic) @@ -138,7 +318,6 @@ GraphicObject::GraphicObject(const Graphic& rGraphic) { ImplEnsureGraphicManager(); ImplAssignGraphicData(); - mpGlobalMgr->ImplRegisterObj(*this, maGraphic, nullptr, nullptr); } GraphicObject::GraphicObject(const GraphicObject& rGraphicObj) @@ -152,20 +331,12 @@ GraphicObject::GraphicObject(const GraphicObject& rGraphicObj) , mbIsInSwapOut(false) { ImplAssignGraphicData(); - mpGlobalMgr->ImplRegisterObj(*this, maGraphic, nullptr, &rGraphicObj); if( rGraphicObj.HasUserData() && rGraphicObj.IsSwappedOut() ) SetSwapState(); } GraphicObject::~GraphicObject() { - mpGlobalMgr->ImplUnregisterObj( *this ); - - if (!mpGlobalMgr->ImplHasObjects()) - { - delete mpGlobalMgr; - mpGlobalMgr = nullptr; - } } void GraphicObject::ImplAssignGraphicData() @@ -178,33 +349,10 @@ void GraphicObject::ImplAssignGraphicData() mbAnimated = maGraphic.IsAnimated(); mbEPS = maGraphic.IsEPS(); mnAnimationLoopCount = ( mbAnimated ? maGraphic.GetAnimationLoopCount() : 0 ); - - // Handle evtl. needed AfterDataChanges - ImplAfterDataChange(); } void GraphicObject::ImplEnsureGraphicManager() { - if (mpGlobalMgr) - return; - - sal_uLong nCacheSize = 20000; - sal_uLong nMaxObjCacheSize = 20000; - sal_uLong nTimeoutSeconds = 20000; - if (!utl::ConfigManager::IsFuzzing()) - { - try - { - nCacheSize = officecfg::Office::Common::Cache::GraphicManager::TotalCacheSize::get(); - nMaxObjCacheSize = officecfg::Office::Common::Cache::GraphicManager::ObjectCacheSize::get(); - nTimeoutSeconds = officecfg::Office::Common::Cache::GraphicManager::ObjectReleaseTime::get(); - } - catch (...) - { - } - } - mpGlobalMgr = new GraphicManager(nCacheSize, nMaxObjCacheSize); - mpGlobalMgr->SetCacheTimeout(nTimeoutSeconds); } void GraphicObject::ImplAutoSwapIn() @@ -259,9 +407,6 @@ void GraphicObject::ImplAutoSwapIn() } mbIsInSwapIn = false; - - if (!mbAutoSwapped) - mpGlobalMgr->ImplGraphicObjectWasSwappedIn( *this ); } ImplAssignGraphicData(); } @@ -339,8 +484,6 @@ GraphicObject& GraphicObject::operator=( const GraphicObject& rGraphicObj ) { if( &rGraphicObj != this ) { - mpGlobalMgr->ImplUnregisterObj( *this ); - maSwapStreamHdl = Link<const GraphicObject*, SvStream*>(); mxSimpleCache.reset(); @@ -350,7 +493,6 @@ GraphicObject& GraphicObject::operator=( const GraphicObject& rGraphicObj ) maUserData = rGraphicObj.maUserData; ImplAssignGraphicData(); mbAutoSwapped = false; - mpGlobalMgr->ImplRegisterObj( *this, maGraphic, nullptr, &rGraphicObj ); if( rGraphicObj.HasUserData() && rGraphicObj.IsSwappedOut() ) SetSwapState(); } @@ -370,7 +512,7 @@ OString GraphicObject::GetUniqueID() const if ( !IsInSwapIn() && IsEPS() ) const_cast<GraphicObject*>(this)->FireSwapInRequest(); - return mpGlobalMgr->ImplGetUniqueID(*this); + return GetGraphic().getUniqueID(); } SvStream* GraphicObject::GetSwapStream() const @@ -455,29 +597,6 @@ void GraphicObject::FireSwapOutRequest() ImplAutoSwapOutHdl( nullptr ); } -bool GraphicObject::IsCached( OutputDevice const * pOut, const Size& rSz, - const GraphicAttr* pAttr, GraphicManagerDrawFlags nFlags ) const -{ - bool bRet; - - if( nFlags & GraphicManagerDrawFlags::CACHED ) - { - Point aPt; - Size aSz( rSz ); - if ( pAttr && pAttr->IsCropped() ) - { - tools::PolyPolygon aClipPolyPoly; - bool bRectClip; - ImplGetCropParams( pOut, aPt, aSz, pAttr, aClipPolyPoly, bRectClip ); - } - bRet = mpGlobalMgr->IsInCache( pOut, aPt, aSz, *this, ( pAttr ? *pAttr : GetAttr() ) ); - } - else - bRet = false; - - return bRet; -} - bool GraphicObject::Draw( OutputDevice* pOut, const Point& rPt, const Size& rSz, const GraphicAttr* pAttr, GraphicManagerDrawFlags nFlags ) { @@ -486,7 +605,6 @@ bool GraphicObject::Draw( OutputDevice* pOut, const Point& rPt, const Size& rSz, Size aSz( rSz ); const DrawModeFlags nOldDrawMode = pOut->GetDrawMode(); bool bCropped = aAttr.IsCropped(); - bool bCached = false; bool bRet; // #i29534# Provide output rects for PDF writer @@ -535,23 +653,13 @@ bool GraphicObject::Draw( OutputDevice* pOut, const Point& rPt, const Size& rSz, } } - bRet = mpGlobalMgr->DrawObj( pOut, aPt, aSz, *this, aAttr, nFlags, bCached ); + bRet = lclDrawObj(pOut, aPt, aSz, *this, aAttr); if( bCropped ) pOut->Pop(); pOut->SetDrawMode( nOldDrawMode ); - // #i29534# Moved below OutDev restoration, to avoid multiple swap-ins - // (code above needs to call GetGraphic twice) - if( bCached ) - { - if (mxSwapOutTimer) - mxSwapOutTimer->Start(); - else - FireSwapOutRequest(); - } - return bRet; } @@ -656,10 +764,8 @@ const Graphic& GraphicObject::GetGraphic() const return maGraphic; } -void GraphicObject::SetGraphic( const Graphic& rGraphic, const GraphicObject* pCopyObj ) +void GraphicObject::SetGraphic( const Graphic& rGraphic, const GraphicObject* /*pCopyObj*/ ) { - mpGlobalMgr->ImplUnregisterObj( *this ); - if (mxSwapOutTimer) mxSwapOutTimer->Stop(); @@ -669,12 +775,8 @@ void GraphicObject::SetGraphic( const Graphic& rGraphic, const GraphicObject* pC maLink.clear(); mxSimpleCache.reset(); - mpGlobalMgr->ImplRegisterObj( *this, maGraphic, nullptr, pCopyObj); - if (mxSwapOutTimer) mxSwapOutTimer->Start(); - - } void GraphicObject::SetGraphic( const Graphic& rGraphic, const OUString& rLink ) @@ -913,7 +1015,7 @@ Graphic GraphicObject::GetTransformedGraphic( const Size& rDestSize, const MapMo return aTransGraphic; } -Graphic GraphicObject::GetTransformedGraphic( const GraphicAttr* pAttr ) const // TODO: Change to Impl +Graphic GraphicObject::GetTransformedGraphic( const GraphicAttr* pAttr ) const { GetGraphic(); @@ -929,21 +1031,21 @@ Graphic GraphicObject::GetTransformedGraphic( const GraphicAttr* pAttr ) const / if( IsAnimated() ) { Animation aAnimation( maGraphic.GetAnimation() ); - GraphicManager::ImplAdjust( aAnimation, aAttr, GraphicAdjustmentFlags::ALL ); + lclImplAdjust( aAnimation, aAttr, GraphicAdjustmentFlags::ALL ); aAnimation.SetLoopCount( mnAnimationLoopCount ); aGraphic = aAnimation; } else { BitmapEx aBmpEx( maGraphic.GetBitmapEx() ); - GraphicManager::ImplAdjust( aBmpEx, aAttr, GraphicAdjustmentFlags::ALL ); + lclImplAdjust( aBmpEx, aAttr, GraphicAdjustmentFlags::ALL ); aGraphic = aBmpEx; } } else { GDIMetaFile aMtf( maGraphic.GetGDIMetaFile() ); - GraphicManager::ImplAdjust( aMtf, aAttr, GraphicAdjustmentFlags::ALL ); + lclImplAdjust( aMtf, aAttr, GraphicAdjustmentFlags::ALL ); aGraphic = aMtf; } } @@ -967,9 +1069,6 @@ bool GraphicObject::SwapOut() { const bool bRet = !mbAutoSwapped && maGraphic.SwapOut(); - if (bRet) - mpGlobalMgr->ImplGraphicObjectWasSwappedOut( *this ); - return bRet; } @@ -988,9 +1087,6 @@ bool GraphicObject::SwapOut( SvStream* pOStm ) { bRet = bRet && maGraphic.SwapOut( pOStm ); } - - if (bRet) - mpGlobalMgr->ImplGraphicObjectWasSwappedOut(*this); } catch(...) { @@ -1012,9 +1108,6 @@ bool GraphicObject::SwapIn() else { bRet = maGraphic.SwapIn(); - - if (bRet) - mpGlobalMgr->ImplGraphicObjectWasSwappedIn(*this); } if( bRet ) @@ -1035,8 +1128,6 @@ void GraphicObject::SetSwapState() if( !IsSwappedOut() ) { mbAutoSwapped = true; - - mpGlobalMgr->ImplGraphicObjectWasSwappedOut(*this); } } diff --git a/vcl/source/graphic/GraphicObject2.cxx b/vcl/source/graphic/GraphicObject2.cxx index e46b035f60b7..da5f61f588a1 100644 --- a/vcl/source/graphic/GraphicObject2.cxx +++ b/vcl/source/graphic/GraphicObject2.cxx @@ -31,1562 +31,10 @@ #include <vcl/animate.hxx> #include <vcl/alpha.hxx> #include <vcl/virdev.hxx> -#include "grfcache.hxx" #include <vcl/GraphicObject.hxx> #include <bitmapwriteaccess.hxx> #include <memory> - -#define WATERMARK_LUM_OFFSET 50 -#define WATERMARK_CON_OFFSET -70 - -namespace { - -constexpr sal_uInt8 MAP(long cVal0, long cVal1, long nFrac) { - return static_cast<sal_uInt8>(((cVal0<<20)+nFrac*(cVal1-cVal0))>>20); -} - -} - -GraphicManager::GraphicManager( sal_uLong nCacheSize, sal_uLong nMaxObjCacheSize ) : - mnUsedSize(0), - mpCache( new GraphicCache( nCacheSize, nMaxObjCacheSize ) ) -{ -} - -GraphicManager::~GraphicManager() -{ - assert(maObjList.empty()); - mpCache.reset(); -} - -void GraphicManager::SetMaxCacheSize( sal_uLong nNewCacheSize ) -{ - mpCache->SetMaxDisplayCacheSize( nNewCacheSize ); -} - -sal_uLong GraphicManager::GetMaxCacheSize() const -{ - return mpCache->GetMaxDisplayCacheSize(); -} - -void GraphicManager::SetCacheTimeout( sal_uLong nTimeoutSeconds ) -{ - mpCache->SetCacheTimeout( nTimeoutSeconds ); -} - -bool GraphicManager::IsInCache( OutputDevice const * pOut, const Point& rPt, - const Size& rSz, const GraphicObject& rObj, - const GraphicAttr& rAttr ) const -{ - return mpCache->IsInDisplayCache( pOut, rPt, rSz, rObj, rAttr ); -} - -bool GraphicManager::DrawObj( OutputDevice* pOut, const Point& rPt, const Size& rSz, - GraphicObject const & rObj, const GraphicAttr& rAttr, - const GraphicManagerDrawFlags nFlags, bool& rCached ) -{ - Point aPt( rPt ); - Size aSz( rSz ); - bool bRet = false; - - rCached = false; - - if( ( rObj.GetType() == GraphicType::Bitmap ) || ( rObj.GetType() == GraphicType::GdiMetafile ) ) - { - // create output and fill cache - - if( rObj.IsAnimated() || ( pOut->GetOutDevType() == OUTDEV_PRINTER ) || - ( !( nFlags & GraphicManagerDrawFlags::NO_SUBSTITUTE ) && - ( ( nFlags & GraphicManagerDrawFlags::SUBSTITUTE ) || - !( nFlags & GraphicManagerDrawFlags::CACHED ) || - ( pOut->GetConnectMetaFile() && !pOut->IsOutputEnabled() ) ) ) ) - { - // simple output of transformed graphic - const Graphic aGraphic( rObj.GetTransformedGraphic( &rAttr ) ); - - if( aGraphic.IsSupportedGraphic() ) - { - const sal_uInt16 nRot10 = rAttr.GetRotation() % 3600; - - if( nRot10 ) - { - tools::Polygon aPoly( tools::Rectangle( aPt, aSz ) ); - - aPoly.Rotate( aPt, nRot10 ); - const tools::Rectangle aRotBoundRect( aPoly.GetBoundRect() ); - aPt = aRotBoundRect.TopLeft(); - aSz = aRotBoundRect.GetSize(); - } - - aGraphic.Draw( pOut, aPt, aSz ); - } - - bRet = true; - } - - if( !bRet ) - { - // cached/direct drawing - if( !mpCache->DrawDisplayCacheObj( pOut, aPt, aSz, rObj, rAttr ) ) - bRet = ImplDraw( pOut, aPt, aSz, rObj, rAttr, rCached ); - else - bRet = rCached = true; - } - } - - return bRet; -} - -void GraphicManager::ImplRegisterObj( const GraphicObject& rObj, Graphic& rSubstitute, - const OString* pID, const GraphicObject* pCopyObj ) -{ - assert(maObjList.find(const_cast<GraphicObject*>(&rObj)) == maObjList.end()); - - maObjList.emplace( const_cast<GraphicObject*>(&rObj) ); - - mpCache->AddGraphicObject( rObj, rSubstitute, pID, pCopyObj ); - if( !rObj.IsSwappedOut() ) - mnUsedSize += rObj.maGraphic.GetSizeBytes(); -} - -void GraphicManager::ImplUnregisterObj( const GraphicObject& rObj ) -{ - mpCache->ReleaseGraphicObject( rObj ); - if( !rObj.IsSwappedOut() ) - { - assert(mnUsedSize >= rObj.maGraphic.GetSizeBytes()); - mnUsedSize -= rObj.maGraphic.GetSizeBytes(); - } - if ( 0 < maObjList.erase( const_cast<GraphicObject*>(&rObj) ) ) - return; - - assert(false); // surely it should have been registered? -} - -void GraphicManager::ImplGraphicObjectWasSwappedOut( const GraphicObject& rObj ) -{ - mpCache->GraphicObjectWasSwappedOut( rObj ); - assert(mnUsedSize >= rObj.GetSizeBytes()); - mnUsedSize -= rObj.GetSizeBytes(); -} - -OString GraphicManager::ImplGetUniqueID( const GraphicObject& rObj ) const -{ - return mpCache->GetUniqueID( rObj ); -} - -namespace -{ - struct simpleSortByDataChangeTimeStamp - { - bool operator() (GraphicObject const * p1, GraphicObject const * p2) const - { - return p1->GetDataChangeTimeStamp() < p2->GetDataChangeTimeStamp(); - } - }; -} // end of anonymous namespace - -void GraphicManager::ImplCheckSizeOfSwappedInGraphics(const GraphicObject* pGraphicToIgnore) -{ - // detect maximum allowed memory footprint. Use the user-settings of MaxCacheSize (defaulted - // to 200MB). - const sal_uLong nMaxCacheSize(GetMaxCacheSize()); - - if(mnUsedSize <= nMaxCacheSize) - return; - - // Copy the object list for now, because maObjList can change in the meantime unexpectedly. - std::vector< GraphicObject* > aCandidates(maObjList.begin(), maObjList.end()); - // if we use more currently, sort by last DataChangeTimeStamp - // sort by DataChangeTimeStamp so that the oldest get removed first - std::sort(aCandidates.begin(), aCandidates.end(), simpleSortByDataChangeTimeStamp()); - - for(decltype(aCandidates)::size_type a(0); mnUsedSize >= nMaxCacheSize && a < aCandidates.size(); a++) - { - // swap out until we have no more or the goal to use less than nMaxCacheSize - // is reached - GraphicObject* pObj = aCandidates[a]; - if( pObj == pGraphicToIgnore ) - { - continue; - } - if (maObjList.find(pObj) == maObjList.end()) - { - // object has been deleted when swapping out another one - continue; - } - - // do not swap out when we have less than 16KB data objects - if(pObj->GetSizeBytes() >= (16 * 1024)) - { - pObj->FireSwapOutRequest(); - } - } -} - -void GraphicManager::ImplGraphicObjectWasSwappedIn( const GraphicObject& rObj ) -{ - mpCache->GraphicObjectWasSwappedIn( rObj ); - mnUsedSize += rObj.maGraphic.GetSizeBytes(); -} - -bool GraphicManager::ImplDraw( OutputDevice* pOut, const Point& rPt, - const Size& rSz, GraphicObject const & rObj, - const GraphicAttr& rAttr, - bool& rCached ) -{ - const Graphic& rGraphic = rObj.GetGraphic(); - bool bRet = false; - - if( rGraphic.IsSupportedGraphic() && !rObj.IsSwappedOut() ) - { - if( GraphicType::Bitmap == rGraphic.GetType() ) - { - const BitmapEx aSrcBmpEx( rGraphic.GetBitmapEx() ); - - // #i46805# No point in caching a bitmap that is rendered - // via RectFill on the OutDev - if( !(pOut->GetDrawMode() & ( DrawModeFlags::BlackBitmap | DrawModeFlags::WhiteBitmap )) && - mpCache->IsDisplayCacheable( pOut, rPt, rSz, rObj, rAttr ) ) - { - BitmapEx aDstBmpEx; - - if( ImplCreateOutput( pOut, rPt, rSz, aSrcBmpEx, rAttr, &aDstBmpEx ) ) - { - rCached = mpCache->CreateDisplayCacheObj( pOut, rPt, rSz, rObj, rAttr, aDstBmpEx ); - bRet = true; - } - } - - if( !bRet ) - bRet = ImplCreateOutput( pOut, rPt, rSz, aSrcBmpEx, rAttr ); - } - else - { - const GDIMetaFile& rSrcMtf = rGraphic.GetGDIMetaFile(); - - if( mpCache->IsDisplayCacheable( pOut, rPt, rSz, rObj, rAttr ) ) - { - GDIMetaFile aDstMtf; - BitmapEx aContainedBmpEx; - - if( ImplCreateOutput( pOut, rPt, rSz, rSrcMtf, rAttr, aDstMtf, aContainedBmpEx ) ) - { - if( !!aContainedBmpEx ) - { - // Use bitmap output method, if metafile basically contains only a single - // bitmap (allows caching the resulting pixmap). - BitmapEx aDstBmpEx; - - if( ImplCreateOutput( pOut, rPt, rSz, aContainedBmpEx, rAttr, &aDstBmpEx ) ) - { - rCached = mpCache->CreateDisplayCacheObj( pOut, rPt, rSz, rObj, rAttr, aDstBmpEx ); - bRet = true; - } - } - else - { - rCached = mpCache->CreateDisplayCacheObj( pOut, rPt, rSz, rObj, rAttr, aDstMtf ); - bRet = true; - } - } - } - - if( !bRet ) - { - const Graphic aGraphic( rObj.GetTransformedGraphic( &rAttr ) ); - - if( aGraphic.IsSupportedGraphic() ) - { - aGraphic.Draw( pOut, rPt, rSz ); - bRet = true; - } - } - } - } - - return bRet; -} - -bool ImplCreateRotatedScaled( const BitmapEx& rBmpEx, const GraphicAttr& rAttributes, - sal_uInt16 nRot10, const Size& rUnrotatedSzPix, - long nStartX, long nEndX, long nStartY, long nEndY, - BitmapEx& rOutBmpEx ) -{ - const long aUnrotatedWidth = rUnrotatedSzPix.Width(); - const long aUnrotatedHeight = rUnrotatedSzPix.Height(); - const long aBitmapWidth = rBmpEx.GetSizePixel().Width(); - const long aBitmapHeight = rBmpEx.GetSizePixel().Height(); - - long nTmpX, nTmpY, nTmpFX, nTmpFY, nTmp; - double fTmp; - - bool bHMirr( rAttributes.GetMirrorFlags() & BmpMirrorFlags::Horizontal ); - bool bVMirr( rAttributes.GetMirrorFlags() & BmpMirrorFlags::Vertical ); - - std::unique_ptr<long[]> pMapIX(new long[ aUnrotatedWidth ]); - std::unique_ptr<long[]> pMapFX(new long[ aUnrotatedWidth ]); - std::unique_ptr<long[]> pMapIY(new long[ aUnrotatedHeight ]); - std::unique_ptr<long[]> pMapFY(new long[ aUnrotatedHeight ]); - - double fRevScaleX; - double fRevScaleY; - - bool scaleByAveraging = false; - - if(aBitmapWidth > 1 && aUnrotatedWidth > 1) - { - fRevScaleX = static_cast<double>( aBitmapWidth - 1 ) / static_cast<double>( aUnrotatedWidth - 1 ); - // create horizontal mapping table - long x; - for( x = 0, nTmpX = aBitmapWidth - 1, nTmp = aBitmapWidth - 2 >= 0 ? aBitmapWidth -2 : 0L; x < aUnrotatedWidth; x++ ) - { - fTmp = x * fRevScaleX; - - if( bHMirr ) - fTmp = nTmpX - fTmp; - - pMapIX[ x ] = MinMax( fTmp, 0, nTmp ); - pMapFX[ x ] = static_cast<long>( ( fTmp - pMapIX[ x ] ) * 1048576.0 ); - } - scaleByAveraging |= fRevScaleX > 5.0/3.0; - } - else - { - if(aBitmapWidth == 1) - { - fRevScaleX = 1.0 / static_cast<double>(aUnrotatedWidth); - for ( long x = 0; x < aUnrotatedWidth ; x++) - { - pMapIX[x] = 0; - pMapFX[x] = 0; - } - scaleByAveraging = true; - } - else - { - fRevScaleX = static_cast<double>(aBitmapWidth) / static_cast<double>(aUnrotatedWidth); - fTmp = static_cast<double>(aBitmapWidth) / 2.0; - - pMapIX[ 0 ] = static_cast<long>(fTmp); - pMapFX[ 0 ] = static_cast<long>( ( fTmp - pMapIX[ 0 ] ) * 1048576.0 ); - scaleByAveraging = true; - } - } - if(aBitmapHeight > 1 && aUnrotatedHeight > 1) - { - fRevScaleY = static_cast<double>( aBitmapHeight - 1 ) / static_cast<double>( aUnrotatedHeight - 1 ); - // create vertical mapping table - long y; - for( y = 0, nTmpY = aBitmapHeight - 1, nTmp = aBitmapHeight - 2 >= 0 ? aBitmapHeight - 2 : 0L; y < aUnrotatedHeight; y++ ) - { - fTmp = y * fRevScaleY; - - if( bVMirr ) - fTmp = nTmpY - fTmp; - - pMapIY[ y ] = MinMax( fTmp, 0, nTmp ); - pMapFY[ y ] = static_cast<long>( ( fTmp - pMapIY[ y ] ) * 1048576.0 ); - } - scaleByAveraging |= fRevScaleY > 5.0/3.0; - } - else - { - if(aBitmapHeight == 1) - { - fRevScaleY = 1.0 / static_cast<double>(aUnrotatedHeight); - for (long y = 0; y < aUnrotatedHeight; ++y) - { - pMapIY[y] = 0; - pMapFY[y] = 0; - } - scaleByAveraging = true; - } - else - { - fRevScaleY = static_cast<double>(aBitmapHeight) / static_cast<double>(aUnrotatedHeight); - fTmp = static_cast<double>(aBitmapHeight) / 2.0; - - pMapIY[ 0 ] = static_cast<long>(fTmp); - pMapFY[ 0 ] = static_cast<long>( ( fTmp - pMapIY[ 0 ] ) * 1048576.0 ); - scaleByAveraging = true; - } - } - - Bitmap aBmp( rBmpEx.GetBitmap() ); - Bitmap aOutBmp; - BitmapReadAccess* pReadAccess = aBmp.AcquireReadAccess(); - BitmapWriteAccess* pWriteAccess; - - const double fCosAngle = cos( nRot10 * F_PI1800 ); - const double fSinAngle = sin( nRot10 * F_PI1800 ); - const long aTargetWidth = nEndX - nStartX + 1; - const long aTargetHeight = nEndY - nStartY + 1; - std::unique_ptr<long[]> pCosX(new long[ aTargetWidth ]); - std::unique_ptr<long[]> pSinX(new long[ aTargetWidth ]); - std::unique_ptr<long[]> pCosY(new long[ aTargetHeight ]); - std::unique_ptr<long[]> pSinY(new long[ aTargetHeight ]); - long nUnRotX, nUnRotY, nSinY, nCosY; - sal_uInt8 cR0, cG0, cB0, cR1, cG1, cB1; - bool bRet = false; - - tools::Polygon aPoly( tools::Rectangle( Point(), rUnrotatedSzPix ) ); - aPoly.Rotate( Point(), nRot10 ); - tools::Rectangle aNewBound( aPoly.GetBoundRect() ); - - // create horizontal mapping table - long x; - for( x = 0, nTmpX = aNewBound.Left() + nStartX; x < aTargetWidth; x++ ) - { - pCosX[ x ] = FRound( fCosAngle * ( fTmp = nTmpX++ << 8 ) ); - pSinX[ x ] = FRound( fSinAngle * fTmp ); - } - - // create vertical mapping table - long y; - for( y = 0, nTmpY = aNewBound.Top() + nStartY; y < aTargetHeight; y++ ) - { - pCosY[ y ] = FRound( fCosAngle * ( fTmp = nTmpY++ << 8 ) ); - pSinY[ y ] = FRound( fSinAngle * fTmp ); - } - - if( pReadAccess ) - { - aOutBmp = Bitmap( Size( aTargetWidth, aTargetHeight ), 24 ); - pWriteAccess = aOutBmp.AcquireWriteAccess(); - - if( pWriteAccess ) - { - BitmapColor aColRes; - - if ( !scaleByAveraging ) - { - if( pReadAccess->HasPalette() ) - { - for( y = 0; y < aTargetHeight; y++ ) - { - nSinY = pSinY[ y ]; - nCosY = pCosY[ y ]; - - Scanline pScanline = pWriteAccess->GetScanline( y ); - for( x = 0; x < aTargetWidth; x++ ) - { - nUnRotX = ( pCosX[ x ] - nSinY ) >> 8; - nUnRotY = ( pSinX[ x ] + nCosY ) >> 8; - - if( ( nUnRotX >= 0 ) && ( nUnRotX < aUnrotatedWidth ) && - ( nUnRotY >= 0 ) && ( nUnRotY < aUnrotatedHeight ) ) - { - nTmpX = pMapIX[ nUnRotX ]; - nTmpFX = pMapFX[ nUnRotX ]; - nTmpY = pMapIY[ nUnRotY ]; - nTmpFY = pMapFY[ nUnRotY ]; - - const BitmapColor& rCol0 = pReadAccess->GetPaletteColor( pReadAccess->GetPixelIndex( nTmpY, nTmpX ) ); - const BitmapColor& rCol1 = pReadAccess->GetPaletteColor( pReadAccess->GetPixelIndex( nTmpY, ++nTmpX ) ); - cR0 = MAP( rCol0.GetRed(), rCol1.GetRed(), nTmpFX ); - cG0 = MAP( rCol0.GetGreen(), rCol1.GetGreen(), nTmpFX ); - cB0 = MAP( rCol0.GetBlue(), rCol1.GetBlue(), nTmpFX ); - - const BitmapColor& rCol3 = pReadAccess->GetPaletteColor( pReadAccess->GetPixelIndex( ++nTmpY, nTmpX ) ); - const BitmapColor& rCol2 = pReadAccess->GetPaletteColor( pReadAccess->GetPixelIndex( nTmpY, --nTmpX ) ); - cR1 = MAP( rCol2.GetRed(), rCol3.GetRed(), nTmpFX ); - cG1 = MAP( rCol2.GetGreen(), rCol3.GetGreen(), nTmpFX ); - cB1 = MAP( rCol2.GetBlue(), rCol3.GetBlue(), nTmpFX ); - - aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) ); - aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) ); - aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) ); - pWriteAccess->SetPixelOnData( pScanline, x, aColRes ); - } - } - } - } - else - { - BitmapColor aCol0, aCol1; - - for( y = 0; y < aTargetHeight; y++ ) - { - nSinY = pSinY[ y ]; - nCosY = pCosY[ y ]; - - Scanline pScanline = pWriteAccess->GetScanline( y ); - for( x = 0; x < aTargetWidth; x++ ) - { - nUnRotX = ( pCosX[ x ] - nSinY ) >> 8; - nUnRotY = ( pSinX[ x ] + nCosY ) >> 8; - - if( ( nUnRotX >= 0 ) && ( nUnRotX < aUnrotatedWidth ) && - ( nUnRotY >= 0 ) && ( nUnRotY < aUnrotatedHeight ) ) - { - nTmpX = pMapIX[ nUnRotX ]; - nTmpFX = pMapFX[ nUnRotX ]; - nTmpY = pMapIY[ nUnRotY ]; - nTmpFY = pMapFY[ nUnRotY ]; - - aCol0 = pReadAccess->GetPixel( nTmpY, nTmpX ); - aCol1 = pReadAccess->GetPixel( nTmpY, ++nTmpX ); - cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX ); - cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX ); - cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX ); - - aCol1 = pReadAccess->GetPixel( ++nTmpY, nTmpX ); - aCol0 = pReadAccess->GetPixel( nTmpY, --nTmpX ); - cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX ); - cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX ); - cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX ); - - aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) ); - aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) ); - aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) ); - pWriteAccess->SetPixelOnData( pScanline, x, aColRes ); - } - } - } - } - } - else // scaleByAveraging - { - double aSumRed, aSumGreen, aSumBlue, aCount; - BitmapColor aColor; - BitmapColor aResultColor; - - for( y = 0; y < aTargetHeight; y++ ) - { - nSinY = pSinY[ y ]; - nCosY = pCosY[ y ]; - - Scanline pScanline = pWriteAccess->GetScanline( y ); - for( x = 0; x < aTargetWidth; x++ ) - { - double aUnrotatedX = ( pCosX[ x ] - nSinY ) / 256.0; - double aUnrotatedY = ( pSinX[ x ] + nCosY ) / 256.0; - - if ( bHMirr ) - aUnrotatedX = aUnrotatedWidth - aUnrotatedX - 1; - if ( bVMirr ) - aUnrotatedY = aUnrotatedHeight - aUnrotatedY - 1; - - if( ( aUnrotatedX >= 0 ) && ( aUnrotatedX < aUnrotatedWidth ) && - ( aUnrotatedY >= 0 ) && ( aUnrotatedY < aUnrotatedHeight ) ) - { - double dYStart = ((aUnrotatedY + 0.5) * fRevScaleY) - 0.5; - double dYEnd = ((aUnrotatedY + 1.5) * fRevScaleY) - 0.5; - - int yStart = MinMax( dYStart, 0, aBitmapHeight - 1); - int yEnd = MinMax( dYEnd, 0, aBitmapHeight - 1); - - double dXStart = ((aUnrotatedX + 0.5) * fRevScaleX) - 0.5; - double dXEnd = ((aUnrotatedX + 1.5) * fRevScaleX) - 0.5; - - int xStart = MinMax( dXStart, 0, aBitmapWidth - 1); - int xEnd = MinMax( dXEnd, 0, aBitmapWidth - 1); - - aSumRed = aSumGreen = aSumBlue = 0.0; - aCount = 0; - - for (int yIn = yStart; yIn <= yEnd; yIn++) - { - Scanline pScanlineRead = pReadAccess->GetScanline( yIn ); - for (int xIn = xStart; xIn <= xEnd; xIn++) - { - if( pReadAccess->HasPalette() ) - aColor = pReadAccess->GetPaletteColor( pReadAccess->GetIndexFromData( pScanlineRead, xIn ) ); - else - aColor = pReadAccess->GetPixelFromData( pScanlineRead, xIn ); - - aSumRed += aColor.GetRed(); - aSumGreen += aColor.GetGreen(); - aSumBlue += aColor.GetBlue(); - - aCount++; - } - } - - aResultColor.SetRed( MinMax( aSumRed / aCount, 0, 255) ); - aResultColor.SetGreen( MinMax( aSumGreen / aCount, 0, 255) ); - aResultColor.SetBlue( MinMax( aSumBlue / aCount, 0, 255) ); - - pWriteAccess->SetPixelOnData( pScanline, x, aResultColor ); - } - } - } - } - - Bitmap::ReleaseAccess( pWriteAccess ); - bRet = true; - } - - Bitmap::ReleaseAccess( pReadAccess ); - } - - // mask processing - if( bRet && ( rBmpEx.IsTransparent() || ( nRot10 != 0 && nRot10 != 900 && nRot10 != 1800 && nRot10 != 2700 ) ) ) - { - bRet = false; - - if( rBmpEx.IsAlpha() ) - { - AlphaMask aAlpha( rBmpEx.GetAlpha() ); - AlphaMask aOutAlpha; - - pReadAccess = aAlpha.AcquireReadAccess(); - - if( pReadAccess ) - { - aOutAlpha = AlphaMask( Size( aTargetWidth, aTargetHeight ) ); - pWriteAccess = aOutAlpha.AcquireWriteAccess(); - - if( pWriteAccess ) - { - if( pReadAccess->GetScanlineFormat() == ScanlineFormat::N8BitPal && - pWriteAccess->GetScanlineFormat() == ScanlineFormat::N8BitPal ) - { - if ( !scaleByAveraging ) - { - Scanline pLine0, pLine1, pLineW; - - for( long nY = 0; nY < aTargetHeight; nY++ ) - { - nSinY = pSinY[ nY ]; - nCosY = pCosY[ nY ]; - pLineW = pWriteAccess->GetScanline( nY ); - - for( long nX = 0; nX < aTargetWidth; nX++ ) - { - nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8; - nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8; - - if( ( nUnRotX >= 0 ) && ( nUnRotX < aUnrotatedWidth ) && - ( nUnRotY >= 0 ) && ( nUnRotY < aUnrotatedHeight ) ) - { - nTmpX = pMapIX[ nUnRotX ]; - nTmpFX = pMapFX[ nUnRotX ]; - nTmpY = pMapIY[ nUnRotY ]; - nTmpFY = pMapFY[ nUnRotY ]; - - pLine0 = pReadAccess->GetScanline( nTmpY++ ); - pLine1 = pReadAccess->GetScanline( nTmpY ); - - const long nAlpha0 = pLine0[ nTmpX ]; - const long nAlpha2 = pLine1[ nTmpX++ ]; - const long nAlpha1 = pLine0[ nTmpX ]; - const long nAlpha3 = pLine1[ nTmpX ]; - const long n0 = MAP( nAlpha0, nAlpha1, nTmpFX ); - const long n1 = MAP( nAlpha2, nAlpha3, nTmpFX ); - - *pLineW++ = MAP( n0, n1, nTmpFY ); - } - else - *pLineW++ = 255; - } - } - } - else // scaleByAveraging - { - const BitmapColor aTrans( pWriteAccess->GetBestMatchingColor( COL_WHITE ) ); - BitmapColor aResultColor( 0 ); - double aSum, aCount; - - for( y = 0; y < aTargetHeight; y++ ) - { - nSinY = pSinY[ y ]; - nCosY = pCosY[ y ]; - Scanline pScanline = pWriteAccess->GetScanline( y ); - - for( x = 0; x < aTargetWidth; x++ ) - { - - double aUnrotatedX = ( pCosX[ x ] - nSinY ) / 256.0; - double aUnrotatedY = ( pSinX[ x ] + nCosY ) / 256.0; - - if ( bHMirr ) - aUnrotatedX = aUnrotatedWidth - aUnrotatedX - 1; - if ( bVMirr ) - aUnrotatedY = aUnrotatedHeight - aUnrotatedY - 1; - - if( ( aUnrotatedX >= 0 ) && ( aUnrotatedX < aUnrotatedWidth ) && - ( aUnrotatedY >= 0 ) && ( aUnrotatedY < aUnrotatedHeight ) ) - { - double dYStart = ((aUnrotatedY + 0.5) * fRevScaleY) - 0.5; - double dYEnd = ((aUnrotatedY + 1.5) * fRevScaleY) - 0.5; - - int yStart = MinMax( dYStart, 0, aBitmapHeight - 1); - int yEnd = MinMax( dYEnd, 0, aBitmapHeight - 1); - - double dXStart = ((aUnrotatedX + 0.5) * fRevScaleX) - 0.5; - double dXEnd = ((aUnrotatedX + 1.5) * fRevScaleX) - 0.5; - - int xStart = MinMax( dXStart, 0, aBitmapWidth - 1); - int xEnd = MinMax( dXEnd, 0, aBitmapWidth - 1); - - aSum = 0.0; - aCount = 0; - - for (int yIn = yStart; yIn <= yEnd; yIn++) - { - Scanline pScanlineRead = pReadAccess->GetScanline( yIn ); - for (int xIn = xStart; xIn <= xEnd; xIn++) - { - aSum += pReadAccess->GetPixelFromData( pScanlineRead, xIn ).GetIndex(); - aCount++; - } - } - aResultColor.SetIndex( MinMax( aSum / aCount, 0, 255) ); - pWriteAccess->SetPixelOnData( pScanline, x, aResultColor ); - } - else - { - pWriteAccess->SetPixelOnData( pScanline, x, aTrans ); - } - } - } - } - } - else - { - const BitmapColor aTrans( pWriteAccess->GetBestMatchingColor( COL_WHITE ) ); - BitmapColor aAlphaVal( 0 ); - - for( long nY = 0; nY < aTargetHeight; nY++ ) - { - nSinY = pSinY[ nY ]; - nCosY = pCosY[ nY ]; - Scanline pScanline = pWriteAccess->GetScanline( nY ); - - for( long nX = 0; nX < aTargetWidth; nX++ ) - { - nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8; - nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8; - - if( ( nUnRotX >= 0 ) && ( nUnRotX < aUnrotatedWidth ) && - ( nUnRotY >= 0 ) && ( nUnRotY < aUnrotatedHeight ) ) - { - nTmpX = pMapIX[ nUnRotX ]; - nTmpFX = pMapFX[ nUnRotX ]; - nTmpY = pMapIY[ nUnRotY ]; - nTmpFY = pMapFY[ nUnRotY ]; - - const long nAlpha0 = pReadAccess->GetPixel( nTmpY, nTmpX ).GetIndex(); - const long nAlpha1 = pReadAccess->GetPixel( nTmpY, ++nTmpX ).GetIndex(); - const long nAlpha3 = pReadAccess->GetPixel( ++nTmpY, nTmpX ).GetIndex(); - const long nAlpha2 = pReadAccess->GetPixel( nTmpY, --nTmpX ).GetIndex(); - const long n0 = MAP( nAlpha0, nAlpha1, nTmpFX ); - const long n1 = MAP( nAlpha2, nAlpha3, nTmpFX ); - - aAlphaVal.SetIndex( MAP( n0, n1, nTmpFY ) ); - pWriteAccess->SetPixelOnData( pScanline, nX, aAlphaVal ); - } - else - pWriteAccess->SetPixelOnData( pScanline, nX, aTrans ); - } - } - } - - aOutAlpha.ReleaseAccess( pWriteAccess ); - bRet = true; - } - - aAlpha.ReleaseAccess( pReadAccess ); - } - - if( bRet ) - rOutBmpEx = BitmapEx( aOutBmp, aOutAlpha ); - } - else - { - Bitmap aOutMsk( Size( aTargetWidth, aTargetHeight ), 1 ); - pWriteAccess = aOutMsk.AcquireWriteAccess(); - - if( pWriteAccess ) - { - Bitmap aMsk( rBmpEx.GetMask() ); - const BitmapColor aB( pWriteAccess->GetBestMatchingColor( COL_BLACK ) ); - const BitmapColor aW( pWriteAccess->GetBestMatchingColor( COL_WHITE ) ); - BitmapReadAccess* pMAcc = nullptr; - - if( !aMsk || ( ( pMAcc = aMsk.AcquireReadAccess() ) != nullptr ) ) - { - std::unique_ptr<long[]> pMapLX(new long[ aUnrotatedWidth ]); - std::unique_ptr<long[]> pMapLY(new long[ aUnrotatedHeight ]); - BitmapColor aTestB; - - if( pMAcc ) - aTestB = pMAcc->GetBestMatchingColor( COL_BLACK ); - - // create new horizontal mapping table - for( long nX = 0; nX < aUnrotatedWidth; nX++ ) - pMapLX[ nX ] = FRound( static_cast<double>(pMapIX[ nX ]) + pMapFX[ nX ] / 1048576.0 ); - - // create new vertical mapping table - for( long nY = 0; nY < aUnrotatedHeight; nY++ ) - pMapLY[ nY ] = FRound( static_cast<double>(pMapIY[ nY ]) + pMapFY[ nY ] / 1048576.0 ); - - // do mask rotation - for( long nY = 0; nY < aTargetHeight; nY++ ) - { - nSinY = pSinY[ nY ]; - nCosY = pCosY[ nY ]; - Scanline pScanline = pWriteAccess->GetScanline( nY ); - - for( long nX = 0; nX < aTargetWidth; nX++ ) - { - nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8; - nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8; - - if( ( nUnRotX >= 0 ) && ( nUnRotX < aUnrotatedWidth ) && - ( nUnRotY >= 0 ) && ( nUnRotY < aUnrotatedHeight ) ) - { - if( pMAcc ) - { - if( pMAcc->GetPixel( pMapLY[ nUnRotY ], pMapLX[ nUnRotX ] ) == aTestB ) - pWriteAccess->SetPixelOnData( pScanline, nX, aB ); - else - pWriteAccess->SetPixelOnData( pScanline, nX, aW ); - } - else - pWriteAccess->SetPixelOnData( pScanline, nX, aB ); - } - else - pWriteAccess->SetPixelOnData( pScanline, nX, aW ); - } - } - - pMapLX.reset(); - pMapLY.reset(); - - if( pMAcc ) - Bitmap::ReleaseAccess( pMAcc ); - - bRet = true; - } - - Bitmap::ReleaseAccess( pWriteAccess ); - } - - if( bRet ) - rOutBmpEx = BitmapEx( aOutBmp, aOutMsk ); - } - - if( !bRet ) - rOutBmpEx = aOutBmp; - } - else - rOutBmpEx = aOutBmp; - - return bRet; -} - -bool GraphicManager::ImplCreateOutput( OutputDevice* pOutputDevice, - const Point& rPoint, const Size& rSize, - const BitmapEx& rBitmapEx, const GraphicAttr& rAttributes, - BitmapEx* pBmpEx ) -{ - sal_uInt16 nRot10 = rAttributes.GetRotation() % 3600; - - Point aOutputPointPix; - Size aOutputSizePix; - Point aUnrotatedPointPix( pOutputDevice->LogicToPixel( rPoint ) ); - Size aUnrotatedSizePix( pOutputDevice->LogicToPixel( rSize ) ); - - bool bRet = false; - - if( nRot10 ) - { - tools::Polygon aPoly( tools::Rectangle( rPoint, rSize ) ); - aPoly.Rotate( rPoint, nRot10 ); - const tools::Rectangle aRotBoundRect( aPoly.GetBoundRect() ); - aOutputPointPix = pOutputDevice->LogicToPixel( aRotBoundRect.TopLeft() ); - aOutputSizePix = pOutputDevice->LogicToPixel( aRotBoundRect.GetSize() ); - } - else - { - aOutputPointPix = aUnrotatedPointPix; - aOutputSizePix = aUnrotatedSizePix; - } - - if( aUnrotatedSizePix.Width() && aUnrotatedSizePix.Height() ) - { - BitmapEx aOutBmpEx; - Point aOutPoint; - Size aOutSize; - const Size& rBmpSzPix = rBitmapEx.GetSizePixel(); - const long nW = rBmpSzPix.Width(); - const long nH = rBmpSzPix.Height(); - long nStartX = -1, nStartY = -1, nEndX = -1, nEndY = -1; - bool bHMirr( rAttributes.GetMirrorFlags() & BmpMirrorFlags::Horizontal ); - bool bVMirr( rAttributes.GetMirrorFlags() & BmpMirrorFlags::Vertical ); - - // calculate output sizes - if( !pBmpEx ) - { - tools::Rectangle aOutRect( Point(), pOutputDevice->GetOutputSizePixel() ); - tools::Rectangle aBmpRect( aOutputPointPix, aOutputSizePix ); - - if( pOutputDevice->GetOutDevType() == OUTDEV_WINDOW ) - { - const vcl::Region aPaintRgn( static_cast<vcl::Window*>( pOutputDevice )->GetPaintRegion() ); - if( !aPaintRgn.IsNull() ) - aOutRect.Intersection( pOutputDevice->LogicToPixel( aPaintRgn.GetBoundRect() ) ); - } - - aOutRect.Intersection( aBmpRect ); - - if( !aOutRect.IsEmpty() ) - { - aOutPoint = pOutputDevice->PixelToLogic( aOutRect.TopLeft() ); - aOutSize = pOutputDevice->PixelToLogic( aOutRect.GetSize() ); - nStartX = aOutRect.Left() - aBmpRect.Left(); - nStartY = aOutRect.Top() - aBmpRect.Top(); - nEndX = aOutRect.Right() - aBmpRect.Left(); - nEndY = aOutRect.Bottom() - aBmpRect.Top(); - } - else - { - nStartX = -1; // invalid - } - } - else - { - aOutPoint = pOutputDevice->PixelToLogic( aOutputPointPix ); - aOutSize = pOutputDevice->PixelToLogic( aOutputSizePix ); - nStartX = nStartY = 0; - nEndX = aOutputSizePix.Width() - 1; - nEndY = aOutputSizePix.Height() - 1; - } - - // do transformation - if( nStartX >= 0 ) - { - const bool bSimple = ( 1 == nW || 1 == nH ); - - if( nRot10 ) - { - if( bSimple ) - { - bRet = ( aOutBmpEx = rBitmapEx ).Scale( aUnrotatedSizePix ); - - if( bRet ) - aOutBmpEx.Rotate( nRot10, COL_TRANSPARENT ); - } - else - { - bRet = ImplCreateRotatedScaled( rBitmapEx, rAttributes, - nRot10, aUnrotatedSizePix, - nStartX, nEndX, nStartY, nEndY, - aOutBmpEx ); - } - } - else - { - if( !bHMirr && !bVMirr && aOutputSizePix == rBmpSzPix ) - { - aOutPoint = pOutputDevice->PixelToLogic( aOutputPointPix ); - aOutSize = pOutputDevice->PixelToLogic( aOutputSizePix ); - aOutBmpEx = rBitmapEx; - bRet = true; - } - else - { - if( bSimple ) - { - bRet = ( aOutBmpEx = rBitmapEx ).Scale( Size( nEndX - nStartX + 1, nEndY - nStartY + 1 ) ); - } - else - { - bRet = ImplCreateRotatedScaled( rBitmapEx, rAttributes, - nRot10, aUnrotatedSizePix, - nStartX, nEndX, nStartY, nEndY, - aOutBmpEx ); - } - } - } - - if( bRet ) - { - // Attribute adjustment if necessary - if( rAttributes.IsSpecialDrawMode() || rAttributes.IsAdjusted() || rAttributes.IsTransparent() ) - ImplAdjust( aOutBmpEx, rAttributes, GraphicAdjustmentFlags::DRAWMODE | GraphicAdjustmentFlags::COLORS | GraphicAdjustmentFlags::TRANSPARENCY ); - - // OutDev adjustment if necessary - if( pOutputDevice->GetOutDevType() != OUTDEV_PRINTER && pOutputDevice->GetBitCount() <= 8 && aOutBmpEx.GetBitCount() >= 8 ) - aOutBmpEx.Dither(); - } - } - - // Create output - if( bRet ) - { - if( !pBmpEx ) - pOutputDevice->DrawBitmapEx( aOutPoint, aOutSize, aOutBmpEx ); - else - { - if( !rAttributes.IsTransparent() && !aOutBmpEx.IsAlpha() ) - aOutBmpEx = BitmapEx( aOutBmpEx.GetBitmap().CreateDisplayBitmap( pOutputDevice ), aOutBmpEx.GetMask() ); - - pOutputDevice->DrawBitmapEx( aOutPoint, aOutSize, *pBmpEx = aOutBmpEx ); - } - } - } - - return bRet; -} - -// This function checks whether the bitmap is usable for skipping -// mtf rendering by using just this one bitmap (i.e. in case the metafile -// contains just this one pixmap that covers the entire metafile area). -static BitmapEx checkMetadataBitmap( const BitmapEx& rBmpEx, - Point rSrcPoint, - Size rSrcSize, - const Point& rDestPoint, - const Size& rDestSize, - const Size& rRefSize, - bool& o_rbNonBitmapActionEncountered ) -{ -// NOTE: If you do changes in this function, change checkMetadataBitmap() in grfcache.cxx too. - BitmapEx aBmpEx; - if( rSrcSize == Size()) - rSrcSize = rBmpEx.GetSizePixel(); - - if( rDestPoint != Point( 0, 0 )) - { // The pixmap in the metafile has an offset (and so would not cover) - // the entire result -> fall back to mtf rendering. - o_rbNonBitmapActionEncountered = true; - return aBmpEx; - } - if( rDestSize != rRefSize ) - { // The pixmap is not fullscale (does not cover the entire metafile area). - // HACK: The code here should refuse to use the bitmap directly - // and fall back to mtf rendering, but there seem to be metafiles - // that do not specify exactly their area (the Windows API requires apps - // the specify it manually, the rectangle is specified as topleft/bottomright - // rather than topleft/size [which may be confusing], and the docs - // on the exact meaning are somewhat confusing as well), so if it turns - // out this metafile really contains just one bitmap and no other painting, - // and if the sizes almost match, just use the pixmap (which will be scaled - // to fit exactly the requested size, so there should not be any actual problem - // caused by this small difference). This will allow caching of the resulting - // (scaled) pixmap, which can make a noticeable performance difference. - if( rBmpEx.GetSizePixel().Width() > 100 && rBmpEx.GetSizePixel().Height() > 100 - && std::abs( rDestSize.Width() - rRefSize.Width()) < 5 - && std::abs( rDestSize.Height() - rRefSize.Height()) < 5 ) - ; // ok, assume it's close enough - else - { // fall back to mtf rendering - o_rbNonBitmapActionEncountered = true; - return aBmpEx; - } - } - - aBmpEx = rBmpEx; - - if( (rSrcPoint.X() != 0 && rSrcPoint.Y() != 0) || - rSrcSize != rBmpEx.GetSizePixel() ) - { - // crop bitmap to given source rectangle (no - // need to copy and convert the whole bitmap) - const tools::Rectangle aCropRect( rSrcPoint, - rSrcSize ); - aBmpEx.Crop( aCropRect ); - } - - return aBmpEx; -} - -bool GraphicManager::ImplCreateOutput( OutputDevice* pOut, - const Point& rPt, const Size& rSz, - const GDIMetaFile& rMtf, const GraphicAttr& rAttr, - GDIMetaFile& rOutMtf, BitmapEx& rOutBmpEx ) -{ - const Size aNewSize( rMtf.GetPrefSize() ); - - rOutMtf = rMtf; - - // Count bitmap actions, and flag actions that paint, but - // are no bitmaps. - sal_Int32 nNumBitmaps(0); - bool bNonBitmapActionEncountered(false); - if( aNewSize.Width() && aNewSize.Height() && rSz.Width() && rSz.Height() ) - { - const double fGrfWH = static_cast<double>(aNewSize.Width()) / aNewSize.Height(); - const double fOutWH = static_cast<double>(rSz.Width()) / rSz.Height(); - - const double fScaleX = fOutWH / fGrfWH; - const double fScaleY = 1.0; - - const MapMode& rPrefMapMode( rMtf.GetPrefMapMode() ); - const Size rSizePix( pOut->LogicToPixel( aNewSize, rPrefMapMode ) ); - -// NOTE: If you do changes in this function, check GraphicDisplayCacheEntry::IsCacheableAsBitmap -// in grfcache.cxx too. - - // Determine whether the metafile basically displays - // a single bitmap (in which case that bitmap is simply used directly - // instead of playing the metafile). Note that - // the solution, as implemented here, is quite suboptimal (the - // cases where a mtf consisting basically of a single bitmap, - // that fail to pass the test below, are probably frequent). A - // better solution would involve FSAA, but that's currently - // expensive, and might trigger bugs on display drivers, if - // VDevs get bigger than the actual screen. - sal_uInt32 nCurPos; - MetaAction* pAct; - for( nCurPos = 0, pAct = rOutMtf.FirstAction(); pAct; - pAct = rOutMtf.NextAction(), nCurPos++ ) - { - MetaAction* pModAct = nullptr; - switch( pAct->GetType() ) - { - case MetaActionType::FONT: - { - // taking care of font width default if scaling metafile. - MetaFontAction* pA = static_cast<MetaFontAction*>(pAct); - vcl::Font aFont( pA->GetFont() ); - if ( !aFont.GetAverageFontWidth() ) - { - FontMetric aFontMetric( pOut->GetFontMetric( aFont ) ); - aFont.SetAverageFontWidth( aFontMetric.GetAverageFontWidth() ); - pModAct = new MetaFontAction( aFont ); - } - SAL_FALLTHROUGH; - } - case MetaActionType::NONE: - SAL_FALLTHROUGH; - - // OutDev state changes (which don't affect bitmap - // output) - case MetaActionType::LINECOLOR: - SAL_FALLTHROUGH; - case MetaActionType::FILLCOLOR: - SAL_FALLTHROUGH; - case MetaActionType::TEXTCOLOR: - SAL_FALLTHROUGH; - case MetaActionType::TEXTFILLCOLOR: - SAL_FALLTHROUGH; - case MetaActionType::TEXTALIGN: - SAL_FALLTHROUGH; - case MetaActionType::TEXTLINECOLOR: - SAL_FALLTHROUGH; - case MetaActionType::TEXTLINE: - SAL_FALLTHROUGH; - case MetaActionType::PUSH: - SAL_FALLTHROUGH; - case MetaActionType::POP: - SAL_FALLTHROUGH; - case MetaActionType::LAYOUTMODE: - SAL_FALLTHROUGH; - case MetaActionType::TEXTLANGUAGE: - SAL_FALLTHROUGH; - case MetaActionType::COMMENT: - break; - - // bitmap output methods - case MetaActionType::BMP: - if( !nNumBitmaps && !bNonBitmapActionEncountered ) - { - MetaBmpAction* pAction = static_cast<MetaBmpAction*>(pAct); - - rOutBmpEx = checkMetadataBitmap( - BitmapEx( pAction->GetBitmap()), - Point(), Size(), - pOut->LogicToPixel( pAction->GetPoint(), - rPrefMapMode ), - pAction->GetBitmap().GetSizePixel(), - rSizePix, - bNonBitmapActionEncountered ); - } - ++nNumBitmaps; - break; - - case MetaActionType::BMPSCALE: - if( !nNumBitmaps && !bNonBitmapActionEncountered ) - { - MetaBmpScaleAction* pAction = static_cast<MetaBmpScaleAction*>(pAct); - - rOutBmpEx = checkMetadataBitmap( - BitmapEx( pAction->GetBitmap()), - Point(), Size(), - pOut->LogicToPixel( pAction->GetPoint(), - rPrefMapMode ), - pOut->LogicToPixel( pAction->GetSize(), - rPrefMapMode ), - rSizePix, - bNonBitmapActionEncountered ); - } - ++nNumBitmaps; - break; - - case MetaActionType::BMPSCALEPART: - if( !nNumBitmaps && !bNonBitmapActionEncountered ) - { - MetaBmpScalePartAction* pAction = static_cast<MetaBmpScalePartAction*>(pAct); - - rOutBmpEx = checkMetadataBitmap( - BitmapEx( pAction->GetBitmap() ), - pAction->GetSrcPoint(), - pAction->GetSrcSize(), - pOut->LogicToPixel( pAction->GetDestPoint(), - rPrefMapMode ), - pOut->LogicToPixel( pAction->GetDestSize(), - rPrefMapMode ), - rSizePix, - bNonBitmapActionEncountered ); - } - ++nNumBitmaps; - break; - - case MetaActionType::BMPEX: - if( !nNumBitmaps && !bNonBitmapActionEncountered ) - { - MetaBmpExAction* pAction = static_cast<MetaBmpExAction*>(pAct); - - rOutBmpEx = checkMetadataBitmap( - pAction->GetBitmapEx(), - Point(), Size(), - pOut->LogicToPixel( pAction->GetPoint(), - rPrefMapMode ), - pAction->GetBitmapEx().GetSizePixel(), - rSizePix, - bNonBitmapActionEncountered ); - } - ++nNumBitmaps; - break; - - case MetaActionType::BMPEXSCALE: - if( !nNumBitmaps && !bNonBitmapActionEncountered ) - { - MetaBmpExScaleAction* pAction = static_cast<MetaBmpExScaleAction*>(pAct); - - rOutBmpEx = checkMetadataBitmap( - pAction->GetBitmapEx(), - Point(), Size(), - pOut->LogicToPixel( pAction->GetPoint(), - rPrefMapMode ), - pOut->LogicToPixel( pAction->GetSize(), - rPrefMapMode ), - rSizePix, - bNonBitmapActionEncountered ); - } - ++nNumBitmaps; - break; - - case MetaActionType::BMPEXSCALEPART: - if( !nNumBitmaps && !bNonBitmapActionEncountered ) - { - MetaBmpExScalePartAction* pAction = static_cast<MetaBmpExScalePartAction*>(pAct); - - rOutBmpEx = checkMetadataBitmap( pAction->GetBitmapEx(), - pAction->GetSrcPoint(), - pAction->GetSrcSize(), - pOut->LogicToPixel( pAction->GetDestPoint(), - rPrefMapMode ), - pOut->LogicToPixel( pAction->GetDestSize(), - rPrefMapMode ), - rSizePix, - bNonBitmapActionEncountered ); - } - ++nNumBitmaps; - break; - - // these actions actually output something (that's - // different from a bitmap) - case MetaActionType::RASTEROP: - if( static_cast<MetaRasterOpAction*>(pAct)->GetRasterOp() == RasterOp::OverPaint ) - break; - SAL_FALLTHROUGH; - case MetaActionType::PIXEL: - SAL_FALLTHROUGH; - case MetaActionType::POINT: - SAL_FALLTHROUGH; - case MetaActionType::LINE: - SAL_FALLTHROUGH; - case MetaActionType::RECT: - SAL_FALLTHROUGH; - case MetaActionType::ROUNDRECT: - SAL_FALLTHROUGH; - case MetaActionType::ELLIPSE: - SAL_FALLTHROUGH; - case MetaActionType::ARC: - SAL_FALLTHROUGH; - case MetaActionType::PIE: - SAL_FALLTHROUGH; - case MetaActionType::CHORD: - SAL_FALLTHROUGH; - case MetaActionType::POLYLINE: - SAL_FALLTHROUGH; - case MetaActionType::POLYGON: - SAL_FALLTHROUGH; - case MetaActionType::POLYPOLYGON: - SAL_FALLTHROUGH; - - case MetaActionType::TEXT: - SAL_FALLTHROUGH; - case MetaActionType::TEXTARRAY: - SAL_FALLTHROUGH; - case MetaActionType::STRETCHTEXT: - SAL_FALLTHROUGH; - case MetaActionType::TEXTRECT: - SAL_FALLTHROUGH; - - case MetaActionType::MASK: - SAL_FALLTHROUGH; - case MetaActionType::MASKSCALE: - SAL_FALLTHROUGH; - case MetaActionType::MASKSCALEPART: - SAL_FALLTHROUGH; - - case MetaActionType::GRADIENT: - SAL_FALLTHROUGH; - case MetaActionType::HATCH: - SAL_FALLTHROUGH; - case MetaActionType::WALLPAPER: - SAL_FALLTHROUGH; - - case MetaActionType::Transparent: - SAL_FALLTHROUGH; - case MetaActionType::EPS: - SAL_FALLTHROUGH; - case MetaActionType::FLOATTRANSPARENT: - SAL_FALLTHROUGH; - case MetaActionType::GRADIENTEX: - SAL_FALLTHROUGH; - - // OutDev state changes that _do_ affect bitmap - // output - case MetaActionType::CLIPREGION: - SAL_FALLTHROUGH; - case MetaActionType::ISECTRECTCLIPREGION: - SAL_FALLTHROUGH; - case MetaActionType::ISECTREGIONCLIPREGION: - SAL_FALLTHROUGH; - case MetaActionType::MOVECLIPREGION: - SAL_FALLTHROUGH; - - case MetaActionType::MAPMODE: - SAL_FALLTHROUGH; - case MetaActionType::REFPOINT: - SAL_FALLTHROUGH; - default: - bNonBitmapActionEncountered = true; - break; - } - if ( pModAct ) - { - MetaAction* pDeleteAction = rOutMtf.ReplaceAction( pModAct, nCurPos ); - assert(pDeleteAction); - pDeleteAction->Delete(); - } - else - { - if( pAct->GetRefCount() > 1 ) - { - MetaAction* pDeleteAction = rOutMtf.ReplaceAction( pModAct = pAct->Clone(), nCurPos ); - assert(pDeleteAction); - pDeleteAction->Delete(); - } - else - pModAct = pAct; - } - pModAct->Scale( fScaleX, fScaleY ); - } - rOutMtf.SetPrefSize( Size( FRound( aNewSize.Width() * fScaleX ), - FRound( aNewSize.Height() * fScaleY ) ) ); - } - - if( nNumBitmaps != 1 || bNonBitmapActionEncountered ) - { - if( rAttr.IsSpecialDrawMode() || rAttr.IsAdjusted() || rAttr.IsMirrored() || rAttr.IsRotated() || rAttr.IsTransparent() ) - ImplAdjust( rOutMtf, rAttr, GraphicAdjustmentFlags::ALL ); - - ImplDraw( pOut, rPt, rSz, rOutMtf, rAttr ); - rOutBmpEx = BitmapEx(); - } - - return true; -} - -void GraphicManager::ImplAdjust( BitmapEx& rBmpEx, const GraphicAttr& rAttr, GraphicAdjustmentFlags nAdjustmentFlags ) -{ - GraphicAttr aAttr( rAttr ); - - if( ( nAdjustmentFlags & GraphicAdjustmentFlags::DRAWMODE ) && aAttr.IsSpecialDrawMode() ) - { - switch( aAttr.GetDrawMode() ) - { - case GraphicDrawMode::Mono: - rBmpEx.Convert( BmpConversion::N1BitThreshold ); - break; - - case GraphicDrawMode::Greys: - rBmpEx.Convert( BmpConversion::N8BitGreys ); - break; - - case GraphicDrawMode::Watermark: - { - aAttr.SetLuminance( aAttr.GetLuminance() + WATERMARK_LUM_OFFSET ); - aAttr.SetContrast( aAttr.GetContrast() + WATERMARK_CON_OFFSET ); - } - break; - - default: - break; - } - } - - if( ( nAdjustmentFlags & GraphicAdjustmentFlags::COLORS ) && aAttr.IsAdjusted() ) - { - rBmpEx.Adjust( aAttr.GetLuminance(), aAttr.GetContrast(), - aAttr.GetChannelR(), aAttr.GetChannelG(), aAttr.GetChannelB(), - aAttr.GetGamma(), aAttr.IsInvert() ); - } - - if( ( nAdjustmentFlags & GraphicAdjustmentFlags::MIRROR ) && aAttr.IsMirrored() ) - { - rBmpEx.Mirror( aAttr.GetMirrorFlags() ); - } - - if( ( nAdjustmentFlags & GraphicAdjustmentFlags::ROTATE ) && aAttr.IsRotated() ) - { - rBmpEx.Rotate( aAttr.GetRotation(), COL_TRANSPARENT ); - } - - if( ( nAdjustmentFlags & GraphicAdjustmentFlags::TRANSPARENCY ) && aAttr.IsTransparent() ) - { - rBmpEx.AdjustTransparency(aAttr.GetTransparency()); - } -} - -void GraphicManager::ImplAdjust( GDIMetaFile& rMtf, const GraphicAttr& rAttr, GraphicAdjustmentFlags nAdjustmentFlags ) -{ - GraphicAttr aAttr( rAttr ); - - if( ( nAdjustmentFlags & GraphicAdjustmentFlags::DRAWMODE ) && aAttr.IsSpecialDrawMode() ) - { - switch( aAttr.GetDrawMode() ) - { - case GraphicDrawMode::Mono: - rMtf.Convert( MtfConversion::N1BitThreshold ); - break; - - case GraphicDrawMode::Greys: - rMtf.Convert( MtfConversion::N8BitGreys ); - break; - - case GraphicDrawMode::Watermark: - { - aAttr.SetLuminance( aAttr.GetLuminance() + WATERMARK_LUM_OFFSET ); - aAttr.SetContrast( aAttr.GetContrast() + WATERMARK_CON_OFFSET ); - } - break; - - default: - break; - } - } - - if( ( nAdjustmentFlags & GraphicAdjustmentFlags::COLORS ) && aAttr.IsAdjusted() ) - { - rMtf.Adjust( aAttr.GetLuminance(), aAttr.GetContrast(), - aAttr.GetChannelR(), aAttr.GetChannelG(), aAttr.GetChannelB(), - aAttr.GetGamma(), aAttr.IsInvert() ); - } - - if( ( nAdjustmentFlags & GraphicAdjustmentFlags::MIRROR ) && aAttr.IsMirrored() ) - { - rMtf.Mirror( aAttr.GetMirrorFlags() ); - } - - if( ( nAdjustmentFlags & GraphicAdjustmentFlags::ROTATE ) && aAttr.IsRotated() ) - { - rMtf.Rotate( aAttr.GetRotation() ); - } - - if( ( nAdjustmentFlags & GraphicAdjustmentFlags::TRANSPARENCY ) && aAttr.IsTransparent() ) - { - OSL_FAIL( "Missing implementation: Mtf-Transparency" ); - } -} - -void GraphicManager::ImplAdjust( Animation& rAnimation, const GraphicAttr& rAttr, GraphicAdjustmentFlags nAdjustmentFlags ) -{ - GraphicAttr aAttr( rAttr ); - - if( ( nAdjustmentFlags & GraphicAdjustmentFlags::DRAWMODE ) && aAttr.IsSpecialDrawMode() ) - { - switch( aAttr.GetDrawMode() ) - { - case GraphicDrawMode::Mono: - rAnimation.Convert( BmpConversion::N1BitThreshold ); - break; - - case GraphicDrawMode::Greys: - rAnimation.Convert( BmpConversion::N8BitGreys ); - break; - - case GraphicDrawMode::Watermark: - { - aAttr.SetLuminance( aAttr.GetLuminance() + WATERMARK_LUM_OFFSET ); - aAttr.SetContrast( aAttr.GetContrast() + WATERMARK_CON_OFFSET ); - } - break; - - default: - break; - } - } - - if( ( nAdjustmentFlags & GraphicAdjustmentFlags::COLORS ) && aAttr.IsAdjusted() ) - { - rAnimation.Adjust( aAttr.GetLuminance(), aAttr.GetContrast(), - aAttr.GetChannelR(), aAttr.GetChannelG(), aAttr.GetChannelB(), - aAttr.GetGamma(), aAttr.IsInvert() ); - } - - if( ( nAdjustmentFlags & GraphicAdjustmentFlags::MIRROR ) && aAttr.IsMirrored() ) - { - rAnimation.Mirror( aAttr.GetMirrorFlags() ); - } - - if( ( nAdjustmentFlags & GraphicAdjustmentFlags::ROTATE ) && aAttr.IsRotated() ) - { - OSL_FAIL( "Missing implementation: Animation-Rotation" ); - } - - if( ( nAdjustmentFlags & GraphicAdjustmentFlags::TRANSPARENCY ) && aAttr.IsTransparent() ) - { - OSL_FAIL( "Missing implementation: Animation-Transparency" ); - } -} - -void GraphicManager::ImplDraw( OutputDevice* pOut, const Point& rPt, const Size& rSz, - const GDIMetaFile& rMtf, const GraphicAttr& rAttr ) -{ - sal_uInt16 nRot10 = rAttr.GetRotation() % 3600; - Point aOutPt( rPt ); - Size aOutSz( rSz ); - - if( nRot10 ) - { - tools::Polygon aPoly( tools::Rectangle( aOutPt, aOutSz ) ); - - aPoly.Rotate( aOutPt, nRot10 ); - const tools::Rectangle aRotBoundRect( aPoly.GetBoundRect() ); - aOutPt = aRotBoundRect.TopLeft(); - aOutSz = aRotBoundRect.GetSize(); - } - - pOut->Push( PushFlags::CLIPREGION ); - pOut->IntersectClipRegion( tools::Rectangle( aOutPt, aOutSz ) ); - - const_cast<GDIMetaFile&>(rMtf).WindStart(); - const_cast<GDIMetaFile&>(rMtf).Play( pOut, aOutPt, aOutSz ); - const_cast<GDIMetaFile&>(rMtf).WindStart(); - - pOut->Pop(); -} - struct ImplTileInfo { ImplTileInfo() : aTileTopLeft(), aNextTileTopLeft(), aTileSizePixel(), nTilesEmptyX(0), nTilesEmptyY(0) {} diff --git a/vcl/source/graphic/grfcache.cxx b/vcl/source/graphic/grfcache.cxx deleted file mode 100644 index 53fa0f268abe..000000000000 --- a/vcl/source/graphic/grfcache.cxx +++ /dev/null @@ -1,1221 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include <sal/config.h> - -#include <cstdlib> - -#include <salhelper/timer.hxx> -#include <vcl/GraphicObject.hxx> -#include <tools/debug.hxx> -#include <vcl/metaact.hxx> -#include <vcl/outdev.hxx> -#include <tools/poly.hxx> -#include <rtl/strbuf.hxx> -#include "grfcache.hxx" -#include <rtl/crc.h> -#include <memory> - -#define MAX_BMP_EXTENT 4096 - -using namespace com::sun::star; - -static const char aHexData[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - -class GraphicID -{ -private: - - sal_uInt32 mnID1; - sal_uInt32 mnID2; - sal_uInt32 mnID3; - BitmapChecksum mnID4; - -public: - explicit GraphicID( const GraphicObject& rObj ); - - bool operator==( const GraphicID& rID ) const - { - return( rID.mnID1 == mnID1 && rID.mnID2 == mnID2 && - rID.mnID3 == mnID3 && rID.mnID4 == mnID4 ); - } - - OString GetIDString() const; - bool IsEmpty() const { return( 0 == mnID4 ); } -}; - -GraphicID::GraphicID( const GraphicObject& rObj ) -{ - const Graphic& rGraphic = rObj.GetGraphic(); - - mnID1 = static_cast<sal_uLong>(rGraphic.GetType()) << 28; - - switch( rGraphic.GetType() ) - { - case GraphicType::Bitmap: - { - if(rGraphic.getVectorGraphicData().get()) - { - const VectorGraphicDataPtr& rVectorGraphicDataPtr = rGraphic.getVectorGraphicData(); - const basegfx::B2DRange& rRange = rVectorGraphicDataPtr->getRange(); - - mnID1 |= rVectorGraphicDataPtr->getVectorGraphicDataArrayLength(); - mnID2 = basegfx::fround(rRange.getWidth()); - mnID3 = basegfx::fround(rRange.getHeight()); - mnID4 = vcl_get_checksum(0, rVectorGraphicDataPtr->getVectorGraphicDataArray().getConstArray(), rVectorGraphicDataPtr->getVectorGraphicDataArrayLength()); - } - else if( rGraphic.IsAnimated() ) - { - const Animation aAnimation( rGraphic.GetAnimation() ); - - mnID1 |= ( aAnimation.Count() & 0x0fffffff ); - mnID2 = aAnimation.GetDisplaySizePixel().Width(); - mnID3 = aAnimation.GetDisplaySizePixel().Height(); - mnID4 = rGraphic.GetChecksum(); - } - else - { - const BitmapEx aBmpEx( rGraphic.GetBitmapEx() ); - - mnID1 |= ( ( ( static_cast<sal_uLong>(aBmpEx.GetTransparentType()) << 8 ) | ( aBmpEx.IsAlpha() ? 1 : 0 ) ) & 0x0fffffff ); - mnID2 = aBmpEx.GetSizePixel().Width(); - mnID3 = aBmpEx.GetSizePixel().Height(); - mnID4 = rGraphic.GetChecksum(); - } - } - break; - - case GraphicType::GdiMetafile: - { - const GDIMetaFile& rMtf = rGraphic.GetGDIMetaFile(); - - mnID1 |= ( rMtf.GetActionSize() & 0x0fffffff ); - mnID2 = rMtf.GetPrefSize().Width(); - mnID3 = rMtf.GetPrefSize().Height(); - mnID4 = rGraphic.GetChecksum(); - } - break; - - default: - mnID2 = mnID3 = mnID4 = 0; - break; - } -} - -OString GraphicID::GetIDString() const -{ - OStringBuffer aHexStr; - sal_Int32 nShift, nIndex = 0; - aHexStr.setLength(24 + (2 * BITMAP_CHECKSUM_SIZE)); - - for( nShift = 28; nShift >= 0; nShift -= 4 ) - aHexStr[nIndex++] = aHexData[ ( mnID1 >> static_cast<sal_uInt32>(nShift) ) & 0xf ]; - - for( nShift = 28; nShift >= 0; nShift -= 4 ) - aHexStr[nIndex++] = aHexData[ ( mnID2 >> static_cast<sal_uInt32>(nShift) ) & 0xf ]; - - for( nShift = 28; nShift >= 0; nShift -= 4 ) - aHexStr[nIndex++] = aHexData[ ( mnID3 >> static_cast<sal_uInt32>(nShift) ) & 0xf ]; - - for( nShift = ( 8 * BITMAP_CHECKSUM_SIZE ) - 4; nShift >= 0; nShift -= 4 ) - aHexStr[nIndex++] = aHexData[ ( mnID4 >> static_cast<sal_uInt32>(nShift) ) & 0xf ]; - - return aHexStr.makeStringAndClear(); -} - -class GraphicCacheEntry -{ -private: - - std::vector< GraphicObject* > maGraphicObjectList; - - GraphicID maID; - GfxLink maGfxLink; - std::unique_ptr<BitmapEx> mpBmpEx; - std::unique_ptr<GDIMetaFile> mpMtf; - std::unique_ptr<Animation> mpAnimation; - bool mbSwappedAll; - - // VectorGraphicData support - VectorGraphicDataPtr maVectorGraphicData; - uno::Sequence<sal_Int8> maPdfData; - - bool ImplInit( const GraphicObject& rObj ); - void ImplFillSubstitute( Graphic& rSubstitute ); - -public: - - explicit GraphicCacheEntry( const GraphicObject& rObj ); - ~GraphicCacheEntry(); - - const GraphicID& GetID() const { return maID; } - - void AddGraphicObjectReference( const GraphicObject& rObj, Graphic& rSubstitute ); - bool ReleaseGraphicObjectReference( const GraphicObject& rObj ); - size_t GetGraphicObjectReferenceCount() { return maGraphicObjectList.size(); } - bool HasGraphicObjectReference( const GraphicObject& rObj ); - - void TryToSwapIn(); - void GraphicObjectWasSwappedOut(); - void GraphicObjectWasSwappedIn( const GraphicObject& rObj ); -}; - -GraphicCacheEntry::GraphicCacheEntry( const GraphicObject& rObj ) : - maID ( rObj ), - mbSwappedAll ( true ) -{ - mbSwappedAll = !ImplInit( rObj ); - maGraphicObjectList.push_back( const_cast<GraphicObject*>(&rObj) ); -} - -GraphicCacheEntry::~GraphicCacheEntry() -{ - DBG_ASSERT( - maGraphicObjectList.empty(), - "GraphicCacheEntry::~GraphicCacheEntry(): Not all GraphicObjects are removed from this entry" - ); -} - -bool GraphicCacheEntry::ImplInit( const GraphicObject& rObj ) -{ - bool bRet = false; - - if( !rObj.IsSwappedOut() ) - { - const Graphic& rGraphic = rObj.GetGraphic(); - - mpBmpEx.reset(); - mpMtf.reset(); - mpAnimation.reset(); - - switch( rGraphic.GetType() ) - { - case GraphicType::Bitmap: - { - if(rGraphic.getVectorGraphicData().get()) - { - maVectorGraphicData = rGraphic.getVectorGraphicData(); - } - else if( rGraphic.IsAnimated() ) - { - mpAnimation.reset(new Animation( rGraphic.GetAnimation() )); - } - else - { - mpBmpEx.reset(new BitmapEx( rGraphic.GetBitmapEx() )); - if (rGraphic.getPdfData().hasElements()) - maPdfData = rGraphic.getPdfData(); - } - } - break; - - case GraphicType::GdiMetafile: - { - mpMtf.reset(new GDIMetaFile( rGraphic.GetGDIMetaFile() )); - } - break; - - default: - DBG_ASSERT( GetID().IsEmpty(), "GraphicCacheEntry::ImplInit: Could not initialize graphic! (=>KA)" ); - break; - } - - if( rGraphic.IsLink() ) - maGfxLink = rGraphic.GetLink(); - else - maGfxLink = GfxLink(); - - bRet = true; - } - - return bRet; -} - -void GraphicCacheEntry::ImplFillSubstitute( Graphic& rSubstitute ) -{ - // create substitute for graphic; - const Size aPrefSize( rSubstitute.GetPrefSize() ); - const MapMode aPrefMapMode( rSubstitute.GetPrefMapMode() ); - const Link<Animation*,void> aAnimationNotifyHdl( rSubstitute.GetAnimationNotifyHdl() ); - const GraphicType eOldType = rSubstitute.GetType(); - const bool bDefaultType = ( rSubstitute.GetType() == GraphicType::Default ); - - if( rSubstitute.IsLink() && ( GfxLinkType::NONE == maGfxLink.GetType() ) ) - maGfxLink = rSubstitute.GetLink(); - - if(maVectorGraphicData.get()) - { - rSubstitute = maVectorGraphicData; - } - else if( mpBmpEx ) - { - rSubstitute = *mpBmpEx; - if (maPdfData.hasElements()) - rSubstitute.setPdfData(maPdfData); - } - else if( mpAnimation ) - { - rSubstitute = *mpAnimation; - } - else if( mpMtf ) - { - rSubstitute = *mpMtf; - } - else - { - rSubstitute.Clear(); - } - - if( eOldType != GraphicType::NONE ) - { - rSubstitute.SetPrefSize( aPrefSize ); - rSubstitute.SetPrefMapMode( aPrefMapMode ); - rSubstitute.SetAnimationNotifyHdl( aAnimationNotifyHdl ); - } - - if( GfxLinkType::NONE != maGfxLink.GetType() ) - { - rSubstitute.SetLink( maGfxLink ); - } - - if( bDefaultType ) - { - rSubstitute.SetDefaultType(); - } -} - -void GraphicCacheEntry::AddGraphicObjectReference( const GraphicObject& rObj, Graphic& rSubstitute ) -{ - if( mbSwappedAll ) - mbSwappedAll = !ImplInit( rObj ); - - OUString rOriginURL = rObj.GetGraphic().getOriginURL(); - ImplFillSubstitute( rSubstitute ); - rSubstitute.setOriginURL(rOriginURL); - maGraphicObjectList.push_back( const_cast<GraphicObject*>(&rObj) ); -} - -bool GraphicCacheEntry::ReleaseGraphicObjectReference( const GraphicObject& rObj ) -{ - for( - auto it = maGraphicObjectList.begin(); - it != maGraphicObjectList.end(); - ++it - ) { - if( &rObj == *it ) - { - maGraphicObjectList.erase( it ); - return true; - } - } - - return false; -} - -bool GraphicCacheEntry::HasGraphicObjectReference( const GraphicObject& rObj ) -{ - bool bRet = false; - - for( size_t i = 0, n = maGraphicObjectList.size(); ( i < n ) && !bRet; ++i ) - if( &rObj == maGraphicObjectList[ i ] ) - bRet = true; - - return bRet; -} - -void GraphicCacheEntry::TryToSwapIn() -{ - if( mbSwappedAll && !maGraphicObjectList.empty() ) - maGraphicObjectList.front()->FireSwapInRequest(); -} - -void GraphicCacheEntry::GraphicObjectWasSwappedOut() -{ - mbSwappedAll = true; - - for( size_t i = 0, n = maGraphicObjectList.size(); ( i < n ) && mbSwappedAll; ++i ) - if( !maGraphicObjectList[ i ]->IsSwappedOut() ) - mbSwappedAll = false; - - if( !mbSwappedAll ) - return; - - mpBmpEx.reset(); - mpMtf.reset(); - mpAnimation.reset(); - - // #119176# also reset VectorGraphicData - maVectorGraphicData.reset(); - maPdfData = uno::Sequence<sal_Int8>(); -} - -void GraphicCacheEntry::GraphicObjectWasSwappedIn( const GraphicObject& rObj ) -{ - if( mbSwappedAll ) - mbSwappedAll = !ImplInit( rObj ); -} - -class GraphicDisplayCacheEntry -{ -private: - - ::salhelper::TTimeValue maReleaseTime; - const GraphicCacheEntry* mpRefCacheEntry; - std::unique_ptr<GDIMetaFile> mpMtf; - std::unique_ptr<BitmapEx> mpBmpEx; - GraphicAttr maAttr; - Size maOutSizePix; - sal_uLong mnCacheSize; - DrawModeFlags mnOutDevDrawMode; - sal_uInt16 mnOutDevBitCount; - - static bool IsCacheableAsBitmap( const GDIMetaFile& rMtf, OutputDevice const * pOut, const Size& rSz ); - - // Copy assignment is forbidden and not implemented. - GraphicDisplayCacheEntry (const GraphicDisplayCacheEntry &) = delete; - GraphicDisplayCacheEntry & operator= (const GraphicDisplayCacheEntry &) = delete; - -public: - - static sal_uLong GetNeededSize( OutputDevice const * pOut, const Point& rPt, const Size& rSz, - const GraphicObject& rObj, const GraphicAttr& rAttr ); - -public: - - GraphicDisplayCacheEntry( const GraphicCacheEntry* pRefCacheEntry, - OutputDevice const * pOut, const Point& rPt, const Size& rSz, - const GraphicObject& rObj, const GraphicAttr& rAttr, - const BitmapEx& rBmpEx ) : - mpRefCacheEntry( pRefCacheEntry ), - mpBmpEx( new BitmapEx( rBmpEx ) ), - maAttr( rAttr ), maOutSizePix( pOut->LogicToPixel( rSz ) ), - mnCacheSize( GetNeededSize( pOut, rPt, rSz, rObj, rAttr ) ), - mnOutDevDrawMode( pOut->GetDrawMode() ), - mnOutDevBitCount( pOut->GetBitCount() ) - { - } - - GraphicDisplayCacheEntry( const GraphicCacheEntry* pRefCacheEntry, - OutputDevice const * pOut, const Point& rPt, const Size& rSz, - const GraphicObject& rObj, const GraphicAttr& rAttr, - const GDIMetaFile& rMtf ) : - mpRefCacheEntry( pRefCacheEntry ), - mpMtf( new GDIMetaFile( rMtf ) ), - maAttr( rAttr ), maOutSizePix( pOut->LogicToPixel( rSz ) ), - mnCacheSize( GetNeededSize( pOut, rPt, rSz, rObj, rAttr ) ), - mnOutDevDrawMode( pOut->GetDrawMode() ), - mnOutDevBitCount( pOut->GetBitCount() ) - { - } - - - sal_uLong GetCacheSize() const { return mnCacheSize; } - const GraphicCacheEntry* GetReferencedCacheEntry() const { return mpRefCacheEntry; } - - void SetReleaseTime( const ::salhelper::TTimeValue& rReleaseTime ) { maReleaseTime = rReleaseTime; } - const ::salhelper::TTimeValue& GetReleaseTime() const { return maReleaseTime; } - - bool Matches( OutputDevice const * pOut, const Point& /*rPtPixel*/, const Size& rSzPixel, - const GraphicCacheEntry* pCacheEntry, const GraphicAttr& rAttr ) const - { - // #i46805# Additional match - // criteria: outdev draw mode and - // bit count. One cannot reuse - // this cache object, if it's - // e.g. generated for - // DrawModeFlags::GrayBitmap. - return( ( pCacheEntry == mpRefCacheEntry ) && - ( maAttr == rAttr ) && - ( ( maOutSizePix == rSzPixel ) || ( !maOutSizePix.Width() && !maOutSizePix.Height() ) ) && - ( pOut->GetBitCount() == mnOutDevBitCount ) && - ( pOut->GetDrawMode() == mnOutDevDrawMode ) ); - } - - void Draw( OutputDevice* pOut, const Point& rPt, const Size& rSz ) const; -}; - -// This whole function is based on checkMetadataBitmap() from grfmgr2.cxx, see that one for details. -// If you do changes here, change the original function too. -static void checkMetadataBitmap( const BitmapEx& rBmpEx, - Point /*rSrcPoint*/, - Size rSrcSize, - const Point& rDestPoint, - const Size& rDestSize, - const Size& rRefSize, - bool& o_rbNonBitmapActionEncountered ) -{ - if( rSrcSize == Size()) - rSrcSize = rBmpEx.GetSizePixel(); - - if( rDestPoint != Point( 0, 0 )) - { - o_rbNonBitmapActionEncountered = true; - return; - } - if( rDestSize != rRefSize ) - { if( rBmpEx.GetSizePixel().Width() > 100 && rBmpEx.GetSizePixel().Height() > 100 - && std::abs( rDestSize.Width() - rRefSize.Width()) < 5 - && std::abs( rDestSize.Height() - rRefSize.Height()) < 5 ) - ; // ok, assume it's close enough - else - { // fall back to mtf rendering - o_rbNonBitmapActionEncountered = true; - return; - } - } -} - -// This function is based on GraphicManager::ImplCreateOutput(), in fact it mostly copies -// it, the difference is that this one does not create anything, it only checks if -// ImplCreateOutput() would use the optimization of using the single bitmap. -// If you do changes here, change the original function too. -bool GraphicDisplayCacheEntry::IsCacheableAsBitmap( const GDIMetaFile& rMtf, - OutputDevice const * pOut, const Size& rSz ) -{ - const Size aNewSize( rMtf.GetPrefSize() ); - GDIMetaFile rOutMtf = rMtf; - - // Count bitmap actions, and flag actions that paint, but - // are no bitmaps. - sal_Int32 nNumBitmaps(0); - bool bNonBitmapActionEncountered(false); - if( aNewSize.Width() && aNewSize.Height() && rSz.Width() && rSz.Height() ) - { - const MapMode& rPrefMapMode( rMtf.GetPrefMapMode() ); - const Size rSizePix( pOut->LogicToPixel( aNewSize, rPrefMapMode ) ); - - sal_uInt32 nCurPos; - MetaAction* pAct; - for( nCurPos = 0, pAct = rOutMtf.FirstAction(); pAct; - pAct = rOutMtf.NextAction(), nCurPos++ ) - { - switch( pAct->GetType() ) - { - case MetaActionType::FONT: - // FALLTHROUGH intended - case MetaActionType::NONE: - // FALLTHROUGH intended - - // OutDev state changes (which don't affect bitmap - // output) - case MetaActionType::LINECOLOR: - // FALLTHROUGH intended - case MetaActionType::FILLCOLOR: - // FALLTHROUGH intended - case MetaActionType::TEXTCOLOR: - // FALLTHROUGH intended - case MetaActionType::TEXTFILLCOLOR: - // FALLTHROUGH intended - case MetaActionType::TEXTALIGN: - // FALLTHROUGH intended - case MetaActionType::TEXTLINECOLOR: - // FALLTHROUGH intended - case MetaActionType::TEXTLINE: - // FALLTHROUGH intended - case MetaActionType::PUSH: - // FALLTHROUGH intended - case MetaActionType::POP: - // FALLTHROUGH intended - case MetaActionType::LAYOUTMODE: - // FALLTHROUGH intended - case MetaActionType::TEXTLANGUAGE: - // FALLTHROUGH intended - case MetaActionType::COMMENT: - break; - - // bitmap output methods - case MetaActionType::BMP: - if( !nNumBitmaps && !bNonBitmapActionEncountered ) - { - MetaBmpAction* pAction = static_cast<MetaBmpAction*>(pAct); - - checkMetadataBitmap( - BitmapEx( pAction->GetBitmap()), - Point(), Size(), - pOut->LogicToPixel( pAction->GetPoint(), - rPrefMapMode ), - pAction->GetBitmap().GetSizePixel(), - rSizePix, - bNonBitmapActionEncountered ); - } - ++nNumBitmaps; - break; - - case MetaActionType::BMPSCALE: - if( !nNumBitmaps && !bNonBitmapActionEncountered ) - { - MetaBmpScaleAction* pAction = static_cast<MetaBmpScaleAction*>(pAct); - - checkMetadataBitmap( - BitmapEx( pAction->GetBitmap()), - Point(), Size(), - pOut->LogicToPixel( pAction->GetPoint(), - rPrefMapMode ), - pOut->LogicToPixel( pAction->GetSize(), - rPrefMapMode ), - rSizePix, - bNonBitmapActionEncountered ); - } - ++nNumBitmaps; - break; - - case MetaActionType::BMPSCALEPART: - if( !nNumBitmaps && !bNonBitmapActionEncountered ) - { - MetaBmpScalePartAction* pAction = static_cast<MetaBmpScalePartAction*>(pAct); - - checkMetadataBitmap( BitmapEx( pAction->GetBitmap() ), - pAction->GetSrcPoint(), - pAction->GetSrcSize(), - pOut->LogicToPixel( pAction->GetDestPoint(), - rPrefMapMode ), - pOut->LogicToPixel( pAction->GetDestSize(), - rPrefMapMode ), - rSizePix, - bNonBitmapActionEncountered ); - } - ++nNumBitmaps; - break; - - case MetaActionType::BMPEX: - if( !nNumBitmaps && !bNonBitmapActionEncountered ) - { - MetaBmpExAction* pAction = static_cast<MetaBmpExAction*>(pAct); - - checkMetadataBitmap( - pAction->GetBitmapEx(), - Point(), Size(), - pOut->LogicToPixel( pAction->GetPoint(), - rPrefMapMode ), - pAction->GetBitmapEx().GetSizePixel(), - rSizePix, - bNonBitmapActionEncountered ); - } - ++nNumBitmaps; - break; - - case MetaActionType::BMPEXSCALE: - if( !nNumBitmaps && !bNonBitmapActionEncountered ) - { - MetaBmpExScaleAction* pAction = static_cast<MetaBmpExScaleAction*>(pAct); - - checkMetadataBitmap( - pAction->GetBitmapEx(), - Point(), Size(), - pOut->LogicToPixel( pAction->GetPoint(), - rPrefMapMode ), - pOut->LogicToPixel( pAction->GetSize(), - rPrefMapMode ), - rSizePix, - bNonBitmapActionEncountered ); - } - ++nNumBitmaps; - break; - - case MetaActionType::BMPEXSCALEPART: - if( !nNumBitmaps && !bNonBitmapActionEncountered ) - { - MetaBmpExScalePartAction* pAction = static_cast<MetaBmpExScalePartAction*>(pAct); - - checkMetadataBitmap( pAction->GetBitmapEx(), - pAction->GetSrcPoint(), - pAction->GetSrcSize(), - pOut->LogicToPixel( pAction->GetDestPoint(), - rPrefMapMode ), - pOut->LogicToPixel( pAction->GetDestSize(), - rPrefMapMode ), - rSizePix, - bNonBitmapActionEncountered ); - } - ++nNumBitmaps; - break; - - // these actions actually output something (that's - // different from a bitmap) - case MetaActionType::RASTEROP: - if( static_cast<MetaRasterOpAction*>(pAct)->GetRasterOp() == RasterOp::OverPaint ) - break; - SAL_FALLTHROUGH; - case MetaActionType::PIXEL: - SAL_FALLTHROUGH; - case MetaActionType::POINT: - SAL_FALLTHROUGH; - case MetaActionType::LINE: - SAL_FALLTHROUGH; - case MetaActionType::RECT: - SAL_FALLTHROUGH; - case MetaActionType::ROUNDRECT: - SAL_FALLTHROUGH; - case MetaActionType::ELLIPSE: - SAL_FALLTHROUGH; - case MetaActionType::ARC: - SAL_FALLTHROUGH; - case MetaActionType::PIE: - SAL_FALLTHROUGH; - case MetaActionType::CHORD: - SAL_FALLTHROUGH; - case MetaActionType::POLYLINE: - SAL_FALLTHROUGH; - case MetaActionType::POLYGON: - SAL_FALLTHROUGH; - case MetaActionType::POLYPOLYGON: - SAL_FALLTHROUGH; - - case MetaActionType::TEXT: - SAL_FALLTHROUGH; - case MetaActionType::TEXTARRAY: - SAL_FALLTHROUGH; - case MetaActionType::STRETCHTEXT: - SAL_FALLTHROUGH; - case MetaActionType::TEXTRECT: - SAL_FALLTHROUGH; - - case MetaActionType::MASK: - SAL_FALLTHROUGH; - case MetaActionType::MASKSCALE: - SAL_FALLTHROUGH; - case MetaActionType::MASKSCALEPART: - SAL_FALLTHROUGH; - - case MetaActionType::GRADIENT: - SAL_FALLTHROUGH; - case MetaActionType::HATCH: - SAL_FALLTHROUGH; - case MetaActionType::WALLPAPER: - SAL_FALLTHROUGH; - - case MetaActionType::Transparent: - SAL_FALLTHROUGH; - case MetaActionType::EPS: - SAL_FALLTHROUGH; - case MetaActionType::FLOATTRANSPARENT: - SAL_FALLTHROUGH; - case MetaActionType::GRADIENTEX: - SAL_FALLTHROUGH; - - // OutDev state changes that _do_ affect bitmap - // output - case MetaActionType::CLIPREGION: - SAL_FALLTHROUGH; - case MetaActionType::ISECTRECTCLIPREGION: - SAL_FALLTHROUGH; - case MetaActionType::ISECTREGIONCLIPREGION: - SAL_FALLTHROUGH; - case MetaActionType::MOVECLIPREGION: - SAL_FALLTHROUGH; - - case MetaActionType::MAPMODE: - SAL_FALLTHROUGH; - case MetaActionType::REFPOINT: - SAL_FALLTHROUGH; - default: - bNonBitmapActionEncountered = true; - break; - } - } - } - return nNumBitmaps == 1 && !bNonBitmapActionEncountered; -} - -sal_uLong GraphicDisplayCacheEntry::GetNeededSize( OutputDevice const * pOut, const Point& /*rPt*/, const Size& rSz, - const GraphicObject& rObj, const GraphicAttr& rAttr ) -{ - const Graphic& rGraphic = rObj.GetGraphic(); - const GraphicType eType = rGraphic.GetType(); - - bool canCacheAsBitmap = false; - if( GraphicType::Bitmap == eType ) - canCacheAsBitmap = true; - else if( GraphicType::GdiMetafile == eType ) - canCacheAsBitmap = IsCacheableAsBitmap( rGraphic.GetGDIMetaFile(), pOut, rSz ); - else - return 0; - if( canCacheAsBitmap ) - { - const Size aOutSizePix( pOut->LogicToPixel( rSz ) ); - const long nBitCount = pOut->GetBitCount(); - - if( ( aOutSizePix.Width() > MAX_BMP_EXTENT ) || - ( aOutSizePix.Height() > MAX_BMP_EXTENT ) ) - { - return ULONG_MAX; - } - else if( nBitCount ) - { - sal_uLong nNeededSize = aOutSizePix.Width() * aOutSizePix.Height() * nBitCount / 8; - if( rObj.IsTransparent() || ( rAttr.GetRotation() % 3600 ) ) - nNeededSize += nNeededSize / nBitCount; - return nNeededSize; - } - else - { - OSL_FAIL( "GraphicDisplayCacheEntry::GetNeededSize(): pOut->GetBitCount() == 0" ); - return 256000; - } - } - else - return rGraphic.GetSizeBytes(); -} - -void GraphicDisplayCacheEntry::Draw( OutputDevice* pOut, const Point& rPt, const Size& rSz ) const -{ - if( mpMtf ) - GraphicManager::ImplDraw( pOut, rPt, rSz, *mpMtf, maAttr ); - else if( mpBmpEx ) - { - if( maAttr.IsRotated() ) - { - tools::Polygon aPoly( tools::Rectangle( rPt, rSz ) ); - - aPoly.Rotate( rPt, maAttr.GetRotation() % 3600 ); - const tools::Rectangle aRotBoundRect( aPoly.GetBoundRect() ); - pOut->DrawBitmapEx( aRotBoundRect.TopLeft(), aRotBoundRect.GetSize(), *mpBmpEx ); - } - else - pOut->DrawBitmapEx( rPt, rSz, *mpBmpEx ); - } -} - -GraphicCache::GraphicCache( sal_uLong nDisplayCacheSize, sal_uLong nMaxObjDisplayCacheSize ) : - maReleaseTimer ( "svtools::GraphicCache maReleaseTimer" ), - mnReleaseTimeoutSeconds ( 0 ), - mnMaxDisplaySize ( nDisplayCacheSize ), - mnMaxObjDisplaySize ( nMaxObjDisplayCacheSize ), - mnUsedDisplaySize ( 0 ) -{ - maReleaseTimer.SetInvokeHandler( LINK( this, GraphicCache, ReleaseTimeoutHdl ) ); - maReleaseTimer.SetTimeout( 10000 ); - maReleaseTimer.SetDebugName( "svtools::GraphicCache maReleaseTimer" ); - maReleaseTimer.Start(); -} - -GraphicCache::~GraphicCache() -{ - DBG_ASSERT( !maGraphicCache.size(), "GraphicCache::~GraphicCache(): there are some GraphicObjects in cache" ); - DBG_ASSERT( maDisplayCache.empty(), "GraphicCache::~GraphicCache(): there are some GraphicObjects in display cache" ); -} - -void GraphicCache::AddGraphicObject( - const GraphicObject& rObj, - Graphic& rSubstitute, - const OString* pID, - const GraphicObject* pCopyObj -) -{ - bool bInserted = false; - - if( !rObj.IsSwappedOut() - && ( pID - || ( pCopyObj - && ( pCopyObj->GetType() != GraphicType::NONE ) - ) - || ( rObj.GetType() != GraphicType::NONE ) - ) - ) - { - if( pCopyObj - && !maGraphicCache.empty() - ) - { - for (auto const& elem : maGraphicCache) - { - if( elem->HasGraphicObjectReference( *pCopyObj ) ) - { - elem->AddGraphicObjectReference( rObj, rSubstitute ); - bInserted = true; - break; - } - } - } - - if( !bInserted ) - { - std::unique_ptr< GraphicID > apID; - - if( !pID ) - { - apID.reset( new GraphicID( rObj ) ); - } - - for (auto const& elem : maGraphicCache) - { - const GraphicID& rEntryID = elem->GetID(); - - if( pID ) - { - if( rEntryID.GetIDString() == *pID ) - { - elem->TryToSwapIn(); - - // since pEntry->TryToSwapIn can modify our current list, we have to - // iterate from beginning to add a reference to the appropriate - // CacheEntry object; after this, quickly jump out of the outer iteration - for (auto const& subelem : maGraphicCache) - { - const GraphicID& rID = subelem->GetID(); - - if( rID.GetIDString() == *pID ) - { - subelem->AddGraphicObjectReference( rObj, rSubstitute ); - bInserted = true; - break; - } - } - - if( !bInserted ) - { - maGraphicCache.push_back( new GraphicCacheEntry( rObj ) ); - bInserted = true; - } - } - } - else - { - if( rEntryID == *apID ) - { - elem->AddGraphicObjectReference( rObj, rSubstitute ); - bInserted = true; - } - } - - if(bInserted) - break; - } - } - } - - if( !bInserted ) - maGraphicCache.push_back( new GraphicCacheEntry( rObj ) ); -} - -void GraphicCache::ReleaseGraphicObject( const GraphicObject& rObj ) -{ - // Release cached object - bool bRemoved = false; - GraphicCacheEntryVector::iterator it = maGraphicCache.begin(); - while (!bRemoved && it != maGraphicCache.end()) - { - bRemoved = (*it)->ReleaseGraphicObjectReference( rObj ); - - if( bRemoved && (0 == (*it)->GetGraphicObjectReferenceCount()) ) - { - // if graphic cache entry has no more references, - // the corresponding display cache object can be removed - GraphicDisplayCacheEntryVector::iterator it2 = maDisplayCache.begin(); - while( it2 != maDisplayCache.end() ) - { - GraphicDisplayCacheEntry* pDisplayEntry = *it2; - if( pDisplayEntry->GetReferencedCacheEntry() == *it ) - { - mnUsedDisplaySize -= pDisplayEntry->GetCacheSize(); - it2 = maDisplayCache.erase( it2 ); - delete pDisplayEntry; - } - else - ++it2; - } - - // delete graphic cache entry - delete *it; - it = maGraphicCache.erase( it ); - } - else - ++it; - } - - DBG_ASSERT( bRemoved, "GraphicCache::ReleaseGraphicObject(...): GraphicObject not found in cache" ); -} - -void GraphicCache::GraphicObjectWasSwappedOut( const GraphicObject& rObj ) -{ - // notify cache that rObj is swapped out (and can thus be pruned - // from the cache) - GraphicCacheEntry* pEntry = ImplGetCacheEntry( rObj ); - - if( pEntry ) - pEntry->GraphicObjectWasSwappedOut(); -} - -void GraphicCache::GraphicObjectWasSwappedIn( const GraphicObject& rObj ) -{ - GraphicCacheEntry* pEntry = ImplGetCacheEntry( rObj ); - - if( pEntry ) - { - if( pEntry->GetID().IsEmpty() ) - { - ReleaseGraphicObject( rObj ); - AddGraphicObject( rObj, const_cast<Graphic&>(rObj.GetGraphic()), nullptr, nullptr ); - } - else - pEntry->GraphicObjectWasSwappedIn( rObj ); - } -} - -void GraphicCache::SetMaxDisplayCacheSize( sal_uLong nNewCacheSize ) -{ - mnMaxDisplaySize = nNewCacheSize; - - if( GetMaxDisplayCacheSize() < GetUsedDisplayCacheSize() ) - ImplFreeDisplayCacheSpace( GetUsedDisplayCacheSize() - GetMaxDisplayCacheSize() ); -} - -void GraphicCache::SetCacheTimeout( sal_uLong nTimeoutSeconds ) -{ - if( mnReleaseTimeoutSeconds == nTimeoutSeconds ) - return; - - ::salhelper::TTimeValue aReleaseTime; - - if( ( mnReleaseTimeoutSeconds = nTimeoutSeconds ) != 0 ) - { - osl_getSystemTime( &aReleaseTime ); - aReleaseTime.addTime( ::salhelper::TTimeValue( nTimeoutSeconds, 0 ) ); - } - - for (auto const& elem : maDisplayCache) - { - elem->SetReleaseTime( aReleaseTime ); - } -} - -bool GraphicCache::IsDisplayCacheable( OutputDevice const * pOut, const Point& rPt, const Size& rSz, - const GraphicObject& rObj, const GraphicAttr& rAttr ) const -{ - return( GraphicDisplayCacheEntry::GetNeededSize( pOut, rPt, rSz, rObj, rAttr ) <= - GetMaxObjDisplayCacheSize() ); -} - -bool GraphicCache::IsInDisplayCache( OutputDevice const * pOut, const Point& rPt, const Size& rSz, - const GraphicObject& rObj, const GraphicAttr& rAttr ) const -{ - const Point aPtPixel( pOut->LogicToPixel( rPt ) ); - const Size aSzPixel( pOut->LogicToPixel( rSz ) ); - const GraphicCacheEntry* pCacheEntry = const_cast<GraphicCache*>(this)->ImplGetCacheEntry( rObj ); - bool bFound = false; - - if( pCacheEntry ) - { - for (auto const& elem : maDisplayCache) - { - if( elem->Matches( pOut, aPtPixel, aSzPixel, pCacheEntry, rAttr ) ) - { - bFound = true; - break; - } - } - } - - return bFound; -} - -OString GraphicCache::GetUniqueID( const GraphicObject& rObj ) const -{ - OString aRet; - GraphicCacheEntry* pEntry = const_cast<GraphicCache*>(this)->ImplGetCacheEntry( rObj ); - - // ensure that the entry is correctly initialized (it has to be read at least once) - if( pEntry && pEntry->GetID().IsEmpty() ) - { - pEntry->TryToSwapIn(); - // do another call to ImplGetCacheEntry in case of modified entry list - pEntry = const_cast<GraphicCache*>(this)->ImplGetCacheEntry( rObj ); - } - - if( pEntry ) - aRet = pEntry->GetID().GetIDString(); - - return aRet; -} - -bool GraphicCache::CreateDisplayCacheObj( OutputDevice const * pOut, const Point& rPt, const Size& rSz, - const GraphicObject& rObj, const GraphicAttr& rAttr, - const BitmapEx& rBmpEx ) -{ - const sal_uLong nNeededSize = GraphicDisplayCacheEntry::GetNeededSize( pOut, rPt, rSz, rObj, rAttr ); - bool bRet = false; - - if( nNeededSize <= GetMaxObjDisplayCacheSize() ) - { - if( nNeededSize > GetFreeDisplayCacheSize() ) - ImplFreeDisplayCacheSpace( nNeededSize - GetFreeDisplayCacheSize() ); - - GraphicDisplayCacheEntry* pNewEntry = new GraphicDisplayCacheEntry( ImplGetCacheEntry( rObj ), - pOut, rPt, rSz, rObj, rAttr, rBmpEx ); - - if( GetCacheTimeout() ) - { - ::salhelper::TTimeValue aReleaseTime; - - osl_getSystemTime( &aReleaseTime ); - aReleaseTime.addTime( ::salhelper::TTimeValue( GetCacheTimeout(), 0 ) ); - pNewEntry->SetReleaseTime( aReleaseTime ); - } - - maDisplayCache.push_back( pNewEntry ); - mnUsedDisplaySize += pNewEntry->GetCacheSize(); - bRet = true; - } - - return bRet; -} - -bool GraphicCache::CreateDisplayCacheObj( OutputDevice const * pOut, const Point& rPt, const Size& rSz, - const GraphicObject& rObj, const GraphicAttr& rAttr, - const GDIMetaFile& rMtf ) -{ - const sal_uLong nNeededSize = GraphicDisplayCacheEntry::GetNeededSize( pOut, rPt, rSz, rObj, rAttr ); - bool bRet = false; - - if( nNeededSize <= GetMaxObjDisplayCacheSize() ) - { - if( nNeededSize > GetFreeDisplayCacheSize() ) - ImplFreeDisplayCacheSpace( nNeededSize - GetFreeDisplayCacheSize() ); - - GraphicDisplayCacheEntry* pNewEntry = new GraphicDisplayCacheEntry( ImplGetCacheEntry( rObj ), - pOut, rPt, rSz, rObj, rAttr, rMtf ); - - if( GetCacheTimeout() ) - { - ::salhelper::TTimeValue aReleaseTime; - - osl_getSystemTime( &aReleaseTime ); - aReleaseTime.addTime( ::salhelper::TTimeValue( GetCacheTimeout(), 0 ) ); - pNewEntry->SetReleaseTime( aReleaseTime ); - } - - maDisplayCache.push_back( pNewEntry ); - mnUsedDisplaySize += pNewEntry->GetCacheSize(); - bRet = true; - } - - return bRet; -} - -bool GraphicCache::DrawDisplayCacheObj( OutputDevice* pOut, const Point& rPt, const Size& rSz, - const GraphicObject& rObj, const GraphicAttr& rAttr ) -{ - const Point aPtPixel( pOut->LogicToPixel( rPt ) ); - const Size aSzPixel( pOut->LogicToPixel( rSz ) ); - const GraphicCacheEntry* pCacheEntry = ImplGetCacheEntry( rObj ); - GraphicDisplayCacheEntry* pDisplayCacheEntry = nullptr; - GraphicDisplayCacheEntryVector::iterator it = maDisplayCache.begin(); - bool bRet = false; - - while( !bRet && it != maDisplayCache.end() ) - { - pDisplayCacheEntry = *it; - if( pDisplayCacheEntry->Matches( pOut, aPtPixel, aSzPixel, pCacheEntry, rAttr ) ) - { - ::salhelper::TTimeValue aReleaseTime; - - // put found object at last used position - it = maDisplayCache.erase( it ); - maDisplayCache.push_back( pDisplayCacheEntry ); - - if( GetCacheTimeout() ) - { - osl_getSystemTime( &aReleaseTime ); - aReleaseTime.addTime( ::salhelper::TTimeValue( GetCacheTimeout(), 0 ) ); - } - - pDisplayCacheEntry->SetReleaseTime( aReleaseTime ); - bRet = true; - } - else - ++it; - } - - if( bRet ) - pDisplayCacheEntry->Draw( pOut, rPt, rSz ); - - return bRet; -} - -bool GraphicCache::ImplFreeDisplayCacheSpace( sal_uLong nSizeToFree ) -{ - sal_uLong nFreedSize = 0; - - if( nSizeToFree ) - { - GraphicDisplayCacheEntryVector::iterator it = maDisplayCache.begin(); - - if( nSizeToFree > mnUsedDisplaySize ) - nSizeToFree = mnUsedDisplaySize; - - while( it != maDisplayCache.end() ) - { - GraphicDisplayCacheEntry* pCacheObj = *it; - - nFreedSize += pCacheObj->GetCacheSize(); - mnUsedDisplaySize -= pCacheObj->GetCacheSize(); - it = maDisplayCache.erase( it ); - delete pCacheObj; - - if( nFreedSize >= nSizeToFree ) - break; - } - } - - return( nFreedSize >= nSizeToFree ); -} - -GraphicCacheEntry* GraphicCache::ImplGetCacheEntry( const GraphicObject& rObj ) -{ - GraphicCacheEntry* pRet = nullptr; - - for (auto const& elem : maGraphicCache) - { - if( elem->HasGraphicObjectReference( rObj ) ) - { - return elem; - } - } - - return pRet; -} - -IMPL_LINK( GraphicCache, ReleaseTimeoutHdl, Timer*, pTimer, void ) -{ - pTimer->Stop(); - - ::salhelper::TTimeValue aCurTime; - GraphicDisplayCacheEntryVector::iterator it = maDisplayCache.begin(); - - osl_getSystemTime( &aCurTime ); - - while( it != maDisplayCache.end() ) - { - GraphicDisplayCacheEntry* pDisplayEntry = *it; - const ::salhelper::TTimeValue& rReleaseTime = pDisplayEntry->GetReleaseTime(); - - if( !rReleaseTime.isEmpty() && ( rReleaseTime < aCurTime ) ) - { - mnUsedDisplaySize -= pDisplayEntry->GetCacheSize(); - it = maDisplayCache.erase( it ); - delete pDisplayEntry; - } - else - ++it; - } - - pTimer->Start(); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/graphic/grfcache.hxx b/vcl/source/graphic/grfcache.hxx deleted file mode 100644 index 7eec013ce521..000000000000 --- a/vcl/source/graphic/grfcache.hxx +++ /dev/null @@ -1,136 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_SOURCE_GRAPHIC_GRFCACHE_HXX -#define INCLUDED_VCL_SOURCE_GRAPHIC_GRFCACHE_HXX - -#include <vcl/graph.hxx> -#include <vcl/timer.hxx> -#include <vector> - - -class GraphicAttr; -class GraphicCacheEntry; -class GraphicDisplayCacheEntry; -class GraphicObject; - -class GraphicCache -{ -private: - typedef std::vector< GraphicCacheEntry* > GraphicCacheEntryVector; - typedef std::vector< GraphicDisplayCacheEntry* > GraphicDisplayCacheEntryVector; - - Timer maReleaseTimer; - GraphicCacheEntryVector maGraphicCache; - GraphicDisplayCacheEntryVector maDisplayCache; - sal_uLong mnReleaseTimeoutSeconds; - sal_uLong mnMaxDisplaySize; - sal_uLong mnMaxObjDisplaySize; - sal_uLong mnUsedDisplaySize; - - bool ImplFreeDisplayCacheSpace( sal_uLong nSizeToFree ); - GraphicCacheEntry* ImplGetCacheEntry( const GraphicObject& rObj ); - - - DECL_LINK( ReleaseTimeoutHdl, Timer*, void ); - -public: - - GraphicCache( - sal_uLong nDisplayCacheSize, - sal_uLong nMaxObjDisplayCacheSize - ); - - ~GraphicCache(); - -public: - - void AddGraphicObject( - const GraphicObject& rObj, - Graphic& rSubstitute, - const OString* pID, - const GraphicObject* pCopyObj - ); - - void ReleaseGraphicObject( const GraphicObject& rObj ); - - void GraphicObjectWasSwappedOut( const GraphicObject& rObj ); - void GraphicObjectWasSwappedIn( const GraphicObject& rObj ); - - OString GetUniqueID( const GraphicObject& rObj ) const; - -public: - - void SetMaxDisplayCacheSize( sal_uLong nNewCacheSize ); - sal_uLong GetMaxDisplayCacheSize() const { return mnMaxDisplaySize; }; - - sal_uLong GetMaxObjDisplayCacheSize() const { return mnMaxObjDisplaySize; } - - sal_uLong GetUsedDisplayCacheSize() const { return mnUsedDisplaySize; } - sal_uLong GetFreeDisplayCacheSize() const { return( mnMaxDisplaySize - mnUsedDisplaySize ); } - - void SetCacheTimeout( sal_uLong nTimeoutSeconds ); - sal_uLong GetCacheTimeout() const { return mnReleaseTimeoutSeconds; } - - bool IsDisplayCacheable( - OutputDevice const * pOut, - const Point& rPt, - const Size& rSz, - const GraphicObject& rObj, - const GraphicAttr& rAttr - ) const; - - bool IsInDisplayCache( - OutputDevice const * pOut, - const Point& rPt, - const Size& rSz, - const GraphicObject& rObj, - const GraphicAttr& rAttr - ) const; - - bool CreateDisplayCacheObj( - OutputDevice const * pOut, - const Point& rPt, - const Size& rSz, - const GraphicObject& rObj, - const GraphicAttr& rAttr, - const BitmapEx& rBmpEx - ); - - bool CreateDisplayCacheObj( - OutputDevice const * pOut, - const Point& rPt, - const Size& rSz, - const GraphicObject& rObj, - const GraphicAttr& rAttr, - const GDIMetaFile& rMtf - ); - - bool DrawDisplayCacheObj( - OutputDevice* pOut, - const Point& rPt, - const Size& rSz, - const GraphicObject& rObj, - const GraphicAttr& rAttr - ); -}; - -#endif // INCLUDED_VCL_SOURCE_GRAPHIC_GRFCACHE_HXX - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |