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 <com/sun/star/container/XNamed.hpp>
21 #include <com/sun/star/beans/PropertyValue.hpp>
22 #include <com/sun/star/beans/XPropertySet.hpp>
23 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
24 #include <com/sun/star/presentation/XPresentationPage.hpp>
25 #include <com/sun/star/container/XIndexAccess.hpp>
26 #include <com/sun/star/document/XFilter.hpp>
27 #include <com/sun/star/text/XText.hpp>
28 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
29 #include <com/sun/star/frame/XModel.hpp>
30 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
31 #include <rtl/ustrbuf.hxx>
32 #include <rtl/string.hxx>
33 #include <sax/tools/converter.hxx>
34 #include <osl/diagnose.h>
38 #include "exporter.hxx"
40 #include "tempfile.hxx"
44 using namespace ::com::sun::star::uno
;
45 using namespace ::com::sun::star::drawing
;
46 using namespace ::com::sun::star::container
;
47 using namespace ::com::sun::star::document
;
48 using namespace ::com::sun::star::io
;
49 using namespace ::com::sun::star::lang
;
50 using namespace ::com::sun::star::text
;
51 using namespace ::std
;
53 using com::sun::star::beans::PropertyValue
;
54 using com::sun::star::beans::XPropertySet
;
55 using com::sun::star::presentation::XPresentationPage
;
56 using com::sun::star::task::XStatusIndicator
;
58 // -----------------------------------------------------------------------------
60 PlaceWareExporter::PlaceWareExporter(const Reference
< XMultiServiceFactory
> &rxMSF
)
65 // -----------------------------------------------------------------------------
67 PlaceWareExporter::~PlaceWareExporter()
71 // -----------------------------------------------------------------------------
77 rtl::OUString maTitle
;
78 rtl::OUString maNotes
;
85 OUString
getTempURL() { return maTempFile
.getFileURL(); }
87 void setName( const rtl::OUString
& rName
) { maName
= rName
; }
88 const rtl::OUString
& getName() const { return maName
; }
90 void setTitle( const rtl::OUString
& rTitle
) { maTitle
= rTitle
; }
91 const rtl::OUString
& getTitle() const { return maTitle
; }
93 void setNotes( const rtl::OUString
& rNotes
) { maNotes
= rNotes
; }
94 const rtl::OUString
& getNotes() const { return maNotes
; }
96 void setURL( const rtl::OUString
& rURL
) { maURL
= rURL
; }
97 const rtl::OUString
& getURL() const { return maURL
; }
100 PageEntry::PageEntry()
101 : maTempFile( TempFile::createTempFileURL() )
105 PageEntry::~PageEntry()
110 static void encodeFile( osl::File
& rSourceFile
, Reference
< XOutputStream
>& xOutputStream
) throw( ::com::sun::star::uno::Exception
)
112 if( xOutputStream
.is() )
114 sal_uInt64
nTemp( 0 );
116 osl::File::RC nRC
= rSourceFile
.setPos( osl_Pos_End
, 0 );
117 if( osl::File::E_None
== nRC
)
119 nRC
= rSourceFile
.getPos( nTemp
);
120 if( osl::File::E_None
== nRC
)
122 nRC
= rSourceFile
.setPos( osl_Pos_Absolut
, 0 );
126 sal_Int32 nLen
= static_cast<sal_Int32
>(nTemp
);
128 if( osl::File::E_None
!= nRC
)
131 sal_Int32 nBufferSize
= 3*1024; // !!! buffer size must be a factor of 3 for base64 to work
132 Sequence
< sal_Int8
> aInBuffer( nBufferSize
< nLen
? nBufferSize
: nLen
);
133 void* pInBuffer
= aInBuffer
.getArray();
135 Sequence
< sal_Int8
> aOutBuffer
;
139 nRC
= rSourceFile
.read( pInBuffer
, aInBuffer
.getLength(), nTemp
);
141 if( (nRC
!= osl::File::E_None
) || (0 == nTemp
) )
144 nRead
= static_cast<sal_Int32
>( nTemp
);
146 if( nRead
< aInBuffer
.getLength() )
148 aInBuffer
.realloc( nRead
);
149 pInBuffer
= aInBuffer
.getArray();
154 rtl::OUStringBuffer aStrBuffer
;
155 ::sax::Converter::encodeBase64(aStrBuffer
, aInBuffer
);
157 sal_Int32 nCount
= aStrBuffer
.getLength();
159 if( aOutBuffer
.getLength() != nCount
)
160 aOutBuffer
.realloc( nCount
);
162 sal_Int8
* pBytes
= aOutBuffer
.getArray();
163 const sal_Unicode
* pUnicode
= aStrBuffer
.getStr();
167 // since base64 is always ascii, we can cast safely
168 *pBytes
++ = static_cast<sal_Int8
>(*pUnicode
++);
171 xOutputStream
->writeBytes( aOutBuffer
);
176 static OString
convertString( OUString aInput
)
178 OString
aRet( aInput
.getStr(), aInput
.getLength(), RTL_TEXTENCODING_ASCII_US
);
179 aRet
= aRet
.replace( '\r', ' ' );
180 aRet
= aRet
.replace( '\n', ' ' );
185 static void createSlideFile( Reference
< XComponent
> xDoc
, ZipFile
& rZipFile
, const rtl::OUString
& rURL
, vector
< PageEntry
* >& rPageEntries
) throw( ::com::sun::star::uno::Exception
)
189 const OString
aNewLine( "\r\n" );
192 Reference
< XDocumentPropertiesSupplier
> xDPS( xDoc
, UNO_QUERY
);
193 Reference
< XDocumentProperties
> xDocProps( xDPS
->getDocumentProperties() );
195 aTemp
= xDocProps
->getTitle();
196 if( aTemp
.isEmpty() )
198 sal_Int32 nPos1
= rURL
.lastIndexOf( (sal_Unicode
)'/' );
201 sal_Int32 nPos2
= rURL
.lastIndexOf( (sal_Unicode
)'.' );
204 aTemp
= rURL
.copy( nPos1
+ 1, nPos2
- nPos1
- 1 );
208 aTemp
= rURL
.copy( nPos1
+ 1 );
217 aInfo
+= OString( "SlideSetName: " );
218 aInfo
+= convertString( aTemp
);
221 aTemp
= xDocProps
->getAuthor();
223 if( !aTemp
.isEmpty() )
225 aInfo
+= OString( "PresenterName: " );
226 aInfo
+= convertString( aTemp
);
230 vector
< PageEntry
* >::iterator
aIter( rPageEntries
.begin() );
231 vector
< PageEntry
* >::iterator
aEnd( rPageEntries
.end() );
232 while( aIter
!= aEnd
)
234 PageEntry
* pEntry
= (*aIter
++);
236 aInfo
+= OString( "slide: " );
237 if( !pEntry
->getTitle().isEmpty() )
239 aInfo
+= convertString( pEntry
->getTitle() );
243 aInfo
+= convertString( pEntry
->getName() );
247 aInfo
+= OString( "type: gif");
250 aInfo
+= OString( "url: " );
251 aInfo
+= convertString( pEntry
->getURL() );
255 if( !pEntry
->getNotes().isEmpty() )
257 aInfo
+= OString( "notes: " );
258 aInfo
+= convertString( pEntry
->getNotes() );
263 TempFile
aInfoFile( TempFile::createTempFileURL() );
268 nRC
= aInfoFile
.open( osl_File_OpenFlag_Write
);
269 if( osl::File::E_None
== nRC
)
271 nRC
= aInfoFile
.write( aInfo
.getStr(), aInfo
.getLength(), nTemp
);
272 if( osl::File::E_None
== nRC
)
274 nRC
= aInfoFile
.setPos( osl_Pos_Absolut
, 0 );
275 if( osl::File::E_None
== nRC
)
277 nRC
= aInfoFile
.close();
282 if( (osl::File::E_None
!= nRC
) || !rZipFile
.addFile( aInfoFile
, OString( RTL_CONSTASCII_STRINGPARAM("slides.txt") ) ))
286 //#define PLACEWARE_DEBUG 1
288 sal_Bool
PlaceWareExporter::doExport( Reference
< XComponent
> xDoc
, Reference
< XOutputStream
> xOutputStream
,
289 const rtl::OUString
& rURL
, Reference
< XInterface
> /* xHandler */, Reference
< XStatusIndicator
>& xStatusIndicator
)
291 sal_Bool bRet
= sal_False
;
293 mxGraphicExporter
= Reference
< XExporter
>::query( mxMSF
->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.GraphicExportFilter") ) ) );
294 Reference
< XDrawPagesSupplier
> xDrawPagesSupplier(xDoc
, UNO_QUERY
);
295 if(!xDrawPagesSupplier
.is())
298 Reference
< XIndexAccess
> xDrawPages( xDrawPagesSupplier
->getDrawPages(), UNO_QUERY
);
302 if(xStatusIndicator
.is())
304 xStatusIndicator
->start(OUString( RTL_CONSTASCII_USTRINGPARAM( "PlaceWare:" )),xDrawPages
->getCount());
307 Reference
< XDrawPage
> xDrawPage
;
311 #ifndef PLACEWARE_DEBUG
312 TempFile
aTempFile( TempFile::createTempFileURL() );
313 nRC
= aTempFile
.open( osl_File_OpenFlag_Write
|osl_File_OpenFlag_Read
);
314 OUString
aURL( aTempFile
.getFileURL() );
316 OUString
aURL( RTL_CONSTASCII_USTRINGPARAM("file:///e:/test.zip") );
317 osl::File::remove( aURL
);
318 osl::File
aTempFile( aURL
);
319 nRC
= aTempFile
.open( osl_File_OpenFlag_Create
|osl_File_OpenFlag_Write
|osl_File_OpenFlag_Read
);
322 if( osl::File::E_None
!= nRC
)
325 vector
< PageEntry
* > aPageEntries
;
327 // Create new package...
330 ZipFile
aZipFile(aTempFile
);
332 // export slides as gifs and collect information for slides
334 const sal_Int32 nPageCount
= xDrawPages
->getCount();
337 for( nPage
= 0; nPage
< nPageCount
; nPage
++)
339 xDrawPages
->getByIndex(nPage
) >>= xDrawPage
;
341 if( !xDrawPage
.is() )
344 PageEntry
* pEntry
= exportPage( xDrawPage
);
345 aPageEntries
.push_back( pEntry
);
347 OUString
aName( RTL_CONSTASCII_USTRINGPARAM("i") );
348 aName
+= OUString::valueOf( nPage
);
349 aName
+= OUString( RTL_CONSTASCII_USTRINGPARAM(".gif") );
350 pEntry
->setURL( aName
);
352 if(xStatusIndicator
.is())
354 xStatusIndicator
->setValue( nPage
+ 1 );
358 // create the slide.txt file
360 createSlideFile( xDoc
, aZipFile
, rURL
, aPageEntries
);
363 vector
< PageEntry
* >::iterator
aIter( aPageEntries
.begin() );
364 vector
< PageEntry
* >::iterator
aEnd( aPageEntries
.end() );
365 while( aIter
!= aEnd
)
367 PageEntry
* pEntry
= (*aIter
++);
369 osl::File
aFile(pEntry
->getTempURL() );
370 const OUString
aTemp( pEntry
->getURL() );
372 if( (osl::File::E_None
!= nRC
) || !aZipFile
.addFile( aFile
, OString( aTemp
.getStr(), aTemp
.getLength(), RTL_TEXTENCODING_ASCII_US
) ) )
376 if(!aZipFile
.close())
379 encodeFile( aTempFile
, xOutputStream
);
383 catch ( RuntimeException
const & )
386 catch ( Exception
const & )
390 vector
< PageEntry
* >::iterator
aIter( aPageEntries
.begin() );
391 vector
< PageEntry
* >::iterator
aEnd( aPageEntries
.end() );
392 while( aIter
!= aEnd
)
397 if( xStatusIndicator
.is() )
398 xStatusIndicator
->end();
403 // -----------------------------------------------------------------------------
405 PageEntry
* PlaceWareExporter::exportPage( Reference
< XDrawPage
>&xDrawPage
)
407 Reference
< XComponent
> xComp( xDrawPage
, UNO_QUERY
);
409 PageEntry
* pEntry
= new PageEntry();
412 Reference
< XNamed
> xNamed( xDrawPage
, UNO_QUERY
);
414 pEntry
->setName( xNamed
->getName() );
416 // get title text from title presentation shape if available
417 const OUString
szTitleTextShape( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.TitleTextShape") );
418 const OUString
szIsEmptyPresObj( RTL_CONSTASCII_USTRINGPARAM("IsEmptyPresentationObject") );
420 sal_Int32 nShapeCount
= xDrawPage
->getCount();
422 for( nShape
= 0; nShape
< nShapeCount
; nShape
++ )
424 Reference
< XShape
> xShape
;
425 xDrawPage
->getByIndex( nShape
) >>= xShape
;
427 if( xShape
.is() && xShape
->getShapeType() == szTitleTextShape
)
429 Reference
< XPropertySet
> xPropSet( xShape
, UNO_QUERY
);
432 sal_Bool bIsEmpty
= true;
433 xPropSet
->getPropertyValue( szIsEmptyPresObj
) >>= bIsEmpty
;
437 Reference
< XText
> xText( xShape
, UNO_QUERY
);
440 pEntry
->setTitle( xText
->getString() );
448 // get notes text if available
449 Reference
< XPresentationPage
> xPresPage( xDrawPage
, UNO_QUERY
);
452 Reference
< XDrawPage
> xNotesPage( xPresPage
->getNotesPage() );
454 const OUString
szNotesShape( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.NotesShape") );
456 nShapeCount
= xNotesPage
->getCount();
457 for( nShape
= 0; nShape
< nShapeCount
; nShape
++ )
459 Reference
< XShape
> xShape
;
460 xNotesPage
->getByIndex( nShape
) >>= xShape
;
462 if( xShape
.is() && (xShape
->getShapeType() == szNotesShape
) )
464 Reference
< XPropertySet
> xPropSet( xShape
, UNO_QUERY
);
467 sal_Bool bIsEmpty
= true;
468 xPropSet
->getPropertyValue( szIsEmptyPresObj
) >>= bIsEmpty
;
472 Reference
< XText
> xText( xShape
, UNO_QUERY
);
475 pEntry
->setNotes( xText
->getString() );
485 Reference
< XFilter
> xFilter( mxGraphicExporter
, UNO_QUERY
);
487 Sequence
< PropertyValue
> aFilterData( 2 );
488 aFilterData
[0].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM("Width") );
489 aFilterData
[0].Value
<<= (sal_Int32
)704;
490 aFilterData
[1].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM("Translucent") );
491 aFilterData
[1].Value
<<= (sal_Bool
)sal_False
;
493 Sequence
< PropertyValue
> aDescriptor( 3 );
494 aDescriptor
[0].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM("FilterName") );
495 aDescriptor
[0].Value
<<= OUString( RTL_CONSTASCII_USTRINGPARAM("GIF") );
496 aDescriptor
[1].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM("URL") );
497 aDescriptor
[1].Value
<<= OUString( pEntry
->getTempURL() );
498 aDescriptor
[2].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM("FilterData") );
499 aDescriptor
[2].Value
<<= aFilterData
;
500 mxGraphicExporter
->setSourceDocument( xComp
);
501 xFilter
->filter( aDescriptor
);
506 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */