xref: /AOO41X/main/vcl/source/gdi/gfxlink.cxx (revision 270a30df12a3c90d81bad020e479e05ab282de97)
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