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