1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: exporter.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_filter.hxx"
33 #include <com/sun/star/container/XNamed.hpp>
34 #include <com/sun/star/beans/PropertyValue.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
37 #ifndef _COM_SUN_STAR_PRESENTATION_PRESENTATIONPAGE_HPP_
38 #include <com/sun/star/presentation/XPresentationPage.hpp>
40 #include <com/sun/star/container/XIndexAccess.hpp>
41 #include <com/sun/star/document/XFilter.hpp>
42 #include <com/sun/star/text/XText.hpp>
43 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
44 #include <com/sun/star/frame/XModel.hpp>
45 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
46 #include <rtl/ustrbuf.hxx>
47 #include <rtl/string.hxx>
48 #include <osl/diagnose.h>
52 #include "exporter.hxx"
53 #include "Base64Codec.hxx"
55 #include "tempfile.hxx"
59 using namespace ::com::sun::star::uno
;
60 using namespace ::com::sun::star::drawing
;
61 using namespace ::com::sun::star::container
;
62 using namespace ::com::sun::star::document
;
63 using namespace ::com::sun::star::io
;
64 using namespace ::com::sun::star::lang
;
65 using namespace ::com::sun::star::text
;
66 using namespace ::std
;
68 using com::sun::star::beans::PropertyValue
;
69 using com::sun::star::beans::XPropertySet
;
70 using com::sun::star::presentation::XPresentationPage
;
71 using com::sun::star::task::XStatusIndicator
;
73 // -----------------------------------------------------------------------------
75 PlaceWareExporter::PlaceWareExporter(const Reference
< XMultiServiceFactory
> &rxMSF
)
80 // -----------------------------------------------------------------------------
82 PlaceWareExporter::~PlaceWareExporter()
86 // -----------------------------------------------------------------------------
92 rtl::OUString maTitle
;
93 rtl::OUString maNotes
;
100 OUString
getTempURL() { return maTempFile
.getFileURL(); }
102 void setName( const rtl::OUString
& rName
) { maName
= rName
; }
103 const rtl::OUString
& getName() const { return maName
; }
105 void setTitle( const rtl::OUString
& rTitle
) { maTitle
= rTitle
; }
106 const rtl::OUString
& getTitle() const { return maTitle
; }
108 void setNotes( const rtl::OUString
& rNotes
) { maNotes
= rNotes
; }
109 const rtl::OUString
& getNotes() const { return maNotes
; }
111 void setURL( const rtl::OUString
& rURL
) { maURL
= rURL
; }
112 const rtl::OUString
& getURL() const { return maURL
; }
115 PageEntry::PageEntry()
116 : maTempFile( TempFile::createTempFileURL() )
120 PageEntry::~PageEntry()
125 static void encodeFile( osl::File
& rSourceFile
, Reference
< XOutputStream
>& xOutputStream
) throw( ::com::sun::star::uno::Exception
)
127 if( xOutputStream
.is() )
129 sal_uInt64
nTemp( 0 );
131 osl::File::RC nRC
= rSourceFile
.setPos( osl_Pos_End
, 0 );
132 if( osl::File::E_None
== nRC
)
134 nRC
= rSourceFile
.getPos( nTemp
);
135 if( osl::File::E_None
== nRC
)
137 nRC
= rSourceFile
.setPos( osl_Pos_Absolut
, 0 );
141 sal_Int32 nLen
= static_cast<sal_Int32
>(nTemp
);
143 if( osl::File::E_None
!= nRC
)
146 sal_Int32 nBufferSize
= 3*1024; // !!! buffer size must be a factor of 3 for base64 to work
147 Sequence
< sal_Int8
> aInBuffer( nBufferSize
< nLen
? nBufferSize
: nLen
);
148 void* pInBuffer
= aInBuffer
.getArray();
150 Sequence
< sal_Int8
> aOutBuffer
;
154 nRC
= rSourceFile
.read( pInBuffer
, aInBuffer
.getLength(), nTemp
);
156 if( (nRC
!= osl::File::E_None
) || (0 == nTemp
) )
159 nRead
= static_cast<sal_Int32
>( nTemp
);
161 if( nRead
< aInBuffer
.getLength() )
163 aInBuffer
.realloc( nRead
);
164 pInBuffer
= aInBuffer
.getArray();
169 rtl::OUStringBuffer aStrBuffer
;
170 Base64Codec::encodeBase64( aStrBuffer
, aInBuffer
);
172 sal_Int32 nCount
= aStrBuffer
.getLength();
174 if( aOutBuffer
.getLength() != nCount
)
175 aOutBuffer
.realloc( nCount
);
177 sal_Int8
* pBytes
= aOutBuffer
.getArray();
178 const sal_Unicode
* pUnicode
= aStrBuffer
.getStr();
182 // since base64 is always ascii, we can cast safely
183 *pBytes
++ = static_cast<sal_Int8
>(*pUnicode
++);
186 xOutputStream
->writeBytes( aOutBuffer
);
191 static OString
convertString( OUString aInput
)
193 OString
aRet( aInput
.getStr(), aInput
.getLength(), RTL_TEXTENCODING_ASCII_US
);
194 aRet
= aRet
.replace( '\r', ' ' );
195 aRet
= aRet
.replace( '\n', ' ' );
200 static void createSlideFile( Reference
< XComponent
> xDoc
, ZipFile
& rZipFile
, const rtl::OUString
& rURL
, vector
< PageEntry
* >& rPageEntries
) throw( ::com::sun::star::uno::Exception
)
204 const OString
aNewLine( "\r\n" );
207 Reference
< XDocumentPropertiesSupplier
> xDPS( xDoc
, UNO_QUERY
);
208 Reference
< XDocumentProperties
> xDocProps( xDPS
->getDocumentProperties() );
210 aTemp
= xDocProps
->getTitle();
211 if( 0 == aTemp
.getLength() )
213 sal_Int32 nPos1
= rURL
.lastIndexOf( (sal_Unicode
)'/' );
216 sal_Int32 nPos2
= rURL
.lastIndexOf( (sal_Unicode
)'.' );
219 aTemp
= rURL
.copy( nPos1
+ 1, nPos2
- nPos1
- 1 );
223 aTemp
= rURL
.copy( nPos1
+ 1 );
232 aInfo
+= OString( "SlideSetName: " );
233 aInfo
+= convertString( aTemp
);
236 aTemp
= xDocProps
->getAuthor();
238 if( aTemp
.getLength() )
240 aInfo
+= OString( "PresenterName: " );
241 aInfo
+= convertString( aTemp
);
245 vector
< PageEntry
* >::iterator
aIter( rPageEntries
.begin() );
246 vector
< PageEntry
* >::iterator
aEnd( rPageEntries
.end() );
247 while( aIter
!= aEnd
)
249 PageEntry
* pEntry
= (*aIter
++);
251 aInfo
+= OString( "slide: " );
252 if( pEntry
->getTitle().getLength() )
254 aInfo
+= convertString( pEntry
->getTitle() );
258 aInfo
+= convertString( pEntry
->getName() );
262 aInfo
+= OString( "type: gif");
265 aInfo
+= OString( "url: " );
266 aInfo
+= convertString( pEntry
->getURL() );
270 if( pEntry
->getNotes().getLength() )
272 aInfo
+= OString( "notes: " );
273 aInfo
+= convertString( pEntry
->getNotes() );
278 TempFile
aInfoFile( TempFile::createTempFileURL() );
283 nRC
= aInfoFile
.open( OpenFlag_Write
);
284 if( osl::File::E_None
== nRC
)
286 nRC
= aInfoFile
.write( aInfo
.getStr(), aInfo
.getLength(), nTemp
);
287 if( osl::File::E_None
== nRC
)
289 nRC
= aInfoFile
.setPos( osl_Pos_Absolut
, 0 );
290 if( osl::File::E_None
== nRC
)
292 nRC
= aInfoFile
.close();
297 if( (osl::File::E_None
!= nRC
) || !rZipFile
.addFile( aInfoFile
, OString( RTL_CONSTASCII_STRINGPARAM("slides.txt") ) ))
301 //#define PLACEWARE_DEBUG 1
303 sal_Bool
PlaceWareExporter::doExport( Reference
< XComponent
> xDoc
, Reference
< XOutputStream
> xOutputStream
,
304 const rtl::OUString
& rURL
, Reference
< XInterface
> /* xHandler */, Reference
< XStatusIndicator
>& xStatusIndicator
)
306 sal_Bool bRet
= sal_False
;
308 mxGraphicExporter
= Reference
< XExporter
>::query( mxMSF
->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.GraphicExportFilter") ) ) );
309 Reference
< XDrawPagesSupplier
> xDrawPagesSupplier(xDoc
, UNO_QUERY
);
310 if(!xDrawPagesSupplier
.is())
313 Reference
< XIndexAccess
> xDrawPages( xDrawPagesSupplier
->getDrawPages(), UNO_QUERY
);
317 if(xStatusIndicator
.is())
319 xStatusIndicator
->start(OUString( RTL_CONSTASCII_USTRINGPARAM( "PlaceWare:" )),xDrawPages
->getCount());
322 Reference
< XDrawPage
> xDrawPage
;
326 #ifndef PLACEWARE_DEBUG
327 TempFile
aTempFile( TempFile::createTempFileURL() );
328 nRC
= aTempFile
.open( osl_File_OpenFlag_Write
|osl_File_OpenFlag_Read
);
329 OUString
aURL( aTempFile
.getFileURL() );
331 OUString
aURL( RTL_CONSTASCII_USTRINGPARAM("file:///e:/test.zip") );
332 osl::File::remove( aURL
);
333 osl::File
aTempFile( aURL
);
334 nRC
= aTempFile
.open( osl_File_OpenFlag_Create
|osl_File_OpenFlag_Write
|osl_File_OpenFlag_Read
);
337 if( osl::File::E_None
!= nRC
)
340 vector
< PageEntry
* > aPageEntries
;
342 // Create new package...
345 ZipFile
aZipFile(aTempFile
);
347 // export slides as gifs and collect information for slides
349 const sal_Int32 nPageCount
= xDrawPages
->getCount();
352 for( nPage
= 0; nPage
< nPageCount
; nPage
++)
354 xDrawPages
->getByIndex(nPage
) >>= xDrawPage
;
356 if( !xDrawPage
.is() )
359 PageEntry
* pEntry
= exportPage( xDrawPage
);
360 aPageEntries
.push_back( pEntry
);
362 OUString
aName( RTL_CONSTASCII_USTRINGPARAM("i") );
363 aName
+= OUString::valueOf( nPage
);
364 aName
+= OUString( RTL_CONSTASCII_USTRINGPARAM(".gif") );
365 pEntry
->setURL( aName
);
367 if(xStatusIndicator
.is())
369 xStatusIndicator
->setValue( nPage
+ 1 );
373 // create the slide.txt file
375 createSlideFile( xDoc
, aZipFile
, rURL
, aPageEntries
);
378 vector
< PageEntry
* >::iterator
aIter( aPageEntries
.begin() );
379 vector
< PageEntry
* >::iterator
aEnd( aPageEntries
.end() );
380 while( aIter
!= aEnd
)
382 PageEntry
* pEntry
= (*aIter
++);
384 osl::File
aFile(pEntry
->getTempURL() );
385 const OUString
aTemp( pEntry
->getURL() );
387 if( (osl::File::E_None
!= nRC
) || !aZipFile
.addFile( aFile
, OString( aTemp
.getStr(), aTemp
.getLength(), RTL_TEXTENCODING_ASCII_US
) ) )
391 if(!aZipFile
.close())
394 encodeFile( aTempFile
, xOutputStream
);
398 catch ( RuntimeException
const & )
401 catch ( Exception
const & )
405 vector
< PageEntry
* >::iterator
aIter( aPageEntries
.begin() );
406 vector
< PageEntry
* >::iterator
aEnd( aPageEntries
.end() );
407 while( aIter
!= aEnd
)
412 if( xStatusIndicator
.is() )
413 xStatusIndicator
->end();
418 // -----------------------------------------------------------------------------
420 PageEntry
* PlaceWareExporter::exportPage( Reference
< XDrawPage
>&xDrawPage
)
422 Reference
< XComponent
> xComp( xDrawPage
, UNO_QUERY
);
424 PageEntry
* pEntry
= new PageEntry();
427 Reference
< XNamed
> xNamed( xDrawPage
, UNO_QUERY
);
429 pEntry
->setName( xNamed
->getName() );
431 // get title text from title presentation shape if available
432 const OUString
szTitleTextShape( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.TitleTextShape") );
433 const OUString
szIsEmptyPresObj( RTL_CONSTASCII_USTRINGPARAM("IsEmptyPresentationObject") );
435 sal_Int32 nShapeCount
= xDrawPage
->getCount();
437 for( nShape
= 0; nShape
< nShapeCount
; nShape
++ )
439 Reference
< XShape
> xShape
;
440 xDrawPage
->getByIndex( nShape
) >>= xShape
;
442 if( xShape
.is() && xShape
->getShapeType() == szTitleTextShape
)
444 Reference
< XPropertySet
> xPropSet( xShape
, UNO_QUERY
);
447 sal_Bool bIsEmpty
= true;
448 xPropSet
->getPropertyValue( szIsEmptyPresObj
) >>= bIsEmpty
;
452 Reference
< XText
> xText( xShape
, UNO_QUERY
);
455 pEntry
->setTitle( xText
->getString() );
463 // get notes text if available
464 Reference
< XPresentationPage
> xPresPage( xDrawPage
, UNO_QUERY
);
467 Reference
< XDrawPage
> xNotesPage( xPresPage
->getNotesPage() );
469 const OUString
szNotesShape( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.NotesShape") );
471 nShapeCount
= xNotesPage
->getCount();
472 for( nShape
= 0; nShape
< nShapeCount
; nShape
++ )
474 Reference
< XShape
> xShape
;
475 xNotesPage
->getByIndex( nShape
) >>= xShape
;
477 if( xShape
.is() && (xShape
->getShapeType() == szNotesShape
) )
479 Reference
< XPropertySet
> xPropSet( xShape
, UNO_QUERY
);
482 sal_Bool bIsEmpty
= true;
483 xPropSet
->getPropertyValue( szIsEmptyPresObj
) >>= bIsEmpty
;
487 Reference
< XText
> xText( xShape
, UNO_QUERY
);
490 pEntry
->setNotes( xText
->getString() );
500 Reference
< XFilter
> xFilter( mxGraphicExporter
, UNO_QUERY
);
502 Sequence
< PropertyValue
> aFilterData( 2 );
503 aFilterData
[0].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM("Width") );
504 aFilterData
[0].Value
<<= (sal_Int32
)704;
505 aFilterData
[1].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM("Translucent") );
506 aFilterData
[1].Value
<<= (sal_Bool
)sal_False
;
508 Sequence
< PropertyValue
> aDescriptor( 3 );
509 aDescriptor
[0].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM("FilterName") );
510 aDescriptor
[0].Value
<<= OUString( RTL_CONSTASCII_USTRINGPARAM("GIF") );
511 aDescriptor
[1].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM("URL") );
512 aDescriptor
[1].Value
<<= OUString( pEntry
->getTempURL() );
513 aDescriptor
[2].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM("FilterData") );
514 aDescriptor
[2].Value
<<= aFilterData
;
515 mxGraphicExporter
->setSourceDocument( xComp
);
516 xFilter
->filter( aDescriptor
);