diff options
Diffstat (limited to 'svx/source/xml/xmlgrhlp.cxx')
-rw-r--r-- | svx/source/xml/xmlgrhlp.cxx | 1155 |
1 files changed, 1155 insertions, 0 deletions
diff --git a/svx/source/xml/xmlgrhlp.cxx b/svx/source/xml/xmlgrhlp.cxx new file mode 100644 index 000000000000..7fd3325cc4d8 --- /dev/null +++ b/svx/source/xml/xmlgrhlp.cxx @@ -0,0 +1,1155 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <sal/macros.h> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <cppuhelper/compbase4.hxx> + +#include <unotools/ucbstreamhelper.hxx> +#include <unotools/streamwrap.hxx> +#include <unotools/tempfile.hxx> +#include <tools/debug.hxx> +#include <vcl/cvtgrf.hxx> +#include <vcl/gfxlink.hxx> +#include <vcl/metaact.hxx> +#include <tools/zcodec.hxx> + +#include "svtools/filter.hxx" +#include "xmlgrhlp.hxx" + +#include <algorithm> + +// ----------- +// - Defines - +// ----------- + +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::io; + +using ::com::sun::star::lang::XMultiServiceFactory; + +#define XML_GRAPHICSTORAGE_NAME "Pictures" +#define XML_PACKAGE_URL_BASE "vnd.sun.star.Package:" +#define XML_GRAPHICOBJECT_URL_BASE "vnd.sun.star.GraphicObject:" + +// --------------------------- +// - SvXMLGraphicInputStream - +// --------------------------- + +const MetaCommentAction* ImplCheckForEPS( GDIMetaFile& rMtf ) +{ + static ByteString aComment( (const sal_Char*)"EPSReplacementGraphic" ); + const MetaCommentAction* pComment = NULL; + + if ( ( rMtf.GetActionCount() >= 2 ) + && ( rMtf.FirstAction()->GetType() == META_EPS_ACTION ) + && ( ((const MetaAction*)rMtf.GetAction( 1 ))->GetType() == META_COMMENT_ACTION ) + && ( ((const MetaCommentAction*)rMtf.GetAction( 1 ))->GetComment() == aComment ) ) + pComment = (const MetaCommentAction*)rMtf.GetAction( 1 ); + + return pComment; +} + +class SvXMLGraphicInputStream : public::cppu::WeakImplHelper1< XInputStream > +{ +private: + + virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) throw(NotConnectedException, BufferSizeExceededException, RuntimeException); + virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) throw(NotConnectedException, BufferSizeExceededException, RuntimeException); + virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) throw(NotConnectedException, BufferSizeExceededException, RuntimeException); + virtual sal_Int32 SAL_CALL available() throw(NotConnectedException, RuntimeException); + virtual void SAL_CALL closeInput() throw(NotConnectedException, RuntimeException); + +private: + + ::utl::TempFile maTmp; + Reference< XInputStream > mxStmWrapper; + + // not available + SvXMLGraphicInputStream(); + SvXMLGraphicInputStream( const SvXMLGraphicInputStream& ); + SvXMLGraphicInputStream& operator==( SvXMLGraphicInputStream& ); + +public: + + SvXMLGraphicInputStream( const ::rtl::OUString& rGraphicId ); + virtual ~SvXMLGraphicInputStream(); + + sal_Bool Exists() const { return mxStmWrapper.is(); } +}; + +// ----------------------------------------------------------------------------- + +SvXMLGraphicInputStream::SvXMLGraphicInputStream( const ::rtl::OUString& rGraphicId ) +{ + String aGraphicId( rGraphicId ); + GraphicObject aGrfObject( ByteString( aGraphicId, RTL_TEXTENCODING_ASCII_US ) ); + + maTmp.EnableKillingFile(); + + if( aGrfObject.GetType() != GRAPHIC_NONE ) + { + SvStream* pStm = ::utl::UcbStreamHelper::CreateStream( maTmp.GetURL(), STREAM_WRITE | STREAM_TRUNC ); + + if( pStm ) + { + Graphic aGraphic( (Graphic&) aGrfObject.GetGraphic() ); + const GfxLink aGfxLink( aGraphic.GetLink() ); + sal_Bool bRet = sal_False; + + if( aGfxLink.GetDataSize() && aGfxLink.GetData() ) + { + pStm->Write( aGfxLink.GetData(), aGfxLink.GetDataSize() ); + bRet = ( pStm->GetError() == 0 ); + } + else + { + if( aGraphic.GetType() == GRAPHIC_BITMAP ) + { + GraphicFilter* pFilter = GraphicFilter::GetGraphicFilter(); + String aFormat; + + if( aGraphic.IsAnimated() ) + aFormat = String( RTL_CONSTASCII_USTRINGPARAM( "gif" ) ); + else + aFormat = String( RTL_CONSTASCII_USTRINGPARAM( "png" ) ); + + bRet = ( pFilter->ExportGraphic( aGraphic, String(), *pStm, pFilter->GetExportFormatNumberForShortName( aFormat ) ) == 0 ); + } + else if( aGraphic.GetType() == GRAPHIC_GDIMETAFILE ) + { + pStm->SetVersion( SOFFICE_FILEFORMAT_8 ); + pStm->SetCompressMode( COMPRESSMODE_ZBITMAP ); + ( (GDIMetaFile&) aGraphic.GetGDIMetaFile() ).Write( *pStm ); + bRet = ( pStm->GetError() == 0 ); + } + } + + if( bRet ) + { + pStm->Seek( 0 ); + mxStmWrapper = new ::utl::OInputStreamWrapper( pStm, sal_True ); + } + else + delete pStm; + } + } +} + +// ----------------------------------------------------------------------------- + +SvXMLGraphicInputStream::~SvXMLGraphicInputStream() +{ +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL SvXMLGraphicInputStream::readBytes( Sequence< sal_Int8 >& rData, sal_Int32 nBytesToRead ) + throw( NotConnectedException, BufferSizeExceededException, RuntimeException ) +{ + if( !mxStmWrapper.is() ) + throw NotConnectedException(); + + return mxStmWrapper->readBytes( rData, nBytesToRead ); +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL SvXMLGraphicInputStream::readSomeBytes( Sequence< sal_Int8 >& rData, sal_Int32 nMaxBytesToRead ) + throw( NotConnectedException, BufferSizeExceededException, RuntimeException ) +{ + if( !mxStmWrapper.is() ) + throw NotConnectedException() ; + + return mxStmWrapper->readSomeBytes( rData, nMaxBytesToRead ); +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL SvXMLGraphicInputStream::skipBytes( sal_Int32 nBytesToSkip ) + throw( NotConnectedException, BufferSizeExceededException, RuntimeException ) +{ + if( !mxStmWrapper.is() ) + throw NotConnectedException() ; + + mxStmWrapper->skipBytes( nBytesToSkip ); +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL SvXMLGraphicInputStream::available() throw( NotConnectedException, RuntimeException ) +{ + if( !mxStmWrapper.is() ) + throw NotConnectedException() ; + + return mxStmWrapper->available(); +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL SvXMLGraphicInputStream::closeInput() throw( NotConnectedException, RuntimeException ) +{ + if( !mxStmWrapper.is() ) + throw NotConnectedException() ; + + mxStmWrapper->closeInput(); +} + +// ---------------------------- +// - SvXMLGraphicOutputStream - +// ---------------------------- + +class SvXMLGraphicOutputStream : public::cppu::WeakImplHelper1< XOutputStream > +{ +private: + + // XOutputStream + virtual void SAL_CALL writeBytes( const Sequence< sal_Int8 >& rData ) throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException ); + virtual void SAL_CALL flush() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException ); + virtual void SAL_CALL closeOutput() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException ); + +private: + + ::utl::TempFile* mpTmp; + SvStream* mpOStm; + Reference< XOutputStream > mxStmWrapper; + GraphicObject maGrfObj; + sal_Bool mbClosed; + + // not available + SvXMLGraphicOutputStream( const SvXMLGraphicOutputStream& ); + SvXMLGraphicOutputStream& operator==( SvXMLGraphicOutputStream& ); + +public: + + SvXMLGraphicOutputStream(); + virtual ~SvXMLGraphicOutputStream(); + + sal_Bool Exists() const { return mxStmWrapper.is(); } + const GraphicObject& GetGraphicObject(); +}; + +// ----------------------------------------------------------------------------- + +SvXMLGraphicOutputStream::SvXMLGraphicOutputStream() : + mpTmp( new ::utl::TempFile ), + mbClosed( sal_False ) +{ + mpTmp->EnableKillingFile(); + + mpOStm = ::utl::UcbStreamHelper::CreateStream( mpTmp->GetURL(), STREAM_WRITE | STREAM_TRUNC ); + + if( mpOStm ) + mxStmWrapper = new ::utl::OOutputStreamWrapper( *mpOStm ); +} + +// ----------------------------------------------------------------------------- + +SvXMLGraphicOutputStream::~SvXMLGraphicOutputStream() +{ + delete mpTmp; + delete mpOStm; +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL SvXMLGraphicOutputStream::writeBytes( const Sequence< sal_Int8 >& rData ) + throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException ) +{ + if( !mxStmWrapper.is() ) + throw NotConnectedException() ; + + mxStmWrapper->writeBytes( rData ); +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL SvXMLGraphicOutputStream::flush() + throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException ) +{ + if( !mxStmWrapper.is() ) + throw NotConnectedException() ; + + mxStmWrapper->flush(); +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL SvXMLGraphicOutputStream::closeOutput() + throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException ) +{ + if( !mxStmWrapper.is() ) + throw NotConnectedException() ; + + mxStmWrapper->closeOutput(); + mxStmWrapper = Reference< XOutputStream >(); + + mbClosed = sal_True; +} + +// ------------------------------------------------------------------------------ + +const GraphicObject& SvXMLGraphicOutputStream::GetGraphicObject() +{ + if( mbClosed && ( maGrfObj.GetType() == GRAPHIC_NONE ) && mpOStm ) + { + Graphic aGraphic; + + mpOStm->Seek( 0 ); + USHORT nFormat = GRFILTER_FORMAT_DONTKNOW; + USHORT pDeterminedFormat = GRFILTER_FORMAT_DONTKNOW; + GraphicFilter::GetGraphicFilter()->ImportGraphic( aGraphic, String(), *mpOStm ,nFormat,&pDeterminedFormat ); + + if (pDeterminedFormat == GRFILTER_FORMAT_DONTKNOW) + { + //Read the first two byte to check whether it is a gzipped stream, is so it may be in wmz or emz format + //unzip them and try again + + BYTE sFirstBytes[ 2 ]; + + mpOStm->Seek( STREAM_SEEK_TO_END ); + ULONG nStreamLen = mpOStm->Tell(); + mpOStm->Seek( 0 ); + + if ( !nStreamLen ) + { + SvLockBytes* pLockBytes = mpOStm->GetLockBytes(); + if ( pLockBytes ) + pLockBytes->SetSynchronMode( TRUE ); + + mpOStm->Seek( STREAM_SEEK_TO_END ); + nStreamLen = mpOStm->Tell(); + mpOStm->Seek( 0 ); + } + if( nStreamLen >= 2 ) + { + //read two byte + mpOStm->Read( sFirstBytes, 2 ); + + if( sFirstBytes[0] == 0x1f && sFirstBytes[1] == 0x8b ) + { + SvMemoryStream* pDest = new SvMemoryStream; + ZCodec aZCodec( 0x8000, 0x8000 ); + aZCodec.BeginCompression(ZCODEC_GZ_LIB); + mpOStm->Seek( 0 ); + aZCodec.Decompress( *mpOStm, *pDest ); + + if (aZCodec.EndCompression() && pDest ) + { + pDest->Seek( STREAM_SEEK_TO_END ); + ULONG nStreamLen_ = pDest->Tell(); + if (nStreamLen_) + { + pDest->Seek(0L); + GraphicFilter::GetGraphicFilter()->ImportGraphic( aGraphic, String(), *pDest ,nFormat,&pDeterminedFormat ); + } + } + delete pDest; + } + } + } + + maGrfObj = aGraphic; + if( maGrfObj.GetType() != GRAPHIC_NONE ) + { + delete mpOStm, mpOStm = NULL; + delete mpTmp, mpTmp = NULL; + } + } + + return maGrfObj; +} + +// ---------------------- +// - SvXMLGraphicHelper - +// ---------------------- + +SvXMLGraphicHelper::SvXMLGraphicHelper( SvXMLGraphicHelperMode eCreateMode ) : + ::cppu::WeakComponentImplHelper2< ::com::sun::star::document::XGraphicObjectResolver, + ::com::sun::star::document::XBinaryStreamResolver >( maMutex ) +{ + Init( NULL, eCreateMode, sal_False ); +} + +SvXMLGraphicHelper::SvXMLGraphicHelper() : + ::cppu::WeakComponentImplHelper2< ::com::sun::star::document::XGraphicObjectResolver, + ::com::sun::star::document::XBinaryStreamResolver >( maMutex ) +{ +} + +// ----------------------------------------------------------------------------- + +SvXMLGraphicHelper::~SvXMLGraphicHelper() +{ +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL SvXMLGraphicHelper::disposing() +{ +} + +// ----------------------------------------------------------------------------- + +sal_Bool SvXMLGraphicHelper::ImplGetStreamNames( const ::rtl::OUString& rURLStr, + ::rtl::OUString& rPictureStorageName, + ::rtl::OUString& rPictureStreamName ) +{ + String aURLStr( rURLStr ); + sal_Bool bRet = sal_False; + + if( aURLStr.Len() ) + { + aURLStr = aURLStr.GetToken( aURLStr.GetTokenCount( ':' ) - 1, ':' ); + const sal_uInt32 nTokenCount = aURLStr.GetTokenCount( '/' ); + + if( 1 == nTokenCount ) + { + rPictureStorageName = String( RTL_CONSTASCII_USTRINGPARAM( XML_GRAPHICSTORAGE_NAME ) ); + rPictureStreamName = aURLStr; + bRet = sal_True; + } + else if( 2 == nTokenCount ) + { + rPictureStorageName = aURLStr.GetToken( 0, '/' ); + + DBG_ASSERT( rPictureStorageName.getLength() && + rPictureStorageName.getStr()[ 0 ] != '#', + "invalid relative URL" ); + + rPictureStreamName = aURLStr.GetToken( 1, '/' ); + bRet = sal_True; + } + else + { + DBG_ERROR( "SvXMLGraphicHelper::ImplInsertGraphicURL: invalid scheme" ); + } + } + + return bRet; +} + +// ----------------------------------------------------------------------------- + +uno::Reference < embed::XStorage > SvXMLGraphicHelper::ImplGetGraphicStorage( const ::rtl::OUString& rStorageName ) +{ + uno::Reference < embed::XStorage > xRetStorage; + if( mxRootStorage.is() ) + { + try + { + xRetStorage = mxRootStorage->openStorageElement( + maCurStorageName = rStorageName, + ( GRAPHICHELPER_MODE_WRITE == meCreateMode ) + ? embed::ElementModes::READWRITE + : embed::ElementModes::READ ); + } + catch ( uno::Exception& ) + { + } + //#i43196# try again to open the storage element - this time readonly + if(!xRetStorage.is()) + { + try + { + xRetStorage = mxRootStorage->openStorageElement( maCurStorageName = rStorageName, embed::ElementModes::READ ); + } + catch ( uno::Exception& ) + { + } + } + } + + return xRetStorage; +} + +// ----------------------------------------------------------------------------- + +SvxGraphicHelperStream_Impl SvXMLGraphicHelper::ImplGetGraphicStream( const ::rtl::OUString& rPictureStorageName, + const ::rtl::OUString& rPictureStreamName, + BOOL bTruncate ) +{ + SvxGraphicHelperStream_Impl aRet; + aRet.xStorage = ImplGetGraphicStorage( rPictureStorageName ); + + if( aRet.xStorage.is() ) + { + sal_Int32 nMode = embed::ElementModes::READ; + if ( GRAPHICHELPER_MODE_WRITE == meCreateMode ) + { + nMode = embed::ElementModes::READWRITE; + if ( bTruncate ) + nMode |= embed::ElementModes::TRUNCATE; + } + + aRet.xStream = aRet.xStorage->openStreamElement( rPictureStreamName, nMode ); + if( aRet.xStream.is() && ( GRAPHICHELPER_MODE_WRITE == meCreateMode ) ) + { +//REMOVE ::rtl::OUString aPropName( RTL_CONSTASCII_USTRINGPARAM("Encrypted") ); + ::rtl::OUString aPropName( RTL_CONSTASCII_USTRINGPARAM("UseCommonStoragePasswordEncryption") ); + uno::Reference < beans::XPropertySet > xProps( aRet.xStream, uno::UNO_QUERY ); + xProps->setPropertyValue( aPropName, uno::makeAny( sal_True) ); + } + } + + return aRet; +} + +// ----------------------------------------------------------------------------- + +String SvXMLGraphicHelper::ImplGetGraphicMimeType( const String& rFileName ) const +{ + struct XMLGraphicMimeTypeMapper + { + const char* pExt; + const char* pMimeType; + }; + + static XMLGraphicMimeTypeMapper aMapper[] = + { + { "gif", "image/gif" }, + { "png", "image/png" }, + { "jpg", "image/jpeg" }, + { "tif", "image/tiff" } + }; + + String aMimeType; + + if( ( rFileName.Len() >= 4 ) && ( rFileName.GetChar( rFileName.Len() - 4 ) == '.' ) ) + { + const ByteString aExt( rFileName.Copy( rFileName.Len() - 3 ), RTL_TEXTENCODING_ASCII_US ); + + for( long i = 0, nCount = SAL_N_ELEMENTS( aMapper ); ( i < nCount ) && !aMimeType.Len(); i++ ) + if( aExt == aMapper[ i ].pExt ) + aMimeType = String( aMapper[ i ].pMimeType, RTL_TEXTENCODING_ASCII_US ); + } + + return aMimeType; +} + +// ----------------------------------------------------------------------------- + +Graphic SvXMLGraphicHelper::ImplReadGraphic( const ::rtl::OUString& rPictureStorageName, + const ::rtl::OUString& rPictureStreamName ) +{ + Graphic aGraphic; + SvxGraphicHelperStream_Impl aStream( ImplGetGraphicStream( rPictureStorageName, rPictureStreamName, FALSE ) ); + if( aStream.xStream.is() ) + { + SvStream* pStream = utl::UcbStreamHelper::CreateStream( aStream.xStream ); + GraphicFilter::GetGraphicFilter()->ImportGraphic( aGraphic, String(), *pStream ); + delete pStream; + } + + return aGraphic; +} + +// ----------------------------------------------------------------------------- + +sal_Bool SvXMLGraphicHelper::ImplWriteGraphic( const ::rtl::OUString& rPictureStorageName, + const ::rtl::OUString& rPictureStreamName, + const ::rtl::OUString& rGraphicId ) +{ + String aGraphicId( rGraphicId ); + GraphicObject aGrfObject( ByteString( aGraphicId, RTL_TEXTENCODING_ASCII_US ) ); + sal_Bool bRet = sal_False; + + if( aGrfObject.GetType() != GRAPHIC_NONE ) + { + SvxGraphicHelperStream_Impl aStream( ImplGetGraphicStream( rPictureStorageName, rPictureStreamName, FALSE ) ); + if( aStream.xStream.is() ) + { + Graphic aGraphic( (Graphic&) aGrfObject.GetGraphic() ); + const GfxLink aGfxLink( aGraphic.GetLink() ); + const ::rtl::OUString aMimeType( ImplGetGraphicMimeType( rPictureStreamName ) ); + uno::Any aAny; + uno::Reference < beans::XPropertySet > xProps( aStream.xStream, uno::UNO_QUERY ); + + // set stream properties (MediaType/Compression) + if( aMimeType.getLength() ) + { + aAny <<= aMimeType; + xProps->setPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), aAny ); + } + + const sal_Bool bCompressed = ( ( 0 == aMimeType.getLength() ) || ( aMimeType == ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("image/tiff")) ) ); + aAny <<= bCompressed; + xProps->setPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) ), aAny ); + + SvStream* pStream = utl::UcbStreamHelper::CreateStream( aStream.xStream ); + if( aGfxLink.GetDataSize() && aGfxLink.GetData() ) + pStream->Write( aGfxLink.GetData(), aGfxLink.GetDataSize() ); + else + { + if( aGraphic.GetType() == GRAPHIC_BITMAP ) + { + GraphicFilter* pFilter = GraphicFilter::GetGraphicFilter(); + String aFormat; + + if( aGraphic.IsAnimated() ) + aFormat = String( RTL_CONSTASCII_USTRINGPARAM( "gif" ) ); + else + aFormat = String( RTL_CONSTASCII_USTRINGPARAM( "png" ) ); + + bRet = ( pFilter->ExportGraphic( aGraphic, String(), *pStream, + pFilter->GetExportFormatNumberForShortName( aFormat ) ) == 0 ); + } + else if( aGraphic.GetType() == GRAPHIC_GDIMETAFILE ) + { + pStream->SetVersion( SOFFICE_FILEFORMAT_8 ); + pStream->SetCompressMode( COMPRESSMODE_ZBITMAP ); + + // SJ: first check if this metafile is just a eps file, then we will store the eps instead of svm + GDIMetaFile& rMtf( (GDIMetaFile&)aGraphic.GetGDIMetaFile() ); + const MetaCommentAction* pComment = ImplCheckForEPS( rMtf ); + if ( pComment ) + { + sal_uInt32 nSize = pComment->GetDataSize(); + const BYTE* pData = pComment->GetData(); + if ( nSize && pData ) + pStream->Write( pData, nSize ); + + const MetaEPSAction* pAct = ( (const MetaEPSAction*)rMtf.FirstAction() ); + const GfxLink& rLink = pAct->GetLink(); + + pStream->Write( rLink.GetData(), rLink.GetDataSize() ); + } + else + rMtf.Write( *pStream ); + + bRet = ( pStream->GetError() == 0 ); + } + } + uno::Reference < embed::XTransactedObject > xStorage( + aStream.xStorage, uno::UNO_QUERY); + delete pStream; + aStream.xStream->getOutputStream()->closeOutput(); + if( xStorage.is() ) + xStorage->commit(); + } + } + + return bRet; +} + +// ----------------------------------------------------------------------------- + +void SvXMLGraphicHelper::ImplInsertGraphicURL( const ::rtl::OUString& rURLStr, sal_uInt32 nInsertPos, rtl::OUString& rRequestedFileName ) +{ + rtl::OUString aURLString( rURLStr ); + ::rtl::OUString aPictureStorageName, aPictureStreamName; + if( ( maURLSet.find( aURLString ) != maURLSet.end() ) ) + { + URLPairVector::iterator aIter( maGrfURLs.begin() ), aEnd( maGrfURLs.end() ); + while( aIter != aEnd ) + { + if( aURLString == (*aIter).first ) + { + maGrfURLs[ nInsertPos ].second = (*aIter).second; + aIter = aEnd; + } + else + aIter++; + } + } + else if( ImplGetStreamNames( aURLString, aPictureStorageName, aPictureStreamName ) ) + { + URLPair& rURLPair = maGrfURLs[ nInsertPos ]; + + if( GRAPHICHELPER_MODE_READ == meCreateMode ) + { + const GraphicObject aObj( ImplReadGraphic( aPictureStorageName, aPictureStreamName ) ); + + if( aObj.GetType() != GRAPHIC_NONE ) + { + const static ::rtl::OUString aBaseURL( RTL_CONSTASCII_USTRINGPARAM( XML_GRAPHICOBJECT_URL_BASE ) ); + + maGrfObjs.push_back( aObj ); + rURLPair.second = aBaseURL; + rURLPair.second += String( aObj.GetUniqueID().GetBuffer(), RTL_TEXTENCODING_ASCII_US ); + } + else + rURLPair.second = String(); + } + else + { + const String aGraphicObjectId( aPictureStreamName ); + const GraphicObject aGrfObject( ByteString( aGraphicObjectId, RTL_TEXTENCODING_ASCII_US ) ); + + if( aGrfObject.GetType() != GRAPHIC_NONE ) + { + String aStreamName( aGraphicObjectId ); + Graphic aGraphic( (Graphic&) aGrfObject.GetGraphic() ); + const GfxLink aGfxLink( aGraphic.GetLink() ); + String aExtension; + + if( aGfxLink.GetDataSize() ) + { + switch( aGfxLink.GetType() ) + { + case( GFX_LINK_TYPE_EPS_BUFFER ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".eps" ) ); break; + case( GFX_LINK_TYPE_NATIVE_GIF ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".gif" ) ); break; + case( GFX_LINK_TYPE_NATIVE_JPG ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".jpg" ) ); break; + case( GFX_LINK_TYPE_NATIVE_PNG ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".png" ) ); break; + case( GFX_LINK_TYPE_NATIVE_TIF ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".tif" ) ); break; + case( GFX_LINK_TYPE_NATIVE_WMF ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".wmf" ) ); break; + case( GFX_LINK_TYPE_NATIVE_MET ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".met" ) ); break; + case( GFX_LINK_TYPE_NATIVE_PCT ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".pct" ) ); break; + + default: + aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".grf" ) ); + break; + } + } + else + { + if( aGrfObject.GetType() == GRAPHIC_BITMAP ) + { + if( aGrfObject.IsAnimated() ) + aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".gif" ) ); + else + aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".png" ) ); + } + else if( aGrfObject.GetType() == GRAPHIC_GDIMETAFILE ) + { + // SJ: first check if this metafile is just a eps file, then we will store the eps instead of svm + GDIMetaFile& rMtf( (GDIMetaFile&)aGraphic.GetGDIMetaFile() ); + if ( ImplCheckForEPS( rMtf ) ) + aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".eps" ) ); + else + aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".svm" ) ); + } + } + + rtl::OUString aURLEntry; + const String sPictures( RTL_CONSTASCII_USTRINGPARAM( "Pictures/" ) ); + + if ( rRequestedFileName.getLength() ) + { + aURLEntry = sPictures; + aURLEntry += rRequestedFileName; + aURLEntry += aExtension; + + URLPairVector::iterator aIter( maGrfURLs.begin() ), aEnd( maGrfURLs.end() ); + while( aIter != aEnd ) + { + if( aURLEntry == (*aIter).second ) + break; + aIter++; + } + if ( aIter == aEnd ) + aStreamName = rRequestedFileName; + } + + aStreamName += aExtension; + + if( mbDirect && aStreamName.Len() ) + ImplWriteGraphic( aPictureStorageName, aStreamName, aGraphicObjectId ); + + rURLPair.second = sPictures; + rURLPair.second += aStreamName; + } + } + + maURLSet.insert( aURLString ); + } +} + +// ----------------------------------------------------------------------------- + +void SvXMLGraphicHelper::Init( const uno::Reference < embed::XStorage >& rXMLStorage, + SvXMLGraphicHelperMode eCreateMode, + BOOL bDirect ) +{ + mxRootStorage = rXMLStorage; + meCreateMode = eCreateMode; + mbDirect = ( ( GRAPHICHELPER_MODE_READ == meCreateMode ) ? bDirect : sal_True ); +} + +// ----------------------------------------------------------------------------- + +SvXMLGraphicHelper* SvXMLGraphicHelper::Create( const uno::Reference < embed::XStorage >& rXMLStorage, + SvXMLGraphicHelperMode eCreateMode, + BOOL bDirect ) +{ + SvXMLGraphicHelper* pThis = new SvXMLGraphicHelper; + + pThis->acquire(); + pThis->Init( rXMLStorage, eCreateMode, bDirect ); + + return pThis; +} + +// ----------------------------------------------------------------------------- + +SvXMLGraphicHelper* SvXMLGraphicHelper::Create( SvXMLGraphicHelperMode eCreateMode ) +{ + SvXMLGraphicHelper* pThis = new SvXMLGraphicHelper; + + pThis->acquire(); + pThis->Init( NULL, eCreateMode, sal_False ); + + return pThis; +} + +// ----------------------------------------------------------------------------- + +void SvXMLGraphicHelper::Destroy( SvXMLGraphicHelper* pSvXMLGraphicHelper ) +{ + if( pSvXMLGraphicHelper ) + { + pSvXMLGraphicHelper->dispose(); + pSvXMLGraphicHelper->release(); + } +} + +// ----------------------------------------------------------------------------- + +// XGraphicObjectResolver +::rtl::OUString SAL_CALL SvXMLGraphicHelper::resolveGraphicObjectURL( const ::rtl::OUString& rURL ) + throw(uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( maMutex ); + const sal_Int32 nIndex = maGrfURLs.size(); + + rtl::OUString aURL( rURL ); + rtl::OUString aUserData; + rtl::OUString aRequestedFileName; + + sal_Int32 nUser = rURL.indexOf( '?', 0 ); + if ( nUser >= 0 ) + { + aURL = rtl::OUString( rURL.copy( 0, nUser ) ); + nUser++; + aUserData = rURL.copy( nUser, rURL.getLength() - nUser ); + } + if ( aUserData.getLength() ) + { + sal_Int32 nIndex2 = 0; + do + { + rtl::OUString aToken = aUserData.getToken( 0, ';', nIndex2 ); + sal_Int32 n = aToken.indexOf( '=' ); + if ( ( n > 0 ) && ( ( n + 1 ) < aToken.getLength() ) ) + { + rtl::OUString aParam( aToken.copy( 0, n ) ); + rtl::OUString aValue( aToken.copy( n + 1, aToken.getLength() - ( n + 1 ) ) ); + + const rtl::OUString sRequestedName( RTL_CONSTASCII_USTRINGPARAM("requestedName") ); + if ( aParam.match( sRequestedName ) ) + aRequestedFileName = aValue; + } + } + while ( nIndex2 >= 0 ); + } + + maGrfURLs.push_back( ::std::make_pair( aURL, ::rtl::OUString() ) ); + ImplInsertGraphicURL( aURL, nIndex, aRequestedFileName ); + + return maGrfURLs[ nIndex ].second; +} + +// ----------------------------------------------------------------------------- + +// XBinaryStreamResolver +Reference< XInputStream > SAL_CALL SvXMLGraphicHelper::getInputStream( const ::rtl::OUString& rURL ) + throw( RuntimeException ) +{ + Reference< XInputStream > xRet; + ::rtl::OUString aPictureStorageName, aGraphicId; + + + if( ( GRAPHICHELPER_MODE_WRITE == meCreateMode ) && + ImplGetStreamNames( rURL, aPictureStorageName, aGraphicId ) ) + { + SvXMLGraphicInputStream* pInputStream = new SvXMLGraphicInputStream( aGraphicId ); + + if( pInputStream->Exists() ) + xRet = pInputStream; + else + delete pInputStream; + } + + return xRet; +} + +// ----------------------------------------------------------------------------- + +Reference< XOutputStream > SAL_CALL SvXMLGraphicHelper::createOutputStream() + throw( RuntimeException ) +{ + Reference< XOutputStream > xRet; + + if( GRAPHICHELPER_MODE_READ == meCreateMode ) + { + SvXMLGraphicOutputStream* pOutputStream = new SvXMLGraphicOutputStream; + + if( pOutputStream->Exists() ) + maGrfStms.push_back( xRet = pOutputStream ); + else + delete pOutputStream; + } + + return xRet; +} + +// ----------------------------------------------------------------------------- + +::rtl::OUString SAL_CALL SvXMLGraphicHelper::resolveOutputStream( const Reference< XOutputStream >& rxBinaryStream ) + throw( RuntimeException ) +{ + ::rtl::OUString aRet; + + if( ( GRAPHICHELPER_MODE_READ == meCreateMode ) && rxBinaryStream.is() ) + { + if( ::std::find( maGrfStms.begin(), maGrfStms.end(), rxBinaryStream ) != maGrfStms.end() ) + { + SvXMLGraphicOutputStream* pOStm = static_cast< SvXMLGraphicOutputStream* >( rxBinaryStream.get() ); + + if( pOStm ) + { + const GraphicObject& rGrfObj = pOStm->GetGraphicObject(); + const ::rtl::OUString aId( ::rtl::OUString::createFromAscii( rGrfObj.GetUniqueID().GetBuffer() ) ); + + if( aId.getLength() ) + { + aRet = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( XML_GRAPHICOBJECT_URL_BASE )); + aRet += aId; + } + } + } + } + + return aRet; +} + + +// -------------------------------------------------------------------------------- + +// for instantiation via service manager +namespace svx +{ + +namespace impl +{ +typedef ::cppu::WeakComponentImplHelper4< + lang::XInitialization, + document::XGraphicObjectResolver, + document::XBinaryStreamResolver, + lang::XServiceInfo > + SvXMLGraphicImportExportHelper_Base; +class MutexContainer +{ +public: + virtual ~MutexContainer(); + +protected: + mutable ::osl::Mutex m_aMutex; +}; +MutexContainer::~MutexContainer() +{} +} // namespace impl + +class SvXMLGraphicImportExportHelper : + public impl::MutexContainer, + public impl::SvXMLGraphicImportExportHelper_Base +{ +public: + SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode ); + +protected: + // is called from WeakComponentImplHelper when XComponent::dispose() was + // called from outside + virtual void SAL_CALL disposing(); + + // ____ XInitialization ____ + // one argument is allowed, which is the XStorage + virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) + throw (Exception, + RuntimeException); + + // ____ XGraphicObjectResolver ____ + virtual ::rtl::OUString SAL_CALL resolveGraphicObjectURL( const ::rtl::OUString& aURL ) + throw (RuntimeException); + + // ____ XBinaryStreamResolver ____ + virtual Reference< io::XInputStream > SAL_CALL getInputStream( const ::rtl::OUString& aURL ) + throw (RuntimeException); + virtual Reference< io::XOutputStream > SAL_CALL createOutputStream() + throw (RuntimeException); + virtual ::rtl::OUString SAL_CALL resolveOutputStream( const Reference< io::XOutputStream >& aBinaryStream ) + throw (RuntimeException); + + // ____ XServiceInfo ____ + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw (RuntimeException); + virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw (RuntimeException); + virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() + throw (RuntimeException); + +private: + SvXMLGraphicHelperMode m_eGraphicHelperMode; + Reference< XGraphicObjectResolver > m_xGraphicObjectResolver; + Reference< XBinaryStreamResolver > m_xBinaryStreamResolver; +}; + +SvXMLGraphicImportExportHelper::SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode ) : + impl::SvXMLGraphicImportExportHelper_Base( m_aMutex ), + m_eGraphicHelperMode( eMode ) +{} + +void SAL_CALL SvXMLGraphicImportExportHelper::disposing() +{ + Reference< XComponent > xComp( m_xGraphicObjectResolver, UNO_QUERY ); + OSL_ASSERT( xComp.is()); + if( xComp.is()) + xComp->dispose(); + // m_xBinaryStreamResolver is a reference to the same object => don't call + // dispose() again +} + +// ____ XInitialization ____ +void SAL_CALL SvXMLGraphicImportExportHelper::initialize( + const Sequence< Any >& aArguments ) + throw (Exception, RuntimeException) +{ + Reference< embed::XStorage > xStorage; + if( aArguments.getLength() > 0 ) + aArguments[0] >>= xStorage; + + SvXMLGraphicHelper * pHelper( SvXMLGraphicHelper::Create( xStorage, m_eGraphicHelperMode )); + m_xGraphicObjectResolver.set( pHelper ); + m_xBinaryStreamResolver.set( pHelper ); + // SvXMLGraphicHelper::Create calls acquire. Since we have two references + // now it is safe (and necessary) to undo this acquire + pHelper->release(); +} + +// ____ XGraphicObjectResolver ____ +::rtl::OUString SAL_CALL SvXMLGraphicImportExportHelper::resolveGraphicObjectURL( const ::rtl::OUString& aURL ) + throw (uno::RuntimeException) +{ + return m_xGraphicObjectResolver->resolveGraphicObjectURL( aURL ); +} + + +// ____ XBinaryStreamResolver ____ +Reference< io::XInputStream > SAL_CALL SvXMLGraphicImportExportHelper::getInputStream( const ::rtl::OUString& aURL ) + throw (uno::RuntimeException) +{ + return m_xBinaryStreamResolver->getInputStream( aURL ); +} +Reference< io::XOutputStream > SAL_CALL SvXMLGraphicImportExportHelper::createOutputStream() + throw (uno::RuntimeException) +{ + return m_xBinaryStreamResolver->createOutputStream(); +} +::rtl::OUString SAL_CALL SvXMLGraphicImportExportHelper::resolveOutputStream( const Reference< io::XOutputStream >& aBinaryStream ) + throw (uno::RuntimeException) +{ + return m_xBinaryStreamResolver->resolveOutputStream( aBinaryStream ); +} + +// ____ XServiceInfo ____ +::rtl::OUString SAL_CALL SvXMLGraphicImportExportHelper::getImplementationName() + throw (uno::RuntimeException) +{ + if( m_eGraphicHelperMode == GRAPHICHELPER_MODE_READ ) + return SvXMLGraphicImportHelper_getImplementationName(); + return SvXMLGraphicExportHelper_getImplementationName(); +} +::sal_Bool SAL_CALL SvXMLGraphicImportExportHelper::supportsService( const ::rtl::OUString& ServiceName ) + throw (uno::RuntimeException) +{ + Sequence< ::rtl::OUString > aServiceNames( getSupportedServiceNames()); + const ::rtl::OUString * pBegin = aServiceNames.getConstArray(); + const ::rtl::OUString * pEnd = pBegin + aServiceNames.getLength(); + return (::std::find( pBegin, pEnd, ServiceName ) != pEnd); +} +Sequence< ::rtl::OUString > SAL_CALL SvXMLGraphicImportExportHelper::getSupportedServiceNames() + throw (uno::RuntimeException) +{ + if( m_eGraphicHelperMode == GRAPHICHELPER_MODE_READ ) + return SvXMLGraphicImportHelper_getSupportedServiceNames(); + return SvXMLGraphicExportHelper_getSupportedServiceNames(); +} + +// import +Reference< XInterface > SAL_CALL SvXMLGraphicImportHelper_createInstance(const Reference< XMultiServiceFactory > & /* rSMgr */ ) + throw( Exception ) +{ + return static_cast< XWeak* >( new SvXMLGraphicImportExportHelper( GRAPHICHELPER_MODE_READ )); +} +::rtl::OUString SAL_CALL SvXMLGraphicImportHelper_getImplementationName() + throw() +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Svx.GraphicImportHelper" )); +} +Sequence< ::rtl::OUString > SAL_CALL SvXMLGraphicImportHelper_getSupportedServiceNames() + throw() +{ + // XGraphicObjectResolver and XBinaryStreamResolver are not part of any service + Sequence< ::rtl::OUString > aSupportedServiceNames( 2 ); + aSupportedServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.GraphicObjectResolver" ) ); + aSupportedServiceNames[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.BinaryStreamResolver" ) ); + return aSupportedServiceNames; +} + +// export +Reference< XInterface > SAL_CALL SvXMLGraphicExportHelper_createInstance(const Reference< XMultiServiceFactory > & /* rSMgr */ ) + throw( Exception ) +{ + return static_cast< XWeak* >( new SvXMLGraphicImportExportHelper( GRAPHICHELPER_MODE_WRITE )); +} +::rtl::OUString SAL_CALL SvXMLGraphicExportHelper_getImplementationName() + throw() +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Svx.GraphicExportHelper" )); +} +Sequence< ::rtl::OUString > SAL_CALL SvXMLGraphicExportHelper_getSupportedServiceNames() + throw() +{ + // XGraphicObjectResolver and XBinaryStreamResolver are not part of any service + Sequence< ::rtl::OUString > aSupportedServiceNames( 2 ); + aSupportedServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.GraphicObjectResolver" ) ); + aSupportedServiceNames[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.BinaryStreamResolver" ) ); + return aSupportedServiceNames; +} + +} // namespace svx + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |