1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26
27 #include <osl/file.h>
28 #include <tools/vcompat.hxx>
29 #include <tools/urlobj.hxx>
30 #include <tools/debug.hxx>
31 #include <unotools/ucbstreamhelper.hxx>
32 #include <unotools/tempfile.hxx>
33 #include <ucbhelper/content.hxx>
34 #include <vcl/graph.hxx>
35 #include <vcl/gfxlink.hxx>
36 #include <vcl/cvtgrf.hxx>
37 #include <com/sun/star/ucb/CommandAbortedException.hpp>
38
39 // -----------
40 // - GfxLink -
41 // -----------
42
GfxLink()43 GfxLink::GfxLink() :
44 meType ( GFX_LINK_TYPE_NONE ),
45 mpBuf ( NULL ),
46 mpSwap ( NULL ),
47 mnBufSize ( 0 ),
48 mnUserId ( 0UL ),
49 mpImpData ( new ImpGfxLink )
50 {
51 }
52
53 // ------------------------------------------------------------------------
54
GfxLink(const GfxLink & rGfxLink)55 GfxLink::GfxLink( const GfxLink& rGfxLink ) :
56 mpImpData( new ImpGfxLink )
57 {
58 ImplCopy( rGfxLink );
59 }
60
61 // ------------------------------------------------------------------------
62
GfxLink(sal_uInt8 * pBuf,sal_uInt32 nSize,GfxLinkType nType,sal_Bool bOwns)63 GfxLink::GfxLink( sal_uInt8* pBuf, sal_uInt32 nSize, GfxLinkType nType, sal_Bool bOwns ) :
64 mpImpData( new ImpGfxLink )
65 {
66 DBG_ASSERT( (pBuf != NULL && nSize) || (!bOwns && nSize == 0),
67 "GfxLink::GfxLink(): empty/NULL buffer given" );
68
69 meType = nType;
70 mnBufSize = nSize;
71 mpSwap = NULL;
72 mnUserId = 0UL;
73
74 if( bOwns )
75 mpBuf = new ImpBuffer( pBuf );
76 else if( nSize )
77 {
78 mpBuf = new ImpBuffer( nSize );
79 memcpy( mpBuf->mpBuffer, pBuf, nSize );
80 }
81 else
82 mpBuf = NULL;
83 }
84
85 // ------------------------------------------------------------------------
86
~GfxLink()87 GfxLink::~GfxLink()
88 {
89 if( mpBuf && !( --mpBuf->mnRefCount ) )
90 delete mpBuf;
91
92 if( mpSwap && !( --mpSwap->mnRefCount ) )
93 delete mpSwap;
94
95 delete mpImpData;
96 }
97
98 // ------------------------------------------------------------------------
99
operator =(const GfxLink & rGfxLink)100 GfxLink& GfxLink::operator=( const GfxLink& rGfxLink )
101 {
102 if( &rGfxLink != this )
103 {
104 if ( mpBuf && !( --mpBuf->mnRefCount ) )
105 delete mpBuf;
106
107 if( mpSwap && !( --mpSwap->mnRefCount ) )
108 delete mpSwap;
109
110 ImplCopy( rGfxLink );
111 }
112
113 return *this;
114 }
115
116 // ------------------------------------------------------------------------
117
IsEqual(const GfxLink & rGfxLink) const118 sal_Bool GfxLink::IsEqual( const GfxLink& rGfxLink ) const
119 {
120 sal_Bool bIsEqual = sal_False;
121
122 if ( ( mnBufSize == rGfxLink.mnBufSize ) && ( meType == rGfxLink.meType ) )
123 {
124 const sal_uInt8* pSource = GetData();
125 const sal_uInt8* pDest = rGfxLink.GetData();
126 sal_uInt32 nSourceSize = GetDataSize();
127 sal_uInt32 nDestSize = rGfxLink.GetDataSize();
128 if ( pSource && pDest && ( nSourceSize == nDestSize ) )
129 {
130 bIsEqual = memcmp( pSource, pDest, nSourceSize ) == 0;
131 }
132 else if ( ( pSource == 0 ) && ( pDest == 0 ) )
133 bIsEqual = sal_True;
134 }
135 return bIsEqual;
136 }
137
138 // ------------------------------------------------------------------------
139
ImplCopy(const GfxLink & rGfxLink)140 void GfxLink::ImplCopy( const GfxLink& rGfxLink )
141 {
142 mnBufSize = rGfxLink.mnBufSize;
143 meType = rGfxLink.meType;
144 mpBuf = rGfxLink.mpBuf;
145 mpSwap = rGfxLink.mpSwap;
146 mnUserId = rGfxLink.mnUserId;
147 *mpImpData = *rGfxLink.mpImpData;
148
149 if( mpBuf )
150 mpBuf->mnRefCount++;
151
152 if( mpSwap )
153 mpSwap->mnRefCount++;
154 }
155
156 // ------------------------------------------------------------------------
157
GetType() const158 GfxLinkType GfxLink::GetType() const
159 {
160 return meType;
161 }
162
163 // ------------------------------------------------------------------------
164
IsNative() const165 sal_Bool GfxLink::IsNative() const
166 {
167 return( meType >= GFX_LINK_FIRST_NATIVE_ID && meType <= GFX_LINK_LAST_NATIVE_ID );
168 }
169
170 // ------------------------------------------------------------------------
171
GetDataSize() const172 sal_uInt32 GfxLink::GetDataSize() const
173 {
174 return mnBufSize;
175 }
176
177 // ------------------------------------------------------------------------
178
GetData() const179 const sal_uInt8* GfxLink::GetData() const
180 {
181 if( IsSwappedOut() )
182 ( (GfxLink*) this )->SwapIn();
183
184 return( mpBuf ? mpBuf->mpBuffer : NULL );
185 }
186
187 // ------------------------------------------------------------------------
188
GetPrefSize() const189 const Size& GfxLink::GetPrefSize() const
190 {
191 return mpImpData->maPrefSize;
192 }
193
194 // ------------------------------------------------------------------------
195
SetPrefSize(const Size & rPrefSize)196 void GfxLink::SetPrefSize( const Size& rPrefSize )
197 {
198 mpImpData->maPrefSize = rPrefSize;
199 mpImpData->mbPrefSizeValid = true;
200 }
201
202 // ------------------------------------------------------------------------
203
IsPrefSizeValid()204 bool GfxLink::IsPrefSizeValid()
205 {
206 return mpImpData->mbPrefSizeValid;
207 }
208
209 // ------------------------------------------------------------------------
210
GetPrefMapMode() const211 const MapMode& GfxLink::GetPrefMapMode() const
212 {
213 return mpImpData->maPrefMapMode;
214 }
215
216 // ------------------------------------------------------------------------
217
SetPrefMapMode(const MapMode & rPrefMapMode)218 void GfxLink::SetPrefMapMode( const MapMode& rPrefMapMode )
219 {
220 mpImpData->maPrefMapMode = rPrefMapMode;
221 mpImpData->mbPrefMapModeValid = true;
222 }
223
224 // ------------------------------------------------------------------------
225
IsPrefMapModeValid()226 bool GfxLink::IsPrefMapModeValid()
227 {
228 return mpImpData->mbPrefMapModeValid;
229 }
230
231 // ------------------------------------------------------------------------
232
LoadNative(Graphic & rGraphic)233 sal_Bool GfxLink::LoadNative( Graphic& rGraphic )
234 {
235 sal_Bool bRet = sal_False;
236
237 if( IsNative() && mnBufSize )
238 {
239 const sal_uInt8* pData = GetData();
240
241 if( pData )
242 {
243 SvMemoryStream aMemStm;
244 sal_uLong nCvtType;
245
246 aMemStm.SetBuffer( (char*) pData, mnBufSize, sal_False, mnBufSize );
247
248 switch( meType )
249 {
250 case( GFX_LINK_TYPE_NATIVE_GIF ): nCvtType = CVT_GIF; break;
251
252 // #15508# added BMP type for better exports (reload when swapped - checked, works)
253 case( GFX_LINK_TYPE_NATIVE_BMP ): nCvtType = CVT_BMP; break;
254
255 case( GFX_LINK_TYPE_NATIVE_JPG ): nCvtType = CVT_JPG; break;
256 case( GFX_LINK_TYPE_NATIVE_PNG ): nCvtType = CVT_PNG; break;
257 case( GFX_LINK_TYPE_NATIVE_TIF ): nCvtType = CVT_TIF; break;
258 case( GFX_LINK_TYPE_NATIVE_WMF ): nCvtType = CVT_WMF; break;
259 case( GFX_LINK_TYPE_NATIVE_MET ): nCvtType = CVT_MET; break;
260 case( GFX_LINK_TYPE_NATIVE_PCT ): nCvtType = CVT_PCT; break;
261 case( GFX_LINK_TYPE_NATIVE_SVG ): nCvtType = CVT_SVG; break;
262
263 default: nCvtType = CVT_UNKNOWN; break;
264 }
265
266 if( nCvtType && ( GraphicConverter::Import( aMemStm, rGraphic, nCvtType ) == ERRCODE_NONE ) )
267 bRet = sal_True;
268 }
269 }
270
271 return bRet;
272 }
273
274 // ------------------------------------------------------------------------
275
SwapOut()276 void GfxLink::SwapOut()
277 {
278 if( !IsSwappedOut() && mpBuf )
279 {
280 mpSwap = new ImpSwap( mpBuf->mpBuffer, mnBufSize );
281
282 if( !mpSwap->IsSwapped() )
283 {
284 delete mpSwap;
285 mpSwap = NULL;
286 }
287 else
288 {
289 if( !( --mpBuf->mnRefCount ) )
290 delete mpBuf;
291
292 mpBuf = NULL;
293 }
294 }
295 }
296
297 // ------------------------------------------------------------------------
298
SwapIn()299 void GfxLink::SwapIn()
300 {
301 if( IsSwappedOut() )
302 {
303 mpBuf = new ImpBuffer( mpSwap->GetData() );
304
305 if( !( --mpSwap->mnRefCount ) )
306 delete mpSwap;
307
308 mpSwap = NULL;
309 }
310 }
311
312 // ------------------------------------------------------------------------
313
ExportNative(SvStream & rOStream) const314 sal_Bool GfxLink::ExportNative( SvStream& rOStream ) const
315 {
316 if( GetDataSize() )
317 {
318 if( IsSwappedOut() )
319 mpSwap->WriteTo( rOStream );
320 else if( GetData() )
321 rOStream.Write( GetData(), GetDataSize() );
322 }
323
324 return ( rOStream.GetError() == ERRCODE_NONE );
325 }
326
327 // ------------------------------------------------------------------------
328
operator <<(SvStream & rOStream,const GfxLink & rGfxLink)329 SvStream& operator<<( SvStream& rOStream, const GfxLink& rGfxLink )
330 {
331 VersionCompat* pCompat = new VersionCompat( rOStream, STREAM_WRITE, 2 );
332
333 // Version 1
334 rOStream << (sal_uInt16) rGfxLink.GetType() << rGfxLink.GetDataSize() << rGfxLink.GetUserId();
335
336 // Version 2
337 rOStream << rGfxLink.GetPrefSize() << rGfxLink.GetPrefMapMode();
338
339 delete pCompat;
340
341 if( rGfxLink.GetDataSize() )
342 {
343 if( rGfxLink.IsSwappedOut() )
344 rGfxLink.mpSwap->WriteTo( rOStream );
345 else if( rGfxLink.GetData() )
346 rOStream.Write( rGfxLink.GetData(), rGfxLink.GetDataSize() );
347 }
348
349 return rOStream;
350 }
351
352 // ------------------------------------------------------------------------
353
operator >>(SvStream & rIStream,GfxLink & rGfxLink)354 SvStream& operator>>( SvStream& rIStream, GfxLink& rGfxLink)
355 {
356 Size aSize;
357 MapMode aMapMode;
358 sal_uInt32 nSize;
359 sal_uInt32 nUserId;
360 sal_uInt16 nType;
361 sal_uInt8* pBuf;
362 bool bMapAndSizeValid( false );
363 VersionCompat* pCompat = new VersionCompat( rIStream, STREAM_READ );
364
365 // Version 1
366 rIStream >> nType >> nSize >> nUserId;
367
368 if( pCompat->GetVersion() >= 2 )
369 {
370 rIStream >> aSize >> aMapMode;
371 bMapAndSizeValid = true;
372 }
373
374 delete pCompat;
375
376 pBuf = new sal_uInt8[ nSize ];
377 rIStream.Read( pBuf, nSize );
378
379 rGfxLink = GfxLink( pBuf, nSize, (GfxLinkType) nType, sal_True );
380 rGfxLink.SetUserId( nUserId );
381
382 if( bMapAndSizeValid )
383 {
384 rGfxLink.SetPrefSize( aSize );
385 rGfxLink.SetPrefMapMode( aMapMode );
386 }
387
388 return rIStream;
389 }
390
391 // -----------
392 // - ImpSwap -
393 // -----------
394
ImpSwap(sal_uInt8 * pData,sal_uLong nDataSize)395 ImpSwap::ImpSwap( sal_uInt8* pData, sal_uLong nDataSize ) :
396 mnDataSize( nDataSize ),
397 mnRefCount( 1UL )
398 {
399 if( pData && mnDataSize )
400 {
401 ::utl::TempFile aTempFile;
402
403 maURL = aTempFile.GetURL();
404 if( maURL.getLength() )
405 {
406 SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( maURL, STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
407 if( pOStm )
408 {
409 pOStm->Write( pData, mnDataSize );
410 sal_Bool bError = ( ERRCODE_NONE != pOStm->GetError() );
411 delete pOStm;
412
413 if( bError )
414 {
415 osl_removeFile( maURL.pData );
416 maURL = String();
417 }
418 }
419 }
420 }
421 }
422
423 // ------------------------------------------------------------------------
424
~ImpSwap()425 ImpSwap::~ImpSwap()
426 {
427 if( IsSwapped() )
428 osl_removeFile( maURL.pData );
429 }
430
431 // ------------------------------------------------------------------------
432
GetData() const433 sal_uInt8* ImpSwap::GetData() const
434 {
435 sal_uInt8* pData;
436
437 if( IsSwapped() )
438 {
439 SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( maURL, STREAM_READWRITE );
440 if( pIStm )
441 {
442 pData = new sal_uInt8[ mnDataSize ];
443 pIStm->Read( pData, mnDataSize );
444 sal_Bool bError = ( ERRCODE_NONE != pIStm->GetError() );
445 sal_Size nActReadSize = pIStm->Tell();
446 if (nActReadSize != mnDataSize)
447 {
448 bError = sal_True;
449 }
450 delete pIStm;
451
452 if( bError )
453 delete[] pData, pData = NULL;
454 }
455 else
456 pData = NULL;
457 }
458 else
459 pData = NULL;
460
461 return pData;
462 }
463
464 // ------------------------------------------------------------------------
465
WriteTo(SvStream & rOStm) const466 void ImpSwap::WriteTo( SvStream& rOStm ) const
467 {
468 sal_uInt8* pData = GetData();
469
470 if( pData )
471 {
472 rOStm.Write( pData, mnDataSize );
473 delete[] pData;
474 }
475 }
476