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