bump product version to 4.1.6.2
[LibreOffice.git] / svx / source / xml / xmlgrhlp.cxx
blob438427da897e9d82daa0a397f384bcd6e21dbcd0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <comphelper/string.hxx>
21 #include <sal/macros.h>
22 #include <rtl/strbuf.hxx>
23 #include <com/sun/star/embed/XTransactedObject.hpp>
24 #include <com/sun/star/embed/ElementModes.hpp>
25 #include <com/sun/star/beans/XPropertySet.hpp>
26 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
27 #include <com/sun/star/lang/XServiceInfo.hpp>
28 #include <com/sun/star/lang/XInitialization.hpp>
29 #include <cppuhelper/compbase4.hxx>
31 #include <unotools/ucbstreamhelper.hxx>
32 #include <unotools/streamwrap.hxx>
33 #include <unotools/tempfile.hxx>
34 #include <unotools/saveopt.hxx>
35 #include <tools/debug.hxx>
36 #include <vcl/cvtgrf.hxx>
37 #include <vcl/gfxlink.hxx>
38 #include <vcl/metaact.hxx>
39 #include <tools/zcodec.hxx>
41 #include <vcl/graphicfilter.hxx>
42 #include "svx/xmlgrhlp.hxx"
43 #include "svx/xmleohlp.hxx"
45 #include <algorithm>
47 using namespace com::sun::star;
48 using namespace com::sun::star::uno;
49 using namespace com::sun::star::io;
51 using ::com::sun::star::lang::XMultiServiceFactory;
53 #define XML_GRAPHICSTORAGE_NAME "Pictures"
54 #define XML_GRAPHICOBJECT_URL_BASE "vnd.sun.star.GraphicObject:"
56 const MetaCommentAction* ImplCheckForEPS( GDIMetaFile& rMtf )
58 const MetaCommentAction* pComment = NULL;
60 if ( ( rMtf.GetActionSize() >= 2 )
61 && ( rMtf.FirstAction()->GetType() == META_EPS_ACTION )
62 && ( ((const MetaAction*)rMtf.GetAction( 1 ))->GetType() == META_COMMENT_ACTION )
63 && ( ((const MetaCommentAction*)rMtf.GetAction( 1 ))->GetComment().equalsL(RTL_CONSTASCII_STRINGPARAM("EPSReplacementGraphic")) ) )
64 pComment = (const MetaCommentAction*)rMtf.GetAction( 1 );
66 return pComment;
69 class SvXMLGraphicInputStream : public::cppu::WeakImplHelper1< XInputStream >
71 private:
73 virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) throw(NotConnectedException, BufferSizeExceededException, RuntimeException);
74 virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) throw(NotConnectedException, BufferSizeExceededException, RuntimeException);
75 virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) throw(NotConnectedException, BufferSizeExceededException, RuntimeException);
76 virtual sal_Int32 SAL_CALL available() throw(NotConnectedException, RuntimeException);
77 virtual void SAL_CALL closeInput() throw(NotConnectedException, RuntimeException);
79 private:
81 ::utl::TempFile maTmp;
82 Reference< XInputStream > mxStmWrapper;
84 // not available
85 SvXMLGraphicInputStream();
86 SvXMLGraphicInputStream( const SvXMLGraphicInputStream& );
87 SvXMLGraphicInputStream& operator==( SvXMLGraphicInputStream& );
89 public:
91 SvXMLGraphicInputStream( const OUString& rGraphicId );
92 virtual ~SvXMLGraphicInputStream();
94 bool Exists() const { return mxStmWrapper.is(); }
97 SvXMLGraphicInputStream::SvXMLGraphicInputStream( const OUString& rGraphicId )
99 GraphicObject aGrfObject( OUStringToOString(rGraphicId, RTL_TEXTENCODING_ASCII_US) );
101 maTmp.EnableKillingFile();
103 if( aGrfObject.GetType() != GRAPHIC_NONE )
105 SvStream* pStm = ::utl::UcbStreamHelper::CreateStream( maTmp.GetURL(), STREAM_WRITE | STREAM_TRUNC );
107 if( pStm )
109 Graphic aGraphic( (Graphic&) aGrfObject.GetGraphic() );
110 const GfxLink aGfxLink( aGraphic.GetLink() );
111 sal_Bool bRet = sal_False;
113 if( aGfxLink.GetDataSize() && aGfxLink.GetData() )
115 pStm->Write( aGfxLink.GetData(), aGfxLink.GetDataSize() );
116 bRet = ( pStm->GetError() == 0 );
118 else
120 if( aGraphic.GetType() == GRAPHIC_BITMAP )
122 GraphicFilter &rFilter = GraphicFilter::GetGraphicFilter();
123 String aFormat;
125 if( aGraphic.IsAnimated() )
126 aFormat = String( "gif" );
127 else
128 aFormat = String( "png" );
130 bRet = ( rFilter.ExportGraphic( aGraphic, String(), *pStm, rFilter.GetExportFormatNumberForShortName( aFormat ) ) == 0 );
132 else if( aGraphic.GetType() == GRAPHIC_GDIMETAFILE )
134 pStm->SetVersion( SOFFICE_FILEFORMAT_8 );
135 pStm->SetCompressMode( COMPRESSMODE_ZBITMAP );
136 ( (GDIMetaFile&) aGraphic.GetGDIMetaFile() ).Write( *pStm );
137 bRet = ( pStm->GetError() == 0 );
141 if( bRet )
143 pStm->Seek( 0 );
144 mxStmWrapper = new ::utl::OInputStreamWrapper( pStm, sal_True );
146 else
147 delete pStm;
152 SvXMLGraphicInputStream::~SvXMLGraphicInputStream()
156 sal_Int32 SAL_CALL SvXMLGraphicInputStream::readBytes( Sequence< sal_Int8 >& rData, sal_Int32 nBytesToRead )
157 throw( NotConnectedException, BufferSizeExceededException, RuntimeException )
159 if( !mxStmWrapper.is() )
160 throw NotConnectedException();
162 return mxStmWrapper->readBytes( rData, nBytesToRead );
165 sal_Int32 SAL_CALL SvXMLGraphicInputStream::readSomeBytes( Sequence< sal_Int8 >& rData, sal_Int32 nMaxBytesToRead )
166 throw( NotConnectedException, BufferSizeExceededException, RuntimeException )
168 if( !mxStmWrapper.is() )
169 throw NotConnectedException() ;
171 return mxStmWrapper->readSomeBytes( rData, nMaxBytesToRead );
174 void SAL_CALL SvXMLGraphicInputStream::skipBytes( sal_Int32 nBytesToSkip )
175 throw( NotConnectedException, BufferSizeExceededException, RuntimeException )
177 if( !mxStmWrapper.is() )
178 throw NotConnectedException() ;
180 mxStmWrapper->skipBytes( nBytesToSkip );
183 sal_Int32 SAL_CALL SvXMLGraphicInputStream::available() throw( NotConnectedException, RuntimeException )
185 if( !mxStmWrapper.is() )
186 throw NotConnectedException() ;
188 return mxStmWrapper->available();
191 void SAL_CALL SvXMLGraphicInputStream::closeInput() throw( NotConnectedException, RuntimeException )
193 if( !mxStmWrapper.is() )
194 throw NotConnectedException() ;
196 mxStmWrapper->closeInput();
199 class SvXMLGraphicOutputStream : public::cppu::WeakImplHelper1< XOutputStream >
201 private:
203 // XOutputStream
204 virtual void SAL_CALL writeBytes( const Sequence< sal_Int8 >& rData ) throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );
205 virtual void SAL_CALL flush() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );
206 virtual void SAL_CALL closeOutput() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );
208 private:
210 ::utl::TempFile* mpTmp;
211 SvStream* mpOStm;
212 Reference< XOutputStream > mxStmWrapper;
213 GraphicObject maGrfObj;
214 sal_Bool mbClosed;
216 // not available
217 SvXMLGraphicOutputStream( const SvXMLGraphicOutputStream& );
218 SvXMLGraphicOutputStream& operator==( SvXMLGraphicOutputStream& );
220 public:
222 SvXMLGraphicOutputStream();
223 virtual ~SvXMLGraphicOutputStream();
225 bool Exists() const { return mxStmWrapper.is(); }
226 const GraphicObject& GetGraphicObject();
229 SvXMLGraphicOutputStream::SvXMLGraphicOutputStream() :
230 mpTmp( new ::utl::TempFile ),
231 mbClosed( sal_False )
233 mpTmp->EnableKillingFile();
235 mpOStm = ::utl::UcbStreamHelper::CreateStream( mpTmp->GetURL(), STREAM_WRITE | STREAM_TRUNC );
237 if( mpOStm )
238 mxStmWrapper = new ::utl::OOutputStreamWrapper( *mpOStm );
241 SvXMLGraphicOutputStream::~SvXMLGraphicOutputStream()
243 delete mpTmp;
244 delete mpOStm;
247 void SAL_CALL SvXMLGraphicOutputStream::writeBytes( const Sequence< sal_Int8 >& rData )
248 throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
250 if( !mxStmWrapper.is() )
251 throw NotConnectedException() ;
253 mxStmWrapper->writeBytes( rData );
256 void SAL_CALL SvXMLGraphicOutputStream::flush()
257 throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
259 if( !mxStmWrapper.is() )
260 throw NotConnectedException() ;
262 mxStmWrapper->flush();
265 void SAL_CALL SvXMLGraphicOutputStream::closeOutput()
266 throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
268 if( !mxStmWrapper.is() )
269 throw NotConnectedException() ;
271 mxStmWrapper->closeOutput();
272 mxStmWrapper = Reference< XOutputStream >();
274 mbClosed = sal_True;
277 const GraphicObject& SvXMLGraphicOutputStream::GetGraphicObject()
279 if( mbClosed && ( maGrfObj.GetType() == GRAPHIC_NONE ) && mpOStm )
281 Graphic aGraphic;
283 mpOStm->Seek( 0 );
284 sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW;
285 sal_uInt16 pDeterminedFormat = GRFILTER_FORMAT_DONTKNOW;
286 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic, String(), *mpOStm ,nFormat,&pDeterminedFormat );
288 if (pDeterminedFormat == GRFILTER_FORMAT_DONTKNOW)
290 //Read the first two byte to check whether it is a gzipped stream, is so it may be in wmz or emz format
291 //unzip them and try again
293 sal_uInt8 sFirstBytes[ 2 ];
295 mpOStm->Seek( STREAM_SEEK_TO_END );
296 sal_uIntPtr nStreamLen = mpOStm->Tell();
297 mpOStm->Seek( 0 );
299 if ( !nStreamLen )
301 SvLockBytes* pLockBytes = mpOStm->GetLockBytes();
302 if ( pLockBytes )
303 pLockBytes->SetSynchronMode( sal_True );
305 mpOStm->Seek( STREAM_SEEK_TO_END );
306 nStreamLen = mpOStm->Tell();
307 mpOStm->Seek( 0 );
309 if( nStreamLen >= 2 )
311 //read two byte
312 mpOStm->Read( sFirstBytes, 2 );
314 if( sFirstBytes[0] == 0x1f && sFirstBytes[1] == 0x8b )
316 SvMemoryStream* pDest = new SvMemoryStream;
317 ZCodec aZCodec( 0x8000, 0x8000 );
318 aZCodec.BeginCompression(ZCODEC_GZ_LIB);
319 mpOStm->Seek( 0 );
320 aZCodec.Decompress( *mpOStm, *pDest );
322 if (aZCodec.EndCompression() && pDest )
324 pDest->Seek( STREAM_SEEK_TO_END );
325 sal_uIntPtr nStreamLen_ = pDest->Tell();
326 if (nStreamLen_)
328 pDest->Seek(0L);
329 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic, String(), *pDest ,nFormat,&pDeterminedFormat );
332 delete pDest;
337 maGrfObj = aGraphic;
338 if( maGrfObj.GetType() != GRAPHIC_NONE )
340 delete mpOStm, mpOStm = NULL;
341 delete mpTmp, mpTmp = NULL;
345 return maGrfObj;
348 SvXMLGraphicHelper::SvXMLGraphicHelper( SvXMLGraphicHelperMode eCreateMode ) :
349 ::cppu::WeakComponentImplHelper2< ::com::sun::star::document::XGraphicObjectResolver,
350 ::com::sun::star::document::XBinaryStreamResolver >( maMutex )
352 Init( NULL, eCreateMode, sal_False );
355 SvXMLGraphicHelper::SvXMLGraphicHelper() :
356 ::cppu::WeakComponentImplHelper2< ::com::sun::star::document::XGraphicObjectResolver,
357 ::com::sun::star::document::XBinaryStreamResolver >( maMutex )
361 SvXMLGraphicHelper::~SvXMLGraphicHelper()
365 void SAL_CALL SvXMLGraphicHelper::disposing()
369 sal_Bool SvXMLGraphicHelper::ImplGetStreamNames( const OUString& rURLStr,
370 OUString& rPictureStorageName,
371 OUString& rPictureStreamName )
373 String aURLStr( rURLStr );
374 sal_Bool bRet = sal_False;
376 if( aURLStr.Len() )
378 aURLStr = aURLStr.GetToken( comphelper::string::getTokenCount(aURLStr, ':') - 1, ':' );
380 const sal_uInt32 nTokenCount = comphelper::string::getTokenCount(aURLStr, '/');
382 if( 1 == nTokenCount )
384 rPictureStorageName = String( XML_GRAPHICSTORAGE_NAME );
385 rPictureStreamName = aURLStr;
387 else
388 SvXMLEmbeddedObjectHelper::splitObjectURL(aURLStr, rPictureStorageName, rPictureStreamName);
390 bRet = !rPictureStreamName.isEmpty();
391 SAL_WARN_IF(!bRet, "svx", "SvXMLGraphicHelper::ImplInsertGraphicURL: invalid scheme: " << rURLStr);
394 return bRet;
397 uno::Reference < embed::XStorage > SvXMLGraphicHelper::ImplGetGraphicStorage( const OUString& rStorageName )
399 uno::Reference < embed::XStorage > xRetStorage;
400 if( mxRootStorage.is() )
404 xRetStorage = mxRootStorage->openStorageElement(
405 maCurStorageName = rStorageName,
406 ( GRAPHICHELPER_MODE_WRITE == meCreateMode )
407 ? embed::ElementModes::READWRITE
408 : embed::ElementModes::READ );
410 catch ( uno::Exception& )
413 //#i43196# try again to open the storage element - this time readonly
414 if(!xRetStorage.is())
418 xRetStorage = mxRootStorage->openStorageElement( maCurStorageName = rStorageName, embed::ElementModes::READ );
420 catch ( uno::Exception& )
426 return xRetStorage;
429 SvxGraphicHelperStream_Impl SvXMLGraphicHelper::ImplGetGraphicStream( const OUString& rPictureStorageName,
430 const OUString& rPictureStreamName,
431 sal_Bool bTruncate )
433 SvxGraphicHelperStream_Impl aRet;
434 aRet.xStorage = ImplGetGraphicStorage( rPictureStorageName );
436 if( aRet.xStorage.is() )
438 sal_Int32 nMode = embed::ElementModes::READ;
439 if ( GRAPHICHELPER_MODE_WRITE == meCreateMode )
441 nMode = embed::ElementModes::READWRITE;
442 if ( bTruncate )
443 nMode |= embed::ElementModes::TRUNCATE;
446 aRet.xStream = aRet.xStorage->openStreamElement( rPictureStreamName, nMode );
447 if( aRet.xStream.is() && ( GRAPHICHELPER_MODE_WRITE == meCreateMode ) )
449 OUString aPropName( "UseCommonStoragePasswordEncryption" );
450 uno::Reference < beans::XPropertySet > xProps( aRet.xStream, uno::UNO_QUERY );
451 xProps->setPropertyValue( aPropName, uno::makeAny( sal_True) );
455 return aRet;
458 String SvXMLGraphicHelper::ImplGetGraphicMimeType( const String& rFileName ) const
460 struct XMLGraphicMimeTypeMapper
462 const char* pExt;
463 const char* pMimeType;
466 static XMLGraphicMimeTypeMapper aMapper[] =
468 { "gif", "image/gif" },
469 { "png", "image/png" },
470 { "jpg", "image/jpeg" },
471 { "tif", "image/tiff" },
472 { "svg", "image/svg+xml" }
475 String aMimeType;
477 if( ( rFileName.Len() >= 4 ) && ( rFileName.GetChar( rFileName.Len() - 4 ) == '.' ) )
479 const OString aExt(OUStringToOString(rFileName.Copy(rFileName.Len() - 3),
480 RTL_TEXTENCODING_ASCII_US));
482 for( long i = 0, nCount = sizeof (aMapper) / sizeof (aMapper[0]); ( i < nCount ) && !aMimeType.Len(); i++ )
483 if( aExt.getStr() == aMapper[ i ].pExt )
484 aMimeType = String( aMapper[ i ].pMimeType, RTL_TEXTENCODING_ASCII_US );
487 return aMimeType;
490 Graphic SvXMLGraphicHelper::ImplReadGraphic( const OUString& rPictureStorageName,
491 const OUString& rPictureStreamName )
493 Graphic aGraphic;
494 SvxGraphicHelperStream_Impl aStream( ImplGetGraphicStream( rPictureStorageName, rPictureStreamName, sal_False ) );
495 if( aStream.xStream.is() )
497 SvStream* pStream = utl::UcbStreamHelper::CreateStream( aStream.xStream );
498 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic, String(), *pStream );
499 delete pStream;
502 return aGraphic;
505 sal_Bool SvXMLGraphicHelper::ImplWriteGraphic( const OUString& rPictureStorageName,
506 const OUString& rPictureStreamName,
507 const OUString& rGraphicId,
508 bool bUseGfxLink )
510 GraphicObject aGrfObject( OUStringToOString(rGraphicId, RTL_TEXTENCODING_ASCII_US) );
511 sal_Bool bRet = sal_False;
513 if( aGrfObject.GetType() != GRAPHIC_NONE )
515 SvxGraphicHelperStream_Impl aStream( ImplGetGraphicStream( rPictureStorageName, rPictureStreamName, sal_False ) );
516 if( aStream.xStream.is() )
518 Graphic aGraphic( (Graphic&) aGrfObject.GetGraphic() );
519 const GfxLink aGfxLink( aGraphic.GetLink() );
520 const OUString aMimeType( ImplGetGraphicMimeType( rPictureStreamName ) );
521 uno::Any aAny;
522 uno::Reference < beans::XPropertySet > xProps( aStream.xStream, uno::UNO_QUERY );
524 // set stream properties (MediaType/Compression)
525 if( !aMimeType.isEmpty() )
527 aAny <<= aMimeType;
528 xProps->setPropertyValue( String( "MediaType" ), aAny );
531 const sal_Bool bCompressed = aMimeType.isEmpty() || aMimeType == "image/tiff";
532 aAny <<= bCompressed;
533 xProps->setPropertyValue( String( "Compressed" ), aAny );
535 SvStream* pStream = utl::UcbStreamHelper::CreateStream( aStream.xStream );
536 if( bUseGfxLink && aGfxLink.GetDataSize() && aGfxLink.GetData() )
537 pStream->Write( aGfxLink.GetData(), aGfxLink.GetDataSize() );
538 else
540 if( aGraphic.GetType() == GRAPHIC_BITMAP )
542 GraphicFilter &rFilter = GraphicFilter::GetGraphicFilter();
543 String aFormat;
545 if( aGraphic.IsAnimated() )
546 aFormat = String( "gif" );
547 else
548 aFormat = String( "png" );
550 bRet = ( rFilter.ExportGraphic( aGraphic, String(), *pStream,
551 rFilter.GetExportFormatNumberForShortName( aFormat ) ) == 0 );
553 else if( aGraphic.GetType() == GRAPHIC_GDIMETAFILE )
555 pStream->SetVersion( SOFFICE_FILEFORMAT_8 );
556 pStream->SetCompressMode( COMPRESSMODE_ZBITMAP );
558 // SJ: first check if this metafile is just a eps file, then we will store the eps instead of svm
559 GDIMetaFile& rMtf( (GDIMetaFile&)aGraphic.GetGDIMetaFile() );
560 const MetaCommentAction* pComment = ImplCheckForEPS( rMtf );
561 if ( pComment )
563 sal_uInt32 nSize = pComment->GetDataSize();
564 const sal_uInt8* pData = pComment->GetData();
565 if ( nSize && pData )
566 pStream->Write( pData, nSize );
568 const MetaEPSAction* pAct = ( (const MetaEPSAction*)rMtf.FirstAction() );
569 const GfxLink& rLink = pAct->GetLink();
571 pStream->Write( rLink.GetData(), rLink.GetDataSize() );
573 else
574 rMtf.Write( *pStream );
576 bRet = ( pStream->GetError() == 0 );
579 uno::Reference < embed::XTransactedObject > xStorage(
580 aStream.xStorage, uno::UNO_QUERY);
581 delete pStream;
582 aStream.xStream->getOutputStream()->closeOutput();
583 if( xStorage.is() )
584 xStorage->commit();
588 return bRet;
591 void SvXMLGraphicHelper::ImplInsertGraphicURL( const OUString& rURLStr, sal_uInt32 nInsertPos, OUString& rRequestedFileName )
593 OUString aURLString( rURLStr );
594 OUString aPictureStorageName, aPictureStreamName;
595 if( ( maURLSet.find( aURLString ) != maURLSet.end() ) )
597 for (URLPairVector::const_iterator aIter( maGrfURLs.begin() ), aEnd( maGrfURLs.end() ); aIter != aEnd ; ++aIter)
599 if( aURLString == (*aIter).first )
601 maGrfURLs[ nInsertPos ].second = (*aIter).second;
602 break;
606 else if( ImplGetStreamNames( aURLString, aPictureStorageName, aPictureStreamName ) )
608 URLPair& rURLPair = maGrfURLs[ nInsertPos ];
610 if( GRAPHICHELPER_MODE_READ == meCreateMode )
612 const GraphicObject aObj( ImplReadGraphic( aPictureStorageName, aPictureStreamName ) );
614 if( aObj.GetType() != GRAPHIC_NONE )
616 maGrfObjs.push_back( aObj );
617 OUString aBaseURL( XML_GRAPHICOBJECT_URL_BASE );
619 rURLPair.second = aBaseURL;
620 rURLPair.second += OStringToOUString(aObj.GetUniqueID(),
621 RTL_TEXTENCODING_ASCII_US);
623 else
624 rURLPair.second = String();
626 else
628 const String aGraphicObjectId( aPictureStreamName );
629 const OString aAsciiObjectID(OUStringToOString(aGraphicObjectId, RTL_TEXTENCODING_ASCII_US));
630 const GraphicObject aGrfObject( aAsciiObjectID );
631 if( aGrfObject.GetType() != GRAPHIC_NONE )
633 String aStreamName( aGraphicObjectId );
634 Graphic aGraphic( (Graphic&) aGrfObject.GetGraphic() );
635 const GfxLink aGfxLink( aGraphic.GetLink() );
636 String aExtension;
637 bool bUseGfxLink( true );
639 if( aGfxLink.GetDataSize() )
641 switch( aGfxLink.GetType() )
643 case( GFX_LINK_TYPE_EPS_BUFFER ): aExtension = String( ".eps" ); break;
644 case( GFX_LINK_TYPE_NATIVE_GIF ): aExtension = String( ".gif" ); break;
645 case( GFX_LINK_TYPE_NATIVE_JPG ): aExtension = String( ".jpg" ); break;
646 case( GFX_LINK_TYPE_NATIVE_PNG ): aExtension = String( ".png" ); break;
647 case( GFX_LINK_TYPE_NATIVE_TIF ): aExtension = String( ".tif" ); break;
648 case( GFX_LINK_TYPE_NATIVE_WMF ): aExtension = String( ".wmf" ); break;
649 case( GFX_LINK_TYPE_NATIVE_MET ): aExtension = String( ".met" ); break;
650 case( GFX_LINK_TYPE_NATIVE_PCT ): aExtension = String( ".pct" ); break;
651 case( GFX_LINK_TYPE_NATIVE_SVG ):
652 // backward-compat kludge: since no released OOo
653 // version to date can handle svg properly, wrap it up
654 // into an svm. slight catch22 here, since strict ODF
655 // conformance _recommends_ svg - then again, most old
656 // ODF consumers are believed to be OOo
657 if( SvtSaveOptions().GetODFDefaultVersion() <= SvtSaveOptions::ODFVER_012 )
659 bUseGfxLink = false;
660 aExtension = String( ".svm" );
662 else
663 aExtension = String( ".svg" );
664 break;
666 default:
667 aExtension = String( ".grf" );
668 break;
671 else
673 if( aGrfObject.GetType() == GRAPHIC_BITMAP )
675 if( aGrfObject.IsAnimated() )
676 aExtension = String( ".gif" );
677 else
678 aExtension = String( ".png" );
680 else if( aGrfObject.GetType() == GRAPHIC_GDIMETAFILE )
682 // SJ: first check if this metafile is just a eps file, then we will store the eps instead of svm
683 GDIMetaFile& rMtf( (GDIMetaFile&)aGraphic.GetGDIMetaFile() );
684 if ( ImplCheckForEPS( rMtf ) )
685 aExtension = String( ".eps" );
686 else
687 aExtension = String( ".svm" );
691 OUString aURLEntry;
692 const String sPictures( "Pictures/" );
694 if ( !rRequestedFileName.isEmpty() )
696 aURLEntry = sPictures;
697 aURLEntry += rRequestedFileName;
698 aURLEntry += aExtension;
700 URLPairVector::const_iterator aIter( maGrfURLs.begin() ), aEnd( maGrfURLs.end() );
701 for ( ; aIter != aEnd; ++aIter )
703 if( aURLEntry == (*aIter).second )
704 break;
706 if ( aIter == aEnd )
707 aStreamName = rRequestedFileName;
710 aStreamName += aExtension;
712 if( mbDirect && aStreamName.Len() )
713 ImplWriteGraphic( aPictureStorageName, aStreamName, aGraphicObjectId, bUseGfxLink );
715 rURLPair.second = sPictures;
716 rURLPair.second += aStreamName;
718 #if OSL_DEBUG_LEVEL > 0
719 else
721 OStringBuffer sMessage(
722 RTL_CONSTASCII_STRINGPARAM("graphic object with ID '"));
723 sMessage.append(aAsciiObjectID).
724 append(RTL_CONSTASCII_STRINGPARAM("' has an unknown type"));
725 OSL_ENSURE( false, sMessage.getStr() );
727 #endif
730 maURLSet.insert( aURLString );
734 void SvXMLGraphicHelper::Init( const uno::Reference < embed::XStorage >& rXMLStorage,
735 SvXMLGraphicHelperMode eCreateMode,
736 sal_Bool bDirect )
738 mxRootStorage = rXMLStorage;
739 meCreateMode = eCreateMode;
740 mbDirect = ( ( GRAPHICHELPER_MODE_READ == meCreateMode ) ? bDirect : sal_True );
743 SvXMLGraphicHelper* SvXMLGraphicHelper::Create( const uno::Reference < embed::XStorage >& rXMLStorage,
744 SvXMLGraphicHelperMode eCreateMode,
745 sal_Bool bDirect )
747 SvXMLGraphicHelper* pThis = new SvXMLGraphicHelper;
749 pThis->acquire();
750 pThis->Init( rXMLStorage, eCreateMode, bDirect );
752 return pThis;
755 SvXMLGraphicHelper* SvXMLGraphicHelper::Create( SvXMLGraphicHelperMode eCreateMode )
757 SvXMLGraphicHelper* pThis = new SvXMLGraphicHelper;
759 pThis->acquire();
760 pThis->Init( NULL, eCreateMode, sal_False );
762 return pThis;
765 void SvXMLGraphicHelper::Destroy( SvXMLGraphicHelper* pSvXMLGraphicHelper )
767 if( pSvXMLGraphicHelper )
769 pSvXMLGraphicHelper->dispose();
770 pSvXMLGraphicHelper->release();
774 // XGraphicObjectResolver
775 OUString SAL_CALL SvXMLGraphicHelper::resolveGraphicObjectURL( const OUString& rURL )
776 throw(uno::RuntimeException)
778 ::osl::MutexGuard aGuard( maMutex );
779 const sal_Int32 nIndex = maGrfURLs.size();
781 OUString aURL( rURL );
782 OUString aUserData;
783 OUString aRequestedFileName;
785 sal_Int32 nUser = rURL.indexOf( '?', 0 );
786 if ( nUser >= 0 )
788 aURL = OUString( rURL.copy( 0, nUser ) );
789 nUser++;
790 aUserData = rURL.copy( nUser, rURL.getLength() - nUser );
792 if ( !aUserData.isEmpty() )
794 sal_Int32 nIndex2 = 0;
797 OUString aToken = aUserData.getToken( 0, ';', nIndex2 );
798 sal_Int32 n = aToken.indexOf( '=' );
799 if ( ( n > 0 ) && ( ( n + 1 ) < aToken.getLength() ) )
801 OUString aParam( aToken.copy( 0, n ) );
802 OUString aValue( aToken.copy( n + 1, aToken.getLength() - ( n + 1 ) ) );
804 const OUString sRequestedName( "requestedName" );
805 if ( aParam.match( sRequestedName ) )
806 aRequestedFileName = aValue;
809 while ( nIndex2 >= 0 );
812 maGrfURLs.push_back( ::std::make_pair( aURL, OUString() ) );
813 ImplInsertGraphicURL( aURL, nIndex, aRequestedFileName );
815 return maGrfURLs[ nIndex ].second;
818 // XBinaryStreamResolver
819 Reference< XInputStream > SAL_CALL SvXMLGraphicHelper::getInputStream( const OUString& rURL )
820 throw( RuntimeException )
822 Reference< XInputStream > xRet;
823 OUString aPictureStorageName, aGraphicId;
826 if( ( GRAPHICHELPER_MODE_WRITE == meCreateMode ) &&
827 ImplGetStreamNames( rURL, aPictureStorageName, aGraphicId ) )
829 SvXMLGraphicInputStream* pInputStream = new SvXMLGraphicInputStream( aGraphicId );
831 if( pInputStream->Exists() )
832 xRet = pInputStream;
833 else
834 delete pInputStream;
837 return xRet;
840 Reference< XOutputStream > SAL_CALL SvXMLGraphicHelper::createOutputStream()
841 throw( RuntimeException )
843 Reference< XOutputStream > xRet;
845 if( GRAPHICHELPER_MODE_READ == meCreateMode )
847 SvXMLGraphicOutputStream* pOutputStream = new SvXMLGraphicOutputStream;
849 if( pOutputStream->Exists() )
850 maGrfStms.push_back( xRet = pOutputStream );
851 else
852 delete pOutputStream;
855 return xRet;
858 OUString SAL_CALL SvXMLGraphicHelper::resolveOutputStream( const Reference< XOutputStream >& rxBinaryStream )
859 throw( RuntimeException )
861 OUString aRet;
863 if( ( GRAPHICHELPER_MODE_READ == meCreateMode ) && rxBinaryStream.is() )
865 if( ::std::find( maGrfStms.begin(), maGrfStms.end(), rxBinaryStream ) != maGrfStms.end() )
867 SvXMLGraphicOutputStream* pOStm = static_cast< SvXMLGraphicOutputStream* >( rxBinaryStream.get() );
869 if( pOStm )
871 const GraphicObject& rGrfObj = pOStm->GetGraphicObject();
872 const OUString aId(OStringToOUString(
873 rGrfObj.GetUniqueID(), RTL_TEXTENCODING_ASCII_US));
875 if( !aId.isEmpty() )
877 aRet = OUString( XML_GRAPHICOBJECT_URL_BASE );
878 aRet += aId;
884 return aRet;
887 // for instantiation via service manager
888 namespace svx
891 namespace impl
893 typedef ::cppu::WeakComponentImplHelper4<
894 lang::XInitialization,
895 document::XGraphicObjectResolver,
896 document::XBinaryStreamResolver,
897 lang::XServiceInfo >
898 SvXMLGraphicImportExportHelper_Base;
899 class MutexContainer
901 public:
902 virtual ~MutexContainer();
904 protected:
905 mutable ::osl::Mutex m_aMutex;
907 MutexContainer::~MutexContainer()
909 } // namespace impl
911 class SvXMLGraphicImportExportHelper :
912 public impl::MutexContainer,
913 public impl::SvXMLGraphicImportExportHelper_Base
915 public:
916 SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode );
918 protected:
919 // is called from WeakComponentImplHelper when XComponent::dispose() was
920 // called from outside
921 virtual void SAL_CALL disposing();
923 // ____ XInitialization ____
924 // one argument is allowed, which is the XStorage
925 virtual void SAL_CALL initialize( const Sequence< Any >& aArguments )
926 throw (Exception,
927 RuntimeException);
929 // ____ XGraphicObjectResolver ____
930 virtual OUString SAL_CALL resolveGraphicObjectURL( const OUString& aURL )
931 throw (RuntimeException);
933 // ____ XBinaryStreamResolver ____
934 virtual Reference< io::XInputStream > SAL_CALL getInputStream( const OUString& aURL )
935 throw (RuntimeException);
936 virtual Reference< io::XOutputStream > SAL_CALL createOutputStream()
937 throw (RuntimeException);
938 virtual OUString SAL_CALL resolveOutputStream( const Reference< io::XOutputStream >& aBinaryStream )
939 throw (RuntimeException);
941 // ____ XServiceInfo ____
942 virtual OUString SAL_CALL getImplementationName()
943 throw (RuntimeException);
944 virtual ::sal_Bool SAL_CALL supportsService( const OUString& ServiceName )
945 throw (RuntimeException);
946 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames()
947 throw (RuntimeException);
949 private:
950 SvXMLGraphicHelperMode m_eGraphicHelperMode;
951 Reference< XGraphicObjectResolver > m_xGraphicObjectResolver;
952 Reference< XBinaryStreamResolver > m_xBinaryStreamResolver;
955 SvXMLGraphicImportExportHelper::SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode ) :
956 impl::SvXMLGraphicImportExportHelper_Base( m_aMutex ),
957 m_eGraphicHelperMode( eMode )
960 void SAL_CALL SvXMLGraphicImportExportHelper::disposing()
962 Reference< XComponent > xComp( m_xGraphicObjectResolver, UNO_QUERY );
963 OSL_ASSERT( xComp.is());
964 if( xComp.is())
965 xComp->dispose();
966 // m_xBinaryStreamResolver is a reference to the same object => don't call
967 // dispose() again
970 // ____ XInitialization ____
971 void SAL_CALL SvXMLGraphicImportExportHelper::initialize(
972 const Sequence< Any >& aArguments )
973 throw (Exception, RuntimeException)
975 Reference< embed::XStorage > xStorage;
976 if( aArguments.getLength() > 0 )
977 aArguments[0] >>= xStorage;
979 SvXMLGraphicHelper * pHelper( SvXMLGraphicHelper::Create( xStorage, m_eGraphicHelperMode ));
980 m_xGraphicObjectResolver.set( pHelper );
981 m_xBinaryStreamResolver.set( pHelper );
982 // SvXMLGraphicHelper::Create calls acquire. Since we have two references
983 // now it is safe (and necessary) to undo this acquire
984 pHelper->release();
987 // ____ XGraphicObjectResolver ____
988 OUString SAL_CALL SvXMLGraphicImportExportHelper::resolveGraphicObjectURL( const OUString& aURL )
989 throw (uno::RuntimeException)
991 return m_xGraphicObjectResolver->resolveGraphicObjectURL( aURL );
995 // ____ XBinaryStreamResolver ____
996 Reference< io::XInputStream > SAL_CALL SvXMLGraphicImportExportHelper::getInputStream( const OUString& aURL )
997 throw (uno::RuntimeException)
999 return m_xBinaryStreamResolver->getInputStream( aURL );
1001 Reference< io::XOutputStream > SAL_CALL SvXMLGraphicImportExportHelper::createOutputStream()
1002 throw (uno::RuntimeException)
1004 return m_xBinaryStreamResolver->createOutputStream();
1006 OUString SAL_CALL SvXMLGraphicImportExportHelper::resolveOutputStream( const Reference< io::XOutputStream >& aBinaryStream )
1007 throw (uno::RuntimeException)
1009 return m_xBinaryStreamResolver->resolveOutputStream( aBinaryStream );
1012 // ____ XServiceInfo ____
1013 OUString SAL_CALL SvXMLGraphicImportExportHelper::getImplementationName()
1014 throw (uno::RuntimeException)
1016 if( m_eGraphicHelperMode == GRAPHICHELPER_MODE_READ )
1017 return SvXMLGraphicImportHelper_getImplementationName();
1018 return SvXMLGraphicExportHelper_getImplementationName();
1020 ::sal_Bool SAL_CALL SvXMLGraphicImportExportHelper::supportsService( const OUString& ServiceName )
1021 throw (uno::RuntimeException)
1023 Sequence< OUString > aServiceNames( getSupportedServiceNames());
1024 const OUString * pBegin = aServiceNames.getConstArray();
1025 const OUString * pEnd = pBegin + aServiceNames.getLength();
1026 return (::std::find( pBegin, pEnd, ServiceName ) != pEnd);
1028 Sequence< OUString > SAL_CALL SvXMLGraphicImportExportHelper::getSupportedServiceNames()
1029 throw (uno::RuntimeException)
1031 if( m_eGraphicHelperMode == GRAPHICHELPER_MODE_READ )
1032 return SvXMLGraphicImportHelper_getSupportedServiceNames();
1033 return SvXMLGraphicExportHelper_getSupportedServiceNames();
1036 // import
1037 Reference< XInterface > SAL_CALL SvXMLGraphicImportHelper_createInstance(const Reference< XMultiServiceFactory > & /* rSMgr */ )
1038 throw( Exception )
1040 return static_cast< XWeak* >( new SvXMLGraphicImportExportHelper( GRAPHICHELPER_MODE_READ ));
1042 OUString SAL_CALL SvXMLGraphicImportHelper_getImplementationName()
1043 throw()
1045 return OUString( "com.sun.star.comp.Svx.GraphicImportHelper" );
1047 Sequence< OUString > SAL_CALL SvXMLGraphicImportHelper_getSupportedServiceNames()
1048 throw()
1050 // XGraphicObjectResolver and XBinaryStreamResolver are not part of any service
1051 Sequence< OUString > aSupportedServiceNames( 2 );
1052 aSupportedServiceNames[0] = OUString( "com.sun.star.document.GraphicObjectResolver" );
1053 aSupportedServiceNames[1] = OUString( "com.sun.star.document.BinaryStreamResolver" );
1054 return aSupportedServiceNames;
1057 // export
1058 Reference< XInterface > SAL_CALL SvXMLGraphicExportHelper_createInstance(const Reference< XMultiServiceFactory > & /* rSMgr */ )
1059 throw( Exception )
1061 return static_cast< XWeak* >( new SvXMLGraphicImportExportHelper( GRAPHICHELPER_MODE_WRITE ));
1063 OUString SAL_CALL SvXMLGraphicExportHelper_getImplementationName()
1064 throw()
1066 return OUString( "com.sun.star.comp.Svx.GraphicExportHelper" );
1068 Sequence< OUString > SAL_CALL SvXMLGraphicExportHelper_getSupportedServiceNames()
1069 throw()
1071 // XGraphicObjectResolver and XBinaryStreamResolver are not part of any service
1072 Sequence< OUString > aSupportedServiceNames( 2 );
1073 aSupportedServiceNames[0] = OUString( "com.sun.star.document.GraphicObjectResolver" );
1074 aSupportedServiceNames[1] = OUString( "com.sun.star.document.BinaryStreamResolver" );
1075 return aSupportedServiceNames;
1078 } // namespace svx
1080 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */