xref: /trunk/main/vcl/source/gdi/gfxlink.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #include <osl/file.h>
32 #include <tools/vcompat.hxx>
33 #include <tools/urlobj.hxx>
34 #include <tools/debug.hxx>
35 #include <unotools/ucbstreamhelper.hxx>
36 #include <unotools/tempfile.hxx>
37 #include <ucbhelper/content.hxx>
38 #include <vcl/graph.hxx>
39 #include <vcl/gfxlink.hxx>
40 #include <vcl/cvtgrf.hxx>
41 #include <com/sun/star/ucb/CommandAbortedException.hpp>
42 
43 // -----------
44 // - GfxLink -
45 // -----------
46 
47 GfxLink::GfxLink() :
48     meType      ( GFX_LINK_TYPE_NONE ),
49     mpBuf       ( NULL ),
50     mpSwap      ( NULL ),
51     mnBufSize   ( 0 ),
52     mnUserId    ( 0UL ),
53     mpImpData   ( new ImpGfxLink )
54 {
55 }
56 
57 // ------------------------------------------------------------------------
58 
59 GfxLink::GfxLink( const GfxLink& rGfxLink ) :
60     mpImpData( new ImpGfxLink )
61 {
62     ImplCopy( rGfxLink );
63 }
64 
65 // ------------------------------------------------------------------------
66 
67 GfxLink::GfxLink( sal_uInt8* pBuf, sal_uInt32 nSize, GfxLinkType nType, sal_Bool bOwns ) :
68     mpImpData( new ImpGfxLink )
69 {
70     DBG_ASSERT( (pBuf != NULL && nSize) || (!bOwns && nSize == 0),
71                 "GfxLink::GfxLink(): empty/NULL buffer given" );
72 
73     meType = nType;
74     mnBufSize = nSize;
75     mpSwap = NULL;
76     mnUserId = 0UL;
77 
78     if( bOwns )
79         mpBuf = new ImpBuffer( pBuf );
80     else if( nSize )
81     {
82         mpBuf = new ImpBuffer( nSize );
83         memcpy( mpBuf->mpBuffer, pBuf, nSize );
84     }
85     else
86         mpBuf = NULL;
87 }
88 
89 // ------------------------------------------------------------------------
90 
91 GfxLink::~GfxLink()
92 {
93     if( mpBuf && !( --mpBuf->mnRefCount ) )
94         delete mpBuf;
95 
96     if( mpSwap && !( --mpSwap->mnRefCount ) )
97         delete mpSwap;
98 
99     delete mpImpData;
100 }
101 
102 // ------------------------------------------------------------------------
103 
104 GfxLink& GfxLink::operator=( const GfxLink& rGfxLink )
105 {
106     if( &rGfxLink != this )
107     {
108         if ( mpBuf && !( --mpBuf->mnRefCount ) )
109             delete mpBuf;
110 
111         if( mpSwap && !( --mpSwap->mnRefCount ) )
112             delete mpSwap;
113 
114         ImplCopy( rGfxLink );
115     }
116 
117     return *this;
118 }
119 
120 // ------------------------------------------------------------------------
121 
122 sal_Bool GfxLink::IsEqual( const GfxLink& rGfxLink ) const
123 {
124     sal_Bool bIsEqual = sal_False;
125 
126     if ( ( mnBufSize == rGfxLink.mnBufSize ) && ( meType == rGfxLink.meType ) )
127     {
128         const sal_uInt8* pSource = GetData();
129         const sal_uInt8* pDest = rGfxLink.GetData();
130         sal_uInt32 nSourceSize = GetDataSize();
131         sal_uInt32 nDestSize = rGfxLink.GetDataSize();
132         if ( pSource && pDest && ( nSourceSize == nDestSize ) )
133         {
134             bIsEqual = memcmp( pSource, pDest, nSourceSize ) == 0;
135         }
136         else if ( ( pSource == 0 ) && ( pDest == 0 ) )
137             bIsEqual = sal_True;
138     }
139     return bIsEqual;
140 }
141 
142 // ------------------------------------------------------------------------
143 
144 void GfxLink::ImplCopy( const GfxLink& rGfxLink )
145 {
146     mnBufSize = rGfxLink.mnBufSize;
147     meType = rGfxLink.meType;
148     mpBuf = rGfxLink.mpBuf;
149     mpSwap = rGfxLink.mpSwap;
150     mnUserId = rGfxLink.mnUserId;
151     *mpImpData = *rGfxLink.mpImpData;
152 
153     if( mpBuf )
154         mpBuf->mnRefCount++;
155 
156     if( mpSwap )
157         mpSwap->mnRefCount++;
158 }
159 
160 // ------------------------------------------------------------------------
161 
162 GfxLinkType GfxLink::GetType() const
163 {
164     return meType;
165 }
166 
167 // ------------------------------------------------------------------------
168 
169 sal_Bool GfxLink::IsNative() const
170 {
171     return( meType >= GFX_LINK_FIRST_NATIVE_ID && meType <= GFX_LINK_LAST_NATIVE_ID );
172 }
173 
174 // ------------------------------------------------------------------------
175 
176 sal_uInt32 GfxLink::GetDataSize() const
177 {
178     return mnBufSize;
179 }
180 
181 // ------------------------------------------------------------------------
182 
183 const sal_uInt8* GfxLink::GetData() const
184 {
185     if( IsSwappedOut() )
186         ( (GfxLink*) this )->SwapIn();
187 
188     return( mpBuf ? mpBuf->mpBuffer : NULL );
189 }
190 
191 // ------------------------------------------------------------------------
192 
193 const Size& GfxLink::GetPrefSize() const
194 {
195     return mpImpData->maPrefSize;
196 }
197 
198 // ------------------------------------------------------------------------
199 
200 void GfxLink::SetPrefSize( const Size& rPrefSize )
201 {
202     mpImpData->maPrefSize = rPrefSize;
203     mpImpData->mbPrefSizeValid = true;
204 }
205 
206 // ------------------------------------------------------------------------
207 
208 bool GfxLink::IsPrefSizeValid()
209 {
210     return mpImpData->mbPrefSizeValid;
211 }
212 
213 // ------------------------------------------------------------------------
214 
215 const MapMode& GfxLink::GetPrefMapMode() const
216 {
217     return mpImpData->maPrefMapMode;
218 }
219 
220 // ------------------------------------------------------------------------
221 
222 void GfxLink::SetPrefMapMode( const MapMode& rPrefMapMode )
223 {
224     mpImpData->maPrefMapMode = rPrefMapMode;
225     mpImpData->mbPrefMapModeValid = true;
226 }
227 
228 // ------------------------------------------------------------------------
229 
230 bool GfxLink::IsPrefMapModeValid()
231 {
232     return mpImpData->mbPrefMapModeValid;
233 }
234 
235 // ------------------------------------------------------------------------
236 
237 sal_Bool GfxLink::LoadNative( Graphic& rGraphic )
238 {
239     sal_Bool bRet = sal_False;
240 
241     if( IsNative() && mnBufSize )
242     {
243         const sal_uInt8* pData = GetData();
244 
245         if( pData )
246         {
247             SvMemoryStream  aMemStm;
248             sal_uLong           nCvtType;
249 
250             aMemStm.SetBuffer( (char*) pData, mnBufSize, sal_False, mnBufSize );
251 
252             switch( meType )
253             {
254                 case( GFX_LINK_TYPE_NATIVE_GIF ): nCvtType = CVT_GIF; break;
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 
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 
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 
314 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 
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 
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 
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 
425 ImpSwap::~ImpSwap()
426 {
427     if( IsSwapped() )
428         osl_removeFile( maURL.pData );
429 }
430 
431 // ------------------------------------------------------------------------
432 
433 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             delete pIStm;
446 
447             if( bError )
448                 delete[] pData, pData = NULL;
449         }
450         else
451             pData = NULL;
452     }
453     else
454         pData = NULL;
455 
456     return pData;
457 }
458 
459 // ------------------------------------------------------------------------
460 
461 void ImpSwap::WriteTo( SvStream& rOStm ) const
462 {
463     sal_uInt8* pData = GetData();
464 
465     if( pData )
466     {
467         rOStm.Write( pData, mnDataSize );
468         delete[] pData;
469     }
470 }
471