Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / svx / source / xml / xmlgrhlp.cxx
blobbd4954a6d348e2af0b4c9c6d021ca9cfd1c7581d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <comphelper/string.hxx>
30 #include <sal/macros.h>
31 #include <rtl/oustringostreaminserter.hxx>
32 #include <rtl/strbuf.hxx>
33 #include <com/sun/star/embed/XTransactedObject.hpp>
34 #include <com/sun/star/embed/ElementModes.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
37 #include <com/sun/star/lang/XServiceInfo.hpp>
38 #include <com/sun/star/lang/XInitialization.hpp>
39 #include <cppuhelper/compbase4.hxx>
41 #include <unotools/ucbstreamhelper.hxx>
42 #include <unotools/streamwrap.hxx>
43 #include <unotools/tempfile.hxx>
44 #include <unotools/saveopt.hxx>
45 #include <tools/debug.hxx>
46 #include <vcl/cvtgrf.hxx>
47 #include <vcl/gfxlink.hxx>
48 #include <vcl/metaact.hxx>
49 #include <tools/zcodec.hxx>
51 #include "svtools/filter.hxx"
52 #include "svx/xmlgrhlp.hxx"
53 #include "svx/xmleohlp.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_GRAPHICOBJECT_URL_BASE "vnd.sun.star.GraphicObject:"
70 // ---------------------------
71 // - SvXMLGraphicInputStream -
72 // ---------------------------
74 const MetaCommentAction* ImplCheckForEPS( GDIMetaFile& rMtf )
76 const MetaCommentAction* pComment = NULL;
78 if ( ( rMtf.GetActionSize() >= 2 )
79 && ( rMtf.FirstAction()->GetType() == META_EPS_ACTION )
80 && ( ((const MetaAction*)rMtf.GetAction( 1 ))->GetType() == META_COMMENT_ACTION )
81 && ( ((const MetaCommentAction*)rMtf.GetAction( 1 ))->GetComment().equalsL(RTL_CONSTASCII_STRINGPARAM("EPSReplacementGraphic")) ) )
82 pComment = (const MetaCommentAction*)rMtf.GetAction( 1 );
84 return pComment;
87 class SvXMLGraphicInputStream : public::cppu::WeakImplHelper1< XInputStream >
89 private:
91 virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) throw(NotConnectedException, BufferSizeExceededException, RuntimeException);
92 virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) throw(NotConnectedException, BufferSizeExceededException, RuntimeException);
93 virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) throw(NotConnectedException, BufferSizeExceededException, RuntimeException);
94 virtual sal_Int32 SAL_CALL available() throw(NotConnectedException, RuntimeException);
95 virtual void SAL_CALL closeInput() throw(NotConnectedException, RuntimeException);
97 private:
99 ::utl::TempFile maTmp;
100 Reference< XInputStream > mxStmWrapper;
102 // not available
103 SvXMLGraphicInputStream();
104 SvXMLGraphicInputStream( const SvXMLGraphicInputStream& );
105 SvXMLGraphicInputStream& operator==( SvXMLGraphicInputStream& );
107 public:
109 SvXMLGraphicInputStream( const ::rtl::OUString& rGraphicId );
110 virtual ~SvXMLGraphicInputStream();
112 sal_Bool Exists() const { return mxStmWrapper.is(); }
115 // -----------------------------------------------------------------------------
117 SvXMLGraphicInputStream::SvXMLGraphicInputStream( const ::rtl::OUString& rGraphicId )
119 GraphicObject aGrfObject( rtl::OUStringToOString(rGraphicId, RTL_TEXTENCODING_ASCII_US) );
121 maTmp.EnableKillingFile();
123 if( aGrfObject.GetType() != GRAPHIC_NONE )
125 SvStream* pStm = ::utl::UcbStreamHelper::CreateStream( maTmp.GetURL(), STREAM_WRITE | STREAM_TRUNC );
127 if( pStm )
129 Graphic aGraphic( (Graphic&) aGrfObject.GetGraphic() );
130 const GfxLink aGfxLink( aGraphic.GetLink() );
131 sal_Bool bRet = sal_False;
133 if( aGfxLink.GetDataSize() && aGfxLink.GetData() )
135 pStm->Write( aGfxLink.GetData(), aGfxLink.GetDataSize() );
136 bRet = ( pStm->GetError() == 0 );
138 else
140 if( aGraphic.GetType() == GRAPHIC_BITMAP )
142 GraphicFilter &rFilter = GraphicFilter::GetGraphicFilter();
143 String aFormat;
145 if( aGraphic.IsAnimated() )
146 aFormat = String( "gif" );
147 else
148 aFormat = String( "png" );
150 bRet = ( rFilter.ExportGraphic( aGraphic, String(), *pStm, rFilter.GetExportFormatNumberForShortName( aFormat ) ) == 0 );
152 else if( aGraphic.GetType() == GRAPHIC_GDIMETAFILE )
154 pStm->SetVersion( SOFFICE_FILEFORMAT_8 );
155 pStm->SetCompressMode( COMPRESSMODE_ZBITMAP );
156 ( (GDIMetaFile&) aGraphic.GetGDIMetaFile() ).Write( *pStm, GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC );
157 bRet = ( pStm->GetError() == 0 );
161 if( bRet )
163 pStm->Seek( 0 );
164 mxStmWrapper = new ::utl::OInputStreamWrapper( pStm, sal_True );
166 else
167 delete pStm;
172 // -----------------------------------------------------------------------------
174 SvXMLGraphicInputStream::~SvXMLGraphicInputStream()
178 // -----------------------------------------------------------------------------
180 sal_Int32 SAL_CALL SvXMLGraphicInputStream::readBytes( Sequence< sal_Int8 >& rData, sal_Int32 nBytesToRead )
181 throw( NotConnectedException, BufferSizeExceededException, RuntimeException )
183 if( !mxStmWrapper.is() )
184 throw NotConnectedException();
186 return mxStmWrapper->readBytes( rData, nBytesToRead );
189 // -----------------------------------------------------------------------------
191 sal_Int32 SAL_CALL SvXMLGraphicInputStream::readSomeBytes( Sequence< sal_Int8 >& rData, sal_Int32 nMaxBytesToRead )
192 throw( NotConnectedException, BufferSizeExceededException, RuntimeException )
194 if( !mxStmWrapper.is() )
195 throw NotConnectedException() ;
197 return mxStmWrapper->readSomeBytes( rData, nMaxBytesToRead );
200 // -----------------------------------------------------------------------------
202 void SAL_CALL SvXMLGraphicInputStream::skipBytes( sal_Int32 nBytesToSkip )
203 throw( NotConnectedException, BufferSizeExceededException, RuntimeException )
205 if( !mxStmWrapper.is() )
206 throw NotConnectedException() ;
208 mxStmWrapper->skipBytes( nBytesToSkip );
211 // -----------------------------------------------------------------------------
213 sal_Int32 SAL_CALL SvXMLGraphicInputStream::available() throw( NotConnectedException, RuntimeException )
215 if( !mxStmWrapper.is() )
216 throw NotConnectedException() ;
218 return mxStmWrapper->available();
221 // -----------------------------------------------------------------------------
223 void SAL_CALL SvXMLGraphicInputStream::closeInput() throw( NotConnectedException, RuntimeException )
225 if( !mxStmWrapper.is() )
226 throw NotConnectedException() ;
228 mxStmWrapper->closeInput();
231 // ----------------------------
232 // - SvXMLGraphicOutputStream -
233 // ----------------------------
235 class SvXMLGraphicOutputStream : public::cppu::WeakImplHelper1< XOutputStream >
237 private:
239 // XOutputStream
240 virtual void SAL_CALL writeBytes( const Sequence< sal_Int8 >& rData ) throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );
241 virtual void SAL_CALL flush() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );
242 virtual void SAL_CALL closeOutput() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );
244 private:
246 ::utl::TempFile* mpTmp;
247 SvStream* mpOStm;
248 Reference< XOutputStream > mxStmWrapper;
249 GraphicObject maGrfObj;
250 sal_Bool mbClosed;
252 // not available
253 SvXMLGraphicOutputStream( const SvXMLGraphicOutputStream& );
254 SvXMLGraphicOutputStream& operator==( SvXMLGraphicOutputStream& );
256 public:
258 SvXMLGraphicOutputStream();
259 virtual ~SvXMLGraphicOutputStream();
261 sal_Bool Exists() const { return mxStmWrapper.is(); }
262 const GraphicObject& GetGraphicObject();
265 // -----------------------------------------------------------------------------
267 SvXMLGraphicOutputStream::SvXMLGraphicOutputStream() :
268 mpTmp( new ::utl::TempFile ),
269 mbClosed( sal_False )
271 mpTmp->EnableKillingFile();
273 mpOStm = ::utl::UcbStreamHelper::CreateStream( mpTmp->GetURL(), STREAM_WRITE | STREAM_TRUNC );
275 if( mpOStm )
276 mxStmWrapper = new ::utl::OOutputStreamWrapper( *mpOStm );
279 // -----------------------------------------------------------------------------
281 SvXMLGraphicOutputStream::~SvXMLGraphicOutputStream()
283 delete mpTmp;
284 delete mpOStm;
287 // -----------------------------------------------------------------------------
289 void SAL_CALL SvXMLGraphicOutputStream::writeBytes( const Sequence< sal_Int8 >& rData )
290 throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
292 if( !mxStmWrapper.is() )
293 throw NotConnectedException() ;
295 mxStmWrapper->writeBytes( rData );
298 // -----------------------------------------------------------------------------
300 void SAL_CALL SvXMLGraphicOutputStream::flush()
301 throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
303 if( !mxStmWrapper.is() )
304 throw NotConnectedException() ;
306 mxStmWrapper->flush();
309 // -----------------------------------------------------------------------------
311 void SAL_CALL SvXMLGraphicOutputStream::closeOutput()
312 throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
314 if( !mxStmWrapper.is() )
315 throw NotConnectedException() ;
317 mxStmWrapper->closeOutput();
318 mxStmWrapper = Reference< XOutputStream >();
320 mbClosed = sal_True;
323 // ------------------------------------------------------------------------------
325 const GraphicObject& SvXMLGraphicOutputStream::GetGraphicObject()
327 if( mbClosed && ( maGrfObj.GetType() == GRAPHIC_NONE ) && mpOStm )
329 Graphic aGraphic;
331 mpOStm->Seek( 0 );
332 sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW;
333 sal_uInt16 pDeterminedFormat = GRFILTER_FORMAT_DONTKNOW;
334 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic, String(), *mpOStm ,nFormat,&pDeterminedFormat );
336 if (pDeterminedFormat == GRFILTER_FORMAT_DONTKNOW)
338 //Read the first two byte to check whether it is a gzipped stream, is so it may be in wmz or emz format
339 //unzip them and try again
341 sal_uInt8 sFirstBytes[ 2 ];
343 mpOStm->Seek( STREAM_SEEK_TO_END );
344 sal_uIntPtr nStreamLen = mpOStm->Tell();
345 mpOStm->Seek( 0 );
347 if ( !nStreamLen )
349 SvLockBytes* pLockBytes = mpOStm->GetLockBytes();
350 if ( pLockBytes )
351 pLockBytes->SetSynchronMode( sal_True );
353 mpOStm->Seek( STREAM_SEEK_TO_END );
354 nStreamLen = mpOStm->Tell();
355 mpOStm->Seek( 0 );
357 if( nStreamLen >= 2 )
359 //read two byte
360 mpOStm->Read( sFirstBytes, 2 );
362 if( sFirstBytes[0] == 0x1f && sFirstBytes[1] == 0x8b )
364 SvMemoryStream* pDest = new SvMemoryStream;
365 ZCodec aZCodec( 0x8000, 0x8000 );
366 aZCodec.BeginCompression(ZCODEC_GZ_LIB);
367 mpOStm->Seek( 0 );
368 aZCodec.Decompress( *mpOStm, *pDest );
370 if (aZCodec.EndCompression() && pDest )
372 pDest->Seek( STREAM_SEEK_TO_END );
373 sal_uIntPtr nStreamLen_ = pDest->Tell();
374 if (nStreamLen_)
376 pDest->Seek(0L);
377 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic, String(), *pDest ,nFormat,&pDeterminedFormat );
380 delete pDest;
385 maGrfObj = aGraphic;
386 if( maGrfObj.GetType() != GRAPHIC_NONE )
388 delete mpOStm, mpOStm = NULL;
389 delete mpTmp, mpTmp = NULL;
393 return maGrfObj;
396 // ----------------------
397 // - SvXMLGraphicHelper -
398 // ----------------------
400 SvXMLGraphicHelper::SvXMLGraphicHelper( SvXMLGraphicHelperMode eCreateMode ) :
401 ::cppu::WeakComponentImplHelper2< ::com::sun::star::document::XGraphicObjectResolver,
402 ::com::sun::star::document::XBinaryStreamResolver >( maMutex )
404 Init( NULL, eCreateMode, sal_False );
407 SvXMLGraphicHelper::SvXMLGraphicHelper() :
408 ::cppu::WeakComponentImplHelper2< ::com::sun::star::document::XGraphicObjectResolver,
409 ::com::sun::star::document::XBinaryStreamResolver >( maMutex )
413 // -----------------------------------------------------------------------------
415 SvXMLGraphicHelper::~SvXMLGraphicHelper()
419 // -----------------------------------------------------------------------------
421 void SAL_CALL SvXMLGraphicHelper::disposing()
425 // -----------------------------------------------------------------------------
427 sal_Bool SvXMLGraphicHelper::ImplGetStreamNames( const ::rtl::OUString& rURLStr,
428 ::rtl::OUString& rPictureStorageName,
429 ::rtl::OUString& rPictureStreamName )
431 String aURLStr( rURLStr );
432 sal_Bool bRet = sal_False;
434 if( aURLStr.Len() )
436 aURLStr = aURLStr.GetToken( comphelper::string::getTokenCount(aURLStr, ':') - 1, ':' );
438 const sal_uInt32 nTokenCount = comphelper::string::getTokenCount(aURLStr, '/');
440 if( 1 == nTokenCount )
442 rPictureStorageName = String( XML_GRAPHICSTORAGE_NAME );
443 rPictureStreamName = aURLStr;
445 else
446 SvXMLEmbeddedObjectHelper::splitObjectURL(aURLStr, rPictureStorageName, rPictureStreamName);
448 bRet = !rPictureStreamName.isEmpty();
449 SAL_WARN_IF(!bRet, "svx", "SvXMLGraphicHelper::ImplInsertGraphicURL: invalid scheme: " << rURLStr);
452 return bRet;
455 // -----------------------------------------------------------------------------
457 uno::Reference < embed::XStorage > SvXMLGraphicHelper::ImplGetGraphicStorage( const ::rtl::OUString& rStorageName )
459 uno::Reference < embed::XStorage > xRetStorage;
460 if( mxRootStorage.is() )
464 xRetStorage = mxRootStorage->openStorageElement(
465 maCurStorageName = rStorageName,
466 ( GRAPHICHELPER_MODE_WRITE == meCreateMode )
467 ? embed::ElementModes::READWRITE
468 : embed::ElementModes::READ );
470 catch ( uno::Exception& )
473 //#i43196# try again to open the storage element - this time readonly
474 if(!xRetStorage.is())
478 xRetStorage = mxRootStorage->openStorageElement( maCurStorageName = rStorageName, embed::ElementModes::READ );
480 catch ( uno::Exception& )
486 return xRetStorage;
489 // -----------------------------------------------------------------------------
491 SvxGraphicHelperStream_Impl SvXMLGraphicHelper::ImplGetGraphicStream( const ::rtl::OUString& rPictureStorageName,
492 const ::rtl::OUString& rPictureStreamName,
493 sal_Bool bTruncate )
495 SvxGraphicHelperStream_Impl aRet;
496 aRet.xStorage = ImplGetGraphicStorage( rPictureStorageName );
498 if( aRet.xStorage.is() )
500 sal_Int32 nMode = embed::ElementModes::READ;
501 if ( GRAPHICHELPER_MODE_WRITE == meCreateMode )
503 nMode = embed::ElementModes::READWRITE;
504 if ( bTruncate )
505 nMode |= embed::ElementModes::TRUNCATE;
508 aRet.xStream = aRet.xStorage->openStreamElement( rPictureStreamName, nMode );
509 if( aRet.xStream.is() && ( GRAPHICHELPER_MODE_WRITE == meCreateMode ) )
511 ::rtl::OUString aPropName( "UseCommonStoragePasswordEncryption" );
512 uno::Reference < beans::XPropertySet > xProps( aRet.xStream, uno::UNO_QUERY );
513 xProps->setPropertyValue( aPropName, uno::makeAny( sal_True) );
517 return aRet;
520 // -----------------------------------------------------------------------------
522 String SvXMLGraphicHelper::ImplGetGraphicMimeType( const String& rFileName ) const
524 struct XMLGraphicMimeTypeMapper
526 const char* pExt;
527 const char* pMimeType;
530 static XMLGraphicMimeTypeMapper aMapper[] =
532 { "gif", "image/gif" },
533 { "png", "image/png" },
534 { "jpg", "image/jpeg" },
535 { "tif", "image/tiff" },
536 { "svg", "image/svg+xml" }
539 String aMimeType;
541 if( ( rFileName.Len() >= 4 ) && ( rFileName.GetChar( rFileName.Len() - 4 ) == '.' ) )
543 const rtl::OString aExt(rtl::OUStringToOString(rFileName.Copy(rFileName.Len() - 3),
544 RTL_TEXTENCODING_ASCII_US));
546 for( long i = 0, nCount = sizeof (aMapper) / sizeof (aMapper[0]); ( i < nCount ) && !aMimeType.Len(); i++ )
547 if( aExt.getStr() == aMapper[ i ].pExt )
548 aMimeType = String( aMapper[ i ].pMimeType, RTL_TEXTENCODING_ASCII_US );
551 return aMimeType;
554 // -----------------------------------------------------------------------------
556 Graphic SvXMLGraphicHelper::ImplReadGraphic( const ::rtl::OUString& rPictureStorageName,
557 const ::rtl::OUString& rPictureStreamName )
559 Graphic aGraphic;
560 SvxGraphicHelperStream_Impl aStream( ImplGetGraphicStream( rPictureStorageName, rPictureStreamName, sal_False ) );
561 if( aStream.xStream.is() )
563 SvStream* pStream = utl::UcbStreamHelper::CreateStream( aStream.xStream );
564 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic, String(), *pStream );
565 delete pStream;
568 return aGraphic;
571 // -----------------------------------------------------------------------------
573 sal_Bool SvXMLGraphicHelper::ImplWriteGraphic( const ::rtl::OUString& rPictureStorageName,
574 const ::rtl::OUString& rPictureStreamName,
575 const ::rtl::OUString& rGraphicId,
576 bool bUseGfxLink )
578 GraphicObject aGrfObject( rtl::OUStringToOString(rGraphicId, RTL_TEXTENCODING_ASCII_US) );
579 sal_Bool bRet = sal_False;
581 if( aGrfObject.GetType() != GRAPHIC_NONE )
583 SvxGraphicHelperStream_Impl aStream( ImplGetGraphicStream( rPictureStorageName, rPictureStreamName, sal_False ) );
584 if( aStream.xStream.is() )
586 Graphic aGraphic( (Graphic&) aGrfObject.GetGraphic() );
587 const GfxLink aGfxLink( aGraphic.GetLink() );
588 const ::rtl::OUString aMimeType( ImplGetGraphicMimeType( rPictureStreamName ) );
589 uno::Any aAny;
590 uno::Reference < beans::XPropertySet > xProps( aStream.xStream, uno::UNO_QUERY );
592 // set stream properties (MediaType/Compression)
593 if( !aMimeType.isEmpty() )
595 aAny <<= aMimeType;
596 xProps->setPropertyValue( String( "MediaType" ), aAny );
599 const sal_Bool bCompressed = aMimeType.isEmpty() || aMimeType == "image/tiff";
600 aAny <<= bCompressed;
601 xProps->setPropertyValue( String( "Compressed" ), aAny );
603 SvStream* pStream = utl::UcbStreamHelper::CreateStream( aStream.xStream );
604 if( bUseGfxLink && aGfxLink.GetDataSize() && aGfxLink.GetData() )
605 pStream->Write( aGfxLink.GetData(), aGfxLink.GetDataSize() );
606 else
608 if( aGraphic.GetType() == GRAPHIC_BITMAP )
610 GraphicFilter &rFilter = GraphicFilter::GetGraphicFilter();
611 String aFormat;
613 if( aGraphic.IsAnimated() )
614 aFormat = String( "gif" );
615 else
616 aFormat = String( "png" );
618 bRet = ( rFilter.ExportGraphic( aGraphic, String(), *pStream,
619 rFilter.GetExportFormatNumberForShortName( aFormat ) ) == 0 );
621 else if( aGraphic.GetType() == GRAPHIC_GDIMETAFILE )
623 pStream->SetVersion( SOFFICE_FILEFORMAT_8 );
624 pStream->SetCompressMode( COMPRESSMODE_ZBITMAP );
626 // SJ: first check if this metafile is just a eps file, then we will store the eps instead of svm
627 GDIMetaFile& rMtf( (GDIMetaFile&)aGraphic.GetGDIMetaFile() );
628 const MetaCommentAction* pComment = ImplCheckForEPS( rMtf );
629 if ( pComment )
631 sal_uInt32 nSize = pComment->GetDataSize();
632 const sal_uInt8* pData = pComment->GetData();
633 if ( nSize && pData )
634 pStream->Write( pData, nSize );
636 const MetaEPSAction* pAct = ( (const MetaEPSAction*)rMtf.FirstAction() );
637 const GfxLink& rLink = pAct->GetLink();
639 pStream->Write( rLink.GetData(), rLink.GetDataSize() );
641 else
642 rMtf.Write( *pStream, GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC );
644 bRet = ( pStream->GetError() == 0 );
647 uno::Reference < embed::XTransactedObject > xStorage(
648 aStream.xStorage, uno::UNO_QUERY);
649 delete pStream;
650 aStream.xStream->getOutputStream()->closeOutput();
651 if( xStorage.is() )
652 xStorage->commit();
656 return bRet;
659 // -----------------------------------------------------------------------------
661 void SvXMLGraphicHelper::ImplInsertGraphicURL( const ::rtl::OUString& rURLStr, sal_uInt32 nInsertPos, rtl::OUString& rRequestedFileName )
663 rtl::OUString aURLString( rURLStr );
664 ::rtl::OUString aPictureStorageName, aPictureStreamName;
665 if( ( maURLSet.find( aURLString ) != maURLSet.end() ) )
667 URLPairVector::iterator aIter( maGrfURLs.begin() ), aEnd( maGrfURLs.end() );
668 while( aIter != aEnd )
670 if( aURLString == (*aIter).first )
672 maGrfURLs[ nInsertPos ].second = (*aIter).second;
673 aIter = aEnd;
675 else
676 aIter++;
679 else if( ImplGetStreamNames( aURLString, aPictureStorageName, aPictureStreamName ) )
681 URLPair& rURLPair = maGrfURLs[ nInsertPos ];
683 if( GRAPHICHELPER_MODE_READ == meCreateMode )
685 const GraphicObject aObj( ImplReadGraphic( aPictureStorageName, aPictureStreamName ) );
687 if( aObj.GetType() != GRAPHIC_NONE )
689 maGrfObjs.push_back( aObj );
690 ::rtl::OUString aBaseURL( XML_GRAPHICOBJECT_URL_BASE );
692 rURLPair.second = aBaseURL;
693 rURLPair.second += rtl::OStringToOUString(aObj.GetUniqueID(),
694 RTL_TEXTENCODING_ASCII_US);
696 else
697 rURLPair.second = String();
699 else
701 const String aGraphicObjectId( aPictureStreamName );
702 const rtl::OString aAsciiObjectID(rtl::OUStringToOString(aGraphicObjectId, RTL_TEXTENCODING_ASCII_US));
703 const GraphicObject aGrfObject( aAsciiObjectID );
704 if( aGrfObject.GetType() != GRAPHIC_NONE )
706 String aStreamName( aGraphicObjectId );
707 Graphic aGraphic( (Graphic&) aGrfObject.GetGraphic() );
708 const GfxLink aGfxLink( aGraphic.GetLink() );
709 String aExtension;
710 bool bUseGfxLink( true );
712 if( aGfxLink.GetDataSize() )
714 switch( aGfxLink.GetType() )
716 case( GFX_LINK_TYPE_EPS_BUFFER ): aExtension = String( ".eps" ); break;
717 case( GFX_LINK_TYPE_NATIVE_GIF ): aExtension = String( ".gif" ); break;
718 case( GFX_LINK_TYPE_NATIVE_JPG ): aExtension = String( ".jpg" ); break;
719 case( GFX_LINK_TYPE_NATIVE_PNG ): aExtension = String( ".png" ); break;
720 case( GFX_LINK_TYPE_NATIVE_TIF ): aExtension = String( ".tif" ); break;
721 case( GFX_LINK_TYPE_NATIVE_WMF ): aExtension = String( ".wmf" ); break;
722 case( GFX_LINK_TYPE_NATIVE_MET ): aExtension = String( ".met" ); break;
723 case( GFX_LINK_TYPE_NATIVE_PCT ): aExtension = String( ".pct" ); break;
724 case( GFX_LINK_TYPE_NATIVE_SVG ):
725 // backward-compat kludge: since no released OOo
726 // version to date can handle svg properly, wrap it up
727 // into an svm. slight catch22 here, since strict ODF
728 // conformance _recommends_ svg - then again, most old
729 // ODF consumers are believed to be OOo
730 if( SvtSaveOptions().GetODFDefaultVersion() <= SvtSaveOptions::ODFVER_012 )
732 bUseGfxLink = false;
733 aExtension = String( ".svm" );
735 else
736 aExtension = String( ".svg" );
737 break;
739 default:
740 aExtension = String( ".grf" );
741 break;
744 else
746 if( aGrfObject.GetType() == GRAPHIC_BITMAP )
748 if( aGrfObject.IsAnimated() )
749 aExtension = String( ".gif" );
750 else
751 aExtension = String( ".png" );
753 else if( aGrfObject.GetType() == GRAPHIC_GDIMETAFILE )
755 // SJ: first check if this metafile is just a eps file, then we will store the eps instead of svm
756 GDIMetaFile& rMtf( (GDIMetaFile&)aGraphic.GetGDIMetaFile() );
757 if ( ImplCheckForEPS( rMtf ) )
758 aExtension = String( ".eps" );
759 else
760 aExtension = String( ".svm" );
764 rtl::OUString aURLEntry;
765 const String sPictures( "Pictures/" );
767 if ( !rRequestedFileName.isEmpty() )
769 aURLEntry = sPictures;
770 aURLEntry += rRequestedFileName;
771 aURLEntry += aExtension;
773 URLPairVector::iterator aIter( maGrfURLs.begin() ), aEnd( maGrfURLs.end() );
774 while( aIter != aEnd )
776 if( aURLEntry == (*aIter).second )
777 break;
778 aIter++;
780 if ( aIter == aEnd )
781 aStreamName = rRequestedFileName;
784 aStreamName += aExtension;
786 if( mbDirect && aStreamName.Len() )
787 ImplWriteGraphic( aPictureStorageName, aStreamName, aGraphicObjectId, bUseGfxLink );
789 rURLPair.second = sPictures;
790 rURLPair.second += aStreamName;
792 #if OSL_DEBUG_LEVEL > 0
793 else
795 rtl::OStringBuffer sMessage(
796 RTL_CONSTASCII_STRINGPARAM("graphic object with ID '"));
797 sMessage.append(aAsciiObjectID).
798 append(RTL_CONSTASCII_STRINGPARAM("' has an unknown type"));
799 OSL_ENSURE( false, sMessage.getStr() );
801 #endif
804 maURLSet.insert( aURLString );
808 // -----------------------------------------------------------------------------
810 void SvXMLGraphicHelper::Init( const uno::Reference < embed::XStorage >& rXMLStorage,
811 SvXMLGraphicHelperMode eCreateMode,
812 sal_Bool bDirect )
814 mxRootStorage = rXMLStorage;
815 meCreateMode = eCreateMode;
816 mbDirect = ( ( GRAPHICHELPER_MODE_READ == meCreateMode ) ? bDirect : sal_True );
819 // -----------------------------------------------------------------------------
821 SvXMLGraphicHelper* SvXMLGraphicHelper::Create( const uno::Reference < embed::XStorage >& rXMLStorage,
822 SvXMLGraphicHelperMode eCreateMode,
823 sal_Bool bDirect )
825 SvXMLGraphicHelper* pThis = new SvXMLGraphicHelper;
827 pThis->acquire();
828 pThis->Init( rXMLStorage, eCreateMode, bDirect );
830 return pThis;
833 // -----------------------------------------------------------------------------
835 SvXMLGraphicHelper* SvXMLGraphicHelper::Create( SvXMLGraphicHelperMode eCreateMode )
837 SvXMLGraphicHelper* pThis = new SvXMLGraphicHelper;
839 pThis->acquire();
840 pThis->Init( NULL, eCreateMode, sal_False );
842 return pThis;
845 // -----------------------------------------------------------------------------
847 void SvXMLGraphicHelper::Destroy( SvXMLGraphicHelper* pSvXMLGraphicHelper )
849 if( pSvXMLGraphicHelper )
851 pSvXMLGraphicHelper->dispose();
852 pSvXMLGraphicHelper->release();
856 // -----------------------------------------------------------------------------
858 // XGraphicObjectResolver
859 ::rtl::OUString SAL_CALL SvXMLGraphicHelper::resolveGraphicObjectURL( const ::rtl::OUString& rURL )
860 throw(uno::RuntimeException)
862 ::osl::MutexGuard aGuard( maMutex );
863 const sal_Int32 nIndex = maGrfURLs.size();
865 rtl::OUString aURL( rURL );
866 rtl::OUString aUserData;
867 rtl::OUString aRequestedFileName;
869 sal_Int32 nUser = rURL.indexOf( '?', 0 );
870 if ( nUser >= 0 )
872 aURL = rtl::OUString( rURL.copy( 0, nUser ) );
873 nUser++;
874 aUserData = rURL.copy( nUser, rURL.getLength() - nUser );
876 if ( !aUserData.isEmpty() )
878 sal_Int32 nIndex2 = 0;
881 rtl::OUString aToken = aUserData.getToken( 0, ';', nIndex2 );
882 sal_Int32 n = aToken.indexOf( '=' );
883 if ( ( n > 0 ) && ( ( n + 1 ) < aToken.getLength() ) )
885 rtl::OUString aParam( aToken.copy( 0, n ) );
886 rtl::OUString aValue( aToken.copy( n + 1, aToken.getLength() - ( n + 1 ) ) );
888 const rtl::OUString sRequestedName( "requestedName" );
889 if ( aParam.match( sRequestedName ) )
890 aRequestedFileName = aValue;
893 while ( nIndex2 >= 0 );
896 maGrfURLs.push_back( ::std::make_pair( aURL, ::rtl::OUString() ) );
897 ImplInsertGraphicURL( aURL, nIndex, aRequestedFileName );
899 return maGrfURLs[ nIndex ].second;
902 // -----------------------------------------------------------------------------
904 // XBinaryStreamResolver
905 Reference< XInputStream > SAL_CALL SvXMLGraphicHelper::getInputStream( const ::rtl::OUString& rURL )
906 throw( RuntimeException )
908 Reference< XInputStream > xRet;
909 ::rtl::OUString aPictureStorageName, aGraphicId;
912 if( ( GRAPHICHELPER_MODE_WRITE == meCreateMode ) &&
913 ImplGetStreamNames( rURL, aPictureStorageName, aGraphicId ) )
915 SvXMLGraphicInputStream* pInputStream = new SvXMLGraphicInputStream( aGraphicId );
917 if( pInputStream->Exists() )
918 xRet = pInputStream;
919 else
920 delete pInputStream;
923 return xRet;
926 // -----------------------------------------------------------------------------
928 Reference< XOutputStream > SAL_CALL SvXMLGraphicHelper::createOutputStream()
929 throw( RuntimeException )
931 Reference< XOutputStream > xRet;
933 if( GRAPHICHELPER_MODE_READ == meCreateMode )
935 SvXMLGraphicOutputStream* pOutputStream = new SvXMLGraphicOutputStream;
937 if( pOutputStream->Exists() )
938 maGrfStms.push_back( xRet = pOutputStream );
939 else
940 delete pOutputStream;
943 return xRet;
946 // -----------------------------------------------------------------------------
948 ::rtl::OUString SAL_CALL SvXMLGraphicHelper::resolveOutputStream( const Reference< XOutputStream >& rxBinaryStream )
949 throw( RuntimeException )
951 ::rtl::OUString aRet;
953 if( ( GRAPHICHELPER_MODE_READ == meCreateMode ) && rxBinaryStream.is() )
955 if( ::std::find( maGrfStms.begin(), maGrfStms.end(), rxBinaryStream ) != maGrfStms.end() )
957 SvXMLGraphicOutputStream* pOStm = static_cast< SvXMLGraphicOutputStream* >( rxBinaryStream.get() );
959 if( pOStm )
961 const GraphicObject& rGrfObj = pOStm->GetGraphicObject();
962 const ::rtl::OUString aId(::rtl::OStringToOUString(
963 rGrfObj.GetUniqueID(), RTL_TEXTENCODING_ASCII_US));
965 if( !aId.isEmpty() )
967 aRet = ::rtl::OUString( XML_GRAPHICOBJECT_URL_BASE );
968 aRet += aId;
974 return aRet;
978 // --------------------------------------------------------------------------------
980 // for instantiation via service manager
981 namespace svx
984 namespace impl
986 typedef ::cppu::WeakComponentImplHelper4<
987 lang::XInitialization,
988 document::XGraphicObjectResolver,
989 document::XBinaryStreamResolver,
990 lang::XServiceInfo >
991 SvXMLGraphicImportExportHelper_Base;
992 class MutexContainer
994 public:
995 virtual ~MutexContainer();
997 protected:
998 mutable ::osl::Mutex m_aMutex;
1000 MutexContainer::~MutexContainer()
1002 } // namespace impl
1004 class SvXMLGraphicImportExportHelper :
1005 public impl::MutexContainer,
1006 public impl::SvXMLGraphicImportExportHelper_Base
1008 public:
1009 SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode );
1011 protected:
1012 // is called from WeakComponentImplHelper when XComponent::dispose() was
1013 // called from outside
1014 virtual void SAL_CALL disposing();
1016 // ____ XInitialization ____
1017 // one argument is allowed, which is the XStorage
1018 virtual void SAL_CALL initialize( const Sequence< Any >& aArguments )
1019 throw (Exception,
1020 RuntimeException);
1022 // ____ XGraphicObjectResolver ____
1023 virtual ::rtl::OUString SAL_CALL resolveGraphicObjectURL( const ::rtl::OUString& aURL )
1024 throw (RuntimeException);
1026 // ____ XBinaryStreamResolver ____
1027 virtual Reference< io::XInputStream > SAL_CALL getInputStream( const ::rtl::OUString& aURL )
1028 throw (RuntimeException);
1029 virtual Reference< io::XOutputStream > SAL_CALL createOutputStream()
1030 throw (RuntimeException);
1031 virtual ::rtl::OUString SAL_CALL resolveOutputStream( const Reference< io::XOutputStream >& aBinaryStream )
1032 throw (RuntimeException);
1034 // ____ XServiceInfo ____
1035 virtual ::rtl::OUString SAL_CALL getImplementationName()
1036 throw (RuntimeException);
1037 virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName )
1038 throw (RuntimeException);
1039 virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames()
1040 throw (RuntimeException);
1042 private:
1043 SvXMLGraphicHelperMode m_eGraphicHelperMode;
1044 Reference< XGraphicObjectResolver > m_xGraphicObjectResolver;
1045 Reference< XBinaryStreamResolver > m_xBinaryStreamResolver;
1048 SvXMLGraphicImportExportHelper::SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode ) :
1049 impl::SvXMLGraphicImportExportHelper_Base( m_aMutex ),
1050 m_eGraphicHelperMode( eMode )
1053 void SAL_CALL SvXMLGraphicImportExportHelper::disposing()
1055 Reference< XComponent > xComp( m_xGraphicObjectResolver, UNO_QUERY );
1056 OSL_ASSERT( xComp.is());
1057 if( xComp.is())
1058 xComp->dispose();
1059 // m_xBinaryStreamResolver is a reference to the same object => don't call
1060 // dispose() again
1063 // ____ XInitialization ____
1064 void SAL_CALL SvXMLGraphicImportExportHelper::initialize(
1065 const Sequence< Any >& aArguments )
1066 throw (Exception, RuntimeException)
1068 Reference< embed::XStorage > xStorage;
1069 if( aArguments.getLength() > 0 )
1070 aArguments[0] >>= xStorage;
1072 SvXMLGraphicHelper * pHelper( SvXMLGraphicHelper::Create( xStorage, m_eGraphicHelperMode ));
1073 m_xGraphicObjectResolver.set( pHelper );
1074 m_xBinaryStreamResolver.set( pHelper );
1075 // SvXMLGraphicHelper::Create calls acquire. Since we have two references
1076 // now it is safe (and necessary) to undo this acquire
1077 pHelper->release();
1080 // ____ XGraphicObjectResolver ____
1081 ::rtl::OUString SAL_CALL SvXMLGraphicImportExportHelper::resolveGraphicObjectURL( const ::rtl::OUString& aURL )
1082 throw (uno::RuntimeException)
1084 return m_xGraphicObjectResolver->resolveGraphicObjectURL( aURL );
1088 // ____ XBinaryStreamResolver ____
1089 Reference< io::XInputStream > SAL_CALL SvXMLGraphicImportExportHelper::getInputStream( const ::rtl::OUString& aURL )
1090 throw (uno::RuntimeException)
1092 return m_xBinaryStreamResolver->getInputStream( aURL );
1094 Reference< io::XOutputStream > SAL_CALL SvXMLGraphicImportExportHelper::createOutputStream()
1095 throw (uno::RuntimeException)
1097 return m_xBinaryStreamResolver->createOutputStream();
1099 ::rtl::OUString SAL_CALL SvXMLGraphicImportExportHelper::resolveOutputStream( const Reference< io::XOutputStream >& aBinaryStream )
1100 throw (uno::RuntimeException)
1102 return m_xBinaryStreamResolver->resolveOutputStream( aBinaryStream );
1105 // ____ XServiceInfo ____
1106 ::rtl::OUString SAL_CALL SvXMLGraphicImportExportHelper::getImplementationName()
1107 throw (uno::RuntimeException)
1109 if( m_eGraphicHelperMode == GRAPHICHELPER_MODE_READ )
1110 return SvXMLGraphicImportHelper_getImplementationName();
1111 return SvXMLGraphicExportHelper_getImplementationName();
1113 ::sal_Bool SAL_CALL SvXMLGraphicImportExportHelper::supportsService( const ::rtl::OUString& ServiceName )
1114 throw (uno::RuntimeException)
1116 Sequence< ::rtl::OUString > aServiceNames( getSupportedServiceNames());
1117 const ::rtl::OUString * pBegin = aServiceNames.getConstArray();
1118 const ::rtl::OUString * pEnd = pBegin + aServiceNames.getLength();
1119 return (::std::find( pBegin, pEnd, ServiceName ) != pEnd);
1121 Sequence< ::rtl::OUString > SAL_CALL SvXMLGraphicImportExportHelper::getSupportedServiceNames()
1122 throw (uno::RuntimeException)
1124 if( m_eGraphicHelperMode == GRAPHICHELPER_MODE_READ )
1125 return SvXMLGraphicImportHelper_getSupportedServiceNames();
1126 return SvXMLGraphicExportHelper_getSupportedServiceNames();
1129 // import
1130 Reference< XInterface > SAL_CALL SvXMLGraphicImportHelper_createInstance(const Reference< XMultiServiceFactory > & /* rSMgr */ )
1131 throw( Exception )
1133 return static_cast< XWeak* >( new SvXMLGraphicImportExportHelper( GRAPHICHELPER_MODE_READ ));
1135 ::rtl::OUString SAL_CALL SvXMLGraphicImportHelper_getImplementationName()
1136 throw()
1138 return ::rtl::OUString( "com.sun.star.comp.Svx.GraphicImportHelper" );
1140 Sequence< ::rtl::OUString > SAL_CALL SvXMLGraphicImportHelper_getSupportedServiceNames()
1141 throw()
1143 // XGraphicObjectResolver and XBinaryStreamResolver are not part of any service
1144 Sequence< ::rtl::OUString > aSupportedServiceNames( 2 );
1145 aSupportedServiceNames[0] = ::rtl::OUString( "com.sun.star.document.GraphicObjectResolver" );
1146 aSupportedServiceNames[1] = ::rtl::OUString( "com.sun.star.document.BinaryStreamResolver" );
1147 return aSupportedServiceNames;
1150 // export
1151 Reference< XInterface > SAL_CALL SvXMLGraphicExportHelper_createInstance(const Reference< XMultiServiceFactory > & /* rSMgr */ )
1152 throw( Exception )
1154 return static_cast< XWeak* >( new SvXMLGraphicImportExportHelper( GRAPHICHELPER_MODE_WRITE ));
1156 ::rtl::OUString SAL_CALL SvXMLGraphicExportHelper_getImplementationName()
1157 throw()
1159 return ::rtl::OUString( "com.sun.star.comp.Svx.GraphicExportHelper" );
1161 Sequence< ::rtl::OUString > SAL_CALL SvXMLGraphicExportHelper_getSupportedServiceNames()
1162 throw()
1164 // XGraphicObjectResolver and XBinaryStreamResolver are not part of any service
1165 Sequence< ::rtl::OUString > aSupportedServiceNames( 2 );
1166 aSupportedServiceNames[0] = ::rtl::OUString( "com.sun.star.document.GraphicObjectResolver" );
1167 aSupportedServiceNames[1] = ::rtl::OUString( "com.sun.star.document.BinaryStreamResolver" );
1168 return aSupportedServiceNames;
1171 } // namespace svx
1173 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */