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" },
475 { "wmf", "image/x-wmf" },
476 { "eps", "image/x-eps" },
477 { "bmp", "image/bmp" },
478 { "pct", "image/x-pict" }
483 if( ( rFileName
.getLength() >= 4 ) && ( rFileName
[ rFileName
.getLength() - 4 ] == '.' ) )
485 const OString
aExt(OUStringToOString(rFileName
.copy(rFileName
.getLength() - 3),
486 RTL_TEXTENCODING_ASCII_US
));
488 for( long i
= 0, nCount
= sizeof (aMapper
) / sizeof (aMapper
[0]); ( i
< nCount
) && aMimeType
.isEmpty(); i
++ )
489 if( strcmp(aExt
.getStr(), aMapper
[ i
].pExt
) == 0 )
490 aMimeType
= OUString( aMapper
[ i
].pMimeType
, strlen( aMapper
[ i
].pMimeType
), RTL_TEXTENCODING_ASCII_US
);
496 Graphic
SvXMLGraphicHelper::ImplReadGraphic( const OUString
& rPictureStorageName
,
497 const OUString
& rPictureStreamName
)
500 SvxGraphicHelperStream_Impl
aStream( ImplGetGraphicStream( rPictureStorageName
, rPictureStreamName
, false ) );
501 if( aStream
.xStream
.is() )
503 boost::scoped_ptr
<SvStream
> pStream(utl::UcbStreamHelper::CreateStream( aStream
.xStream
));
504 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic
, "", *pStream
);
510 bool SvXMLGraphicHelper::ImplWriteGraphic( const OUString
& rPictureStorageName
,
511 const OUString
& rPictureStreamName
,
512 const OUString
& rGraphicId
,
515 GraphicObject
aGrfObject( OUStringToOString(rGraphicId
, RTL_TEXTENCODING_ASCII_US
) );
518 if( aGrfObject
.GetType() != GRAPHIC_NONE
)
520 SvxGraphicHelperStream_Impl
aStream( ImplGetGraphicStream( rPictureStorageName
, rPictureStreamName
, false ) );
521 if( aStream
.xStream
.is() )
523 Graphic
aGraphic( (Graphic
&) aGrfObject
.GetGraphic() );
524 const GfxLink
aGfxLink( aGraphic
.GetLink() );
525 const OUString
aMimeType( ImplGetGraphicMimeType( rPictureStreamName
) );
527 uno::Reference
< beans::XPropertySet
> xProps( aStream
.xStream
, uno::UNO_QUERY
);
529 // set stream properties (MediaType/Compression)
530 if( !aMimeType
.isEmpty() )
533 xProps
->setPropertyValue( "MediaType", aAny
);
536 const bool bCompressed
= aMimeType
.isEmpty() || aMimeType
== "image/tiff" || aMimeType
== "image/svg+xml";
537 aAny
<<= bCompressed
;
538 xProps
->setPropertyValue( "Compressed", aAny
);
540 boost::scoped_ptr
<SvStream
> pStream(utl::UcbStreamHelper::CreateStream( aStream
.xStream
));
541 if( bUseGfxLink
&& aGfxLink
.GetDataSize() && aGfxLink
.GetData() )
542 pStream
->Write( aGfxLink
.GetData(), aGfxLink
.GetDataSize() );
545 if( aGraphic
.GetType() == GRAPHIC_BITMAP
)
547 GraphicFilter
&rFilter
= GraphicFilter::GetGraphicFilter();
550 if( aGraphic
.IsAnimated() )
555 bRet
= ( rFilter
.ExportGraphic( aGraphic
, "", *pStream
,
556 rFilter
.GetExportFormatNumberForShortName( aFormat
) ) == 0 );
558 else if( aGraphic
.GetType() == GRAPHIC_GDIMETAFILE
)
560 pStream
->SetVersion( SOFFICE_FILEFORMAT_8
);
561 pStream
->SetCompressMode( SvStreamCompressFlags::ZBITMAP
);
563 // SJ: first check if this metafile is just a eps file, then we will store the eps instead of svm
564 GDIMetaFile
& rMtf( (GDIMetaFile
&)aGraphic
.GetGDIMetaFile() );
565 const MetaCommentAction
* pComment
= ImplCheckForEPS( rMtf
);
568 sal_uInt32 nSize
= pComment
->GetDataSize();
569 const sal_uInt8
* pData
= pComment
->GetData();
570 if ( nSize
&& pData
)
571 pStream
->Write( pData
, nSize
);
573 const MetaEPSAction
* pAct
= static_cast<const MetaEPSAction
*>(rMtf
.FirstAction());
574 const GfxLink
& rLink
= pAct
->GetLink();
576 pStream
->Write( rLink
.GetData(), rLink
.GetDataSize() );
579 rMtf
.Write( *pStream
);
581 bRet
= ( pStream
->GetError() == 0 );
584 uno::Reference
< embed::XTransactedObject
> xStorage(
585 aStream
.xStorage
, uno::UNO_QUERY
);
587 aStream
.xStream
->getOutputStream()->closeOutput();
596 void SvXMLGraphicHelper::ImplInsertGraphicURL( const OUString
& rURLStr
, sal_uInt32 nInsertPos
, OUString
& rRequestedFileName
)
598 OUString
aURLString( rURLStr
);
599 OUString aPictureStorageName
, aPictureStreamName
;
600 if( ( maURLSet
.find( aURLString
) != maURLSet
.end() ) )
602 for (URLPairVector::const_iterator
aIter( maGrfURLs
.begin() ), aEnd( maGrfURLs
.end() ); aIter
!= aEnd
; ++aIter
)
604 if( aURLString
== (*aIter
).first
)
606 maGrfURLs
[ nInsertPos
].second
= (*aIter
).second
;
611 else if( ImplGetStreamNames( aURLString
, aPictureStorageName
, aPictureStreamName
) )
613 URLPair
& rURLPair
= maGrfURLs
[ nInsertPos
];
615 if( GRAPHICHELPER_MODE_READ
== meCreateMode
)
617 const GraphicObject
aObj( ImplReadGraphic( aPictureStorageName
, aPictureStreamName
) );
619 if( aObj
.GetType() != GRAPHIC_NONE
)
621 maGrfObjs
.push_back( aObj
);
622 OUString
aBaseURL( XML_GRAPHICOBJECT_URL_BASE
);
624 rURLPair
.second
= aBaseURL
;
625 rURLPair
.second
+= OStringToOUString(aObj
.GetUniqueID(),
626 RTL_TEXTENCODING_ASCII_US
);
629 rURLPair
.second
.clear();
633 const OUString
aGraphicObjectId( aPictureStreamName
);
634 const OString
aAsciiObjectID(OUStringToOString(aGraphicObjectId
, RTL_TEXTENCODING_ASCII_US
));
635 const GraphicObject
aGrfObject( aAsciiObjectID
);
636 if( aGrfObject
.GetType() != GRAPHIC_NONE
)
638 OUString
aStreamName( aGraphicObjectId
);
639 Graphic
aGraphic( (Graphic
&) aGrfObject
.GetGraphic() );
640 const GfxLink
aGfxLink( aGraphic
.GetLink() );
642 bool bUseGfxLink( true );
644 if( aGfxLink
.GetDataSize() )
646 switch( aGfxLink
.GetType() )
648 case( GFX_LINK_TYPE_EPS_BUFFER
): aExtension
= ".eps"; break;
649 case( GFX_LINK_TYPE_NATIVE_GIF
): aExtension
= ".gif"; break;
650 // #i15508# added BMP type for better exports (checked, works)
651 case( GFX_LINK_TYPE_NATIVE_BMP
): aExtension
= ".bmp"; break;
652 case( GFX_LINK_TYPE_NATIVE_JPG
): aExtension
= ".jpg"; break;
653 case( GFX_LINK_TYPE_NATIVE_PNG
): aExtension
= ".png"; break;
654 case( GFX_LINK_TYPE_NATIVE_TIF
): aExtension
= ".tif"; break;
655 case( GFX_LINK_TYPE_NATIVE_WMF
): aExtension
= ".wmf"; break;
656 case( GFX_LINK_TYPE_NATIVE_MET
): aExtension
= ".met"; break;
657 case( GFX_LINK_TYPE_NATIVE_PCT
): aExtension
= ".pct"; break;
658 case( GFX_LINK_TYPE_NATIVE_SVG
):
659 // backward-compat kludge: since no released OOo
660 // version to date can handle svg properly, wrap it up
661 // into an svm. slight catch22 here, since strict ODF
662 // conformance _recommends_ svg - then again, most old
663 // ODF consumers are believed to be OOo
664 if( SvtSaveOptions().GetODFDefaultVersion() <= SvtSaveOptions::ODFVER_012
)
680 if( aGrfObject
.GetType() == GRAPHIC_BITMAP
)
682 if( aGrfObject
.IsAnimated() )
687 else if( aGrfObject
.GetType() == GRAPHIC_GDIMETAFILE
)
689 // SJ: first check if this metafile is just a eps file, then we will store the eps instead of svm
690 GDIMetaFile
& rMtf( (GDIMetaFile
&)aGraphic
.GetGDIMetaFile() );
691 if ( ImplCheckForEPS( rMtf
) )
699 const OUString
sPictures( "Pictures/" );
701 if ( !rRequestedFileName
.isEmpty() )
703 aURLEntry
= sPictures
;
704 aURLEntry
+= rRequestedFileName
;
705 aURLEntry
+= aExtension
;
707 URLPairVector::const_iterator
aIter( maGrfURLs
.begin() ), aEnd( maGrfURLs
.end() );
708 for ( ; aIter
!= aEnd
; ++aIter
)
710 if( aURLEntry
== (*aIter
).second
)
714 aStreamName
= rRequestedFileName
;
717 aStreamName
+= aExtension
;
719 if( mbDirect
&& !aStreamName
.isEmpty() )
720 ImplWriteGraphic( aPictureStorageName
, aStreamName
, aGraphicObjectId
, bUseGfxLink
);
722 rURLPair
.second
= sPictures
;
723 rURLPair
.second
+= aStreamName
;
725 #if OSL_DEBUG_LEVEL > 0
728 OStringBuffer
sMessage("graphic object with ID '");
729 sMessage
.append(aAsciiObjectID
).
730 append("' has an unknown type");
731 OSL_ENSURE( false, sMessage
.getStr() );
736 maURLSet
.insert( aURLString
);
740 void SvXMLGraphicHelper::Init( const uno::Reference
< embed::XStorage
>& rXMLStorage
,
741 SvXMLGraphicHelperMode eCreateMode
,
744 mxRootStorage
= rXMLStorage
;
745 meCreateMode
= eCreateMode
;
746 mbDirect
= meCreateMode
!= GRAPHICHELPER_MODE_READ
|| bDirect
;
749 SvXMLGraphicHelper
* SvXMLGraphicHelper::Create( const uno::Reference
< embed::XStorage
>& rXMLStorage
,
750 SvXMLGraphicHelperMode eCreateMode
,
753 SvXMLGraphicHelper
* pThis
= new SvXMLGraphicHelper
;
756 pThis
->Init( rXMLStorage
, eCreateMode
, bDirect
);
761 SvXMLGraphicHelper
* SvXMLGraphicHelper::Create( SvXMLGraphicHelperMode eCreateMode
)
763 SvXMLGraphicHelper
* pThis
= new SvXMLGraphicHelper
;
766 pThis
->Init( NULL
, eCreateMode
, false );
771 void SvXMLGraphicHelper::Destroy( SvXMLGraphicHelper
* pSvXMLGraphicHelper
)
773 if( pSvXMLGraphicHelper
)
775 pSvXMLGraphicHelper
->dispose();
776 pSvXMLGraphicHelper
->release();
780 // XGraphicObjectResolver
781 OUString SAL_CALL
SvXMLGraphicHelper::resolveGraphicObjectURL( const OUString
& rURL
)
782 throw(uno::RuntimeException
, std::exception
)
784 ::osl::MutexGuard
aGuard( maMutex
);
785 const sal_Int32 nIndex
= maGrfURLs
.size();
787 OUString
aURL( rURL
);
789 OUString aRequestedFileName
;
791 sal_Int32 nUser
= rURL
.indexOf( '?', 0 );
794 aURL
= rURL
.copy( 0, nUser
);
796 aUserData
= rURL
.copy( nUser
, rURL
.getLength() - nUser
);
798 if ( !aUserData
.isEmpty() )
800 sal_Int32 nIndex2
= 0;
803 OUString aToken
= aUserData
.getToken( 0, ';', nIndex2
);
804 sal_Int32 n
= aToken
.indexOf( '=' );
805 if ( ( n
> 0 ) && ( ( n
+ 1 ) < aToken
.getLength() ) )
807 OUString
aParam( aToken
.copy( 0, n
) );
808 OUString
aValue( aToken
.copy( n
+ 1, aToken
.getLength() - ( n
+ 1 ) ) );
810 const OUString
sRequestedName( "requestedName" );
811 if ( aParam
.match( sRequestedName
) )
812 aRequestedFileName
= aValue
;
815 while ( nIndex2
>= 0 );
818 maGrfURLs
.push_back( ::std::make_pair( aURL
, OUString() ) );
819 ImplInsertGraphicURL( aURL
, nIndex
, aRequestedFileName
);
821 return maGrfURLs
[ nIndex
].second
;
824 // XBinaryStreamResolver
825 Reference
< XInputStream
> SAL_CALL
SvXMLGraphicHelper::getInputStream( const OUString
& rURL
)
826 throw( RuntimeException
, std::exception
)
828 Reference
< XInputStream
> xRet
;
829 OUString aPictureStorageName
, aGraphicId
;
832 if( ( GRAPHICHELPER_MODE_WRITE
== meCreateMode
) &&
833 ImplGetStreamNames( rURL
, aPictureStorageName
, aGraphicId
) )
835 SvXMLGraphicInputStream
* pInputStream
= new SvXMLGraphicInputStream( aGraphicId
);
837 if( pInputStream
->Exists() )
846 Reference
< XOutputStream
> SAL_CALL
SvXMLGraphicHelper::createOutputStream()
847 throw( RuntimeException
, std::exception
)
849 Reference
< XOutputStream
> xRet
;
851 if( GRAPHICHELPER_MODE_READ
== meCreateMode
)
853 SvXMLGraphicOutputStream
* pOutputStream
= new SvXMLGraphicOutputStream
;
855 if( pOutputStream
->Exists() )
856 maGrfStms
.push_back( xRet
= pOutputStream
);
858 delete pOutputStream
;
864 OUString SAL_CALL
SvXMLGraphicHelper::resolveOutputStream( const Reference
< XOutputStream
>& rxBinaryStream
)
865 throw( RuntimeException
, std::exception
)
869 if( ( GRAPHICHELPER_MODE_READ
== meCreateMode
) && rxBinaryStream
.is() )
871 if( ::std::find( maGrfStms
.begin(), maGrfStms
.end(), rxBinaryStream
) != maGrfStms
.end() )
873 SvXMLGraphicOutputStream
* pOStm
= static_cast< SvXMLGraphicOutputStream
* >( rxBinaryStream
.get() );
877 const GraphicObject
& rGrfObj
= pOStm
->GetGraphicObject();
878 const OUString
aId(OStringToOUString(
879 rGrfObj
.GetUniqueID(), RTL_TEXTENCODING_ASCII_US
));
883 aRet
= XML_GRAPHICOBJECT_URL_BASE
;
893 // for instantiation via service manager
898 typedef ::cppu::WeakComponentImplHelper4
<
899 lang::XInitialization
,
900 document::XGraphicObjectResolver
,
901 document::XBinaryStreamResolver
,
903 SvXMLGraphicImportExportHelper_Base
;
907 virtual ~MutexContainer();
910 mutable ::osl::Mutex m_aMutex
;
912 MutexContainer::~MutexContainer()
916 class SvXMLGraphicImportExportHelper
:
917 public impl::MutexContainer
,
918 public impl::SvXMLGraphicImportExportHelper_Base
921 SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode
);
924 // is called from WeakComponentImplHelper when XComponent::dispose() was
925 // called from outside
926 virtual void SAL_CALL
disposing() SAL_OVERRIDE
;
928 // ____ XInitialization ____
929 // one argument is allowed, which is the XStorage
930 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
)
932 RuntimeException
, std::exception
) SAL_OVERRIDE
;
934 // ____ XGraphicObjectResolver ____
935 virtual OUString SAL_CALL
resolveGraphicObjectURL( const OUString
& aURL
)
936 throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
938 // ____ XBinaryStreamResolver ____
939 virtual Reference
< io::XInputStream
> SAL_CALL
getInputStream( const OUString
& aURL
)
940 throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
941 virtual Reference
< io::XOutputStream
> SAL_CALL
createOutputStream()
942 throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
943 virtual OUString SAL_CALL
resolveOutputStream( const Reference
< io::XOutputStream
>& aBinaryStream
)
944 throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
946 // ____ XServiceInfo ____
947 virtual OUString SAL_CALL
getImplementationName()
948 throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
949 virtual sal_Bool SAL_CALL
supportsService( const OUString
& ServiceName
)
950 throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
951 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames()
952 throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
955 SvXMLGraphicHelperMode m_eGraphicHelperMode
;
956 Reference
< XGraphicObjectResolver
> m_xGraphicObjectResolver
;
957 Reference
< XBinaryStreamResolver
> m_xBinaryStreamResolver
;
960 SvXMLGraphicImportExportHelper::SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode
) :
961 impl::SvXMLGraphicImportExportHelper_Base( m_aMutex
),
962 m_eGraphicHelperMode( eMode
)
965 void SAL_CALL
SvXMLGraphicImportExportHelper::disposing()
967 Reference
< XComponent
> xComp( m_xGraphicObjectResolver
, UNO_QUERY
);
968 OSL_ASSERT( xComp
.is());
971 // m_xBinaryStreamResolver is a reference to the same object => don't call
975 // ____ XInitialization ____
976 void SAL_CALL
SvXMLGraphicImportExportHelper::initialize(
977 const Sequence
< Any
>& aArguments
)
978 throw (Exception
, RuntimeException
, std::exception
)
980 Reference
< embed::XStorage
> xStorage
;
981 if( aArguments
.getLength() > 0 )
982 aArguments
[0] >>= xStorage
;
984 SvXMLGraphicHelper
* pHelper( SvXMLGraphicHelper::Create( xStorage
, m_eGraphicHelperMode
));
985 m_xGraphicObjectResolver
.set( pHelper
);
986 m_xBinaryStreamResolver
.set( pHelper
);
987 // SvXMLGraphicHelper::Create calls acquire. Since we have two references
988 // now it is safe (and necessary) to undo this acquire
992 // ____ XGraphicObjectResolver ____
993 OUString SAL_CALL
SvXMLGraphicImportExportHelper::resolveGraphicObjectURL( const OUString
& aURL
)
994 throw (uno::RuntimeException
, std::exception
)
996 return m_xGraphicObjectResolver
->resolveGraphicObjectURL( aURL
);
1000 // ____ XBinaryStreamResolver ____
1001 Reference
< io::XInputStream
> SAL_CALL
SvXMLGraphicImportExportHelper::getInputStream( const OUString
& aURL
)
1002 throw (uno::RuntimeException
, std::exception
)
1004 return m_xBinaryStreamResolver
->getInputStream( aURL
);
1006 Reference
< io::XOutputStream
> SAL_CALL
SvXMLGraphicImportExportHelper::createOutputStream()
1007 throw (uno::RuntimeException
, std::exception
)
1009 return m_xBinaryStreamResolver
->createOutputStream();
1011 OUString SAL_CALL
SvXMLGraphicImportExportHelper::resolveOutputStream( const Reference
< io::XOutputStream
>& aBinaryStream
)
1012 throw (uno::RuntimeException
, std::exception
)
1014 return m_xBinaryStreamResolver
->resolveOutputStream( aBinaryStream
);
1017 // ____ XServiceInfo ____
1018 OUString SAL_CALL
SvXMLGraphicImportExportHelper::getImplementationName()
1019 throw (uno::RuntimeException
, std::exception
)
1021 if( m_eGraphicHelperMode
== GRAPHICHELPER_MODE_READ
)
1022 return OUString("com.sun.star.comp.Svx.GraphicImportHelper");
1023 return OUString("com.sun.star.comp.Svx.GraphicExportHelper");
1026 sal_Bool SAL_CALL
SvXMLGraphicImportExportHelper::supportsService( const OUString
& ServiceName
)
1027 throw (uno::RuntimeException
, std::exception
)
1029 return cppu::supportsService(this, ServiceName
);
1032 Sequence
< OUString
> SAL_CALL
SvXMLGraphicImportExportHelper::getSupportedServiceNames()
1033 throw (uno::RuntimeException
, std::exception
)
1035 // XGraphicObjectResolver and XBinaryStreamResolver are not part of any service
1036 Sequence
< OUString
> aSupportedServiceNames( 2 );
1037 aSupportedServiceNames
[0] = "com.sun.star.document.GraphicObjectResolver";
1038 aSupportedServiceNames
[1] = "com.sun.star.document.BinaryStreamResolver";
1039 return aSupportedServiceNames
;
1044 /** Create this with createInstanceWithArguments. service name
1045 "com.sun.star.comp.Svx.GraphicImportHelper", one argument which is the
1046 XStorage. Without arguments no helper class is created. With an empty
1047 argument the helper class is created and initialized like in the CTOR to
1048 SvXMLGraphicHelper that only gets the create mode.
1050 You should call dispose after you no longer need this component.
1052 uses eCreateMode == GRAPHICHELPER_MODE_READ, bDirect == sal_True in
1055 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
* SAL_CALL
1056 com_sun_star_comp_Svx_GraphicImportHelper_get_implementation(
1057 css::uno::XComponentContext
*,
1058 css::uno::Sequence
<css::uno::Any
> const &)
1060 return cppu::acquire(new SvXMLGraphicImportExportHelper(GRAPHICHELPER_MODE_READ
));
1063 /** Create this with createInstanceWithArguments. service name
1064 "com.sun.star.comp.Svx.GraphicExportHelper", one argument which is the
1065 XStorage. Without arguments no helper class is created. With an empty
1066 argument the helper class is created and initialized like in the CTOR to
1067 SvXMLGraphicHelper that only gets the create mode
1069 To write the Pictures stream, you have to call dispose at this component.
1070 Make sure you call dipose before you commit the parent storage.
1072 uses eCreateMode == GRAPHICHELPER_MODE_WRITE, bDirect == sal_True in
1075 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
* SAL_CALL
1076 com_sun_star_comp_Svx_GraphicExportHelper_get_implementation(
1077 css::uno::XComponentContext
*,
1078 css::uno::Sequence
<css::uno::Any
> const &)
1080 return cppu::acquire(new SvXMLGraphicImportExportHelper(GRAPHICHELPER_MODE_WRITE
));
1083 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */