/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_vcl.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // ----------- // - Defines - // ----------- #define GRAPHIC_MAXPARTLEN 256000L #define GRAPHIC_MTFTOBMP_MAXEXT 2048 #define GRAPHIC_STREAMBUFSIZE 8192UL #define SYS_WINMETAFILE 0x00000003L #define SYS_WNTMETAFILE 0x00000004L #define SYS_OS2METAFILE 0x00000005L #define SYS_MACMETAFILE 0x00000006L #define GRAPHIC_FORMAT_50 static_cast(COMPAT_FORMAT( 'G', 'R', 'F', '5' )) #define NATIVE_FORMAT_50 static_cast(COMPAT_FORMAT( 'N', 'A', 'T', '5' )) // --------------- // - ImpSwapFile - // --------------- struct ImpSwapFile { INetURLObject aSwapURL; sal_uLong nRefCount; }; // ----------------- // - Graphicreader - // ----------------- class ReaderData { public: Size maPreviewSize; }; GraphicReader::~GraphicReader() { delete mpReaderData; } // ------------------------------------------------------------------------ sal_Bool GraphicReader::IsPreviewModeEnabled() const { if( !mpReaderData ) return sal_False; if( mpReaderData->maPreviewSize.Width() ) return sal_True; if( mpReaderData->maPreviewSize.Height() ) return sal_True; return sal_False; } // ------------------------------------------------------------------------ void GraphicReader::DisablePreviewMode() { if( mpReaderData ) mpReaderData->maPreviewSize = Size( 0, 0 ); } // ------------------------------------------------------------------------ void GraphicReader::SetPreviewSize( const Size& rSize ) { if( !mpReaderData ) mpReaderData = new ReaderData; mpReaderData->maPreviewSize = rSize; } // ------------------------------------------------------------------------ Size GraphicReader::GetPreviewSize() const { Size aSize( 0, 0 ); if( mpReaderData ) aSize = mpReaderData->maPreviewSize; return aSize; } // -------------- // - ImpGraphic - // -------------- ImpGraphic::ImpGraphic() : mpAnimation ( NULL ), mpContext ( NULL ), mpSwapFile ( NULL ), mpGfxLink ( NULL ), meType ( GRAPHIC_NONE ), mnDocFilePos ( 0UL ), mnSizeBytes ( 0UL ), mnRefCount ( 1UL ), mbSwapOut ( sal_False ), mbSwapUnderway ( sal_False ) { } // ------------------------------------------------------------------------ ImpGraphic::ImpGraphic( const ImpGraphic& rImpGraphic ) : maMetaFile ( rImpGraphic.maMetaFile ), maEx ( rImpGraphic.maEx ), mpContext ( NULL ), mpSwapFile ( rImpGraphic.mpSwapFile ), meType ( rImpGraphic.meType ), maDocFileURLStr ( rImpGraphic.maDocFileURLStr ), mnDocFilePos ( rImpGraphic.mnDocFilePos ), mnSizeBytes ( rImpGraphic.mnSizeBytes ), mnRefCount ( 1UL ), mbSwapOut ( rImpGraphic.mbSwapOut ), mbSwapUnderway ( sal_False ) { if( mpSwapFile ) mpSwapFile->nRefCount++; if( rImpGraphic.mpGfxLink ) mpGfxLink = new GfxLink( *rImpGraphic.mpGfxLink ); else mpGfxLink = NULL; if( rImpGraphic.mpAnimation ) { mpAnimation = new Animation( *rImpGraphic.mpAnimation ); maEx = mpAnimation->GetBitmapEx(); } else mpAnimation = NULL; maSvgData = rImpGraphic.maSvgData; } // ------------------------------------------------------------------------ ImpGraphic::ImpGraphic( const Bitmap& rBitmap ) : maEx ( rBitmap ), mpAnimation ( NULL ), mpContext ( NULL ), mpSwapFile ( NULL ), mpGfxLink ( NULL ), meType ( !rBitmap ? GRAPHIC_NONE : GRAPHIC_BITMAP ), mnDocFilePos ( 0UL ), mnSizeBytes ( 0UL ), mnRefCount ( 1UL ), mbSwapOut ( sal_False ), mbSwapUnderway ( sal_False ) { } // ------------------------------------------------------------------------ ImpGraphic::ImpGraphic( const BitmapEx& rBitmapEx ) : maEx ( rBitmapEx ), mpAnimation ( NULL ), mpContext ( NULL ), mpSwapFile ( NULL ), mpGfxLink ( NULL ), meType ( !rBitmapEx ? GRAPHIC_NONE : GRAPHIC_BITMAP ), mnDocFilePos ( 0UL ), mnSizeBytes ( 0UL ), mnRefCount ( 1UL ), mbSwapOut ( sal_False ), mbSwapUnderway ( sal_False ) { } // ------------------------------------------------------------------------ ImpGraphic::ImpGraphic(const SvgDataPtr& rSvgDataPtr) : mpAnimation( NULL ), mpContext( NULL ), mpSwapFile( NULL ), mpGfxLink( NULL ), meType( rSvgDataPtr.get() ? GRAPHIC_BITMAP : GRAPHIC_NONE ), mnDocFilePos( 0UL ), mnSizeBytes( 0UL ), mnRefCount( 1UL ), mbSwapOut( sal_False ), mbSwapUnderway( sal_False ), maSvgData(rSvgDataPtr) { } // ------------------------------------------------------------------------ ImpGraphic::ImpGraphic( const Animation& rAnimation ) : maEx ( rAnimation.GetBitmapEx() ), mpAnimation ( new Animation( rAnimation ) ), mpContext ( NULL ), mpSwapFile ( NULL ), mpGfxLink ( NULL ), meType ( GRAPHIC_BITMAP ), mnDocFilePos ( 0UL ), mnSizeBytes ( 0UL ), mnRefCount ( 1UL ), mbSwapOut ( sal_False ), mbSwapUnderway ( sal_False ) { } // ------------------------------------------------------------------------ ImpGraphic::ImpGraphic( const GDIMetaFile& rMtf ) : maMetaFile ( rMtf ), mpAnimation ( NULL ), mpContext ( NULL ), mpSwapFile ( NULL ), mpGfxLink ( NULL ), meType ( GRAPHIC_GDIMETAFILE ), mnDocFilePos ( 0UL ), mnSizeBytes ( 0UL ), mnRefCount ( 1UL ), mbSwapOut ( sal_False ), mbSwapUnderway ( sal_False ) { } // ------------------------------------------------------------------------ ImpGraphic::~ImpGraphic() { ImplClear(); if( (sal_uLong) mpContext > 1UL ) delete mpContext; } // ------------------------------------------------------------------------ ImpGraphic& ImpGraphic::operator=( const ImpGraphic& rImpGraphic ) { if( &rImpGraphic != this ) { if( !mbSwapUnderway ) ImplClear(); maMetaFile = rImpGraphic.maMetaFile; meType = rImpGraphic.meType; mnSizeBytes = rImpGraphic.mnSizeBytes; delete mpAnimation; if ( rImpGraphic.mpAnimation ) { mpAnimation = new Animation( *rImpGraphic.mpAnimation ); maEx = mpAnimation->GetBitmapEx(); } else { mpAnimation = NULL; maEx = rImpGraphic.maEx; } if( !mbSwapUnderway ) { maDocFileURLStr = rImpGraphic.maDocFileURLStr; mnDocFilePos = rImpGraphic.mnDocFilePos; mbSwapOut = rImpGraphic.mbSwapOut; mpSwapFile = rImpGraphic.mpSwapFile; if( mpSwapFile ) mpSwapFile->nRefCount++; } delete mpGfxLink; if( rImpGraphic.mpGfxLink ) mpGfxLink = new GfxLink( *rImpGraphic.mpGfxLink ); else mpGfxLink = NULL; maSvgData = rImpGraphic.maSvgData; } return *this; } // ------------------------------------------------------------------------ sal_Bool ImpGraphic::operator==( const ImpGraphic& rImpGraphic ) const { sal_Bool bRet = sal_False; if( this == &rImpGraphic ) bRet = sal_True; else if( !ImplIsSwapOut() && ( rImpGraphic.meType == meType ) ) { switch( meType ) { case( GRAPHIC_NONE ): bRet = sal_True; break; case( GRAPHIC_GDIMETAFILE ): { if( rImpGraphic.maMetaFile == maMetaFile ) bRet = sal_True; } break; case( GRAPHIC_BITMAP ): { if(maSvgData.get()) { if(maSvgData == rImpGraphic.maSvgData) { bRet = sal_True; } else if(rImpGraphic.maSvgData) { if(maSvgData->getSvgDataArrayLength() == rImpGraphic.maSvgData->getSvgDataArrayLength()) { if(0 == memcmp( maSvgData->getSvgDataArray().get(), rImpGraphic.maSvgData->getSvgDataArray().get(), maSvgData->getSvgDataArrayLength())) { bRet = sal_True; } } } } else if( mpAnimation ) { if( rImpGraphic.mpAnimation && ( *rImpGraphic.mpAnimation == *mpAnimation ) ) bRet = sal_True; } else if( !rImpGraphic.mpAnimation && ( rImpGraphic.maEx == maEx ) ) { bRet = sal_True; } } break; default: break; } } return bRet; } // ------------------------------------------------------------------------ void ImpGraphic::ImplClearGraphics( sal_Bool bCreateSwapInfo ) { if( bCreateSwapInfo && !ImplIsSwapOut() ) { maSwapInfo.maPrefMapMode = ImplGetPrefMapMode(); maSwapInfo.maPrefSize = ImplGetPrefSize(); } maEx.Clear(); maMetaFile.Clear(); if( mpAnimation ) { mpAnimation->Clear(); delete mpAnimation; mpAnimation = NULL; } if( mpGfxLink ) { delete mpGfxLink; mpGfxLink = NULL; } maSvgData.reset(); } // ------------------------------------------------------------------------ void ImpGraphic::ImplClear() { if( mpSwapFile ) { if( mpSwapFile->nRefCount > 1 ) mpSwapFile->nRefCount--; else { try { ::ucbhelper::Content aCnt( mpSwapFile->aSwapURL.GetMainURL( INetURLObject::NO_DECODE ), ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() ); aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ), ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) ); } catch( const ::com::sun::star::ucb::ContentCreationException& ) { } catch( const ::com::sun::star::uno::RuntimeException& ) { } catch( const ::com::sun::star::ucb::CommandAbortedException& ) { } catch( const ::com::sun::star::uno::Exception& ) { } delete mpSwapFile; } mpSwapFile = NULL; } mbSwapOut = sal_False; mnDocFilePos = 0UL; maDocFileURLStr.Erase(); // cleanup ImplClearGraphics( sal_False ); meType = GRAPHIC_NONE; mnSizeBytes = 0; } // ------------------------------------------------------------------------ GraphicType ImpGraphic::ImplGetType() const { return meType; } // ------------------------------------------------------------------------ void ImpGraphic::ImplSetDefaultType() { ImplClear(); meType = GRAPHIC_DEFAULT; } // ------------------------------------------------------------------------ sal_Bool ImpGraphic::ImplIsSupportedGraphic() const { return( meType != GRAPHIC_NONE ); } // ------------------------------------------------------------------------ sal_Bool ImpGraphic::ImplIsTransparent() const { sal_Bool bRet(sal_True); if( meType == GRAPHIC_BITMAP && !maSvgData.get()) { bRet = ( mpAnimation ? mpAnimation->IsTransparent() : maEx.IsTransparent() ); } return bRet; } // ------------------------------------------------------------------------ sal_Bool ImpGraphic::ImplIsAlpha() const { sal_Bool bRet(sal_False); if(maSvgData.get()) { bRet = sal_True; } else if( meType == GRAPHIC_BITMAP ) { bRet = ( NULL == mpAnimation ) && maEx.IsAlpha(); } return bRet; } // ------------------------------------------------------------------------ sal_Bool ImpGraphic::ImplIsAnimated() const { return( mpAnimation != NULL ); } // ------------------------------------------------------------------------ sal_Bool ImpGraphic::ImplIsEPS() const { return( ( meType == GRAPHIC_GDIMETAFILE ) && ( maMetaFile.GetActionCount() > 0 ) && ( maMetaFile.GetAction( 0 )->GetType() == META_EPS_ACTION ) ); } // ------------------------------------------------------------------------ Bitmap ImpGraphic::ImplGetBitmap(const GraphicConversionParameters& rParameters) const { Bitmap aRetBmp; if( meType == GRAPHIC_BITMAP ) { if(maSvgData.get() && maEx.IsEmpty()) { // use maEx as local buffer for rendered svg const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement(); } const BitmapEx& rRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx ); const Color aReplaceColor( COL_WHITE ); aRetBmp = rRetBmpEx.GetBitmap( &aReplaceColor ); if(rParameters.getSizePixel().Width() || rParameters.getSizePixel().Height()) aRetBmp.Scale(rParameters.getSizePixel()); } else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() ) { if(maEx.IsEmpty()) { // calculate size VirtualDevice aVDev; Size aDrawSize(aVDev.LogicToPixel(maMetaFile.GetPrefSize(), maMetaFile.GetPrefMapMode())); if(rParameters.getSizePixel().Width() && rParameters.getSizePixel().Height()) { // apply given size if exists aDrawSize = rParameters.getSizePixel(); } if(aDrawSize.Width() && aDrawSize.Height() && !rParameters.getUnlimitedSize() && (aDrawSize.Width() > GRAPHIC_MTFTOBMP_MAXEXT || aDrawSize.Height() > GRAPHIC_MTFTOBMP_MAXEXT)) { // limit bitmap size to a maximum of GRAPHIC_MTFTOBMP_MAXEXT x GRAPHIC_MTFTOBMP_MAXEXT double fWH((double)aDrawSize.Width() / (double)aDrawSize.Height()); if(fWH <= 1.0) { aDrawSize.setWidth(basegfx::fround(GRAPHIC_MTFTOBMP_MAXEXT * fWH)); aDrawSize.setHeight(GRAPHIC_MTFTOBMP_MAXEXT); } else { aDrawSize.setWidth(GRAPHIC_MTFTOBMP_MAXEXT); aDrawSize.setHeight(basegfx::fround(GRAPHIC_MTFTOBMP_MAXEXT / fWH)); } } // calculate pixel size. Normally, it's the same as aDrawSize, but may // need to be extended when hairlines are on the right or bottom edge Size aPixelSize(aDrawSize); if(GRAPHIC_GDIMETAFILE == ImplGetType()) { // get hairline and full bound rect Rectangle aHairlineRect; const Rectangle aRect(maMetaFile.GetBoundRect(aVDev, &aHairlineRect)); if(!aRect.IsEmpty() && !aHairlineRect.IsEmpty()) { // expand if needed to allow bottom and right hairlines to be added if(aRect.Right() == aHairlineRect.Right()) { aPixelSize.setWidth(aPixelSize.getWidth() + 1); } if(aRect.Bottom() == aHairlineRect.Bottom()) { aPixelSize.setHeight(aPixelSize.getHeight() + 1); } } } if(aVDev.SetOutputSizePixel(aPixelSize)) { if(rParameters.getAntiAliase()) { aVDev.SetAntialiasing(aVDev.GetAntialiasing() | ANTIALIASING_ENABLE_B2DDRAW); } if(rParameters.getSnapHorVerLines()) { aVDev.SetAntialiasing(aVDev.GetAntialiasing() | ANTIALIASING_PIXELSNAPHAIRLINE); } ImplDraw( &aVDev, Point(), aDrawSize ); // use maEx as local buffer for rendered metafile const_cast< ImpGraphic* >(this)->maEx = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() ); } } aRetBmp = maEx.GetBitmap(); } if( !!aRetBmp ) { aRetBmp.SetPrefMapMode( ImplGetPrefMapMode() ); aRetBmp.SetPrefSize( ImplGetPrefSize() ); } return aRetBmp; } // ------------------------------------------------------------------------ BitmapEx ImpGraphic::ImplGetBitmapEx(const GraphicConversionParameters& rParameters) const { BitmapEx aRetBmpEx; if( meType == GRAPHIC_BITMAP ) { if(maSvgData.get() && maEx.IsEmpty()) { // use maEx as local buffer for rendered svg const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement(); } aRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx ); if(rParameters.getSizePixel().Width() || rParameters.getSizePixel().Height()) { aRetBmpEx.Scale( rParameters.getSizePixel(), rParameters.getScaleHighQuality() ? BMP_SCALE_BESTQUALITY : BMP_SCALE_FASTESTINTERPOLATE); } } else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() ) { if(maEx.IsEmpty()) { const ImpGraphic aMonoMask( maMetaFile.GetMonochromeMtf( COL_BLACK ) ); // use maEx as local buffer for rendered metafile const_cast< ImpGraphic* >(this)->maEx = BitmapEx(ImplGetBitmap(rParameters), aMonoMask.ImplGetBitmap(rParameters)); } aRetBmpEx = maEx; } return aRetBmpEx; } // ------------------------------------------------------------------------ Animation ImpGraphic::ImplGetAnimation() const { Animation aAnimation; if( mpAnimation ) aAnimation = *mpAnimation; return aAnimation; } // ------------------------------------------------------------------------ const GDIMetaFile& ImpGraphic::ImplGetGDIMetaFile() const { if(GRAPHIC_BITMAP == meType && !maMetaFile.GetActionCount()) { // #119735# // Use the local maMetaFile as container for a metafile-representation // of the bitmap graphic. This will be done only once, thus be buffered. // I checked all usages of maMetaFile, it is only used when type is not // GRAPHIC_BITMAP. In operator= it will get copied, thus buffering will // survive copying (change this if not wanted) ImpGraphic* pThat = const_cast< ImpGraphic* >(this); if(maSvgData.get() && !maEx) { // use maEx as local buffer for rendered svg pThat->maEx = maSvgData->getReplacement(); } // #123983# directly create a metafile with the same PrefSize and PrefMapMode // the bitmap has, this will be an always correct metafile if(maEx.IsTransparent()) { pThat->maMetaFile.AddAction(new MetaBmpExScaleAction(Point(), maEx.GetPrefSize(), maEx)); } else { pThat->maMetaFile.AddAction(new MetaBmpScaleAction(Point(), maEx.GetPrefSize(), maEx.GetBitmap())); } pThat->maMetaFile.Stop(); pThat->maMetaFile.WindStart(); pThat->maMetaFile.SetPrefSize(maEx.GetPrefSize()); pThat->maMetaFile.SetPrefMapMode(maEx.GetPrefMapMode()); } return maMetaFile; } // ------------------------------------------------------------------------ Size ImpGraphic::ImplGetPrefSize() const { Size aSize; if( ImplIsSwapOut() ) aSize = maSwapInfo.maPrefSize; else { switch( meType ) { case( GRAPHIC_NONE ): case( GRAPHIC_DEFAULT ): break; case( GRAPHIC_BITMAP ): { if(maSvgData.get() && maEx.IsEmpty()) { // svg not yet buffered in maEx, return size derived from range const basegfx::B2DRange& rRange = maSvgData->getRange(); aSize = Size(basegfx::fround(rRange.getWidth()), basegfx::fround(rRange.getHeight())); } else { aSize = maEx.GetPrefSize(); if( !aSize.Width() || !aSize.Height() ) { aSize = maEx.GetSizePixel(); } } } break; default: { if( ImplIsSupportedGraphic() ) aSize = maMetaFile.GetPrefSize(); } break; } } return aSize; } // ------------------------------------------------------------------------ void ImpGraphic::ImplSetPrefSize( const Size& rPrefSize ) { switch( meType ) { case( GRAPHIC_NONE ): case( GRAPHIC_DEFAULT ): break; case( GRAPHIC_BITMAP ): { //UUUU used when importing a writer FlyFrame with SVG as graphic, added conversion // to allow setting the PrefSize at the BitmapEx to hold it if(maSvgData.get() && maEx.IsEmpty()) { // use maEx as local buffer for rendered svg const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement(); } // #108077# Push through pref size to animation object, // will be lost on copy otherwise if( ImplIsAnimated() ) { const_cast< BitmapEx& >(mpAnimation->GetBitmapEx()).SetPrefSize( rPrefSize ); } maEx.SetPrefSize( rPrefSize ); } break; default: { if( ImplIsSupportedGraphic() ) maMetaFile.SetPrefSize( rPrefSize ); } break; } } // ------------------------------------------------------------------------ MapMode ImpGraphic::ImplGetPrefMapMode() const { MapMode aMapMode; if( ImplIsSwapOut() ) aMapMode = maSwapInfo.maPrefMapMode; else { switch( meType ) { case( GRAPHIC_NONE ): case( GRAPHIC_DEFAULT ): break; case( GRAPHIC_BITMAP ): { if(maSvgData.get() && maEx.IsEmpty()) { // svg not yet buffered in maEx, return default PrefMapMode aMapMode = MapMode(MAP_100TH_MM); } else { const Size aSize( maEx.GetPrefSize() ); if ( aSize.Width() && aSize.Height() ) aMapMode = maEx.GetPrefMapMode(); } } break; default: { if( ImplIsSupportedGraphic() ) return maMetaFile.GetPrefMapMode(); } break; } } return aMapMode; } // ------------------------------------------------------------------------ void ImpGraphic::ImplSetPrefMapMode( const MapMode& rPrefMapMode ) { switch( meType ) { case( GRAPHIC_NONE ): case( GRAPHIC_DEFAULT ): break; case( GRAPHIC_BITMAP ): { if(maSvgData.get()) { // ignore for Svg. If this is really used (except the grfcache) // it can be extended by using maEx as buffer for maSvgData->getReplacement() } else { // #108077# Push through pref mapmode to animation object, // will be lost on copy otherwise if( ImplIsAnimated() ) { const_cast< BitmapEx& >(mpAnimation->GetBitmapEx()).SetPrefMapMode( rPrefMapMode ); } maEx.SetPrefMapMode( rPrefMapMode ); } } break; default: { if( ImplIsSupportedGraphic() ) maMetaFile.SetPrefMapMode( rPrefMapMode ); } break; } } // ------------------------------------------------------------------------ sal_uLong ImpGraphic::ImplGetSizeBytes() const { if( 0 == mnSizeBytes ) { if( meType == GRAPHIC_BITMAP ) { if(maSvgData.get()) { mnSizeBytes = maSvgData->getSvgDataArrayLength(); } else { mnSizeBytes = mpAnimation ? mpAnimation->GetSizeBytes() : maEx.GetSizeBytes(); } } else if( meType == GRAPHIC_GDIMETAFILE ) { mnSizeBytes = maMetaFile.GetSizeBytes(); } } return( mnSizeBytes ); } // ------------------------------------------------------------------------ void ImpGraphic::ImplDraw( OutputDevice* pOutDev, const Point& rDestPt ) const { if( ImplIsSupportedGraphic() && !ImplIsSwapOut() ) { switch( meType ) { case( GRAPHIC_DEFAULT ): break; case( GRAPHIC_BITMAP ): { if(maSvgData.get() && !maEx) { // use maEx as local buffer for rendered svg const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement(); } if ( mpAnimation ) { mpAnimation->Draw( pOutDev, rDestPt ); } else { maEx.Draw( pOutDev, rDestPt ); } } break; default: ImplDraw( pOutDev, rDestPt, maMetaFile.GetPrefSize() ); break; } } } // ------------------------------------------------------------------------ void ImpGraphic::ImplDraw( OutputDevice* pOutDev, const Point& rDestPt, const Size& rDestSize ) const { if( ImplIsSupportedGraphic() && !ImplIsSwapOut() ) { switch( meType ) { case( GRAPHIC_DEFAULT ): break; case( GRAPHIC_BITMAP ): { if(maSvgData.get() && maEx.IsEmpty()) { // use maEx as local buffer for rendered svg const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement(); } if( mpAnimation ) { mpAnimation->Draw( pOutDev, rDestPt, rDestSize ); } else { maEx.Draw( pOutDev, rDestPt, rDestSize ); } } break; default: { ( (ImpGraphic*) this )->maMetaFile.WindStart(); ( (ImpGraphic*) this )->maMetaFile.Play( pOutDev, rDestPt, rDestSize ); ( (ImpGraphic*) this )->maMetaFile.WindStart(); } break; } } } // ------------------------------------------------------------------------ void ImpGraphic::ImplStartAnimation( OutputDevice* pOutDev, const Point& rDestPt, long nExtraData, OutputDevice* pFirstFrameOutDev ) { if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation ) mpAnimation->Start( pOutDev, rDestPt, nExtraData, pFirstFrameOutDev ); } // ------------------------------------------------------------------------ void ImpGraphic::ImplStartAnimation( OutputDevice* pOutDev, const Point& rDestPt, const Size& rDestSize, long nExtraData, OutputDevice* pFirstFrameOutDev ) { if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation ) mpAnimation->Start( pOutDev, rDestPt, rDestSize, nExtraData, pFirstFrameOutDev ); } // ------------------------------------------------------------------------ void ImpGraphic::ImplStopAnimation( OutputDevice* pOutDev, long nExtraData ) { if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation ) mpAnimation->Stop( pOutDev, nExtraData ); } // ------------------------------------------------------------------------ void ImpGraphic::ImplSetAnimationNotifyHdl( const Link& rLink ) { if( mpAnimation ) mpAnimation->SetNotifyHdl( rLink ); } // ------------------------------------------------------------------------ Link ImpGraphic::ImplGetAnimationNotifyHdl() const { Link aLink; if( mpAnimation ) aLink = mpAnimation->GetNotifyHdl(); return aLink; } // ------------------------------------------------------------------------ sal_uLong ImpGraphic::ImplGetAnimationLoopCount() const { return( mpAnimation ? mpAnimation->GetLoopCount() : 0UL ); } // ------------------------------------------------------------------------ void ImpGraphic::ImplResetAnimationLoopCount() { if( mpAnimation ) mpAnimation->ResetLoopCount(); } // ------------------------------------------------------------------------ List* ImpGraphic::ImplGetAnimationInfoList() const { return( mpAnimation ? mpAnimation->GetAInfoList() : NULL ); } // ------------------------------------------------------------------------ GraphicReader* ImpGraphic::ImplGetContext() { return mpContext; } // ------------------------------------------------------------------------ void ImpGraphic::ImplSetContext( GraphicReader* pReader ) { mpContext = pReader; } // ------------------------------------------------------------------------ void ImpGraphic::ImplSetDocFileName( const String& rName, sal_uLong nFilePos ) { const INetURLObject aURL( rName ); DBG_ASSERT( !rName.Len() || ( aURL.GetProtocol() != INET_PROT_NOT_VALID ), "Graphic::SetDocFileName(...): invalid URL" ); maDocFileURLStr = aURL.GetMainURL( INetURLObject::NO_DECODE ); mnDocFilePos = nFilePos; } // ------------------------------------------------------------------------ const String& ImpGraphic::ImplGetDocFileName() const { return maDocFileURLStr; } // ------------------------------------------------------------------------ sal_uLong ImpGraphic::ImplGetDocFilePos() const { return mnDocFilePos; } // ------------------------------------------------------------------------ sal_Bool ImpGraphic::ImplReadEmbedded( SvStream& rIStm, sal_Bool bSwap ) { MapMode aMapMode; Size aSize; const sal_uLong nStartPos = rIStm.Tell(); sal_uInt32 nId; sal_uLong nHeaderLen; long nType; long nLen; const sal_uInt16 nOldFormat = rIStm.GetNumberFormatInt(); sal_Bool bRet = sal_False; if( !mbSwapUnderway ) { const String aTempURLStr( maDocFileURLStr ); const sal_uLong nTempPos = mnDocFilePos; ImplClear(); maDocFileURLStr = aTempURLStr; mnDocFilePos = nTempPos; } rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); rIStm >> nId; // check version if( GRAPHIC_FORMAT_50 == nId ) { // read new style header VersionCompat* pCompat = new VersionCompat( rIStm, STREAM_READ ); rIStm >> nType; rIStm >> nLen; rIStm >> aSize; rIStm >> aMapMode; delete pCompat; } else { // read old style header long nWidth, nHeight; long nMapMode, nScaleNumX, nScaleDenomX; long nScaleNumY, nScaleDenomY, nOffsX, nOffsY; rIStm.SeekRel( -4L ); rIStm >> nType >> nLen >> nWidth >> nHeight; rIStm >> nMapMode >> nScaleNumX >> nScaleDenomX >> nScaleNumY; rIStm >> nScaleDenomY >> nOffsX >> nOffsY; // swapped if( nType > 100L ) { nType = SWAPLONG( nType ); nLen = SWAPLONG( nLen ); nWidth = SWAPLONG( nWidth ); nHeight = SWAPLONG( nHeight ); nMapMode = SWAPLONG( nMapMode ); nScaleNumX = SWAPLONG( nScaleNumX ); nScaleDenomX = SWAPLONG( nScaleDenomX ); nScaleNumY = SWAPLONG( nScaleNumY ); nScaleDenomY = SWAPLONG( nScaleDenomY ); nOffsX = SWAPLONG( nOffsX ); nOffsY = SWAPLONG( nOffsY ); } aSize = Size( nWidth, nHeight ); aMapMode = MapMode( (MapUnit) nMapMode, Point( nOffsX, nOffsY ), Fraction( nScaleNumX, nScaleDenomX ), Fraction( nScaleNumY, nScaleDenomY ) ); } nHeaderLen = rIStm.Tell() - nStartPos; meType = (GraphicType) nType; if( meType ) { if( meType == GRAPHIC_BITMAP ) { if(maSvgData.get() && maEx.IsEmpty()) { // use maEx as local buffer for rendered svg maEx = maSvgData->getReplacement(); } maEx.aBitmapSize = aSize; if( aMapMode != MapMode() ) { maEx.SetPrefMapMode( aMapMode ); maEx.SetPrefSize( aSize ); } } else { maMetaFile.SetPrefMapMode( aMapMode ); maMetaFile.SetPrefSize( aSize ); } if( bSwap ) { if( maDocFileURLStr.Len() ) { rIStm.Seek( nStartPos + nHeaderLen + nLen ); bRet = mbSwapOut = sal_True; } else { ::utl::TempFile aTempFile; const INetURLObject aTmpURL( aTempFile.GetURL() ); if( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ).getLength() ) { SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READWRITE | STREAM_SHARE_DENYWRITE ); if( pOStm ) { sal_uLong nFullLen = nHeaderLen + nLen; sal_uLong nPartLen = Min( nFullLen, (sal_uLong) GRAPHIC_MAXPARTLEN ); sal_uInt8* pBuffer = (sal_uInt8*) rtl_allocateMemory( nPartLen ); pOStm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); if( pBuffer ) { rIStm.Seek( nStartPos ); while( nFullLen ) { rIStm.Read( (char*) pBuffer, nPartLen ); pOStm->Write( (char*) pBuffer, nPartLen ); nFullLen -= nPartLen; if( nFullLen < GRAPHIC_MAXPARTLEN ) nPartLen = nFullLen; } rtl_freeMemory( pBuffer ); sal_uLong nReadErr = rIStm.GetError(), nWriteErr = pOStm->GetError(); delete pOStm, pOStm = NULL; if( !nReadErr && !nWriteErr ) { bRet = mbSwapOut = sal_True; mpSwapFile = new ImpSwapFile; mpSwapFile->nRefCount = 1; mpSwapFile->aSwapURL = aTmpURL; } else { try { ::ucbhelper::Content aCnt( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() ); aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ), ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) ); } catch( const ::com::sun::star::ucb::ContentCreationException& ) { } catch( const ::com::sun::star::uno::RuntimeException& ) { } catch( const ::com::sun::star::ucb::CommandAbortedException& ) { } catch( const ::com::sun::star::uno::Exception& ) { } } } delete pOStm; } } } } else if( meType == GRAPHIC_BITMAP || meType == GRAPHIC_GDIMETAFILE ) { rIStm >> *this; bRet = ( rIStm.GetError() == 0UL ); } else if( meType >= SYS_WINMETAFILE && meType <= SYS_MACMETAFILE ) { Graphic aSysGraphic; sal_uLong nCvtType; switch( sal::static_int_cast(meType) ) { case( SYS_WINMETAFILE ): case( SYS_WNTMETAFILE ): nCvtType = CVT_WMF; break; case( SYS_OS2METAFILE ): nCvtType = CVT_MET; break; case( SYS_MACMETAFILE ): nCvtType = CVT_PCT; break; default: nCvtType = CVT_UNKNOWN; break; } if( nType && GraphicConverter::Import( rIStm, aSysGraphic, nCvtType ) == ERRCODE_NONE ) { *this = ImpGraphic( aSysGraphic.GetGDIMetaFile() ); bRet = ( rIStm.GetError() == 0UL ); } else meType = GRAPHIC_DEFAULT; } if( bRet ) { ImplSetPrefMapMode( aMapMode ); ImplSetPrefSize( aSize ); } } else bRet = sal_True; rIStm.SetNumberFormatInt( nOldFormat ); return bRet; } // ------------------------------------------------------------------------ sal_Bool ImpGraphic::ImplWriteEmbedded( SvStream& rOStm ) { sal_Bool bRet = sal_False; if( ( meType != GRAPHIC_NONE ) && ( meType != GRAPHIC_DEFAULT ) && !ImplIsSwapOut() ) { const MapMode aMapMode( ImplGetPrefMapMode() ); const Size aSize( ImplGetPrefSize() ); const sal_uInt16 nOldFormat = rOStm.GetNumberFormatInt(); sal_uLong nDataFieldPos; rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); // write correct version ( old style/new style header ) if( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 ) { // write ID for new format (5.0) rOStm << GRAPHIC_FORMAT_50; // write new style header VersionCompat* pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 ); rOStm << (long) meType; // data size is updated later nDataFieldPos = rOStm.Tell(); rOStm << (long) 0; rOStm << aSize; rOStm << aMapMode; delete pCompat; } else { // write old style (<=4.0) header rOStm << (long) meType; // data size is updated later nDataFieldPos = rOStm.Tell(); rOStm << (long) 0; rOStm << (long) aSize.Width(); rOStm << (long) aSize.Height(); rOStm << (long) aMapMode.GetMapUnit(); rOStm << (long) aMapMode.GetScaleX().GetNumerator(); rOStm << (long) aMapMode.GetScaleX().GetDenominator(); rOStm << (long) aMapMode.GetScaleY().GetNumerator(); rOStm << (long) aMapMode.GetScaleY().GetDenominator(); rOStm << (long) aMapMode.GetOrigin().X(); rOStm << (long) aMapMode.GetOrigin().Y(); } // write data block if( !rOStm.GetError() ) { const sal_uLong nDataStart = rOStm.Tell(); if( ImplIsSupportedGraphic() ) rOStm << *this; if( !rOStm.GetError() ) { const sal_uLong nStmPos2 = rOStm.Tell(); rOStm.Seek( nDataFieldPos ); rOStm << (long) ( nStmPos2 - nDataStart ); rOStm.Seek( nStmPos2 ); bRet = sal_True; } } rOStm.SetNumberFormatInt( nOldFormat ); } return bRet; } // ------------------------------------------------------------------------ sal_Bool ImpGraphic::ImplSwapOut() { sal_Bool bRet = sal_False; if( !ImplIsSwapOut() ) { if( !maDocFileURLStr.Len() ) { ::utl::TempFile aTempFile; const INetURLObject aTmpURL( aTempFile.GetURL() ); if( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ).getLength() ) { SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READWRITE | STREAM_SHARE_DENYWRITE ); if( pOStm ) { pOStm->SetVersion( SOFFICE_FILEFORMAT_50 ); pOStm->SetCompressMode( COMPRESSMODE_NATIVE ); if( ( bRet = ImplSwapOut( pOStm ) ) == sal_True ) { mpSwapFile = new ImpSwapFile; mpSwapFile->nRefCount = 1; mpSwapFile->aSwapURL = aTmpURL; } else { delete pOStm, pOStm = NULL; try { ::ucbhelper::Content aCnt( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() ); aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ), ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) ); } catch( const ::com::sun::star::ucb::ContentCreationException& ) { } catch( const ::com::sun::star::uno::RuntimeException& ) { } catch( const ::com::sun::star::ucb::CommandAbortedException& ) { } catch( const ::com::sun::star::uno::Exception& ) { } } delete pOStm; } } } else { ImplClearGraphics( sal_True ); bRet = mbSwapOut = sal_True; } } return bRet; } // ------------------------------------------------------------------------ sal_Bool ImpGraphic::ImplSwapOut( SvStream* pOStm ) { sal_Bool bRet = sal_False; if( pOStm ) { pOStm->SetBufferSize( GRAPHIC_STREAMBUFSIZE ); if( !pOStm->GetError() && ImplWriteEmbedded( *pOStm ) ) { pOStm->Flush(); if( !pOStm->GetError() ) { ImplClearGraphics( sal_True ); bRet = mbSwapOut = sal_True; } } } else { ImplClearGraphics( sal_True ); bRet = mbSwapOut = sal_True; } return bRet; } // ------------------------------------------------------------------------ sal_Bool ImpGraphic::ImplSwapIn() { sal_Bool bRet = sal_False; if( ImplIsSwapOut() ) { String aSwapURL; if( mpSwapFile ) aSwapURL = mpSwapFile->aSwapURL.GetMainURL( INetURLObject::NO_DECODE ); else aSwapURL = maDocFileURLStr; if( aSwapURL.Len() ) { SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( aSwapURL, STREAM_READWRITE | STREAM_SHARE_DENYWRITE ); if( pIStm ) { pIStm->SetVersion( SOFFICE_FILEFORMAT_50 ); pIStm->SetCompressMode( COMPRESSMODE_NATIVE ); if( !mpSwapFile ) pIStm->Seek( mnDocFilePos ); bRet = ImplSwapIn( pIStm ); delete pIStm; if( mpSwapFile ) { if( mpSwapFile->nRefCount > 1 ) mpSwapFile->nRefCount--; else { try { ::ucbhelper::Content aCnt( aSwapURL, ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() ); aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ), ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) ); } catch( const ::com::sun::star::ucb::ContentCreationException& ) { } catch( const ::com::sun::star::uno::RuntimeException& ) { } catch( const ::com::sun::star::ucb::CommandAbortedException& ) { } catch( const ::com::sun::star::uno::Exception& ) { } delete mpSwapFile; } mpSwapFile = NULL; } } } } return bRet; } // ------------------------------------------------------------------------ sal_Bool ImpGraphic::ImplSwapIn( SvStream* pIStm ) { sal_Bool bRet = sal_False; if( pIStm ) { pIStm->SetBufferSize( GRAPHIC_STREAMBUFSIZE ); if( !pIStm->GetError() ) { mbSwapUnderway = sal_True; bRet = ImplReadEmbedded( *pIStm ); mbSwapUnderway = sal_False; if( !bRet ) ImplClear(); else mbSwapOut = sal_False; } } return bRet; } // ------------------------------------------------------------------------ sal_Bool ImpGraphic::ImplIsSwapOut() const { return mbSwapOut; } // ------------------------------------------------------------------------ void ImpGraphic::ImplSetLink( const GfxLink& rGfxLink ) { delete mpGfxLink; mpGfxLink = new GfxLink( rGfxLink ); if( mpGfxLink->IsNative() ) mpGfxLink->SwapOut(); } // ------------------------------------------------------------------------ GfxLink ImpGraphic::ImplGetLink() { return( mpGfxLink ? *mpGfxLink : GfxLink() ); } // ------------------------------------------------------------------------ sal_Bool ImpGraphic::ImplIsLink() const { return ( mpGfxLink != NULL ) ? sal_True : sal_False; } // ------------------------------------------------------------------------ sal_uLong ImpGraphic::ImplGetChecksum() const { sal_uLong nRet = 0; if( ImplIsSupportedGraphic() && !ImplIsSwapOut() ) { switch( meType ) { case( GRAPHIC_DEFAULT ): break; case( GRAPHIC_BITMAP ): { if(maSvgData.get() && maEx.IsEmpty()) { // use maEx as local buffer for rendered svg const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement(); } if( mpAnimation ) { nRet = mpAnimation->GetChecksum(); } else { nRet = maEx.GetChecksum(); } } break; default: nRet = maMetaFile.GetChecksum(); break; } } return nRet; } // ------------------------------------------------------------------------ sal_Bool ImpGraphic::ImplExportNative( SvStream& rOStm ) const { sal_Bool bResult = sal_False; if( !rOStm.GetError() ) { if( !ImplIsSwapOut() ) { if( mpGfxLink && mpGfxLink->IsNative() ) bResult = mpGfxLink->ExportNative( rOStm ); else { rOStm << *this; bResult = ( rOStm.GetError() == ERRCODE_NONE ); } } else rOStm.SetError( SVSTREAM_GENERALERROR ); } return bResult; } // ------------------------------------------------------------------------ const SvgDataPtr& ImpGraphic::getSvgData() const { return maSvgData; } // ------------------------------------------------------------------------ SvStream& operator>>( SvStream& rIStm, ImpGraphic& rImpGraphic ) { if( !rIStm.GetError() ) { const sal_uLong nStmPos1 = rIStm.Tell(); sal_uInt32 nTmp; if ( !rImpGraphic.mbSwapUnderway ) rImpGraphic.ImplClear(); // read Id rIStm >> nTmp; // if there is no more data, avoid further expensive // reading which will create VDevs and other stuff, just to // read nothing. CAUTION: Eof is only true AFTER reading another // byte, a speciality of SvMemoryStream (!) if(!rIStm.GetError() && !rIStm.IsEof()) { if( NATIVE_FORMAT_50 == nTmp ) { Graphic aGraphic; GfxLink aLink; VersionCompat* pCompat; // read compat info pCompat = new VersionCompat( rIStm, STREAM_READ ); delete pCompat; rIStm >> aLink; // set dummy link to avoid creation of additional link after filtering; // we set a default link to avoid unnecessary swapping of native data aGraphic.SetLink( GfxLink() ); if( !rIStm.GetError() && aLink.LoadNative( aGraphic ) ) { // set link only, if no other link was set const sal_Bool bSetLink = ( rImpGraphic.mpGfxLink == NULL ); // assign graphic rImpGraphic = *aGraphic.ImplGetImpGraphic(); if( aLink.IsPrefMapModeValid() ) rImpGraphic.ImplSetPrefMapMode( aLink.GetPrefMapMode() ); if( aLink.IsPrefSizeValid() ) rImpGraphic.ImplSetPrefSize( aLink.GetPrefSize() ); if( bSetLink ) rImpGraphic.ImplSetLink( aLink ); } else { rIStm.Seek( nStmPos1 ); rIStm.SetError( ERRCODE_IO_WRONGFORMAT ); } } else { BitmapEx aBmpEx; const sal_uInt16 nOldFormat = rIStm.GetNumberFormatInt(); rIStm.SeekRel( -4 ); rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); ReadDIBBitmapEx(aBmpEx, rIStm); if( !rIStm.GetError() ) { sal_uInt32 nMagic1(0), nMagic2(0); sal_uLong nActPos = rIStm.Tell(); rIStm >> nMagic1 >> nMagic2; rIStm.Seek( nActPos ); rImpGraphic = ImpGraphic( aBmpEx ); if( !rIStm.GetError() && ( 0x5344414e == nMagic1 ) && ( 0x494d4931 == nMagic2 ) ) { delete rImpGraphic.mpAnimation; rImpGraphic.mpAnimation = new Animation; rIStm >> *rImpGraphic.mpAnimation; // #108077# manually set loaded BmpEx to Animation // (which skips loading its BmpEx if already done) rImpGraphic.mpAnimation->SetBitmapEx(aBmpEx); } else rIStm.ResetError(); } else { GDIMetaFile aMtf; rIStm.Seek( nStmPos1 ); rIStm.ResetError(); rIStm >> aMtf; if( !rIStm.GetError() ) { rImpGraphic = aMtf; } else { // try to stream in Svg defining data (length, byte array and evtl. path) // See below (operator<<) for more information const sal_uInt32 nSvgMagic((sal_uInt32('s') << 24) | (sal_uInt32('v') << 16) | (sal_uInt32('g') << 8) | sal_uInt32('0')); sal_uInt32 nMagic; rIStm.Seek(nStmPos1); rIStm.ResetError(); rIStm >> nMagic; if(nSvgMagic == nMagic) { sal_uInt32 mnSvgDataArrayLength(0); rIStm >> mnSvgDataArrayLength; if(mnSvgDataArrayLength) { SvgDataArray aNewData(new sal_uInt8[mnSvgDataArrayLength]); UniString aPath; rIStm.Read(aNewData.get(), mnSvgDataArrayLength); rIStm.ReadByteString(aPath); if(!rIStm.GetError()) { SvgDataPtr aSvgDataPtr( new SvgData( aNewData, mnSvgDataArrayLength, rtl::OUString(aPath))); rImpGraphic = aSvgDataPtr; } } } rIStm.Seek(nStmPos1); } } rIStm.SetNumberFormatInt( nOldFormat ); } } } return rIStm; } // ------------------------------------------------------------------------ SvStream& operator<<( SvStream& rOStm, const ImpGraphic& rImpGraphic ) { if( !rOStm.GetError() ) { if( !rImpGraphic.ImplIsSwapOut() ) { if( ( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 ) && ( rOStm.GetCompressMode() & COMPRESSMODE_NATIVE ) && rImpGraphic.mpGfxLink && rImpGraphic.mpGfxLink->IsNative() ) { VersionCompat* pCompat; // native format rOStm << NATIVE_FORMAT_50; // write compat info pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 ); delete pCompat; rImpGraphic.mpGfxLink->SetPrefMapMode( rImpGraphic.ImplGetPrefMapMode() ); rImpGraphic.mpGfxLink->SetPrefSize( rImpGraphic.ImplGetPrefSize() ); rOStm << *rImpGraphic.mpGfxLink; } else { // own format const sal_uInt16 nOldFormat = rOStm.GetNumberFormatInt(); rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); switch( rImpGraphic.ImplGetType() ) { case( GRAPHIC_NONE ): case( GRAPHIC_DEFAULT ): break; case GRAPHIC_BITMAP: { if(rImpGraphic.getSvgData().get()) { // stream out Svg defining data (length, byte array and evtl. path) // this is used e.g. in swapping out graphic data and in transporting it over UNO API // as sequence of bytes, but AFAIK not written anywhere to any kind of file, so it should be // no problem to extend it; only used at runtime const sal_uInt32 nSvgMagic((sal_uInt32('s') << 24) | (sal_uInt32('v') << 16) | (sal_uInt32('g') << 8) | sal_uInt32('0')); rOStm << nSvgMagic; rOStm << rImpGraphic.getSvgData()->getSvgDataArrayLength(); rOStm.Write(rImpGraphic.getSvgData()->getSvgDataArray().get(), rImpGraphic.getSvgData()->getSvgDataArrayLength()); rOStm.WriteByteString(rImpGraphic.getSvgData()->getPath()); } else if( rImpGraphic.ImplIsAnimated()) { rOStm << *rImpGraphic.mpAnimation; } else { WriteDIBBitmapEx(rImpGraphic.maEx, rOStm); } } break; default: { if( rImpGraphic.ImplIsSupportedGraphic() ) rOStm << rImpGraphic.maMetaFile; } break; } rOStm.SetNumberFormatInt( nOldFormat ); } } else rOStm.SetError( SVSTREAM_GENERALERROR ); } return rOStm; }