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 <comphelper/fileformat.h>
30 #include <comphelper/graphicmimetype.hxx>
31 #include <cppuhelper/compbase.hxx>
32 #include <cppuhelper/implbase.hxx>
33 #include <cppuhelper/supportsservice.hxx>
35 #include <rtl/ref.hxx>
36 #include <unotools/ucbstreamhelper.hxx>
37 #include <unotools/streamwrap.hxx>
38 #include <unotools/tempfile.hxx>
39 #include <unotools/saveopt.hxx>
40 #include <vcl/gfxlink.hxx>
41 #include <vcl/metaact.hxx>
42 #include <tools/zcodec.hxx>
44 #include <vcl/GraphicObject.hxx>
45 #include <vcl/graphicfilter.hxx>
46 #include <svx/xmlgrhlp.hxx>
47 #include <svx/xmleohlp.hxx>
53 using namespace com::sun::star
;
54 using namespace com::sun::star::uno
;
55 using namespace com::sun::star::io
;
57 namespace com::sun::star::uno
{ class XComponentContext
; }
59 #define XML_GRAPHICSTORAGE_NAME "Pictures"
60 #define XML_GRAPHICOBJECT_URL_BASE "vnd.sun.star.GraphicObject:"
64 const MetaCommentAction
* ImplCheckForEPS( GDIMetaFile
const & rMtf
)
66 const MetaCommentAction
* pComment
= nullptr;
68 if ( rMtf
.GetActionSize() >= 2
69 && rMtf
.GetAction(0)->GetType() == MetaActionType::EPS
70 && rMtf
.GetAction(1)->GetType() == MetaActionType::COMMENT
71 && ( static_cast<const MetaCommentAction
*>(rMtf
.GetAction( 1 ))->GetComment() == "EPSReplacementGraphic" ) )
72 pComment
= static_cast<const MetaCommentAction
*>(rMtf
.GetAction( 1 ));
77 class GraphicInputStream
: public cppu::WeakImplHelper
<XInputStream
>
80 virtual sal_Int32 SAL_CALL
readBytes(Sequence
<sal_Int8
> & aData
, sal_Int32 nBytesToRead
) override
;
81 virtual sal_Int32 SAL_CALL
readSomeBytes(Sequence
<sal_Int8
> & aData
, sal_Int32 nMaxBytesToRead
) override
;
82 virtual void SAL_CALL
skipBytes(sal_Int32 nBytesToSkip
) override
;
83 virtual sal_Int32 SAL_CALL
available() override
;
84 virtual void SAL_CALL
closeInput() override
;
87 utl::TempFile maTempFile
;
88 Reference
<XInputStream
> mxStreamWrapper
;
92 explicit GraphicInputStream(GraphicObject
const & raGraphicObject
, const OUString
& rMimeType
);
93 GraphicInputStream(const GraphicInputStream
&) = delete;
95 GraphicInputStream
& operator=(const GraphicInputStream
&) = delete;
99 return mxStreamWrapper
.is();
104 GraphicInputStream::GraphicInputStream(GraphicObject
const & aGraphicObject
, const OUString
& rMimeType
)
106 maTempFile
.EnableKillingFile();
108 if (aGraphicObject
.GetType() == GraphicType::NONE
)
111 std::unique_ptr
<SvStream
> pStream
= ::utl::UcbStreamHelper::CreateStream(maTempFile
.GetURL(), StreamMode::WRITE
| StreamMode::TRUNC
);
116 const Graphic
& aGraphic(aGraphicObject
.GetGraphic());
117 const GfxLink
aGfxLink(aGraphic
.GetGfxLink());
120 if (aGfxLink
.GetDataSize() && aGfxLink
.GetData())
122 if (rMimeType
.isEmpty())
124 pStream
->WriteBytes(aGfxLink
.GetData(), aGfxLink
.GetDataSize());
125 bRet
= (pStream
->GetError() == ERRCODE_NONE
);
129 GraphicFilter
&rFilter
= GraphicFilter::GetGraphicFilter();
130 bRet
= (rFilter
.ExportGraphic(aGraphic
, "", *pStream
, rFilter
.GetExportFormatNumberForMediaType(rMimeType
)) == ERRCODE_NONE
);
135 if (aGraphic
.GetType() == GraphicType::Bitmap
)
137 GraphicFilter
& rFilter
= GraphicFilter::GetGraphicFilter();
138 OUString aFormat
= rMimeType
;
140 if (aGraphic
.IsAnimated())
141 aFormat
= "image/gif";
142 else if (aFormat
.isEmpty())
143 aFormat
= "image/png";
145 bRet
= (rFilter
.ExportGraphic(aGraphic
, "", *pStream
, rFilter
.GetExportFormatNumberForMediaType(aFormat
)) == ERRCODE_NONE
);
147 else if (rMimeType
.isEmpty() && aGraphic
.GetType() == GraphicType::GdiMetafile
)
149 pStream
->SetVersion(SOFFICE_FILEFORMAT_8
);
150 pStream
->SetCompressMode(SvStreamCompressFlags::ZBITMAP
);
151 const_cast<GDIMetaFile
&>(aGraphic
.GetGDIMetaFile()).Write(*pStream
);
152 bRet
= (pStream
->GetError() == ERRCODE_NONE
);
154 else if (!rMimeType
.isEmpty())
156 GraphicFilter
& rFilter
= GraphicFilter::GetGraphicFilter();
157 bRet
= ( rFilter
.ExportGraphic( aGraphic
, "", *pStream
, rFilter
.GetExportFormatNumberForMediaType( rMimeType
) ) == ERRCODE_NONE
);
164 mxStreamWrapper
= new ::utl::OInputStreamWrapper(std::move(pStream
));
168 sal_Int32 SAL_CALL
GraphicInputStream::readBytes(Sequence
<sal_Int8
> & rData
, sal_Int32 nBytesToRead
)
170 if (!mxStreamWrapper
.is())
171 throw NotConnectedException();
173 return mxStreamWrapper
->readBytes(rData
, nBytesToRead
);
176 sal_Int32 SAL_CALL
GraphicInputStream::readSomeBytes(Sequence
<sal_Int8
>& rData
, sal_Int32 nMaxBytesToRead
)
178 if (!mxStreamWrapper
.is())
179 throw NotConnectedException() ;
181 return mxStreamWrapper
->readSomeBytes(rData
, nMaxBytesToRead
);
184 void SAL_CALL
GraphicInputStream::skipBytes(sal_Int32 nBytesToSkip
)
186 if (!mxStreamWrapper
.is())
187 throw NotConnectedException();
189 mxStreamWrapper
->skipBytes(nBytesToSkip
);
192 sal_Int32 SAL_CALL
GraphicInputStream::available()
194 if (!mxStreamWrapper
.is())
195 throw NotConnectedException();
197 return mxStreamWrapper
->available();
200 void SAL_CALL
GraphicInputStream::closeInput()
202 if (!mxStreamWrapper
.is())
203 throw NotConnectedException();
205 mxStreamWrapper
->closeInput();
208 class SvXMLGraphicOutputStream
:
209 public cppu::WeakImplHelper
<XOutputStream
>
214 virtual void SAL_CALL
writeBytes( const Sequence
< sal_Int8
>& rData
) override
;
215 virtual void SAL_CALL
flush() override
;
216 virtual void SAL_CALL
closeOutput() override
;
220 std::unique_ptr
<::utl::TempFile
> mpTmp
;
221 std::unique_ptr
<SvStream
> mpOStm
;
222 Reference
< XOutputStream
> mxStmWrapper
;
223 std::unique_ptr
<GraphicObject
> mxGrfObj
;
228 SvXMLGraphicOutputStream();
229 virtual ~SvXMLGraphicOutputStream() override
;
230 SvXMLGraphicOutputStream(const SvXMLGraphicOutputStream
&) = delete;
231 SvXMLGraphicOutputStream
& operator=(const SvXMLGraphicOutputStream
&) = delete;
233 bool Exists() const { return mxStmWrapper
.is(); }
234 const GraphicObject
& GetGraphicObject();
235 Graphic
GetGraphic();
238 SvXMLGraphicOutputStream::SvXMLGraphicOutputStream()
239 : mpTmp(new ::utl::TempFile
)
240 , mxGrfObj(new GraphicObject
)
243 mpTmp
->EnableKillingFile();
245 mpOStm
= ::utl::UcbStreamHelper::CreateStream( mpTmp
->GetURL(), StreamMode::WRITE
| StreamMode::TRUNC
);
248 mxStmWrapper
= new ::utl::OOutputStreamWrapper( *mpOStm
);
251 SvXMLGraphicOutputStream::~SvXMLGraphicOutputStream()
257 void SAL_CALL
SvXMLGraphicOutputStream::writeBytes( const Sequence
< sal_Int8
>& rData
)
259 if( !mxStmWrapper
.is() )
260 throw NotConnectedException() ;
262 mxStmWrapper
->writeBytes( rData
);
265 void SAL_CALL
SvXMLGraphicOutputStream::flush()
267 if( !mxStmWrapper
.is() )
268 throw NotConnectedException() ;
270 mxStmWrapper
->flush();
273 void SAL_CALL
SvXMLGraphicOutputStream::closeOutput()
275 if( !mxStmWrapper
.is() )
276 throw NotConnectedException() ;
278 mxStmWrapper
->closeOutput();
279 mxStmWrapper
.clear();
284 Graphic
SvXMLGraphicOutputStream::GetGraphic()
288 if (mbClosed
&& mxGrfObj
->GetType() == GraphicType::NONE
&& mpOStm
)
291 sal_uInt16 nFormat
= GRFILTER_FORMAT_DONTKNOW
;
292 sal_uInt16 nDeterminedFormat
= GRFILTER_FORMAT_DONTKNOW
;
293 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic
, "", *mpOStm
,nFormat
,&nDeterminedFormat
);
295 if (nDeterminedFormat
== GRFILTER_FORMAT_DONTKNOW
)
297 //Read the first two byte to check whether it is a gzipped stream, is so it may be in wmz or emz format
298 //unzip them and try again
300 sal_uInt8 sFirstBytes
[ 2 ];
302 sal_uInt64 nStreamLen
= mpOStm
->TellEnd();
305 if ( nStreamLen
== 0 )
307 SvLockBytes
* pLockBytes
= mpOStm
->GetLockBytes();
309 pLockBytes
->SetSynchronMode();
311 nStreamLen
= mpOStm
->TellEnd();
314 if( nStreamLen
>= 2 )
317 mpOStm
->ReadBytes(sFirstBytes
, 2);
319 if( sFirstBytes
[0] == 0x1f && sFirstBytes
[1] == 0x8b )
321 std::unique_ptr
<SvMemoryStream
> pDest(new SvMemoryStream
);
322 ZCodec
aZCodec( 0x8000, 0x8000 );
323 aZCodec
.BeginCompression(ZCODEC_DEFAULT_COMPRESSION
, /*gzLib*/true);
325 aZCodec
.Decompress( *mpOStm
, *pDest
);
327 if (aZCodec
.EndCompression())
329 sal_uInt64 nStreamLen_
= pDest
->TellEnd();
333 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic
, "", *pDest
,nFormat
,&nDeterminedFormat
);
341 if (aGraphic
.GetType() != GraphicType::NONE
)
349 const GraphicObject
& SvXMLGraphicOutputStream::GetGraphicObject()
351 Graphic
aGraphic(GetGraphic());
352 if (aGraphic
.GetType() != GraphicType::NONE
)
354 mxGrfObj
.reset(new GraphicObject(aGraphic
));
361 SvXMLGraphicHelper::SvXMLGraphicHelper(SvXMLGraphicHelperMode eCreateMode
)
362 : cppu::WeakComponentImplHelper
<document::XGraphicObjectResolver
,
363 document::XGraphicStorageHandler
,
364 document::XBinaryStreamResolver
>(maMutex
)
366 Init( nullptr, eCreateMode
);
369 SvXMLGraphicHelper::SvXMLGraphicHelper()
370 : cppu::WeakComponentImplHelper
<document::XGraphicObjectResolver
,
371 document::XGraphicStorageHandler
,
372 document::XBinaryStreamResolver
>(maMutex
)
373 , meCreateMode(SvXMLGraphicHelperMode::Read
)
377 SvXMLGraphicHelper::~SvXMLGraphicHelper()
381 void SAL_CALL
SvXMLGraphicHelper::disposing()
385 bool SvXMLGraphicHelper::ImplGetStreamNames( const OUString
& rURLStr
,
386 OUString
& rPictureStorageName
,
387 OUString
& rPictureStreamName
)
389 if (rURLStr
.isEmpty())
392 const OUString aURLStr
{rURLStr
.copy(rURLStr
.lastIndexOf(':')+1)};
394 if( !aURLStr
.isEmpty() && aURLStr
.indexOf('/')<0 ) // just one token?
396 rPictureStorageName
= XML_GRAPHICSTORAGE_NAME
;
397 rPictureStreamName
= aURLStr
;
400 SvXMLEmbeddedObjectHelper::splitObjectURL(aURLStr
, rPictureStorageName
, rPictureStreamName
);
402 SAL_WARN_IF(rPictureStreamName
.isEmpty(), "svx", "SvXMLGraphicHelper::ImplInsertGraphicURL: invalid scheme: " << rURLStr
);
404 return !rPictureStreamName
.isEmpty();
407 uno::Reference
< embed::XStorage
> SvXMLGraphicHelper::ImplGetGraphicStorage( const OUString
& rStorageName
)
409 uno::Reference
< embed::XStorage
> xRetStorage
;
410 if( mxRootStorage
.is() )
414 maCurStorageName
= rStorageName
;
415 xRetStorage
= mxRootStorage
->openStorageElement(
417 ( SvXMLGraphicHelperMode::Write
== meCreateMode
)
418 ? embed::ElementModes::READWRITE
419 : embed::ElementModes::READ
);
421 catch ( uno::Exception
& )
424 //#i43196# try again to open the storage element - this time readonly
425 if(!xRetStorage
.is())
429 maCurStorageName
= rStorageName
;
430 xRetStorage
= mxRootStorage
->openStorageElement( maCurStorageName
, embed::ElementModes::READ
);
432 catch ( uno::Exception
& )
441 SvxGraphicHelperStream_Impl
SvXMLGraphicHelper::ImplGetGraphicStream( const OUString
& rPictureStorageName
,
442 const OUString
& rPictureStreamName
)
444 SvxGraphicHelperStream_Impl aRet
;
445 aRet
.xStorage
= ImplGetGraphicStorage( rPictureStorageName
);
447 if( aRet
.xStorage
.is() )
449 sal_Int32 nMode
= embed::ElementModes::READ
;
450 if ( SvXMLGraphicHelperMode::Write
== meCreateMode
)
452 nMode
= embed::ElementModes::READWRITE
;
455 aRet
.xStream
= aRet
.xStorage
->openStreamElement( rPictureStreamName
, nMode
);
456 if( aRet
.xStream
.is() && ( SvXMLGraphicHelperMode::Write
== meCreateMode
) )
458 uno::Reference
< beans::XPropertySet
> xProps( aRet
.xStream
, uno::UNO_QUERY
);
459 xProps
->setPropertyValue( "UseCommonStoragePasswordEncryption", uno::makeAny( true) );
466 OUString
SvXMLGraphicHelper::ImplGetGraphicMimeType( const OUString
& rFileName
)
468 if( ( rFileName
.getLength() >= 4 ) && ( rFileName
[ rFileName
.getLength() - 4 ] == '.' ) )
470 const OString
aExt(OUStringToOString(rFileName
.copy(rFileName
.getLength() - 3),
471 RTL_TEXTENCODING_ASCII_US
));
472 return comphelper::GraphicMimeTypeHelper::GetMimeTypeForExtension( aExt
);
478 Graphic
SvXMLGraphicHelper::ImplReadGraphic( const OUString
& rPictureStorageName
,
479 const OUString
& rPictureStreamName
)
481 Graphic aReturnGraphic
;
482 SvxGraphicHelperStream_Impl
aStream( ImplGetGraphicStream( rPictureStorageName
, rPictureStreamName
) );
483 if (aStream
.xStream
.is())
485 GraphicFilter
& rGraphicFilter
= GraphicFilter::GetGraphicFilter();
486 std::unique_ptr
<SvStream
> pStream(utl::UcbStreamHelper::CreateStream(aStream
.xStream
));
487 Graphic aGraphic
= rGraphicFilter
.ImportUnloadedGraphic(*pStream
);
488 if (!aGraphic
.IsNone())
489 aReturnGraphic
= aGraphic
;
491 rGraphicFilter
.ImportGraphic(aReturnGraphic
, "", *pStream
);
494 return aReturnGraphic
;
497 void SvXMLGraphicHelper::Init( const uno::Reference
< embed::XStorage
>& rXMLStorage
,
498 SvXMLGraphicHelperMode eCreateMode
,
499 const OUString
& rGraphicMimeType
)
501 mxRootStorage
= rXMLStorage
;
502 meCreateMode
= eCreateMode
;
503 maOutputMimeType
= rGraphicMimeType
;
506 rtl::Reference
<SvXMLGraphicHelper
> SvXMLGraphicHelper::Create( const uno::Reference
< embed::XStorage
>& rXMLStorage
,
507 SvXMLGraphicHelperMode eCreateMode
)
509 rtl::Reference
<SvXMLGraphicHelper
> pThis
= new SvXMLGraphicHelper
;
510 pThis
->Init( rXMLStorage
, eCreateMode
, OUString() );
515 rtl::Reference
<SvXMLGraphicHelper
> SvXMLGraphicHelper::Create( SvXMLGraphicHelperMode eCreateMode
,
516 const OUString
& rGraphicMimeType
)
518 rtl::Reference
<SvXMLGraphicHelper
> pThis
= new SvXMLGraphicHelper
;
520 pThis
->Init( nullptr, eCreateMode
, rGraphicMimeType
);
528 void splitUserDataFromURL(OUString
const & rWholeURL
, OUString
& rJustURL
, OUString
& rUserData
)
530 sal_Int32 nUser
= rWholeURL
.indexOf('?');
533 rJustURL
= rWholeURL
.copy(0, nUser
);
535 rUserData
= rWholeURL
.copy(nUser
);
539 rJustURL
= rWholeURL
;
543 } // end anonymous namespace
545 // XGraphicObjectResolver
546 OUString SAL_CALL
SvXMLGraphicHelper::resolveGraphicObjectURL( const OUString
& /*rURL*/ )
548 throw uno::RuntimeException("XGraphicObjectResolver has been removed in LibreOffice 6.1");
551 // XGraphicStorageHandler
552 uno::Reference
<graphic::XGraphic
> SAL_CALL
SvXMLGraphicHelper::loadGraphic(OUString
const & rURL
)
554 osl::MutexGuard
aGuard(maMutex
);
556 uno::Reference
<graphic::XGraphic
> xGraphic
;
560 splitUserDataFromURL(rURL
, aURLOnly
, aUserData
);
562 auto aIterator
= maGraphicObjects
.find(aURLOnly
);
563 if (aIterator
!= maGraphicObjects
.end())
565 return aIterator
->second
;
568 OUString aPictureStorageName
, aPictureStreamName
;
570 if (ImplGetStreamNames(aURLOnly
, aPictureStorageName
, aPictureStreamName
))
572 const GraphicObject
aGraphicObject(ImplReadGraphic(aPictureStorageName
, aPictureStreamName
));
574 if (aGraphicObject
.GetType() != GraphicType::NONE
)
576 xGraphic
= aGraphicObject
.GetGraphic().GetXGraphic();
577 maGraphicObjects
[aURLOnly
] = xGraphic
;
584 uno::Reference
<graphic::XGraphic
> SAL_CALL
SvXMLGraphicHelper::loadGraphicFromOutputStream(uno::Reference
<io::XOutputStream
> const & rxOutputStream
)
586 osl::MutexGuard
aGuard(maMutex
);
588 uno::Reference
<graphic::XGraphic
> xGraphic
;
590 if ((SvXMLGraphicHelperMode::Read
== meCreateMode
) && rxOutputStream
.is())
593 SvXMLGraphicOutputStream
* pGraphicOutputStream
= static_cast<SvXMLGraphicOutputStream
*>(rxOutputStream
.get());
594 if (pGraphicOutputStream
)
596 xGraphic
= pGraphicOutputStream
->GetGraphic().GetXGraphic();
602 OUString SAL_CALL
SvXMLGraphicHelper::saveGraphicByName(css::uno::Reference
<css::graphic::XGraphic
> const & rxGraphic
,
603 OUString
& rOutSavedMimeType
, OUString
const & rRequestName
)
605 return implSaveGraphic(rxGraphic
, rOutSavedMimeType
, rRequestName
);
608 OUString SAL_CALL
SvXMLGraphicHelper::saveGraphic(css::uno::Reference
<css::graphic::XGraphic
> const & rxGraphic
)
610 OUString aOutMimeType
;
611 return implSaveGraphic(rxGraphic
, aOutMimeType
, OUString());
614 OUString
SvXMLGraphicHelper::implSaveGraphic(css::uno::Reference
<css::graphic::XGraphic
> const & rxGraphic
,
615 OUString
& rOutSavedMimeType
, OUString
const & rRequestName
)
617 Graphic
aGraphic(rxGraphic
);
619 auto aIterator
= maExportGraphics
.find(aGraphic
);
620 if (aIterator
!= maExportGraphics
.end())
622 auto const & aURLAndMimePair
= aIterator
->second
;
623 rOutSavedMimeType
= aURLAndMimePair
.second
;
624 return aURLAndMimePair
.first
;
627 GraphicObject
aGraphicObject(aGraphic
);
629 if (aGraphicObject
.GetType() != GraphicType::NONE
)
631 const GfxLink
aGfxLink(aGraphic
.GetGfxLink());
633 bool bUseGfxLink
= true;
635 if (aGfxLink
.GetDataSize())
637 switch (aGfxLink
.GetType())
639 case GfxLinkType::EpsBuffer
: aExtension
= ".eps"; break;
640 case GfxLinkType::NativeGif
: aExtension
= ".gif"; break;
641 // #i15508# added BMP type for better exports (checked, works)
642 case GfxLinkType::NativeBmp
: aExtension
= ".bmp"; break;
643 case GfxLinkType::NativeJpg
: aExtension
= ".jpg"; break;
644 case GfxLinkType::NativePng
: aExtension
= ".png"; break;
645 case GfxLinkType::NativeTif
: aExtension
= ".tif"; break;
646 case GfxLinkType::NativeWmf
:
647 if (aGfxLink
.IsEMF())
652 case GfxLinkType::NativeMet
: aExtension
= ".met"; break;
653 case GfxLinkType::NativePct
: aExtension
= ".pct"; break;
654 case GfxLinkType::NativeSvg
:
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().GetODFSaneDefaultVersion() < SvtSaveOptions::ODFSVER_012
661 || SvtSaveOptions().GetODFSaneDefaultVersion() == SvtSaveOptions::ODFSVER_012_EXT_COMPAT
)
671 case GfxLinkType::NativePdf
: aExtension
= ".pdf"; break;
680 if (aGraphicObject
.GetType() == GraphicType::Bitmap
)
682 if (aGraphicObject
.IsAnimated())
687 else if (aGraphicObject
.GetType() == GraphicType::GdiMetafile
)
689 // SJ: first check if this metafile is just an eps file, then we will store the eps instead of svm
690 GDIMetaFile
& rMetafile(const_cast<GDIMetaFile
&>(aGraphic
.GetGDIMetaFile()));
692 if (ImplCheckForEPS(rMetafile
))
699 OUString rPictureStreamName
;
700 if (!rRequestName
.isEmpty())
702 rPictureStreamName
= rRequestName
+ aExtension
;
706 OUString sId
= OStringToOUString(aGraphicObject
.GetUniqueID(), RTL_TEXTENCODING_ASCII_US
);
707 rPictureStreamName
= sId
+ aExtension
;
710 SvxGraphicHelperStream_Impl
aStream(ImplGetGraphicStream(XML_GRAPHICSTORAGE_NAME
, rPictureStreamName
));
712 if (aStream
.xStream
.is())
714 const OUString
aMimeType(ImplGetGraphicMimeType(rPictureStreamName
));
715 uno::Reference
<beans::XPropertySet
> xProps(aStream
.xStream
, uno::UNO_QUERY
);
717 // set stream properties (MediaType/Compression)
718 if (!aMimeType
.isEmpty())
720 xProps
->setPropertyValue("MediaType", uno::Any(aMimeType
));
723 // picture formats that actually _do_ benefit from zip
724 // storage compression
725 // .svm pics gets compressed via ZBITMAP old-style stream
727 static const char* aCompressiblePics
[] =
738 bool bSuccess
= false;
740 bool bCompressed
= aMimeType
.isEmpty();
743 for(const char* p
: aCompressiblePics
)
745 if( aMimeType
.equalsIgnoreAsciiCaseAscii(p
) )
753 xProps
->setPropertyValue("Compressed", Any(bCompressed
));
755 std::unique_ptr
<SvStream
> pStream(utl::UcbStreamHelper::CreateStream(aStream
.xStream
));
756 if (bUseGfxLink
&& aGfxLink
.GetDataSize() && aGfxLink
.GetData())
758 pStream
->WriteBytes(aGfxLink
.GetData(), aGfxLink
.GetDataSize());
759 rOutSavedMimeType
= aMimeType
;
760 bSuccess
= (pStream
->GetError() == ERRCODE_NONE
);
764 if (aGraphic
.GetType() == GraphicType::Bitmap
)
766 GraphicFilter
& rFilter
= GraphicFilter::GetGraphicFilter();
769 if (aGraphic
.IsAnimated())
777 rOutSavedMimeType
= comphelper::GraphicMimeTypeHelper::GetMimeTypeForExtension(aFormat
.toUtf8());
779 bSuccess
= (rFilter
.ExportGraphic(aGraphic
, "", *pStream
, rFilter
.GetExportFormatNumberForShortName(aFormat
)) == ERRCODE_NONE
);
781 else if (aGraphic
.GetType() == GraphicType::GdiMetafile
)
783 pStream
->SetVersion(SOFFICE_FILEFORMAT_8
);
784 pStream
->SetCompressMode(SvStreamCompressFlags::ZBITMAP
);
785 rOutSavedMimeType
= comphelper::GraphicMimeTypeHelper::GetMimeTypeForExtension("svm");
787 // SJ: first check if this metafile is just an eps file, then we will store the eps instead of svm
788 GDIMetaFile
& rMtf(const_cast<GDIMetaFile
&>(aGraphic
.GetGDIMetaFile()));
789 const MetaCommentAction
* pComment
= ImplCheckForEPS(rMtf
);
792 sal_uInt32 nSize
= pComment
->GetDataSize();
793 const sal_uInt8
* pData
= pComment
->GetData();
795 pStream
->WriteBytes(pData
, nSize
);
797 const MetaEPSAction
* pAct
= static_cast<const MetaEPSAction
*>(rMtf
.FirstAction());
798 const GfxLink
& rLink
= pAct
->GetLink();
800 pStream
->WriteBytes(rLink
.GetData(), rLink
.GetDataSize());
804 rMtf
.Write(*pStream
);
807 bSuccess
= (pStream
->GetError() == ERRCODE_NONE
);
814 uno::Reference
<embed::XTransactedObject
> xStorage(aStream
.xStorage
, uno::UNO_QUERY
);
816 aStream
.xStream
->getOutputStream()->closeOutput();
820 OUString aStoragePath
= "Pictures/" + rPictureStreamName
;
823 maExportGraphics
[aGraphic
] = std::make_pair(aStoragePath
, rOutSavedMimeType
);
832 uno::Reference
<io::XInputStream
> SAL_CALL
SvXMLGraphicHelper::createInputStream(uno::Reference
<graphic::XGraphic
> const & rxGraphic
)
834 Reference
<XInputStream
> xInputStream
;
836 Graphic
aGraphic(rxGraphic
);
837 GraphicObject
aGraphicObject(aGraphic
);
839 if (SvXMLGraphicHelperMode::Write
== meCreateMode
)
841 OUString sMimeType
= comphelper::GraphicMimeTypeHelper::GetMimeTypeForExtension(OUStringToOString(maOutputMimeType
, RTL_TEXTENCODING_ASCII_US
));
842 std::unique_ptr
<GraphicInputStream
> pInputStream(new GraphicInputStream(aGraphicObject
, sMimeType
));
844 // We release the pointer from unique_ptr and assign it to the input stream return type.
845 // In case the stream doesn't exists, unique_ptr will delete the pointer when we go out of scope.
846 if (pInputStream
->exists())
847 xInputStream
= pInputStream
.release();
853 // XBinaryStreamResolver
854 Reference
< XInputStream
> SAL_CALL
SvXMLGraphicHelper::getInputStream( const OUString
& /*rURL*/ )
856 Reference
<XInputStream
> xRet
;
860 Reference
< XOutputStream
> SAL_CALL
SvXMLGraphicHelper::createOutputStream()
862 Reference
< XOutputStream
> xRet
;
864 if( SvXMLGraphicHelperMode::Read
== meCreateMode
)
866 std::unique_ptr
<SvXMLGraphicOutputStream
> pOutputStream(new SvXMLGraphicOutputStream
);
868 if( pOutputStream
->Exists() )
870 xRet
= pOutputStream
.release();
871 maGrfStms
.push_back( xRet
);
878 OUString SAL_CALL
SvXMLGraphicHelper::resolveOutputStream( const Reference
< XOutputStream
>& rxBinaryStream
)
882 if( ( SvXMLGraphicHelperMode::Read
== meCreateMode
) && rxBinaryStream
.is() )
884 if( ::std::find( maGrfStms
.begin(), maGrfStms
.end(), rxBinaryStream
) != maGrfStms
.end() )
886 SvXMLGraphicOutputStream
* pOStm
= static_cast< SvXMLGraphicOutputStream
* >( rxBinaryStream
.get() );
890 const GraphicObject
& rGrfObj
= pOStm
->GetGraphicObject();
891 const OUString
aId(OStringToOUString(
892 rGrfObj
.GetUniqueID(), RTL_TEXTENCODING_ASCII_US
));
896 aRet
= XML_GRAPHICOBJECT_URL_BASE
+ aId
;
905 // for instantiation via service manager
910 typedef cppu::WeakComponentImplHelper
<lang::XInitialization
,
911 document::XGraphicObjectResolver
,
912 document::XGraphicStorageHandler
,
913 document::XBinaryStreamResolver
,
915 SvXMLGraphicImportExportHelper_Base
;
920 virtual ~MutexContainer();
923 mutable ::osl::Mutex m_aMutex
;
926 MutexContainer::~MutexContainer()
931 class SvXMLGraphicImportExportHelper
:
932 public impl::MutexContainer
,
933 public impl::SvXMLGraphicImportExportHelper_Base
936 explicit SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode
);
939 // is called from WeakComponentImplHelper when XComponent::dispose() was
940 // called from outside
941 virtual void SAL_CALL
disposing() override
;
943 // ____ XInitialization ____
944 // one argument is allowed, which is the XStorage
945 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
) override
;
947 // ____ XGraphicObjectResolver ____
948 virtual OUString SAL_CALL
resolveGraphicObjectURL( const OUString
& aURL
) override
;
950 // ____ XGraphicStorageHandler ____
951 virtual css::uno::Reference
<css::graphic::XGraphic
> SAL_CALL
952 loadGraphic(const OUString
& aURL
) override
;
954 virtual css::uno::Reference
<css::graphic::XGraphic
> SAL_CALL
955 loadGraphicFromOutputStream(css::uno::Reference
<css::io::XOutputStream
> const & rxOutputStream
) override
;
957 virtual OUString SAL_CALL
958 saveGraphic(css::uno::Reference
<css::graphic::XGraphic
> const & rxGraphic
) override
;
960 virtual OUString SAL_CALL
961 saveGraphicByName(css::uno::Reference
<css::graphic::XGraphic
> const & rxGraphic
, OUString
& rOutSavedMimeType
, OUString
const & rRequestName
) override
;
963 virtual css::uno::Reference
<css::io::XInputStream
> SAL_CALL
964 createInputStream(css::uno::Reference
<css::graphic::XGraphic
> const & rxGraphic
) override
;
966 // ____ XBinaryStreamResolver ____
967 virtual Reference
< io::XInputStream
> SAL_CALL
getInputStream( const OUString
& aURL
) override
;
968 virtual Reference
< io::XOutputStream
> SAL_CALL
createOutputStream() override
;
969 virtual OUString SAL_CALL
resolveOutputStream( const Reference
< io::XOutputStream
>& aBinaryStream
) override
;
971 // ____ XServiceInfo ____
972 virtual OUString SAL_CALL
getImplementationName() override
;
973 virtual sal_Bool SAL_CALL
supportsService( const OUString
& ServiceName
) override
;
974 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
977 SvXMLGraphicHelperMode m_eGraphicHelperMode
;
978 Reference
< XGraphicObjectResolver
> m_xGraphicObjectResolver
;
979 Reference
< XGraphicStorageHandler
> m_xGraphicStorageHandler
;
980 Reference
< XBinaryStreamResolver
> m_xBinaryStreamResolver
;
983 SvXMLGraphicImportExportHelper::SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode
) :
984 impl::SvXMLGraphicImportExportHelper_Base( m_aMutex
),
985 m_eGraphicHelperMode( eMode
)
988 void SAL_CALL
SvXMLGraphicImportExportHelper::disposing()
990 Reference
< XComponent
> xComp( m_xGraphicObjectResolver
, UNO_QUERY
);
991 OSL_ASSERT( xComp
.is());
994 // m_xBinaryStreamResolver and m_xGraphicStorageHandler are a reference to the same object,
995 // don't call dispose() again
998 // ____ XInitialization ____
999 void SAL_CALL
SvXMLGraphicImportExportHelper::initialize(
1000 const Sequence
< Any
>& aArguments
)
1002 Reference
< embed::XStorage
> xStorage
;
1003 if( aArguments
.hasElements() )
1004 aArguments
[0] >>= xStorage
;
1006 rtl::Reference
<SvXMLGraphicHelper
> pHelper( SvXMLGraphicHelper::Create( xStorage
, m_eGraphicHelperMode
));
1007 m_xGraphicObjectResolver
.set( pHelper
.get() );
1008 m_xGraphicStorageHandler
.set( pHelper
.get() );
1009 m_xBinaryStreamResolver
.set( pHelper
.get() );
1012 // ____ XGraphicObjectResolver ____
1013 OUString SAL_CALL
SvXMLGraphicImportExportHelper::resolveGraphicObjectURL( const OUString
& aURL
)
1015 return m_xGraphicObjectResolver
->resolveGraphicObjectURL( aURL
);
1018 // ____ XGraphicStorageHandler ____
1019 uno::Reference
<graphic::XGraphic
> SAL_CALL
SvXMLGraphicImportExportHelper::loadGraphic(OUString
const & rURL
)
1021 return m_xGraphicStorageHandler
->loadGraphic(rURL
);
1024 uno::Reference
<graphic::XGraphic
> SAL_CALL
SvXMLGraphicImportExportHelper::loadGraphicFromOutputStream(uno::Reference
<io::XOutputStream
> const & rxOutputStream
)
1026 return m_xGraphicStorageHandler
->loadGraphicFromOutputStream(rxOutputStream
);
1029 OUString SAL_CALL
SvXMLGraphicImportExportHelper::saveGraphic(css::uno::Reference
<css::graphic::XGraphic
> const & rxGraphic
)
1031 return m_xGraphicStorageHandler
->saveGraphic(rxGraphic
);
1034 OUString SAL_CALL
SvXMLGraphicImportExportHelper::saveGraphicByName(css::uno::Reference
<css::graphic::XGraphic
> const & rxGraphic
,
1035 OUString
& rOutSavedMimeType
, OUString
const & rRequestName
)
1037 return m_xGraphicStorageHandler
->saveGraphicByName(rxGraphic
, rOutSavedMimeType
, rRequestName
);
1040 uno::Reference
<io::XInputStream
> SAL_CALL
SvXMLGraphicImportExportHelper::createInputStream(uno::Reference
<graphic::XGraphic
> const & rxGraphic
)
1042 return m_xGraphicStorageHandler
->createInputStream(rxGraphic
);
1045 // ____ XBinaryStreamResolver ____
1046 Reference
< io::XInputStream
> SAL_CALL
SvXMLGraphicImportExportHelper::getInputStream( const OUString
& aURL
)
1048 return m_xBinaryStreamResolver
->getInputStream( aURL
);
1050 Reference
< io::XOutputStream
> SAL_CALL
SvXMLGraphicImportExportHelper::createOutputStream()
1052 return m_xBinaryStreamResolver
->createOutputStream();
1054 OUString SAL_CALL
SvXMLGraphicImportExportHelper::resolveOutputStream( const Reference
< io::XOutputStream
>& aBinaryStream
)
1056 return m_xBinaryStreamResolver
->resolveOutputStream( aBinaryStream
);
1059 // ____ XServiceInfo ____
1060 OUString SAL_CALL
SvXMLGraphicImportExportHelper::getImplementationName()
1062 if( m_eGraphicHelperMode
== SvXMLGraphicHelperMode::Read
)
1063 return "com.sun.star.comp.Svx.GraphicImportHelper";
1064 return "com.sun.star.comp.Svx.GraphicExportHelper";
1067 sal_Bool SAL_CALL
SvXMLGraphicImportExportHelper::supportsService( const OUString
& ServiceName
)
1069 return cppu::supportsService(this, ServiceName
);
1072 Sequence
< OUString
> SAL_CALL
SvXMLGraphicImportExportHelper::getSupportedServiceNames()
1074 return { "com.sun.star.document.GraphicObjectResolver",
1075 "com.sun.star.document.GraphicStorageHandler",
1076 "com.sun.star.document.BinaryStreamResolver" };
1081 /** Create this with createInstanceWithArguments. service name
1082 "com.sun.star.comp.Svx.GraphicImportHelper", one argument which is the
1083 XStorage. Without arguments no helper class is created. With an empty
1084 argument the helper class is created and initialized like in the CTOR to
1085 SvXMLGraphicHelper that only gets the create mode.
1087 You should call dispose after you no longer need this component.
1089 uses eCreateMode == SvXMLGraphicHelperMode::Read, bDirect == sal_True in
1092 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1093 com_sun_star_comp_Svx_GraphicImportHelper_get_implementation(
1094 css::uno::XComponentContext
*,
1095 css::uno::Sequence
<css::uno::Any
> const &)
1097 return cppu::acquire(new SvXMLGraphicImportExportHelper(SvXMLGraphicHelperMode::Read
));
1100 /** Create this with createInstanceWithArguments. service name
1101 "com.sun.star.comp.Svx.GraphicExportHelper", one argument which is the
1102 XStorage. Without arguments no helper class is created. With an empty
1103 argument the helper class is created and initialized like in the CTOR to
1104 SvXMLGraphicHelper that only gets the create mode
1106 To write the Pictures stream, you have to call dispose at this component.
1107 Make sure you call dispose before you commit the parent storage.
1109 uses eCreateMode == SvXMLGraphicHelperMode::Write, bDirect == sal_True in
1112 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1113 com_sun_star_comp_Svx_GraphicExportHelper_get_implementation(
1114 css::uno::XComponentContext
*,
1115 css::uno::Sequence
<css::uno::Any
> const &)
1117 return cppu::acquire(new SvXMLGraphicImportExportHelper(SvXMLGraphicHelperMode::Write
));
1120 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */