update emoji autocorrect entries from po-files
[LibreOffice.git] / vcl / source / gdi / impgraph.cxx
bloba49100208a069b46af62735bb0dd2494723be41f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "sal/config.h"
22 #include <comphelper/processfactory.hxx>
23 #include <tools/fract.hxx>
24 #include <tools/vcompat.hxx>
25 #include <tools/urlobj.hxx>
26 #include <tools/debug.hxx>
27 #include <tools/stream.hxx>
28 #include <tools/helpers.hxx>
29 #include <ucbhelper/content.hxx>
30 #include <unotools/ucbstreamhelper.hxx>
31 #include <unotools/tempfile.hxx>
32 #include <vcl/outdev.hxx>
33 #include <vcl/virdev.hxx>
34 #include <vcl/gfxlink.hxx>
35 #include <vcl/cvtgrf.hxx>
36 #include <vcl/graph.hxx>
37 #include <vcl/metaact.hxx>
38 #include <impgraph.hxx>
39 #include <com/sun/star/ucb/CommandAbortedException.hpp>
40 #include <vcl/dibtools.hxx>
41 #include <memory>
43 #define GRAPHIC_MTFTOBMP_MAXEXT 2048
44 #define GRAPHIC_STREAMBUFSIZE 8192UL
46 #define SYS_WINMETAFILE 0x00000003L
47 #define SYS_WNTMETAFILE 0x00000004L
48 #define SYS_OS2METAFILE 0x00000005L
49 #define SYS_MACMETAFILE 0x00000006L
51 #define GRAPHIC_FORMAT_50 static_cast<sal_uInt32>(COMPAT_FORMAT( 'G', 'R', 'F', '5' ))
52 #define NATIVE_FORMAT_50 static_cast<sal_uInt32>(COMPAT_FORMAT( 'N', 'A', 'T', '5' ))
54 struct ImpSwapFile
56 INetURLObject aSwapURL;
57 sal_uLong nRefCount;
60 class ReaderData
62 public:
63 Size maPreviewSize;
66 GraphicReader::~GraphicReader()
68 delete mpReaderData;
71 void GraphicReader::DisablePreviewMode()
73 if( mpReaderData )
74 mpReaderData->maPreviewSize = Size( 0, 0 );
77 void GraphicReader::SetPreviewSize( const Size& rSize )
79 if( !mpReaderData )
80 mpReaderData = new ReaderData;
81 mpReaderData->maPreviewSize = rSize;
84 Size GraphicReader::GetPreviewSize() const
86 Size aSize( 0, 0 );
87 if( mpReaderData )
88 aSize = mpReaderData->maPreviewSize;
89 return aSize;
92 ImpGraphic::ImpGraphic() :
93 mpAnimation ( NULL ),
94 mpContext ( NULL ),
95 mpSwapFile ( NULL ),
96 mpGfxLink ( NULL ),
97 meType ( GRAPHIC_NONE ),
98 mnSizeBytes ( 0UL ),
99 mnRefCount ( 1UL ),
100 mbSwapOut ( false ),
101 mbSwapUnderway ( false )
105 ImpGraphic::ImpGraphic( const ImpGraphic& rImpGraphic ) :
106 maMetaFile ( rImpGraphic.maMetaFile ),
107 maEx ( rImpGraphic.maEx ),
108 mpContext ( NULL ),
109 mpSwapFile ( rImpGraphic.mpSwapFile ),
110 meType ( rImpGraphic.meType ),
111 mnSizeBytes ( rImpGraphic.mnSizeBytes ),
112 mnRefCount ( 1UL ),
113 mbSwapOut ( rImpGraphic.mbSwapOut ),
114 mbSwapUnderway ( false )
116 if( mpSwapFile )
117 mpSwapFile->nRefCount++;
119 if( rImpGraphic.mpGfxLink )
120 mpGfxLink = new GfxLink( *rImpGraphic.mpGfxLink );
121 else
122 mpGfxLink = NULL;
124 if( rImpGraphic.mpAnimation )
126 mpAnimation = new Animation( *rImpGraphic.mpAnimation );
127 maEx = mpAnimation->GetBitmapEx();
129 else
130 mpAnimation = NULL;
132 maSvgData = rImpGraphic.maSvgData;
135 ImpGraphic::ImpGraphic( const Bitmap& rBitmap ) :
136 maEx ( rBitmap ),
137 mpAnimation ( NULL ),
138 mpContext ( NULL ),
139 mpSwapFile ( NULL ),
140 mpGfxLink ( NULL ),
141 meType ( !rBitmap.IsEmpty() ? GRAPHIC_BITMAP : GRAPHIC_NONE ),
142 mnSizeBytes ( 0UL ),
143 mnRefCount ( 1UL ),
144 mbSwapOut ( false ),
145 mbSwapUnderway ( false )
149 ImpGraphic::ImpGraphic( const BitmapEx& rBitmapEx ) :
150 maEx ( rBitmapEx ),
151 mpAnimation ( NULL ),
152 mpContext ( NULL ),
153 mpSwapFile ( NULL ),
154 mpGfxLink ( NULL ),
155 meType ( !rBitmapEx.IsEmpty() ? GRAPHIC_BITMAP : GRAPHIC_NONE ),
156 mnSizeBytes ( 0UL ),
157 mnRefCount ( 1UL ),
158 mbSwapOut ( false ),
159 mbSwapUnderway ( false )
163 ImpGraphic::ImpGraphic(const SvgDataPtr& rSvgDataPtr)
164 : mpAnimation( NULL ),
165 mpContext( NULL ),
166 mpSwapFile( NULL ),
167 mpGfxLink( NULL ),
168 meType( rSvgDataPtr.get() ? GRAPHIC_BITMAP : GRAPHIC_NONE ),
169 mnSizeBytes( 0UL ),
170 mnRefCount( 1UL ),
171 mbSwapOut( false ),
172 mbSwapUnderway( false ),
173 maSvgData(rSvgDataPtr)
177 ImpGraphic::ImpGraphic( const Animation& rAnimation ) :
178 maEx ( rAnimation.GetBitmapEx() ),
179 mpAnimation ( new Animation( rAnimation ) ),
180 mpContext ( NULL ),
181 mpSwapFile ( NULL ),
182 mpGfxLink ( NULL ),
183 meType ( GRAPHIC_BITMAP ),
184 mnSizeBytes ( 0UL ),
185 mnRefCount ( 1UL ),
186 mbSwapOut ( false ),
187 mbSwapUnderway ( false )
191 ImpGraphic::ImpGraphic( const GDIMetaFile& rMtf ) :
192 maMetaFile ( rMtf ),
193 mpAnimation ( NULL ),
194 mpContext ( NULL ),
195 mpSwapFile ( NULL ),
196 mpGfxLink ( NULL ),
197 meType ( GRAPHIC_GDIMETAFILE ),
198 mnSizeBytes ( 0UL ),
199 mnRefCount ( 1UL ),
200 mbSwapOut ( false ),
201 mbSwapUnderway ( false )
205 ImpGraphic::~ImpGraphic()
207 ImplClear();
209 if( reinterpret_cast<sal_uLong>(mpContext) > 1UL )
210 delete mpContext;
213 ImpGraphic& ImpGraphic::operator=( const ImpGraphic& rImpGraphic )
215 if( &rImpGraphic != this )
217 if( !mbSwapUnderway )
218 ImplClear();
220 maMetaFile = rImpGraphic.maMetaFile;
221 meType = rImpGraphic.meType;
222 mnSizeBytes = rImpGraphic.mnSizeBytes;
224 delete mpAnimation;
226 if ( rImpGraphic.mpAnimation )
228 mpAnimation = new Animation( *rImpGraphic.mpAnimation );
229 maEx = mpAnimation->GetBitmapEx();
231 else
233 mpAnimation = NULL;
234 maEx = rImpGraphic.maEx;
237 if( !mbSwapUnderway )
239 mbSwapOut = rImpGraphic.mbSwapOut;
240 mpSwapFile = rImpGraphic.mpSwapFile;
242 if( mpSwapFile )
243 mpSwapFile->nRefCount++;
246 delete mpGfxLink;
248 if( rImpGraphic.mpGfxLink )
249 mpGfxLink = new GfxLink( *rImpGraphic.mpGfxLink );
250 else
251 mpGfxLink = NULL;
253 maSvgData = rImpGraphic.maSvgData;
256 return *this;
259 bool ImpGraphic::operator==( const ImpGraphic& rImpGraphic ) const
261 bool bRet = false;
263 if( this == &rImpGraphic )
264 bRet = true;
265 else if( !ImplIsSwapOut() && ( rImpGraphic.meType == meType ) )
267 switch( meType )
269 case( GRAPHIC_NONE ):
270 bRet = true;
271 break;
273 case( GRAPHIC_GDIMETAFILE ):
275 if( rImpGraphic.maMetaFile == maMetaFile )
276 bRet = true;
278 break;
280 case( GRAPHIC_BITMAP ):
282 if(maSvgData.get())
284 if(maSvgData == rImpGraphic.maSvgData)
286 bRet = true;
288 else if(rImpGraphic.maSvgData)
290 if(maSvgData->getSvgDataArrayLength() == rImpGraphic.maSvgData->getSvgDataArrayLength())
292 if(0 == memcmp(
293 maSvgData->getSvgDataArray().get(),
294 rImpGraphic.maSvgData->getSvgDataArray().get(),
295 maSvgData->getSvgDataArrayLength()))
297 bRet = true;
302 else if( mpAnimation )
304 if( rImpGraphic.mpAnimation && ( *rImpGraphic.mpAnimation == *mpAnimation ) )
305 bRet = true;
307 else if( !rImpGraphic.mpAnimation && ( rImpGraphic.maEx == maEx ) )
309 bRet = true;
312 break;
314 default:
315 break;
319 return bRet;
322 void ImpGraphic::ImplClearGraphics( bool bCreateSwapInfo )
324 if( bCreateSwapInfo && !ImplIsSwapOut() )
326 maSwapInfo.maPrefMapMode = ImplGetPrefMapMode();
327 maSwapInfo.maPrefSize = ImplGetPrefSize();
330 maEx.Clear();
331 maMetaFile.Clear();
333 if( mpAnimation )
335 mpAnimation->Clear();
336 delete mpAnimation;
337 mpAnimation = NULL;
340 if( mpGfxLink )
342 delete mpGfxLink;
343 mpGfxLink = NULL;
346 maSvgData.reset();
349 void ImpGraphic::ImplClear()
351 if( mpSwapFile )
353 if( mpSwapFile->nRefCount > 1 )
354 mpSwapFile->nRefCount--;
355 else
359 ::ucbhelper::Content aCnt( mpSwapFile->aSwapURL.GetMainURL( INetURLObject::NO_DECODE ),
360 ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >(),
361 comphelper::getProcessComponentContext() );
363 aCnt.executeCommand( OUString("delete"),
364 ::com::sun::star::uno::makeAny( true ) );
366 catch( const ::com::sun::star::ucb::ContentCreationException& )
369 catch( const ::com::sun::star::uno::RuntimeException& )
372 catch( const ::com::sun::star::ucb::CommandAbortedException& )
375 catch( const ::com::sun::star::uno::Exception& )
379 delete mpSwapFile;
382 mpSwapFile = NULL;
385 mbSwapOut = false;
387 // cleanup
388 ImplClearGraphics( false );
389 meType = GRAPHIC_NONE;
390 mnSizeBytes = 0;
394 void ImpGraphic::ImplSetDefaultType()
396 ImplClear();
397 meType = GRAPHIC_DEFAULT;
400 bool ImpGraphic::ImplIsSupportedGraphic() const
402 return( meType != GRAPHIC_NONE );
405 bool ImpGraphic::ImplIsTransparent() const
407 bool bRet(true);
409 if( meType == GRAPHIC_BITMAP && !maSvgData.get())
411 bRet = ( mpAnimation ? mpAnimation->IsTransparent() : maEx.IsTransparent() );
414 return bRet;
417 bool ImpGraphic::ImplIsAlpha() const
419 bool bRet(false);
421 if(maSvgData.get())
423 bRet = true;
425 else if( meType == GRAPHIC_BITMAP )
427 bRet = ( NULL == mpAnimation ) && maEx.IsAlpha();
430 return bRet;
433 bool ImpGraphic::ImplIsAnimated() const
435 return( mpAnimation != NULL );
438 bool ImpGraphic::ImplIsEPS() const
440 return( ( meType == GRAPHIC_GDIMETAFILE ) &&
441 ( maMetaFile.GetActionSize() > 0 ) &&
442 ( maMetaFile.GetAction( 0 )->GetType() == MetaActionType::EPS ) );
445 Bitmap ImpGraphic::ImplGetBitmap(const GraphicConversionParameters& rParameters) const
447 Bitmap aRetBmp;
449 if( meType == GRAPHIC_BITMAP )
451 if(maSvgData.get() && maEx.IsEmpty())
453 // use maEx as local buffer for rendered svg
454 const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement();
457 const BitmapEx& rRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx );
458 const Color aReplaceColor( COL_WHITE );
460 aRetBmp = rRetBmpEx.GetBitmap( &aReplaceColor );
462 if(rParameters.getSizePixel().Width() || rParameters.getSizePixel().Height())
463 aRetBmp.Scale(rParameters.getSizePixel());
465 else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() )
467 if(maEx.IsEmpty())
469 // calculate size
470 ScopedVclPtrInstance< VirtualDevice > aVDev;
471 Size aDrawSize(aVDev->LogicToPixel(maMetaFile.GetPrefSize(), maMetaFile.GetPrefMapMode()));
473 if(rParameters.getSizePixel().Width() && rParameters.getSizePixel().Height())
475 // apply given size if exists
476 aDrawSize = rParameters.getSizePixel();
479 if(aDrawSize.Width() && aDrawSize.Height() && !rParameters.getUnlimitedSize()
480 && (aDrawSize.Width() > GRAPHIC_MTFTOBMP_MAXEXT || aDrawSize.Height() > GRAPHIC_MTFTOBMP_MAXEXT))
482 // limit bitmap size to a maximum of GRAPHIC_MTFTOBMP_MAXEXT x GRAPHIC_MTFTOBMP_MAXEXT
483 double fWH((double)aDrawSize.Width() / (double)aDrawSize.Height());
485 if(fWH <= 1.0)
487 aDrawSize.setWidth(basegfx::fround(GRAPHIC_MTFTOBMP_MAXEXT * fWH));
488 aDrawSize.setHeight(GRAPHIC_MTFTOBMP_MAXEXT);
490 else
492 aDrawSize.setWidth(GRAPHIC_MTFTOBMP_MAXEXT);
493 aDrawSize.setHeight(basegfx::fround(GRAPHIC_MTFTOBMP_MAXEXT / fWH));
497 // calculate pixel size. Normally, it's the same as aDrawSize, but may
498 // need to be extended when hairlines are on the right or bottom edge
499 Size aPixelSize(aDrawSize);
501 if(GRAPHIC_GDIMETAFILE == ImplGetType())
503 // get hairline and full bound rect
504 Rectangle aHairlineRect;
505 const Rectangle aRect(maMetaFile.GetBoundRect(*aVDev.get(), &aHairlineRect));
507 if(!aRect.IsEmpty() && !aHairlineRect.IsEmpty())
509 // expand if needed to allow bottom and right hairlines to be added
510 if(aRect.Right() == aHairlineRect.Right())
512 aPixelSize.setWidth(aPixelSize.getWidth() + 1);
515 if(aRect.Bottom() == aHairlineRect.Bottom())
517 aPixelSize.setHeight(aPixelSize.getHeight() + 1);
522 if(aVDev->SetOutputSizePixel(aPixelSize))
524 if(rParameters.getAntiAliase())
526 aVDev->SetAntialiasing(aVDev->GetAntialiasing() | AntialiasingFlags::EnableB2dDraw);
529 if(rParameters.getSnapHorVerLines())
531 aVDev->SetAntialiasing(aVDev->GetAntialiasing() | AntialiasingFlags::PixelSnapHairline);
534 ImplDraw( aVDev.get(), Point(), aDrawSize );
536 // use maEx as local buffer for rendered metafile
537 const_cast< ImpGraphic* >(this)->maEx = aVDev->GetBitmap( Point(), aVDev->GetOutputSizePixel() );
541 aRetBmp = maEx.GetBitmap();
544 if( !!aRetBmp )
546 aRetBmp.SetPrefMapMode( ImplGetPrefMapMode() );
547 aRetBmp.SetPrefSize( ImplGetPrefSize() );
550 return aRetBmp;
553 BitmapEx ImpGraphic::ImplGetBitmapEx(const GraphicConversionParameters& rParameters) const
555 BitmapEx aRetBmpEx;
557 if( meType == GRAPHIC_BITMAP )
559 if(maSvgData.get() && maEx.IsEmpty())
561 // use maEx as local buffer for rendered svg
562 const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement();
565 aRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx );
567 if(rParameters.getSizePixel().Width() || rParameters.getSizePixel().Height())
569 aRetBmpEx.Scale(
570 rParameters.getSizePixel(),
571 rParameters.getScaleHighQuality() ? BmpScaleFlag::Interpolate : BmpScaleFlag::Fast);
574 else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() )
576 if(maEx.IsEmpty())
578 const ImpGraphic aMonoMask( maMetaFile.GetMonochromeMtf( COL_BLACK ) );
580 // use maEx as local buffer for rendered metafile
581 const_cast< ImpGraphic* >(this)->maEx = BitmapEx(ImplGetBitmap(rParameters), aMonoMask.ImplGetBitmap(rParameters));
584 aRetBmpEx = maEx;
587 return aRetBmpEx;
590 Animation ImpGraphic::ImplGetAnimation() const
592 Animation aAnimation;
594 if( mpAnimation )
595 aAnimation = *mpAnimation;
597 return aAnimation;
600 const GDIMetaFile& ImpGraphic::ImplGetGDIMetaFile() const
602 if (GRAPHIC_BITMAP == meType && !maMetaFile.GetActionSize())
604 // #i119735#
605 // Use the local maMetaFile as container for a metafile-representation
606 // of the bitmap graphic. This will be done only once, thus be buffered.
607 // I checked all usages of maMetaFile, it is only used when type is not
608 // GRAPHIC_BITMAP. In operator= it will get copied, thus buffering will
609 // survive copying (change this if not wanted)
610 ImpGraphic* pThat = const_cast< ImpGraphic* >(this);
612 if(maSvgData.get() && !maEx)
614 // use maEx as local buffer for rendered svg
615 pThat->maEx = maSvgData->getReplacement();
618 // #123983# directly create a metafile with the same PrefSize and PrefMapMode
619 // the bitmap has, this will be an always correct metafile
620 if(maEx.IsTransparent())
622 pThat->maMetaFile.AddAction(new MetaBmpExScaleAction(Point(), maEx.GetPrefSize(), maEx));
624 else
626 pThat->maMetaFile.AddAction(new MetaBmpScaleAction(Point(), maEx.GetPrefSize(), maEx.GetBitmap()));
629 pThat->maMetaFile.Stop();
630 pThat->maMetaFile.WindStart();
631 pThat->maMetaFile.SetPrefSize(maEx.GetPrefSize());
632 pThat->maMetaFile.SetPrefMapMode(maEx.GetPrefMapMode());
635 return maMetaFile;
638 Size ImpGraphic::ImplGetPrefSize() const
640 Size aSize;
642 if( ImplIsSwapOut() )
643 aSize = maSwapInfo.maPrefSize;
644 else
646 switch( meType )
648 case( GRAPHIC_NONE ):
649 case( GRAPHIC_DEFAULT ):
650 break;
652 case( GRAPHIC_BITMAP ):
654 if(maSvgData.get() && maEx.IsEmpty())
656 // svg not yet buffered in maEx, return size derived from range
657 const basegfx::B2DRange& rRange = maSvgData->getRange();
659 aSize = Size(basegfx::fround(rRange.getWidth()), basegfx::fround(rRange.getHeight()));
661 else
663 aSize = maEx.GetPrefSize();
665 if( !aSize.Width() || !aSize.Height() )
667 aSize = maEx.GetSizePixel();
671 break;
673 default:
675 if( ImplIsSupportedGraphic() )
676 aSize = maMetaFile.GetPrefSize();
678 break;
682 return aSize;
685 void ImpGraphic::ImplSetPrefSize( const Size& rPrefSize )
687 switch( meType )
689 case( GRAPHIC_NONE ):
690 case( GRAPHIC_DEFAULT ):
691 break;
693 case( GRAPHIC_BITMAP ):
695 //UUUU used when importing a writer FlyFrame with SVG as graphic, added conversion
696 // to allow setting the PrefSize at the BitmapEx to hold it
697 if(maSvgData.get() && maEx.IsEmpty())
699 // use maEx as local buffer for rendered svg
700 const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement();
703 // #108077# Push through pref size to animation object,
704 // will be lost on copy otherwise
705 if( ImplIsAnimated() )
707 const_cast< BitmapEx& >(mpAnimation->GetBitmapEx()).SetPrefSize( rPrefSize );
710 maEx.SetPrefSize( rPrefSize );
712 break;
714 default:
716 if( ImplIsSupportedGraphic() )
717 maMetaFile.SetPrefSize( rPrefSize );
719 break;
723 MapMode ImpGraphic::ImplGetPrefMapMode() const
725 MapMode aMapMode;
727 if( ImplIsSwapOut() )
728 aMapMode = maSwapInfo.maPrefMapMode;
729 else
731 switch( meType )
733 case( GRAPHIC_NONE ):
734 case( GRAPHIC_DEFAULT ):
735 break;
737 case( GRAPHIC_BITMAP ):
739 if(maSvgData.get() && maEx.IsEmpty())
741 // svg not yet buffered in maEx, return default PrefMapMode
742 aMapMode = MapMode(MAP_100TH_MM);
744 else
746 const Size aSize( maEx.GetPrefSize() );
748 if ( aSize.Width() && aSize.Height() )
749 aMapMode = maEx.GetPrefMapMode();
752 break;
754 default:
756 if( ImplIsSupportedGraphic() )
757 return maMetaFile.GetPrefMapMode();
759 break;
763 return aMapMode;
766 void ImpGraphic::ImplSetPrefMapMode( const MapMode& rPrefMapMode )
768 switch( meType )
770 case( GRAPHIC_NONE ):
771 case( GRAPHIC_DEFAULT ):
772 break;
774 case( GRAPHIC_BITMAP ):
776 if(maSvgData.get())
778 // ignore for Svg. If this is really used (except the grfcache)
779 // it can be extended by using maEx as buffer for maSvgData->getReplacement()
781 else
783 // #108077# Push through pref mapmode to animation object,
784 // will be lost on copy otherwise
785 if( ImplIsAnimated() )
787 const_cast< BitmapEx& >(mpAnimation->GetBitmapEx()).SetPrefMapMode( rPrefMapMode );
790 maEx.SetPrefMapMode( rPrefMapMode );
793 break;
795 default:
797 if( ImplIsSupportedGraphic() )
798 maMetaFile.SetPrefMapMode( rPrefMapMode );
800 break;
804 sal_uLong ImpGraphic::ImplGetSizeBytes() const
806 if( 0 == mnSizeBytes )
808 if( meType == GRAPHIC_BITMAP )
810 if(maSvgData.get())
812 mnSizeBytes = maSvgData->getSvgDataArrayLength();
814 else
816 mnSizeBytes = mpAnimation ? mpAnimation->GetSizeBytes() : maEx.GetSizeBytes();
819 else if( meType == GRAPHIC_GDIMETAFILE )
821 mnSizeBytes = maMetaFile.GetSizeBytes();
825 return mnSizeBytes;
828 void ImpGraphic::ImplDraw( OutputDevice* pOutDev, const Point& rDestPt ) const
830 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
832 switch( meType )
834 case( GRAPHIC_DEFAULT ):
835 break;
837 case( GRAPHIC_BITMAP ):
839 if(maSvgData.get() && !maEx)
841 // use maEx as local buffer for rendered svg
842 const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement();
845 if ( mpAnimation )
847 mpAnimation->Draw( pOutDev, rDestPt );
849 else
851 maEx.Draw( pOutDev, rDestPt );
854 break;
856 default:
857 ImplDraw( pOutDev, rDestPt, maMetaFile.GetPrefSize() );
858 break;
863 void ImpGraphic::ImplDraw( OutputDevice* pOutDev,
864 const Point& rDestPt, const Size& rDestSize ) const
866 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
868 switch( meType )
870 case( GRAPHIC_DEFAULT ):
871 break;
873 case( GRAPHIC_BITMAP ):
875 if(maSvgData.get() && maEx.IsEmpty())
877 // use maEx as local buffer for rendered svg
878 const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement();
881 if( mpAnimation )
883 mpAnimation->Draw( pOutDev, rDestPt, rDestSize );
885 else
887 maEx.Draw( pOutDev, rDestPt, rDestSize );
890 break;
892 default:
894 const_cast<ImpGraphic*>(this)->maMetaFile.WindStart();
895 const_cast<ImpGraphic*>(this)->maMetaFile.Play( pOutDev, rDestPt, rDestSize );
896 const_cast<ImpGraphic*>(this)->maMetaFile.WindStart();
898 break;
903 void ImpGraphic::ImplStartAnimation( OutputDevice* pOutDev, const Point& rDestPt,
904 const Size& rDestSize, long nExtraData,
905 OutputDevice* pFirstFrameOutDev )
907 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation )
908 mpAnimation->Start( pOutDev, rDestPt, rDestSize, nExtraData, pFirstFrameOutDev );
911 void ImpGraphic::ImplStopAnimation( OutputDevice* pOutDev, long nExtraData )
913 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation )
914 mpAnimation->Stop( pOutDev, nExtraData );
917 void ImpGraphic::ImplSetAnimationNotifyHdl( const Link<>& rLink )
919 if( mpAnimation )
920 mpAnimation->SetNotifyHdl( rLink );
923 Link<> ImpGraphic::ImplGetAnimationNotifyHdl() const
925 Link<> aLink;
927 if( mpAnimation )
928 aLink = mpAnimation->GetNotifyHdl();
930 return aLink;
933 sal_uLong ImpGraphic::ImplGetAnimationLoopCount() const
935 return( mpAnimation ? mpAnimation->GetLoopCount() : 0UL );
939 void ImpGraphic::ImplSetContext( GraphicReader* pReader )
941 mpContext = pReader;
944 bool ImpGraphic::ImplReadEmbedded( SvStream& rIStm )
946 MapMode aMapMode;
947 Size aSize;
948 sal_uInt32 nId;
949 sal_Int32 nType;
950 sal_Int32 nLen;
951 const SvStreamEndian nOldFormat = rIStm.GetEndian();
952 bool bRet = false;
954 rIStm.SetEndian( SvStreamEndian::LITTLE );
955 rIStm.ReadUInt32( nId );
957 // check version
958 if( GRAPHIC_FORMAT_50 == nId )
960 // read new style header
961 VersionCompat* pCompat = new VersionCompat( rIStm, StreamMode::READ );
963 rIStm.ReadInt32( nType );
964 rIStm.ReadInt32( nLen );
965 ReadPair( rIStm, aSize );
966 ReadMapMode( rIStm, aMapMode );
968 delete pCompat;
970 else
972 // read old style header
973 sal_Int32 nWidth, nHeight;
974 sal_Int32 nMapMode, nScaleNumX, nScaleDenomX;
975 sal_Int32 nScaleNumY, nScaleDenomY, nOffsX, nOffsY;
977 rIStm.SeekRel( -4L );
979 rIStm.ReadInt32( nType ).ReadInt32( nLen ).ReadInt32( nWidth ).ReadInt32( nHeight );
980 rIStm.ReadInt32( nMapMode ).ReadInt32( nScaleNumX ).ReadInt32( nScaleDenomX ).ReadInt32( nScaleNumY );
981 rIStm.ReadInt32( nScaleDenomY ).ReadInt32( nOffsX ).ReadInt32( nOffsY );
983 // swapped
984 if( nType > 100L )
986 nType = OSL_SWAPDWORD( nType );
987 nLen = OSL_SWAPDWORD( nLen );
988 nWidth = OSL_SWAPDWORD( nWidth );
989 nHeight = OSL_SWAPDWORD( nHeight );
990 nMapMode = OSL_SWAPDWORD( nMapMode );
991 nScaleNumX = OSL_SWAPDWORD( nScaleNumX );
992 nScaleDenomX = OSL_SWAPDWORD( nScaleDenomX );
993 nScaleNumY = OSL_SWAPDWORD( nScaleNumY );
994 nScaleDenomY = OSL_SWAPDWORD( nScaleDenomY );
995 nOffsX = OSL_SWAPDWORD( nOffsX );
996 nOffsY = OSL_SWAPDWORD( nOffsY );
999 aSize = Size( nWidth, nHeight );
1000 aMapMode = MapMode( (MapUnit) nMapMode, Point( nOffsX, nOffsY ),
1001 Fraction( nScaleNumX, nScaleDenomX ),
1002 Fraction( nScaleNumY, nScaleDenomY ) );
1005 meType = (GraphicType) nType;
1007 if( meType )
1009 if( meType == GRAPHIC_BITMAP )
1011 if(maSvgData.get() && maEx.IsEmpty())
1013 // use maEx as local buffer for rendered svg
1014 maEx = maSvgData->getReplacement();
1017 maEx.aBitmapSize = aSize;
1019 if( aMapMode != MapMode() )
1021 maEx.SetPrefMapMode( aMapMode );
1022 maEx.SetPrefSize( aSize );
1025 else
1027 maMetaFile.SetPrefMapMode( aMapMode );
1028 maMetaFile.SetPrefSize( aSize );
1031 if( meType == GRAPHIC_BITMAP || meType == GRAPHIC_GDIMETAFILE )
1033 ReadImpGraphic( rIStm, *this );
1034 bRet = ( rIStm.GetError() == 0UL );
1036 else if( sal::static_int_cast<sal_uLong>(meType) >= SYS_WINMETAFILE
1037 && sal::static_int_cast<sal_uLong>(meType) <= SYS_MACMETAFILE )
1039 Graphic aSysGraphic;
1040 sal_uLong nCvtType;
1042 switch( sal::static_int_cast<sal_uLong>(meType) )
1044 case( SYS_WINMETAFILE ):
1045 case( SYS_WNTMETAFILE ): nCvtType = CVT_WMF; break;
1046 case( SYS_OS2METAFILE ): nCvtType = CVT_MET; break;
1047 case( SYS_MACMETAFILE ): nCvtType = CVT_PCT; break;
1049 default:
1050 nCvtType = CVT_UNKNOWN;
1051 break;
1054 if( nType && GraphicConverter::Import( rIStm, aSysGraphic, nCvtType ) == ERRCODE_NONE )
1056 *this = ImpGraphic( aSysGraphic.GetGDIMetaFile() );
1057 bRet = ( rIStm.GetError() == 0UL );
1059 else
1060 meType = GRAPHIC_DEFAULT;
1063 if( bRet )
1065 ImplSetPrefMapMode( aMapMode );
1066 ImplSetPrefSize( aSize );
1069 else
1070 bRet = true;
1072 rIStm.SetEndian( nOldFormat );
1074 return bRet;
1077 bool ImpGraphic::ImplWriteEmbedded( SvStream& rOStm )
1079 bool bRet = false;
1081 if( ( meType != GRAPHIC_NONE ) && ( meType != GRAPHIC_DEFAULT ) && !ImplIsSwapOut() )
1083 const MapMode aMapMode( ImplGetPrefMapMode() );
1084 const Size aSize( ImplGetPrefSize() );
1085 const SvStreamEndian nOldFormat = rOStm.GetEndian();
1086 sal_uLong nDataFieldPos;
1088 rOStm.SetEndian( SvStreamEndian::LITTLE );
1090 // write correct version ( old style/new style header )
1091 if( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 )
1093 // write ID for new format (5.0)
1094 rOStm.WriteUInt32( GRAPHIC_FORMAT_50 );
1096 // write new style header
1097 VersionCompat* pCompat = new VersionCompat( rOStm, StreamMode::WRITE, 1 );
1099 rOStm.WriteInt32( meType );
1101 // data size is updated later
1102 nDataFieldPos = rOStm.Tell();
1103 rOStm.WriteInt32( 0 );
1105 WritePair( rOStm, aSize );
1106 WriteMapMode( rOStm, aMapMode );
1108 delete pCompat;
1110 else
1112 // write old style (<=4.0) header
1113 rOStm.WriteInt32( meType );
1115 // data size is updated later
1116 nDataFieldPos = rOStm.Tell();
1117 rOStm.WriteInt32( 0 );
1118 rOStm.WriteInt32( aSize.Width() );
1119 rOStm.WriteInt32( aSize.Height() );
1120 rOStm.WriteInt32( aMapMode.GetMapUnit() );
1121 rOStm.WriteInt32( aMapMode.GetScaleX().GetNumerator() );
1122 rOStm.WriteInt32( aMapMode.GetScaleX().GetDenominator() );
1123 rOStm.WriteInt32( aMapMode.GetScaleY().GetNumerator() );
1124 rOStm.WriteInt32( aMapMode.GetScaleY().GetDenominator() );
1125 rOStm.WriteInt32( aMapMode.GetOrigin().X() );
1126 rOStm.WriteInt32( aMapMode.GetOrigin().Y() );
1129 // write data block
1130 if( !rOStm.GetError() )
1132 const sal_uLong nDataStart = rOStm.Tell();
1134 if( ImplIsSupportedGraphic() )
1135 WriteImpGraphic( rOStm, *this );
1137 if( !rOStm.GetError() )
1139 const sal_uLong nStmPos2 = rOStm.Tell();
1140 rOStm.Seek( nDataFieldPos );
1141 rOStm.WriteInt32( nStmPos2 - nDataStart );
1142 rOStm.Seek( nStmPos2 );
1143 bRet = true;
1147 rOStm.SetEndian( nOldFormat );
1150 return bRet;
1153 bool ImpGraphic::ImplSwapOut()
1155 bool bRet = false;
1157 if( !ImplIsSwapOut() )
1159 ::utl::TempFile aTempFile;
1160 const INetURLObject aTmpURL( aTempFile.GetURL() );
1162 if( !aTmpURL.GetMainURL( INetURLObject::NO_DECODE ).isEmpty() )
1164 std::unique_ptr<SvStream> xOStm;
1167 xOStm.reset(::utl::UcbStreamHelper::CreateStream( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READWRITE | StreamMode::SHARE_DENYWRITE ));
1169 catch( const ::com::sun::star::uno::Exception& )
1172 if( xOStm )
1174 xOStm->SetVersion( SOFFICE_FILEFORMAT_50 );
1175 xOStm->SetCompressMode( SvStreamCompressFlags::NATIVE );
1177 if( ( bRet = ImplSwapOut( xOStm.get() ) ) )
1179 mpSwapFile = new ImpSwapFile;
1180 mpSwapFile->nRefCount = 1;
1181 mpSwapFile->aSwapURL = aTmpURL;
1183 else
1185 xOStm.reset();
1189 ::ucbhelper::Content aCnt( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ),
1190 ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >(),
1191 comphelper::getProcessComponentContext() );
1193 aCnt.executeCommand( OUString("delete"),
1194 ::com::sun::star::uno::makeAny( true ) );
1196 catch( const ::com::sun::star::ucb::ContentCreationException& )
1199 catch( const ::com::sun::star::uno::RuntimeException& )
1202 catch( const ::com::sun::star::ucb::CommandAbortedException& )
1205 catch( const ::com::sun::star::uno::Exception& )
1213 return bRet;
1216 void ImpGraphic::ImplSwapOutAsLink()
1218 ImplClearGraphics( true );
1219 mbSwapOut = true;
1222 bool ImpGraphic::ImplSwapOut( SvStream* xOStm )
1224 bool bRet = false;
1226 if( xOStm )
1228 xOStm->SetBufferSize( GRAPHIC_STREAMBUFSIZE );
1230 if( !xOStm->GetError() && ImplWriteEmbedded( *xOStm ) )
1232 xOStm->Flush();
1234 if( !xOStm->GetError() )
1236 ImplClearGraphics( true );
1237 bRet = mbSwapOut = true;
1241 else
1243 SAL_WARN("vcl.gdi", "Graphic SwapOut: No stream for swap out!");
1246 return bRet;
1249 bool ImpGraphic::ImplSwapIn()
1251 bool bRet = false;
1253 if( ImplIsSwapOut() )
1255 OUString aSwapURL;
1257 if( mpSwapFile )
1258 aSwapURL = mpSwapFile->aSwapURL.GetMainURL( INetURLObject::NO_DECODE );
1260 if( !aSwapURL.isEmpty() )
1262 std::unique_ptr<SvStream> xIStm;
1265 xIStm.reset(::utl::UcbStreamHelper::CreateStream( aSwapURL, STREAM_READWRITE | StreamMode::SHARE_DENYWRITE ));
1267 catch( const ::com::sun::star::uno::Exception& )
1271 if( xIStm )
1273 xIStm->SetVersion( SOFFICE_FILEFORMAT_50 );
1274 xIStm->SetCompressMode( SvStreamCompressFlags::NATIVE );
1276 bRet = ImplSwapIn( xIStm.get() );
1277 xIStm.reset();
1279 if( mpSwapFile )
1281 if( mpSwapFile->nRefCount > 1 )
1282 mpSwapFile->nRefCount--;
1283 else
1287 ::ucbhelper::Content aCnt( aSwapURL,
1288 ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >(),
1289 comphelper::getProcessComponentContext() );
1291 aCnt.executeCommand( OUString("delete"),
1292 ::com::sun::star::uno::makeAny( true ) );
1294 catch( const ::com::sun::star::ucb::ContentCreationException& )
1297 catch( const ::com::sun::star::uno::RuntimeException& )
1300 catch( const ::com::sun::star::ucb::CommandAbortedException& )
1303 catch( const ::com::sun::star::uno::Exception& )
1307 delete mpSwapFile;
1310 mpSwapFile = NULL;
1316 return bRet;
1319 bool ImpGraphic::ImplSwapIn( SvStream* xIStm )
1321 bool bRet = false;
1323 if( xIStm )
1325 xIStm->SetBufferSize( GRAPHIC_STREAMBUFSIZE );
1327 if( !xIStm->GetError() )
1329 mbSwapUnderway = true;
1330 bRet = ImplReadEmbedded( *xIStm );
1331 mbSwapUnderway = false;
1333 if( !bRet )
1334 ImplClear();
1335 else
1336 mbSwapOut = false;
1340 return bRet;
1344 void ImpGraphic::ImplSetLink( const GfxLink& rGfxLink )
1346 delete mpGfxLink;
1347 mpGfxLink = new GfxLink( rGfxLink );
1349 if( mpGfxLink->IsNative() )
1350 mpGfxLink->SwapOut();
1353 GfxLink ImpGraphic::ImplGetLink()
1355 return( mpGfxLink ? *mpGfxLink : GfxLink() );
1358 bool ImpGraphic::ImplIsLink() const
1360 return ( mpGfxLink != NULL );
1363 BitmapChecksum ImpGraphic::ImplGetChecksum() const
1365 BitmapChecksum nRet = 0;
1367 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
1369 switch( meType )
1371 case( GRAPHIC_DEFAULT ):
1372 break;
1374 case( GRAPHIC_BITMAP ):
1376 if(maSvgData.get() && maEx.IsEmpty())
1378 // use maEx as local buffer for rendered svg
1379 const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement();
1382 if( mpAnimation )
1384 nRet = mpAnimation->GetChecksum();
1386 else
1388 nRet = maEx.GetChecksum();
1391 break;
1393 default:
1394 nRet = maMetaFile.GetChecksum();
1395 break;
1399 return nRet;
1402 bool ImpGraphic::ImplExportNative( SvStream& rOStm ) const
1404 bool bResult = false;
1406 if( !rOStm.GetError() )
1408 if( !ImplIsSwapOut() )
1410 if( mpGfxLink && mpGfxLink->IsNative() )
1411 bResult = mpGfxLink->ExportNative( rOStm );
1412 else
1414 WriteImpGraphic( rOStm, *this );
1415 bResult = ( rOStm.GetError() == ERRCODE_NONE );
1418 else
1419 rOStm.SetError( SVSTREAM_GENERALERROR );
1422 return bResult;
1426 SvStream& ReadImpGraphic( SvStream& rIStm, ImpGraphic& rImpGraphic )
1428 if( !rIStm.GetError() )
1430 const sal_uLong nStmPos1 = rIStm.Tell();
1431 sal_uInt32 nTmp;
1433 if ( !rImpGraphic.mbSwapUnderway )
1434 rImpGraphic.ImplClear();
1436 // read Id
1437 rIStm.ReadUInt32( nTmp );
1439 // if there is no more data, avoid further expensive
1440 // reading which will create VDevs and other stuff, just to
1441 // read nothing. CAUTION: Eof is only true AFTER reading another
1442 // byte, a speciality of SvMemoryStream (!)
1443 if(!rIStm.GetError() && !rIStm.IsEof())
1445 if( NATIVE_FORMAT_50 == nTmp )
1447 Graphic aGraphic;
1448 GfxLink aLink;
1449 VersionCompat* pCompat;
1451 // read compat info
1452 pCompat = new VersionCompat( rIStm, StreamMode::READ );
1453 delete pCompat;
1455 ReadGfxLink( rIStm, aLink );
1457 // set dummy link to avoid creation of additional link after filtering;
1458 // we set a default link to avoid unnecessary swapping of native data
1459 aGraphic.SetLink( GfxLink() );
1461 if( !rIStm.GetError() && aLink.LoadNative( aGraphic ) )
1463 // set link only, if no other link was set
1464 const bool bSetLink = ( rImpGraphic.mpGfxLink == NULL );
1466 // assign graphic
1467 rImpGraphic = *aGraphic.ImplGetImpGraphic();
1469 if( aLink.IsPrefMapModeValid() )
1470 rImpGraphic.ImplSetPrefMapMode( aLink.GetPrefMapMode() );
1472 if( aLink.IsPrefSizeValid() )
1473 rImpGraphic.ImplSetPrefSize( aLink.GetPrefSize() );
1475 if( bSetLink )
1476 rImpGraphic.ImplSetLink( aLink );
1478 else
1480 rIStm.Seek( nStmPos1 );
1481 rIStm.SetError( ERRCODE_IO_WRONGFORMAT );
1484 else
1486 BitmapEx aBmpEx;
1487 const SvStreamEndian nOldFormat = rIStm.GetEndian();
1489 rIStm.SeekRel( -4 );
1490 rIStm.SetEndian( SvStreamEndian::LITTLE );
1491 ReadDIBBitmapEx(aBmpEx, rIStm);
1493 if( !rIStm.GetError() )
1495 sal_uInt32 nMagic1(0), nMagic2(0);
1496 sal_uLong nActPos = rIStm.Tell();
1498 rIStm.ReadUInt32( nMagic1 ).ReadUInt32( nMagic2 );
1499 rIStm.Seek( nActPos );
1501 rImpGraphic = ImpGraphic( aBmpEx );
1503 if( !rIStm.GetError() && ( 0x5344414e == nMagic1 ) && ( 0x494d4931 == nMagic2 ) )
1505 delete rImpGraphic.mpAnimation;
1506 rImpGraphic.mpAnimation = new Animation;
1507 ReadAnimation( rIStm, *rImpGraphic.mpAnimation );
1509 // #108077# manually set loaded BmpEx to Animation
1510 // (which skips loading its BmpEx if already done)
1511 rImpGraphic.mpAnimation->SetBitmapEx(aBmpEx);
1513 else
1514 rIStm.ResetError();
1516 else
1518 GDIMetaFile aMtf;
1520 rIStm.Seek( nStmPos1 );
1521 rIStm.ResetError();
1522 ReadGDIMetaFile( rIStm, aMtf );
1524 if( !rIStm.GetError() )
1526 rImpGraphic = aMtf;
1528 else
1530 // try to stream in Svg defining data (length, byte array and evtl. path)
1531 // See below (operator<<) for more information
1532 const sal_uInt32 nSvgMagic((sal_uInt32('s') << 24) | (sal_uInt32('v') << 16) | (sal_uInt32('g') << 8) | sal_uInt32('0'));
1533 sal_uInt32 nMagic;
1534 rIStm.Seek(nStmPos1);
1535 rIStm.ResetError();
1536 rIStm.ReadUInt32( nMagic );
1538 if(nSvgMagic == nMagic)
1540 sal_uInt32 mnSvgDataArrayLength(0);
1541 rIStm.ReadUInt32( mnSvgDataArrayLength );
1543 if(mnSvgDataArrayLength)
1545 SvgDataArray aNewData(new sal_uInt8[mnSvgDataArrayLength]);
1546 OUString aPath;
1548 rIStm.Read(aNewData.get(), mnSvgDataArrayLength);
1549 aPath = rIStm.ReadUniOrByteString(rIStm.GetStreamCharSet());
1551 if(!rIStm.GetError())
1553 SvgDataPtr aSvgDataPtr(
1554 new SvgData(
1555 aNewData,
1556 mnSvgDataArrayLength,
1557 OUString(aPath)));
1559 rImpGraphic = aSvgDataPtr;
1564 rIStm.Seek(nStmPos1);
1568 rIStm.SetEndian( nOldFormat );
1573 return rIStm;
1576 SvStream& WriteImpGraphic( SvStream& rOStm, const ImpGraphic& rImpGraphic )
1578 if( !rOStm.GetError() )
1580 if( !rImpGraphic.ImplIsSwapOut() )
1582 if( ( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 ) &&
1583 ( rOStm.GetCompressMode() & SvStreamCompressFlags::NATIVE ) &&
1584 rImpGraphic.mpGfxLink && rImpGraphic.mpGfxLink->IsNative() )
1586 VersionCompat* pCompat;
1588 // native format
1589 rOStm.WriteUInt32( NATIVE_FORMAT_50 );
1591 // write compat info
1592 pCompat = new VersionCompat( rOStm, StreamMode::WRITE, 1 );
1593 delete pCompat;
1595 rImpGraphic.mpGfxLink->SetPrefMapMode( rImpGraphic.ImplGetPrefMapMode() );
1596 rImpGraphic.mpGfxLink->SetPrefSize( rImpGraphic.ImplGetPrefSize() );
1597 WriteGfxLink( rOStm, *rImpGraphic.mpGfxLink );
1599 else
1601 // own format
1602 const SvStreamEndian nOldFormat = rOStm.GetEndian();
1603 rOStm.SetEndian( SvStreamEndian::LITTLE );
1605 switch( rImpGraphic.ImplGetType() )
1607 case( GRAPHIC_NONE ):
1608 case( GRAPHIC_DEFAULT ):
1609 break;
1611 case GRAPHIC_BITMAP:
1613 if(rImpGraphic.getSvgData().get())
1615 // stream out Svg defining data (length, byte array and evtl. path)
1616 // this is used e.g. in swapping out graphic data and in transporting it over UNO API
1617 // as sequence of bytes, but AFAIK not written anywhere to any kind of file, so it should be
1618 // no problem to extend it; only used at runtime
1619 const sal_uInt32 nSvgMagic((sal_uInt32('s') << 24) | (sal_uInt32('v') << 16) | (sal_uInt32('g') << 8) | sal_uInt32('0'));
1621 rOStm.WriteUInt32( nSvgMagic );
1622 rOStm.WriteUInt32( rImpGraphic.getSvgData()->getSvgDataArrayLength() );
1623 rOStm.Write(rImpGraphic.getSvgData()->getSvgDataArray().get(), rImpGraphic.getSvgData()->getSvgDataArrayLength());
1624 rOStm.WriteUniOrByteString(rImpGraphic.getSvgData()->getPath(),
1625 rOStm.GetStreamCharSet());
1627 else if( rImpGraphic.ImplIsAnimated())
1629 WriteAnimation( rOStm, *rImpGraphic.mpAnimation );
1631 else
1633 WriteDIBBitmapEx(rImpGraphic.maEx, rOStm);
1636 break;
1638 default:
1640 if( rImpGraphic.ImplIsSupportedGraphic() )
1641 WriteGDIMetaFile( rOStm, rImpGraphic.maMetaFile );
1643 break;
1646 rOStm.SetEndian( nOldFormat );
1649 else
1650 rOStm.SetError( SVSTREAM_GENERALERROR );
1653 return rOStm;
1656 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */