1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <tools/vcompat.hxx>
22 #include <tools/debug.hxx>
23 #include <unotools/ucbstreamhelper.hxx>
24 #include <unotools/tempfile.hxx>
25 #include <ucbhelper/content.hxx>
26 #include <vcl/graph.hxx>
27 #include <vcl/gfxlink.hxx>
28 #include <vcl/cvtgrf.hxx>
29 #include <com/sun/star/ucb/CommandAbortedException.hpp>
33 meType ( GFX_LINK_TYPE_NONE
),
38 mpImpData ( new ImpGfxLink
)
42 GfxLink::GfxLink( const GfxLink
& rGfxLink
) :
43 mpImpData( new ImpGfxLink
)
48 GfxLink::GfxLink( sal_uInt8
* pBuf
, sal_uInt32 nSize
, GfxLinkType nType
, bool bOwns
) :
49 mpImpData( new ImpGfxLink
)
51 DBG_ASSERT( (pBuf
!= NULL
&& nSize
) || (!bOwns
&& nSize
== 0),
52 "GfxLink::GfxLink(): empty/NULL buffer given" );
60 mpBuf
= new ImpBuffer( pBuf
);
63 mpBuf
= new ImpBuffer( nSize
);
64 memcpy( mpBuf
->mpBuffer
, pBuf
, nSize
);
72 if( mpBuf
&& !( --mpBuf
->mnRefCount
) )
75 if( mpSwap
&& !( --mpSwap
->mnRefCount
) )
81 GfxLink
& GfxLink::operator=( const GfxLink
& rGfxLink
)
83 if( &rGfxLink
!= this )
85 if ( mpBuf
&& !( --mpBuf
->mnRefCount
) )
88 if( mpSwap
&& !( --mpSwap
->mnRefCount
) )
97 bool GfxLink::IsEqual( const GfxLink
& rGfxLink
) const
99 bool bIsEqual
= false;
101 if ( ( mnBufSize
== rGfxLink
.mnBufSize
) && ( meType
== rGfxLink
.meType
) )
103 const sal_uInt8
* pSource
= GetData();
104 const sal_uInt8
* pDest
= rGfxLink
.GetData();
105 sal_uInt32 nSourceSize
= GetDataSize();
106 sal_uInt32 nDestSize
= rGfxLink
.GetDataSize();
107 if ( pSource
&& pDest
&& ( nSourceSize
== nDestSize
) )
109 bIsEqual
= memcmp( pSource
, pDest
, nSourceSize
) == 0;
111 else if ( ( pSource
== 0 ) && ( pDest
== 0 ) )
117 void GfxLink::ImplCopy( const GfxLink
& rGfxLink
)
119 mnBufSize
= rGfxLink
.mnBufSize
;
120 meType
= rGfxLink
.meType
;
121 mpBuf
= rGfxLink
.mpBuf
;
122 mpSwap
= rGfxLink
.mpSwap
;
123 mnUserId
= rGfxLink
.mnUserId
;
124 *mpImpData
= *rGfxLink
.mpImpData
;
130 mpSwap
->mnRefCount
++;
134 bool GfxLink::IsNative() const
136 return( meType
>= GFX_LINK_FIRST_NATIVE_ID
&& meType
<= GFX_LINK_LAST_NATIVE_ID
);
140 const sal_uInt8
* GfxLink::GetData() const
143 const_cast<GfxLink
*>(this)->SwapIn();
145 return( mpBuf
? mpBuf
->mpBuffer
: NULL
);
149 void GfxLink::SetPrefSize( const Size
& rPrefSize
)
151 mpImpData
->maPrefSize
= rPrefSize
;
152 mpImpData
->mbPrefSizeValid
= true;
157 void GfxLink::SetPrefMapMode( const MapMode
& rPrefMapMode
)
159 mpImpData
->maPrefMapMode
= rPrefMapMode
;
160 mpImpData
->mbPrefMapModeValid
= true;
164 bool GfxLink::LoadNative( Graphic
& rGraphic
)
168 if( IsNative() && mnBufSize
)
170 const sal_uInt8
* pData
= GetData();
174 SvMemoryStream aMemStm
;
177 aMemStm
.SetBuffer( const_cast<sal_uInt8
*>(pData
), mnBufSize
, false, mnBufSize
);
181 case( GFX_LINK_TYPE_NATIVE_GIF
): nCvtType
= CVT_GIF
; break;
183 // #i15508# added BMP type for better exports (reload when swapped - checked, works)
184 case( GFX_LINK_TYPE_NATIVE_BMP
): nCvtType
= CVT_BMP
; break;
186 case( GFX_LINK_TYPE_NATIVE_JPG
): nCvtType
= CVT_JPG
; break;
187 case( GFX_LINK_TYPE_NATIVE_PNG
): nCvtType
= CVT_PNG
; break;
188 case( GFX_LINK_TYPE_NATIVE_TIF
): nCvtType
= CVT_TIF
; break;
189 case( GFX_LINK_TYPE_NATIVE_WMF
): nCvtType
= CVT_WMF
; break;
190 case( GFX_LINK_TYPE_NATIVE_MET
): nCvtType
= CVT_MET
; break;
191 case( GFX_LINK_TYPE_NATIVE_PCT
): nCvtType
= CVT_PCT
; break;
192 case( GFX_LINK_TYPE_NATIVE_SVG
): nCvtType
= CVT_SVG
; break;
194 default: nCvtType
= CVT_UNKNOWN
; break;
197 if( nCvtType
&& ( GraphicConverter::Import( aMemStm
, rGraphic
, nCvtType
) == ERRCODE_NONE
) )
205 void GfxLink::SwapOut()
207 if( !IsSwappedOut() && mpBuf
)
209 mpSwap
= new ImpSwap( mpBuf
->mpBuffer
, mnBufSize
);
211 if( !mpSwap
->IsSwapped() )
218 if( !( --mpBuf
->mnRefCount
) )
226 void GfxLink::SwapIn()
230 mpBuf
= new ImpBuffer( mpSwap
->GetData() );
232 if( !( --mpSwap
->mnRefCount
) )
239 bool GfxLink::ExportNative( SvStream
& rOStream
) const
244 mpSwap
->WriteTo( rOStream
);
246 rOStream
.Write( GetData(), GetDataSize() );
249 return ( rOStream
.GetError() == ERRCODE_NONE
);
252 SvStream
& WriteGfxLink( SvStream
& rOStream
, const GfxLink
& rGfxLink
)
254 VersionCompat
* pCompat
= new VersionCompat( rOStream
, StreamMode::WRITE
, 2 );
257 rOStream
.WriteUInt16( rGfxLink
.GetType() ).WriteUInt32( rGfxLink
.GetDataSize() ).WriteUInt32( rGfxLink
.GetUserId() );
260 WritePair( rOStream
, rGfxLink
.GetPrefSize() );
261 WriteMapMode( rOStream
, rGfxLink
.GetPrefMapMode() );
265 if( rGfxLink
.GetDataSize() )
267 if( rGfxLink
.IsSwappedOut() )
268 rGfxLink
.mpSwap
->WriteTo( rOStream
);
269 else if( rGfxLink
.GetData() )
270 rOStream
.Write( rGfxLink
.GetData(), rGfxLink
.GetDataSize() );
276 SvStream
& ReadGfxLink( SvStream
& rIStream
, GfxLink
& rGfxLink
)
284 bool bMapAndSizeValid( false );
285 VersionCompat
* pCompat
= new VersionCompat( rIStream
, StreamMode::READ
);
288 rIStream
.ReadUInt16( nType
).ReadUInt32( nSize
).ReadUInt32( nUserId
);
290 if( pCompat
->GetVersion() >= 2 )
292 ReadPair( rIStream
, aSize
);
293 ReadMapMode( rIStream
, aMapMode
);
294 bMapAndSizeValid
= true;
299 pBuf
= new sal_uInt8
[ nSize
];
300 rIStream
.Read( pBuf
, nSize
);
302 rGfxLink
= GfxLink( pBuf
, nSize
, (GfxLinkType
) nType
, true );
303 rGfxLink
.SetUserId( nUserId
);
305 if( bMapAndSizeValid
)
307 rGfxLink
.SetPrefSize( aSize
);
308 rGfxLink
.SetPrefMapMode( aMapMode
);
314 ImpSwap::ImpSwap( sal_uInt8
* pData
, sal_uLong nDataSize
) :
315 mnDataSize( nDataSize
),
318 if( pData
&& mnDataSize
)
320 ::utl::TempFile aTempFile
;
322 maURL
= aTempFile
.GetURL();
323 if( !maURL
.isEmpty() )
325 std::unique_ptr
<SvStream
> xOStm(::utl::UcbStreamHelper::CreateStream( maURL
, STREAM_READWRITE
| StreamMode::SHARE_DENYWRITE
));
328 xOStm
->Write( pData
, mnDataSize
);
329 bool bError
= ( ERRCODE_NONE
!= xOStm
->GetError() );
334 osl_removeFile( maURL
.pData
);
345 osl_removeFile( maURL
.pData
);
348 sal_uInt8
* ImpSwap::GetData() const
354 std::unique_ptr
<SvStream
> xIStm(::utl::UcbStreamHelper::CreateStream( maURL
, STREAM_READWRITE
));
357 pData
= new sal_uInt8
[ mnDataSize
];
358 xIStm
->Read( pData
, mnDataSize
);
359 bool bError
= ( ERRCODE_NONE
!= xIStm
->GetError() );
360 sal_Size nActReadSize
= xIStm
->Tell();
361 if (nActReadSize
!= mnDataSize
)
368 delete[] pData
, pData
= NULL
;
379 void ImpSwap::WriteTo( SvStream
& rOStm
) const
381 sal_uInt8
* pData
= GetData();
385 rOStm
.Write( pData
, mnDataSize
);
390 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */