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>
21 #include <sal/log.hxx>
23 #include <com/sun/star/embed/XTransactedObject.hpp>
24 #include <com/sun/star/embed/ElementModes.hpp>
25 #include <com/sun/star/beans/XPropertySet.hpp>
26 #include <com/sun/star/io/NotConnectedException.hpp>
27 #include <com/sun/star/lang/XServiceInfo.hpp>
28 #include <com/sun/star/lang/XInitialization.hpp>
29 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
30 #include <com/sun/star/util/XCancellable.hpp>
31 #include <com/sun/star/embed/XHierarchicalStorageAccess.hpp>
32 #include <comphelper/fileformat.h>
33 #include <comphelper/graphicmimetype.hxx>
34 #include <cppuhelper/compbase.hxx>
35 #include <cppuhelper/implbase.hxx>
36 #include <cppuhelper/supportsservice.hxx>
38 #include <rtl/ref.hxx>
39 #include <unotools/ucbstreamhelper.hxx>
40 #include <unotools/streamwrap.hxx>
41 #include <unotools/tempfile.hxx>
42 #include <unotools/saveopt.hxx>
43 #include <vcl/gfxlink.hxx>
44 #include <vcl/metaact.hxx>
45 #include <tools/zcodec.hxx>
46 #include <tools/diagnose_ex.h>
48 #include <vcl/GraphicObject.hxx>
49 #include <vcl/graphicfilter.hxx>
50 #include <svx/xmlgrhlp.hxx>
51 #include <svx/xmleohlp.hxx>
55 #include <string_view>
58 using namespace com::sun::star
;
59 using namespace com::sun::star::uno
;
60 using namespace com::sun::star::io
;
62 namespace com::sun::star::uno
{ class XComponentContext
; }
64 #define XML_GRAPHICSTORAGE_NAME "Pictures"
65 #define XML_GRAPHICOBJECT_URL_BASE "vnd.sun.star.GraphicObject:"
69 const MetaCommentAction
* ImplCheckForEPS( GDIMetaFile
const & rMtf
)
71 const MetaCommentAction
* pComment
= nullptr;
73 if ( rMtf
.GetActionSize() >= 2
74 && rMtf
.GetAction(0)->GetType() == MetaActionType::EPS
75 && rMtf
.GetAction(1)->GetType() == MetaActionType::COMMENT
76 && ( static_cast<const MetaCommentAction
*>(rMtf
.GetAction( 1 ))->GetComment() == "EPSReplacementGraphic" ) )
77 pComment
= static_cast<const MetaCommentAction
*>(rMtf
.GetAction( 1 ));
82 class GraphicInputStream
: public cppu::WeakImplHelper
<XInputStream
>
85 virtual sal_Int32 SAL_CALL
readBytes(Sequence
<sal_Int8
> & aData
, sal_Int32 nBytesToRead
) override
;
86 virtual sal_Int32 SAL_CALL
readSomeBytes(Sequence
<sal_Int8
> & aData
, sal_Int32 nMaxBytesToRead
) override
;
87 virtual void SAL_CALL
skipBytes(sal_Int32 nBytesToSkip
) override
;
88 virtual sal_Int32 SAL_CALL
available() override
;
89 virtual void SAL_CALL
closeInput() override
;
92 utl::TempFile maTempFile
;
93 Reference
<XInputStream
> mxStreamWrapper
;
97 explicit GraphicInputStream(GraphicObject
const & raGraphicObject
, const OUString
& rMimeType
);
98 GraphicInputStream(const GraphicInputStream
&) = delete;
100 GraphicInputStream
& operator=(const GraphicInputStream
&) = delete;
104 return mxStreamWrapper
.is();
109 GraphicInputStream::GraphicInputStream(GraphicObject
const & aGraphicObject
, const OUString
& rMimeType
)
111 maTempFile
.EnableKillingFile();
113 if (aGraphicObject
.GetType() == GraphicType::NONE
)
116 std::unique_ptr
<SvStream
> pStream
= ::utl::UcbStreamHelper::CreateStream(maTempFile
.GetURL(), StreamMode::WRITE
| StreamMode::TRUNC
);
121 const Graphic
& aGraphic(aGraphicObject
.GetGraphic());
122 const GfxLink
aGfxLink(aGraphic
.GetGfxLink());
125 if (aGfxLink
.GetDataSize() && aGfxLink
.GetData())
127 if (rMimeType
.isEmpty())
129 pStream
->WriteBytes(aGfxLink
.GetData(), aGfxLink
.GetDataSize());
130 bRet
= (pStream
->GetError() == ERRCODE_NONE
);
134 GraphicFilter
&rFilter
= GraphicFilter::GetGraphicFilter();
135 bRet
= (rFilter
.ExportGraphic(aGraphic
, "", *pStream
, rFilter
.GetExportFormatNumberForMediaType(rMimeType
)) == ERRCODE_NONE
);
140 if (aGraphic
.GetType() == GraphicType::Bitmap
)
142 GraphicFilter
& rFilter
= GraphicFilter::GetGraphicFilter();
143 OUString aFormat
= rMimeType
;
145 if (aGraphic
.IsAnimated())
146 aFormat
= "image/gif";
147 else if (aFormat
.isEmpty())
148 aFormat
= "image/png";
150 bRet
= (rFilter
.ExportGraphic(aGraphic
, "", *pStream
, rFilter
.GetExportFormatNumberForMediaType(aFormat
)) == ERRCODE_NONE
);
152 else if (rMimeType
.isEmpty() && aGraphic
.GetType() == GraphicType::GdiMetafile
)
154 pStream
->SetVersion(SOFFICE_FILEFORMAT_8
);
155 pStream
->SetCompressMode(SvStreamCompressFlags::ZBITMAP
);
156 const_cast<GDIMetaFile
&>(aGraphic
.GetGDIMetaFile()).Write(*pStream
);
157 bRet
= (pStream
->GetError() == ERRCODE_NONE
);
159 else if (!rMimeType
.isEmpty())
161 GraphicFilter
& rFilter
= GraphicFilter::GetGraphicFilter();
162 bRet
= ( rFilter
.ExportGraphic( aGraphic
, "", *pStream
, rFilter
.GetExportFormatNumberForMediaType( rMimeType
) ) == ERRCODE_NONE
);
169 mxStreamWrapper
= new ::utl::OInputStreamWrapper(std::move(pStream
));
173 sal_Int32 SAL_CALL
GraphicInputStream::readBytes(Sequence
<sal_Int8
> & rData
, sal_Int32 nBytesToRead
)
175 if (!mxStreamWrapper
.is())
176 throw NotConnectedException();
178 return mxStreamWrapper
->readBytes(rData
, nBytesToRead
);
181 sal_Int32 SAL_CALL
GraphicInputStream::readSomeBytes(Sequence
<sal_Int8
>& rData
, sal_Int32 nMaxBytesToRead
)
183 if (!mxStreamWrapper
.is())
184 throw NotConnectedException() ;
186 return mxStreamWrapper
->readSomeBytes(rData
, nMaxBytesToRead
);
189 void SAL_CALL
GraphicInputStream::skipBytes(sal_Int32 nBytesToSkip
)
191 if (!mxStreamWrapper
.is())
192 throw NotConnectedException();
194 mxStreamWrapper
->skipBytes(nBytesToSkip
);
197 sal_Int32 SAL_CALL
GraphicInputStream::available()
199 if (!mxStreamWrapper
.is())
200 throw NotConnectedException();
202 return mxStreamWrapper
->available();
205 void SAL_CALL
GraphicInputStream::closeInput()
207 if (!mxStreamWrapper
.is())
208 throw NotConnectedException();
210 mxStreamWrapper
->closeInput();
213 class SvXMLGraphicOutputStream
:
214 public cppu::WeakImplHelper
<XOutputStream
>
219 virtual void SAL_CALL
writeBytes( const Sequence
< sal_Int8
>& rData
) override
;
220 virtual void SAL_CALL
flush() override
;
221 virtual void SAL_CALL
closeOutput() override
;
225 std::unique_ptr
<::utl::TempFile
> mpTmp
;
226 std::unique_ptr
<SvStream
> mpOStm
;
227 Reference
< XOutputStream
> mxStmWrapper
;
228 std::unique_ptr
<GraphicObject
> mxGrfObj
;
233 SvXMLGraphicOutputStream();
234 virtual ~SvXMLGraphicOutputStream() override
;
235 SvXMLGraphicOutputStream(const SvXMLGraphicOutputStream
&) = delete;
236 SvXMLGraphicOutputStream
& operator=(const SvXMLGraphicOutputStream
&) = delete;
238 bool Exists() const { return mxStmWrapper
.is(); }
239 const GraphicObject
& GetGraphicObject();
240 Graphic
GetGraphic();
243 SvXMLGraphicOutputStream::SvXMLGraphicOutputStream()
244 : mpTmp(new ::utl::TempFile
)
245 , mxGrfObj(new GraphicObject
)
248 mpTmp
->EnableKillingFile();
250 mpOStm
= ::utl::UcbStreamHelper::CreateStream( mpTmp
->GetURL(), StreamMode::WRITE
| StreamMode::TRUNC
);
253 mxStmWrapper
= new ::utl::OOutputStreamWrapper( *mpOStm
);
256 SvXMLGraphicOutputStream::~SvXMLGraphicOutputStream()
262 void SAL_CALL
SvXMLGraphicOutputStream::writeBytes( const Sequence
< sal_Int8
>& rData
)
264 if( !mxStmWrapper
.is() )
265 throw NotConnectedException() ;
267 mxStmWrapper
->writeBytes( rData
);
270 void SAL_CALL
SvXMLGraphicOutputStream::flush()
272 if( !mxStmWrapper
.is() )
273 throw NotConnectedException() ;
275 mxStmWrapper
->flush();
278 void SAL_CALL
SvXMLGraphicOutputStream::closeOutput()
280 if( !mxStmWrapper
.is() )
281 throw NotConnectedException() ;
283 mxStmWrapper
->closeOutput();
284 mxStmWrapper
.clear();
289 Graphic
SvXMLGraphicOutputStream::GetGraphic()
293 if (mbClosed
&& mxGrfObj
->GetType() == GraphicType::NONE
&& mpOStm
)
296 sal_uInt16 nFormat
= GRFILTER_FORMAT_DONTKNOW
;
297 sal_uInt16 nDeterminedFormat
= GRFILTER_FORMAT_DONTKNOW
;
298 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic
, "", *mpOStm
,nFormat
,&nDeterminedFormat
);
300 if (nDeterminedFormat
== GRFILTER_FORMAT_DONTKNOW
)
302 //Read the first two byte to check whether it is a gzipped stream, is so it may be in wmz or emz format
303 //unzip them and try again
305 sal_uInt8 sFirstBytes
[ 2 ];
307 sal_uInt64 nStreamLen
= mpOStm
->TellEnd();
310 if ( nStreamLen
== 0 )
312 SvLockBytes
* pLockBytes
= mpOStm
->GetLockBytes();
314 pLockBytes
->SetSynchronMode();
316 nStreamLen
= mpOStm
->TellEnd();
319 if( nStreamLen
>= 2 )
322 mpOStm
->ReadBytes(sFirstBytes
, 2);
324 if( sFirstBytes
[0] == 0x1f && sFirstBytes
[1] == 0x8b )
326 SvMemoryStream aDest
;
327 ZCodec
aZCodec( 0x8000, 0x8000 );
328 aZCodec
.BeginCompression(ZCODEC_DEFAULT_COMPRESSION
, /*gzLib*/true);
330 aZCodec
.Decompress( *mpOStm
, aDest
);
332 if (aZCodec
.EndCompression())
334 sal_uInt64 nStreamLen_
= aDest
.TellEnd();
338 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic
, "", aDest
,nFormat
,&nDeterminedFormat
);
346 if (aGraphic
.GetType() != GraphicType::NONE
)
354 const GraphicObject
& SvXMLGraphicOutputStream::GetGraphicObject()
356 Graphic
aGraphic(GetGraphic());
357 if (aGraphic
.GetType() != GraphicType::NONE
)
359 mxGrfObj
.reset(new GraphicObject(aGraphic
));
366 SvXMLGraphicHelper::SvXMLGraphicHelper(SvXMLGraphicHelperMode eCreateMode
)
367 : cppu::WeakComponentImplHelper
<document::XGraphicObjectResolver
,
368 document::XGraphicStorageHandler
,
369 document::XBinaryStreamResolver
>(maMutex
)
371 Init( nullptr, eCreateMode
);
374 SvXMLGraphicHelper::SvXMLGraphicHelper()
375 : cppu::WeakComponentImplHelper
<document::XGraphicObjectResolver
,
376 document::XGraphicStorageHandler
,
377 document::XBinaryStreamResolver
>(maMutex
)
378 , meCreateMode(SvXMLGraphicHelperMode::Read
)
382 SvXMLGraphicHelper::~SvXMLGraphicHelper()
386 void SAL_CALL
SvXMLGraphicHelper::disposing()
390 bool SvXMLGraphicHelper::ImplGetStreamNames( const OUString
& rURLStr
,
391 OUString
& rPictureStorageName
,
392 OUString
& rPictureStreamName
)
394 if (rURLStr
.isEmpty())
397 const OUString aURLStr
{rURLStr
.copy(rURLStr
.lastIndexOf(':')+1)};
399 if( !aURLStr
.isEmpty() && aURLStr
.indexOf('/')<0 ) // just one token?
401 rPictureStorageName
= XML_GRAPHICSTORAGE_NAME
;
402 rPictureStreamName
= aURLStr
;
405 SvXMLEmbeddedObjectHelper::splitObjectURL(aURLStr
, rPictureStorageName
, rPictureStreamName
);
407 SAL_WARN_IF(rPictureStreamName
.isEmpty(), "svx", "SvXMLGraphicHelper::ImplInsertGraphicURL: invalid scheme: " << rURLStr
);
409 return !rPictureStreamName
.isEmpty();
412 uno::Reference
< embed::XStorage
> SvXMLGraphicHelper::ImplGetGraphicStorage( const OUString
& rStorageName
)
414 uno::Reference
< embed::XStorage
> xRetStorage
;
415 if( mxRootStorage
.is() )
419 maCurStorageName
= rStorageName
;
420 xRetStorage
= mxRootStorage
->openStorageElement(
422 ( SvXMLGraphicHelperMode::Write
== meCreateMode
)
423 ? embed::ElementModes::READWRITE
424 : embed::ElementModes::READ
);
426 catch ( uno::Exception
& )
429 //#i43196# try again to open the storage element - this time readonly
430 if(!xRetStorage
.is())
434 maCurStorageName
= rStorageName
;
435 xRetStorage
= mxRootStorage
->openStorageElement( maCurStorageName
, embed::ElementModes::READ
);
437 catch ( uno::Exception
& )
446 SvxGraphicHelperStream_Impl
SvXMLGraphicHelper::ImplGetGraphicStream( const OUString
& rPictureStorageName
,
447 const OUString
& rPictureStreamName
)
449 SvxGraphicHelperStream_Impl aRet
;
450 aRet
.xStorage
= ImplGetGraphicStorage( rPictureStorageName
);
452 sal_Int32 nMode
= embed::ElementModes::READ
;
453 if (SvXMLGraphicHelperMode::Write
== meCreateMode
)
455 nMode
= embed::ElementModes::READWRITE
;
458 if (aRet
.xStorage
.is())
460 aRet
.xStream
= aRet
.xStorage
->openStreamElement( rPictureStreamName
, nMode
);
462 else if (rPictureStorageName
.indexOf('/') != -1)
464 uno::Reference
<embed::XHierarchicalStorageAccess
> xHierRootStorage(mxRootStorage
,
466 if (xHierRootStorage
.is())
470 aRet
.xStream
= xHierRootStorage
->openStreamElementByHierarchicalName(
471 rPictureStorageName
+ "/" + rPictureStreamName
, nMode
);
472 aRet
.xStorage
= mxRootStorage
;
474 catch (const uno::Exception
&)
476 TOOLS_WARN_EXCEPTION("svx",
477 "SvXMLGraphicHelper::ImplGetGraphicStream: failed to open "
478 << rPictureStreamName
);
483 if (aRet
.xStream
.is() && (SvXMLGraphicHelperMode::Write
== meCreateMode
))
485 uno::Reference
<beans::XPropertySet
> xProps(aRet
.xStream
, uno::UNO_QUERY
);
486 xProps
->setPropertyValue("UseCommonStoragePasswordEncryption", uno::makeAny(true));
492 OUString
SvXMLGraphicHelper::ImplGetGraphicMimeType( const OUString
& rFileName
)
494 if( ( rFileName
.getLength() >= 4 ) && ( rFileName
[ rFileName
.getLength() - 4 ] == '.' ) )
496 const OString
aExt(OUStringToOString(rFileName
.subView(rFileName
.getLength() - 3),
497 RTL_TEXTENCODING_ASCII_US
));
498 return comphelper::GraphicMimeTypeHelper::GetMimeTypeForExtension( aExt
);
504 Graphic
SvXMLGraphicHelper::ImplReadGraphic( const OUString
& rPictureStorageName
,
505 const OUString
& rPictureStreamName
)
507 Graphic aReturnGraphic
;
508 SvxGraphicHelperStream_Impl
aStream( ImplGetGraphicStream( rPictureStorageName
, rPictureStreamName
) );
509 if (aStream
.xStream
.is())
511 GraphicFilter
& rGraphicFilter
= GraphicFilter::GetGraphicFilter();
512 std::unique_ptr
<SvStream
> pStream(utl::UcbStreamHelper::CreateStream(aStream
.xStream
));
513 Graphic aGraphic
= rGraphicFilter
.ImportUnloadedGraphic(*pStream
);
514 if (!aGraphic
.IsNone())
515 aReturnGraphic
= aGraphic
;
517 rGraphicFilter
.ImportGraphic(aReturnGraphic
, "", *pStream
);
520 return aReturnGraphic
;
523 void SvXMLGraphicHelper::Init( const uno::Reference
< embed::XStorage
>& rXMLStorage
,
524 SvXMLGraphicHelperMode eCreateMode
,
525 const OUString
& rGraphicMimeType
)
527 mxRootStorage
= rXMLStorage
;
528 meCreateMode
= eCreateMode
;
529 maOutputMimeType
= rGraphicMimeType
;
532 rtl::Reference
<SvXMLGraphicHelper
> SvXMLGraphicHelper::Create( const uno::Reference
< embed::XStorage
>& rXMLStorage
,
533 SvXMLGraphicHelperMode eCreateMode
)
535 rtl::Reference
<SvXMLGraphicHelper
> pThis
= new SvXMLGraphicHelper
;
536 pThis
->Init( rXMLStorage
, eCreateMode
, OUString() );
541 rtl::Reference
<SvXMLGraphicHelper
> SvXMLGraphicHelper::Create( SvXMLGraphicHelperMode eCreateMode
,
542 const OUString
& rGraphicMimeType
)
544 rtl::Reference
<SvXMLGraphicHelper
> pThis
= new SvXMLGraphicHelper
;
546 pThis
->Init( nullptr, eCreateMode
, rGraphicMimeType
);
554 void splitUserDataFromURL(OUString
const & rWholeURL
, OUString
& rJustURL
, OUString
& rUserData
)
556 sal_Int32 nUser
= rWholeURL
.indexOf('?');
559 rJustURL
= rWholeURL
.copy(0, nUser
);
561 rUserData
= rWholeURL
.copy(nUser
);
565 rJustURL
= rWholeURL
;
569 } // end anonymous namespace
571 // XGraphicObjectResolver
572 OUString SAL_CALL
SvXMLGraphicHelper::resolveGraphicObjectURL( const OUString
& /*rURL*/ )
574 throw uno::RuntimeException("XGraphicObjectResolver has been removed in LibreOffice 6.1");
577 // XGraphicStorageHandler
578 uno::Reference
<graphic::XGraphic
> SAL_CALL
SvXMLGraphicHelper::loadGraphic(OUString
const & rURL
)
580 osl::MutexGuard
aGuard(maMutex
);
582 uno::Reference
<graphic::XGraphic
> xGraphic
;
586 splitUserDataFromURL(rURL
, aURLOnly
, aUserData
);
588 auto aIterator
= maGraphicObjects
.find(aURLOnly
);
589 if (aIterator
!= maGraphicObjects
.end())
591 return aIterator
->second
;
594 OUString aPictureStorageName
, aPictureStreamName
;
596 if (ImplGetStreamNames(aURLOnly
, aPictureStorageName
, aPictureStreamName
))
598 const GraphicObject
aGraphicObject(ImplReadGraphic(aPictureStorageName
, aPictureStreamName
));
600 if (aGraphicObject
.GetType() != GraphicType::NONE
)
602 xGraphic
= aGraphicObject
.GetGraphic().GetXGraphic();
603 maGraphicObjects
[aURLOnly
] = xGraphic
;
610 uno::Reference
<graphic::XGraphic
> SAL_CALL
SvXMLGraphicHelper::loadGraphicFromOutputStream(uno::Reference
<io::XOutputStream
> const & rxOutputStream
)
612 osl::MutexGuard
aGuard(maMutex
);
614 uno::Reference
<graphic::XGraphic
> xGraphic
;
616 if ((SvXMLGraphicHelperMode::Read
== meCreateMode
) && rxOutputStream
.is())
619 SvXMLGraphicOutputStream
* pGraphicOutputStream
= static_cast<SvXMLGraphicOutputStream
*>(rxOutputStream
.get());
620 if (pGraphicOutputStream
)
622 xGraphic
= pGraphicOutputStream
->GetGraphic().GetXGraphic();
628 OUString SAL_CALL
SvXMLGraphicHelper::saveGraphicByName(css::uno::Reference
<css::graphic::XGraphic
> const & rxGraphic
,
629 OUString
& rOutSavedMimeType
, OUString
const & rRequestName
)
631 return implSaveGraphic(rxGraphic
, rOutSavedMimeType
, rRequestName
);
634 OUString SAL_CALL
SvXMLGraphicHelper::saveGraphic(css::uno::Reference
<css::graphic::XGraphic
> const & rxGraphic
)
636 OUString aOutMimeType
;
637 return implSaveGraphic(rxGraphic
, aOutMimeType
, std::u16string_view());
640 OUString
SvXMLGraphicHelper::implSaveGraphic(css::uno::Reference
<css::graphic::XGraphic
> const & rxGraphic
,
641 OUString
& rOutSavedMimeType
, std::u16string_view rRequestName
)
643 Graphic
aGraphic(rxGraphic
);
645 auto aIterator
= maExportGraphics
.find(aGraphic
);
646 if (aIterator
!= maExportGraphics
.end())
648 auto const & aURLAndMimePair
= aIterator
->second
;
649 rOutSavedMimeType
= aURLAndMimePair
.second
;
650 return aURLAndMimePair
.first
;
653 GraphicObject
aGraphicObject(aGraphic
);
655 if (aGraphicObject
.GetType() != GraphicType::NONE
)
657 const GfxLink
aGfxLink(aGraphic
.GetGfxLink());
659 bool bUseGfxLink
= true;
661 if (aGfxLink
.GetDataSize())
663 switch (aGfxLink
.GetType())
665 case GfxLinkType::EpsBuffer
: aExtension
= ".eps"; break;
666 case GfxLinkType::NativeGif
: aExtension
= ".gif"; break;
667 // #i15508# added BMP type for better exports (checked, works)
668 case GfxLinkType::NativeBmp
: aExtension
= ".bmp"; break;
669 case GfxLinkType::NativeJpg
: aExtension
= ".jpg"; break;
670 case GfxLinkType::NativePng
: aExtension
= ".png"; break;
671 case GfxLinkType::NativeTif
: aExtension
= ".tif"; break;
672 case GfxLinkType::NativeWmf
:
673 if (aGfxLink
.IsEMF())
678 case GfxLinkType::NativeMet
: aExtension
= ".met"; break;
679 case GfxLinkType::NativePct
: aExtension
= ".pct"; break;
680 case GfxLinkType::NativeSvg
:
681 // backward-compat kludge: since no released OOo
682 // version to date can handle svg properly, wrap it up
683 // into an svm. slight catch22 here, since strict ODF
684 // conformance _recommends_ svg - then again, most old
685 // ODF consumers are believed to be OOo
686 if (SvtSaveOptions().GetODFSaneDefaultVersion() < SvtSaveOptions::ODFSVER_012
687 || SvtSaveOptions().GetODFSaneDefaultVersion() == SvtSaveOptions::ODFSVER_012_EXT_COMPAT
)
697 case GfxLinkType::NativePdf
: aExtension
= ".pdf"; break;
706 if (aGraphicObject
.GetType() == GraphicType::Bitmap
)
708 if (aGraphicObject
.IsAnimated())
713 else if (aGraphicObject
.GetType() == GraphicType::GdiMetafile
)
715 // SJ: first check if this metafile is just an eps file, then we will store the eps instead of svm
716 GDIMetaFile
& rMetafile(const_cast<GDIMetaFile
&>(aGraphic
.GetGDIMetaFile()));
718 if (ImplCheckForEPS(rMetafile
))
725 OUString rPictureStreamName
;
726 if (!rRequestName
.empty())
728 rPictureStreamName
= rRequestName
+ aExtension
;
732 OUString sId
= OStringToOUString(aGraphicObject
.GetUniqueID(), RTL_TEXTENCODING_ASCII_US
);
733 rPictureStreamName
= sId
+ aExtension
;
736 SvxGraphicHelperStream_Impl
aStream(ImplGetGraphicStream(XML_GRAPHICSTORAGE_NAME
, rPictureStreamName
));
738 if (aStream
.xStream
.is())
740 const OUString
aMimeType(ImplGetGraphicMimeType(rPictureStreamName
));
741 uno::Reference
<beans::XPropertySet
> xProps(aStream
.xStream
, uno::UNO_QUERY
);
743 // set stream properties (MediaType/Compression)
744 if (!aMimeType
.isEmpty())
746 xProps
->setPropertyValue("MediaType", uno::Any(aMimeType
));
749 // picture formats that actually _do_ benefit from zip
750 // storage compression
751 // .svm pics gets compressed via ZBITMAP old-style stream
753 static const char* aCompressiblePics
[] =
764 bool bSuccess
= false;
766 bool bCompressed
= aMimeType
.isEmpty();
769 for(const char* p
: aCompressiblePics
)
771 if( aMimeType
.equalsIgnoreAsciiCaseAscii(p
) )
779 xProps
->setPropertyValue("Compressed", Any(bCompressed
));
781 std::unique_ptr
<SvStream
> pStream(utl::UcbStreamHelper::CreateStream(aStream
.xStream
));
782 if (bUseGfxLink
&& aGfxLink
.GetDataSize() && aGfxLink
.GetData())
784 pStream
->WriteBytes(aGfxLink
.GetData(), aGfxLink
.GetDataSize());
785 rOutSavedMimeType
= aMimeType
;
786 bSuccess
= (pStream
->GetError() == ERRCODE_NONE
);
790 if (aGraphic
.GetType() == GraphicType::Bitmap
)
792 GraphicFilter
& rFilter
= GraphicFilter::GetGraphicFilter();
795 if (aGraphic
.IsAnimated())
803 rOutSavedMimeType
= comphelper::GraphicMimeTypeHelper::GetMimeTypeForExtension(aFormat
.toUtf8());
805 bSuccess
= (rFilter
.ExportGraphic(aGraphic
, "", *pStream
, rFilter
.GetExportFormatNumberForShortName(aFormat
)) == ERRCODE_NONE
);
807 else if (aGraphic
.GetType() == GraphicType::GdiMetafile
)
809 pStream
->SetVersion(SOFFICE_FILEFORMAT_8
);
810 pStream
->SetCompressMode(SvStreamCompressFlags::ZBITMAP
);
811 rOutSavedMimeType
= comphelper::GraphicMimeTypeHelper::GetMimeTypeForExtension("svm");
813 // SJ: first check if this metafile is just an eps file, then we will store the eps instead of svm
814 GDIMetaFile
& rMtf(const_cast<GDIMetaFile
&>(aGraphic
.GetGDIMetaFile()));
815 const MetaCommentAction
* pComment
= ImplCheckForEPS(rMtf
);
818 sal_uInt32 nSize
= pComment
->GetDataSize();
819 const sal_uInt8
* pData
= pComment
->GetData();
821 pStream
->WriteBytes(pData
, nSize
);
823 const MetaEPSAction
* pAct
= static_cast<const MetaEPSAction
*>(rMtf
.FirstAction());
824 const GfxLink
& rLink
= pAct
->GetLink();
826 pStream
->WriteBytes(rLink
.GetData(), rLink
.GetDataSize());
830 rMtf
.Write(*pStream
);
833 bSuccess
= (pStream
->GetError() == ERRCODE_NONE
);
840 uno::Reference
<embed::XTransactedObject
> xStorage(aStream
.xStorage
, uno::UNO_QUERY
);
842 aStream
.xStream
->getOutputStream()->closeOutput();
846 OUString aStoragePath
= "Pictures/" + rPictureStreamName
;
849 maExportGraphics
[aGraphic
] = std::make_pair(aStoragePath
, rOutSavedMimeType
);
858 uno::Reference
<io::XInputStream
> SAL_CALL
SvXMLGraphicHelper::createInputStream(uno::Reference
<graphic::XGraphic
> const & rxGraphic
)
860 Reference
<XInputStream
> xInputStream
;
862 Graphic
aGraphic(rxGraphic
);
863 GraphicObject
aGraphicObject(aGraphic
);
865 if (SvXMLGraphicHelperMode::Write
== meCreateMode
)
867 OUString sMimeType
= comphelper::GraphicMimeTypeHelper::GetMimeTypeForExtension(OUStringToOString(maOutputMimeType
, RTL_TEXTENCODING_ASCII_US
));
868 rtl::Reference
<GraphicInputStream
> pInputStream(new GraphicInputStream(aGraphicObject
, sMimeType
));
870 // We release the pointer from unique_ptr and assign it to the input stream return type.
871 // In case the stream doesn't exists, unique_ptr will delete the pointer when we go out of scope.
872 if (pInputStream
->exists())
873 xInputStream
= pInputStream
.get();
879 // XBinaryStreamResolver
880 Reference
< XInputStream
> SAL_CALL
SvXMLGraphicHelper::getInputStream( const OUString
& /*rURL*/ )
882 Reference
<XInputStream
> xRet
;
886 Reference
< XOutputStream
> SAL_CALL
SvXMLGraphicHelper::createOutputStream()
888 Reference
< XOutputStream
> xRet
;
890 if( SvXMLGraphicHelperMode::Read
== meCreateMode
)
892 rtl::Reference
<SvXMLGraphicOutputStream
> pOutputStream(new SvXMLGraphicOutputStream
);
894 if( pOutputStream
->Exists() )
896 xRet
= pOutputStream
.get();
897 maGrfStms
.push_back( xRet
);
904 OUString SAL_CALL
SvXMLGraphicHelper::resolveOutputStream( const Reference
< XOutputStream
>& rxBinaryStream
)
908 if( ( SvXMLGraphicHelperMode::Read
== meCreateMode
) && rxBinaryStream
.is() )
910 if( ::std::find( maGrfStms
.begin(), maGrfStms
.end(), rxBinaryStream
) != maGrfStms
.end() )
912 SvXMLGraphicOutputStream
* pOStm
= static_cast< SvXMLGraphicOutputStream
* >( rxBinaryStream
.get() );
916 const GraphicObject
& rGrfObj
= pOStm
->GetGraphicObject();
917 const OUString
aId(OStringToOUString(
918 rGrfObj
.GetUniqueID(), RTL_TEXTENCODING_ASCII_US
));
922 aRet
= XML_GRAPHICOBJECT_URL_BASE
+ aId
;
931 // for instantiation via service manager
936 typedef cppu::WeakComponentImplHelper
<lang::XInitialization
,
937 document::XGraphicObjectResolver
,
938 document::XGraphicStorageHandler
,
939 document::XBinaryStreamResolver
,
941 SvXMLGraphicImportExportHelper_Base
;
946 virtual ~MutexContainer();
949 mutable ::osl::Mutex m_aMutex
;
952 MutexContainer::~MutexContainer()
957 class SvXMLGraphicImportExportHelper
:
958 public impl::MutexContainer
,
959 public impl::SvXMLGraphicImportExportHelper_Base
962 explicit SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode
);
965 // is called from WeakComponentImplHelper when XComponent::dispose() was
966 // called from outside
967 virtual void SAL_CALL
disposing() override
;
969 // ____ XInitialization ____
970 // one argument is allowed, which is the XStorage
971 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
) override
;
973 // ____ XGraphicObjectResolver ____
974 virtual OUString SAL_CALL
resolveGraphicObjectURL( const OUString
& aURL
) override
;
976 // ____ XGraphicStorageHandler ____
977 virtual css::uno::Reference
<css::graphic::XGraphic
> SAL_CALL
978 loadGraphic(const OUString
& aURL
) override
;
980 virtual css::uno::Reference
<css::graphic::XGraphic
> SAL_CALL
981 loadGraphicFromOutputStream(css::uno::Reference
<css::io::XOutputStream
> const & rxOutputStream
) override
;
983 virtual OUString SAL_CALL
984 saveGraphic(css::uno::Reference
<css::graphic::XGraphic
> const & rxGraphic
) override
;
986 virtual OUString SAL_CALL
987 saveGraphicByName(css::uno::Reference
<css::graphic::XGraphic
> const & rxGraphic
, OUString
& rOutSavedMimeType
, OUString
const & rRequestName
) override
;
989 virtual css::uno::Reference
<css::io::XInputStream
> SAL_CALL
990 createInputStream(css::uno::Reference
<css::graphic::XGraphic
> const & rxGraphic
) override
;
992 // ____ XBinaryStreamResolver ____
993 virtual Reference
< io::XInputStream
> SAL_CALL
getInputStream( const OUString
& aURL
) override
;
994 virtual Reference
< io::XOutputStream
> SAL_CALL
createOutputStream() override
;
995 virtual OUString SAL_CALL
resolveOutputStream( const Reference
< io::XOutputStream
>& aBinaryStream
) override
;
997 // ____ XServiceInfo ____
998 virtual OUString SAL_CALL
getImplementationName() override
;
999 virtual sal_Bool SAL_CALL
supportsService( const OUString
& ServiceName
) override
;
1000 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
1003 SvXMLGraphicHelperMode m_eGraphicHelperMode
;
1004 Reference
< XGraphicObjectResolver
> m_xGraphicObjectResolver
;
1005 Reference
< XGraphicStorageHandler
> m_xGraphicStorageHandler
;
1006 Reference
< XBinaryStreamResolver
> m_xBinaryStreamResolver
;
1009 SvXMLGraphicImportExportHelper::SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode
) :
1010 impl::SvXMLGraphicImportExportHelper_Base( m_aMutex
),
1011 m_eGraphicHelperMode( eMode
)
1014 void SAL_CALL
SvXMLGraphicImportExportHelper::disposing()
1016 Reference
< XComponent
> xComp( m_xGraphicObjectResolver
, UNO_QUERY
);
1017 OSL_ASSERT( xComp
.is());
1020 // m_xBinaryStreamResolver and m_xGraphicStorageHandler are a reference to the same object,
1021 // don't call dispose() again
1024 // ____ XInitialization ____
1025 void SAL_CALL
SvXMLGraphicImportExportHelper::initialize(
1026 const Sequence
< Any
>& aArguments
)
1028 Reference
< embed::XStorage
> xStorage
;
1029 if( aArguments
.hasElements() )
1030 aArguments
[0] >>= xStorage
;
1032 rtl::Reference
<SvXMLGraphicHelper
> pHelper( SvXMLGraphicHelper::Create( xStorage
, m_eGraphicHelperMode
));
1033 m_xGraphicObjectResolver
= pHelper
;
1034 m_xGraphicStorageHandler
= pHelper
;
1035 m_xBinaryStreamResolver
= pHelper
;
1038 // ____ XGraphicObjectResolver ____
1039 OUString SAL_CALL
SvXMLGraphicImportExportHelper::resolveGraphicObjectURL( const OUString
& aURL
)
1041 return m_xGraphicObjectResolver
->resolveGraphicObjectURL( aURL
);
1044 // ____ XGraphicStorageHandler ____
1045 uno::Reference
<graphic::XGraphic
> SAL_CALL
SvXMLGraphicImportExportHelper::loadGraphic(OUString
const & rURL
)
1047 return m_xGraphicStorageHandler
->loadGraphic(rURL
);
1050 uno::Reference
<graphic::XGraphic
> SAL_CALL
SvXMLGraphicImportExportHelper::loadGraphicFromOutputStream(uno::Reference
<io::XOutputStream
> const & rxOutputStream
)
1052 return m_xGraphicStorageHandler
->loadGraphicFromOutputStream(rxOutputStream
);
1055 OUString SAL_CALL
SvXMLGraphicImportExportHelper::saveGraphic(css::uno::Reference
<css::graphic::XGraphic
> const & rxGraphic
)
1057 return m_xGraphicStorageHandler
->saveGraphic(rxGraphic
);
1060 OUString SAL_CALL
SvXMLGraphicImportExportHelper::saveGraphicByName(css::uno::Reference
<css::graphic::XGraphic
> const & rxGraphic
,
1061 OUString
& rOutSavedMimeType
, OUString
const & rRequestName
)
1063 return m_xGraphicStorageHandler
->saveGraphicByName(rxGraphic
, rOutSavedMimeType
, rRequestName
);
1066 uno::Reference
<io::XInputStream
> SAL_CALL
SvXMLGraphicImportExportHelper::createInputStream(uno::Reference
<graphic::XGraphic
> const & rxGraphic
)
1068 return m_xGraphicStorageHandler
->createInputStream(rxGraphic
);
1071 // ____ XBinaryStreamResolver ____
1072 Reference
< io::XInputStream
> SAL_CALL
SvXMLGraphicImportExportHelper::getInputStream( const OUString
& aURL
)
1074 return m_xBinaryStreamResolver
->getInputStream( aURL
);
1076 Reference
< io::XOutputStream
> SAL_CALL
SvXMLGraphicImportExportHelper::createOutputStream()
1078 return m_xBinaryStreamResolver
->createOutputStream();
1080 OUString SAL_CALL
SvXMLGraphicImportExportHelper::resolveOutputStream( const Reference
< io::XOutputStream
>& aBinaryStream
)
1082 return m_xBinaryStreamResolver
->resolveOutputStream( aBinaryStream
);
1085 // ____ XServiceInfo ____
1086 OUString SAL_CALL
SvXMLGraphicImportExportHelper::getImplementationName()
1088 if( m_eGraphicHelperMode
== SvXMLGraphicHelperMode::Read
)
1089 return "com.sun.star.comp.Svx.GraphicImportHelper";
1090 return "com.sun.star.comp.Svx.GraphicExportHelper";
1093 sal_Bool SAL_CALL
SvXMLGraphicImportExportHelper::supportsService( const OUString
& ServiceName
)
1095 return cppu::supportsService(this, ServiceName
);
1098 Sequence
< OUString
> SAL_CALL
SvXMLGraphicImportExportHelper::getSupportedServiceNames()
1100 return { "com.sun.star.document.GraphicObjectResolver",
1101 "com.sun.star.document.GraphicStorageHandler",
1102 "com.sun.star.document.BinaryStreamResolver" };
1107 /** Create this with createInstanceWithArguments. service name
1108 "com.sun.star.comp.Svx.GraphicImportHelper", one argument which is the
1109 XStorage. Without arguments no helper class is created. With an empty
1110 argument the helper class is created and initialized like in the CTOR to
1111 SvXMLGraphicHelper that only gets the create mode.
1113 You should call dispose after you no longer need this component.
1115 uses eCreateMode == SvXMLGraphicHelperMode::Read, bDirect == sal_True in
1118 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1119 com_sun_star_comp_Svx_GraphicImportHelper_get_implementation(
1120 css::uno::XComponentContext
*,
1121 css::uno::Sequence
<css::uno::Any
> const &)
1123 return cppu::acquire(new SvXMLGraphicImportExportHelper(SvXMLGraphicHelperMode::Read
));
1126 /** Create this with createInstanceWithArguments. service name
1127 "com.sun.star.comp.Svx.GraphicExportHelper", one argument which is the
1128 XStorage. Without arguments no helper class is created. With an empty
1129 argument the helper class is created and initialized like in the CTOR to
1130 SvXMLGraphicHelper that only gets the create mode
1132 To write the Pictures stream, you have to call dispose at this component.
1133 Make sure you call dispose before you commit the parent storage.
1135 uses eCreateMode == SvXMLGraphicHelperMode::Write, bDirect == sal_True in
1138 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1139 com_sun_star_comp_Svx_GraphicExportHelper_get_implementation(
1140 css::uno::XComponentContext
*,
1141 css::uno::Sequence
<css::uno::Any
> const &)
1143 return cppu::acquire(new SvXMLGraphicImportExportHelper(SvXMLGraphicHelperMode::Write
));
1148 void DropUnusedNamedItems(css::uno::Reference
<css::uno::XInterface
> const& xModel
)
1150 uno::Reference
<lang::XMultiServiceFactory
> const xModelFactory(xModel
, uno::UNO_QUERY
);
1151 assert(xModelFactory
.is());
1154 uno::Reference
<util::XCancellable
> const xGradient(
1155 xModelFactory
->createInstance("com.sun.star.drawing.GradientTable"),
1159 xGradient
->cancel();
1162 uno::Reference
<util::XCancellable
> const xHatch(
1163 xModelFactory
->createInstance("com.sun.star.drawing.HatchTable"),
1170 uno::Reference
<util::XCancellable
> const xBitmap(
1171 xModelFactory
->createInstance("com.sun.star.drawing.BitmapTable"),
1178 uno::Reference
<util::XCancellable
> const xTransGradient(
1179 xModelFactory
->createInstance("com.sun.star.drawing.TransparencyGradientTable"),
1181 if (xTransGradient
.is())
1183 xTransGradient
->cancel();
1186 uno::Reference
<util::XCancellable
> const xMarker(
1187 xModelFactory
->createInstance("com.sun.star.drawing.MarkerTable"),
1194 uno::Reference
<util::XCancellable
> const xDashes(
1195 xModelFactory
->createInstance("com.sun.star.drawing.DashTable"),
1202 catch (const Exception
&)
1204 TOOLS_WARN_EXCEPTION("svx", "dropUnusedNamedItems(): exception during clearing of unused named items");
1210 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */