lok: Don't attempt to select the exact text after a failed search.
[LibreOffice.git] / svx / source / xml / xmlgrhlp.cxx
blobdba2a919ce3df664928db2cb06fb4df11e9bb906
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 <sal/config.h>
22 #include <boost/noncopyable.hpp>
23 #include <comphelper/string.hxx>
24 #include <sal/macros.h>
25 #include <com/sun/star/embed/XTransactedObject.hpp>
26 #include <com/sun/star/embed/ElementModes.hpp>
27 #include <com/sun/star/beans/XPropertySet.hpp>
28 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
29 #include <com/sun/star/lang/XServiceInfo.hpp>
30 #include <com/sun/star/lang/XInitialization.hpp>
31 #include <cppuhelper/compbase4.hxx>
32 #include <cppuhelper/supportsservice.hxx>
34 #include <rtl/ref.hxx>
35 #include <unotools/ucbstreamhelper.hxx>
36 #include <unotools/streamwrap.hxx>
37 #include <unotools/tempfile.hxx>
38 #include <unotools/saveopt.hxx>
39 #include <vcl/cvtgrf.hxx>
40 #include <vcl/gfxlink.hxx>
41 #include <vcl/metaact.hxx>
42 #include <tools/zcodec.hxx>
44 #include <vcl/graphicfilter.hxx>
45 #include "svx/xmlgrhlp.hxx"
46 #include "svx/xmleohlp.hxx"
48 #include <algorithm>
49 #include <boost/scoped_ptr.hpp>
51 using namespace com::sun::star;
52 using namespace com::sun::star::uno;
53 using namespace com::sun::star::io;
55 using ::com::sun::star::lang::XMultiServiceFactory;
57 #define XML_GRAPHICSTORAGE_NAME "Pictures"
58 #define XML_GRAPHICOBJECT_URL_BASE "vnd.sun.star.GraphicObject:"
60 namespace {
62 const MetaCommentAction* ImplCheckForEPS( GDIMetaFile& rMtf )
64 const MetaCommentAction* pComment = NULL;
66 if ( rMtf.GetActionSize() >= 2
67 && rMtf.GetAction(0)->GetType() == MetaActionType::EPS
68 && rMtf.GetAction(1)->GetType() == MetaActionType::COMMENT
69 && ( static_cast<const MetaCommentAction*>(rMtf.GetAction( 1 ))->GetComment() == "EPSReplacementGraphic" ) )
70 pComment = static_cast<const MetaCommentAction*>(rMtf.GetAction( 1 ));
72 return pComment;
75 class SvXMLGraphicInputStream:
76 public cppu::WeakImplHelper1<XInputStream>, private boost::noncopyable
78 private:
80 virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) throw(NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception) SAL_OVERRIDE;
81 virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) throw(NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception) SAL_OVERRIDE;
82 virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) throw(NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception) SAL_OVERRIDE;
83 virtual sal_Int32 SAL_CALL available() throw(NotConnectedException, RuntimeException, std::exception) SAL_OVERRIDE;
84 virtual void SAL_CALL closeInput() throw(NotConnectedException, RuntimeException, std::exception) SAL_OVERRIDE;
86 private:
88 ::utl::TempFile maTmp;
89 Reference< XInputStream > mxStmWrapper;
91 public:
93 SvXMLGraphicInputStream( const OUString& rGraphicId );
94 virtual ~SvXMLGraphicInputStream();
96 bool Exists() const { return mxStmWrapper.is(); }
99 SvXMLGraphicInputStream::SvXMLGraphicInputStream( const OUString& rGraphicId )
101 GraphicObject aGrfObject( OUStringToOString(rGraphicId, RTL_TEXTENCODING_ASCII_US) );
103 maTmp.EnableKillingFile();
105 if( aGrfObject.GetType() != GRAPHIC_NONE )
107 SvStream* pStm = ::utl::UcbStreamHelper::CreateStream( maTmp.GetURL(), StreamMode::WRITE | StreamMode::TRUNC );
109 if( pStm )
111 Graphic aGraphic( (Graphic&) aGrfObject.GetGraphic() );
112 const GfxLink aGfxLink( aGraphic.GetLink() );
113 bool bRet = false;
115 if( aGfxLink.GetDataSize() && aGfxLink.GetData() )
117 pStm->Write( aGfxLink.GetData(), aGfxLink.GetDataSize() );
118 bRet = ( pStm->GetError() == 0 );
120 else
122 if( aGraphic.GetType() == GRAPHIC_BITMAP )
124 GraphicFilter &rFilter = GraphicFilter::GetGraphicFilter();
125 OUString aFormat;
127 if( aGraphic.IsAnimated() )
128 aFormat = "gif";
129 else
130 aFormat = "png";
132 bRet = ( rFilter.ExportGraphic( aGraphic, "", *pStm, rFilter.GetExportFormatNumberForShortName( aFormat ) ) == 0 );
134 else if( aGraphic.GetType() == GRAPHIC_GDIMETAFILE )
136 pStm->SetVersion( SOFFICE_FILEFORMAT_8 );
137 pStm->SetCompressMode( SvStreamCompressFlags::ZBITMAP );
138 ( (GDIMetaFile&) aGraphic.GetGDIMetaFile() ).Write( *pStm );
139 bRet = ( pStm->GetError() == 0 );
143 if( bRet )
145 pStm->Seek( 0 );
146 mxStmWrapper = new ::utl::OInputStreamWrapper( pStm, true );
148 else
149 delete pStm;
154 SvXMLGraphicInputStream::~SvXMLGraphicInputStream()
158 sal_Int32 SAL_CALL SvXMLGraphicInputStream::readBytes( Sequence< sal_Int8 >& rData, sal_Int32 nBytesToRead )
159 throw( NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception )
161 if( !mxStmWrapper.is() )
162 throw NotConnectedException();
164 return mxStmWrapper->readBytes( rData, nBytesToRead );
167 sal_Int32 SAL_CALL SvXMLGraphicInputStream::readSomeBytes( Sequence< sal_Int8 >& rData, sal_Int32 nMaxBytesToRead )
168 throw( NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception )
170 if( !mxStmWrapper.is() )
171 throw NotConnectedException() ;
173 return mxStmWrapper->readSomeBytes( rData, nMaxBytesToRead );
176 void SAL_CALL SvXMLGraphicInputStream::skipBytes( sal_Int32 nBytesToSkip )
177 throw( NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception )
179 if( !mxStmWrapper.is() )
180 throw NotConnectedException() ;
182 mxStmWrapper->skipBytes( nBytesToSkip );
185 sal_Int32 SAL_CALL SvXMLGraphicInputStream::available() throw( NotConnectedException, RuntimeException, std::exception )
187 if( !mxStmWrapper.is() )
188 throw NotConnectedException() ;
190 return mxStmWrapper->available();
193 void SAL_CALL SvXMLGraphicInputStream::closeInput() throw( NotConnectedException, RuntimeException, std::exception )
195 if( !mxStmWrapper.is() )
196 throw NotConnectedException() ;
198 mxStmWrapper->closeInput();
201 class SvXMLGraphicOutputStream:
202 public cppu::WeakImplHelper1<XOutputStream>, private boost::noncopyable
204 private:
206 // XOutputStream
207 virtual void SAL_CALL writeBytes( const Sequence< sal_Int8 >& rData ) throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception ) SAL_OVERRIDE;
208 virtual void SAL_CALL flush() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception ) SAL_OVERRIDE;
209 virtual void SAL_CALL closeOutput() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception ) SAL_OVERRIDE;
211 private:
213 ::utl::TempFile* mpTmp;
214 SvStream* mpOStm;
215 Reference< XOutputStream > mxStmWrapper;
216 GraphicObject maGrfObj;
217 bool mbClosed;
219 public:
221 SvXMLGraphicOutputStream();
222 virtual ~SvXMLGraphicOutputStream();
224 bool Exists() const { return mxStmWrapper.is(); }
225 const GraphicObject& GetGraphicObject();
228 SvXMLGraphicOutputStream::SvXMLGraphicOutputStream() :
229 mpTmp( new ::utl::TempFile ),
230 mbClosed( false )
232 mpTmp->EnableKillingFile();
234 mpOStm = ::utl::UcbStreamHelper::CreateStream( mpTmp->GetURL(), StreamMode::WRITE | StreamMode::TRUNC );
236 if( mpOStm )
237 mxStmWrapper = new ::utl::OOutputStreamWrapper( *mpOStm );
240 SvXMLGraphicOutputStream::~SvXMLGraphicOutputStream()
242 delete mpTmp;
243 delete mpOStm;
246 void SAL_CALL SvXMLGraphicOutputStream::writeBytes( const Sequence< sal_Int8 >& rData )
247 throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception )
249 if( !mxStmWrapper.is() )
250 throw NotConnectedException() ;
252 mxStmWrapper->writeBytes( rData );
255 void SAL_CALL SvXMLGraphicOutputStream::flush()
256 throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception )
258 if( !mxStmWrapper.is() )
259 throw NotConnectedException() ;
261 mxStmWrapper->flush();
264 void SAL_CALL SvXMLGraphicOutputStream::closeOutput()
265 throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception )
267 if( !mxStmWrapper.is() )
268 throw NotConnectedException() ;
270 mxStmWrapper->closeOutput();
271 mxStmWrapper.clear();
273 mbClosed = true;
276 const GraphicObject& SvXMLGraphicOutputStream::GetGraphicObject()
278 if( mbClosed && ( maGrfObj.GetType() == GRAPHIC_NONE ) && mpOStm )
280 Graphic aGraphic;
282 mpOStm->Seek( 0 );
283 sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW;
284 sal_uInt16 pDeterminedFormat = GRFILTER_FORMAT_DONTKNOW;
285 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic, "", *mpOStm ,nFormat,&pDeterminedFormat );
287 if (pDeterminedFormat == GRFILTER_FORMAT_DONTKNOW)
289 //Read the first two byte to check whether it is a gzipped stream, is so it may be in wmz or emz format
290 //unzip them and try again
292 sal_uInt8 sFirstBytes[ 2 ];
294 mpOStm->Seek( STREAM_SEEK_TO_END );
295 sal_uIntPtr nStreamLen = mpOStm->Tell();
296 mpOStm->Seek( 0 );
298 if ( !nStreamLen )
300 SvLockBytes* pLockBytes = mpOStm->GetLockBytes();
301 if ( pLockBytes )
302 pLockBytes->SetSynchronMode( true );
304 mpOStm->Seek( STREAM_SEEK_TO_END );
305 nStreamLen = mpOStm->Tell();
306 mpOStm->Seek( 0 );
308 if( nStreamLen >= 2 )
310 //read two byte
311 mpOStm->Read( sFirstBytes, 2 );
313 if( sFirstBytes[0] == 0x1f && sFirstBytes[1] == 0x8b )
315 boost::scoped_ptr<SvMemoryStream> pDest(new SvMemoryStream);
316 ZCodec aZCodec( 0x8000, 0x8000 );
317 aZCodec.BeginCompression(ZCODEC_DEFAULT_COMPRESSION, false, true);
318 mpOStm->Seek( 0 );
319 aZCodec.Decompress( *mpOStm, *pDest );
321 if (aZCodec.EndCompression() && pDest )
323 pDest->Seek( STREAM_SEEK_TO_END );
324 sal_uIntPtr nStreamLen_ = pDest->Tell();
325 if (nStreamLen_)
327 pDest->Seek(0L);
328 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic, "", *pDest ,nFormat,&pDeterminedFormat );
335 maGrfObj = aGraphic;
336 if( maGrfObj.GetType() != GRAPHIC_NONE )
338 delete mpOStm, mpOStm = NULL;
339 delete mpTmp, mpTmp = NULL;
343 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, false );
355 SvXMLGraphicHelper::SvXMLGraphicHelper()
356 : ::cppu::WeakComponentImplHelper2< ::com::sun::star::document::XGraphicObjectResolver,
357 ::com::sun::star::document::XBinaryStreamResolver >( maMutex )
358 , meCreateMode(GRAPHICHELPER_MODE_READ)
359 , mbDirect(false)
363 SvXMLGraphicHelper::~SvXMLGraphicHelper()
367 void SAL_CALL SvXMLGraphicHelper::disposing()
371 bool SvXMLGraphicHelper::ImplGetStreamNames( const OUString& rURLStr,
372 OUString& rPictureStorageName,
373 OUString& rPictureStreamName )
375 OUString aURLStr( rURLStr );
376 bool bRet = false;
378 if( !aURLStr.isEmpty() )
380 aURLStr = aURLStr.getToken( comphelper::string::getTokenCount(aURLStr, ':') - 1, ':' );
382 const sal_uInt32 nTokenCount = comphelper::string::getTokenCount(aURLStr, '/');
384 if( 1 == nTokenCount )
386 rPictureStorageName = XML_GRAPHICSTORAGE_NAME;
387 rPictureStreamName = aURLStr;
389 else
390 SvXMLEmbeddedObjectHelper::splitObjectURL(aURLStr, rPictureStorageName, rPictureStreamName);
392 bRet = !rPictureStreamName.isEmpty();
393 SAL_WARN_IF(!bRet, "svx", "SvXMLGraphicHelper::ImplInsertGraphicURL: invalid scheme: " << rURLStr);
396 return bRet;
399 uno::Reference < embed::XStorage > SvXMLGraphicHelper::ImplGetGraphicStorage( const OUString& rStorageName )
401 uno::Reference < embed::XStorage > xRetStorage;
402 if( mxRootStorage.is() )
406 xRetStorage = mxRootStorage->openStorageElement(
407 maCurStorageName = rStorageName,
408 ( GRAPHICHELPER_MODE_WRITE == meCreateMode )
409 ? embed::ElementModes::READWRITE
410 : embed::ElementModes::READ );
412 catch ( uno::Exception& )
415 //#i43196# try again to open the storage element - this time readonly
416 if(!xRetStorage.is())
420 xRetStorage = mxRootStorage->openStorageElement( maCurStorageName = rStorageName, embed::ElementModes::READ );
422 catch ( uno::Exception& )
428 return xRetStorage;
431 SvxGraphicHelperStream_Impl SvXMLGraphicHelper::ImplGetGraphicStream( const OUString& rPictureStorageName,
432 const OUString& rPictureStreamName,
433 bool bTruncate )
435 SvxGraphicHelperStream_Impl aRet;
436 aRet.xStorage = ImplGetGraphicStorage( rPictureStorageName );
438 if( aRet.xStorage.is() )
440 sal_Int32 nMode = embed::ElementModes::READ;
441 if ( GRAPHICHELPER_MODE_WRITE == meCreateMode )
443 nMode = embed::ElementModes::READWRITE;
444 if ( bTruncate )
445 nMode |= embed::ElementModes::TRUNCATE;
448 aRet.xStream = aRet.xStorage->openStreamElement( rPictureStreamName, nMode );
449 if( aRet.xStream.is() && ( GRAPHICHELPER_MODE_WRITE == meCreateMode ) )
451 OUString aPropName( "UseCommonStoragePasswordEncryption" );
452 uno::Reference < beans::XPropertySet > xProps( aRet.xStream, uno::UNO_QUERY );
453 xProps->setPropertyValue( aPropName, uno::makeAny( sal_True) );
457 return aRet;
460 OUString SvXMLGraphicHelper::ImplGetGraphicMimeType( const OUString& rFileName ) const
462 struct XMLGraphicMimeTypeMapper
464 const char* pExt;
465 const char* pMimeType;
468 static const XMLGraphicMimeTypeMapper aMapper[] =
470 { "gif", "image/gif" },
471 { "png", "image/png" },
472 { "jpg", "image/jpeg" },
473 { "tif", "image/tiff" },
474 { "svg", "image/svg+xml" }
477 OUString aMimeType;
479 if( ( rFileName.getLength() >= 4 ) && ( rFileName[ rFileName.getLength() - 4 ] == '.' ) )
481 const OString aExt(OUStringToOString(rFileName.copy(rFileName.getLength() - 3),
482 RTL_TEXTENCODING_ASCII_US));
484 for( long i = 0, nCount = sizeof (aMapper) / sizeof (aMapper[0]); ( i < nCount ) && aMimeType.isEmpty(); i++ )
485 if( strcmp(aExt.getStr(), aMapper[ i ].pExt) == 0 )
486 aMimeType = OUString( aMapper[ i ].pMimeType, strlen( aMapper[ i ].pMimeType ), RTL_TEXTENCODING_ASCII_US );
489 return aMimeType;
492 Graphic SvXMLGraphicHelper::ImplReadGraphic( const OUString& rPictureStorageName,
493 const OUString& rPictureStreamName )
495 Graphic aGraphic;
496 SvxGraphicHelperStream_Impl aStream( ImplGetGraphicStream( rPictureStorageName, rPictureStreamName, false ) );
497 if( aStream.xStream.is() )
499 boost::scoped_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream( aStream.xStream ));
500 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic, "", *pStream );
503 return aGraphic;
506 bool SvXMLGraphicHelper::ImplWriteGraphic( const OUString& rPictureStorageName,
507 const OUString& rPictureStreamName,
508 const OUString& rGraphicId,
509 bool bUseGfxLink )
511 GraphicObject aGrfObject( OUStringToOString(rGraphicId, RTL_TEXTENCODING_ASCII_US) );
512 bool bRet = false;
514 if( aGrfObject.GetType() != GRAPHIC_NONE )
516 SvxGraphicHelperStream_Impl aStream( ImplGetGraphicStream( rPictureStorageName, rPictureStreamName, false ) );
517 if( aStream.xStream.is() )
519 Graphic aGraphic( (Graphic&) aGrfObject.GetGraphic() );
520 const GfxLink aGfxLink( aGraphic.GetLink() );
521 const OUString aMimeType( ImplGetGraphicMimeType( rPictureStreamName ) );
522 uno::Any aAny;
523 uno::Reference < beans::XPropertySet > xProps( aStream.xStream, uno::UNO_QUERY );
525 // set stream properties (MediaType/Compression)
526 if( !aMimeType.isEmpty() )
528 aAny <<= aMimeType;
529 xProps->setPropertyValue( "MediaType", aAny );
532 const bool bCompressed = aMimeType.isEmpty() || aMimeType == "image/tiff" || aMimeType == "image/svg+xml";
533 aAny <<= bCompressed;
534 xProps->setPropertyValue( "Compressed", aAny );
536 boost::scoped_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream( aStream.xStream ));
537 if( bUseGfxLink && aGfxLink.GetDataSize() && aGfxLink.GetData() )
538 pStream->Write( aGfxLink.GetData(), aGfxLink.GetDataSize() );
539 else
541 if( aGraphic.GetType() == GRAPHIC_BITMAP )
543 GraphicFilter &rFilter = GraphicFilter::GetGraphicFilter();
544 OUString aFormat;
546 if( aGraphic.IsAnimated() )
547 aFormat = "gif";
548 else
549 aFormat = "png";
551 bRet = ( rFilter.ExportGraphic( aGraphic, "", *pStream,
552 rFilter.GetExportFormatNumberForShortName( aFormat ) ) == 0 );
554 else if( aGraphic.GetType() == GRAPHIC_GDIMETAFILE )
556 pStream->SetVersion( SOFFICE_FILEFORMAT_8 );
557 pStream->SetCompressMode( SvStreamCompressFlags::ZBITMAP );
559 // SJ: first check if this metafile is just a eps file, then we will store the eps instead of svm
560 GDIMetaFile& rMtf( (GDIMetaFile&)aGraphic.GetGDIMetaFile() );
561 const MetaCommentAction* pComment = ImplCheckForEPS( rMtf );
562 if ( pComment )
564 sal_uInt32 nSize = pComment->GetDataSize();
565 const sal_uInt8* pData = pComment->GetData();
566 if ( nSize && pData )
567 pStream->Write( pData, nSize );
569 const MetaEPSAction* pAct = static_cast<const MetaEPSAction*>(rMtf.FirstAction());
570 const GfxLink& rLink = pAct->GetLink();
572 pStream->Write( rLink.GetData(), rLink.GetDataSize() );
574 else
575 rMtf.Write( *pStream );
577 bRet = ( pStream->GetError() == 0 );
580 uno::Reference < embed::XTransactedObject > xStorage(
581 aStream.xStorage, uno::UNO_QUERY);
582 pStream.reset();
583 aStream.xStream->getOutputStream()->closeOutput();
584 if( xStorage.is() )
585 xStorage->commit();
589 return bRet;
592 void SvXMLGraphicHelper::ImplInsertGraphicURL( const OUString& rURLStr, sal_uInt32 nInsertPos, OUString& rRequestedFileName )
594 OUString aURLString( rURLStr );
595 OUString aPictureStorageName, aPictureStreamName;
596 if( ( maURLSet.find( aURLString ) != maURLSet.end() ) )
598 for (URLPairVector::const_iterator aIter( maGrfURLs.begin() ), aEnd( maGrfURLs.end() ); aIter != aEnd ; ++aIter)
600 if( aURLString == (*aIter).first )
602 maGrfURLs[ nInsertPos ].second = (*aIter).second;
603 break;
607 else if( ImplGetStreamNames( aURLString, aPictureStorageName, aPictureStreamName ) )
609 URLPair& rURLPair = maGrfURLs[ nInsertPos ];
611 if( GRAPHICHELPER_MODE_READ == meCreateMode )
613 const GraphicObject aObj( ImplReadGraphic( aPictureStorageName, aPictureStreamName ) );
615 if( aObj.GetType() != GRAPHIC_NONE )
617 maGrfObjs.push_back( aObj );
618 OUString aBaseURL( XML_GRAPHICOBJECT_URL_BASE );
620 rURLPair.second = aBaseURL;
621 rURLPair.second += OStringToOUString(aObj.GetUniqueID(),
622 RTL_TEXTENCODING_ASCII_US);
624 else
625 rURLPair.second.clear();
627 else
629 const OUString aGraphicObjectId( aPictureStreamName );
630 const OString aAsciiObjectID(OUStringToOString(aGraphicObjectId, RTL_TEXTENCODING_ASCII_US));
631 const GraphicObject aGrfObject( aAsciiObjectID );
632 if( aGrfObject.GetType() != GRAPHIC_NONE )
634 OUString aStreamName( aGraphicObjectId );
635 Graphic aGraphic( (Graphic&) aGrfObject.GetGraphic() );
636 const GfxLink aGfxLink( aGraphic.GetLink() );
637 OUString aExtension;
638 bool bUseGfxLink( true );
640 if( aGfxLink.GetDataSize() )
642 switch( aGfxLink.GetType() )
644 case( GFX_LINK_TYPE_EPS_BUFFER ): aExtension = ".eps"; break;
645 case( GFX_LINK_TYPE_NATIVE_GIF ): aExtension = ".gif"; break;
646 // #i15508# added BMP type for better exports (checked, works)
647 case( GFX_LINK_TYPE_NATIVE_BMP ): aExtension = ".bmp"; break;
648 case( GFX_LINK_TYPE_NATIVE_JPG ): aExtension = ".jpg"; break;
649 case( GFX_LINK_TYPE_NATIVE_PNG ): aExtension = ".png"; break;
650 case( GFX_LINK_TYPE_NATIVE_TIF ): aExtension = ".tif"; break;
651 case( GFX_LINK_TYPE_NATIVE_WMF ): aExtension = ".wmf"; break;
652 case( GFX_LINK_TYPE_NATIVE_MET ): aExtension = ".met"; break;
653 case( GFX_LINK_TYPE_NATIVE_PCT ): aExtension = ".pct"; break;
654 case( GFX_LINK_TYPE_NATIVE_SVG ):
655 // backward-compat kludge: since no released OOo
656 // version to date can handle svg properly, wrap it up
657 // into an svm. slight catch22 here, since strict ODF
658 // conformance _recommends_ svg - then again, most old
659 // ODF consumers are believed to be OOo
660 if( SvtSaveOptions().GetODFDefaultVersion() <= SvtSaveOptions::ODFVER_012 )
662 bUseGfxLink = false;
663 aExtension = ".svm";
665 else
666 aExtension = ".svg";
667 break;
669 default:
670 aExtension = ".grf";
671 break;
674 else
676 if( aGrfObject.GetType() == GRAPHIC_BITMAP )
678 if( aGrfObject.IsAnimated() )
679 aExtension = ".gif";
680 else
681 aExtension = ".png";
683 else if( aGrfObject.GetType() == GRAPHIC_GDIMETAFILE )
685 // SJ: first check if this metafile is just a eps file, then we will store the eps instead of svm
686 GDIMetaFile& rMtf( (GDIMetaFile&)aGraphic.GetGDIMetaFile() );
687 if ( ImplCheckForEPS( rMtf ) )
688 aExtension = ".eps";
689 else
690 aExtension = ".svm";
694 OUString aURLEntry;
695 const OUString sPictures( "Pictures/" );
697 if ( !rRequestedFileName.isEmpty() )
699 aURLEntry = sPictures;
700 aURLEntry += rRequestedFileName;
701 aURLEntry += aExtension;
703 URLPairVector::const_iterator aIter( maGrfURLs.begin() ), aEnd( maGrfURLs.end() );
704 for ( ; aIter != aEnd; ++aIter )
706 if( aURLEntry == (*aIter).second )
707 break;
709 if ( aIter == aEnd )
710 aStreamName = rRequestedFileName;
713 aStreamName += aExtension;
715 if( mbDirect && !aStreamName.isEmpty() )
716 ImplWriteGraphic( aPictureStorageName, aStreamName, aGraphicObjectId, bUseGfxLink );
718 rURLPair.second = sPictures;
719 rURLPair.second += aStreamName;
721 #if OSL_DEBUG_LEVEL > 0
722 else
724 OStringBuffer sMessage("graphic object with ID '");
725 sMessage.append(aAsciiObjectID).
726 append("' has an unknown type");
727 OSL_ENSURE( false, sMessage.getStr() );
729 #endif
732 maURLSet.insert( aURLString );
736 void SvXMLGraphicHelper::Init( const uno::Reference < embed::XStorage >& rXMLStorage,
737 SvXMLGraphicHelperMode eCreateMode,
738 bool bDirect )
740 mxRootStorage = rXMLStorage;
741 meCreateMode = eCreateMode;
742 mbDirect = meCreateMode != GRAPHICHELPER_MODE_READ || bDirect;
745 SvXMLGraphicHelper* SvXMLGraphicHelper::Create( const uno::Reference < embed::XStorage >& rXMLStorage,
746 SvXMLGraphicHelperMode eCreateMode,
747 bool bDirect )
749 SvXMLGraphicHelper* pThis = new SvXMLGraphicHelper;
751 pThis->acquire();
752 pThis->Init( rXMLStorage, eCreateMode, bDirect );
754 return pThis;
757 SvXMLGraphicHelper* SvXMLGraphicHelper::Create( SvXMLGraphicHelperMode eCreateMode )
759 SvXMLGraphicHelper* pThis = new SvXMLGraphicHelper;
761 pThis->acquire();
762 pThis->Init( NULL, eCreateMode, false );
764 return pThis;
767 void SvXMLGraphicHelper::Destroy( SvXMLGraphicHelper* pSvXMLGraphicHelper )
769 if( pSvXMLGraphicHelper )
771 pSvXMLGraphicHelper->dispose();
772 pSvXMLGraphicHelper->release();
776 // XGraphicObjectResolver
777 OUString SAL_CALL SvXMLGraphicHelper::resolveGraphicObjectURL( const OUString& rURL )
778 throw(uno::RuntimeException, std::exception)
780 ::osl::MutexGuard aGuard( maMutex );
781 const sal_Int32 nIndex = maGrfURLs.size();
783 OUString aURL( rURL );
784 OUString aUserData;
785 OUString aRequestedFileName;
787 sal_Int32 nUser = rURL.indexOf( '?', 0 );
788 if ( nUser >= 0 )
790 aURL = rURL.copy( 0, nUser );
791 nUser++;
792 aUserData = rURL.copy( nUser, rURL.getLength() - nUser );
794 if ( !aUserData.isEmpty() )
796 sal_Int32 nIndex2 = 0;
799 OUString aToken = aUserData.getToken( 0, ';', nIndex2 );
800 sal_Int32 n = aToken.indexOf( '=' );
801 if ( ( n > 0 ) && ( ( n + 1 ) < aToken.getLength() ) )
803 OUString aParam( aToken.copy( 0, n ) );
804 OUString aValue( aToken.copy( n + 1, aToken.getLength() - ( n + 1 ) ) );
806 const OUString sRequestedName( "requestedName" );
807 if ( aParam.match( sRequestedName ) )
808 aRequestedFileName = aValue;
811 while ( nIndex2 >= 0 );
814 maGrfURLs.push_back( ::std::make_pair( aURL, OUString() ) );
815 ImplInsertGraphicURL( aURL, nIndex, aRequestedFileName );
817 return maGrfURLs[ nIndex ].second;
820 // XBinaryStreamResolver
821 Reference< XInputStream > SAL_CALL SvXMLGraphicHelper::getInputStream( const OUString& rURL )
822 throw( RuntimeException, std::exception )
824 Reference< XInputStream > xRet;
825 OUString aPictureStorageName, aGraphicId;
828 if( ( GRAPHICHELPER_MODE_WRITE == meCreateMode ) &&
829 ImplGetStreamNames( rURL, aPictureStorageName, aGraphicId ) )
831 SvXMLGraphicInputStream* pInputStream = new SvXMLGraphicInputStream( aGraphicId );
833 if( pInputStream->Exists() )
834 xRet = pInputStream;
835 else
836 delete pInputStream;
839 return xRet;
842 Reference< XOutputStream > SAL_CALL SvXMLGraphicHelper::createOutputStream()
843 throw( RuntimeException, std::exception )
845 Reference< XOutputStream > xRet;
847 if( GRAPHICHELPER_MODE_READ == meCreateMode )
849 SvXMLGraphicOutputStream* pOutputStream = new SvXMLGraphicOutputStream;
851 if( pOutputStream->Exists() )
852 maGrfStms.push_back( xRet = pOutputStream );
853 else
854 delete pOutputStream;
857 return xRet;
860 OUString SAL_CALL SvXMLGraphicHelper::resolveOutputStream( const Reference< XOutputStream >& rxBinaryStream )
861 throw( RuntimeException, std::exception )
863 OUString aRet;
865 if( ( GRAPHICHELPER_MODE_READ == meCreateMode ) && rxBinaryStream.is() )
867 if( ::std::find( maGrfStms.begin(), maGrfStms.end(), rxBinaryStream ) != maGrfStms.end() )
869 SvXMLGraphicOutputStream* pOStm = static_cast< SvXMLGraphicOutputStream* >( rxBinaryStream.get() );
871 if( pOStm )
873 const GraphicObject& rGrfObj = pOStm->GetGraphicObject();
874 const OUString aId(OStringToOUString(
875 rGrfObj.GetUniqueID(), RTL_TEXTENCODING_ASCII_US));
877 if( !aId.isEmpty() )
879 aRet = XML_GRAPHICOBJECT_URL_BASE;
880 aRet += aId;
886 return aRet;
889 // for instantiation via service manager
890 namespace {
892 namespace impl
894 typedef ::cppu::WeakComponentImplHelper4<
895 lang::XInitialization,
896 document::XGraphicObjectResolver,
897 document::XBinaryStreamResolver,
898 lang::XServiceInfo >
899 SvXMLGraphicImportExportHelper_Base;
900 class MutexContainer
902 public:
903 virtual ~MutexContainer();
905 protected:
906 mutable ::osl::Mutex m_aMutex;
908 MutexContainer::~MutexContainer()
910 } // namespace impl
912 class SvXMLGraphicImportExportHelper :
913 public impl::MutexContainer,
914 public impl::SvXMLGraphicImportExportHelper_Base
916 public:
917 SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode );
919 protected:
920 // is called from WeakComponentImplHelper when XComponent::dispose() was
921 // called from outside
922 virtual void SAL_CALL disposing() SAL_OVERRIDE;
924 // ____ XInitialization ____
925 // one argument is allowed, which is the XStorage
926 virtual void SAL_CALL initialize( const Sequence< Any >& aArguments )
927 throw (Exception,
928 RuntimeException, std::exception) SAL_OVERRIDE;
930 // ____ XGraphicObjectResolver ____
931 virtual OUString SAL_CALL resolveGraphicObjectURL( const OUString& aURL )
932 throw (RuntimeException, std::exception) SAL_OVERRIDE;
934 // ____ XBinaryStreamResolver ____
935 virtual Reference< io::XInputStream > SAL_CALL getInputStream( const OUString& aURL )
936 throw (RuntimeException, std::exception) SAL_OVERRIDE;
937 virtual Reference< io::XOutputStream > SAL_CALL createOutputStream()
938 throw (RuntimeException, std::exception) SAL_OVERRIDE;
939 virtual OUString SAL_CALL resolveOutputStream( const Reference< io::XOutputStream >& aBinaryStream )
940 throw (RuntimeException, std::exception) SAL_OVERRIDE;
942 // ____ XServiceInfo ____
943 virtual OUString SAL_CALL getImplementationName()
944 throw (RuntimeException, std::exception) SAL_OVERRIDE;
945 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName )
946 throw (RuntimeException, std::exception) SAL_OVERRIDE;
947 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames()
948 throw (RuntimeException, std::exception) SAL_OVERRIDE;
950 private:
951 SvXMLGraphicHelperMode m_eGraphicHelperMode;
952 Reference< XGraphicObjectResolver > m_xGraphicObjectResolver;
953 Reference< XBinaryStreamResolver > m_xBinaryStreamResolver;
956 SvXMLGraphicImportExportHelper::SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode ) :
957 impl::SvXMLGraphicImportExportHelper_Base( m_aMutex ),
958 m_eGraphicHelperMode( eMode )
961 void SAL_CALL SvXMLGraphicImportExportHelper::disposing()
963 Reference< XComponent > xComp( m_xGraphicObjectResolver, UNO_QUERY );
964 OSL_ASSERT( xComp.is());
965 if( xComp.is())
966 xComp->dispose();
967 // m_xBinaryStreamResolver is a reference to the same object => don't call
968 // dispose() again
971 // ____ XInitialization ____
972 void SAL_CALL SvXMLGraphicImportExportHelper::initialize(
973 const Sequence< Any >& aArguments )
974 throw (Exception, RuntimeException, std::exception)
976 Reference< embed::XStorage > xStorage;
977 if( aArguments.getLength() > 0 )
978 aArguments[0] >>= xStorage;
980 SvXMLGraphicHelper * pHelper( SvXMLGraphicHelper::Create( xStorage, m_eGraphicHelperMode ));
981 m_xGraphicObjectResolver.set( pHelper );
982 m_xBinaryStreamResolver.set( pHelper );
983 // SvXMLGraphicHelper::Create calls acquire. Since we have two references
984 // now it is safe (and necessary) to undo this acquire
985 pHelper->release();
988 // ____ XGraphicObjectResolver ____
989 OUString SAL_CALL SvXMLGraphicImportExportHelper::resolveGraphicObjectURL( const OUString& aURL )
990 throw (uno::RuntimeException, std::exception)
992 return m_xGraphicObjectResolver->resolveGraphicObjectURL( aURL );
996 // ____ XBinaryStreamResolver ____
997 Reference< io::XInputStream > SAL_CALL SvXMLGraphicImportExportHelper::getInputStream( const OUString& aURL )
998 throw (uno::RuntimeException, std::exception)
1000 return m_xBinaryStreamResolver->getInputStream( aURL );
1002 Reference< io::XOutputStream > SAL_CALL SvXMLGraphicImportExportHelper::createOutputStream()
1003 throw (uno::RuntimeException, std::exception)
1005 return m_xBinaryStreamResolver->createOutputStream();
1007 OUString SAL_CALL SvXMLGraphicImportExportHelper::resolveOutputStream( const Reference< io::XOutputStream >& aBinaryStream )
1008 throw (uno::RuntimeException, std::exception)
1010 return m_xBinaryStreamResolver->resolveOutputStream( aBinaryStream );
1013 // ____ XServiceInfo ____
1014 OUString SAL_CALL SvXMLGraphicImportExportHelper::getImplementationName()
1015 throw (uno::RuntimeException, std::exception)
1017 if( m_eGraphicHelperMode == GRAPHICHELPER_MODE_READ )
1018 return OUString("com.sun.star.comp.Svx.GraphicImportHelper");
1019 return OUString("com.sun.star.comp.Svx.GraphicExportHelper");
1022 sal_Bool SAL_CALL SvXMLGraphicImportExportHelper::supportsService( const OUString& ServiceName )
1023 throw (uno::RuntimeException, std::exception)
1025 return cppu::supportsService(this, ServiceName);
1028 Sequence< OUString > SAL_CALL SvXMLGraphicImportExportHelper::getSupportedServiceNames()
1029 throw (uno::RuntimeException, std::exception)
1031 // XGraphicObjectResolver and XBinaryStreamResolver are not part of any service
1032 Sequence< OUString > aSupportedServiceNames( 2 );
1033 aSupportedServiceNames[0] = "com.sun.star.document.GraphicObjectResolver";
1034 aSupportedServiceNames[1] = "com.sun.star.document.BinaryStreamResolver";
1035 return aSupportedServiceNames;
1040 /** Create this with createInstanceWithArguments. service name
1041 "com.sun.star.comp.Svx.GraphicImportHelper", one argument which is the
1042 XStorage. Without arguments no helper class is created. With an empty
1043 argument the helper class is created and initialized like in the CTOR to
1044 SvXMLGraphicHelper that only gets the create mode.
1046 You should call dispose after you no longer need this component.
1048 uses eCreateMode == GRAPHICHELPER_MODE_READ, bDirect == sal_True in
1049 SvXMLGraphicHelper
1051 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
1052 com_sun_star_comp_Svx_GraphicImportHelper_get_implementation(
1053 css::uno::XComponentContext *,
1054 css::uno::Sequence<css::uno::Any> const &)
1056 return cppu::acquire(new SvXMLGraphicImportExportHelper(GRAPHICHELPER_MODE_READ));
1059 /** Create this with createInstanceWithArguments. service name
1060 "com.sun.star.comp.Svx.GraphicExportHelper", one argument which is the
1061 XStorage. Without arguments no helper class is created. With an empty
1062 argument the helper class is created and initialized like in the CTOR to
1063 SvXMLGraphicHelper that only gets the create mode
1065 To write the Pictures stream, you have to call dispose at this component.
1066 Make sure you call dipose before you commit the parent storage.
1068 uses eCreateMode == GRAPHICHELPER_MODE_WRITE, bDirect == sal_True in
1069 SvXMLGraphicHelper
1071 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
1072 com_sun_star_comp_Svx_GraphicExportHelper_get_implementation(
1073 css::uno::XComponentContext *,
1074 css::uno::Sequence<css::uno::Any> const &)
1076 return cppu::acquire(new SvXMLGraphicImportExportHelper(GRAPHICHELPER_MODE_WRITE));
1079 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */