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