xref: /trunk/main/vcl/source/gdi/impgraph.cxx (revision bb18ee55)
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         // calculate size
563         VirtualDevice aVDev;
564         Size aDrawSize(aVDev.LogicToPixel(maMetaFile.GetPrefSize(), maMetaFile.GetPrefMapMode()));
565 
566         if(rParameters.getSizePixel().Width() && rParameters.getSizePixel().Height())
567         {
568             // apply given size if exists
569             aDrawSize = rParameters.getSizePixel();
570         }
571 
572         if(aDrawSize.Width() && aDrawSize.Height() && !rParameters.getUnlimitedSize()
573             && (aDrawSize.Width() > GRAPHIC_MTFTOBMP_MAXEXT || aDrawSize.Height() > GRAPHIC_MTFTOBMP_MAXEXT))
574         {
575             // limit bitmap size to a maximum of GRAPHIC_MTFTOBMP_MAXEXT x GRAPHIC_MTFTOBMP_MAXEXT
576             double fWH((double)aDrawSize.Width() / (double)aDrawSize.Height());
577 
578             if(fWH <= 1.0)
579             {
580                 aDrawSize.setWidth(basegfx::fround(GRAPHIC_MTFTOBMP_MAXEXT * fWH));
581                 aDrawSize.setHeight(GRAPHIC_MTFTOBMP_MAXEXT);
582             }
583             else
584             {
585                 aDrawSize.setWidth(GRAPHIC_MTFTOBMP_MAXEXT);
586                 aDrawSize.setHeight(basegfx::fround(GRAPHIC_MTFTOBMP_MAXEXT / fWH));
587             }
588         }
589 
590         // calculate pixel size. Normally, it's the same as aDrawSize, but may
591         // need to be extended when hairlines are on the right or bottom edge
592         Size aPixelSize(aDrawSize);
593 
594         if(GRAPHIC_GDIMETAFILE == ImplGetType())
595         {
596             // get hairline and full bound rect
597             Rectangle aHairlineRect;
598             const Rectangle aRect(maMetaFile.GetBoundRect(aVDev, &aHairlineRect));
599 
600             if(!aRect.IsEmpty() && !aHairlineRect.IsEmpty())
601             {
602                 // expand if needed to allow bottom and right hairlines to be added
603                 if(aRect.Right() == aHairlineRect.Right())
604                 {
605                     aPixelSize.setWidth(aPixelSize.getWidth() + 1);
606                 }
607 
608                 if(aRect.Bottom() == aHairlineRect.Bottom())
609                 {
610                     aPixelSize.setHeight(aPixelSize.getHeight() + 1);
611                 }
612             }
613         }
614 
615         if(aVDev.SetOutputSizePixel(aPixelSize))
616         {
617             if(rParameters.getAntiAliase())
618             {
619                 aVDev.SetAntialiasing(aVDev.GetAntialiasing() | ANTIALIASING_ENABLE_B2DDRAW);
620             }
621 
622             if(rParameters.getSnapHorVerLines())
623             {
624                 aVDev.SetAntialiasing(aVDev.GetAntialiasing() | ANTIALIASING_PIXELSNAPHAIRLINE);
625             }
626 
627             ImplDraw( &aVDev, Point(), aDrawSize );
628             aRetBmp =  aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() );
629         }
630     }
631 
632 	if( !!aRetBmp )
633 	{
634 		aRetBmp.SetPrefMapMode( ImplGetPrefMapMode() );
635 		aRetBmp.SetPrefSize( ImplGetPrefSize() );
636 	}
637 
638     return aRetBmp;
639 }
640 
641 // ------------------------------------------------------------------------
642 
643 BitmapEx ImpGraphic::ImplGetBitmapEx(const GraphicConversionParameters& rParameters) const
644 {
645     BitmapEx aRetBmpEx;
646 
647     if( meType == GRAPHIC_BITMAP )
648     {
649         if(maSvgData.get() && maEx.IsEmpty())
650         {
651             // use maEx as local buffer for rendered svg
652             const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement();
653         }
654 
655 		aRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx );
656 
657         if(rParameters.getSizePixel().Width() || rParameters.getSizePixel().Height())
658             aRetBmpEx.Scale(rParameters.getSizePixel());
659     }
660     else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() )
661     {
662 		const ImpGraphic aMonoMask( maMetaFile.GetMonochromeMtf( COL_BLACK ) );
663 		aRetBmpEx = BitmapEx(ImplGetBitmap(rParameters), aMonoMask.ImplGetBitmap(rParameters));
664     }
665 
666     return aRetBmpEx;
667 }
668 
669 // ------------------------------------------------------------------------
670 
671 Animation ImpGraphic::ImplGetAnimation() const
672 {
673 	Animation aAnimation;
674 
675 	if( mpAnimation )
676 		aAnimation = *mpAnimation;
677 
678 	return aAnimation;
679 }
680 
681 // ------------------------------------------------------------------------
682 
683 const GDIMetaFile& ImpGraphic::ImplGetGDIMetaFile() const
684 {
685 	return maMetaFile;
686 }
687 
688 // ------------------------------------------------------------------------
689 
690 Size ImpGraphic::ImplGetPrefSize() const
691 {
692 	Size aSize;
693 
694 	if( ImplIsSwapOut() )
695 		aSize = maSwapInfo.maPrefSize;
696 	else
697 	{
698 		switch( meType )
699 		{
700 			case( GRAPHIC_NONE ):
701 			case( GRAPHIC_DEFAULT ):
702 			break;
703 
704 			case( GRAPHIC_BITMAP ):
705 			{
706                 if(maSvgData.get() && maEx.IsEmpty())
707                 {
708                     // svg not yet buffered in maEx, return size derived from range
709                     const basegfx::B2DRange& rRange = maSvgData->getRange();
710 
711                     aSize = Size(basegfx::fround(rRange.getWidth()), basegfx::fround(rRange.getHeight()));
712                 }
713                 else
714                 {
715                     aSize = maEx.GetPrefSize();
716 
717 				    if( !aSize.Width() || !aSize.Height() )
718                     {
719 					    aSize = maEx.GetSizePixel();
720                     }
721                 }
722 			}
723 			break;
724 
725 			default:
726 			{
727 				if( ImplIsSupportedGraphic() )
728 				  aSize = maMetaFile.GetPrefSize();
729 			}
730 			break;
731 		}
732 	}
733 
734 	return aSize;
735 }
736 
737 // ------------------------------------------------------------------------
738 
739 void ImpGraphic::ImplSetPrefSize( const Size& rPrefSize )
740 {
741     switch( meType )
742     {
743         case( GRAPHIC_NONE ):
744         case( GRAPHIC_DEFAULT ):
745 		break;
746 
747 		case( GRAPHIC_BITMAP ):
748         {
749             // #108077# Push through pref size to animation object,
750             // will be lost on copy otherwise
751             if(maSvgData.get())
752             {
753                 // ignore for Svg. If this is really used (except the grfcache)
754                 // it can be extended by using maEx as buffer for maSvgData->getReplacement()
755             }
756             else
757             {
758                 if( ImplIsAnimated() )
759                 {
760                     const_cast< BitmapEx& >(mpAnimation->GetBitmapEx()).SetPrefSize( rPrefSize );
761                 }
762 
763                 maEx.SetPrefSize( rPrefSize );
764             }
765         }
766 		break;
767 
768         default:
769 		{
770 			if( ImplIsSupportedGraphic() )
771 				maMetaFile.SetPrefSize( rPrefSize );
772 		}
773 		break;
774     }
775 }
776 
777 // ------------------------------------------------------------------------
778 
779 MapMode ImpGraphic::ImplGetPrefMapMode() const
780 {
781 	MapMode aMapMode;
782 
783 	if( ImplIsSwapOut() )
784 		aMapMode = maSwapInfo.maPrefMapMode;
785 	else
786 	{
787 		switch( meType )
788 		{
789 			case( GRAPHIC_NONE ):
790 			case( GRAPHIC_DEFAULT ):
791 			break;
792 
793 			case( GRAPHIC_BITMAP ):
794 			{
795                 if(maSvgData.get() && maEx.IsEmpty())
796                 {
797                     // svg not yet buffered in maEx, return default PrefMapMode
798                     aMapMode = MapMode(MAP_100TH_MM);
799                 }
800                 else
801                 {
802 				    const Size aSize( maEx.GetPrefSize() );
803 
804 				    if ( aSize.Width() && aSize.Height() )
805 					    aMapMode = maEx.GetPrefMapMode();
806                 }
807 			}
808 			break;
809 
810 			default:
811 			{
812 				if( ImplIsSupportedGraphic() )
813 					return maMetaFile.GetPrefMapMode();
814 			}
815 			break;
816 		}
817 	}
818 
819 	return aMapMode;
820 }
821 
822 // ------------------------------------------------------------------------
823 
824 void ImpGraphic::ImplSetPrefMapMode( const MapMode& rPrefMapMode )
825 {
826     switch( meType )
827     {
828         case( GRAPHIC_NONE ):
829         case( GRAPHIC_DEFAULT ):
830 		break;
831 
832 		case( GRAPHIC_BITMAP ):
833         {
834             if(maSvgData.get())
835             {
836                 // ignore for Svg. If this is really used (except the grfcache)
837                 // it can be extended by using maEx as buffer for maSvgData->getReplacement()
838             }
839             else
840             {
841                 // #108077# Push through pref mapmode to animation object,
842                 // will be lost on copy otherwise
843                 if( ImplIsAnimated() )
844                 {
845                     const_cast< BitmapEx& >(mpAnimation->GetBitmapEx()).SetPrefMapMode( rPrefMapMode );
846                 }
847 
848 			    maEx.SetPrefMapMode( rPrefMapMode );
849             }
850         }
851 		break;
852 
853         default:
854 		{
855 			if( ImplIsSupportedGraphic() )
856 				maMetaFile.SetPrefMapMode( rPrefMapMode );
857 		}
858 		break;
859     }
860 }
861 
862 // ------------------------------------------------------------------------
863 
864 sal_uLong ImpGraphic::ImplGetSizeBytes() const
865 {
866     if( 0 == mnSizeBytes )
867     {
868         if( meType == GRAPHIC_BITMAP )
869 	    {
870             if(maSvgData.get())
871             {
872                 mnSizeBytes = maSvgData->getSvgDataArrayLength();
873             }
874             else
875             {
876                 mnSizeBytes = mpAnimation ? mpAnimation->GetSizeBytes() : maEx.GetSizeBytes();
877             }
878         }
879         else if( meType == GRAPHIC_GDIMETAFILE )
880         {
881             mnSizeBytes = maMetaFile.GetSizeBytes();
882         }
883     }
884 
885 	return( mnSizeBytes );
886 }
887 
888 // ------------------------------------------------------------------------
889 
890 void ImpGraphic::ImplDraw( OutputDevice* pOutDev, const Point& rDestPt ) const
891 {
892     if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
893 	{
894 		switch( meType )
895 		{
896 			case( GRAPHIC_DEFAULT ):
897 			break;
898 
899 			case( GRAPHIC_BITMAP ):
900 			{
901                 if(maSvgData.get() && !maEx)
902                 {
903                     // use maEx as local buffer for rendered svg
904                     const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement();
905                 }
906 
907                 if ( mpAnimation )
908                 {
909 					mpAnimation->Draw( pOutDev, rDestPt );
910                 }
911 				else
912                 {
913 					maEx.Draw( pOutDev, rDestPt );
914                 }
915 			}
916 			break;
917 
918 			default:
919 				ImplDraw( pOutDev, rDestPt, maMetaFile.GetPrefSize() );
920 			break;
921 		}
922 	}
923 }
924 
925 // ------------------------------------------------------------------------
926 
927 void ImpGraphic::ImplDraw( OutputDevice* pOutDev,
928 						   const Point& rDestPt, const Size& rDestSize ) const
929 {
930     if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
931 	{
932 		switch( meType )
933 		{
934 			case( GRAPHIC_DEFAULT ):
935 			break;
936 
937 			case( GRAPHIC_BITMAP ):
938 			{
939                 if(maSvgData.get() && maEx.IsEmpty())
940                 {
941                     // use maEx as local buffer for rendered svg
942                     const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement();
943                 }
944 
945                 if( mpAnimation )
946                 {
947 					mpAnimation->Draw( pOutDev, rDestPt, rDestSize );
948                 }
949 				else
950                 {
951 					maEx.Draw( pOutDev, rDestPt, rDestSize );
952                 }
953 			}
954 			break;
955 
956 			default:
957 			{
958 				( (ImpGraphic*) this )->maMetaFile.WindStart();
959 				( (ImpGraphic*) this )->maMetaFile.Play( pOutDev, rDestPt, rDestSize );
960 				( (ImpGraphic*) this )->maMetaFile.WindStart();
961 			}
962 			break;
963 		}
964 	}
965 }
966 
967 // ------------------------------------------------------------------------
968 
969 void ImpGraphic::ImplStartAnimation( OutputDevice* pOutDev,
970 									 const Point& rDestPt,
971 									 long nExtraData,
972 									 OutputDevice* pFirstFrameOutDev )
973 {
974     if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation )
975 	    mpAnimation->Start( pOutDev, rDestPt, nExtraData, pFirstFrameOutDev );
976 }
977 
978 // ------------------------------------------------------------------------
979 
980 void ImpGraphic::ImplStartAnimation( OutputDevice* pOutDev, const Point& rDestPt,
981 									 const Size& rDestSize, long nExtraData,
982 									 OutputDevice* pFirstFrameOutDev )
983 {
984     if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation )
985 	    mpAnimation->Start( pOutDev, rDestPt, rDestSize, nExtraData, pFirstFrameOutDev );
986 }
987 
988 // ------------------------------------------------------------------------
989 
990 void ImpGraphic::ImplStopAnimation( OutputDevice* pOutDev, long nExtraData )
991 {
992     if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation )
993 	    mpAnimation->Stop( pOutDev, nExtraData );
994 }
995 
996 // ------------------------------------------------------------------------
997 
998 void ImpGraphic::ImplSetAnimationNotifyHdl( const Link& rLink )
999 {
1000 	if( mpAnimation )
1001 		mpAnimation->SetNotifyHdl( rLink );
1002 }
1003 
1004 // ------------------------------------------------------------------------
1005 
1006 Link ImpGraphic::ImplGetAnimationNotifyHdl() const
1007 {
1008 	Link aLink;
1009 
1010 	if( mpAnimation )
1011 		aLink = mpAnimation->GetNotifyHdl();
1012 
1013 	return aLink;
1014 }
1015 
1016 // ------------------------------------------------------------------------
1017 
1018 sal_uLong ImpGraphic::ImplGetAnimationLoopCount() const
1019 {
1020 	return( mpAnimation ? mpAnimation->GetLoopCount() : 0UL );
1021 }
1022 
1023 // ------------------------------------------------------------------------
1024 
1025 void ImpGraphic::ImplResetAnimationLoopCount()
1026 {
1027 	if( mpAnimation )
1028 		mpAnimation->ResetLoopCount();
1029 }
1030 
1031 // ------------------------------------------------------------------------
1032 
1033 List* ImpGraphic::ImplGetAnimationInfoList() const
1034 {
1035 	return( mpAnimation ? mpAnimation->GetAInfoList() : NULL );
1036 }
1037 
1038 // ------------------------------------------------------------------------
1039 
1040 GraphicReader* ImpGraphic::ImplGetContext()
1041 {
1042 	return mpContext;
1043 }
1044 
1045 // ------------------------------------------------------------------------
1046 
1047 void ImpGraphic::ImplSetContext( GraphicReader* pReader )
1048 {
1049 	mpContext = pReader;
1050 }
1051 
1052 // ------------------------------------------------------------------------
1053 
1054 void ImpGraphic::ImplSetDocFileName( const String& rName, sal_uLong nFilePos )
1055 {
1056 	const INetURLObject aURL( rName );
1057 
1058 	DBG_ASSERT( !rName.Len() || ( aURL.GetProtocol() != INET_PROT_NOT_VALID ), "Graphic::SetDocFileName(...): invalid URL" );
1059 
1060 	maDocFileURLStr = aURL.GetMainURL( INetURLObject::NO_DECODE );
1061 	mnDocFilePos = nFilePos;
1062 }
1063 
1064 // ------------------------------------------------------------------------
1065 
1066 const String& ImpGraphic::ImplGetDocFileName() const
1067 {
1068 	return maDocFileURLStr;
1069 }
1070 
1071 // ------------------------------------------------------------------------
1072 
1073 sal_uLong ImpGraphic::ImplGetDocFilePos() const
1074 {
1075 	return mnDocFilePos;
1076 }
1077 
1078 // ------------------------------------------------------------------------
1079 
1080 sal_Bool ImpGraphic::ImplReadEmbedded( SvStream& rIStm, sal_Bool bSwap )
1081 {
1082 	MapMode			aMapMode;
1083 	Size			aSize;
1084     const sal_uLong		nStartPos = rIStm.Tell();
1085 	sal_uInt32		nId;
1086 	sal_uLong			nHeaderLen;
1087 	long			nType;
1088 	long			nLen;
1089     const sal_uInt16	nOldFormat = rIStm.GetNumberFormatInt();
1090 	sal_Bool			bRet = sal_False;
1091 
1092     if( !mbSwapUnderway )
1093     {
1094         const String		aTempURLStr( maDocFileURLStr );
1095         const sal_uLong			nTempPos = mnDocFilePos;
1096 
1097 		ImplClear();
1098 
1099         maDocFileURLStr = aTempURLStr;
1100         mnDocFilePos = nTempPos;
1101     }
1102 
1103     rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1104 	rIStm >> nId;
1105 
1106 	// check version
1107 	if( GRAPHIC_FORMAT_50 == nId )
1108 	{
1109 		// read new style header
1110 		VersionCompat* pCompat = new VersionCompat( rIStm, STREAM_READ );
1111 
1112 		rIStm >> nType;
1113 		rIStm >> nLen;
1114 		rIStm >> aSize;
1115 		rIStm >> aMapMode;
1116 
1117 		delete pCompat;
1118 	}
1119 	else
1120 	{
1121 		// read old style header
1122 	    long nWidth, nHeight;
1123 	    long nMapMode, nScaleNumX, nScaleDenomX;
1124 		long nScaleNumY, nScaleDenomY, nOffsX, nOffsY;
1125 
1126 		rIStm.SeekRel( -4L );
1127 
1128 		rIStm >> nType >> nLen >> nWidth >> nHeight;
1129 		rIStm >> nMapMode >> nScaleNumX >> nScaleDenomX >> nScaleNumY;
1130 		rIStm >> nScaleDenomY >> nOffsX >> nOffsY;
1131 
1132 		// swapped
1133 		if( nType > 100L )
1134 		{
1135 			nType = SWAPLONG( nType );
1136 			nLen = SWAPLONG( nLen );
1137 			nWidth = SWAPLONG( nWidth );
1138 			nHeight = SWAPLONG( nHeight );
1139 			nMapMode = SWAPLONG( nMapMode );
1140 			nScaleNumX = SWAPLONG( nScaleNumX );
1141 			nScaleDenomX = SWAPLONG( nScaleDenomX );
1142 			nScaleNumY = SWAPLONG( nScaleNumY );
1143 			nScaleDenomY = SWAPLONG( nScaleDenomY );
1144 			nOffsX = SWAPLONG( nOffsX );
1145 			nOffsY = SWAPLONG( nOffsY );
1146 		}
1147 
1148 		aSize = Size( nWidth, nHeight );
1149 		aMapMode = MapMode( (MapUnit) nMapMode, Point( nOffsX, nOffsY ),
1150 							Fraction( nScaleNumX, nScaleDenomX ),
1151 							Fraction( nScaleNumY, nScaleDenomY ) );
1152 	}
1153 
1154 	nHeaderLen = rIStm.Tell() - nStartPos;
1155     meType = (GraphicType) nType;
1156 
1157 	if( meType )
1158 	{
1159 		if( meType == GRAPHIC_BITMAP )
1160 		{
1161             if(maSvgData.get() && maEx.IsEmpty())
1162             {
1163                 // use maEx as local buffer for rendered svg
1164                 maEx = maSvgData->getReplacement();
1165             }
1166 
1167             maEx.aBitmapSize = aSize;
1168 
1169 			if( aMapMode != MapMode() )
1170 			{
1171 				maEx.SetPrefMapMode( aMapMode );
1172 				maEx.SetPrefSize( aSize );
1173 			}
1174 		}
1175 		else
1176 		{
1177 			maMetaFile.SetPrefMapMode( aMapMode );
1178 			maMetaFile.SetPrefSize( aSize );
1179 		}
1180 
1181 		if( bSwap )
1182 		{
1183 			if( maDocFileURLStr.Len() )
1184 			{
1185 				rIStm.Seek( nStartPos + nHeaderLen + nLen );
1186 				bRet = mbSwapOut = sal_True;
1187 			}
1188 			else
1189 			{
1190 				::utl::TempFile		aTempFile;
1191 				const INetURLObject	aTmpURL( aTempFile.GetURL() );
1192 
1193 				if( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ).getLength() )
1194 				{
1195 					SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
1196 
1197 					if( pOStm )
1198 					{
1199 						sal_uLong	nFullLen = nHeaderLen + nLen;
1200 						sal_uLong	nPartLen = Min( nFullLen, (sal_uLong) GRAPHIC_MAXPARTLEN );
1201 						sal_uInt8*	pBuffer = (sal_uInt8*) rtl_allocateMemory( nPartLen );
1202 
1203 		      			pOStm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1204 
1205 						if( pBuffer )
1206 						{
1207 							rIStm.Seek( nStartPos );
1208 
1209 							while( nFullLen )
1210 							{
1211 								rIStm.Read( (char*) pBuffer, nPartLen );
1212 								pOStm->Write( (char*) pBuffer, nPartLen );
1213 
1214 								nFullLen -= nPartLen;
1215 
1216 								if( nFullLen < GRAPHIC_MAXPARTLEN )
1217 									nPartLen = nFullLen;
1218 							}
1219 
1220 							rtl_freeMemory( pBuffer );
1221 							sal_uLong nReadErr = rIStm.GetError(), nWriteErr = pOStm->GetError();
1222 							delete pOStm, pOStm = NULL;
1223 
1224 							if( !nReadErr && !nWriteErr )
1225 							{
1226 								bRet = mbSwapOut = sal_True;
1227 								mpSwapFile = new ImpSwapFile;
1228 								mpSwapFile->nRefCount = 1;
1229 								mpSwapFile->aSwapURL = aTmpURL;
1230 							}
1231 							else
1232 							{
1233 								try
1234 								{
1235 									::ucbhelper::Content aCnt( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ),
1236 														 ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
1237 
1238 									aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
1239 														 ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
1240 								}
1241 								catch( const ::com::sun::star::ucb::ContentCreationException& )
1242 								{
1243 								}
1244 								catch( const ::com::sun::star::uno::RuntimeException& )
1245 								{
1246 								}
1247 								catch( const ::com::sun::star::ucb::CommandAbortedException& )
1248 								{
1249             					}
1250         		                catch( const ::com::sun::star::uno::Exception& )
1251 		                        {
1252 		                        }
1253 							}
1254 						}
1255 
1256 						delete pOStm;
1257 					}
1258 				}
1259 			}
1260 		}
1261 		else if( meType == GRAPHIC_BITMAP || meType == GRAPHIC_GDIMETAFILE )
1262 		{
1263 			rIStm >> *this;
1264 			bRet = ( rIStm.GetError() == 0UL );
1265 		}
1266 		else if( meType >= SYS_WINMETAFILE && meType <= SYS_MACMETAFILE )
1267 		{
1268 			Graphic aSysGraphic;
1269 			sal_uLong	nCvtType;
1270 
1271 			switch( sal::static_int_cast<sal_uLong>(meType) )
1272 			{
1273 				case( SYS_WINMETAFILE ):
1274 				case( SYS_WNTMETAFILE ): nCvtType = CVT_WMF; break;
1275 				case( SYS_OS2METAFILE ): nCvtType = CVT_MET; break;
1276 				case( SYS_MACMETAFILE ): nCvtType = CVT_PCT; break;
1277 
1278 				default:
1279 					nCvtType = CVT_UNKNOWN;
1280 				break;
1281 			}
1282 
1283 			if( nType && GraphicConverter::Import( rIStm, aSysGraphic, nCvtType ) == ERRCODE_NONE )
1284 			{
1285 				*this = ImpGraphic( aSysGraphic.GetGDIMetaFile() );
1286 				bRet = ( rIStm.GetError() == 0UL );
1287 			}
1288 			else
1289 				meType = GRAPHIC_DEFAULT;
1290 		}
1291 
1292 		if( bRet )
1293 		{
1294 			ImplSetPrefMapMode( aMapMode );
1295 			ImplSetPrefSize( aSize );
1296 		}
1297 	}
1298 	else
1299 		bRet = sal_True;
1300 
1301 	rIStm.SetNumberFormatInt( nOldFormat );
1302 
1303 	return bRet;
1304 }
1305 
1306 // ------------------------------------------------------------------------
1307 
1308 sal_Bool ImpGraphic::ImplWriteEmbedded( SvStream& rOStm )
1309 {
1310 	sal_Bool bRet = sal_False;
1311 
1312 	if( ( meType != GRAPHIC_NONE ) && ( meType != GRAPHIC_DEFAULT ) && !ImplIsSwapOut() )
1313 	{
1314 		const MapMode	aMapMode( ImplGetPrefMapMode() );
1315 		const Size		aSize( ImplGetPrefSize() );
1316 		const sal_uInt16	nOldFormat = rOStm.GetNumberFormatInt();
1317 		sal_uLong			nDataFieldPos;
1318 
1319 		rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1320 
1321 		// write correct version ( old style/new style header )
1322 		if( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 )
1323 		{
1324 			// write ID for new format (5.0)
1325 			rOStm << GRAPHIC_FORMAT_50;
1326 
1327 			// write new style header
1328 			VersionCompat* pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 );
1329 
1330 			rOStm << (long) meType;
1331 
1332 			// data size is updated later
1333 			nDataFieldPos = rOStm.Tell();
1334 			rOStm << (long) 0;
1335 
1336 			rOStm << aSize;
1337 			rOStm << aMapMode;
1338 
1339 			delete pCompat;
1340 		}
1341 		else
1342 		{
1343 			// write old style (<=4.0) header
1344 			rOStm << (long) meType;
1345 
1346 			// data size is updated later
1347 			nDataFieldPos = rOStm.Tell();
1348 			rOStm << (long) 0;
1349 
1350 			rOStm << (long) aSize.Width();
1351 			rOStm << (long) aSize.Height();
1352 			rOStm << (long) aMapMode.GetMapUnit();
1353 			rOStm << (long) aMapMode.GetScaleX().GetNumerator();
1354 			rOStm << (long) aMapMode.GetScaleX().GetDenominator();
1355 			rOStm << (long) aMapMode.GetScaleY().GetNumerator();
1356 			rOStm << (long) aMapMode.GetScaleY().GetDenominator();
1357 			rOStm << (long) aMapMode.GetOrigin().X();
1358 			rOStm << (long) aMapMode.GetOrigin().Y();
1359 		}
1360 
1361 		// write data block
1362 		if( !rOStm.GetError() )
1363 		{
1364 			const sal_uLong nDataStart = rOStm.Tell();
1365 
1366 			if( ImplIsSupportedGraphic() )
1367 				rOStm << *this;
1368 
1369 			if( !rOStm.GetError() )
1370 			{
1371 				const sal_uLong nStmPos2 = rOStm.Tell();
1372 				rOStm.Seek( nDataFieldPos );
1373 				rOStm << (long) ( nStmPos2 - nDataStart );
1374 				rOStm.Seek( nStmPos2 );
1375 				bRet = sal_True;
1376 			}
1377 		}
1378 
1379 		rOStm.SetNumberFormatInt( nOldFormat );
1380 	}
1381 
1382 	return bRet;
1383 }
1384 
1385 // ------------------------------------------------------------------------
1386 
1387 sal_Bool ImpGraphic::ImplSwapOut()
1388 {
1389 	sal_Bool bRet = sal_False;
1390 
1391     if( !ImplIsSwapOut() )
1392 	{
1393 		if( !maDocFileURLStr.Len() )
1394 		{
1395 			::utl::TempFile		aTempFile;
1396 			const INetURLObject	aTmpURL( aTempFile.GetURL() );
1397 
1398 			if( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ).getLength() )
1399 			{
1400 				SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
1401 
1402 				if( pOStm )
1403 				{
1404                     pOStm->SetVersion( SOFFICE_FILEFORMAT_50 );
1405 					pOStm->SetCompressMode( COMPRESSMODE_NATIVE );
1406 
1407 					if( ( bRet = ImplSwapOut( pOStm ) ) == sal_True )
1408 					{
1409 						mpSwapFile = new ImpSwapFile;
1410 						mpSwapFile->nRefCount = 1;
1411 						mpSwapFile->aSwapURL = aTmpURL;
1412 					}
1413 					else
1414 					{
1415 						delete pOStm, pOStm = NULL;
1416 
1417 						try
1418 						{
1419 							::ucbhelper::Content aCnt( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ),
1420 												 ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
1421 
1422 							aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
1423 												 ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
1424 						}
1425 						catch( const ::com::sun::star::ucb::ContentCreationException& )
1426 						{
1427 						}
1428 						catch( const ::com::sun::star::uno::RuntimeException& )
1429 						{
1430 						}
1431 						catch( const ::com::sun::star::ucb::CommandAbortedException& )
1432 						{
1433 						}
1434         		        catch( const ::com::sun::star::uno::Exception& )
1435 		                {
1436 		                }
1437 					}
1438 
1439 					delete pOStm;
1440 				}
1441 			}
1442 		}
1443 		else
1444 		{
1445 			ImplClearGraphics( sal_True );
1446 			bRet = mbSwapOut = sal_True;
1447 		}
1448 	}
1449 
1450     return bRet;
1451 }
1452 
1453 // ------------------------------------------------------------------------
1454 
1455 sal_Bool ImpGraphic::ImplSwapOut( SvStream* pOStm )
1456 {
1457 	sal_Bool bRet = sal_False;
1458 
1459     if( pOStm )
1460     {
1461         pOStm->SetBufferSize( GRAPHIC_STREAMBUFSIZE );
1462 
1463 		if( !pOStm->GetError() && ImplWriteEmbedded( *pOStm ) )
1464 		{
1465 			pOStm->Flush();
1466 
1467 			if( !pOStm->GetError() )
1468 			{
1469 				ImplClearGraphics( sal_True );
1470 				bRet = mbSwapOut = sal_True;
1471 			}
1472 		}
1473     }
1474 	else
1475 	{
1476 		ImplClearGraphics( sal_True );
1477 		bRet = mbSwapOut = sal_True;
1478 	}
1479 
1480     return bRet;
1481 }
1482 
1483 // ------------------------------------------------------------------------
1484 
1485 sal_Bool ImpGraphic::ImplSwapIn()
1486 {
1487     sal_Bool bRet = sal_False;
1488 
1489 	if( ImplIsSwapOut() )
1490 	{
1491 		String aSwapURL;
1492 
1493 		if( mpSwapFile )
1494 			aSwapURL = mpSwapFile->aSwapURL.GetMainURL( INetURLObject::NO_DECODE );
1495 		else
1496 			aSwapURL = maDocFileURLStr;
1497 
1498 		if( aSwapURL.Len() )
1499 		{
1500 			SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( aSwapURL, STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
1501 
1502 			if( pIStm )
1503 			{
1504                 pIStm->SetVersion( SOFFICE_FILEFORMAT_50 );
1505 				pIStm->SetCompressMode( COMPRESSMODE_NATIVE );
1506 
1507 				if( !mpSwapFile )
1508 					pIStm->Seek( mnDocFilePos );
1509 
1510 				bRet = ImplSwapIn( pIStm );
1511 				delete pIStm;
1512 
1513 				if( mpSwapFile )
1514 				{
1515 					if( mpSwapFile->nRefCount > 1 )
1516 						mpSwapFile->nRefCount--;
1517 					else
1518 					{
1519 						try
1520 						{
1521 							::ucbhelper::Content aCnt( aSwapURL,
1522 												 ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
1523 
1524 							aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
1525 												 ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
1526 						}
1527 						catch( const ::com::sun::star::ucb::ContentCreationException& )
1528 						{
1529 						}
1530 						catch( const ::com::sun::star::uno::RuntimeException& )
1531 						{
1532 						}
1533 						catch( const ::com::sun::star::ucb::CommandAbortedException& )
1534 						{
1535 						}
1536         		        catch( const ::com::sun::star::uno::Exception& )
1537 		                {
1538 		                }
1539 
1540 						delete mpSwapFile;
1541 					}
1542 
1543 					mpSwapFile = NULL;
1544 				}
1545 			}
1546 		}
1547 	}
1548 
1549     return bRet;
1550 }
1551 
1552 // ------------------------------------------------------------------------
1553 
1554 sal_Bool ImpGraphic::ImplSwapIn( SvStream* pIStm )
1555 {
1556 	sal_Bool bRet = sal_False;
1557 
1558     if( pIStm )
1559 	{
1560 		pIStm->SetBufferSize( GRAPHIC_STREAMBUFSIZE );
1561 
1562 		if( !pIStm->GetError() )
1563 		{
1564 			mbSwapUnderway = sal_True;
1565 			bRet = ImplReadEmbedded( *pIStm );
1566 			mbSwapUnderway = sal_False;
1567 
1568 			if( !bRet )
1569 				ImplClear();
1570 			else
1571 				mbSwapOut = sal_False;
1572 		}
1573 	}
1574 
1575     return bRet;
1576 }
1577 
1578 // ------------------------------------------------------------------------
1579 
1580 sal_Bool ImpGraphic::ImplIsSwapOut() const
1581 {
1582 	return mbSwapOut;
1583 }
1584 
1585 // ------------------------------------------------------------------------
1586 
1587 void ImpGraphic::ImplSetLink( const	GfxLink& rGfxLink )
1588 {
1589 	delete mpGfxLink;
1590 	mpGfxLink = new GfxLink( rGfxLink );
1591 
1592 	if( mpGfxLink->IsNative() )
1593 		mpGfxLink->SwapOut();
1594 }
1595 
1596 // ------------------------------------------------------------------------
1597 
1598 GfxLink ImpGraphic::ImplGetLink()
1599 {
1600 	return( mpGfxLink ? *mpGfxLink : GfxLink() );
1601 }
1602 
1603 // ------------------------------------------------------------------------
1604 
1605 sal_Bool ImpGraphic::ImplIsLink() const
1606 {
1607 	return ( mpGfxLink != NULL ) ? sal_True : sal_False;
1608 }
1609 
1610 // ------------------------------------------------------------------------
1611 
1612 sal_uLong ImpGraphic::ImplGetChecksum() const
1613 {
1614 	sal_uLong nRet = 0;
1615 
1616     if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
1617 	{
1618 		switch( meType )
1619 		{
1620 			case( GRAPHIC_DEFAULT ):
1621 			break;
1622 
1623 			case( GRAPHIC_BITMAP ):
1624 			{
1625                 if(maSvgData.get() && maEx.IsEmpty())
1626                 {
1627                     // use maEx as local buffer for rendered svg
1628                     const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement();
1629                 }
1630 
1631                 if( mpAnimation )
1632                 {
1633 					nRet = mpAnimation->GetChecksum();
1634                 }
1635 				else
1636                 {
1637 					nRet = maEx.GetChecksum();
1638                 }
1639 			}
1640 			break;
1641 
1642 			default:
1643 				nRet = maMetaFile.GetChecksum();
1644 			break;
1645 		}
1646 	}
1647 
1648 	return nRet;
1649 }
1650 
1651 // ------------------------------------------------------------------------
1652 
1653 sal_Bool ImpGraphic::ImplExportNative( SvStream& rOStm ) const
1654 {
1655 	sal_Bool bResult = sal_False;
1656 
1657 	if( !rOStm.GetError() )
1658 	{
1659 		if( !ImplIsSwapOut() )
1660 		{
1661 			if( mpGfxLink && mpGfxLink->IsNative() )
1662 				bResult = mpGfxLink->ExportNative( rOStm );
1663 			else
1664 			{
1665 				rOStm << *this;
1666 				bResult = ( rOStm.GetError() == ERRCODE_NONE );
1667 			}
1668 		}
1669 		else
1670 			 rOStm.SetError( SVSTREAM_GENERALERROR );
1671 	}
1672 
1673 	return bResult;
1674 }
1675 
1676 // ------------------------------------------------------------------------
1677 
1678 const SvgDataPtr& ImpGraphic::getSvgData() const
1679 {
1680     return maSvgData;
1681 }
1682 
1683 // ------------------------------------------------------------------------
1684 
1685 SvStream& operator>>( SvStream& rIStm, ImpGraphic& rImpGraphic )
1686 {
1687 	if( !rIStm.GetError() )
1688 	{
1689 		const sal_uLong	nStmPos1 = rIStm.Tell();
1690 		sal_uInt32 nTmp;
1691 
1692 		if ( !rImpGraphic.mbSwapUnderway )
1693 			rImpGraphic.ImplClear();
1694 
1695 		// read Id
1696 		rIStm >> nTmp;
1697 
1698         // if there is no more data, avoid further expensive
1699         // reading which will create VDevs and other stuff, just to
1700         // read nothing. CAUTION: Eof is only true AFTER reading another
1701         // byte, a speciality of SvMemoryStream (!)
1702         if(!rIStm.GetError() && !rIStm.IsEof())
1703         {
1704 		    if( NATIVE_FORMAT_50 == nTmp )
1705 		    {
1706 			    Graphic			aGraphic;
1707 			    GfxLink			aLink;
1708 			    VersionCompat*	pCompat;
1709 
1710 			    // read compat info
1711 			    pCompat = new VersionCompat( rIStm, STREAM_READ );
1712 			    delete pCompat;
1713 
1714 			    rIStm >> aLink;
1715 
1716 			    // set dummy link to avoid creation of additional link after filtering;
1717 			    // we set a default link to avoid unnecessary swapping of native data
1718 			    aGraphic.SetLink( GfxLink() );
1719 
1720 			    if( !rIStm.GetError() && aLink.LoadNative( aGraphic ) )
1721 			    {
1722 				    // set link only, if no other link was set
1723 				    const sal_Bool bSetLink = ( rImpGraphic.mpGfxLink == NULL );
1724 
1725 				    // assign graphic
1726 				    rImpGraphic = *aGraphic.ImplGetImpGraphic();
1727 
1728                     if( aLink.IsPrefMapModeValid() )
1729                         rImpGraphic.ImplSetPrefMapMode( aLink.GetPrefMapMode() );
1730 
1731                     if( aLink.IsPrefSizeValid() )
1732                         rImpGraphic.ImplSetPrefSize( aLink.GetPrefSize() );
1733 
1734 				    if( bSetLink )
1735 					    rImpGraphic.ImplSetLink( aLink );
1736 			    }
1737 			    else
1738 			    {
1739 				    rIStm.Seek( nStmPos1 );
1740 				    rIStm.SetError( ERRCODE_IO_WRONGFORMAT );
1741 			    }
1742 		    }
1743 		    else
1744 		    {
1745 			    BitmapEx		aBmpEx;
1746 			    const sal_uInt16	nOldFormat = rIStm.GetNumberFormatInt();
1747 
1748 			    rIStm.SeekRel( -4 );
1749 			    rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1750 			    rIStm >> aBmpEx;
1751 
1752 			    if( !rIStm.GetError() )
1753 			    {
1754 				    sal_uInt32	nMagic1(0), nMagic2(0);
1755 				    sal_uLong	nActPos = rIStm.Tell();
1756 
1757 				    rIStm >> nMagic1 >> nMagic2;
1758 				    rIStm.Seek( nActPos );
1759 
1760 				    rImpGraphic = ImpGraphic( aBmpEx );
1761 
1762 				    if( !rIStm.GetError() && ( 0x5344414e == nMagic1 ) && ( 0x494d4931 == nMagic2 ) )
1763 				    {
1764 					    delete rImpGraphic.mpAnimation;
1765 					    rImpGraphic.mpAnimation = new Animation;
1766 					    rIStm >> *rImpGraphic.mpAnimation;
1767 
1768                         // #108077# manually set loaded BmpEx to Animation
1769                         // (which skips loading its BmpEx if already done)
1770                         rImpGraphic.mpAnimation->SetBitmapEx(aBmpEx);
1771 				    }
1772 				    else
1773 					    rIStm.ResetError();
1774 			    }
1775 			    else
1776 			    {
1777 				    GDIMetaFile aMtf;
1778 
1779 				    rIStm.Seek( nStmPos1 );
1780 				    rIStm.ResetError();
1781 				    rIStm >> aMtf;
1782 
1783 				    if( !rIStm.GetError() )
1784                     {
1785 					    rImpGraphic = aMtf;
1786                     }
1787 				    else
1788                     {
1789                         // try to stream in Svg defining data (length, byte array and evtl. path)
1790                         // See below (operator<<) for more information
1791                         const sal_uInt32 nSvgMagic((sal_uInt32('s') << 24) | (sal_uInt32('v') << 16) | (sal_uInt32('g') << 8) | sal_uInt32('0'));
1792                         sal_uInt32 nMagic;
1793                         rIStm.Seek(nStmPos1);
1794                         rIStm.ResetError();
1795                         rIStm >> nMagic;
1796 
1797                         if(nSvgMagic == nMagic)
1798                         {
1799                             sal_uInt32 mnSvgDataArrayLength(0);
1800                             rIStm >> mnSvgDataArrayLength;
1801 
1802                             if(mnSvgDataArrayLength)
1803                             {
1804                                 SvgDataArray aNewData(new sal_uInt8[mnSvgDataArrayLength]);
1805                                 UniString aPath;
1806 
1807                                 rIStm.Read(aNewData.get(), mnSvgDataArrayLength);
1808                                 rIStm.ReadByteString(aPath);
1809 
1810                                 if(!rIStm.GetError())
1811                                 {
1812                                     SvgDataPtr aSvgDataPtr(
1813                                         new SvgData(
1814                                             aNewData,
1815                                             mnSvgDataArrayLength,
1816                                             rtl::OUString(aPath)));
1817 
1818                                     rImpGraphic = aSvgDataPtr;
1819                                 }
1820                             }
1821                         }
1822 
1823                         rIStm.Seek(nStmPos1);
1824                     }
1825 			    }
1826 
1827 			    rIStm.SetNumberFormatInt( nOldFormat );
1828 		    }
1829         }
1830 	}
1831 
1832     return rIStm;
1833 }
1834 
1835 // ------------------------------------------------------------------------
1836 
1837 SvStream& operator<<( SvStream& rOStm, const ImpGraphic& rImpGraphic )
1838 {
1839 	if( !rOStm.GetError() )
1840 	{
1841 		if( !rImpGraphic.ImplIsSwapOut() )
1842 		{
1843 			if( ( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 ) &&
1844 				( rOStm.GetCompressMode() & COMPRESSMODE_NATIVE ) &&
1845 				rImpGraphic.mpGfxLink && rImpGraphic.mpGfxLink->IsNative() )
1846 			{
1847 				VersionCompat* pCompat;
1848 
1849 				// native format
1850 				rOStm << NATIVE_FORMAT_50;
1851 
1852 				// write compat info
1853 				pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 );
1854 				delete pCompat;
1855 
1856                 rImpGraphic.mpGfxLink->SetPrefMapMode( rImpGraphic.ImplGetPrefMapMode() );
1857                 rImpGraphic.mpGfxLink->SetPrefSize( rImpGraphic.ImplGetPrefSize() );
1858 				rOStm << *rImpGraphic.mpGfxLink;
1859 			}
1860 			else
1861 			{
1862 				// own format
1863 				const sal_uInt16 nOldFormat = rOStm.GetNumberFormatInt();
1864 				rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1865 
1866 				switch( rImpGraphic.ImplGetType() )
1867 				{
1868 					case( GRAPHIC_NONE ):
1869 					case( GRAPHIC_DEFAULT ):
1870 					break;
1871 
1872 					case GRAPHIC_BITMAP:
1873 					{
1874                         if(rImpGraphic.getSvgData().get())
1875                         {
1876                             // stream out Svg defining data (length, byte array and evtl. path)
1877                             // this is used e.g. in swapping out graphic data and in transporting it over UNO API
1878                             // as sequence of bytes, but AFAIK not written anywhere to any kind of file, so it should be
1879                             // no problem to extend it; only used at runtime
1880                             const sal_uInt32 nSvgMagic((sal_uInt32('s') << 24) | (sal_uInt32('v') << 16) | (sal_uInt32('g') << 8) | sal_uInt32('0'));
1881 
1882                             rOStm << nSvgMagic;
1883                             rOStm << rImpGraphic.getSvgData()->getSvgDataArrayLength();
1884                             rOStm.Write(rImpGraphic.getSvgData()->getSvgDataArray().get(), rImpGraphic.getSvgData()->getSvgDataArrayLength());
1885                             rOStm.WriteByteString(rImpGraphic.getSvgData()->getPath());
1886                         }
1887 						else if( rImpGraphic.ImplIsAnimated())
1888                         {
1889 							rOStm << *rImpGraphic.mpAnimation;
1890                         }
1891 						else
1892                         {
1893 							rOStm << rImpGraphic.maEx;
1894                         }
1895 					}
1896 					break;
1897 
1898 					default:
1899 					{
1900 						if( rImpGraphic.ImplIsSupportedGraphic() )
1901 							rOStm << rImpGraphic.maMetaFile;
1902 					}
1903 					break;
1904 				}
1905 
1906 				rOStm.SetNumberFormatInt( nOldFormat );
1907 			}
1908 		}
1909 		else
1910 			 rOStm.SetError( SVSTREAM_GENERALERROR );
1911 	}
1912 
1913     return rOStm;
1914 }
1915