/************************************************************************* * * $RCSfile: impgraph.cxx,v $ * * $Revision: 1.5 $ * * last change: $Author: ka $ $Date: 2000-11-10 15:53:38 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses * * - GNU Lesser General Public License Version 2.1 * - Sun Industry Standards Source License Version 1.1 * * Sun Microsystems Inc., October, 2000 * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2000 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * * Sun Industry Standards Source License Version 1.1 * ================================================= * The contents of this file are subject to the Sun Industry Standards * Source License Version 1.1 (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.openoffice.org/license.html. * * Software provided under this License is provided on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. * See the License for the specific provisions governing your rights and * obligations concerning the Software. * * The Initial Developer of the Original Code is: Sun Microsystems, Inc. * * Copyright: 2000 by Sun Microsystems, Inc. * * All Rights Reserved. * * Contributor(s): _______________________________________ * * ************************************************************************/ #define _SV_IMPGRAPH_CXX #ifndef _VCOMPAT_HXX #include #endif #ifndef _URLOBJ_HXX #include #endif #ifndef _DEBUG_HXX #include #endif #ifndef _UCBHELPER_CONTENT_HXX #include #endif #ifndef _UNTOOLS_UCBSTREAMHELPER_HXX #include #endif #ifndef _UNTOOLS_TEMPFILE_HXX #include #endif #ifndef _SV_OUTDEV_HXX #include #endif #ifndef _SV_VIRDEV_HXX #include #endif #ifndef _DEBUG_HXX #include #endif #ifndef _STREAM_HXX #include #endif #ifndef _NEW_HXX #include #endif #include #ifndef _GFXLINK_HXX #include #endif #ifndef _SV_CVTGRF_HXX #include #endif #ifndef _SV_SALBTYPE_HXX #include #endif #ifndef _SV_GRAPH_HXX #include #endif #ifndef _COM_SUN_STAR_UCB_COMMANDABORTEDEXCEPTION_HPP_ #include #endif // ----------- // - Defines - // ----------- #define GRAPHIC_MAXPARTLEN 256000L #define GRAPHIC_MTFTOBMP_MAXEXT 2048 #define GRAPHIC_STREAMBUFSIZE 8192UL #define SYS_WINMETAFILE 0x00000003UL #define SYS_WNTMETAFILE 0x00000004UL #define SYS_OS2METAFILE 0x00000005UL #define SYS_MACMETAFILE 0x00000006UL #define GRAPHIC_FORMAT_50 COMPAT_FORMAT( 'G', 'R', 'F', '5' ) #define NATIVE_FORMAT_50 COMPAT_FORMAT( 'N', 'A', 'T', '5' ) // --------------- // - ImpSwapFile - // --------------- struct ImpSwapFile { INetURLObject aSwapURL; USHORT nRefCount; }; // ----------------- // - Graphicreader - // ----------------- GraphicReader::~GraphicReader() { } // -------------- // - ImpGraphic - // -------------- ImpGraphic::ImpGraphic() : mpAnimation ( NULL ), mpContext ( NULL ), mpSwapFile ( NULL ), mpGfxLink ( NULL ), meType ( GRAPHIC_NONE ), mnDocFilePos ( 0UL ), mnRefCount ( 1UL ), mbSwapOut ( FALSE ), mbSwapUnderway ( FALSE ) { } // ------------------------------------------------------------------------ ImpGraphic::ImpGraphic( const ImpGraphic& rImpGraphic ) : maEx ( rImpGraphic.maEx ), maMetaFile ( rImpGraphic.maMetaFile ), mpContext ( NULL ), mpSwapFile ( rImpGraphic.mpSwapFile ), meType ( rImpGraphic.meType ), maDocFileURLStr ( rImpGraphic.maDocFileURLStr ), mnDocFilePos ( rImpGraphic.mnDocFilePos ), mnRefCount ( 1UL ), mbSwapOut ( rImpGraphic.mbSwapOut ), mbSwapUnderway ( 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; } // ------------------------------------------------------------------------ ImpGraphic::ImpGraphic( const Bitmap& rBitmap ) : maEx ( rBitmap ), mpAnimation ( NULL ), mpContext ( NULL ), mpSwapFile ( NULL ), mpGfxLink ( NULL ), meType ( !rBitmap ? GRAPHIC_NONE : GRAPHIC_BITMAP ), mnDocFilePos ( 0UL ), mnRefCount ( 1UL ), mbSwapOut ( FALSE ), mbSwapUnderway ( FALSE ) { } // ------------------------------------------------------------------------ ImpGraphic::ImpGraphic( const BitmapEx& rBitmapEx ) : maEx ( rBitmapEx ), mpAnimation ( NULL ), mpContext ( NULL ), mpSwapFile ( NULL ), mpGfxLink ( NULL ), meType ( !rBitmapEx ? GRAPHIC_NONE : GRAPHIC_BITMAP ), mnDocFilePos ( 0UL ), mnRefCount ( 1UL ), mbSwapOut ( FALSE ), mbSwapUnderway ( FALSE ) { } // ------------------------------------------------------------------------ ImpGraphic::ImpGraphic( const Animation& rAnimation ) : maEx ( rAnimation.GetBitmapEx() ), mpAnimation ( new Animation( rAnimation ) ), mpContext ( NULL ), mpSwapFile ( NULL ), mpGfxLink ( NULL ), meType ( GRAPHIC_BITMAP ), mnDocFilePos ( 0UL ), mnRefCount ( 1UL ), mbSwapOut ( FALSE ), mbSwapUnderway ( FALSE ) { } // ------------------------------------------------------------------------ ImpGraphic::ImpGraphic( const GDIMetaFile& rMtf ) : maMetaFile ( rMtf ), mpAnimation ( NULL ), mpContext ( NULL ), mpSwapFile ( NULL ), mpGfxLink ( NULL ), meType ( GRAPHIC_GDIMETAFILE ), mnDocFilePos ( 0UL ), mnRefCount ( 1UL ), mbSwapOut ( FALSE ), mbSwapUnderway ( FALSE ) { } // ------------------------------------------------------------------------ ImpGraphic::~ImpGraphic() { ImplClear(); if( (ULONG) mpContext > 1UL ) delete mpContext; } // ------------------------------------------------------------------------ ImpGraphic& ImpGraphic::operator=( const ImpGraphic& rImpGraphic ) { if( &rImpGraphic != this ) { if( !mbSwapUnderway ) ImplClear(); maMetaFile = rImpGraphic.maMetaFile; meType = rImpGraphic.meType; 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; } return *this; } // ------------------------------------------------------------------------ BOOL ImpGraphic::operator==( const ImpGraphic& rImpGraphic ) const { BOOL bRet = FALSE; if( this == &rImpGraphic ) bRet = TRUE; else if( !ImplIsSwapOut() && ( rImpGraphic.meType == meType ) ) { switch( meType ) { case( GRAPHIC_NONE ): bRet = TRUE; break; case( GRAPHIC_GDIMETAFILE ): { if( rImpGraphic.maMetaFile == maMetaFile ) bRet = TRUE; } break; case( GRAPHIC_BITMAP ): { if( mpAnimation ) { if( rImpGraphic.mpAnimation && ( *rImpGraphic.mpAnimation == *mpAnimation ) ) bRet = TRUE; } else if( !rImpGraphic.mpAnimation && ( rImpGraphic.maEx == maEx ) ) bRet = TRUE; } break; default: break; } } return bRet; } // ------------------------------------------------------------------------ void ImpGraphic::ImplClearGraphics( 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; } } // ------------------------------------------------------------------------ void ImpGraphic::ImplClear() { if( mpSwapFile ) { if( mpSwapFile->nRefCount > 1 ) mpSwapFile->nRefCount--; else { try { ::ucb::Content aCnt( mpSwapFile->aSwapURL.GetMainURL(), ::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( ::com::sun::star::ucb::CommandAbortedException& ) { DBG_ERRORFILE( "CommandAbortedException" ); } catch( ... ) { DBG_ERRORFILE( "Any other exception" ); } delete mpSwapFile; } mpSwapFile = NULL; } mbSwapOut = FALSE; mnDocFilePos = 0UL; maDocFileURLStr.Erase(); // cleanup ImplClearGraphics( FALSE ); meType = GRAPHIC_NONE; } // ------------------------------------------------------------------------ GraphicType ImpGraphic::ImplGetType() const { return meType; } // ------------------------------------------------------------------------ void ImpGraphic::ImplSetDefaultType() { ImplClear(); meType = GRAPHIC_DEFAULT; } // ------------------------------------------------------------------------ BOOL ImpGraphic::ImplIsSupportedGraphic() const { return( meType != GRAPHIC_NONE ); } // ------------------------------------------------------------------------ BOOL ImpGraphic::ImplIsTransparent() const { BOOL bRet; if( meType == GRAPHIC_BITMAP ) bRet = ( mpAnimation ? mpAnimation->IsTransparent() : maEx.IsTransparent() ); else bRet = TRUE; return bRet; } // ------------------------------------------------------------------------ BOOL ImpGraphic::ImplIsAlpha() const { BOOL bRet; if( meType == GRAPHIC_BITMAP ) bRet = ( NULL == mpAnimation ) && maEx.IsAlpha(); else bRet = FALSE; return bRet; } // ------------------------------------------------------------------------ BOOL ImpGraphic::ImplIsAnimated() const { return( mpAnimation != NULL ); } // ------------------------------------------------------------------------ Bitmap ImpGraphic::ImplGetBitmap() const { Bitmap aRetBmp; if( meType == GRAPHIC_BITMAP ) { const BitmapEx& rRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx ); const Color aReplaceColor( COL_WHITE ); aRetBmp = rRetBmpEx.GetBitmap( &aReplaceColor ); } else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() ) { VirtualDevice aVDev; Size aSizePix( aVDev.LogicToPixel( maMetaFile.GetPrefSize(), maMetaFile.GetPrefMapMode() ) ); if( aSizePix.Width() && aSizePix.Height() && ( aSizePix.Width() > GRAPHIC_MTFTOBMP_MAXEXT || aSizePix.Height() > GRAPHIC_MTFTOBMP_MAXEXT ) ) { double fWH = (double) aSizePix.Width() / aSizePix.Height(); if( fWH <= 1.0 ) { aSizePix.Width() = FRound( fWH * GRAPHIC_MTFTOBMP_MAXEXT ); aSizePix.Height() = GRAPHIC_MTFTOBMP_MAXEXT; } else { aSizePix.Width() = GRAPHIC_MTFTOBMP_MAXEXT; aSizePix.Height() = FRound( GRAPHIC_MTFTOBMP_MAXEXT / fWH ); } } if( aVDev.SetOutputSizePixel( aSizePix ) ) { const Point aPt; ImplDraw( &aVDev, aPt, aSizePix ); aRetBmp = aVDev.GetBitmap( aPt, aSizePix ); } } if( !!aRetBmp ) { aRetBmp.SetPrefMapMode( ImplGetPrefMapMode() ); aRetBmp.SetPrefSize( ImplGetPrefSize() ); } return aRetBmp; } // ------------------------------------------------------------------------ BitmapEx ImpGraphic::ImplGetBitmapEx() const { BitmapEx aRetBmpEx; if( meType == GRAPHIC_BITMAP ) aRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx ); else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() ) { const ImpGraphic aMonoMask( maMetaFile.GetMonochromeMtf( COL_BLACK ) ); aRetBmpEx = BitmapEx( ImplGetBitmap(), aMonoMask.ImplGetBitmap() ); } return aRetBmpEx; } // ------------------------------------------------------------------------ Animation ImpGraphic::ImplGetAnimation() const { Animation aAnimation; if( mpAnimation ) aAnimation = *mpAnimation; return aAnimation; } // ------------------------------------------------------------------------ const GDIMetaFile& ImpGraphic::ImplGetGDIMetaFile() const { 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 ): { 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 ): 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 ): { 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 ): maEx.SetPrefMapMode( rPrefMapMode ); break; default: { if( ImplIsSupportedGraphic() ) maMetaFile.SetPrefMapMode( rPrefMapMode ); } break; } } // ------------------------------------------------------------------------ ULONG ImpGraphic::ImplGetSizeBytes() const { ULONG nSizeBytes; if( meType == GRAPHIC_BITMAP ) { if( mpAnimation ) nSizeBytes = mpAnimation->GetSizeBytes(); else nSizeBytes = maEx.GetSizeBytes(); } else nSizeBytes = 0UL; return nSizeBytes; } // ------------------------------------------------------------------------ void ImpGraphic::ImplDraw( OutputDevice* pOutDev, const Point& rDestPt ) const { if( ImplIsSupportedGraphic() && !ImplIsSwapOut() ) { switch( meType ) { case( GRAPHIC_DEFAULT ): break; case( GRAPHIC_BITMAP ): { 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( 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; } // ------------------------------------------------------------------------ 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, ULONG nFilePos ) { const INetURLObject aURL( rName ); DBG_ASSERT( !rName.Len() || ( aURL.GetProtocol() != INET_PROT_NOT_VALID ), "Graphic::SetDocFileName(...): invalid URL" ); maDocFileURLStr = aURL.GetMainURL(); mnDocFilePos = nFilePos; } // ------------------------------------------------------------------------ const String& ImpGraphic::ImplGetDocFileName() const { return maDocFileURLStr; } // ------------------------------------------------------------------------ ULONG ImpGraphic::ImplGetDocFilePos() const { return mnDocFilePos; } // ------------------------------------------------------------------------ BOOL ImpGraphic::ImplReadEmbedded( SvStream& rIStm, BOOL bSwap ) { MapMode aMapMode; Size aSize; const ULONG nStartPos = rIStm.Tell(); ULONG nId; ULONG nHeaderLen; long nType; long nLen; const USHORT nOldFormat = rIStm.GetNumberFormatInt(); BOOL bRet = FALSE; if( !mbSwapUnderway ) { const String aTempURLStr( maDocFileURLStr ); const 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 ) { 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 = TRUE; } else { ::utl::TempFile aTempFile; const INetURLObject aTmpURL( aTempFile.GetURL() ); if( aTmpURL.GetMainURL().Len() ) { SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( aTmpURL.GetMainURL(), STREAM_READWRITE | STREAM_SHARE_DENYWRITE ); if( pOStm ) { ULONG nFullLen = nHeaderLen + nLen; ULONG nPartLen = Min( nFullLen, (ULONG) GRAPHIC_MAXPARTLEN ); BYTE* pBuffer = (BYTE*) SvMemAlloc( 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; } SvMemFree( pBuffer ); ULONG nReadErr = rIStm.GetError(), nWriteErr = pOStm->GetError(); delete pOStm, pOStm = NULL; if( !nReadErr && !nWriteErr ) { bRet = mbSwapOut = TRUE; mpSwapFile = new ImpSwapFile; mpSwapFile->nRefCount = 1; mpSwapFile->aSwapURL = aTmpURL; } else { try { ::ucb::Content aCnt( aTmpURL.GetMainURL(), ::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( ::com::sun::star::ucb::CommandAbortedException& ) { DBG_ERRORFILE( "CommandAbortedException" ); } catch( ... ) { DBG_ERRORFILE( "Any other 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; ULONG nCvtType; switch( (ULONG) 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 = TRUE; rIStm.SetNumberFormatInt( nOldFormat ); return bRet; } // ------------------------------------------------------------------------ BOOL ImpGraphic::ImplWriteEmbedded( SvStream& rOStm ) { BOOL bRet = FALSE; if( ( meType != GRAPHIC_NONE ) && ( meType != GRAPHIC_DEFAULT ) && !ImplIsSwapOut() ) { const MapMode aMapMode( ImplGetPrefMapMode() ); const Size aSize( ImplGetPrefSize() ); const USHORT nOldFormat = rOStm.GetNumberFormatInt(); const ULONG nStmPos1 = rOStm.Tell(); 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 ULONG nDataStart = rOStm.Tell(); if( ImplIsSupportedGraphic() ) rOStm << *this; if( !rOStm.GetError() ) { const ULONG nStmPos2 = rOStm.Tell(); rOStm.Seek( nDataFieldPos ); rOStm << (long) ( nStmPos2 - nDataStart ); rOStm.Seek( nStmPos2 ); bRet = TRUE; } } rOStm.SetNumberFormatInt( nOldFormat ); } return bRet; } // ------------------------------------------------------------------------ BOOL ImpGraphic::ImplSwapOut() { BOOL bRet = FALSE; if( !ImplIsSwapOut() ) { if( !maDocFileURLStr.Len() ) { ::utl::TempFile aTempFile; const INetURLObject aTmpURL( aTempFile.GetURL() ); if( aTmpURL.GetMainURL().Len() ) { SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( aTmpURL.GetMainURL(), STREAM_READWRITE | STREAM_SHARE_DENYWRITE ); if( pOStm ) { pOStm->SetVersion( SOFFICE_FILEFORMAT_NOW ); pOStm->SetCompressMode( COMPRESSMODE_NATIVE ); if( ( bRet = ImplSwapOut( pOStm ) ) == TRUE ) { mpSwapFile = new ImpSwapFile; mpSwapFile->nRefCount = 1; mpSwapFile->aSwapURL = aTmpURL; } else { delete pOStm, pOStm = NULL; try { ::ucb::Content aCnt( aTmpURL.GetMainURL(), ::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( ::com::sun::star::ucb::CommandAbortedException& ) { DBG_ERRORFILE( "CommandAbortedException" ); } catch( ... ) { DBG_ERRORFILE( "Any other exception" ); } } delete pOStm; } } } else { ImplClearGraphics( TRUE ); bRet = mbSwapOut = TRUE; } } return bRet; } // ------------------------------------------------------------------------ BOOL ImpGraphic::ImplSwapOut( SvStream* pOStm ) { BOOL bRet = FALSE; if( pOStm ) { pOStm->SetBufferSize( GRAPHIC_STREAMBUFSIZE ); if( !pOStm->GetError() && ImplWriteEmbedded( *pOStm ) ) { pOStm->Flush(); if( !pOStm->GetError() ) { ImplClearGraphics( TRUE ); bRet = mbSwapOut = TRUE; } } } else { ImplClearGraphics( TRUE ); bRet = mbSwapOut = TRUE; } return bRet; } // ------------------------------------------------------------------------ BOOL ImpGraphic::ImplSwapIn() { BOOL bRet = FALSE; if( ImplIsSwapOut() ) { String aSwapURL; if( mpSwapFile ) aSwapURL = mpSwapFile->aSwapURL.GetMainURL(); else aSwapURL = maDocFileURLStr; if( aSwapURL.Len() ) { SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( aSwapURL, STREAM_READWRITE | STREAM_SHARE_DENYWRITE ); if( pIStm ) { pIStm->SetVersion( SOFFICE_FILEFORMAT_NOW ); pIStm->SetCompressMode( COMPRESSMODE_NATIVE ); if( !mpSwapFile ) pIStm->Seek( mnDocFilePos ); bRet = ImplSwapIn( pIStm ); delete pIStm; if( mpSwapFile ) { if( mpSwapFile->nRefCount > 1 ) mpSwapFile->nRefCount--; else { try { ::ucb::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( ::com::sun::star::ucb::CommandAbortedException& ) { DBG_ERRORFILE( "CommandAbortedException" ); } catch( ... ) { DBG_ERRORFILE( "Any other exception" ); } delete mpSwapFile; } mpSwapFile = NULL; } } } } return bRet; } // ------------------------------------------------------------------------ BOOL ImpGraphic::ImplSwapIn( SvStream* pIStm ) { BOOL bRet = FALSE; if( pIStm ) { pIStm->SetBufferSize( GRAPHIC_STREAMBUFSIZE ); if( !pIStm->GetError() ) { mbSwapUnderway = TRUE; bRet = ImplReadEmbedded( *pIStm ); mbSwapUnderway = FALSE; if( !bRet ) ImplClear(); else mbSwapOut = FALSE; } } return bRet; } // ------------------------------------------------------------------------ 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() ); } // ------------------------------------------------------------------------ BOOL ImpGraphic::ImplIsLink() const { return ( mpGfxLink != NULL ) ? TRUE : FALSE; } // ------------------------------------------------------------------------ ULONG ImpGraphic::ImplGetChecksum() const { ULONG nRet = 0; if( ImplIsSupportedGraphic() && !ImplIsSwapOut() ) { switch( meType ) { case( GRAPHIC_DEFAULT ): break; case( GRAPHIC_BITMAP ): { if( mpAnimation ) nRet = mpAnimation->GetChecksum(); else nRet = maEx.GetChecksum(); } break; default: nRet = maMetaFile.GetChecksum(); break; } } return nRet; } // ------------------------------------------------------------------------ BOOL ImpGraphic::ImplCopy() const { DBG_ERROR( "Missing implementation!" ); return FALSE; } // ------------------------------------------------------------------------ BOOL ImpGraphic::ImplPaste() { DBG_ERROR( "Missing implementation!" ); return FALSE; } // ------------------------------------------------------------------------ SvStream& operator>>( SvStream& rIStm, ImpGraphic& rImpGraphic ) { if( !rIStm.GetError() ) { const ULONG nStmPos1 = rIStm.Tell(); ULONG nTmp; if ( !rImpGraphic.mbSwapUnderway ) rImpGraphic.ImplClear(); // read Id rIStm >> nTmp; 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 BOOL bSetLink = ( rImpGraphic.mpGfxLink == NULL ); // assign graphic rImpGraphic = *aGraphic.ImplGetImpGraphic(); if( bSetLink ) rImpGraphic.ImplSetLink( aLink ); } else { rIStm.Seek( nStmPos1 ); rIStm.SetError( ERRCODE_IO_WRONGFORMAT ); } } else { BitmapEx aBmpEx; const USHORT nOldFormat = rIStm.GetNumberFormatInt(); rIStm.SeekRel( -4 ); rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); rIStm >> aBmpEx; if( !rIStm.GetError() ) { UINT32 nMagic1, nMagic2; ULONG nActPos = rIStm.Tell(); rIStm >> nMagic1 >> nMagic2; rIStm.Seek( nActPos ); rImpGraphic = ImpGraphic( aBmpEx ); if( ( 0x5344414e == nMagic1 ) && ( 0x494d4931 == nMagic2 ) && !rIStm.GetError() ) { delete rImpGraphic.mpAnimation; rImpGraphic.mpAnimation = new Animation; rIStm >> *rImpGraphic.mpAnimation; } } else { GDIMetaFile aMtf; rIStm.Seek( nStmPos1 ); rIStm.ResetError(); rIStm >> aMtf; if( !rIStm.GetError() ) rImpGraphic = aMtf; else 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; rOStm << *rImpGraphic.mpGfxLink; } else { // own format const USHORT nOldFormat = rOStm.GetNumberFormatInt(); rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); switch( rImpGraphic.ImplGetType() ) { case( GRAPHIC_NONE ): case( GRAPHIC_DEFAULT ): break; case GRAPHIC_BITMAP: { if ( rImpGraphic.ImplIsAnimated() ) rOStm << *rImpGraphic.mpAnimation; else rOStm << rImpGraphic.maEx; } break; default: { if( rImpGraphic.ImplIsSupportedGraphic() ) rOStm << rImpGraphic.maMetaFile; } break; } rOStm.SetNumberFormatInt( nOldFormat ); } } else rOStm.SetError( SVSTREAM_GENERALERROR ); } return rOStm; }