diff options
Diffstat (limited to 'svtools/source/graphic/grfcache.cxx')
-rw-r--r-- | svtools/source/graphic/grfcache.cxx | 1221 |
1 files changed, 0 insertions, 1221 deletions
diff --git a/svtools/source/graphic/grfcache.cxx b/svtools/source/graphic/grfcache.cxx deleted file mode 100644 index 430c2318888b..000000000000 --- a/svtools/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 <svtools/grfmgr.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: */ |