xref: /trunk/main/vcl/source/gdi/gfxlink.cxx (revision 9f62ea84)
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 
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 
55 GfxLink::GfxLink( const GfxLink& rGfxLink ) :
56     mpImpData( new ImpGfxLink )
57 {
58 	ImplCopy( rGfxLink );
59 }
60 
61 // ------------------------------------------------------------------------
62 
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 
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 
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 
118 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 
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 
158 GfxLinkType GfxLink::GetType() const
159 {
160 	return meType;
161 }
162 
163 // ------------------------------------------------------------------------
164 
165 sal_Bool GfxLink::IsNative() const
166 {
167 	return( meType >= GFX_LINK_FIRST_NATIVE_ID && meType <= GFX_LINK_LAST_NATIVE_ID );
168 }
169 
170 // ------------------------------------------------------------------------
171 
172 sal_uInt32 GfxLink::GetDataSize() const
173 {
174 	return mnBufSize;
175 }
176 
177 // ------------------------------------------------------------------------
178 
179 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 
189 const Size&	GfxLink::GetPrefSize() const
190 {
191     return mpImpData->maPrefSize;
192 }
193 
194 // ------------------------------------------------------------------------
195 
196 void GfxLink::SetPrefSize( const Size& rPrefSize )
197 {
198     mpImpData->maPrefSize = rPrefSize;
199     mpImpData->mbPrefSizeValid = true;
200 }
201 
202 // ------------------------------------------------------------------------
203 
204 bool GfxLink::IsPrefSizeValid()
205 {
206     return mpImpData->mbPrefSizeValid;
207 }
208 
209 // ------------------------------------------------------------------------
210 
211 const MapMode& GfxLink::GetPrefMapMode() const
212 {
213     return mpImpData->maPrefMapMode;
214 }
215 
216 // ------------------------------------------------------------------------
217 
218 void GfxLink::SetPrefMapMode( const MapMode& rPrefMapMode )
219 {
220     mpImpData->maPrefMapMode = rPrefMapMode;
221     mpImpData->mbPrefMapModeValid = true;
222 }
223 
224 // ------------------------------------------------------------------------
225 
226 bool GfxLink::IsPrefMapModeValid()
227 {
228     return mpImpData->mbPrefMapModeValid;
229 }
230 
231 // ------------------------------------------------------------------------
232 
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 				case( GFX_LINK_TYPE_NATIVE_JPG ): nCvtType = CVT_JPG; break;
252 				case( GFX_LINK_TYPE_NATIVE_PNG ): nCvtType = CVT_PNG; break;
253 				case( GFX_LINK_TYPE_NATIVE_TIF ): nCvtType = CVT_TIF; break;
254 				case( GFX_LINK_TYPE_NATIVE_WMF ): nCvtType = CVT_WMF; break;
255 				case( GFX_LINK_TYPE_NATIVE_MET ): nCvtType = CVT_MET; break;
256 				case( GFX_LINK_TYPE_NATIVE_PCT ): nCvtType = CVT_PCT; break;
257 				case( GFX_LINK_TYPE_NATIVE_SVG ): nCvtType = CVT_SVG; break;
258 
259 				default: nCvtType = CVT_UNKNOWN; break;
260 			}
261 
262 			if( nCvtType && ( GraphicConverter::Import( aMemStm, rGraphic, nCvtType ) == ERRCODE_NONE ) )
263 				bRet = sal_True;
264 		}
265 	}
266 
267 	return bRet;
268 }
269 
270 // ------------------------------------------------------------------------
271 
272 void GfxLink::SwapOut()
273 {
274 	if( !IsSwappedOut() && mpBuf )
275 	{
276 		mpSwap = new ImpSwap( mpBuf->mpBuffer, mnBufSize );
277 
278 		if( !mpSwap->IsSwapped() )
279 		{
280 			delete mpSwap;
281 			mpSwap = NULL;
282 		}
283 		else
284         {
285             if( !( --mpBuf->mnRefCount ) )
286                 delete mpBuf;
287 
288             mpBuf = NULL;
289         }
290 	}
291 }
292 
293 // ------------------------------------------------------------------------
294 
295 void GfxLink::SwapIn()
296 {
297 	if( IsSwappedOut() )
298 	{
299 		mpBuf = new ImpBuffer( mpSwap->GetData() );
300 
301 		if( !( --mpSwap->mnRefCount ) )
302 			delete mpSwap;
303 
304 		mpSwap = NULL;
305 	}
306 }
307 
308 // ------------------------------------------------------------------------
309 
310 sal_Bool GfxLink::ExportNative( SvStream& rOStream ) const
311 {
312 	if( GetDataSize() )
313 	{
314 		if( IsSwappedOut() )
315 			mpSwap->WriteTo( rOStream );
316 		else if( GetData() )
317 			rOStream.Write( GetData(), GetDataSize() );
318 	}
319 
320 	return ( rOStream.GetError() == ERRCODE_NONE );
321 }
322 
323 // ------------------------------------------------------------------------
324 
325 SvStream& operator<<( SvStream& rOStream, const GfxLink& rGfxLink )
326 {
327 	VersionCompat* pCompat = new VersionCompat( rOStream, STREAM_WRITE, 2 );
328 
329 	// Version 1
330     rOStream << (sal_uInt16) rGfxLink.GetType() << rGfxLink.GetDataSize() << rGfxLink.GetUserId();
331 
332     // Version 2
333     rOStream << rGfxLink.GetPrefSize() << rGfxLink.GetPrefMapMode();
334 
335 	delete pCompat;
336 
337 	if( rGfxLink.GetDataSize() )
338 	{
339 		if( rGfxLink.IsSwappedOut() )
340 			rGfxLink.mpSwap->WriteTo( rOStream );
341 		else if( rGfxLink.GetData() )
342 			rOStream.Write( rGfxLink.GetData(), rGfxLink.GetDataSize() );
343 	}
344 
345 	return rOStream;
346 }
347 
348 // ------------------------------------------------------------------------
349 
350 SvStream& operator>>( SvStream& rIStream, GfxLink& rGfxLink)
351 {
352     Size            aSize;
353     MapMode         aMapMode;
354 	sal_uInt32		nSize;
355 	sal_uInt32		nUserId;
356 	sal_uInt16			nType;
357 	sal_uInt8*			pBuf;
358     bool			bMapAndSizeValid( false );
359 	VersionCompat*	pCompat = new VersionCompat( rIStream, STREAM_READ );
360 
361 	// Version 1
362     rIStream >> nType >> nSize >> nUserId;
363 
364     if( pCompat->GetVersion() >= 2 )
365     {
366         rIStream >> aSize >> aMapMode;
367         bMapAndSizeValid = true;
368     }
369 
370 	delete pCompat;
371 
372 	pBuf = new sal_uInt8[ nSize ];
373 	rIStream.Read( pBuf, nSize );
374 
375 	rGfxLink = GfxLink( pBuf, nSize, (GfxLinkType) nType, sal_True );
376 	rGfxLink.SetUserId( nUserId );
377 
378     if( bMapAndSizeValid )
379     {
380         rGfxLink.SetPrefSize( aSize );
381         rGfxLink.SetPrefMapMode( aMapMode );
382     }
383 
384 	return rIStream;
385 }
386 
387 // -----------
388 // - ImpSwap -
389 // -----------
390 
391 ImpSwap::ImpSwap( sal_uInt8* pData, sal_uLong nDataSize ) :
392 			mnDataSize( nDataSize ),
393 			mnRefCount( 1UL )
394 {
395 	if( pData && mnDataSize )
396 	{
397 		::utl::TempFile aTempFile;
398 
399 		maURL = aTempFile.GetURL();
400 		if( maURL.getLength() )
401 		{
402 			SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( maURL, STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
403 			if( pOStm )
404 			{
405 				pOStm->Write( pData, mnDataSize );
406 				sal_Bool bError = ( ERRCODE_NONE != pOStm->GetError() );
407 				delete pOStm;
408 
409 				if( bError )
410 				{
411 					osl_removeFile( maURL.pData );
412 					maURL = String();
413 				}
414 			}
415 		}
416 	}
417 }
418 
419 // ------------------------------------------------------------------------
420 
421 ImpSwap::~ImpSwap()
422 {
423 	if( IsSwapped() )
424 		osl_removeFile( maURL.pData );
425 }
426 
427 // ------------------------------------------------------------------------
428 
429 sal_uInt8* ImpSwap::GetData() const
430 {
431 	sal_uInt8* pData;
432 
433 	if( IsSwapped() )
434 	{
435 		SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( maURL, STREAM_READWRITE );
436 		if( pIStm )
437 		{
438 			pData = new sal_uInt8[ mnDataSize ];
439 			pIStm->Read( pData, mnDataSize );
440 			sal_Bool bError = ( ERRCODE_NONE != pIStm->GetError() );
441 			delete pIStm;
442 
443 			if( bError )
444 				delete[] pData, pData = NULL;
445 		}
446 		else
447 			pData = NULL;
448 	}
449 	else
450 		pData = NULL;
451 
452 	return pData;
453 }
454 
455 // ------------------------------------------------------------------------
456 
457 void ImpSwap::WriteTo( SvStream& rOStm ) const
458 {
459 	sal_uInt8* pData = GetData();
460 
461 	if( pData )
462 	{
463 		rOStm.Write( pData, mnDataSize );
464 		delete[] pData;
465 	}
466 }
467