Bump for 4.0-15
[LibreOffice.git] / filter / source / placeware / exporter.cxx
blobf019f52093caa0ec5273b3bab5e15bf6c4162c6c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
36 #include <vector>
38 #include "exporter.hxx"
39 #include "zip.hxx"
40 #include "tempfile.hxx"
42 using rtl::OUString;
43 using rtl::OString;
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)
61 : mxMSF( rxMSF )
65 // -----------------------------------------------------------------------------
67 PlaceWareExporter::~PlaceWareExporter()
71 // -----------------------------------------------------------------------------
72 class PageEntry
74 private:
75 TempFile maTempFile;
76 rtl::OUString maName;
77 rtl::OUString maTitle;
78 rtl::OUString maNotes;
79 rtl::OUString maURL;
81 public:
82 PageEntry();
83 ~PageEntry();
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 )
129 throw IOException();
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;
136 sal_Int32 nRead;
137 while( nLen )
139 nRC = rSourceFile.read( pInBuffer, aInBuffer.getLength(), nTemp );
141 if( (nRC != osl::File::E_None) || (0 == nTemp) )
142 throw IOException();
144 nRead = static_cast<sal_Int32>( nTemp );
146 if( nRead < aInBuffer.getLength() )
148 aInBuffer.realloc( nRead );
149 pInBuffer = aInBuffer.getArray();
152 nLen -= nRead;
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();
165 while( nCount-- )
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', ' ' );
182 return aRet;
185 static void createSlideFile( Reference< XComponent > xDoc, ZipFile& rZipFile, const rtl::OUString& rURL, vector< PageEntry* >& rPageEntries ) throw( ::com::sun::star::uno::Exception )
187 OString aInfo;
189 const OString aNewLine( "\r\n" );
190 OUString aTemp;
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)'/' );
199 if( -1 != nPos1 )
201 sal_Int32 nPos2 = rURL.lastIndexOf( (sal_Unicode)'.' );
202 if( nPos2 > nPos1 )
204 aTemp = rURL.copy( nPos1 + 1, nPos2 - nPos1 - 1 );
206 else
208 aTemp = rURL.copy( nPos1 + 1 );
211 else
213 aTemp = rURL;
217 aInfo += OString( "SlideSetName: " );
218 aInfo += convertString( aTemp );
219 aInfo += aNewLine;
221 aTemp = xDocProps->getAuthor();
223 if( !aTemp.isEmpty() )
225 aInfo += OString( "PresenterName: " );
226 aInfo += convertString( aTemp );
227 aInfo += aNewLine;
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() );
241 else
243 aInfo += convertString( pEntry->getName() );
245 aInfo += aNewLine;
247 aInfo += OString( "type: gif");
248 aInfo += aNewLine;
250 aInfo += OString( "url: " );
251 aInfo += convertString( pEntry->getURL() );
252 aInfo += aNewLine;
255 if( !pEntry->getNotes().isEmpty() )
257 aInfo += OString( "notes: " );
258 aInfo += convertString( pEntry->getNotes() );
259 aInfo += aNewLine;
263 TempFile aInfoFile( TempFile::createTempFileURL() );
265 osl::File::RC nRC;
266 sal_uInt64 nTemp;
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") ) ))
283 throw IOException();
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())
296 return sal_False;
298 Reference< XIndexAccess > xDrawPages( xDrawPagesSupplier->getDrawPages(), UNO_QUERY );
299 if(!xDrawPages.is())
300 return sal_False;
302 if(xStatusIndicator.is())
304 xStatusIndicator->start(OUString( RTL_CONSTASCII_USTRINGPARAM( "PlaceWare:" )),xDrawPages->getCount());
307 Reference< XDrawPage > xDrawPage;
309 osl::File::RC nRC;
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() );
315 #else
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 );
320 #endif
322 if( osl::File::E_None != nRC )
323 return sal_False;
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();
335 sal_Int32 nPage;
337 for( nPage = 0; nPage < nPageCount; nPage++)
339 xDrawPages->getByIndex(nPage) >>= xDrawPage;
341 if( !xDrawPage.is() )
342 continue;
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 );
362 // add gifs to zip
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 ) ) )
373 throw IOException();
376 if(!aZipFile.close())
377 throw IOException();
379 encodeFile( aTempFile, xOutputStream );
381 bRet = sal_True;
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 )
394 delete (*aIter++);
397 if( xStatusIndicator.is() )
398 xStatusIndicator->end();
400 return bRet;
403 // -----------------------------------------------------------------------------
405 PageEntry* PlaceWareExporter::exportPage( Reference< XDrawPage >&xDrawPage )
407 Reference< XComponent > xComp( xDrawPage, UNO_QUERY );
409 PageEntry* pEntry = new PageEntry();
411 // get page name
412 Reference< XNamed > xNamed( xDrawPage, UNO_QUERY );
413 if( xNamed.is() )
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();
421 sal_Int32 nShape;
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 );
430 if( xPropSet.is() )
432 sal_Bool bIsEmpty = true;
433 xPropSet->getPropertyValue( szIsEmptyPresObj ) >>= bIsEmpty;
435 if( !bIsEmpty )
437 Reference< XText > xText( xShape, UNO_QUERY );
438 if( xText.is() )
440 pEntry->setTitle( xText->getString() );
444 break;
448 // get notes text if available
449 Reference< XPresentationPage > xPresPage( xDrawPage, UNO_QUERY );
450 if( xPresPage.is() )
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 );
465 if( xPropSet.is() )
467 sal_Bool bIsEmpty = true;
468 xPropSet->getPropertyValue( szIsEmptyPresObj ) >>= bIsEmpty;
470 if( !bIsEmpty )
472 Reference< XText > xText( xShape, UNO_QUERY );
473 if( xText.is() )
475 pEntry->setNotes( xText->getString() );
479 break;
484 // create the gif
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 );
503 return pEntry;
506 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */