1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <comphelper/string.hxx>
30 #include <sal/macros.h>
31 #include <rtl/oustringostreaminserter.hxx>
32 #include <rtl/strbuf.hxx>
33 #include <com/sun/star/embed/XTransactedObject.hpp>
34 #include <com/sun/star/embed/ElementModes.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
37 #include <com/sun/star/lang/XServiceInfo.hpp>
38 #include <com/sun/star/lang/XInitialization.hpp>
39 #include <cppuhelper/compbase4.hxx>
41 #include <unotools/ucbstreamhelper.hxx>
42 #include <unotools/streamwrap.hxx>
43 #include <unotools/tempfile.hxx>
44 #include <unotools/saveopt.hxx>
45 #include <tools/debug.hxx>
46 #include <vcl/cvtgrf.hxx>
47 #include <vcl/gfxlink.hxx>
48 #include <vcl/metaact.hxx>
49 #include <tools/zcodec.hxx>
51 #include "svtools/filter.hxx"
52 #include "svx/xmlgrhlp.hxx"
53 #include "svx/xmleohlp.hxx"
61 using namespace com::sun::star
;
62 using namespace com::sun::star::uno
;
63 using namespace com::sun::star::io
;
65 using ::com::sun::star::lang::XMultiServiceFactory
;
67 #define XML_GRAPHICSTORAGE_NAME "Pictures"
68 #define XML_GRAPHICOBJECT_URL_BASE "vnd.sun.star.GraphicObject:"
70 // ---------------------------
71 // - SvXMLGraphicInputStream -
72 // ---------------------------
74 const MetaCommentAction
* ImplCheckForEPS( GDIMetaFile
& rMtf
)
76 const MetaCommentAction
* pComment
= NULL
;
78 if ( ( rMtf
.GetActionSize() >= 2 )
79 && ( rMtf
.FirstAction()->GetType() == META_EPS_ACTION
)
80 && ( ((const MetaAction
*)rMtf
.GetAction( 1 ))->GetType() == META_COMMENT_ACTION
)
81 && ( ((const MetaCommentAction
*)rMtf
.GetAction( 1 ))->GetComment().equalsL(RTL_CONSTASCII_STRINGPARAM("EPSReplacementGraphic")) ) )
82 pComment
= (const MetaCommentAction
*)rMtf
.GetAction( 1 );
87 class SvXMLGraphicInputStream
: public::cppu::WeakImplHelper1
< XInputStream
>
91 virtual sal_Int32 SAL_CALL
readBytes( Sequence
< sal_Int8
>& aData
, sal_Int32 nBytesToRead
) throw(NotConnectedException
, BufferSizeExceededException
, RuntimeException
);
92 virtual sal_Int32 SAL_CALL
readSomeBytes(Sequence
< sal_Int8
>& aData
, sal_Int32 nMaxBytesToRead
) throw(NotConnectedException
, BufferSizeExceededException
, RuntimeException
);
93 virtual void SAL_CALL
skipBytes(sal_Int32 nBytesToSkip
) throw(NotConnectedException
, BufferSizeExceededException
, RuntimeException
);
94 virtual sal_Int32 SAL_CALL
available() throw(NotConnectedException
, RuntimeException
);
95 virtual void SAL_CALL
closeInput() throw(NotConnectedException
, RuntimeException
);
99 ::utl::TempFile maTmp
;
100 Reference
< XInputStream
> mxStmWrapper
;
103 SvXMLGraphicInputStream();
104 SvXMLGraphicInputStream( const SvXMLGraphicInputStream
& );
105 SvXMLGraphicInputStream
& operator==( SvXMLGraphicInputStream
& );
109 SvXMLGraphicInputStream( const ::rtl::OUString
& rGraphicId
);
110 virtual ~SvXMLGraphicInputStream();
112 sal_Bool
Exists() const { return mxStmWrapper
.is(); }
115 // -----------------------------------------------------------------------------
117 SvXMLGraphicInputStream::SvXMLGraphicInputStream( const ::rtl::OUString
& rGraphicId
)
119 GraphicObject
aGrfObject( rtl::OUStringToOString(rGraphicId
, RTL_TEXTENCODING_ASCII_US
) );
121 maTmp
.EnableKillingFile();
123 if( aGrfObject
.GetType() != GRAPHIC_NONE
)
125 SvStream
* pStm
= ::utl::UcbStreamHelper::CreateStream( maTmp
.GetURL(), STREAM_WRITE
| STREAM_TRUNC
);
129 Graphic
aGraphic( (Graphic
&) aGrfObject
.GetGraphic() );
130 const GfxLink
aGfxLink( aGraphic
.GetLink() );
131 sal_Bool bRet
= sal_False
;
133 if( aGfxLink
.GetDataSize() && aGfxLink
.GetData() )
135 pStm
->Write( aGfxLink
.GetData(), aGfxLink
.GetDataSize() );
136 bRet
= ( pStm
->GetError() == 0 );
140 if( aGraphic
.GetType() == GRAPHIC_BITMAP
)
142 GraphicFilter
&rFilter
= GraphicFilter::GetGraphicFilter();
145 if( aGraphic
.IsAnimated() )
146 aFormat
= String( "gif" );
148 aFormat
= String( "png" );
150 bRet
= ( rFilter
.ExportGraphic( aGraphic
, String(), *pStm
, rFilter
.GetExportFormatNumberForShortName( aFormat
) ) == 0 );
152 else if( aGraphic
.GetType() == GRAPHIC_GDIMETAFILE
)
154 pStm
->SetVersion( SOFFICE_FILEFORMAT_8
);
155 pStm
->SetCompressMode( COMPRESSMODE_ZBITMAP
);
156 ( (GDIMetaFile
&) aGraphic
.GetGDIMetaFile() ).Write( *pStm
, GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC
);
157 bRet
= ( pStm
->GetError() == 0 );
164 mxStmWrapper
= new ::utl::OInputStreamWrapper( pStm
, sal_True
);
172 // -----------------------------------------------------------------------------
174 SvXMLGraphicInputStream::~SvXMLGraphicInputStream()
178 // -----------------------------------------------------------------------------
180 sal_Int32 SAL_CALL
SvXMLGraphicInputStream::readBytes( Sequence
< sal_Int8
>& rData
, sal_Int32 nBytesToRead
)
181 throw( NotConnectedException
, BufferSizeExceededException
, RuntimeException
)
183 if( !mxStmWrapper
.is() )
184 throw NotConnectedException();
186 return mxStmWrapper
->readBytes( rData
, nBytesToRead
);
189 // -----------------------------------------------------------------------------
191 sal_Int32 SAL_CALL
SvXMLGraphicInputStream::readSomeBytes( Sequence
< sal_Int8
>& rData
, sal_Int32 nMaxBytesToRead
)
192 throw( NotConnectedException
, BufferSizeExceededException
, RuntimeException
)
194 if( !mxStmWrapper
.is() )
195 throw NotConnectedException() ;
197 return mxStmWrapper
->readSomeBytes( rData
, nMaxBytesToRead
);
200 // -----------------------------------------------------------------------------
202 void SAL_CALL
SvXMLGraphicInputStream::skipBytes( sal_Int32 nBytesToSkip
)
203 throw( NotConnectedException
, BufferSizeExceededException
, RuntimeException
)
205 if( !mxStmWrapper
.is() )
206 throw NotConnectedException() ;
208 mxStmWrapper
->skipBytes( nBytesToSkip
);
211 // -----------------------------------------------------------------------------
213 sal_Int32 SAL_CALL
SvXMLGraphicInputStream::available() throw( NotConnectedException
, RuntimeException
)
215 if( !mxStmWrapper
.is() )
216 throw NotConnectedException() ;
218 return mxStmWrapper
->available();
221 // -----------------------------------------------------------------------------
223 void SAL_CALL
SvXMLGraphicInputStream::closeInput() throw( NotConnectedException
, RuntimeException
)
225 if( !mxStmWrapper
.is() )
226 throw NotConnectedException() ;
228 mxStmWrapper
->closeInput();
231 // ----------------------------
232 // - SvXMLGraphicOutputStream -
233 // ----------------------------
235 class SvXMLGraphicOutputStream
: public::cppu::WeakImplHelper1
< XOutputStream
>
240 virtual void SAL_CALL
writeBytes( const Sequence
< sal_Int8
>& rData
) throw( NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
);
241 virtual void SAL_CALL
flush() throw( NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
);
242 virtual void SAL_CALL
closeOutput() throw( NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
);
246 ::utl::TempFile
* mpTmp
;
248 Reference
< XOutputStream
> mxStmWrapper
;
249 GraphicObject maGrfObj
;
253 SvXMLGraphicOutputStream( const SvXMLGraphicOutputStream
& );
254 SvXMLGraphicOutputStream
& operator==( SvXMLGraphicOutputStream
& );
258 SvXMLGraphicOutputStream();
259 virtual ~SvXMLGraphicOutputStream();
261 sal_Bool
Exists() const { return mxStmWrapper
.is(); }
262 const GraphicObject
& GetGraphicObject();
265 // -----------------------------------------------------------------------------
267 SvXMLGraphicOutputStream::SvXMLGraphicOutputStream() :
268 mpTmp( new ::utl::TempFile
),
269 mbClosed( sal_False
)
271 mpTmp
->EnableKillingFile();
273 mpOStm
= ::utl::UcbStreamHelper::CreateStream( mpTmp
->GetURL(), STREAM_WRITE
| STREAM_TRUNC
);
276 mxStmWrapper
= new ::utl::OOutputStreamWrapper( *mpOStm
);
279 // -----------------------------------------------------------------------------
281 SvXMLGraphicOutputStream::~SvXMLGraphicOutputStream()
287 // -----------------------------------------------------------------------------
289 void SAL_CALL
SvXMLGraphicOutputStream::writeBytes( const Sequence
< sal_Int8
>& rData
)
290 throw( NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
292 if( !mxStmWrapper
.is() )
293 throw NotConnectedException() ;
295 mxStmWrapper
->writeBytes( rData
);
298 // -----------------------------------------------------------------------------
300 void SAL_CALL
SvXMLGraphicOutputStream::flush()
301 throw( NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
303 if( !mxStmWrapper
.is() )
304 throw NotConnectedException() ;
306 mxStmWrapper
->flush();
309 // -----------------------------------------------------------------------------
311 void SAL_CALL
SvXMLGraphicOutputStream::closeOutput()
312 throw( NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
314 if( !mxStmWrapper
.is() )
315 throw NotConnectedException() ;
317 mxStmWrapper
->closeOutput();
318 mxStmWrapper
= Reference
< XOutputStream
>();
323 // ------------------------------------------------------------------------------
325 const GraphicObject
& SvXMLGraphicOutputStream::GetGraphicObject()
327 if( mbClosed
&& ( maGrfObj
.GetType() == GRAPHIC_NONE
) && mpOStm
)
332 sal_uInt16 nFormat
= GRFILTER_FORMAT_DONTKNOW
;
333 sal_uInt16 pDeterminedFormat
= GRFILTER_FORMAT_DONTKNOW
;
334 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic
, String(), *mpOStm
,nFormat
,&pDeterminedFormat
);
336 if (pDeterminedFormat
== GRFILTER_FORMAT_DONTKNOW
)
338 //Read the first two byte to check whether it is a gzipped stream, is so it may be in wmz or emz format
339 //unzip them and try again
341 sal_uInt8 sFirstBytes
[ 2 ];
343 mpOStm
->Seek( STREAM_SEEK_TO_END
);
344 sal_uIntPtr nStreamLen
= mpOStm
->Tell();
349 SvLockBytes
* pLockBytes
= mpOStm
->GetLockBytes();
351 pLockBytes
->SetSynchronMode( sal_True
);
353 mpOStm
->Seek( STREAM_SEEK_TO_END
);
354 nStreamLen
= mpOStm
->Tell();
357 if( nStreamLen
>= 2 )
360 mpOStm
->Read( sFirstBytes
, 2 );
362 if( sFirstBytes
[0] == 0x1f && sFirstBytes
[1] == 0x8b )
364 SvMemoryStream
* pDest
= new SvMemoryStream
;
365 ZCodec
aZCodec( 0x8000, 0x8000 );
366 aZCodec
.BeginCompression(ZCODEC_GZ_LIB
);
368 aZCodec
.Decompress( *mpOStm
, *pDest
);
370 if (aZCodec
.EndCompression() && pDest
)
372 pDest
->Seek( STREAM_SEEK_TO_END
);
373 sal_uIntPtr nStreamLen_
= pDest
->Tell();
377 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic
, String(), *pDest
,nFormat
,&pDeterminedFormat
);
386 if( maGrfObj
.GetType() != GRAPHIC_NONE
)
388 delete mpOStm
, mpOStm
= NULL
;
389 delete mpTmp
, mpTmp
= NULL
;
396 // ----------------------
397 // - SvXMLGraphicHelper -
398 // ----------------------
400 SvXMLGraphicHelper::SvXMLGraphicHelper( SvXMLGraphicHelperMode eCreateMode
) :
401 ::cppu::WeakComponentImplHelper2
< ::com::sun::star::document::XGraphicObjectResolver
,
402 ::com::sun::star::document::XBinaryStreamResolver
>( maMutex
)
404 Init( NULL
, eCreateMode
, sal_False
);
407 SvXMLGraphicHelper::SvXMLGraphicHelper() :
408 ::cppu::WeakComponentImplHelper2
< ::com::sun::star::document::XGraphicObjectResolver
,
409 ::com::sun::star::document::XBinaryStreamResolver
>( maMutex
)
413 // -----------------------------------------------------------------------------
415 SvXMLGraphicHelper::~SvXMLGraphicHelper()
419 // -----------------------------------------------------------------------------
421 void SAL_CALL
SvXMLGraphicHelper::disposing()
425 // -----------------------------------------------------------------------------
427 sal_Bool
SvXMLGraphicHelper::ImplGetStreamNames( const ::rtl::OUString
& rURLStr
,
428 ::rtl::OUString
& rPictureStorageName
,
429 ::rtl::OUString
& rPictureStreamName
)
431 String
aURLStr( rURLStr
);
432 sal_Bool bRet
= sal_False
;
436 aURLStr
= aURLStr
.GetToken( comphelper::string::getTokenCount(aURLStr
, ':') - 1, ':' );
438 const sal_uInt32 nTokenCount
= comphelper::string::getTokenCount(aURLStr
, '/');
440 if( 1 == nTokenCount
)
442 rPictureStorageName
= String( XML_GRAPHICSTORAGE_NAME
);
443 rPictureStreamName
= aURLStr
;
446 SvXMLEmbeddedObjectHelper::splitObjectURL(aURLStr
, rPictureStorageName
, rPictureStreamName
);
448 bRet
= !rPictureStreamName
.isEmpty();
449 SAL_WARN_IF(!bRet
, "svx", "SvXMLGraphicHelper::ImplInsertGraphicURL: invalid scheme: " << rURLStr
);
455 // -----------------------------------------------------------------------------
457 uno::Reference
< embed::XStorage
> SvXMLGraphicHelper::ImplGetGraphicStorage( const ::rtl::OUString
& rStorageName
)
459 uno::Reference
< embed::XStorage
> xRetStorage
;
460 if( mxRootStorage
.is() )
464 xRetStorage
= mxRootStorage
->openStorageElement(
465 maCurStorageName
= rStorageName
,
466 ( GRAPHICHELPER_MODE_WRITE
== meCreateMode
)
467 ? embed::ElementModes::READWRITE
468 : embed::ElementModes::READ
);
470 catch ( uno::Exception
& )
473 //#i43196# try again to open the storage element - this time readonly
474 if(!xRetStorage
.is())
478 xRetStorage
= mxRootStorage
->openStorageElement( maCurStorageName
= rStorageName
, embed::ElementModes::READ
);
480 catch ( uno::Exception
& )
489 // -----------------------------------------------------------------------------
491 SvxGraphicHelperStream_Impl
SvXMLGraphicHelper::ImplGetGraphicStream( const ::rtl::OUString
& rPictureStorageName
,
492 const ::rtl::OUString
& rPictureStreamName
,
495 SvxGraphicHelperStream_Impl aRet
;
496 aRet
.xStorage
= ImplGetGraphicStorage( rPictureStorageName
);
498 if( aRet
.xStorage
.is() )
500 sal_Int32 nMode
= embed::ElementModes::READ
;
501 if ( GRAPHICHELPER_MODE_WRITE
== meCreateMode
)
503 nMode
= embed::ElementModes::READWRITE
;
505 nMode
|= embed::ElementModes::TRUNCATE
;
508 aRet
.xStream
= aRet
.xStorage
->openStreamElement( rPictureStreamName
, nMode
);
509 if( aRet
.xStream
.is() && ( GRAPHICHELPER_MODE_WRITE
== meCreateMode
) )
511 ::rtl::OUString
aPropName( "UseCommonStoragePasswordEncryption" );
512 uno::Reference
< beans::XPropertySet
> xProps( aRet
.xStream
, uno::UNO_QUERY
);
513 xProps
->setPropertyValue( aPropName
, uno::makeAny( sal_True
) );
520 // -----------------------------------------------------------------------------
522 String
SvXMLGraphicHelper::ImplGetGraphicMimeType( const String
& rFileName
) const
524 struct XMLGraphicMimeTypeMapper
527 const char* pMimeType
;
530 static XMLGraphicMimeTypeMapper aMapper
[] =
532 { "gif", "image/gif" },
533 { "png", "image/png" },
534 { "jpg", "image/jpeg" },
535 { "tif", "image/tiff" },
536 { "svg", "image/svg+xml" }
541 if( ( rFileName
.Len() >= 4 ) && ( rFileName
.GetChar( rFileName
.Len() - 4 ) == '.' ) )
543 const rtl::OString
aExt(rtl::OUStringToOString(rFileName
.Copy(rFileName
.Len() - 3),
544 RTL_TEXTENCODING_ASCII_US
));
546 for( long i
= 0, nCount
= sizeof (aMapper
) / sizeof (aMapper
[0]); ( i
< nCount
) && !aMimeType
.Len(); i
++ )
547 if( aExt
.getStr() == aMapper
[ i
].pExt
)
548 aMimeType
= String( aMapper
[ i
].pMimeType
, RTL_TEXTENCODING_ASCII_US
);
554 // -----------------------------------------------------------------------------
556 Graphic
SvXMLGraphicHelper::ImplReadGraphic( const ::rtl::OUString
& rPictureStorageName
,
557 const ::rtl::OUString
& rPictureStreamName
)
560 SvxGraphicHelperStream_Impl
aStream( ImplGetGraphicStream( rPictureStorageName
, rPictureStreamName
, sal_False
) );
561 if( aStream
.xStream
.is() )
563 SvStream
* pStream
= utl::UcbStreamHelper::CreateStream( aStream
.xStream
);
564 GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic
, String(), *pStream
);
571 // -----------------------------------------------------------------------------
573 sal_Bool
SvXMLGraphicHelper::ImplWriteGraphic( const ::rtl::OUString
& rPictureStorageName
,
574 const ::rtl::OUString
& rPictureStreamName
,
575 const ::rtl::OUString
& rGraphicId
,
578 GraphicObject
aGrfObject( rtl::OUStringToOString(rGraphicId
, RTL_TEXTENCODING_ASCII_US
) );
579 sal_Bool bRet
= sal_False
;
581 if( aGrfObject
.GetType() != GRAPHIC_NONE
)
583 SvxGraphicHelperStream_Impl
aStream( ImplGetGraphicStream( rPictureStorageName
, rPictureStreamName
, sal_False
) );
584 if( aStream
.xStream
.is() )
586 Graphic
aGraphic( (Graphic
&) aGrfObject
.GetGraphic() );
587 const GfxLink
aGfxLink( aGraphic
.GetLink() );
588 const ::rtl::OUString
aMimeType( ImplGetGraphicMimeType( rPictureStreamName
) );
590 uno::Reference
< beans::XPropertySet
> xProps( aStream
.xStream
, uno::UNO_QUERY
);
592 // set stream properties (MediaType/Compression)
593 if( !aMimeType
.isEmpty() )
596 xProps
->setPropertyValue( String( "MediaType" ), aAny
);
599 const sal_Bool bCompressed
= aMimeType
.isEmpty() || aMimeType
== "image/tiff";
600 aAny
<<= bCompressed
;
601 xProps
->setPropertyValue( String( "Compressed" ), aAny
);
603 SvStream
* pStream
= utl::UcbStreamHelper::CreateStream( aStream
.xStream
);
604 if( bUseGfxLink
&& aGfxLink
.GetDataSize() && aGfxLink
.GetData() )
605 pStream
->Write( aGfxLink
.GetData(), aGfxLink
.GetDataSize() );
608 if( aGraphic
.GetType() == GRAPHIC_BITMAP
)
610 GraphicFilter
&rFilter
= GraphicFilter::GetGraphicFilter();
613 if( aGraphic
.IsAnimated() )
614 aFormat
= String( "gif" );
616 aFormat
= String( "png" );
618 bRet
= ( rFilter
.ExportGraphic( aGraphic
, String(), *pStream
,
619 rFilter
.GetExportFormatNumberForShortName( aFormat
) ) == 0 );
621 else if( aGraphic
.GetType() == GRAPHIC_GDIMETAFILE
)
623 pStream
->SetVersion( SOFFICE_FILEFORMAT_8
);
624 pStream
->SetCompressMode( COMPRESSMODE_ZBITMAP
);
626 // SJ: first check if this metafile is just a eps file, then we will store the eps instead of svm
627 GDIMetaFile
& rMtf( (GDIMetaFile
&)aGraphic
.GetGDIMetaFile() );
628 const MetaCommentAction
* pComment
= ImplCheckForEPS( rMtf
);
631 sal_uInt32 nSize
= pComment
->GetDataSize();
632 const sal_uInt8
* pData
= pComment
->GetData();
633 if ( nSize
&& pData
)
634 pStream
->Write( pData
, nSize
);
636 const MetaEPSAction
* pAct
= ( (const MetaEPSAction
*)rMtf
.FirstAction() );
637 const GfxLink
& rLink
= pAct
->GetLink();
639 pStream
->Write( rLink
.GetData(), rLink
.GetDataSize() );
642 rMtf
.Write( *pStream
, GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC
);
644 bRet
= ( pStream
->GetError() == 0 );
647 uno::Reference
< embed::XTransactedObject
> xStorage(
648 aStream
.xStorage
, uno::UNO_QUERY
);
650 aStream
.xStream
->getOutputStream()->closeOutput();
659 // -----------------------------------------------------------------------------
661 void SvXMLGraphicHelper::ImplInsertGraphicURL( const ::rtl::OUString
& rURLStr
, sal_uInt32 nInsertPos
, rtl::OUString
& rRequestedFileName
)
663 rtl::OUString
aURLString( rURLStr
);
664 ::rtl::OUString aPictureStorageName
, aPictureStreamName
;
665 if( ( maURLSet
.find( aURLString
) != maURLSet
.end() ) )
667 URLPairVector::iterator
aIter( maGrfURLs
.begin() ), aEnd( maGrfURLs
.end() );
668 while( aIter
!= aEnd
)
670 if( aURLString
== (*aIter
).first
)
672 maGrfURLs
[ nInsertPos
].second
= (*aIter
).second
;
679 else if( ImplGetStreamNames( aURLString
, aPictureStorageName
, aPictureStreamName
) )
681 URLPair
& rURLPair
= maGrfURLs
[ nInsertPos
];
683 if( GRAPHICHELPER_MODE_READ
== meCreateMode
)
685 const GraphicObject
aObj( ImplReadGraphic( aPictureStorageName
, aPictureStreamName
) );
687 if( aObj
.GetType() != GRAPHIC_NONE
)
689 maGrfObjs
.push_back( aObj
);
690 ::rtl::OUString
aBaseURL( XML_GRAPHICOBJECT_URL_BASE
);
692 rURLPair
.second
= aBaseURL
;
693 rURLPair
.second
+= rtl::OStringToOUString(aObj
.GetUniqueID(),
694 RTL_TEXTENCODING_ASCII_US
);
697 rURLPair
.second
= String();
701 const String
aGraphicObjectId( aPictureStreamName
);
702 const rtl::OString
aAsciiObjectID(rtl::OUStringToOString(aGraphicObjectId
, RTL_TEXTENCODING_ASCII_US
));
703 const GraphicObject
aGrfObject( aAsciiObjectID
);
704 if( aGrfObject
.GetType() != GRAPHIC_NONE
)
706 String
aStreamName( aGraphicObjectId
);
707 Graphic
aGraphic( (Graphic
&) aGrfObject
.GetGraphic() );
708 const GfxLink
aGfxLink( aGraphic
.GetLink() );
710 bool bUseGfxLink( true );
712 if( aGfxLink
.GetDataSize() )
714 switch( aGfxLink
.GetType() )
716 case( GFX_LINK_TYPE_EPS_BUFFER
): aExtension
= String( ".eps" ); break;
717 case( GFX_LINK_TYPE_NATIVE_GIF
): aExtension
= String( ".gif" ); break;
718 case( GFX_LINK_TYPE_NATIVE_JPG
): aExtension
= String( ".jpg" ); break;
719 case( GFX_LINK_TYPE_NATIVE_PNG
): aExtension
= String( ".png" ); break;
720 case( GFX_LINK_TYPE_NATIVE_TIF
): aExtension
= String( ".tif" ); break;
721 case( GFX_LINK_TYPE_NATIVE_WMF
): aExtension
= String( ".wmf" ); break;
722 case( GFX_LINK_TYPE_NATIVE_MET
): aExtension
= String( ".met" ); break;
723 case( GFX_LINK_TYPE_NATIVE_PCT
): aExtension
= String( ".pct" ); break;
724 case( GFX_LINK_TYPE_NATIVE_SVG
):
725 // backward-compat kludge: since no released OOo
726 // version to date can handle svg properly, wrap it up
727 // into an svm. slight catch22 here, since strict ODF
728 // conformance _recommends_ svg - then again, most old
729 // ODF consumers are believed to be OOo
730 if( SvtSaveOptions().GetODFDefaultVersion() <= SvtSaveOptions::ODFVER_012
)
733 aExtension
= String( ".svm" );
736 aExtension
= String( ".svg" );
740 aExtension
= String( ".grf" );
746 if( aGrfObject
.GetType() == GRAPHIC_BITMAP
)
748 if( aGrfObject
.IsAnimated() )
749 aExtension
= String( ".gif" );
751 aExtension
= String( ".png" );
753 else if( aGrfObject
.GetType() == GRAPHIC_GDIMETAFILE
)
755 // SJ: first check if this metafile is just a eps file, then we will store the eps instead of svm
756 GDIMetaFile
& rMtf( (GDIMetaFile
&)aGraphic
.GetGDIMetaFile() );
757 if ( ImplCheckForEPS( rMtf
) )
758 aExtension
= String( ".eps" );
760 aExtension
= String( ".svm" );
764 rtl::OUString aURLEntry
;
765 const String
sPictures( "Pictures/" );
767 if ( !rRequestedFileName
.isEmpty() )
769 aURLEntry
= sPictures
;
770 aURLEntry
+= rRequestedFileName
;
771 aURLEntry
+= aExtension
;
773 URLPairVector::iterator
aIter( maGrfURLs
.begin() ), aEnd( maGrfURLs
.end() );
774 while( aIter
!= aEnd
)
776 if( aURLEntry
== (*aIter
).second
)
781 aStreamName
= rRequestedFileName
;
784 aStreamName
+= aExtension
;
786 if( mbDirect
&& aStreamName
.Len() )
787 ImplWriteGraphic( aPictureStorageName
, aStreamName
, aGraphicObjectId
, bUseGfxLink
);
789 rURLPair
.second
= sPictures
;
790 rURLPair
.second
+= aStreamName
;
792 #if OSL_DEBUG_LEVEL > 0
795 rtl::OStringBuffer
sMessage(
796 RTL_CONSTASCII_STRINGPARAM("graphic object with ID '"));
797 sMessage
.append(aAsciiObjectID
).
798 append(RTL_CONSTASCII_STRINGPARAM("' has an unknown type"));
799 OSL_ENSURE( false, sMessage
.getStr() );
804 maURLSet
.insert( aURLString
);
808 // -----------------------------------------------------------------------------
810 void SvXMLGraphicHelper::Init( const uno::Reference
< embed::XStorage
>& rXMLStorage
,
811 SvXMLGraphicHelperMode eCreateMode
,
814 mxRootStorage
= rXMLStorage
;
815 meCreateMode
= eCreateMode
;
816 mbDirect
= ( ( GRAPHICHELPER_MODE_READ
== meCreateMode
) ? bDirect
: sal_True
);
819 // -----------------------------------------------------------------------------
821 SvXMLGraphicHelper
* SvXMLGraphicHelper::Create( const uno::Reference
< embed::XStorage
>& rXMLStorage
,
822 SvXMLGraphicHelperMode eCreateMode
,
825 SvXMLGraphicHelper
* pThis
= new SvXMLGraphicHelper
;
828 pThis
->Init( rXMLStorage
, eCreateMode
, bDirect
);
833 // -----------------------------------------------------------------------------
835 SvXMLGraphicHelper
* SvXMLGraphicHelper::Create( SvXMLGraphicHelperMode eCreateMode
)
837 SvXMLGraphicHelper
* pThis
= new SvXMLGraphicHelper
;
840 pThis
->Init( NULL
, eCreateMode
, sal_False
);
845 // -----------------------------------------------------------------------------
847 void SvXMLGraphicHelper::Destroy( SvXMLGraphicHelper
* pSvXMLGraphicHelper
)
849 if( pSvXMLGraphicHelper
)
851 pSvXMLGraphicHelper
->dispose();
852 pSvXMLGraphicHelper
->release();
856 // -----------------------------------------------------------------------------
858 // XGraphicObjectResolver
859 ::rtl::OUString SAL_CALL
SvXMLGraphicHelper::resolveGraphicObjectURL( const ::rtl::OUString
& rURL
)
860 throw(uno::RuntimeException
)
862 ::osl::MutexGuard
aGuard( maMutex
);
863 const sal_Int32 nIndex
= maGrfURLs
.size();
865 rtl::OUString
aURL( rURL
);
866 rtl::OUString aUserData
;
867 rtl::OUString aRequestedFileName
;
869 sal_Int32 nUser
= rURL
.indexOf( '?', 0 );
872 aURL
= rtl::OUString( rURL
.copy( 0, nUser
) );
874 aUserData
= rURL
.copy( nUser
, rURL
.getLength() - nUser
);
876 if ( !aUserData
.isEmpty() )
878 sal_Int32 nIndex2
= 0;
881 rtl::OUString aToken
= aUserData
.getToken( 0, ';', nIndex2
);
882 sal_Int32 n
= aToken
.indexOf( '=' );
883 if ( ( n
> 0 ) && ( ( n
+ 1 ) < aToken
.getLength() ) )
885 rtl::OUString
aParam( aToken
.copy( 0, n
) );
886 rtl::OUString
aValue( aToken
.copy( n
+ 1, aToken
.getLength() - ( n
+ 1 ) ) );
888 const rtl::OUString
sRequestedName( "requestedName" );
889 if ( aParam
.match( sRequestedName
) )
890 aRequestedFileName
= aValue
;
893 while ( nIndex2
>= 0 );
896 maGrfURLs
.push_back( ::std::make_pair( aURL
, ::rtl::OUString() ) );
897 ImplInsertGraphicURL( aURL
, nIndex
, aRequestedFileName
);
899 return maGrfURLs
[ nIndex
].second
;
902 // -----------------------------------------------------------------------------
904 // XBinaryStreamResolver
905 Reference
< XInputStream
> SAL_CALL
SvXMLGraphicHelper::getInputStream( const ::rtl::OUString
& rURL
)
906 throw( RuntimeException
)
908 Reference
< XInputStream
> xRet
;
909 ::rtl::OUString aPictureStorageName
, aGraphicId
;
912 if( ( GRAPHICHELPER_MODE_WRITE
== meCreateMode
) &&
913 ImplGetStreamNames( rURL
, aPictureStorageName
, aGraphicId
) )
915 SvXMLGraphicInputStream
* pInputStream
= new SvXMLGraphicInputStream( aGraphicId
);
917 if( pInputStream
->Exists() )
926 // -----------------------------------------------------------------------------
928 Reference
< XOutputStream
> SAL_CALL
SvXMLGraphicHelper::createOutputStream()
929 throw( RuntimeException
)
931 Reference
< XOutputStream
> xRet
;
933 if( GRAPHICHELPER_MODE_READ
== meCreateMode
)
935 SvXMLGraphicOutputStream
* pOutputStream
= new SvXMLGraphicOutputStream
;
937 if( pOutputStream
->Exists() )
938 maGrfStms
.push_back( xRet
= pOutputStream
);
940 delete pOutputStream
;
946 // -----------------------------------------------------------------------------
948 ::rtl::OUString SAL_CALL
SvXMLGraphicHelper::resolveOutputStream( const Reference
< XOutputStream
>& rxBinaryStream
)
949 throw( RuntimeException
)
951 ::rtl::OUString aRet
;
953 if( ( GRAPHICHELPER_MODE_READ
== meCreateMode
) && rxBinaryStream
.is() )
955 if( ::std::find( maGrfStms
.begin(), maGrfStms
.end(), rxBinaryStream
) != maGrfStms
.end() )
957 SvXMLGraphicOutputStream
* pOStm
= static_cast< SvXMLGraphicOutputStream
* >( rxBinaryStream
.get() );
961 const GraphicObject
& rGrfObj
= pOStm
->GetGraphicObject();
962 const ::rtl::OUString
aId(::rtl::OStringToOUString(
963 rGrfObj
.GetUniqueID(), RTL_TEXTENCODING_ASCII_US
));
967 aRet
= ::rtl::OUString( XML_GRAPHICOBJECT_URL_BASE
);
978 // --------------------------------------------------------------------------------
980 // for instantiation via service manager
986 typedef ::cppu::WeakComponentImplHelper4
<
987 lang::XInitialization
,
988 document::XGraphicObjectResolver
,
989 document::XBinaryStreamResolver
,
991 SvXMLGraphicImportExportHelper_Base
;
995 virtual ~MutexContainer();
998 mutable ::osl::Mutex m_aMutex
;
1000 MutexContainer::~MutexContainer()
1004 class SvXMLGraphicImportExportHelper
:
1005 public impl::MutexContainer
,
1006 public impl::SvXMLGraphicImportExportHelper_Base
1009 SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode
);
1012 // is called from WeakComponentImplHelper when XComponent::dispose() was
1013 // called from outside
1014 virtual void SAL_CALL
disposing();
1016 // ____ XInitialization ____
1017 // one argument is allowed, which is the XStorage
1018 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
)
1022 // ____ XGraphicObjectResolver ____
1023 virtual ::rtl::OUString SAL_CALL
resolveGraphicObjectURL( const ::rtl::OUString
& aURL
)
1024 throw (RuntimeException
);
1026 // ____ XBinaryStreamResolver ____
1027 virtual Reference
< io::XInputStream
> SAL_CALL
getInputStream( const ::rtl::OUString
& aURL
)
1028 throw (RuntimeException
);
1029 virtual Reference
< io::XOutputStream
> SAL_CALL
createOutputStream()
1030 throw (RuntimeException
);
1031 virtual ::rtl::OUString SAL_CALL
resolveOutputStream( const Reference
< io::XOutputStream
>& aBinaryStream
)
1032 throw (RuntimeException
);
1034 // ____ XServiceInfo ____
1035 virtual ::rtl::OUString SAL_CALL
getImplementationName()
1036 throw (RuntimeException
);
1037 virtual ::sal_Bool SAL_CALL
supportsService( const ::rtl::OUString
& ServiceName
)
1038 throw (RuntimeException
);
1039 virtual Sequence
< ::rtl::OUString
> SAL_CALL
getSupportedServiceNames()
1040 throw (RuntimeException
);
1043 SvXMLGraphicHelperMode m_eGraphicHelperMode
;
1044 Reference
< XGraphicObjectResolver
> m_xGraphicObjectResolver
;
1045 Reference
< XBinaryStreamResolver
> m_xBinaryStreamResolver
;
1048 SvXMLGraphicImportExportHelper::SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode
) :
1049 impl::SvXMLGraphicImportExportHelper_Base( m_aMutex
),
1050 m_eGraphicHelperMode( eMode
)
1053 void SAL_CALL
SvXMLGraphicImportExportHelper::disposing()
1055 Reference
< XComponent
> xComp( m_xGraphicObjectResolver
, UNO_QUERY
);
1056 OSL_ASSERT( xComp
.is());
1059 // m_xBinaryStreamResolver is a reference to the same object => don't call
1063 // ____ XInitialization ____
1064 void SAL_CALL
SvXMLGraphicImportExportHelper::initialize(
1065 const Sequence
< Any
>& aArguments
)
1066 throw (Exception
, RuntimeException
)
1068 Reference
< embed::XStorage
> xStorage
;
1069 if( aArguments
.getLength() > 0 )
1070 aArguments
[0] >>= xStorage
;
1072 SvXMLGraphicHelper
* pHelper( SvXMLGraphicHelper::Create( xStorage
, m_eGraphicHelperMode
));
1073 m_xGraphicObjectResolver
.set( pHelper
);
1074 m_xBinaryStreamResolver
.set( pHelper
);
1075 // SvXMLGraphicHelper::Create calls acquire. Since we have two references
1076 // now it is safe (and necessary) to undo this acquire
1080 // ____ XGraphicObjectResolver ____
1081 ::rtl::OUString SAL_CALL
SvXMLGraphicImportExportHelper::resolveGraphicObjectURL( const ::rtl::OUString
& aURL
)
1082 throw (uno::RuntimeException
)
1084 return m_xGraphicObjectResolver
->resolveGraphicObjectURL( aURL
);
1088 // ____ XBinaryStreamResolver ____
1089 Reference
< io::XInputStream
> SAL_CALL
SvXMLGraphicImportExportHelper::getInputStream( const ::rtl::OUString
& aURL
)
1090 throw (uno::RuntimeException
)
1092 return m_xBinaryStreamResolver
->getInputStream( aURL
);
1094 Reference
< io::XOutputStream
> SAL_CALL
SvXMLGraphicImportExportHelper::createOutputStream()
1095 throw (uno::RuntimeException
)
1097 return m_xBinaryStreamResolver
->createOutputStream();
1099 ::rtl::OUString SAL_CALL
SvXMLGraphicImportExportHelper::resolveOutputStream( const Reference
< io::XOutputStream
>& aBinaryStream
)
1100 throw (uno::RuntimeException
)
1102 return m_xBinaryStreamResolver
->resolveOutputStream( aBinaryStream
);
1105 // ____ XServiceInfo ____
1106 ::rtl::OUString SAL_CALL
SvXMLGraphicImportExportHelper::getImplementationName()
1107 throw (uno::RuntimeException
)
1109 if( m_eGraphicHelperMode
== GRAPHICHELPER_MODE_READ
)
1110 return SvXMLGraphicImportHelper_getImplementationName();
1111 return SvXMLGraphicExportHelper_getImplementationName();
1113 ::sal_Bool SAL_CALL
SvXMLGraphicImportExportHelper::supportsService( const ::rtl::OUString
& ServiceName
)
1114 throw (uno::RuntimeException
)
1116 Sequence
< ::rtl::OUString
> aServiceNames( getSupportedServiceNames());
1117 const ::rtl::OUString
* pBegin
= aServiceNames
.getConstArray();
1118 const ::rtl::OUString
* pEnd
= pBegin
+ aServiceNames
.getLength();
1119 return (::std::find( pBegin
, pEnd
, ServiceName
) != pEnd
);
1121 Sequence
< ::rtl::OUString
> SAL_CALL
SvXMLGraphicImportExportHelper::getSupportedServiceNames()
1122 throw (uno::RuntimeException
)
1124 if( m_eGraphicHelperMode
== GRAPHICHELPER_MODE_READ
)
1125 return SvXMLGraphicImportHelper_getSupportedServiceNames();
1126 return SvXMLGraphicExportHelper_getSupportedServiceNames();
1130 Reference
< XInterface
> SAL_CALL
SvXMLGraphicImportHelper_createInstance(const Reference
< XMultiServiceFactory
> & /* rSMgr */ )
1133 return static_cast< XWeak
* >( new SvXMLGraphicImportExportHelper( GRAPHICHELPER_MODE_READ
));
1135 ::rtl::OUString SAL_CALL
SvXMLGraphicImportHelper_getImplementationName()
1138 return ::rtl::OUString( "com.sun.star.comp.Svx.GraphicImportHelper" );
1140 Sequence
< ::rtl::OUString
> SAL_CALL
SvXMLGraphicImportHelper_getSupportedServiceNames()
1143 // XGraphicObjectResolver and XBinaryStreamResolver are not part of any service
1144 Sequence
< ::rtl::OUString
> aSupportedServiceNames( 2 );
1145 aSupportedServiceNames
[0] = ::rtl::OUString( "com.sun.star.document.GraphicObjectResolver" );
1146 aSupportedServiceNames
[1] = ::rtl::OUString( "com.sun.star.document.BinaryStreamResolver" );
1147 return aSupportedServiceNames
;
1151 Reference
< XInterface
> SAL_CALL
SvXMLGraphicExportHelper_createInstance(const Reference
< XMultiServiceFactory
> & /* rSMgr */ )
1154 return static_cast< XWeak
* >( new SvXMLGraphicImportExportHelper( GRAPHICHELPER_MODE_WRITE
));
1156 ::rtl::OUString SAL_CALL
SvXMLGraphicExportHelper_getImplementationName()
1159 return ::rtl::OUString( "com.sun.star.comp.Svx.GraphicExportHelper" );
1161 Sequence
< ::rtl::OUString
> SAL_CALL
SvXMLGraphicExportHelper_getSupportedServiceNames()
1164 // XGraphicObjectResolver and XBinaryStreamResolver are not part of any service
1165 Sequence
< ::rtl::OUString
> aSupportedServiceNames( 2 );
1166 aSupportedServiceNames
[0] = ::rtl::OUString( "com.sun.star.document.GraphicObjectResolver" );
1167 aSupportedServiceNames
[1] = ::rtl::OUString( "com.sun.star.document.BinaryStreamResolver" );
1168 return aSupportedServiceNames
;
1173 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */