update dev300-m58
[ooovba.git] / svx / source / xml / xmlgrhlp.cxx
blob1ba98b3e7927506e1785c5fc68d69cf8d4acd4f5
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xmlgrhlp.cxx,v $
10 * $Revision: 1.34 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
33 #include <com/sun/star/embed/XTransactedObject.hpp>
34 #ifndef _COM_SUN_STAR_EMBED_ElementModes_HPP_
35 #include <com/sun/star/embed/ElementModes.hpp>
36 #endif
37 #include <com/sun/star/beans/XPropertySet.hpp>
38 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
39 #include <com/sun/star/lang/XServiceInfo.hpp>
40 #include <com/sun/star/lang/XInitialization.hpp>
41 #include <cppuhelper/compbase4.hxx>
43 #include <unotools/ucbstreamhelper.hxx>
44 #include <unotools/streamwrap.hxx>
45 #include <unotools/tempfile.hxx>
46 #include <tools/debug.hxx>
47 #include <vcl/cvtgrf.hxx>
48 #include <vcl/gfxlink.hxx>
49 #include <vcl/metaact.hxx>
50 #include <tools/zcodec.hxx>
52 #include "impgrf.hxx"
53 #include "xmlgrhlp.hxx"
55 #include <algorithm>
57 // -----------
58 // - Defines -
59 // -----------
61 using namespace com::sun::star;
62 using namespace com::sun::star::uno;
63 using namespace com::sun::star::io;
65 using ::com::sun::star::lang::XMultiServiceFactory;
67 #define XML_GRAPHICSTORAGE_NAME "Pictures"
68 #define XML_PACKAGE_URL_BASE "vnd.sun.star.Package:"
69 #define XML_GRAPHICOBJECT_URL_BASE "vnd.sun.star.GraphicObject:"
71 // ---------------------------
72 // - SvXMLGraphicInputStream -
73 // ---------------------------
75 const MetaCommentAction* ImplCheckForEPS( GDIMetaFile& rMtf )
77 static ByteString aComment( (const sal_Char*)"EPSReplacementGraphic" );
78 const MetaCommentAction* pComment = NULL;
80 if ( ( rMtf.GetActionCount() >= 2 )
81 && ( rMtf.FirstAction()->GetType() == META_EPS_ACTION )
82 && ( ((const MetaAction*)rMtf.GetAction( 1 ))->GetType() == META_COMMENT_ACTION )
83 && ( ((const MetaCommentAction*)rMtf.GetAction( 1 ))->GetComment() == aComment ) )
84 pComment = (const MetaCommentAction*)rMtf.GetAction( 1 );
86 return pComment;
89 class SvXMLGraphicInputStream : public::cppu::WeakImplHelper1< XInputStream >
91 private:
93 virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) throw(NotConnectedException, BufferSizeExceededException, RuntimeException);
94 virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) throw(NotConnectedException, BufferSizeExceededException, RuntimeException);
95 virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) throw(NotConnectedException, BufferSizeExceededException, RuntimeException);
96 virtual sal_Int32 SAL_CALL available() throw(NotConnectedException, RuntimeException);
97 virtual void SAL_CALL closeInput() throw(NotConnectedException, RuntimeException);
99 private:
101 ::utl::TempFile maTmp;
102 Reference< XInputStream > mxStmWrapper;
104 // not available
105 SvXMLGraphicInputStream();
106 SvXMLGraphicInputStream( const SvXMLGraphicInputStream& );
107 SvXMLGraphicInputStream& operator==( SvXMLGraphicInputStream& );
109 public:
111 SvXMLGraphicInputStream( const ::rtl::OUString& rGraphicId );
112 virtual ~SvXMLGraphicInputStream();
114 sal_Bool Exists() const { return mxStmWrapper.is(); }
117 // -----------------------------------------------------------------------------
119 SvXMLGraphicInputStream::SvXMLGraphicInputStream( const ::rtl::OUString& rGraphicId )
121 String aGraphicId( rGraphicId );
122 GraphicObject aGrfObject( ByteString( aGraphicId, RTL_TEXTENCODING_ASCII_US ) );
124 maTmp.EnableKillingFile();
126 if( aGrfObject.GetType() != GRAPHIC_NONE )
128 SvStream* pStm = ::utl::UcbStreamHelper::CreateStream( maTmp.GetURL(), STREAM_WRITE | STREAM_TRUNC );
130 if( pStm )
132 Graphic aGraphic( (Graphic&) aGrfObject.GetGraphic() );
133 const GfxLink aGfxLink( aGraphic.GetLink() );
134 sal_Bool bRet = sal_False;
136 if( aGfxLink.GetDataSize() && aGfxLink.GetData() )
138 pStm->Write( aGfxLink.GetData(), aGfxLink.GetDataSize() );
139 bRet = ( pStm->GetError() == 0 );
141 else
143 if( aGraphic.GetType() == GRAPHIC_BITMAP )
145 GraphicFilter* pFilter = GetGrfFilter();
146 String aFormat;
148 if( aGraphic.IsAnimated() )
149 aFormat = String( RTL_CONSTASCII_USTRINGPARAM( "gif" ) );
150 else
151 aFormat = String( RTL_CONSTASCII_USTRINGPARAM( "png" ) );
153 bRet = ( pFilter->ExportGraphic( aGraphic, String(), *pStm, pFilter->GetExportFormatNumberForShortName( aFormat ) ) == 0 );
155 else if( aGraphic.GetType() == GRAPHIC_GDIMETAFILE )
157 pStm->SetVersion( SOFFICE_FILEFORMAT_8 );
158 pStm->SetCompressMode( COMPRESSMODE_ZBITMAP );
159 ( (GDIMetaFile&) aGraphic.GetGDIMetaFile() ).Write( *pStm );
160 bRet = ( pStm->GetError() == 0 );
164 if( bRet )
166 pStm->Seek( 0 );
167 mxStmWrapper = new ::utl::OInputStreamWrapper( pStm, sal_True );
169 else
170 delete pStm;
175 // -----------------------------------------------------------------------------
177 SvXMLGraphicInputStream::~SvXMLGraphicInputStream()
181 // -----------------------------------------------------------------------------
183 sal_Int32 SAL_CALL SvXMLGraphicInputStream::readBytes( Sequence< sal_Int8 >& rData, sal_Int32 nBytesToRead )
184 throw( NotConnectedException, BufferSizeExceededException, RuntimeException )
186 if( !mxStmWrapper.is() )
187 throw NotConnectedException();
189 return mxStmWrapper->readBytes( rData, nBytesToRead );
192 // -----------------------------------------------------------------------------
194 sal_Int32 SAL_CALL SvXMLGraphicInputStream::readSomeBytes( Sequence< sal_Int8 >& rData, sal_Int32 nMaxBytesToRead )
195 throw( NotConnectedException, BufferSizeExceededException, RuntimeException )
197 if( !mxStmWrapper.is() )
198 throw NotConnectedException() ;
200 return mxStmWrapper->readSomeBytes( rData, nMaxBytesToRead );
203 // -----------------------------------------------------------------------------
205 void SAL_CALL SvXMLGraphicInputStream::skipBytes( sal_Int32 nBytesToSkip )
206 throw( NotConnectedException, BufferSizeExceededException, RuntimeException )
208 if( !mxStmWrapper.is() )
209 throw NotConnectedException() ;
211 mxStmWrapper->skipBytes( nBytesToSkip );
214 // -----------------------------------------------------------------------------
216 sal_Int32 SAL_CALL SvXMLGraphicInputStream::available() throw( NotConnectedException, RuntimeException )
218 if( !mxStmWrapper.is() )
219 throw NotConnectedException() ;
221 return mxStmWrapper->available();
224 // -----------------------------------------------------------------------------
226 void SAL_CALL SvXMLGraphicInputStream::closeInput() throw( NotConnectedException, RuntimeException )
228 if( !mxStmWrapper.is() )
229 throw NotConnectedException() ;
231 mxStmWrapper->closeInput();
234 // ----------------------------
235 // - SvXMLGraphicOutputStream -
236 // ----------------------------
238 class SvXMLGraphicOutputStream : public::cppu::WeakImplHelper1< XOutputStream >
240 private:
242 // XOutputStream
243 virtual void SAL_CALL writeBytes( const Sequence< sal_Int8 >& rData ) throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );
244 virtual void SAL_CALL flush() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );
245 virtual void SAL_CALL closeOutput() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );
247 private:
249 ::utl::TempFile* mpTmp;
250 SvStream* mpOStm;
251 Reference< XOutputStream > mxStmWrapper;
252 GraphicObject maGrfObj;
253 sal_Bool mbClosed;
255 // not available
256 SvXMLGraphicOutputStream( const SvXMLGraphicOutputStream& );
257 SvXMLGraphicOutputStream& operator==( SvXMLGraphicOutputStream& );
259 public:
261 SvXMLGraphicOutputStream();
262 virtual ~SvXMLGraphicOutputStream();
264 sal_Bool Exists() const { return mxStmWrapper.is(); }
265 const GraphicObject& GetGraphicObject();
268 // -----------------------------------------------------------------------------
270 SvXMLGraphicOutputStream::SvXMLGraphicOutputStream() :
271 mpTmp( new ::utl::TempFile ),
272 mbClosed( sal_False )
274 mpTmp->EnableKillingFile();
276 mpOStm = ::utl::UcbStreamHelper::CreateStream( mpTmp->GetURL(), STREAM_WRITE | STREAM_TRUNC );
278 if( mpOStm )
279 mxStmWrapper = new ::utl::OOutputStreamWrapper( *mpOStm );
282 // -----------------------------------------------------------------------------
284 SvXMLGraphicOutputStream::~SvXMLGraphicOutputStream()
286 delete mpTmp;
287 delete mpOStm;
290 // -----------------------------------------------------------------------------
292 void SAL_CALL SvXMLGraphicOutputStream::writeBytes( const Sequence< sal_Int8 >& rData )
293 throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
295 if( !mxStmWrapper.is() )
296 throw NotConnectedException() ;
298 mxStmWrapper->writeBytes( rData );
301 // -----------------------------------------------------------------------------
303 void SAL_CALL SvXMLGraphicOutputStream::flush()
304 throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
306 if( !mxStmWrapper.is() )
307 throw NotConnectedException() ;
309 mxStmWrapper->flush();
312 // -----------------------------------------------------------------------------
314 void SAL_CALL SvXMLGraphicOutputStream::closeOutput()
315 throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
317 if( !mxStmWrapper.is() )
318 throw NotConnectedException() ;
320 mxStmWrapper->closeOutput();
321 mxStmWrapper = Reference< XOutputStream >();
323 mbClosed = sal_True;
326 // ------------------------------------------------------------------------------
328 const GraphicObject& SvXMLGraphicOutputStream::GetGraphicObject()
330 if( mbClosed && ( maGrfObj.GetType() == GRAPHIC_NONE ) && mpOStm )
332 Graphic aGraphic;
334 mpOStm->Seek( 0 );
335 USHORT nFormat = GRFILTER_FORMAT_DONTKNOW;
336 USHORT pDeterminedFormat = GRFILTER_FORMAT_DONTKNOW;
337 GetGrfFilter()->ImportGraphic( aGraphic, String(), *mpOStm ,nFormat,&pDeterminedFormat );
339 if (pDeterminedFormat == GRFILTER_FORMAT_DONTKNOW)
341 //Read the first two byte to check whether it is a gzipped stream, is so it may be in wmz or emz format
342 //unzip them and try again
344 BYTE sFirstBytes[ 2 ];
346 mpOStm->Seek( STREAM_SEEK_TO_END );
347 ULONG nStreamLen = mpOStm->Tell();
348 mpOStm->Seek( 0 );
350 if ( !nStreamLen )
352 SvLockBytes* pLockBytes = mpOStm->GetLockBytes();
353 if ( pLockBytes )
354 pLockBytes->SetSynchronMode( TRUE );
356 mpOStm->Seek( STREAM_SEEK_TO_END );
357 nStreamLen = mpOStm->Tell();
358 mpOStm->Seek( 0 );
360 if( nStreamLen >= 2 )
362 //read two byte
363 mpOStm->Read( sFirstBytes, 2 );
365 if( sFirstBytes[0] == 0x1f && sFirstBytes[1] == 0x8b )
367 SvMemoryStream* pDest = new SvMemoryStream;
368 ZCodec aZCodec( 0x8000, 0x8000 );
369 aZCodec.BeginCompression(ZCODEC_GZ_LIB);
370 mpOStm->Seek( 0 );
371 aZCodec.Decompress( *mpOStm, *pDest );
373 if (aZCodec.EndCompression() && pDest )
375 pDest->Seek( STREAM_SEEK_TO_END );
376 ULONG nStreamLen_ = pDest->Tell();
377 if (nStreamLen_)
379 pDest->Seek(0L);
380 GetGrfFilter()->ImportGraphic( aGraphic, String(), *pDest ,nFormat,&pDeterminedFormat );
383 delete pDest;
388 maGrfObj = aGraphic;
389 if( maGrfObj.GetType() != GRAPHIC_NONE )
391 delete mpOStm, mpOStm = NULL;
392 delete mpTmp, mpTmp = NULL;
396 return maGrfObj;
399 // ----------------------
400 // - SvXMLGraphicHelper -
401 // ----------------------
403 SvXMLGraphicHelper::SvXMLGraphicHelper( SvXMLGraphicHelperMode eCreateMode ) :
404 ::cppu::WeakComponentImplHelper2< ::com::sun::star::document::XGraphicObjectResolver,
405 ::com::sun::star::document::XBinaryStreamResolver >( maMutex )
407 Init( NULL, eCreateMode, sal_False );
410 SvXMLGraphicHelper::SvXMLGraphicHelper() :
411 ::cppu::WeakComponentImplHelper2< ::com::sun::star::document::XGraphicObjectResolver,
412 ::com::sun::star::document::XBinaryStreamResolver >( maMutex )
416 // -----------------------------------------------------------------------------
418 SvXMLGraphicHelper::~SvXMLGraphicHelper()
422 // -----------------------------------------------------------------------------
424 void SAL_CALL SvXMLGraphicHelper::disposing()
428 // -----------------------------------------------------------------------------
430 sal_Bool SvXMLGraphicHelper::ImplGetStreamNames( const ::rtl::OUString& rURLStr,
431 ::rtl::OUString& rPictureStorageName,
432 ::rtl::OUString& rPictureStreamName )
434 String aURLStr( rURLStr );
435 sal_Bool bRet = sal_False;
437 if( aURLStr.Len() )
439 aURLStr = aURLStr.GetToken( aURLStr.GetTokenCount( ':' ) - 1, ':' );
440 const sal_uInt32 nTokenCount = aURLStr.GetTokenCount( '/' );
442 if( 1 == nTokenCount )
444 rPictureStorageName = String( RTL_CONSTASCII_USTRINGPARAM( XML_GRAPHICSTORAGE_NAME ) );
445 rPictureStreamName = aURLStr;
446 bRet = sal_True;
448 else if( 2 == nTokenCount )
450 rPictureStorageName = aURLStr.GetToken( 0, '/' );
452 DBG_ASSERT( rPictureStorageName.getLength() &&
453 rPictureStorageName.getStr()[ 0 ] != '#',
454 "invalid relative URL" );
456 rPictureStreamName = aURLStr.GetToken( 1, '/' );
457 bRet = sal_True;
459 else
461 DBG_ERROR( "SvXMLGraphicHelper::ImplInsertGraphicURL: invalid scheme" );
465 return bRet;
468 // -----------------------------------------------------------------------------
470 uno::Reference < embed::XStorage > SvXMLGraphicHelper::ImplGetGraphicStorage( const ::rtl::OUString& rStorageName )
472 uno::Reference < embed::XStorage > xRetStorage;
473 if( mxRootStorage.is() )
477 xRetStorage = mxRootStorage->openStorageElement(
478 maCurStorageName = rStorageName,
479 ( GRAPHICHELPER_MODE_WRITE == meCreateMode )
480 ? embed::ElementModes::READWRITE
481 : embed::ElementModes::READ );
483 catch ( uno::Exception& )
486 //#i43196# try again to open the storage element - this time readonly
487 if(!xRetStorage.is())
491 xRetStorage = mxRootStorage->openStorageElement( maCurStorageName = rStorageName, embed::ElementModes::READ );
493 catch ( uno::Exception& )
499 return xRetStorage;
502 // -----------------------------------------------------------------------------
504 SvxGraphicHelperStream_Impl SvXMLGraphicHelper::ImplGetGraphicStream( const ::rtl::OUString& rPictureStorageName,
505 const ::rtl::OUString& rPictureStreamName,
506 BOOL bTruncate )
508 SvxGraphicHelperStream_Impl aRet;
509 aRet.xStorage = ImplGetGraphicStorage( rPictureStorageName );
511 if( aRet.xStorage.is() )
513 sal_Int32 nMode = embed::ElementModes::READ;
514 if ( GRAPHICHELPER_MODE_WRITE == meCreateMode )
516 nMode = embed::ElementModes::READWRITE;
517 if ( bTruncate )
518 nMode |= embed::ElementModes::TRUNCATE;
521 aRet.xStream = aRet.xStorage->openStreamElement( rPictureStreamName, nMode );
522 if( aRet.xStream.is() && ( GRAPHICHELPER_MODE_WRITE == meCreateMode ) )
524 //REMOVE ::rtl::OUString aPropName( RTL_CONSTASCII_USTRINGPARAM("Encrypted") );
525 ::rtl::OUString aPropName( RTL_CONSTASCII_USTRINGPARAM("UseCommonStoragePasswordEncryption") );
526 uno::Reference < beans::XPropertySet > xProps( aRet.xStream, uno::UNO_QUERY );
527 xProps->setPropertyValue( aPropName, uno::makeAny( sal_True) );
531 return aRet;
534 // -----------------------------------------------------------------------------
536 String SvXMLGraphicHelper::ImplGetGraphicMimeType( const String& rFileName ) const
538 struct XMLGraphicMimeTypeMapper
540 const char* pExt;
541 const char* pMimeType;
544 static XMLGraphicMimeTypeMapper aMapper[] =
546 { "gif", "image/gif" },
547 { "png", "image/png" },
548 { "jpg", "image/jpeg" },
549 { "tif", "image/tiff" }
552 String aMimeType;
554 if( ( rFileName.Len() >= 4 ) && ( rFileName.GetChar( rFileName.Len() - 4 ) == '.' ) )
556 const ByteString aExt( rFileName.Copy( rFileName.Len() - 3 ), RTL_TEXTENCODING_ASCII_US );
558 for( long i = 0, nCount = sizeof( aMapper ) / sizeof( aMapper[ 0 ] ); ( i < nCount ) && !aMimeType.Len(); i++ )
559 if( aExt == aMapper[ i ].pExt )
560 aMimeType = String( aMapper[ i ].pMimeType, RTL_TEXTENCODING_ASCII_US );
563 return aMimeType;
566 // -----------------------------------------------------------------------------
568 Graphic SvXMLGraphicHelper::ImplReadGraphic( const ::rtl::OUString& rPictureStorageName,
569 const ::rtl::OUString& rPictureStreamName )
571 Graphic aGraphic;
572 SvxGraphicHelperStream_Impl aStream( ImplGetGraphicStream( rPictureStorageName, rPictureStreamName, FALSE ) );
573 if( aStream.xStream.is() )
575 SvStream* pStream = utl::UcbStreamHelper::CreateStream( aStream.xStream );
576 GetGrfFilter()->ImportGraphic( aGraphic, String(), *pStream );
577 delete pStream;
580 return aGraphic;
583 // -----------------------------------------------------------------------------
585 sal_Bool SvXMLGraphicHelper::ImplWriteGraphic( const ::rtl::OUString& rPictureStorageName,
586 const ::rtl::OUString& rPictureStreamName,
587 const ::rtl::OUString& rGraphicId )
589 String aGraphicId( rGraphicId );
590 GraphicObject aGrfObject( ByteString( aGraphicId, RTL_TEXTENCODING_ASCII_US ) );
591 sal_Bool bRet = sal_False;
593 if( aGrfObject.GetType() != GRAPHIC_NONE )
595 SvxGraphicHelperStream_Impl aStream( ImplGetGraphicStream( rPictureStorageName, rPictureStreamName, FALSE ) );
596 if( aStream.xStream.is() )
598 Graphic aGraphic( (Graphic&) aGrfObject.GetGraphic() );
599 const GfxLink aGfxLink( aGraphic.GetLink() );
600 const ::rtl::OUString aMimeType( ImplGetGraphicMimeType( rPictureStreamName ) );
601 uno::Any aAny;
602 uno::Reference < beans::XPropertySet > xProps( aStream.xStream, uno::UNO_QUERY );
604 // set stream properties (MediaType/Compression)
605 if( aMimeType.getLength() )
607 aAny <<= aMimeType;
608 xProps->setPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), aAny );
611 const sal_Bool bCompressed = ( ( 0 == aMimeType.getLength() ) || ( aMimeType == ::rtl::OUString::createFromAscii( "image/tiff" ) ) );
612 aAny <<= bCompressed;
613 xProps->setPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) ), aAny );
615 SvStream* pStream = utl::UcbStreamHelper::CreateStream( aStream.xStream );
616 if( aGfxLink.GetDataSize() && aGfxLink.GetData() )
617 pStream->Write( aGfxLink.GetData(), aGfxLink.GetDataSize() );
618 else
620 if( aGraphic.GetType() == GRAPHIC_BITMAP )
622 GraphicFilter* pFilter = GetGrfFilter();
623 String aFormat;
625 if( aGraphic.IsAnimated() )
626 aFormat = String( RTL_CONSTASCII_USTRINGPARAM( "gif" ) );
627 else
628 aFormat = String( RTL_CONSTASCII_USTRINGPARAM( "png" ) );
630 bRet = ( pFilter->ExportGraphic( aGraphic, String(), *pStream,
631 pFilter->GetExportFormatNumberForShortName( aFormat ) ) == 0 );
633 else if( aGraphic.GetType() == GRAPHIC_GDIMETAFILE )
635 pStream->SetVersion( SOFFICE_FILEFORMAT_8 );
636 pStream->SetCompressMode( COMPRESSMODE_ZBITMAP );
638 // SJ: first check if this metafile is just a eps file, then we will store the eps instead of svm
639 GDIMetaFile& rMtf( (GDIMetaFile&)aGraphic.GetGDIMetaFile() );
640 const MetaCommentAction* pComment = ImplCheckForEPS( rMtf );
641 if ( pComment )
643 sal_uInt32 nSize = pComment->GetDataSize();
644 const BYTE* pData = pComment->GetData();
645 if ( nSize && pData )
646 pStream->Write( pData, nSize );
648 const MetaEPSAction* pAct = ( (const MetaEPSAction*)rMtf.FirstAction() );
649 const GfxLink& rLink = pAct->GetLink();
651 pStream->Write( rLink.GetData(), rLink.GetDataSize() );
653 else
654 rMtf.Write( *pStream );
656 bRet = ( pStream->GetError() == 0 );
659 uno::Reference < embed::XTransactedObject > xStorage(
660 aStream.xStorage, uno::UNO_QUERY);
661 delete pStream;
662 aStream.xStream->getOutputStream()->closeOutput();
663 if( xStorage.is() )
664 xStorage->commit();
668 return bRet;
671 // -----------------------------------------------------------------------------
673 void SvXMLGraphicHelper::ImplInsertGraphicURL( const ::rtl::OUString& rURLStr, sal_uInt32 nInsertPos, rtl::OUString& rRequestedFileName )
675 rtl::OUString aURLString( rURLStr );
676 ::rtl::OUString aPictureStorageName, aPictureStreamName;
677 if( ( maURLSet.find( aURLString ) != maURLSet.end() ) )
679 URLPairVector::iterator aIter( maGrfURLs.begin() ), aEnd( maGrfURLs.end() );
680 while( aIter != aEnd )
682 if( aURLString == (*aIter).first )
684 maGrfURLs[ nInsertPos ].second = (*aIter).second;
685 aIter = aEnd;
687 else
688 aIter++;
691 else if( ImplGetStreamNames( aURLString, aPictureStorageName, aPictureStreamName ) )
693 URLPair& rURLPair = maGrfURLs[ nInsertPos ];
695 if( GRAPHICHELPER_MODE_READ == meCreateMode )
697 const GraphicObject aObj( ImplReadGraphic( aPictureStorageName, aPictureStreamName ) );
699 if( aObj.GetType() != GRAPHIC_NONE )
701 const static ::rtl::OUString aBaseURL( RTL_CONSTASCII_USTRINGPARAM( XML_GRAPHICOBJECT_URL_BASE ) );
703 maGrfObjs.push_back( aObj );
704 rURLPair.second = aBaseURL;
705 rURLPair.second += String( aObj.GetUniqueID().GetBuffer(), RTL_TEXTENCODING_ASCII_US );
707 else
708 rURLPair.second = String();
710 else
712 const String aGraphicObjectId( aPictureStreamName );
713 const GraphicObject aGrfObject( ByteString( aGraphicObjectId, RTL_TEXTENCODING_ASCII_US ) );
715 if( aGrfObject.GetType() != GRAPHIC_NONE )
717 String aStreamName( aGraphicObjectId );
718 Graphic aGraphic( (Graphic&) aGrfObject.GetGraphic() );
719 const GfxLink aGfxLink( aGraphic.GetLink() );
720 String aExtension;
722 if( aGfxLink.GetDataSize() )
724 switch( aGfxLink.GetType() )
726 case( GFX_LINK_TYPE_EPS_BUFFER ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".eps" ) ); break;
727 case( GFX_LINK_TYPE_NATIVE_GIF ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".gif" ) ); break;
728 case( GFX_LINK_TYPE_NATIVE_JPG ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".jpg" ) ); break;
729 case( GFX_LINK_TYPE_NATIVE_PNG ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".png" ) ); break;
730 case( GFX_LINK_TYPE_NATIVE_TIF ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".tif" ) ); break;
731 case( GFX_LINK_TYPE_NATIVE_WMF ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".wmf" ) ); break;
732 case( GFX_LINK_TYPE_NATIVE_MET ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".met" ) ); break;
733 case( GFX_LINK_TYPE_NATIVE_PCT ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".pct" ) ); break;
735 default:
736 aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".grf" ) );
737 break;
740 else
742 if( aGrfObject.GetType() == GRAPHIC_BITMAP )
744 if( aGrfObject.IsAnimated() )
745 aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".gif" ) );
746 else
747 aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".png" ) );
749 else if( aGrfObject.GetType() == GRAPHIC_GDIMETAFILE )
751 // SJ: first check if this metafile is just a eps file, then we will store the eps instead of svm
752 GDIMetaFile& rMtf( (GDIMetaFile&)aGraphic.GetGDIMetaFile() );
753 if ( ImplCheckForEPS( rMtf ) )
754 aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".eps" ) );
755 else
756 aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".svm" ) );
760 rtl::OUString aURLEntry;
761 const String sPictures( RTL_CONSTASCII_USTRINGPARAM( "Pictures/" ) );
763 if ( rRequestedFileName.getLength() )
765 aURLEntry = sPictures;
766 aURLEntry += rRequestedFileName;
767 aURLEntry += aExtension;
769 URLPairVector::iterator aIter( maGrfURLs.begin() ), aEnd( maGrfURLs.end() );
770 while( aIter != aEnd )
772 if( aURLEntry == (*aIter).second )
773 break;
774 aIter++;
776 if ( aIter == aEnd )
777 aStreamName = rRequestedFileName;
780 aStreamName += aExtension;
782 if( mbDirect && aStreamName.Len() )
783 ImplWriteGraphic( aPictureStorageName, aStreamName, aGraphicObjectId );
785 rURLPair.second = sPictures;
786 rURLPair.second += aStreamName;
790 maURLSet.insert( aURLString );
794 // -----------------------------------------------------------------------------
796 void SvXMLGraphicHelper::Init( const uno::Reference < embed::XStorage >& rXMLStorage,
797 SvXMLGraphicHelperMode eCreateMode,
798 BOOL bDirect )
800 mxRootStorage = rXMLStorage;
801 meCreateMode = eCreateMode;
802 mbDirect = ( ( GRAPHICHELPER_MODE_READ == meCreateMode ) ? bDirect : sal_True );
805 // -----------------------------------------------------------------------------
807 SvXMLGraphicHelper* SvXMLGraphicHelper::Create( const uno::Reference < embed::XStorage >& rXMLStorage,
808 SvXMLGraphicHelperMode eCreateMode,
809 BOOL bDirect )
811 SvXMLGraphicHelper* pThis = new SvXMLGraphicHelper;
813 pThis->acquire();
814 pThis->Init( rXMLStorage, eCreateMode, bDirect );
816 return pThis;
819 // -----------------------------------------------------------------------------
821 SvXMLGraphicHelper* SvXMLGraphicHelper::Create( SvXMLGraphicHelperMode eCreateMode )
823 SvXMLGraphicHelper* pThis = new SvXMLGraphicHelper;
825 pThis->acquire();
826 pThis->Init( NULL, eCreateMode, sal_False );
828 return pThis;
831 // -----------------------------------------------------------------------------
833 void SvXMLGraphicHelper::Destroy( SvXMLGraphicHelper* pSvXMLGraphicHelper )
835 if( pSvXMLGraphicHelper )
837 pSvXMLGraphicHelper->dispose();
838 pSvXMLGraphicHelper->release();
842 // -----------------------------------------------------------------------------
844 // XGraphicObjectResolver
845 ::rtl::OUString SAL_CALL SvXMLGraphicHelper::resolveGraphicObjectURL( const ::rtl::OUString& rURL )
846 throw(uno::RuntimeException)
848 ::osl::MutexGuard aGuard( maMutex );
849 const sal_Int32 nIndex = maGrfURLs.size();
851 rtl::OUString aURL( rURL );
852 rtl::OUString aUserData;
853 rtl::OUString aRequestedFileName;
855 sal_Int32 nUser = rURL.indexOf( '?', 0 );
856 if ( nUser >= 0 )
858 aURL = rtl::OUString( rURL.copy( 0, nUser ) );
859 nUser++;
860 aUserData = rURL.copy( nUser, rURL.getLength() - nUser );
862 if ( aUserData.getLength() )
864 sal_Int32 nIndex2 = 0;
867 rtl::OUString aToken = aUserData.getToken( 0, ';', nIndex2 );
868 sal_Int32 n = aToken.indexOf( '=' );
869 if ( ( n > 0 ) && ( ( n + 1 ) < aToken.getLength() ) )
871 rtl::OUString aParam( aToken.copy( 0, n ) );
872 rtl::OUString aValue( aToken.copy( n + 1, aToken.getLength() - ( n + 1 ) ) );
874 const rtl::OUString sRequestedName( RTL_CONSTASCII_USTRINGPARAM("requestedName") );
875 if ( aParam.match( sRequestedName ) )
876 aRequestedFileName = aValue;
879 while ( nIndex2 >= 0 );
882 maGrfURLs.push_back( ::std::make_pair( aURL, ::rtl::OUString() ) );
883 ImplInsertGraphicURL( aURL, nIndex, aRequestedFileName );
885 return maGrfURLs[ nIndex ].second;
888 // -----------------------------------------------------------------------------
890 // XBinaryStreamResolver
891 Reference< XInputStream > SAL_CALL SvXMLGraphicHelper::getInputStream( const ::rtl::OUString& rURL )
892 throw( RuntimeException )
894 Reference< XInputStream > xRet;
895 ::rtl::OUString aPictureStorageName, aGraphicId;
898 if( ( GRAPHICHELPER_MODE_WRITE == meCreateMode ) &&
899 ImplGetStreamNames( rURL, aPictureStorageName, aGraphicId ) )
901 SvXMLGraphicInputStream* pInputStream = new SvXMLGraphicInputStream( aGraphicId );
903 if( pInputStream->Exists() )
904 xRet = pInputStream;
905 else
906 delete pInputStream;
909 return xRet;
912 // -----------------------------------------------------------------------------
914 Reference< XOutputStream > SAL_CALL SvXMLGraphicHelper::createOutputStream()
915 throw( RuntimeException )
917 Reference< XOutputStream > xRet;
919 if( GRAPHICHELPER_MODE_READ == meCreateMode )
921 SvXMLGraphicOutputStream* pOutputStream = new SvXMLGraphicOutputStream;
923 if( pOutputStream->Exists() )
924 maGrfStms.push_back( xRet = pOutputStream );
925 else
926 delete pOutputStream;
929 return xRet;
932 // -----------------------------------------------------------------------------
934 ::rtl::OUString SAL_CALL SvXMLGraphicHelper::resolveOutputStream( const Reference< XOutputStream >& rxBinaryStream )
935 throw( RuntimeException )
937 ::rtl::OUString aRet;
939 if( ( GRAPHICHELPER_MODE_READ == meCreateMode ) && rxBinaryStream.is() )
941 if( ::std::find( maGrfStms.begin(), maGrfStms.end(), rxBinaryStream ) != maGrfStms.end() )
943 SvXMLGraphicOutputStream* pOStm = static_cast< SvXMLGraphicOutputStream* >( rxBinaryStream.get() );
945 if( pOStm )
947 const GraphicObject& rGrfObj = pOStm->GetGraphicObject();
948 const ::rtl::OUString aId( ::rtl::OUString::createFromAscii( rGrfObj.GetUniqueID().GetBuffer() ) );
950 if( aId.getLength() )
952 aRet = ::rtl::OUString::createFromAscii( XML_GRAPHICOBJECT_URL_BASE );
953 aRet += aId;
959 return aRet;
963 // --------------------------------------------------------------------------------
965 // for instantiation via service manager
966 namespace svx
969 namespace impl
971 typedef ::cppu::WeakComponentImplHelper4<
972 lang::XInitialization,
973 document::XGraphicObjectResolver,
974 document::XBinaryStreamResolver,
975 lang::XServiceInfo >
976 SvXMLGraphicImportExportHelper_Base;
977 class MutexContainer
979 public:
980 virtual ~MutexContainer();
982 protected:
983 mutable ::osl::Mutex m_aMutex;
985 MutexContainer::~MutexContainer()
987 } // namespace impl
989 class SvXMLGraphicImportExportHelper :
990 public impl::MutexContainer,
991 public impl::SvXMLGraphicImportExportHelper_Base
993 public:
994 SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode );
996 protected:
997 // is called from WeakComponentImplHelper when XComponent::dispose() was
998 // called from outside
999 virtual void SAL_CALL disposing();
1001 // ____ XInitialization ____
1002 // one argument is allowed, which is the XStorage
1003 virtual void SAL_CALL initialize( const Sequence< Any >& aArguments )
1004 throw (Exception,
1005 RuntimeException);
1007 // ____ XGraphicObjectResolver ____
1008 virtual ::rtl::OUString SAL_CALL resolveGraphicObjectURL( const ::rtl::OUString& aURL )
1009 throw (RuntimeException);
1011 // ____ XBinaryStreamResolver ____
1012 virtual Reference< io::XInputStream > SAL_CALL getInputStream( const ::rtl::OUString& aURL )
1013 throw (RuntimeException);
1014 virtual Reference< io::XOutputStream > SAL_CALL createOutputStream()
1015 throw (RuntimeException);
1016 virtual ::rtl::OUString SAL_CALL resolveOutputStream( const Reference< io::XOutputStream >& aBinaryStream )
1017 throw (RuntimeException);
1019 // ____ XServiceInfo ____
1020 virtual ::rtl::OUString SAL_CALL getImplementationName()
1021 throw (RuntimeException);
1022 virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName )
1023 throw (RuntimeException);
1024 virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames()
1025 throw (RuntimeException);
1027 private:
1028 SvXMLGraphicHelperMode m_eGraphicHelperMode;
1029 Reference< XGraphicObjectResolver > m_xGraphicObjectResolver;
1030 Reference< XBinaryStreamResolver > m_xBinaryStreamResolver;
1033 SvXMLGraphicImportExportHelper::SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode ) :
1034 impl::SvXMLGraphicImportExportHelper_Base( m_aMutex ),
1035 m_eGraphicHelperMode( eMode )
1038 void SAL_CALL SvXMLGraphicImportExportHelper::disposing()
1040 Reference< XComponent > xComp( m_xGraphicObjectResolver, UNO_QUERY );
1041 OSL_ASSERT( xComp.is());
1042 if( xComp.is())
1043 xComp->dispose();
1044 // m_xBinaryStreamResolver is a reference to the same object => don't call
1045 // dispose() again
1048 // ____ XInitialization ____
1049 void SAL_CALL SvXMLGraphicImportExportHelper::initialize(
1050 const Sequence< Any >& aArguments )
1051 throw (Exception, RuntimeException)
1053 Reference< embed::XStorage > xStorage;
1054 if( aArguments.getLength() > 0 )
1055 aArguments[0] >>= xStorage;
1057 SvXMLGraphicHelper * pHelper( SvXMLGraphicHelper::Create( xStorage, m_eGraphicHelperMode ));
1058 m_xGraphicObjectResolver.set( pHelper );
1059 m_xBinaryStreamResolver.set( pHelper );
1060 // SvXMLGraphicHelper::Create calls acquire. Since we have two references
1061 // now it is safe (and necessary) to undo this acquire
1062 pHelper->release();
1065 // ____ XGraphicObjectResolver ____
1066 ::rtl::OUString SAL_CALL SvXMLGraphicImportExportHelper::resolveGraphicObjectURL( const ::rtl::OUString& aURL )
1067 throw (uno::RuntimeException)
1069 return m_xGraphicObjectResolver->resolveGraphicObjectURL( aURL );
1073 // ____ XBinaryStreamResolver ____
1074 Reference< io::XInputStream > SAL_CALL SvXMLGraphicImportExportHelper::getInputStream( const ::rtl::OUString& aURL )
1075 throw (uno::RuntimeException)
1077 return m_xBinaryStreamResolver->getInputStream( aURL );
1079 Reference< io::XOutputStream > SAL_CALL SvXMLGraphicImportExportHelper::createOutputStream()
1080 throw (uno::RuntimeException)
1082 return m_xBinaryStreamResolver->createOutputStream();
1084 ::rtl::OUString SAL_CALL SvXMLGraphicImportExportHelper::resolveOutputStream( const Reference< io::XOutputStream >& aBinaryStream )
1085 throw (uno::RuntimeException)
1087 return m_xBinaryStreamResolver->resolveOutputStream( aBinaryStream );
1090 // ____ XServiceInfo ____
1091 ::rtl::OUString SAL_CALL SvXMLGraphicImportExportHelper::getImplementationName()
1092 throw (uno::RuntimeException)
1094 if( m_eGraphicHelperMode == GRAPHICHELPER_MODE_READ )
1095 return SvXMLGraphicImportHelper_getImplementationName();
1096 return SvXMLGraphicExportHelper_getImplementationName();
1098 ::sal_Bool SAL_CALL SvXMLGraphicImportExportHelper::supportsService( const ::rtl::OUString& ServiceName )
1099 throw (uno::RuntimeException)
1101 Sequence< ::rtl::OUString > aServiceNames( getSupportedServiceNames());
1102 const ::rtl::OUString * pBegin = aServiceNames.getConstArray();
1103 const ::rtl::OUString * pEnd = pBegin + aServiceNames.getLength();
1104 return (::std::find( pBegin, pEnd, ServiceName ) != pEnd);
1106 Sequence< ::rtl::OUString > SAL_CALL SvXMLGraphicImportExportHelper::getSupportedServiceNames()
1107 throw (uno::RuntimeException)
1109 if( m_eGraphicHelperMode == GRAPHICHELPER_MODE_READ )
1110 return SvXMLGraphicImportHelper_getSupportedServiceNames();
1111 return SvXMLGraphicExportHelper_getSupportedServiceNames();
1114 // import
1115 Reference< XInterface > SAL_CALL SvXMLGraphicImportHelper_createInstance(const Reference< XMultiServiceFactory > & /* rSMgr */ )
1116 throw( Exception )
1118 return static_cast< XWeak* >( new SvXMLGraphicImportExportHelper( GRAPHICHELPER_MODE_READ ));
1120 ::rtl::OUString SAL_CALL SvXMLGraphicImportHelper_getImplementationName()
1121 throw()
1123 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Svx.GraphicImportHelper" ));
1125 Sequence< ::rtl::OUString > SAL_CALL SvXMLGraphicImportHelper_getSupportedServiceNames()
1126 throw()
1128 // XGraphicObjectResolver and XBinaryStreamResolver are not part of any service
1129 Sequence< ::rtl::OUString > aSupportedServiceNames( 2 );
1130 aSupportedServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.GraphicObjectResolver" ) );
1131 aSupportedServiceNames[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.BinaryStreamResolver" ) );
1132 return aSupportedServiceNames;
1135 // export
1136 Reference< XInterface > SAL_CALL SvXMLGraphicExportHelper_createInstance(const Reference< XMultiServiceFactory > & /* rSMgr */ )
1137 throw( Exception )
1139 return static_cast< XWeak* >( new SvXMLGraphicImportExportHelper( GRAPHICHELPER_MODE_WRITE ));
1141 ::rtl::OUString SAL_CALL SvXMLGraphicExportHelper_getImplementationName()
1142 throw()
1144 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Svx.GraphicExportHelper" ));
1146 Sequence< ::rtl::OUString > SAL_CALL SvXMLGraphicExportHelper_getSupportedServiceNames()
1147 throw()
1149 // XGraphicObjectResolver and XBinaryStreamResolver are not part of any service
1150 Sequence< ::rtl::OUString > aSupportedServiceNames( 2 );
1151 aSupportedServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.GraphicObjectResolver" ) );
1152 aSupportedServiceNames[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.BinaryStreamResolver" ) );
1153 return aSupportedServiceNames;
1156 } // namespace svx