xref: /trunk/main/vcl/source/gdi/impgraph.cxx (revision cdf0e10c)
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 <tools/vcompat.hxx>
32 #include <tools/urlobj.hxx>
33 #include <tools/debug.hxx>
34 #include <tools/stream.hxx>
35 
36 #include <ucbhelper/content.hxx>
37 
38 #include <unotools/ucbstreamhelper.hxx>
39 #include <unotools/tempfile.hxx>
40 
41 #include <vcl/outdev.hxx>
42 #include <vcl/virdev.hxx>
43 #include <vcl/gfxlink.hxx>
44 #include <vcl/cvtgrf.hxx>
45 #include <vcl/salbtype.hxx>
46 #include <vcl/graph.hxx>
47 #include <vcl/metaact.hxx>
48 
49 #include <impgraph.hxx>
50 
51 #include <com/sun/star/ucb/CommandAbortedException.hpp>
52 
53 // -----------
54 // - Defines -
55 // -----------
56 
57 #define GRAPHIC_MAXPARTLEN			256000L
58 #define GRAPHIC_MTFTOBMP_MAXEXT		2048
59 #define GRAPHIC_STREAMBUFSIZE		8192UL
60 
61 #define SYS_WINMETAFILE			    0x00000003L
62 #define SYS_WNTMETAFILE			    0x00000004L
63 #define SYS_OS2METAFILE			    0x00000005L
64 #define SYS_MACMETAFILE			    0x00000006L
65 
66 #define GRAPHIC_FORMAT_50		    static_cast<sal_uInt32>(COMPAT_FORMAT( 'G', 'R', 'F', '5' ))
67 #define NATIVE_FORMAT_50		    static_cast<sal_uInt32>(COMPAT_FORMAT( 'N', 'A', 'T', '5' ))
68 
69 // ---------------
70 // - ImpSwapFile -
71 // ---------------
72 
73 struct ImpSwapFile
74 {
75     INetURLObject	aSwapURL;
76 	sal_uLong			nRefCount;
77 };
78 
79 // -----------------
80 // - Graphicreader -
81 // -----------------
82 
83 class ReaderData
84 {
85 public:
86     Size    maPreviewSize;
87 };
88 
89 GraphicReader::~GraphicReader()
90 {
91     delete mpReaderData;
92 }
93 
94 // ------------------------------------------------------------------------
95 
96 sal_Bool GraphicReader::IsPreviewModeEnabled() const
97 {
98     if( !mpReaderData )
99         return sal_False;
100     if( mpReaderData->maPreviewSize.Width() )
101         return sal_True;
102     if( mpReaderData->maPreviewSize.Height() )
103         return sal_True;
104     return sal_False;
105 }
106 
107 // ------------------------------------------------------------------------
108 
109 void GraphicReader::DisablePreviewMode()
110 {
111     if( mpReaderData )
112         mpReaderData->maPreviewSize = Size( 0, 0 );
113 }
114 
115 // ------------------------------------------------------------------------
116 
117 void GraphicReader::SetPreviewSize( const Size& rSize )
118 {
119     if( !mpReaderData )
120         mpReaderData = new ReaderData;
121     mpReaderData->maPreviewSize = rSize;
122 }
123 
124 // ------------------------------------------------------------------------
125 
126 Size GraphicReader::GetPreviewSize() const
127 {
128     Size aSize( 0, 0 );
129     if( mpReaderData )
130         aSize = mpReaderData->maPreviewSize;
131     return aSize;
132 }
133 
134 // --------------
135 // - ImpGraphic -
136 // --------------
137 
138 ImpGraphic::ImpGraphic() :
139 		mpAnimation		( NULL ),
140 		mpContext		( NULL ),
141 		mpSwapFile		( NULL ),
142 		mpGfxLink		( NULL ),
143 		meType			( GRAPHIC_NONE ),
144 		mnDocFilePos    ( 0UL ),
145         mnSizeBytes     ( 0UL ),
146 		mnRefCount      ( 1UL ),
147 		mbSwapOut       ( sal_False ),
148 		mbSwapUnderway	( sal_False )
149 {
150 }
151 
152 // ------------------------------------------------------------------------
153 
154 ImpGraphic::ImpGraphic( const ImpGraphic& rImpGraphic ) :
155 		maMetaFile		( rImpGraphic.maMetaFile ),
156 		maEx			( rImpGraphic.maEx ),
157 	    mpContext		( NULL ),
158 		mpSwapFile		( rImpGraphic.mpSwapFile ),
159 		meType			( rImpGraphic.meType ),
160 		maDocFileURLStr	( rImpGraphic.maDocFileURLStr ),
161 		mnDocFilePos	( rImpGraphic.mnDocFilePos ),
162         mnSizeBytes     ( rImpGraphic.mnSizeBytes ),
163 		mnRefCount		( 1UL ),
164 		mbSwapOut		( rImpGraphic.mbSwapOut ),
165 		mbSwapUnderway	( sal_False )
166 {
167 	if( mpSwapFile )
168 		mpSwapFile->nRefCount++;
169 
170 	if( rImpGraphic.mpGfxLink )
171 		mpGfxLink = new GfxLink( *rImpGraphic.mpGfxLink );
172 	else
173 		mpGfxLink = NULL;
174 
175     if( rImpGraphic.mpAnimation )
176     {
177         mpAnimation = new Animation( *rImpGraphic.mpAnimation );
178         maEx = mpAnimation->GetBitmapEx();
179     }
180     else
181         mpAnimation = NULL;
182 }
183 
184 // ------------------------------------------------------------------------
185 
186 ImpGraphic::ImpGraphic( const Bitmap& rBitmap ) :
187 		maEx			( rBitmap ),
188 		mpAnimation		( NULL ),
189 		mpContext		( NULL ),
190 		mpSwapFile		( NULL ),
191 		mpGfxLink		( NULL ),
192 		meType			( !rBitmap ? GRAPHIC_NONE : GRAPHIC_BITMAP ),
193 		mnDocFilePos	( 0UL ),
194         mnSizeBytes     ( 0UL ),
195 		mnRefCount		( 1UL ),
196 		mbSwapOut		( sal_False ),
197 		mbSwapUnderway	( sal_False )
198 {
199 }
200 
201 // ------------------------------------------------------------------------
202 
203 ImpGraphic::ImpGraphic( const BitmapEx& rBitmapEx ) :
204 		maEx			( rBitmapEx ),
205 		mpAnimation		( NULL ),
206 		mpContext		( NULL ),
207 		mpSwapFile		( NULL ),
208 		mpGfxLink		( NULL ),
209 		meType			( !rBitmapEx ? GRAPHIC_NONE : GRAPHIC_BITMAP ),
210 		mnDocFilePos	( 0UL ),
211         mnSizeBytes     ( 0UL ),
212 		mnRefCount		( 1UL ),
213 		mbSwapOut		( sal_False ),
214 		mbSwapUnderway	( sal_False )
215 {
216 }
217 
218 // ------------------------------------------------------------------------
219 
220 ImpGraphic::ImpGraphic( const Animation& rAnimation ) :
221 	    maEx			( rAnimation.GetBitmapEx() ),
222 	    mpAnimation		( new Animation( rAnimation ) ),
223 		mpContext		( NULL ),
224 		mpSwapFile		( NULL ),
225 		mpGfxLink		( NULL ),
226 		meType			( GRAPHIC_BITMAP ),
227 		mnDocFilePos	( 0UL ),
228         mnSizeBytes     ( 0UL ),
229 		mnRefCount		( 1UL ),
230 		mbSwapOut		( sal_False ),
231 		mbSwapUnderway	( sal_False )
232 {
233 }
234 
235 // ------------------------------------------------------------------------
236 
237 ImpGraphic::ImpGraphic( const GDIMetaFile& rMtf ) :
238 	    maMetaFile		( rMtf ),
239 		mpAnimation		( NULL ),
240 		mpContext		( NULL ),
241 		mpSwapFile		( NULL ),
242 		mpGfxLink		( NULL ),
243 		meType			( GRAPHIC_GDIMETAFILE ),
244 		mnDocFilePos	( 0UL ),
245         mnSizeBytes     ( 0UL ),
246 		mnRefCount		( 1UL ),
247 		mbSwapOut		( sal_False ),
248 		mbSwapUnderway	( sal_False )
249 {
250 }
251 
252 // ------------------------------------------------------------------------
253 
254 ImpGraphic::~ImpGraphic()
255 {
256     ImplClear();
257 
258     if( (sal_uLong) mpContext > 1UL )
259         delete mpContext;
260 }
261 
262 // ------------------------------------------------------------------------
263 
264 ImpGraphic& ImpGraphic::operator=( const ImpGraphic& rImpGraphic )
265 {
266     if( &rImpGraphic != this )
267 	{
268 		if( !mbSwapUnderway )
269 			ImplClear();
270 
271 		maMetaFile = rImpGraphic.maMetaFile;
272 		meType = rImpGraphic.meType;
273         mnSizeBytes = rImpGraphic.mnSizeBytes;
274 
275 		delete mpAnimation;
276 
277 		if ( rImpGraphic.mpAnimation )
278 		{
279 			mpAnimation = new Animation( *rImpGraphic.mpAnimation );
280 			maEx = mpAnimation->GetBitmapEx();
281 		}
282 		else
283 		{
284 			mpAnimation = NULL;
285 			maEx = rImpGraphic.maEx;
286 		}
287 
288 		if( !mbSwapUnderway )
289 		{
290 			maDocFileURLStr = rImpGraphic.maDocFileURLStr;
291 			mnDocFilePos = rImpGraphic.mnDocFilePos;
292 			mbSwapOut = rImpGraphic.mbSwapOut;
293 			mpSwapFile = rImpGraphic.mpSwapFile;
294 
295 			if( mpSwapFile )
296 				mpSwapFile->nRefCount++;
297 		}
298 
299 		delete mpGfxLink;
300 
301 		if( rImpGraphic.mpGfxLink )
302 			mpGfxLink = new GfxLink( *rImpGraphic.mpGfxLink );
303 		else
304 			mpGfxLink = NULL;
305 	}
306 
307 	return *this;
308 }
309 
310 // ------------------------------------------------------------------------
311 
312 sal_Bool ImpGraphic::operator==( const ImpGraphic& rImpGraphic ) const
313 {
314 	sal_Bool bRet = sal_False;
315 
316 	if( this == &rImpGraphic )
317 		bRet = sal_True;
318 	else if( !ImplIsSwapOut() && ( rImpGraphic.meType == meType ) )
319 	{
320 		switch( meType )
321 		{
322 			case( GRAPHIC_NONE ):
323 				bRet = sal_True;
324 			break;
325 
326 			case( GRAPHIC_GDIMETAFILE ):
327 			{
328 				if( rImpGraphic.maMetaFile == maMetaFile )
329 					bRet = sal_True;
330 			}
331 			break;
332 
333 			case( GRAPHIC_BITMAP ):
334 			{
335 				if( mpAnimation )
336 				{
337 					if( rImpGraphic.mpAnimation && ( *rImpGraphic.mpAnimation == *mpAnimation ) )
338 						bRet = sal_True;
339 				}
340 				else if( !rImpGraphic.mpAnimation && ( rImpGraphic.maEx == maEx ) )
341 					bRet = sal_True;
342 			}
343 			break;
344 
345 			default:
346 			break;
347 		}
348 	}
349 
350 	return bRet;
351 }
352 
353 // ------------------------------------------------------------------------
354 
355 void ImpGraphic::ImplClearGraphics( sal_Bool bCreateSwapInfo )
356 {
357 	if( bCreateSwapInfo && !ImplIsSwapOut() )
358 	{
359 		maSwapInfo.maPrefMapMode = ImplGetPrefMapMode();
360 		maSwapInfo.maPrefSize = ImplGetPrefSize();
361 	}
362 
363     maEx.Clear();
364 	maMetaFile.Clear();
365 
366     if( mpAnimation )
367     {
368         mpAnimation->Clear();
369         delete mpAnimation;
370         mpAnimation = NULL;
371     }
372 
373 	if( mpGfxLink )
374 	{
375 		delete mpGfxLink;
376 		mpGfxLink = NULL;
377 	}
378 }
379 
380 // ------------------------------------------------------------------------
381 
382 void ImpGraphic::ImplClear()
383 {
384     if( mpSwapFile )
385     {
386         if( mpSwapFile->nRefCount > 1 )
387             mpSwapFile->nRefCount--;
388         else
389         {
390 			try
391 			{
392 				::ucbhelper::Content aCnt( mpSwapFile->aSwapURL.GetMainURL( INetURLObject::NO_DECODE ),
393 									 ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
394 
395 				aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
396 									 ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
397 			}
398 			catch( const ::com::sun::star::ucb::ContentCreationException& )
399 			{
400 			}
401 			catch( const ::com::sun::star::uno::RuntimeException& )
402 			{
403 			}
404 			catch( const ::com::sun::star::ucb::CommandAbortedException& )
405 			{
406 			}
407         	catch( const ::com::sun::star::uno::Exception& )
408 		    {
409 		    }
410 
411             delete mpSwapFile;
412         }
413 
414         mpSwapFile = NULL;
415     }
416 
417     mbSwapOut = sal_False;
418     mnDocFilePos = 0UL;
419     maDocFileURLStr.Erase();
420 
421     // cleanup
422 	ImplClearGraphics( sal_False );
423     meType = GRAPHIC_NONE;
424     mnSizeBytes = 0;
425 }
426 
427 // ------------------------------------------------------------------------
428 
429 GraphicType ImpGraphic::ImplGetType() const
430 {
431 	return meType;
432 }
433 
434 // ------------------------------------------------------------------------
435 
436 void ImpGraphic::ImplSetDefaultType()
437 {
438 	ImplClear();
439 	meType = GRAPHIC_DEFAULT;
440 }
441 
442 // ------------------------------------------------------------------------
443 
444 sal_Bool ImpGraphic::ImplIsSupportedGraphic() const
445 {
446 	return( meType != GRAPHIC_NONE );
447 }
448 
449 // ------------------------------------------------------------------------
450 
451 sal_Bool ImpGraphic::ImplIsTransparent() const
452 {
453 	sal_Bool bRet;
454 
455     if( meType == GRAPHIC_BITMAP )
456 		bRet = ( mpAnimation ? mpAnimation->IsTransparent() : maEx.IsTransparent() );
457     else
458 		bRet = sal_True;
459 
460 	return bRet;
461 }
462 
463 // ------------------------------------------------------------------------
464 
465 sal_Bool ImpGraphic::ImplIsAlpha() const
466 {
467 	sal_Bool bRet;
468 
469     if( meType == GRAPHIC_BITMAP )
470 		bRet = ( NULL == mpAnimation ) && maEx.IsAlpha();
471     else
472 		bRet = sal_False;
473 
474 	return bRet;
475 }
476 
477 // ------------------------------------------------------------------------
478 
479 sal_Bool ImpGraphic::ImplIsAnimated() const
480 {
481 	return( mpAnimation != NULL );
482 }
483 
484 // ------------------------------------------------------------------------
485 
486 sal_Bool ImpGraphic::ImplIsEPS() const
487 {
488     return( ( meType == GRAPHIC_GDIMETAFILE ) &&
489             ( maMetaFile.GetActionCount() > 0 ) &&
490             ( maMetaFile.GetAction( 0 )->GetType() == META_EPS_ACTION ) );
491 }
492 
493 // ------------------------------------------------------------------------
494 
495 sal_Bool ImpGraphic::ImplIsRenderGraphic() const
496 {
497     return( ( GRAPHIC_GDIMETAFILE == meType ) &&
498             ( 1 == maMetaFile.GetActionCount() ) &&
499             ( META_RENDERGRAPHIC_ACTION == maMetaFile.GetAction( 0 )->GetType() ) );
500 }
501 
502 // ------------------------------------------------------------------------
503 
504 sal_Bool ImpGraphic::ImplHasRenderGraphic() const
505 {
506     sal_Bool bRet = sal_False;
507 
508     if( GRAPHIC_GDIMETAFILE == meType )
509     {
510         GDIMetaFile& rMtf = const_cast< ImpGraphic* >( this )->maMetaFile;
511 
512         for( MetaAction* pAct = rMtf.FirstAction(); pAct && !bRet; pAct = rMtf.NextAction() )
513         {
514             if( META_RENDERGRAPHIC_ACTION == pAct->GetType() )
515             {
516                 bRet = sal_True;
517             }
518         }
519 
520         rMtf.WindStart();
521     }
522 
523     return( bRet );
524 }
525 
526 // ------------------------------------------------------------------------
527 
528 Bitmap ImpGraphic::ImplGetBitmap(const GraphicConversionParameters& rParameters) const
529 {
530     Bitmap aRetBmp;
531 
532     if( meType == GRAPHIC_BITMAP )
533     {
534 		const BitmapEx& rRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx );
535 		const Color		aReplaceColor( COL_WHITE );
536 
537 		aRetBmp = rRetBmpEx.GetBitmap( &aReplaceColor );
538 
539         if(rParameters.getSizePixel().Width() || rParameters.getSizePixel().Height())
540             aRetBmp.Scale(rParameters.getSizePixel());
541     }
542     else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() )
543     {
544         // use corner points of graphic to determine the pixel
545         // extent of the graphic (rounding errors are possible else)
546         VirtualDevice	aVDev;
547 	    const Point     aNullPt;
548         const Point     aTLPix( aVDev.LogicToPixel( aNullPt, maMetaFile.GetPrefMapMode() ) );
549         const Point     aBRPix( aVDev.LogicToPixel( Point( maMetaFile.GetPrefSize().Width() - 1, maMetaFile.GetPrefSize().Height() - 1 ), maMetaFile.GetPrefMapMode() ) );
550         Size            aDrawSize( aVDev.LogicToPixel( maMetaFile.GetPrefSize(), maMetaFile.GetPrefMapMode() ) );
551         Size			aSizePix( labs( aBRPix.X() - aTLPix.X() ) + 1, labs( aBRPix.Y() - aTLPix.Y() ) + 1 );
552 
553         if(rParameters.getSizePixel().Width() && rParameters.getSizePixel().Height())
554         {
555             aDrawSize.Width() = FRound((double)rParameters.getSizePixel().Width() *
556                 (double)aDrawSize.Width() / (double)aSizePix.Width());
557             aDrawSize.Height() = FRound((double)rParameters.getSizePixel().Height() *
558                 (double)aDrawSize.Height() / (double)aSizePix.Height());
559 
560             aSizePix = rParameters.getSizePixel();
561         }
562 
563 		if( aSizePix.Width() && aSizePix.Height() && !rParameters.getUnlimitedSize()
564             && (aSizePix.Width() > GRAPHIC_MTFTOBMP_MAXEXT || aSizePix.Height() > GRAPHIC_MTFTOBMP_MAXEXT))
565 		{
566 			const Size  aOldSizePix( aSizePix );
567             double      fWH = (double) aSizePix.Width() / aSizePix.Height();
568 
569 			if( fWH <= 1.0 )
570 				aSizePix.Width() = FRound( GRAPHIC_MTFTOBMP_MAXEXT * fWH ), aSizePix.Height() = GRAPHIC_MTFTOBMP_MAXEXT;
571 			else
572 				aSizePix.Width() = GRAPHIC_MTFTOBMP_MAXEXT, aSizePix.Height() = FRound(  GRAPHIC_MTFTOBMP_MAXEXT / fWH );
573 
574             aDrawSize.Width() = FRound( ( (double) aDrawSize.Width() * aSizePix.Width() ) / aOldSizePix.Width() );
575             aDrawSize.Height() = FRound( ( (double) aDrawSize.Height() * aSizePix.Height() ) / aOldSizePix.Height() );
576 		}
577 
578 		if( aVDev.SetOutputSizePixel( aSizePix ) )
579         {
580             if(rParameters.getAntiAliase())
581             {
582                 aVDev.SetAntialiasing(aVDev.GetAntialiasing() | ANTIALIASING_ENABLE_B2DDRAW);
583             }
584 
585             if(rParameters.getSnapHorVerLines())
586             {
587                 aVDev.SetAntialiasing(aVDev.GetAntialiasing() | ANTIALIASING_PIXELSNAPHAIRLINE);
588             }
589 
590             ImplDraw( &aVDev, aNullPt, aDrawSize );
591             aRetBmp =  aVDev.GetBitmap( aNullPt, aVDev.GetOutputSizePixel() );
592         }
593     }
594 
595 	if( !!aRetBmp )
596 	{
597 		aRetBmp.SetPrefMapMode( ImplGetPrefMapMode() );
598 		aRetBmp.SetPrefSize( ImplGetPrefSize() );
599 	}
600 
601     return aRetBmp;
602 }
603 
604 // ------------------------------------------------------------------------
605 
606 BitmapEx ImpGraphic::ImplGetBitmapEx(const GraphicConversionParameters& rParameters) const
607 {
608     BitmapEx aRetBmpEx;
609 
610     if( meType == GRAPHIC_BITMAP )
611     {
612 		aRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx );
613 
614         if(rParameters.getSizePixel().Width() || rParameters.getSizePixel().Height())
615             aRetBmpEx.Scale(rParameters.getSizePixel());
616     }
617     else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() )
618     {
619 		const ImpGraphic aMonoMask( maMetaFile.GetMonochromeMtf( COL_BLACK ) );
620 		aRetBmpEx = BitmapEx(ImplGetBitmap(rParameters), aMonoMask.ImplGetBitmap(rParameters));
621     }
622 
623     return aRetBmpEx;
624 }
625 
626 // ------------------------------------------------------------------------
627 
628 Animation ImpGraphic::ImplGetAnimation() const
629 {
630 	Animation aAnimation;
631 
632 	if( mpAnimation )
633 		aAnimation = *mpAnimation;
634 
635 	return aAnimation;
636 }
637 
638 // ------------------------------------------------------------------------
639 
640 ::vcl::RenderGraphic ImpGraphic::ImplGetRenderGraphic() const
641 {
642     ::vcl::RenderGraphic aRet;
643 
644     if( ImplIsRenderGraphic() )
645         aRet = static_cast< MetaRenderGraphicAction* >( maMetaFile.GetAction( 0 ) )->GetRenderGraphic();
646 
647     return( aRet );
648 }
649 
650 // ------------------------------------------------------------------------
651 
652 const GDIMetaFile& ImpGraphic::ImplGetGDIMetaFile() const
653 {
654 	return maMetaFile;
655 }
656 
657 // ------------------------------------------------------------------------
658 
659 Size ImpGraphic::ImplGetPrefSize() const
660 {
661 	Size aSize;
662 
663 	if( ImplIsSwapOut() )
664 		aSize = maSwapInfo.maPrefSize;
665 	else
666 	{
667 		switch( meType )
668 		{
669 			case( GRAPHIC_NONE ):
670 			case( GRAPHIC_DEFAULT ):
671 			break;
672 
673 			case( GRAPHIC_BITMAP ):
674 			{
675 				aSize = maEx.GetPrefSize();
676 
677 				if( !aSize.Width() || !aSize.Height() )
678 					aSize = maEx.GetSizePixel();
679 			}
680 			break;
681 
682 			default:
683 			{
684 				if( ImplIsSupportedGraphic() )
685 				  aSize = maMetaFile.GetPrefSize();
686 			}
687 			break;
688 		}
689 	}
690 
691 	return aSize;
692 }
693 
694 // ------------------------------------------------------------------------
695 
696 void ImpGraphic::ImplSetPrefSize( const Size& rPrefSize )
697 {
698     switch( meType )
699     {
700         case( GRAPHIC_NONE ):
701         case( GRAPHIC_DEFAULT ):
702 		break;
703 
704 		case( GRAPHIC_BITMAP ):
705             // #108077# Push through pref size to animation object,
706             // will be lost on copy otherwise
707             if( ImplIsAnimated() )
708                 const_cast< BitmapEx& >(mpAnimation->GetBitmapEx()).SetPrefSize( rPrefSize );
709 
710             maEx.SetPrefSize( rPrefSize );
711 		break;
712 
713         default:
714 		{
715 			if( ImplIsSupportedGraphic() )
716 				maMetaFile.SetPrefSize( rPrefSize );
717 		}
718 		break;
719     }
720 }
721 
722 // ------------------------------------------------------------------------
723 
724 MapMode ImpGraphic::ImplGetPrefMapMode() const
725 {
726 	MapMode aMapMode;
727 
728 	if( ImplIsSwapOut() )
729 		aMapMode = maSwapInfo.maPrefMapMode;
730 	else
731 	{
732 		switch( meType )
733 		{
734 			case( GRAPHIC_NONE ):
735 			case( GRAPHIC_DEFAULT ):
736 			break;
737 
738 			case( GRAPHIC_BITMAP ):
739 			{
740 				const Size aSize( maEx.GetPrefSize() );
741 
742 				if ( aSize.Width() && aSize.Height() )
743 					aMapMode = maEx.GetPrefMapMode();
744 			}
745 			break;
746 
747 			default:
748 			{
749 				if( ImplIsSupportedGraphic() )
750 					return maMetaFile.GetPrefMapMode();
751 			}
752 			break;
753 		}
754 	}
755 
756 	return aMapMode;
757 }
758 
759 // ------------------------------------------------------------------------
760 
761 void ImpGraphic::ImplSetPrefMapMode( const MapMode& rPrefMapMode )
762 {
763     switch( meType )
764     {
765         case( GRAPHIC_NONE ):
766         case( GRAPHIC_DEFAULT ):
767 		break;
768 
769 		case( GRAPHIC_BITMAP ):
770             // #108077# Push through pref mapmode to animation object,
771             // will be lost on copy otherwise
772             if( ImplIsAnimated() )
773                 const_cast< BitmapEx& >(mpAnimation->GetBitmapEx()).SetPrefMapMode( rPrefMapMode );
774 
775 			maEx.SetPrefMapMode( rPrefMapMode );
776 		break;
777 
778         default:
779 		{
780 			if( ImplIsSupportedGraphic() )
781 				maMetaFile.SetPrefMapMode( rPrefMapMode );
782 		}
783 		break;
784     }
785 }
786 
787 // ------------------------------------------------------------------------
788 
789 sal_uLong ImpGraphic::ImplGetSizeBytes() const
790 {
791     if( 0 == mnSizeBytes )
792     {
793         if( meType == GRAPHIC_BITMAP )
794 	    {
795             mnSizeBytes = mpAnimation ? mpAnimation->GetSizeBytes() : maEx.GetSizeBytes();
796         }
797         else if( meType == GRAPHIC_GDIMETAFILE )
798         {
799             mnSizeBytes = maMetaFile.GetSizeBytes();
800         }
801     }
802 
803 	return( mnSizeBytes );
804 }
805 
806 // ------------------------------------------------------------------------
807 
808 void ImpGraphic::ImplDraw( OutputDevice* pOutDev, const Point& rDestPt ) const
809 {
810     if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
811 	{
812 		switch( meType )
813 		{
814 			case( GRAPHIC_DEFAULT ):
815 			break;
816 
817 			case( GRAPHIC_BITMAP ):
818 			{
819 				if ( mpAnimation )
820 					mpAnimation->Draw( pOutDev, rDestPt );
821 				else
822 					maEx.Draw( pOutDev, rDestPt );
823 			}
824 			break;
825 
826 			default:
827 				ImplDraw( pOutDev, rDestPt, maMetaFile.GetPrefSize() );
828 			break;
829 		}
830 	}
831 }
832 
833 // ------------------------------------------------------------------------
834 
835 void ImpGraphic::ImplDraw( OutputDevice* pOutDev,
836 						   const Point& rDestPt, const Size& rDestSize ) const
837 {
838     if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
839 	{
840 		switch( meType )
841 		{
842 			case( GRAPHIC_DEFAULT ):
843 			break;
844 
845 			case( GRAPHIC_BITMAP ):
846 			{
847 				if( mpAnimation )
848 					mpAnimation->Draw( pOutDev, rDestPt, rDestSize );
849 				else
850 					maEx.Draw( pOutDev, rDestPt, rDestSize );
851 			}
852 			break;
853 
854 			default:
855 			{
856 				( (ImpGraphic*) this )->maMetaFile.WindStart();
857 				( (ImpGraphic*) this )->maMetaFile.Play( pOutDev, rDestPt, rDestSize );
858 				( (ImpGraphic*) this )->maMetaFile.WindStart();
859 			}
860 			break;
861 		}
862 	}
863 }
864 
865 // ------------------------------------------------------------------------
866 
867 void ImpGraphic::ImplStartAnimation( OutputDevice* pOutDev,
868 									 const Point& rDestPt,
869 									 long nExtraData,
870 									 OutputDevice* pFirstFrameOutDev )
871 {
872     if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation )
873 	    mpAnimation->Start( pOutDev, rDestPt, nExtraData, pFirstFrameOutDev );
874 }
875 
876 // ------------------------------------------------------------------------
877 
878 void ImpGraphic::ImplStartAnimation( OutputDevice* pOutDev, const Point& rDestPt,
879 									 const Size& rDestSize, long nExtraData,
880 									 OutputDevice* pFirstFrameOutDev )
881 {
882     if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation )
883 	    mpAnimation->Start( pOutDev, rDestPt, rDestSize, nExtraData, pFirstFrameOutDev );
884 }
885 
886 // ------------------------------------------------------------------------
887 
888 void ImpGraphic::ImplStopAnimation( OutputDevice* pOutDev, long nExtraData )
889 {
890     if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation )
891 	    mpAnimation->Stop( pOutDev, nExtraData );
892 }
893 
894 // ------------------------------------------------------------------------
895 
896 void ImpGraphic::ImplSetAnimationNotifyHdl( const Link& rLink )
897 {
898 	if( mpAnimation )
899 		mpAnimation->SetNotifyHdl( rLink );
900 }
901 
902 // ------------------------------------------------------------------------
903 
904 Link ImpGraphic::ImplGetAnimationNotifyHdl() const
905 {
906 	Link aLink;
907 
908 	if( mpAnimation )
909 		aLink = mpAnimation->GetNotifyHdl();
910 
911 	return aLink;
912 }
913 
914 // ------------------------------------------------------------------------
915 
916 sal_uLong ImpGraphic::ImplGetAnimationLoopCount() const
917 {
918 	return( mpAnimation ? mpAnimation->GetLoopCount() : 0UL );
919 }
920 
921 // ------------------------------------------------------------------------
922 
923 void ImpGraphic::ImplResetAnimationLoopCount()
924 {
925 	if( mpAnimation )
926 		mpAnimation->ResetLoopCount();
927 }
928 
929 // ------------------------------------------------------------------------
930 
931 List* ImpGraphic::ImplGetAnimationInfoList() const
932 {
933 	return( mpAnimation ? mpAnimation->GetAInfoList() : NULL );
934 }
935 
936 // ------------------------------------------------------------------------
937 
938 GraphicReader* ImpGraphic::ImplGetContext()
939 {
940 	return mpContext;
941 }
942 
943 // ------------------------------------------------------------------------
944 
945 void ImpGraphic::ImplSetContext( GraphicReader* pReader )
946 {
947 	mpContext = pReader;
948 }
949 
950 // ------------------------------------------------------------------------
951 
952 void ImpGraphic::ImplSetDocFileName( const String& rName, sal_uLong nFilePos )
953 {
954 	const INetURLObject aURL( rName );
955 
956 	DBG_ASSERT( !rName.Len() || ( aURL.GetProtocol() != INET_PROT_NOT_VALID ), "Graphic::SetDocFileName(...): invalid URL" );
957 
958 	maDocFileURLStr = aURL.GetMainURL( INetURLObject::NO_DECODE );
959 	mnDocFilePos = nFilePos;
960 }
961 
962 // ------------------------------------------------------------------------
963 
964 const String& ImpGraphic::ImplGetDocFileName() const
965 {
966 	return maDocFileURLStr;
967 }
968 
969 // ------------------------------------------------------------------------
970 
971 sal_uLong ImpGraphic::ImplGetDocFilePos() const
972 {
973 	return mnDocFilePos;
974 }
975 
976 // ------------------------------------------------------------------------
977 
978 sal_Bool ImpGraphic::ImplReadEmbedded( SvStream& rIStm, sal_Bool bSwap )
979 {
980 	MapMode			aMapMode;
981 	Size			aSize;
982     const sal_uLong		nStartPos = rIStm.Tell();
983 	sal_uInt32		nId;
984 	sal_uLong			nHeaderLen;
985 	long			nType;
986 	long			nLen;
987     const sal_uInt16	nOldFormat = rIStm.GetNumberFormatInt();
988 	sal_Bool			bRet = sal_False;
989 
990     if( !mbSwapUnderway )
991     {
992         const String		aTempURLStr( maDocFileURLStr );
993         const sal_uLong			nTempPos = mnDocFilePos;
994 
995 		ImplClear();
996 
997         maDocFileURLStr = aTempURLStr;
998         mnDocFilePos = nTempPos;
999     }
1000 
1001     rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1002 	rIStm >> nId;
1003 
1004 	// check version
1005 	if( GRAPHIC_FORMAT_50 == nId )
1006 	{
1007 		// read new style header
1008 		VersionCompat* pCompat = new VersionCompat( rIStm, STREAM_READ );
1009 
1010 		rIStm >> nType;
1011 		rIStm >> nLen;
1012 		rIStm >> aSize;
1013 		rIStm >> aMapMode;
1014 
1015 		delete pCompat;
1016 	}
1017 	else
1018 	{
1019 		// read old style header
1020 	    long nWidth, nHeight;
1021 	    long nMapMode, nScaleNumX, nScaleDenomX;
1022 		long nScaleNumY, nScaleDenomY, nOffsX, nOffsY;
1023 
1024 		rIStm.SeekRel( -4L );
1025 
1026 		rIStm >> nType >> nLen >> nWidth >> nHeight;
1027 		rIStm >> nMapMode >> nScaleNumX >> nScaleDenomX >> nScaleNumY;
1028 		rIStm >> nScaleDenomY >> nOffsX >> nOffsY;
1029 
1030 		// swapped
1031 		if( nType > 100L )
1032 		{
1033 			nType = SWAPLONG( nType );
1034 			nLen = SWAPLONG( nLen );
1035 			nWidth = SWAPLONG( nWidth );
1036 			nHeight = SWAPLONG( nHeight );
1037 			nMapMode = SWAPLONG( nMapMode );
1038 			nScaleNumX = SWAPLONG( nScaleNumX );
1039 			nScaleDenomX = SWAPLONG( nScaleDenomX );
1040 			nScaleNumY = SWAPLONG( nScaleNumY );
1041 			nScaleDenomY = SWAPLONG( nScaleDenomY );
1042 			nOffsX = SWAPLONG( nOffsX );
1043 			nOffsY = SWAPLONG( nOffsY );
1044 		}
1045 
1046 		aSize = Size( nWidth, nHeight );
1047 		aMapMode = MapMode( (MapUnit) nMapMode, Point( nOffsX, nOffsY ),
1048 							Fraction( nScaleNumX, nScaleDenomX ),
1049 							Fraction( nScaleNumY, nScaleDenomY ) );
1050 	}
1051 
1052 	nHeaderLen = rIStm.Tell() - nStartPos;
1053     meType = (GraphicType) nType;
1054 
1055 	if( meType )
1056 	{
1057 		if( meType == GRAPHIC_BITMAP )
1058 		{
1059 			maEx.aBitmapSize = aSize;
1060 
1061 			if( aMapMode != MapMode() )
1062 			{
1063 				maEx.SetPrefMapMode( aMapMode );
1064 				maEx.SetPrefSize( aSize );
1065 			}
1066 		}
1067 		else
1068 		{
1069 			maMetaFile.SetPrefMapMode( aMapMode );
1070 			maMetaFile.SetPrefSize( aSize );
1071 		}
1072 
1073 		if( bSwap )
1074 		{
1075 			if( maDocFileURLStr.Len() )
1076 			{
1077 				rIStm.Seek( nStartPos + nHeaderLen + nLen );
1078 				bRet = mbSwapOut = sal_True;
1079 			}
1080 			else
1081 			{
1082 				::utl::TempFile		aTempFile;
1083 				const INetURLObject	aTmpURL( aTempFile.GetURL() );
1084 
1085 				if( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ).getLength() )
1086 				{
1087 					SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
1088 
1089 					if( pOStm )
1090 					{
1091 						sal_uLong	nFullLen = nHeaderLen + nLen;
1092 						sal_uLong	nPartLen = Min( nFullLen, (sal_uLong) GRAPHIC_MAXPARTLEN );
1093 						sal_uInt8*	pBuffer = (sal_uInt8*) rtl_allocateMemory( nPartLen );
1094 
1095 		      			pOStm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1096 
1097 						if( pBuffer )
1098 						{
1099 							rIStm.Seek( nStartPos );
1100 
1101 							while( nFullLen )
1102 							{
1103 								rIStm.Read( (char*) pBuffer, nPartLen );
1104 								pOStm->Write( (char*) pBuffer, nPartLen );
1105 
1106 								nFullLen -= nPartLen;
1107 
1108 								if( nFullLen < GRAPHIC_MAXPARTLEN )
1109 									nPartLen = nFullLen;
1110 							}
1111 
1112 							rtl_freeMemory( pBuffer );
1113 							sal_uLong nReadErr = rIStm.GetError(), nWriteErr = pOStm->GetError();
1114 							delete pOStm, pOStm = NULL;
1115 
1116 							if( !nReadErr && !nWriteErr )
1117 							{
1118 								bRet = mbSwapOut = sal_True;
1119 								mpSwapFile = new ImpSwapFile;
1120 								mpSwapFile->nRefCount = 1;
1121 								mpSwapFile->aSwapURL = aTmpURL;
1122 							}
1123 							else
1124 							{
1125 								try
1126 								{
1127 									::ucbhelper::Content aCnt( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ),
1128 														 ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
1129 
1130 									aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
1131 														 ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
1132 								}
1133 								catch( const ::com::sun::star::ucb::ContentCreationException& )
1134 								{
1135 								}
1136 								catch( const ::com::sun::star::uno::RuntimeException& )
1137 								{
1138 								}
1139 								catch( const ::com::sun::star::ucb::CommandAbortedException& )
1140 								{
1141             					}
1142         		                catch( const ::com::sun::star::uno::Exception& )
1143 		                        {
1144 		                        }
1145 							}
1146 						}
1147 
1148 						delete pOStm;
1149 					}
1150 				}
1151 			}
1152 		}
1153 		else if( meType == GRAPHIC_BITMAP || meType == GRAPHIC_GDIMETAFILE )
1154 		{
1155 			rIStm >> *this;
1156 			bRet = ( rIStm.GetError() == 0UL );
1157 		}
1158 		else if( meType >= SYS_WINMETAFILE && meType <= SYS_MACMETAFILE )
1159 		{
1160 			Graphic aSysGraphic;
1161 			sal_uLong	nCvtType;
1162 
1163 			switch( sal::static_int_cast<sal_uLong>(meType) )
1164 			{
1165 				case( SYS_WINMETAFILE ):
1166 				case( SYS_WNTMETAFILE ): nCvtType = CVT_WMF; break;
1167 				case( SYS_OS2METAFILE ): nCvtType = CVT_MET; break;
1168 				case( SYS_MACMETAFILE ): nCvtType = CVT_PCT; break;
1169 
1170 				default:
1171 					nCvtType = CVT_UNKNOWN;
1172 				break;
1173 			}
1174 
1175 			if( nType && GraphicConverter::Import( rIStm, aSysGraphic, nCvtType ) == ERRCODE_NONE )
1176 			{
1177 				*this = ImpGraphic( aSysGraphic.GetGDIMetaFile() );
1178 				bRet = ( rIStm.GetError() == 0UL );
1179 			}
1180 			else
1181 				meType = GRAPHIC_DEFAULT;
1182 		}
1183 
1184 		if( bRet )
1185 		{
1186 			ImplSetPrefMapMode( aMapMode );
1187 			ImplSetPrefSize( aSize );
1188 		}
1189 	}
1190 	else
1191 		bRet = sal_True;
1192 
1193 	rIStm.SetNumberFormatInt( nOldFormat );
1194 
1195 	return bRet;
1196 }
1197 
1198 // ------------------------------------------------------------------------
1199 
1200 sal_Bool ImpGraphic::ImplWriteEmbedded( SvStream& rOStm )
1201 {
1202 	sal_Bool bRet = sal_False;
1203 
1204 	if( ( meType != GRAPHIC_NONE ) && ( meType != GRAPHIC_DEFAULT ) && !ImplIsSwapOut() )
1205 	{
1206 		const MapMode	aMapMode( ImplGetPrefMapMode() );
1207 		const Size		aSize( ImplGetPrefSize() );
1208 		const sal_uInt16	nOldFormat = rOStm.GetNumberFormatInt();
1209 		sal_uLong			nDataFieldPos;
1210 
1211 		rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1212 
1213 		// write correct version ( old style/new style header )
1214 		if( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 )
1215 		{
1216 			// write ID for new format (5.0)
1217 			rOStm << GRAPHIC_FORMAT_50;
1218 
1219 			// write new style header
1220 			VersionCompat* pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 );
1221 
1222 			rOStm << (long) meType;
1223 
1224 			// data size is updated later
1225 			nDataFieldPos = rOStm.Tell();
1226 			rOStm << (long) 0;
1227 
1228 			rOStm << aSize;
1229 			rOStm << aMapMode;
1230 
1231 			delete pCompat;
1232 		}
1233 		else
1234 		{
1235 			// write old style (<=4.0) header
1236 			rOStm << (long) meType;
1237 
1238 			// data size is updated later
1239 			nDataFieldPos = rOStm.Tell();
1240 			rOStm << (long) 0;
1241 
1242 			rOStm << (long) aSize.Width();
1243 			rOStm << (long) aSize.Height();
1244 			rOStm << (long) aMapMode.GetMapUnit();
1245 			rOStm << (long) aMapMode.GetScaleX().GetNumerator();
1246 			rOStm << (long) aMapMode.GetScaleX().GetDenominator();
1247 			rOStm << (long) aMapMode.GetScaleY().GetNumerator();
1248 			rOStm << (long) aMapMode.GetScaleY().GetDenominator();
1249 			rOStm << (long) aMapMode.GetOrigin().X();
1250 			rOStm << (long) aMapMode.GetOrigin().Y();
1251 		}
1252 
1253 		// write data block
1254 		if( !rOStm.GetError() )
1255 		{
1256 			const sal_uLong nDataStart = rOStm.Tell();
1257 
1258 			if( ImplIsSupportedGraphic() )
1259 				rOStm << *this;
1260 
1261 			if( !rOStm.GetError() )
1262 			{
1263 				const sal_uLong nStmPos2 = rOStm.Tell();
1264 				rOStm.Seek( nDataFieldPos );
1265 				rOStm << (long) ( nStmPos2 - nDataStart );
1266 				rOStm.Seek( nStmPos2 );
1267 				bRet = sal_True;
1268 			}
1269 		}
1270 
1271 		rOStm.SetNumberFormatInt( nOldFormat );
1272 	}
1273 
1274 	return bRet;
1275 }
1276 
1277 // ------------------------------------------------------------------------
1278 
1279 sal_Bool ImpGraphic::ImplSwapOut()
1280 {
1281 	sal_Bool bRet = sal_False;
1282 
1283     if( !ImplIsSwapOut() )
1284 	{
1285 		if( !maDocFileURLStr.Len() )
1286 		{
1287 			::utl::TempFile		aTempFile;
1288 			const INetURLObject	aTmpURL( aTempFile.GetURL() );
1289 
1290 			if( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ).getLength() )
1291 			{
1292 				SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
1293 
1294 				if( pOStm )
1295 				{
1296                     pOStm->SetVersion( SOFFICE_FILEFORMAT_50 );
1297 					pOStm->SetCompressMode( COMPRESSMODE_NATIVE );
1298 
1299 					if( ( bRet = ImplSwapOut( pOStm ) ) == sal_True )
1300 					{
1301 						mpSwapFile = new ImpSwapFile;
1302 						mpSwapFile->nRefCount = 1;
1303 						mpSwapFile->aSwapURL = aTmpURL;
1304 					}
1305 					else
1306 					{
1307 						delete pOStm, pOStm = NULL;
1308 
1309 						try
1310 						{
1311 							::ucbhelper::Content aCnt( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ),
1312 												 ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
1313 
1314 							aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
1315 												 ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
1316 						}
1317 						catch( const ::com::sun::star::ucb::ContentCreationException& )
1318 						{
1319 						}
1320 						catch( const ::com::sun::star::uno::RuntimeException& )
1321 						{
1322 						}
1323 						catch( const ::com::sun::star::ucb::CommandAbortedException& )
1324 						{
1325 						}
1326         		        catch( const ::com::sun::star::uno::Exception& )
1327 		                {
1328 		                }
1329 					}
1330 
1331 					delete pOStm;
1332 				}
1333 			}
1334 		}
1335 		else
1336 		{
1337 			ImplClearGraphics( sal_True );
1338 			bRet = mbSwapOut = sal_True;
1339 		}
1340 	}
1341 
1342     return bRet;
1343 }
1344 
1345 // ------------------------------------------------------------------------
1346 
1347 sal_Bool ImpGraphic::ImplSwapOut( SvStream* pOStm )
1348 {
1349 	sal_Bool bRet = sal_False;
1350 
1351     if( pOStm )
1352     {
1353         pOStm->SetBufferSize( GRAPHIC_STREAMBUFSIZE );
1354 
1355 		if( !pOStm->GetError() && ImplWriteEmbedded( *pOStm ) )
1356 		{
1357 			pOStm->Flush();
1358 
1359 			if( !pOStm->GetError() )
1360 			{
1361 				ImplClearGraphics( sal_True );
1362 				bRet = mbSwapOut = sal_True;
1363 			}
1364 		}
1365     }
1366 	else
1367 	{
1368 		ImplClearGraphics( sal_True );
1369 		bRet = mbSwapOut = sal_True;
1370 	}
1371 
1372     return bRet;
1373 }
1374 
1375 // ------------------------------------------------------------------------
1376 
1377 sal_Bool ImpGraphic::ImplSwapIn()
1378 {
1379     sal_Bool bRet = sal_False;
1380 
1381 	if( ImplIsSwapOut() )
1382 	{
1383 		String aSwapURL;
1384 
1385 		if( mpSwapFile )
1386 			aSwapURL = mpSwapFile->aSwapURL.GetMainURL( INetURLObject::NO_DECODE );
1387 		else
1388 			aSwapURL = maDocFileURLStr;
1389 
1390 		if( aSwapURL.Len() )
1391 		{
1392 			SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( aSwapURL, STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
1393 
1394 			if( pIStm )
1395 			{
1396                 pIStm->SetVersion( SOFFICE_FILEFORMAT_50 );
1397 				pIStm->SetCompressMode( COMPRESSMODE_NATIVE );
1398 
1399 				if( !mpSwapFile )
1400 					pIStm->Seek( mnDocFilePos );
1401 
1402 				bRet = ImplSwapIn( pIStm );
1403 				delete pIStm;
1404 
1405 				if( mpSwapFile )
1406 				{
1407 					if( mpSwapFile->nRefCount > 1 )
1408 						mpSwapFile->nRefCount--;
1409 					else
1410 					{
1411 						try
1412 						{
1413 							::ucbhelper::Content aCnt( aSwapURL,
1414 												 ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
1415 
1416 							aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
1417 												 ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
1418 						}
1419 						catch( const ::com::sun::star::ucb::ContentCreationException& )
1420 						{
1421 						}
1422 						catch( const ::com::sun::star::uno::RuntimeException& )
1423 						{
1424 						}
1425 						catch( const ::com::sun::star::ucb::CommandAbortedException& )
1426 						{
1427 						}
1428         		        catch( const ::com::sun::star::uno::Exception& )
1429 		                {
1430 		                }
1431 
1432 						delete mpSwapFile;
1433 					}
1434 
1435 					mpSwapFile = NULL;
1436 				}
1437 			}
1438 		}
1439 	}
1440 
1441     return bRet;
1442 }
1443 
1444 // ------------------------------------------------------------------------
1445 
1446 sal_Bool ImpGraphic::ImplSwapIn( SvStream* pIStm )
1447 {
1448 	sal_Bool bRet = sal_False;
1449 
1450     if( pIStm )
1451 	{
1452 		pIStm->SetBufferSize( GRAPHIC_STREAMBUFSIZE );
1453 
1454 		if( !pIStm->GetError() )
1455 		{
1456 			mbSwapUnderway = sal_True;
1457 			bRet = ImplReadEmbedded( *pIStm );
1458 			mbSwapUnderway = sal_False;
1459 
1460 			if( !bRet )
1461 				ImplClear();
1462 			else
1463 				mbSwapOut = sal_False;
1464 		}
1465 	}
1466 
1467     return bRet;
1468 }
1469 
1470 // ------------------------------------------------------------------------
1471 
1472 sal_Bool ImpGraphic::ImplIsSwapOut() const
1473 {
1474 	return mbSwapOut;
1475 }
1476 
1477 // ------------------------------------------------------------------------
1478 
1479 void ImpGraphic::ImplSetLink( const	GfxLink& rGfxLink )
1480 {
1481 	delete mpGfxLink;
1482 	mpGfxLink = new GfxLink( rGfxLink );
1483 
1484 	if( mpGfxLink->IsNative() )
1485 		mpGfxLink->SwapOut();
1486 }
1487 
1488 // ------------------------------------------------------------------------
1489 
1490 GfxLink ImpGraphic::ImplGetLink()
1491 {
1492 	return( mpGfxLink ? *mpGfxLink : GfxLink() );
1493 }
1494 
1495 // ------------------------------------------------------------------------
1496 
1497 sal_Bool ImpGraphic::ImplIsLink() const
1498 {
1499 	return ( mpGfxLink != NULL ) ? sal_True : sal_False;
1500 }
1501 
1502 // ------------------------------------------------------------------------
1503 
1504 sal_uLong ImpGraphic::ImplGetChecksum() const
1505 {
1506 	sal_uLong nRet = 0;
1507 
1508     if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
1509 	{
1510 		switch( meType )
1511 		{
1512 			case( GRAPHIC_DEFAULT ):
1513 			break;
1514 
1515 			case( GRAPHIC_BITMAP ):
1516 			{
1517 				if( mpAnimation )
1518 					nRet = mpAnimation->GetChecksum();
1519 				else
1520 					nRet = maEx.GetChecksum();
1521 			}
1522 			break;
1523 
1524 			default:
1525 				nRet = maMetaFile.GetChecksum();
1526 			break;
1527 		}
1528 	}
1529 
1530 	return nRet;
1531 }
1532 
1533 // ------------------------------------------------------------------------
1534 
1535 sal_Bool ImpGraphic::ImplExportNative( SvStream& rOStm ) const
1536 {
1537 	sal_Bool bResult = sal_False;
1538 
1539 	if( !rOStm.GetError() )
1540 	{
1541 		if( !ImplIsSwapOut() )
1542 		{
1543 			if( mpGfxLink && mpGfxLink->IsNative() )
1544 				bResult = mpGfxLink->ExportNative( rOStm );
1545 			else
1546 			{
1547 				rOStm << *this;
1548 				bResult = ( rOStm.GetError() == ERRCODE_NONE );
1549 			}
1550 		}
1551 		else
1552 			 rOStm.SetError( SVSTREAM_GENERALERROR );
1553 	}
1554 
1555 	return bResult;
1556 }
1557 
1558 // ------------------------------------------------------------------------
1559 
1560 SvStream& operator>>( SvStream& rIStm, ImpGraphic& rImpGraphic )
1561 {
1562 	if( !rIStm.GetError() )
1563 	{
1564 		const sal_uLong	nStmPos1 = rIStm.Tell();
1565 		sal_uInt32 nTmp;
1566 
1567 		if ( !rImpGraphic.mbSwapUnderway )
1568 			rImpGraphic.ImplClear();
1569 
1570 		// read Id
1571 		rIStm >> nTmp;
1572 
1573         // if there is no more data, avoid further expensive
1574         // reading which will create VDevs and other stuff, just to
1575         // read nothing. CAUTION: Eof is only true AFTER reading another
1576         // byte, a speciality of SvMemoryStream (!)
1577         if(!rIStm.GetError() && !rIStm.IsEof())
1578         {
1579 		    if( NATIVE_FORMAT_50 == nTmp )
1580 		    {
1581 			    Graphic			aGraphic;
1582 			    GfxLink			aLink;
1583 			    VersionCompat*	pCompat;
1584 
1585 			    // read compat info
1586 			    pCompat = new VersionCompat( rIStm, STREAM_READ );
1587 			    delete pCompat;
1588 
1589 			    rIStm >> aLink;
1590 
1591 			    // set dummy link to avoid creation of additional link after filtering;
1592 			    // we set a default link to avoid unnecessary swapping of native data
1593 			    aGraphic.SetLink( GfxLink() );
1594 
1595 			    if( !rIStm.GetError() && aLink.LoadNative( aGraphic ) )
1596 			    {
1597 				    // set link only, if no other link was set
1598 				    const sal_Bool bSetLink = ( rImpGraphic.mpGfxLink == NULL );
1599 
1600 				    // assign graphic
1601 				    rImpGraphic = *aGraphic.ImplGetImpGraphic();
1602 
1603                     if( aLink.IsPrefMapModeValid() )
1604                         rImpGraphic.ImplSetPrefMapMode( aLink.GetPrefMapMode() );
1605 
1606                     if( aLink.IsPrefSizeValid() )
1607                         rImpGraphic.ImplSetPrefSize( aLink.GetPrefSize() );
1608 
1609 				    if( bSetLink )
1610 					    rImpGraphic.ImplSetLink( aLink );
1611 			    }
1612 			    else
1613 			    {
1614 				    rIStm.Seek( nStmPos1 );
1615 				    rIStm.SetError( ERRCODE_IO_WRONGFORMAT );
1616 			    }
1617 		    }
1618 		    else
1619 		    {
1620 			    BitmapEx		aBmpEx;
1621 			    const sal_uInt16	nOldFormat = rIStm.GetNumberFormatInt();
1622 
1623 			    rIStm.SeekRel( -4 );
1624 			    rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1625 			    rIStm >> aBmpEx;
1626 
1627 			    if( !rIStm.GetError() )
1628 			    {
1629 				    sal_uInt32	nMagic1(0), nMagic2(0);
1630 				    sal_uLong	nActPos = rIStm.Tell();
1631 
1632 				    rIStm >> nMagic1 >> nMagic2;
1633 				    rIStm.Seek( nActPos );
1634 
1635 				    rImpGraphic = ImpGraphic( aBmpEx );
1636 
1637 				    if( !rIStm.GetError() && ( 0x5344414e == nMagic1 ) && ( 0x494d4931 == nMagic2 ) )
1638 				    {
1639 					    delete rImpGraphic.mpAnimation;
1640 					    rImpGraphic.mpAnimation = new Animation;
1641 					    rIStm >> *rImpGraphic.mpAnimation;
1642 
1643                         // #108077# manually set loaded BmpEx to Animation
1644                         // (which skips loading its BmpEx if already done)
1645                         rImpGraphic.mpAnimation->SetBitmapEx(aBmpEx);
1646 				    }
1647 				    else
1648 					    rIStm.ResetError();
1649 			    }
1650 			    else
1651 			    {
1652 				    GDIMetaFile aMtf;
1653 
1654 				    rIStm.Seek( nStmPos1 );
1655 				    rIStm.ResetError();
1656 				    rIStm >> aMtf;
1657 
1658 				    if( !rIStm.GetError() )
1659 					    rImpGraphic = aMtf;
1660 				    else
1661 					    rIStm.Seek( nStmPos1 );
1662 			    }
1663 
1664 			    rIStm.SetNumberFormatInt( nOldFormat );
1665 		    }
1666         }
1667 	}
1668 
1669     return rIStm;
1670 }
1671 
1672 // ------------------------------------------------------------------------
1673 
1674 SvStream& operator<<( SvStream& rOStm, const ImpGraphic& rImpGraphic )
1675 {
1676 	if( !rOStm.GetError() )
1677 	{
1678 		if( !rImpGraphic.ImplIsSwapOut() )
1679 		{
1680 			if( ( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 ) &&
1681 				( rOStm.GetCompressMode() & COMPRESSMODE_NATIVE ) &&
1682 				rImpGraphic.mpGfxLink && rImpGraphic.mpGfxLink->IsNative() )
1683 			{
1684 				VersionCompat* pCompat;
1685 
1686 				// native format
1687 				rOStm << NATIVE_FORMAT_50;
1688 
1689 				// write compat info
1690 				pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 );
1691 				delete pCompat;
1692 
1693                 rImpGraphic.mpGfxLink->SetPrefMapMode( rImpGraphic.ImplGetPrefMapMode() );
1694                 rImpGraphic.mpGfxLink->SetPrefSize( rImpGraphic.ImplGetPrefSize() );
1695 				rOStm << *rImpGraphic.mpGfxLink;
1696 			}
1697 			else
1698 			{
1699 				// own format
1700 				const sal_uInt16 nOldFormat = rOStm.GetNumberFormatInt();
1701 				rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1702 
1703 				switch( rImpGraphic.ImplGetType() )
1704 				{
1705 					case( GRAPHIC_NONE ):
1706 					case( GRAPHIC_DEFAULT ):
1707 					break;
1708 
1709 					case GRAPHIC_BITMAP:
1710 					{
1711 						if ( rImpGraphic.ImplIsAnimated() )
1712 							rOStm << *rImpGraphic.mpAnimation;
1713 						else
1714 							rOStm << rImpGraphic.maEx;
1715 					}
1716 					break;
1717 
1718 					default:
1719 					{
1720 						if( rImpGraphic.ImplIsSupportedGraphic() )
1721 							rOStm << rImpGraphic.maMetaFile;
1722 					}
1723 					break;
1724 				}
1725 
1726 				rOStm.SetNumberFormatInt( nOldFormat );
1727 			}
1728 		}
1729 		else
1730 			 rOStm.SetError( SVSTREAM_GENERALERROR );
1731 	}
1732 
1733     return rOStm;
1734 }
1735