diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2016-05-24 08:56:15 +0200 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2016-05-24 10:12:17 +0200 |
commit | 2c8e66129f14c6d0b9174d27546e233b3995d8d4 (patch) | |
tree | a9c64f91b5d6e0fcc2c6696a3a9367d919b5d736 | |
parent | 3c91b8d80bb95eae05b095a3ee9ea8d664adce64 (diff) |
Revert "Simplify GfxLink using std::shared_ptr to clarify ownership"
This reverts commit d64431ac5a7bede7661c64e0bd6d46805841e704, which caused ASan
to complain about "alloc-dealloc-mismatch (operator new [] vs operator delete)"
(while e.g. building Gallery_arrows), as GfxLink::mpSwpInData is a
std::shared_ptr<sal_uInt8> holding a pointer to an array of sal_uInt8.
-rw-r--r-- | include/vcl/gfxlink.hxx | 98 | ||||
-rw-r--r-- | vcl/source/gdi/gfxlink.cxx | 225 |
2 files changed, 228 insertions, 95 deletions
diff --git a/include/vcl/gfxlink.hxx b/include/vcl/gfxlink.hxx index aa0e8fea37a2..3bdb4b79595a 100644 --- a/include/vcl/gfxlink.hxx +++ b/include/vcl/gfxlink.hxx @@ -25,10 +25,56 @@ #include <tools/solar.h> #include <vcl/dllapi.h> #include <vcl/mapmod.hxx> -#include <memory> class SvStream; + +struct ImpBuffer +{ + sal_uLong mnRefCount; + sal_uInt8* mpBuffer; + + ImpBuffer( sal_uInt8* pBuf ) { mnRefCount = 1UL; mpBuffer = pBuf; } + + ~ImpBuffer() { delete[] mpBuffer; } +}; + + +struct ImpSwap +{ + OUString maURL; + sal_uLong mnDataSize; + sal_uLong mnRefCount; + + ImpSwap( sal_uInt8* pData, sal_uLong nDataSize ); + ~ImpSwap(); + + sal_uInt8* GetData() const; + + bool IsSwapped() const { return maURL.getLength() > 0; } + + void WriteTo( SvStream& rOStm ) const; +}; + + +struct ImpGfxLink +{ + MapMode maPrefMapMode; + Size maPrefSize; + bool mbPrefMapModeValid; + bool mbPrefSizeValid; + + ImpGfxLink() : + maPrefMapMode(), + maPrefSize(), + mbPrefMapModeValid( false ), + mbPrefSizeValid( false ) + {} +}; + +//#endif // __PRIVATE + + enum GfxLinkType { GFX_LINK_TYPE_NONE = 0, @@ -42,6 +88,7 @@ enum GfxLinkType GFX_LINK_TYPE_NATIVE_PCT = 8, // Don't forget to update the following defines GFX_LINK_TYPE_NATIVE_SVG = 9, // Don't forget to update the following defines GFX_LINK_TYPE_NATIVE_MOV = 10, // Don't forget to update the following defines + // #i15508# added BMP type support GFX_LINK_TYPE_NATIVE_BMP = 11, // Don't forget to update the following defines GFX_LINK_TYPE_USER = 0xffff }; @@ -49,58 +96,49 @@ enum GfxLinkType #define GFX_LINK_FIRST_NATIVE_ID GFX_LINK_TYPE_NATIVE_GIF #define GFX_LINK_LAST_NATIVE_ID GFX_LINK_TYPE_NATIVE_BMP + +struct ImpBuffer; +struct ImpSwap; +struct ImpGfxLink; class Graphic; class VCL_DLLPUBLIC GfxLink { private: - struct SwapOutData - { - SwapOutData(const OUString &aURL); - ~SwapOutData(); + GfxLinkType meType; + ImpBuffer* mpBuf; + ImpSwap* mpSwap; + sal_uInt32 mnBufSize; + sal_uInt32 mnUserId; + ImpGfxLink* mpImpData; - OUString maURL; // File is removed in the destructor + SAL_DLLPRIVATE void ImplCopy( const GfxLink& rGfxLink ); - }; - - GfxLinkType meType = GFX_LINK_TYPE_NONE; - sal_uInt32 mnUserId = 0; - - std::shared_ptr<sal_uInt8> mpSwapInData; - std::shared_ptr<SwapOutData> mpSwapOutData; - - sal_uInt32 mnSwapInDataSize = 0; - MapMode maPrefMapMode; - Size maPrefSize; - bool mbPrefMapModeValid = false; - bool mbPrefSizeValid = false; - - SAL_DLLPRIVATE std::shared_ptr<sal_uInt8> GetSwapInData() const; public: GfxLink(); - - // pBuff = The Graphic data. This class takes ownership of this + GfxLink( const GfxLink& ); GfxLink( sal_uInt8* pBuf, sal_uInt32 nBufSize, GfxLinkType nType ); ~GfxLink(); - bool IsEqual( const GfxLink& ) const; + GfxLink& operator=( const GfxLink& ); + bool IsEqual( const GfxLink& ) const; GfxLinkType GetType() const { return meType;} void SetUserId( sal_uInt32 nUserId ) { mnUserId = nUserId; } sal_uInt32 GetUserId() const { return mnUserId; } - sal_uInt32 GetDataSize() const { return mnSwapInDataSize;} + sal_uInt32 GetDataSize() const { return mnBufSize;} const sal_uInt8* GetData() const; - const Size& GetPrefSize() const { return maPrefSize;} + const Size& GetPrefSize() const { return mpImpData->maPrefSize;} void SetPrefSize( const Size& rPrefSize ); - bool IsPrefSizeValid() { return mbPrefSizeValid;} + bool IsPrefSizeValid() { return mpImpData->mbPrefSizeValid;} - const MapMode& GetPrefMapMode() const { return maPrefMapMode;} + const MapMode& GetPrefMapMode() const { return mpImpData->maPrefMapMode;} void SetPrefMapMode( const MapMode& rPrefMapMode ); - bool IsPrefMapModeValid() { return mbPrefMapModeValid;} + bool IsPrefMapModeValid() { return mpImpData->mbPrefMapModeValid;} bool IsNative() const; @@ -110,7 +148,7 @@ public: void SwapOut(); void SwapIn(); - bool IsSwappedOut() const { return( bool(mpSwapOutData) ); } + bool IsSwappedOut() const { return( mpSwap != nullptr ); } public: diff --git a/vcl/source/gdi/gfxlink.cxx b/vcl/source/gdi/gfxlink.cxx index 5b87fb3b1cac..266c8a46681d 100644 --- a/vcl/source/gdi/gfxlink.cxx +++ b/vcl/source/gdi/gfxlink.cxx @@ -30,29 +30,67 @@ #include <com/sun/star/ucb/CommandAbortedException.hpp> #include <memory> -GfxLink::GfxLink() +GfxLink::GfxLink() : + meType ( GFX_LINK_TYPE_NONE ), + mpBuf ( nullptr ), + mpSwap ( nullptr ), + mnBufSize ( 0 ), + mnUserId ( 0UL ), + mpImpData ( new ImpGfxLink ) { } -GfxLink::GfxLink( sal_uInt8* pBuf, sal_uInt32 nSize, GfxLinkType nType ) +GfxLink::GfxLink( const GfxLink& rGfxLink ) : + mpImpData( new ImpGfxLink ) +{ + ImplCopy( rGfxLink ); +} + +GfxLink::GfxLink( sal_uInt8* pBuf, sal_uInt32 nSize, GfxLinkType nType ) : + mpImpData( new ImpGfxLink ) { DBG_ASSERT( pBuf != nullptr && nSize, "GfxLink::GfxLink(): empty/NULL buffer given" ); meType = nType; - mnSwapInDataSize = nSize; - mpSwapInData = std::shared_ptr<sal_uInt8>(pBuf); + mnBufSize = nSize; + mpSwap = nullptr; + mnUserId = 0UL; + mpBuf = new ImpBuffer( pBuf ); } GfxLink::~GfxLink() { + if( mpBuf && !( --mpBuf->mnRefCount ) ) + delete mpBuf; + + if( mpSwap && !( --mpSwap->mnRefCount ) ) + delete mpSwap; + + delete mpImpData; +} + +GfxLink& GfxLink::operator=( const GfxLink& rGfxLink ) +{ + if( &rGfxLink != this ) + { + if ( mpBuf && !( --mpBuf->mnRefCount ) ) + delete mpBuf; + + if( mpSwap && !( --mpSwap->mnRefCount ) ) + delete mpSwap; + + ImplCopy( rGfxLink ); + } + + return *this; } bool GfxLink::IsEqual( const GfxLink& rGfxLink ) const { bool bIsEqual = false; - if ( ( mnSwapInDataSize == rGfxLink.mnSwapInDataSize ) && ( meType == rGfxLink.meType ) ) + if ( ( mnBufSize == rGfxLink.mnBufSize ) && ( meType == rGfxLink.meType ) ) { const sal_uInt8* pSource = GetData(); const sal_uInt8* pDest = rGfxLink.GetData(); @@ -68,6 +106,22 @@ bool GfxLink::IsEqual( const GfxLink& rGfxLink ) const return bIsEqual; } +void GfxLink::ImplCopy( const GfxLink& rGfxLink ) +{ + mnBufSize = rGfxLink.mnBufSize; + meType = rGfxLink.meType; + mpBuf = rGfxLink.mpBuf; + mpSwap = rGfxLink.mpSwap; + mnUserId = rGfxLink.mnUserId; + *mpImpData = *rGfxLink.mpImpData; + + if( mpBuf ) + mpBuf->mnRefCount++; + + if( mpSwap ) + mpSwap->mnRefCount++; +} + bool GfxLink::IsNative() const { @@ -80,21 +134,21 @@ const sal_uInt8* GfxLink::GetData() const if( IsSwappedOut() ) const_cast<GfxLink*>(this)->SwapIn(); - return( mpSwapInData.get() ); + return( mpBuf ? mpBuf->mpBuffer : nullptr ); } void GfxLink::SetPrefSize( const Size& rPrefSize ) { - maPrefSize = rPrefSize; - mbPrefSizeValid = true; + mpImpData->maPrefSize = rPrefSize; + mpImpData->mbPrefSizeValid = true; } void GfxLink::SetPrefMapMode( const MapMode& rPrefMapMode ) { - maPrefMapMode = rPrefMapMode; - mbPrefMapModeValid = true; + mpImpData->maPrefMapMode = rPrefMapMode; + mpImpData->mbPrefMapModeValid = true; } @@ -102,7 +156,7 @@ bool GfxLink::LoadNative( Graphic& rGraphic ) { bool bRet = false; - if( IsNative() && mnSwapInDataSize ) + if( IsNative() && mnBufSize ) { const sal_uInt8* pData = GetData(); @@ -111,12 +165,15 @@ bool GfxLink::LoadNative( Graphic& rGraphic ) SvMemoryStream aMemStm; ConvertDataFormat nCvtType; - aMemStm.SetBuffer( const_cast<sal_uInt8*>(pData), mnSwapInDataSize, mnSwapInDataSize ); + aMemStm.SetBuffer( const_cast<sal_uInt8*>(pData), mnBufSize, mnBufSize ); switch( meType ) { case GFX_LINK_TYPE_NATIVE_GIF: nCvtType = ConvertDataFormat::GIF; break; + + // #i15508# added BMP type for better exports (reload when swapped - checked, works) case GFX_LINK_TYPE_NATIVE_BMP: nCvtType = ConvertDataFormat::BMP; break; + case GFX_LINK_TYPE_NATIVE_JPG: nCvtType = ConvertDataFormat::JPG; break; case GFX_LINK_TYPE_NATIVE_PNG: nCvtType = ConvertDataFormat::PNG; break; case GFX_LINK_TYPE_NATIVE_TIF: nCvtType = ConvertDataFormat::TIF; break; @@ -138,29 +195,21 @@ bool GfxLink::LoadNative( Graphic& rGraphic ) void GfxLink::SwapOut() { - if( !IsSwappedOut() && mpSwapInData && mnSwapInDataSize ) + if( !IsSwappedOut() && mpBuf ) { - ::utl::TempFile aTempFile; - - OUString aURL = aTempFile.GetURL(); + mpSwap = new ImpSwap( mpBuf->mpBuffer, mnBufSize ); - if( !aURL.isEmpty() ) + if( !mpSwap->IsSwapped() ) { - std::shared_ptr<GfxLink::SwapOutData> pSwapOut; - pSwapOut = std::make_shared<SwapOutData>(aURL); // aURL is removed in the destructor - std::unique_ptr<SvStream> xOStm(::utl::UcbStreamHelper::CreateStream( aURL, STREAM_READWRITE | StreamMode::SHARE_DENYWRITE )); - if( xOStm ) - { - xOStm->Write( mpSwapInData.get(), mnSwapInDataSize ); - bool bError = ( ERRCODE_NONE != xOStm->GetError() ); - xOStm.reset(); + delete mpSwap; + mpSwap = nullptr; + } + else + { + if( !( --mpBuf->mnRefCount ) ) + delete mpBuf; - if( !bError ) - { - mpSwapOutData = pSwapOut; - mpSwapInData.reset(); - } - } + mpBuf = nullptr; } } } @@ -169,12 +218,12 @@ void GfxLink::SwapIn() { if( IsSwappedOut() ) { - auto pData = GetSwapInData(); - if (pData) - { - mpSwapInData = pData; - mpSwapOutData.reset(); - } + mpBuf = new ImpBuffer( mpSwap->GetData() ); + + if( !( --mpSwap->mnRefCount ) ) + delete mpSwap; + + mpSwap = nullptr; } } @@ -182,9 +231,10 @@ bool GfxLink::ExportNative( SvStream& rOStream ) const { if( GetDataSize() ) { - auto pData = GetSwapInData(); - if (pData) - rOStream.Write( pData.get(), mnSwapInDataSize ); + if( IsSwappedOut() ) + mpSwap->WriteTo( rOStream ); + else if( GetData() ) + rOStream.Write( GetData(), GetDataSize() ); } return ( rOStream.GetError() == ERRCODE_NONE ); @@ -205,9 +255,10 @@ SvStream& WriteGfxLink( SvStream& rOStream, const GfxLink& rGfxLink ) if( rGfxLink.GetDataSize() ) { - auto pData = rGfxLink.GetSwapInData(); - if (pData) - rOStream.Write( pData.get(), rGfxLink.mnSwapInDataSize ); + if( rGfxLink.IsSwappedOut() ) + rGfxLink.mpSwap->WriteTo( rOStream ); + else if( rGfxLink.GetData() ) + rOStream.Write( rGfxLink.GetData(), rGfxLink.GetDataSize() ); } return rOStream; @@ -219,7 +270,8 @@ SvStream& ReadGfxLink( SvStream& rIStream, GfxLink& rGfxLink) MapMode aMapMode; sal_uInt32 nSize; sal_uInt32 nUserId; - sal_uInt16 nType; + sal_uInt16 nType; + sal_uInt8* pBuf; bool bMapAndSizeValid( false ); std::unique_ptr<VersionCompat> pCompat(new VersionCompat( rIStream, StreamMode::READ )); @@ -235,7 +287,7 @@ SvStream& ReadGfxLink( SvStream& rIStream, GfxLink& rGfxLink) pCompat.reset(); // destructor writes stuff into the header - sal_uInt8* pBuf = new sal_uInt8[ nSize ]; + pBuf = new sal_uInt8[ nSize ]; rIStream.Read( pBuf, nSize ); rGfxLink = GfxLink( pBuf, nSize, (GfxLinkType) nType ); @@ -250,40 +302,83 @@ SvStream& ReadGfxLink( SvStream& rIStream, GfxLink& rGfxLink) return rIStream; } -GfxLink::SwapOutData::SwapOutData(const OUString &aURL) : maURL(aURL) +ImpSwap::ImpSwap( sal_uInt8* pData, sal_uLong nDataSize ) : + mnDataSize( nDataSize ), + mnRefCount( 1UL ) { + if( pData && mnDataSize ) + { + ::utl::TempFile aTempFile; + + maURL = aTempFile.GetURL(); + if( !maURL.isEmpty() ) + { + std::unique_ptr<SvStream> xOStm(::utl::UcbStreamHelper::CreateStream( maURL, STREAM_READWRITE | StreamMode::SHARE_DENYWRITE )); + if( xOStm ) + { + xOStm->Write( pData, mnDataSize ); + bool bError = ( ERRCODE_NONE != xOStm->GetError() ); + xOStm.reset(); + + if( bError ) + { + osl_removeFile( maURL.pData ); + maURL.clear(); + } + } + } + } } -GfxLink::SwapOutData::~SwapOutData() +ImpSwap::~ImpSwap() { - if( maURL.getLength() > 0 ) + if( IsSwapped() ) osl_removeFile( maURL.pData ); } -std::shared_ptr<sal_uInt8> GfxLink::GetSwapInData() const +sal_uInt8* ImpSwap::GetData() const { - if( !IsSwappedOut() ) - return mpSwapInData; - - std::shared_ptr<sal_uInt8> pData; + sal_uInt8* pData; - std::unique_ptr<SvStream> xIStm(::utl::UcbStreamHelper::CreateStream( mpSwapOutData->maURL, STREAM_READWRITE )); - if( xIStm ) + if( IsSwapped() ) { - pData = std::shared_ptr<sal_uInt8>(new sal_uInt8[ mnSwapInDataSize ]); - xIStm->Read( pData.get(), mnSwapInDataSize ); - bool bError = ( ERRCODE_NONE != xIStm->GetError() ); - sal_Size nActReadSize = xIStm->Tell(); - if (nActReadSize != mnSwapInDataSize) + std::unique_ptr<SvStream> xIStm(::utl::UcbStreamHelper::CreateStream( maURL, STREAM_READWRITE )); + if( xIStm ) { - bError = true; - } - xIStm.reset(); + pData = new sal_uInt8[ mnDataSize ]; + xIStm->Read( pData, mnDataSize ); + bool bError = ( ERRCODE_NONE != xIStm->GetError() ); + sal_Size nActReadSize = xIStm->Tell(); + if (nActReadSize != mnDataSize) + { + bError = true; + } + xIStm.reset(); - if( bError ) - pData.reset(); + if( bError ) + { + delete[] pData; + pData = nullptr; + } + } + else + pData = nullptr; } + else + pData = nullptr; + return pData; } +void ImpSwap::WriteTo( SvStream& rOStm ) const +{ + sal_uInt8* pData = GetData(); + + if( pData ) + { + rOStm.Write( pData, mnDataSize ); + delete[] pData; + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |