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 <comphelper/string.hxx>
21 #include <sal/macros.h>
22 #include <rtl/strbuf.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/lang/XMultiServiceFactory.hpp>
27 #include <com/sun/star/lang/XServiceInfo.hpp>
28 #include <com/sun/star/lang/XInitialization.hpp>
29 #include <cppuhelper/compbase4.hxx>
31 #include <unotools/ucbstreamhelper.hxx>
32 #include <unotools/streamwrap.hxx>
33 #include <unotools/tempfile.hxx>
34 #include <unotools/saveopt.hxx>
35 #include <tools/debug.hxx>
36 #include <vcl/cvtgrf.hxx>
37 #include <vcl/gfxlink.hxx>
38 #include <vcl/metaact.hxx>
39 #include <tools/zcodec.hxx>
41 #include <vcl/graphicfilter.hxx>
42 #include "svx/xmlgrhlp.hxx"
43 #include "svx/xmleohlp.hxx"
47 using namespace com::sun::star
;
48 using namespace com::sun::star::uno
;
49 using namespace com::sun::star::io
;
51 using ::com::sun::star::lang::XMultiServiceFactory
;
53 #define XML_GRAPHICSTORAGE_NAME "Pictures"
54 #define XML_GRAPHICOBJECT_URL_BASE "vnd.sun.star.GraphicObject:"
56 const MetaCommentAction
* ImplCheckForEPS( GDIMetaFile
& rMtf
)
58 const MetaCommentAction
* pComment
= NULL
;
60 if ( ( rMtf
.GetActionSize() >= 2 )
61 && ( rMtf
.FirstAction()->GetType() == META_EPS_ACTION
)
62 && ( ((const MetaAction
*)rMtf
.GetAction( 1 ))->GetType() == META_COMMENT_ACTION
)
63 && ( ((const MetaCommentAction
*)rMtf
.GetAction( 1 ))->GetComment().equalsL(RTL_CONSTASCII_STRINGPARAM("EPSReplacementGraphic")) ) )
64 pComment
= (const MetaCommentAction
*)rMtf
.GetAction( 1 );
69 class SvXMLGraphicInputStream
: public::cppu::WeakImplHelper1
< XInputStream
>
73 virtual sal_Int32 SAL_CALL
readBytes( Sequence
< sal_Int8
>& aData
, sal_Int32 nBytesToRead
) throw(NotConnectedException
, BufferSizeExceededException
, RuntimeException
);
74 virtual sal_Int32 SAL_CALL
readSomeBytes(Sequence
< sal_Int8
>& aData
, sal_Int32 nMaxBytesToRead
) throw(NotConnectedException
, BufferSizeExceededException
, RuntimeException
);
75 virtual void SAL_CALL
skipBytes(sal_Int32 nBytesToSkip
) throw(NotConnectedException
, BufferSizeExceededException
, RuntimeException
);
76 virtual sal_Int32 SAL_CALL
available() throw(NotConnectedException
, RuntimeException
);
77 virtual void SAL_CALL
closeInput() throw(NotConnectedException
, RuntimeException
);
81 ::utl::TempFile maTmp
;
82 Reference
< XInputStream
> mxStmWrapper
;
85 SvXMLGraphicInputStream();
86 SvXMLGraphicInputStream( const SvXMLGraphicInputStream
& );
87 SvXMLGraphicInputStream
& operator==( SvXMLGraphicInputStream
& );
91 SvXMLGraphicInputStream( const OUString
& rGraphicId
);
92 virtual ~SvXMLGraphicInputStream();
94 bool Exists() const { return mxStmWrapper
.is(); }
97 SvXMLGraphicInputStream::SvXMLGraphicInputStream( const OUString
& rGraphicId
)
99 GraphicObject
aGrfObject( OUStringToOString(rGraphicId
, RTL_TEXTENCODING_ASCII_US
) );
101 maTmp
.EnableKillingFile();
103 if( aGrfObject
.GetType() != GRAPHIC_NONE
)
105 SvStream
* pStm
= ::utl::UcbStreamHelper::CreateStream( maTmp
.GetURL(), STREAM_WRITE
| STREAM_TRUNC
);
109 Graphic
aGraphic( (Graphic
&) aGrfObject
.GetGraphic() );
110 const GfxLink
aGfxLink( aGraphic
.GetLink() );
111 sal_Bool bRet
= sal_False
;
113 if( aGfxLink
.GetDataSize() && aGfxLink
.GetData() )
115 pStm
->Write( aGfxLink
.GetData(), aGfxLink
.GetDataSize() );
116 bRet
= ( pStm
->GetError() == 0 );
120 if( aGraphic
.GetType() == GRAPHIC_BITMAP
)
122 GraphicFilter
&rFilter
= GraphicFilter::GetGraphicFilter();
125 if( aGraphic
.IsAnimated() )
126 aFormat
= String( "gif" );
128 aFormat
= String( "png" );
130 bRet
= ( rFilter
.ExportGraphic( aGraphic
, String(), *pStm
, rFilter
.GetExportFormatNumberForShortName( aFormat
) ) == 0 );
132 else if( aGraphic
.GetType() == GRAPHIC_GDIMETAFILE
)
134 pStm
->SetVersion( SOFFICE_FILEFORMAT_8
);
135 pStm
->SetCompressMode( COMPRESSMODE_ZBITMAP
);
136 ( (GDIMetaFile
&) aGraphic
.GetGDIMetaFile() ).Write( *pStm
);
137 bRet
= ( pStm
->GetError() == 0 );
144 mxStmWrapper
= new ::utl::OInputStreamWrapper( pStm
, sal_True
);
152 SvXMLGraphicInputStream::~SvXMLGraphicInputStream()
156 sal_Int32 SAL_CALL
SvXMLGraphicInputStream::readBytes( Sequence
< sal_Int8
>& rData
, sal_Int32 nBytesToRead
)
157 throw( NotConnectedException
, BufferSizeExceededException
, RuntimeException
)
159 if( !mxStmWrapper
.is() )
160 throw NotConnectedException();
162 return mxStmWrapper
->readBytes( rData
, nBytesToRead
);
165 sal_Int32 SAL_CALL
SvXMLGraphicInputStream::readSomeBytes( Sequence
< sal_Int8
>& rData
, sal_Int32 nMaxBytesToRead
)
166 throw( NotConnectedException
, BufferSizeExceededException
, RuntimeException
)
168 if( !mxStmWrapper
.is() )
169 throw NotConnectedException() ;
171 return mxStmWrapper
->readSomeBytes( rData
, nMaxBytesToRead
);
174 void SAL_CALL
SvXMLGraphicInputStream::skipBytes( sal_Int32 nBytesToSkip
)
175 throw( NotConnectedException
, BufferSizeExceededException
, RuntimeException
)
177 if( !mxStmWrapper
.is() )
178 throw NotConnectedException() ;
180 mxStmWrapper
->skipBytes( nBytesToSkip
);
183 sal_Int32 SAL_CALL
SvXMLGraphicInputStream::available() throw( NotConnectedException
, RuntimeException
)
185 if( !mxStmWrapper
.is() )
186 throw NotConnectedException() ;
188 return mxStmWrapper
->available();
191 void SAL_CALL
SvXMLGraphicInputStream::closeInput() throw( NotConnectedException
, RuntimeException
)
193 if( !mxStmWrapper
.is() )
194 throw NotConnectedException() ;
196 mxStmWrapper
->closeInput();
199 class SvXMLGraphicOutputStream
: public::cppu::WeakImplHelper1
< XOutputStream
>
204 virtual void SAL_CALL
writeBytes( const Sequence
< sal_Int8
>& rData
) throw( NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
);
205 virtual void SAL_CALL
flush() throw( NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
);
206 virtual void SAL_CALL
closeOutput() throw( NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
);
210 ::utl::TempFile
* mpTmp
;
212 Reference
< XOutputStream
> mxStmWrapper
;
213 GraphicObject maGrfObj
;
217 SvXMLGraphicOutputStream( const SvXMLGraphicOutputStream
& );
218 SvXMLGraphicOutputStream
& operator==( SvXMLGraphicOutputStream
& );
222 SvXMLGraphicOutputStream();
223 virtual ~SvXMLGraphicOutputStream();
225 bool Exists() const { return mxStmWrapper
.is(); }
226 const GraphicObject
& GetGraphicObject();
229 SvXMLGraphicOutputStream::SvXMLGraphicOutputStream() :
230 mpTmp( new ::utl::TempFile
),
231 mbClosed( sal_False
)
233 mpTmp
->EnableKillingFile();
235 mpOStm
= ::utl::UcbStreamHelper::CreateStream( mpTmp
->GetURL(), STREAM_WRITE
| STREAM_TRUNC
);
238 mxStmWrapper
= new ::utl::OOutputStreamWrapper( *mpOStm
);
241 SvXMLGraphicOutputStream::~SvXMLGraphicOutputStream()
247 void SAL_CALL
SvXMLGraphicOutputStream::writeBytes( const Sequence
< sal_Int8
>& rData
)
248 throw( NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
250 if( !mxStmWrapper
.is() )
251 throw NotConnectedException() ;
253 mxStmWrapper
->writeBytes( rData
);
256 void SAL_CALL
SvXMLGraphicOutputStream::flush()
257 throw( NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
259 if( !mxStmWrapper
.is() )
260 throw NotConnectedException() ;
262 mxStmWrapper
->flush();
265 void SAL_CALL
SvXMLGraphicOutputStream::closeOutput()
266 throw( NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
268 if( !mxStmWrapper
.is() )
269 throw NotConnectedException() ;
271 mxStmWrapper
->closeOutput();
272 mxStmWrapper
= Reference
< XOutputStream
>();
277 const GraphicObject
& SvXMLGraphicOutputStream::GetGraphicObject()
279 if( mbClosed
&& ( maGrfObj
.GetType() == GRAPHIC_NONE
) && mpOStm
)
284 sal_uInt16 nFormat
= GRFILTER_FORMAT_DONTKNOW
;
285 sal_uInt16 pDeterminedFormat
= GRFILTER_FORMAT_DONTKNOW
;
286 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic
, String(), *mpOStm
,nFormat
,&pDeterminedFormat
);
288 if (pDeterminedFormat
== GRFILTER_FORMAT_DONTKNOW
)
290 //Read the first two byte to check whether it is a gzipped stream, is so it may be in wmz or emz format
291 //unzip them and try again
293 sal_uInt8 sFirstBytes
[ 2 ];
295 mpOStm
->Seek( STREAM_SEEK_TO_END
);
296 sal_uIntPtr nStreamLen
= mpOStm
->Tell();
301 SvLockBytes
* pLockBytes
= mpOStm
->GetLockBytes();
303 pLockBytes
->SetSynchronMode( sal_True
);
305 mpOStm
->Seek( STREAM_SEEK_TO_END
);
306 nStreamLen
= mpOStm
->Tell();
309 if( nStreamLen
>= 2 )
312 mpOStm
->Read( sFirstBytes
, 2 );
314 if( sFirstBytes
[0] == 0x1f && sFirstBytes
[1] == 0x8b )
316 SvMemoryStream
* pDest
= new SvMemoryStream
;
317 ZCodec
aZCodec( 0x8000, 0x8000 );
318 aZCodec
.BeginCompression(ZCODEC_GZ_LIB
);
320 aZCodec
.Decompress( *mpOStm
, *pDest
);
322 if (aZCodec
.EndCompression() && pDest
)
324 pDest
->Seek( STREAM_SEEK_TO_END
);
325 sal_uIntPtr nStreamLen_
= pDest
->Tell();
329 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic
, String(), *pDest
,nFormat
,&pDeterminedFormat
);
338 if( maGrfObj
.GetType() != GRAPHIC_NONE
)
340 delete mpOStm
, mpOStm
= NULL
;
341 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
, sal_False
);
355 SvXMLGraphicHelper::SvXMLGraphicHelper() :
356 ::cppu::WeakComponentImplHelper2
< ::com::sun::star::document::XGraphicObjectResolver
,
357 ::com::sun::star::document::XBinaryStreamResolver
>( maMutex
)
361 SvXMLGraphicHelper::~SvXMLGraphicHelper()
365 void SAL_CALL
SvXMLGraphicHelper::disposing()
369 sal_Bool
SvXMLGraphicHelper::ImplGetStreamNames( const OUString
& rURLStr
,
370 OUString
& rPictureStorageName
,
371 OUString
& rPictureStreamName
)
373 String
aURLStr( rURLStr
);
374 sal_Bool bRet
= sal_False
;
378 aURLStr
= aURLStr
.GetToken( comphelper::string::getTokenCount(aURLStr
, ':') - 1, ':' );
380 const sal_uInt32 nTokenCount
= comphelper::string::getTokenCount(aURLStr
, '/');
382 if( 1 == nTokenCount
)
384 rPictureStorageName
= String( XML_GRAPHICSTORAGE_NAME
);
385 rPictureStreamName
= aURLStr
;
388 SvXMLEmbeddedObjectHelper::splitObjectURL(aURLStr
, rPictureStorageName
, rPictureStreamName
);
390 bRet
= !rPictureStreamName
.isEmpty();
391 SAL_WARN_IF(!bRet
, "svx", "SvXMLGraphicHelper::ImplInsertGraphicURL: invalid scheme: " << rURLStr
);
397 uno::Reference
< embed::XStorage
> SvXMLGraphicHelper::ImplGetGraphicStorage( const OUString
& rStorageName
)
399 uno::Reference
< embed::XStorage
> xRetStorage
;
400 if( mxRootStorage
.is() )
404 xRetStorage
= mxRootStorage
->openStorageElement(
405 maCurStorageName
= rStorageName
,
406 ( GRAPHICHELPER_MODE_WRITE
== meCreateMode
)
407 ? embed::ElementModes::READWRITE
408 : embed::ElementModes::READ
);
410 catch ( uno::Exception
& )
413 //#i43196# try again to open the storage element - this time readonly
414 if(!xRetStorage
.is())
418 xRetStorage
= mxRootStorage
->openStorageElement( maCurStorageName
= rStorageName
, embed::ElementModes::READ
);
420 catch ( uno::Exception
& )
429 SvxGraphicHelperStream_Impl
SvXMLGraphicHelper::ImplGetGraphicStream( const OUString
& rPictureStorageName
,
430 const OUString
& rPictureStreamName
,
433 SvxGraphicHelperStream_Impl aRet
;
434 aRet
.xStorage
= ImplGetGraphicStorage( rPictureStorageName
);
436 if( aRet
.xStorage
.is() )
438 sal_Int32 nMode
= embed::ElementModes::READ
;
439 if ( GRAPHICHELPER_MODE_WRITE
== meCreateMode
)
441 nMode
= embed::ElementModes::READWRITE
;
443 nMode
|= embed::ElementModes::TRUNCATE
;
446 aRet
.xStream
= aRet
.xStorage
->openStreamElement( rPictureStreamName
, nMode
);
447 if( aRet
.xStream
.is() && ( GRAPHICHELPER_MODE_WRITE
== meCreateMode
) )
449 OUString
aPropName( "UseCommonStoragePasswordEncryption" );
450 uno::Reference
< beans::XPropertySet
> xProps( aRet
.xStream
, uno::UNO_QUERY
);
451 xProps
->setPropertyValue( aPropName
, uno::makeAny( sal_True
) );
458 String
SvXMLGraphicHelper::ImplGetGraphicMimeType( const String
& rFileName
) const
460 struct XMLGraphicMimeTypeMapper
463 const char* pMimeType
;
466 static XMLGraphicMimeTypeMapper aMapper
[] =
468 { "gif", "image/gif" },
469 { "png", "image/png" },
470 { "jpg", "image/jpeg" },
471 { "tif", "image/tiff" },
472 { "svg", "image/svg+xml" }
477 if( ( rFileName
.Len() >= 4 ) && ( rFileName
.GetChar( rFileName
.Len() - 4 ) == '.' ) )
479 const OString
aExt(OUStringToOString(rFileName
.Copy(rFileName
.Len() - 3),
480 RTL_TEXTENCODING_ASCII_US
));
482 for( long i
= 0, nCount
= sizeof (aMapper
) / sizeof (aMapper
[0]); ( i
< nCount
) && !aMimeType
.Len(); i
++ )
483 if( aExt
.getStr() == aMapper
[ i
].pExt
)
484 aMimeType
= String( aMapper
[ i
].pMimeType
, RTL_TEXTENCODING_ASCII_US
);
490 Graphic
SvXMLGraphicHelper::ImplReadGraphic( const OUString
& rPictureStorageName
,
491 const OUString
& rPictureStreamName
)
494 SvxGraphicHelperStream_Impl
aStream( ImplGetGraphicStream( rPictureStorageName
, rPictureStreamName
, sal_False
) );
495 if( aStream
.xStream
.is() )
497 SvStream
* pStream
= utl::UcbStreamHelper::CreateStream( aStream
.xStream
);
498 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic
, String(), *pStream
);
505 sal_Bool
SvXMLGraphicHelper::ImplWriteGraphic( const OUString
& rPictureStorageName
,
506 const OUString
& rPictureStreamName
,
507 const OUString
& rGraphicId
,
510 GraphicObject
aGrfObject( OUStringToOString(rGraphicId
, RTL_TEXTENCODING_ASCII_US
) );
511 sal_Bool bRet
= sal_False
;
513 if( aGrfObject
.GetType() != GRAPHIC_NONE
)
515 SvxGraphicHelperStream_Impl
aStream( ImplGetGraphicStream( rPictureStorageName
, rPictureStreamName
, sal_False
) );
516 if( aStream
.xStream
.is() )
518 Graphic
aGraphic( (Graphic
&) aGrfObject
.GetGraphic() );
519 const GfxLink
aGfxLink( aGraphic
.GetLink() );
520 const OUString
aMimeType( ImplGetGraphicMimeType( rPictureStreamName
) );
522 uno::Reference
< beans::XPropertySet
> xProps( aStream
.xStream
, uno::UNO_QUERY
);
524 // set stream properties (MediaType/Compression)
525 if( !aMimeType
.isEmpty() )
528 xProps
->setPropertyValue( String( "MediaType" ), aAny
);
531 const sal_Bool bCompressed
= aMimeType
.isEmpty() || aMimeType
== "image/tiff";
532 aAny
<<= bCompressed
;
533 xProps
->setPropertyValue( String( "Compressed" ), aAny
);
535 SvStream
* pStream
= utl::UcbStreamHelper::CreateStream( aStream
.xStream
);
536 if( bUseGfxLink
&& aGfxLink
.GetDataSize() && aGfxLink
.GetData() )
537 pStream
->Write( aGfxLink
.GetData(), aGfxLink
.GetDataSize() );
540 if( aGraphic
.GetType() == GRAPHIC_BITMAP
)
542 GraphicFilter
&rFilter
= GraphicFilter::GetGraphicFilter();
545 if( aGraphic
.IsAnimated() )
546 aFormat
= String( "gif" );
548 aFormat
= String( "png" );
550 bRet
= ( rFilter
.ExportGraphic( aGraphic
, String(), *pStream
,
551 rFilter
.GetExportFormatNumberForShortName( aFormat
) ) == 0 );
553 else if( aGraphic
.GetType() == GRAPHIC_GDIMETAFILE
)
555 pStream
->SetVersion( SOFFICE_FILEFORMAT_8
);
556 pStream
->SetCompressMode( COMPRESSMODE_ZBITMAP
);
558 // SJ: first check if this metafile is just a eps file, then we will store the eps instead of svm
559 GDIMetaFile
& rMtf( (GDIMetaFile
&)aGraphic
.GetGDIMetaFile() );
560 const MetaCommentAction
* pComment
= ImplCheckForEPS( rMtf
);
563 sal_uInt32 nSize
= pComment
->GetDataSize();
564 const sal_uInt8
* pData
= pComment
->GetData();
565 if ( nSize
&& pData
)
566 pStream
->Write( pData
, nSize
);
568 const MetaEPSAction
* pAct
= ( (const MetaEPSAction
*)rMtf
.FirstAction() );
569 const GfxLink
& rLink
= pAct
->GetLink();
571 pStream
->Write( rLink
.GetData(), rLink
.GetDataSize() );
574 rMtf
.Write( *pStream
);
576 bRet
= ( pStream
->GetError() == 0 );
579 uno::Reference
< embed::XTransactedObject
> xStorage(
580 aStream
.xStorage
, uno::UNO_QUERY
);
582 aStream
.xStream
->getOutputStream()->closeOutput();
591 void SvXMLGraphicHelper::ImplInsertGraphicURL( const OUString
& rURLStr
, sal_uInt32 nInsertPos
, OUString
& rRequestedFileName
)
593 OUString
aURLString( rURLStr
);
594 OUString aPictureStorageName
, aPictureStreamName
;
595 if( ( maURLSet
.find( aURLString
) != maURLSet
.end() ) )
597 for (URLPairVector::const_iterator
aIter( maGrfURLs
.begin() ), aEnd( maGrfURLs
.end() ); aIter
!= aEnd
; ++aIter
)
599 if( aURLString
== (*aIter
).first
)
601 maGrfURLs
[ nInsertPos
].second
= (*aIter
).second
;
606 else if( ImplGetStreamNames( aURLString
, aPictureStorageName
, aPictureStreamName
) )
608 URLPair
& rURLPair
= maGrfURLs
[ nInsertPos
];
610 if( GRAPHICHELPER_MODE_READ
== meCreateMode
)
612 const GraphicObject
aObj( ImplReadGraphic( aPictureStorageName
, aPictureStreamName
) );
614 if( aObj
.GetType() != GRAPHIC_NONE
)
616 maGrfObjs
.push_back( aObj
);
617 OUString
aBaseURL( XML_GRAPHICOBJECT_URL_BASE
);
619 rURLPair
.second
= aBaseURL
;
620 rURLPair
.second
+= OStringToOUString(aObj
.GetUniqueID(),
621 RTL_TEXTENCODING_ASCII_US
);
624 rURLPair
.second
= String();
628 const String
aGraphicObjectId( aPictureStreamName
);
629 const OString
aAsciiObjectID(OUStringToOString(aGraphicObjectId
, RTL_TEXTENCODING_ASCII_US
));
630 const GraphicObject
aGrfObject( aAsciiObjectID
);
631 if( aGrfObject
.GetType() != GRAPHIC_NONE
)
633 String
aStreamName( aGraphicObjectId
);
634 Graphic
aGraphic( (Graphic
&) aGrfObject
.GetGraphic() );
635 const GfxLink
aGfxLink( aGraphic
.GetLink() );
637 bool bUseGfxLink( true );
639 if( aGfxLink
.GetDataSize() )
641 switch( aGfxLink
.GetType() )
643 case( GFX_LINK_TYPE_EPS_BUFFER
): aExtension
= String( ".eps" ); break;
644 case( GFX_LINK_TYPE_NATIVE_GIF
): aExtension
= String( ".gif" ); break;
645 case( GFX_LINK_TYPE_NATIVE_JPG
): aExtension
= String( ".jpg" ); break;
646 case( GFX_LINK_TYPE_NATIVE_PNG
): aExtension
= String( ".png" ); break;
647 case( GFX_LINK_TYPE_NATIVE_TIF
): aExtension
= String( ".tif" ); break;
648 case( GFX_LINK_TYPE_NATIVE_WMF
): aExtension
= String( ".wmf" ); break;
649 case( GFX_LINK_TYPE_NATIVE_MET
): aExtension
= String( ".met" ); break;
650 case( GFX_LINK_TYPE_NATIVE_PCT
): aExtension
= String( ".pct" ); break;
651 case( GFX_LINK_TYPE_NATIVE_SVG
):
652 // backward-compat kludge: since no released OOo
653 // version to date can handle svg properly, wrap it up
654 // into an svm. slight catch22 here, since strict ODF
655 // conformance _recommends_ svg - then again, most old
656 // ODF consumers are believed to be OOo
657 if( SvtSaveOptions().GetODFDefaultVersion() <= SvtSaveOptions::ODFVER_012
)
660 aExtension
= String( ".svm" );
663 aExtension
= String( ".svg" );
667 aExtension
= String( ".grf" );
673 if( aGrfObject
.GetType() == GRAPHIC_BITMAP
)
675 if( aGrfObject
.IsAnimated() )
676 aExtension
= String( ".gif" );
678 aExtension
= String( ".png" );
680 else if( aGrfObject
.GetType() == GRAPHIC_GDIMETAFILE
)
682 // SJ: first check if this metafile is just a eps file, then we will store the eps instead of svm
683 GDIMetaFile
& rMtf( (GDIMetaFile
&)aGraphic
.GetGDIMetaFile() );
684 if ( ImplCheckForEPS( rMtf
) )
685 aExtension
= String( ".eps" );
687 aExtension
= String( ".svm" );
692 const String
sPictures( "Pictures/" );
694 if ( !rRequestedFileName
.isEmpty() )
696 aURLEntry
= sPictures
;
697 aURLEntry
+= rRequestedFileName
;
698 aURLEntry
+= aExtension
;
700 URLPairVector::const_iterator
aIter( maGrfURLs
.begin() ), aEnd( maGrfURLs
.end() );
701 for ( ; aIter
!= aEnd
; ++aIter
)
703 if( aURLEntry
== (*aIter
).second
)
707 aStreamName
= rRequestedFileName
;
710 aStreamName
+= aExtension
;
712 if( mbDirect
&& aStreamName
.Len() )
713 ImplWriteGraphic( aPictureStorageName
, aStreamName
, aGraphicObjectId
, bUseGfxLink
);
715 rURLPair
.second
= sPictures
;
716 rURLPair
.second
+= aStreamName
;
718 #if OSL_DEBUG_LEVEL > 0
721 OStringBuffer
sMessage(
722 RTL_CONSTASCII_STRINGPARAM("graphic object with ID '"));
723 sMessage
.append(aAsciiObjectID
).
724 append(RTL_CONSTASCII_STRINGPARAM("' has an unknown type"));
725 OSL_ENSURE( false, sMessage
.getStr() );
730 maURLSet
.insert( aURLString
);
734 void SvXMLGraphicHelper::Init( const uno::Reference
< embed::XStorage
>& rXMLStorage
,
735 SvXMLGraphicHelperMode eCreateMode
,
738 mxRootStorage
= rXMLStorage
;
739 meCreateMode
= eCreateMode
;
740 mbDirect
= ( ( GRAPHICHELPER_MODE_READ
== meCreateMode
) ? bDirect
: sal_True
);
743 SvXMLGraphicHelper
* SvXMLGraphicHelper::Create( const uno::Reference
< embed::XStorage
>& rXMLStorage
,
744 SvXMLGraphicHelperMode eCreateMode
,
747 SvXMLGraphicHelper
* pThis
= new SvXMLGraphicHelper
;
750 pThis
->Init( rXMLStorage
, eCreateMode
, bDirect
);
755 SvXMLGraphicHelper
* SvXMLGraphicHelper::Create( SvXMLGraphicHelperMode eCreateMode
)
757 SvXMLGraphicHelper
* pThis
= new SvXMLGraphicHelper
;
760 pThis
->Init( NULL
, eCreateMode
, sal_False
);
765 void SvXMLGraphicHelper::Destroy( SvXMLGraphicHelper
* pSvXMLGraphicHelper
)
767 if( pSvXMLGraphicHelper
)
769 pSvXMLGraphicHelper
->dispose();
770 pSvXMLGraphicHelper
->release();
774 // XGraphicObjectResolver
775 OUString SAL_CALL
SvXMLGraphicHelper::resolveGraphicObjectURL( const OUString
& rURL
)
776 throw(uno::RuntimeException
)
778 ::osl::MutexGuard
aGuard( maMutex
);
779 const sal_Int32 nIndex
= maGrfURLs
.size();
781 OUString
aURL( rURL
);
783 OUString aRequestedFileName
;
785 sal_Int32 nUser
= rURL
.indexOf( '?', 0 );
788 aURL
= OUString( rURL
.copy( 0, nUser
) );
790 aUserData
= rURL
.copy( nUser
, rURL
.getLength() - nUser
);
792 if ( !aUserData
.isEmpty() )
794 sal_Int32 nIndex2
= 0;
797 OUString aToken
= aUserData
.getToken( 0, ';', nIndex2
);
798 sal_Int32 n
= aToken
.indexOf( '=' );
799 if ( ( n
> 0 ) && ( ( n
+ 1 ) < aToken
.getLength() ) )
801 OUString
aParam( aToken
.copy( 0, n
) );
802 OUString
aValue( aToken
.copy( n
+ 1, aToken
.getLength() - ( n
+ 1 ) ) );
804 const OUString
sRequestedName( "requestedName" );
805 if ( aParam
.match( sRequestedName
) )
806 aRequestedFileName
= aValue
;
809 while ( nIndex2
>= 0 );
812 maGrfURLs
.push_back( ::std::make_pair( aURL
, OUString() ) );
813 ImplInsertGraphicURL( aURL
, nIndex
, aRequestedFileName
);
815 return maGrfURLs
[ nIndex
].second
;
818 // XBinaryStreamResolver
819 Reference
< XInputStream
> SAL_CALL
SvXMLGraphicHelper::getInputStream( const OUString
& rURL
)
820 throw( RuntimeException
)
822 Reference
< XInputStream
> xRet
;
823 OUString aPictureStorageName
, aGraphicId
;
826 if( ( GRAPHICHELPER_MODE_WRITE
== meCreateMode
) &&
827 ImplGetStreamNames( rURL
, aPictureStorageName
, aGraphicId
) )
829 SvXMLGraphicInputStream
* pInputStream
= new SvXMLGraphicInputStream( aGraphicId
);
831 if( pInputStream
->Exists() )
840 Reference
< XOutputStream
> SAL_CALL
SvXMLGraphicHelper::createOutputStream()
841 throw( RuntimeException
)
843 Reference
< XOutputStream
> xRet
;
845 if( GRAPHICHELPER_MODE_READ
== meCreateMode
)
847 SvXMLGraphicOutputStream
* pOutputStream
= new SvXMLGraphicOutputStream
;
849 if( pOutputStream
->Exists() )
850 maGrfStms
.push_back( xRet
= pOutputStream
);
852 delete pOutputStream
;
858 OUString SAL_CALL
SvXMLGraphicHelper::resolveOutputStream( const Reference
< XOutputStream
>& rxBinaryStream
)
859 throw( RuntimeException
)
863 if( ( GRAPHICHELPER_MODE_READ
== meCreateMode
) && rxBinaryStream
.is() )
865 if( ::std::find( maGrfStms
.begin(), maGrfStms
.end(), rxBinaryStream
) != maGrfStms
.end() )
867 SvXMLGraphicOutputStream
* pOStm
= static_cast< SvXMLGraphicOutputStream
* >( rxBinaryStream
.get() );
871 const GraphicObject
& rGrfObj
= pOStm
->GetGraphicObject();
872 const OUString
aId(OStringToOUString(
873 rGrfObj
.GetUniqueID(), RTL_TEXTENCODING_ASCII_US
));
877 aRet
= OUString( XML_GRAPHICOBJECT_URL_BASE
);
887 // for instantiation via service manager
893 typedef ::cppu::WeakComponentImplHelper4
<
894 lang::XInitialization
,
895 document::XGraphicObjectResolver
,
896 document::XBinaryStreamResolver
,
898 SvXMLGraphicImportExportHelper_Base
;
902 virtual ~MutexContainer();
905 mutable ::osl::Mutex m_aMutex
;
907 MutexContainer::~MutexContainer()
911 class SvXMLGraphicImportExportHelper
:
912 public impl::MutexContainer
,
913 public impl::SvXMLGraphicImportExportHelper_Base
916 SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode
);
919 // is called from WeakComponentImplHelper when XComponent::dispose() was
920 // called from outside
921 virtual void SAL_CALL
disposing();
923 // ____ XInitialization ____
924 // one argument is allowed, which is the XStorage
925 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
)
929 // ____ XGraphicObjectResolver ____
930 virtual OUString SAL_CALL
resolveGraphicObjectURL( const OUString
& aURL
)
931 throw (RuntimeException
);
933 // ____ XBinaryStreamResolver ____
934 virtual Reference
< io::XInputStream
> SAL_CALL
getInputStream( const OUString
& aURL
)
935 throw (RuntimeException
);
936 virtual Reference
< io::XOutputStream
> SAL_CALL
createOutputStream()
937 throw (RuntimeException
);
938 virtual OUString SAL_CALL
resolveOutputStream( const Reference
< io::XOutputStream
>& aBinaryStream
)
939 throw (RuntimeException
);
941 // ____ XServiceInfo ____
942 virtual OUString SAL_CALL
getImplementationName()
943 throw (RuntimeException
);
944 virtual ::sal_Bool SAL_CALL
supportsService( const OUString
& ServiceName
)
945 throw (RuntimeException
);
946 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames()
947 throw (RuntimeException
);
950 SvXMLGraphicHelperMode m_eGraphicHelperMode
;
951 Reference
< XGraphicObjectResolver
> m_xGraphicObjectResolver
;
952 Reference
< XBinaryStreamResolver
> m_xBinaryStreamResolver
;
955 SvXMLGraphicImportExportHelper::SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode
) :
956 impl::SvXMLGraphicImportExportHelper_Base( m_aMutex
),
957 m_eGraphicHelperMode( eMode
)
960 void SAL_CALL
SvXMLGraphicImportExportHelper::disposing()
962 Reference
< XComponent
> xComp( m_xGraphicObjectResolver
, UNO_QUERY
);
963 OSL_ASSERT( xComp
.is());
966 // m_xBinaryStreamResolver is a reference to the same object => don't call
970 // ____ XInitialization ____
971 void SAL_CALL
SvXMLGraphicImportExportHelper::initialize(
972 const Sequence
< Any
>& aArguments
)
973 throw (Exception
, RuntimeException
)
975 Reference
< embed::XStorage
> xStorage
;
976 if( aArguments
.getLength() > 0 )
977 aArguments
[0] >>= xStorage
;
979 SvXMLGraphicHelper
* pHelper( SvXMLGraphicHelper::Create( xStorage
, m_eGraphicHelperMode
));
980 m_xGraphicObjectResolver
.set( pHelper
);
981 m_xBinaryStreamResolver
.set( pHelper
);
982 // SvXMLGraphicHelper::Create calls acquire. Since we have two references
983 // now it is safe (and necessary) to undo this acquire
987 // ____ XGraphicObjectResolver ____
988 OUString SAL_CALL
SvXMLGraphicImportExportHelper::resolveGraphicObjectURL( const OUString
& aURL
)
989 throw (uno::RuntimeException
)
991 return m_xGraphicObjectResolver
->resolveGraphicObjectURL( aURL
);
995 // ____ XBinaryStreamResolver ____
996 Reference
< io::XInputStream
> SAL_CALL
SvXMLGraphicImportExportHelper::getInputStream( const OUString
& aURL
)
997 throw (uno::RuntimeException
)
999 return m_xBinaryStreamResolver
->getInputStream( aURL
);
1001 Reference
< io::XOutputStream
> SAL_CALL
SvXMLGraphicImportExportHelper::createOutputStream()
1002 throw (uno::RuntimeException
)
1004 return m_xBinaryStreamResolver
->createOutputStream();
1006 OUString SAL_CALL
SvXMLGraphicImportExportHelper::resolveOutputStream( const Reference
< io::XOutputStream
>& aBinaryStream
)
1007 throw (uno::RuntimeException
)
1009 return m_xBinaryStreamResolver
->resolveOutputStream( aBinaryStream
);
1012 // ____ XServiceInfo ____
1013 OUString SAL_CALL
SvXMLGraphicImportExportHelper::getImplementationName()
1014 throw (uno::RuntimeException
)
1016 if( m_eGraphicHelperMode
== GRAPHICHELPER_MODE_READ
)
1017 return SvXMLGraphicImportHelper_getImplementationName();
1018 return SvXMLGraphicExportHelper_getImplementationName();
1020 ::sal_Bool SAL_CALL
SvXMLGraphicImportExportHelper::supportsService( const OUString
& ServiceName
)
1021 throw (uno::RuntimeException
)
1023 Sequence
< OUString
> aServiceNames( getSupportedServiceNames());
1024 const OUString
* pBegin
= aServiceNames
.getConstArray();
1025 const OUString
* pEnd
= pBegin
+ aServiceNames
.getLength();
1026 return (::std::find( pBegin
, pEnd
, ServiceName
) != pEnd
);
1028 Sequence
< OUString
> SAL_CALL
SvXMLGraphicImportExportHelper::getSupportedServiceNames()
1029 throw (uno::RuntimeException
)
1031 if( m_eGraphicHelperMode
== GRAPHICHELPER_MODE_READ
)
1032 return SvXMLGraphicImportHelper_getSupportedServiceNames();
1033 return SvXMLGraphicExportHelper_getSupportedServiceNames();
1037 Reference
< XInterface
> SAL_CALL
SvXMLGraphicImportHelper_createInstance(const Reference
< XMultiServiceFactory
> & /* rSMgr */ )
1040 return static_cast< XWeak
* >( new SvXMLGraphicImportExportHelper( GRAPHICHELPER_MODE_READ
));
1042 OUString SAL_CALL
SvXMLGraphicImportHelper_getImplementationName()
1045 return OUString( "com.sun.star.comp.Svx.GraphicImportHelper" );
1047 Sequence
< OUString
> SAL_CALL
SvXMLGraphicImportHelper_getSupportedServiceNames()
1050 // XGraphicObjectResolver and XBinaryStreamResolver are not part of any service
1051 Sequence
< OUString
> aSupportedServiceNames( 2 );
1052 aSupportedServiceNames
[0] = OUString( "com.sun.star.document.GraphicObjectResolver" );
1053 aSupportedServiceNames
[1] = OUString( "com.sun.star.document.BinaryStreamResolver" );
1054 return aSupportedServiceNames
;
1058 Reference
< XInterface
> SAL_CALL
SvXMLGraphicExportHelper_createInstance(const Reference
< XMultiServiceFactory
> & /* rSMgr */ )
1061 return static_cast< XWeak
* >( new SvXMLGraphicImportExportHelper( GRAPHICHELPER_MODE_WRITE
));
1063 OUString SAL_CALL
SvXMLGraphicExportHelper_getImplementationName()
1066 return OUString( "com.sun.star.comp.Svx.GraphicExportHelper" );
1068 Sequence
< OUString
> SAL_CALL
SvXMLGraphicExportHelper_getSupportedServiceNames()
1071 // XGraphicObjectResolver and XBinaryStreamResolver are not part of any service
1072 Sequence
< OUString
> aSupportedServiceNames( 2 );
1073 aSupportedServiceNames
[0] = OUString( "com.sun.star.document.GraphicObjectResolver" );
1074 aSupportedServiceNames
[1] = OUString( "com.sun.star.document.BinaryStreamResolver" );
1075 return aSupportedServiceNames
;
1080 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */