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