1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
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:"
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 ));
75 class SvXMLGraphicInputStream
:
76 public cppu::WeakImplHelper1
<XInputStream
>, private boost::noncopyable
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
;
88 ::utl::TempFile maTmp
;
89 Reference
< XInputStream
> mxStmWrapper
;
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
);
111 Graphic
aGraphic( (Graphic
&) aGrfObject
.GetGraphic() );
112 const GfxLink
aGfxLink( aGraphic
.GetLink() );
115 if( aGfxLink
.GetDataSize() && aGfxLink
.GetData() )
117 pStm
->Write( aGfxLink
.GetData(), aGfxLink
.GetDataSize() );
118 bRet
= ( pStm
->GetError() == 0 );
122 if( aGraphic
.GetType() == GRAPHIC_BITMAP
)
124 GraphicFilter
&rFilter
= GraphicFilter::GetGraphicFilter();
127 if( aGraphic
.IsAnimated() )
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 );
146 mxStmWrapper
= new ::utl::OInputStreamWrapper( pStm
, true );
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
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
;
213 ::utl::TempFile
* mpTmp
;
215 Reference
< XOutputStream
> mxStmWrapper
;
216 GraphicObject maGrfObj
;
221 SvXMLGraphicOutputStream();
222 virtual ~SvXMLGraphicOutputStream();
224 bool Exists() const { return mxStmWrapper
.is(); }
225 const GraphicObject
& GetGraphicObject();
228 SvXMLGraphicOutputStream::SvXMLGraphicOutputStream() :
229 mpTmp( new ::utl::TempFile
),
232 mpTmp
->EnableKillingFile();
234 mpOStm
= ::utl::UcbStreamHelper::CreateStream( mpTmp
->GetURL(), StreamMode::WRITE
| StreamMode::TRUNC
);
237 mxStmWrapper
= new ::utl::OOutputStreamWrapper( *mpOStm
);
240 SvXMLGraphicOutputStream::~SvXMLGraphicOutputStream()
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();
276 const GraphicObject
& SvXMLGraphicOutputStream::GetGraphicObject()
278 if( mbClosed
&& ( maGrfObj
.GetType() == GRAPHIC_NONE
) && mpOStm
)
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();
300 SvLockBytes
* pLockBytes
= mpOStm
->GetLockBytes();
302 pLockBytes
->SetSynchronMode( true );
304 mpOStm
->Seek( STREAM_SEEK_TO_END
);
305 nStreamLen
= mpOStm
->Tell();
308 if( nStreamLen
>= 2 )
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);
319 aZCodec
.Decompress( *mpOStm
, *pDest
);
321 if (aZCodec
.EndCompression() && pDest
)
323 pDest
->Seek( STREAM_SEEK_TO_END
);
324 sal_uIntPtr nStreamLen_
= pDest
->Tell();
328 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic
, "", *pDest
,nFormat
,&pDeterminedFormat
);
336 if( maGrfObj
.GetType() != GRAPHIC_NONE
)
338 delete mpOStm
, mpOStm
= NULL
;
339 delete mpTmp
, mpTmp
= NULL
;
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
)
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
);
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
;
390 SvXMLEmbeddedObjectHelper::splitObjectURL(aURLStr
, rPictureStorageName
, rPictureStreamName
);
392 bRet
= !rPictureStreamName
.isEmpty();
393 SAL_WARN_IF(!bRet
, "svx", "SvXMLGraphicHelper::ImplInsertGraphicURL: invalid scheme: " << rURLStr
);
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
& )
431 SvxGraphicHelperStream_Impl
SvXMLGraphicHelper::ImplGetGraphicStream( const OUString
& rPictureStorageName
,
432 const OUString
& rPictureStreamName
,
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
;
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
) );
460 OUString
SvXMLGraphicHelper::ImplGetGraphicMimeType( const OUString
& rFileName
) const
462 struct XMLGraphicMimeTypeMapper
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" }
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
);
492 Graphic
SvXMLGraphicHelper::ImplReadGraphic( const OUString
& rPictureStorageName
,
493 const OUString
& rPictureStreamName
)
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
);
506 bool SvXMLGraphicHelper::ImplWriteGraphic( const OUString
& rPictureStorageName
,
507 const OUString
& rPictureStreamName
,
508 const OUString
& rGraphicId
,
511 GraphicObject
aGrfObject( OUStringToOString(rGraphicId
, RTL_TEXTENCODING_ASCII_US
) );
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
) );
523 uno::Reference
< beans::XPropertySet
> xProps( aStream
.xStream
, uno::UNO_QUERY
);
525 // set stream properties (MediaType/Compression)
526 if( !aMimeType
.isEmpty() )
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() );
541 if( aGraphic
.GetType() == GRAPHIC_BITMAP
)
543 GraphicFilter
&rFilter
= GraphicFilter::GetGraphicFilter();
546 if( aGraphic
.IsAnimated() )
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
);
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() );
575 rMtf
.Write( *pStream
);
577 bRet
= ( pStream
->GetError() == 0 );
580 uno::Reference
< embed::XTransactedObject
> xStorage(
581 aStream
.xStorage
, uno::UNO_QUERY
);
583 aStream
.xStream
->getOutputStream()->closeOutput();
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
;
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
);
625 rURLPair
.second
.clear();
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() );
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
)
676 if( aGrfObject
.GetType() == GRAPHIC_BITMAP
)
678 if( aGrfObject
.IsAnimated() )
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
) )
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
)
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
724 OStringBuffer
sMessage("graphic object with ID '");
725 sMessage
.append(aAsciiObjectID
).
726 append("' has an unknown type");
727 OSL_ENSURE( false, sMessage
.getStr() );
732 maURLSet
.insert( aURLString
);
736 void SvXMLGraphicHelper::Init( const uno::Reference
< embed::XStorage
>& rXMLStorage
,
737 SvXMLGraphicHelperMode eCreateMode
,
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
,
749 SvXMLGraphicHelper
* pThis
= new SvXMLGraphicHelper
;
752 pThis
->Init( rXMLStorage
, eCreateMode
, bDirect
);
757 SvXMLGraphicHelper
* SvXMLGraphicHelper::Create( SvXMLGraphicHelperMode eCreateMode
)
759 SvXMLGraphicHelper
* pThis
= new SvXMLGraphicHelper
;
762 pThis
->Init( NULL
, eCreateMode
, false );
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
);
785 OUString aRequestedFileName
;
787 sal_Int32 nUser
= rURL
.indexOf( '?', 0 );
790 aURL
= rURL
.copy( 0, 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() )
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
);
854 delete pOutputStream
;
860 OUString SAL_CALL
SvXMLGraphicHelper::resolveOutputStream( const Reference
< XOutputStream
>& rxBinaryStream
)
861 throw( RuntimeException
, std::exception
)
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() );
873 const GraphicObject
& rGrfObj
= pOStm
->GetGraphicObject();
874 const OUString
aId(OStringToOUString(
875 rGrfObj
.GetUniqueID(), RTL_TEXTENCODING_ASCII_US
));
879 aRet
= XML_GRAPHICOBJECT_URL_BASE
;
889 // for instantiation via service manager
894 typedef ::cppu::WeakComponentImplHelper4
<
895 lang::XInitialization
,
896 document::XGraphicObjectResolver
,
897 document::XBinaryStreamResolver
,
899 SvXMLGraphicImportExportHelper_Base
;
903 virtual ~MutexContainer();
906 mutable ::osl::Mutex m_aMutex
;
908 MutexContainer::~MutexContainer()
912 class SvXMLGraphicImportExportHelper
:
913 public impl::MutexContainer
,
914 public impl::SvXMLGraphicImportExportHelper_Base
917 SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode
);
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
)
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
;
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());
967 // m_xBinaryStreamResolver is a reference to the same object => don't call
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
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
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
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: */