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 "ImagePreparer.hxx"
22 #include <comphelper/processfactory.hxx>
23 #include <osl/file.hxx>
24 #include <rtl/ustrbuf.hxx>
25 #include <sax/tools/converter.hxx>
26 #include <rtl/strbuf.hxx>
27 #include <unotools/streamwrap.hxx>
29 #include <svl/itemset.hxx>
30 #include <sfx2/docfile.hxx>
32 #include <com/sun/star/beans/PropertyValue.hpp>
33 #include <com/sun/star/container/XNameAccess.hpp>
34 #include <com/sun/star/document/XFilter.hpp>
35 #include <com/sun/star/document/XImporter.hpp>
36 #include <com/sun/star/document/XExporter.hpp>
37 #include <com/sun/star/drawing/GraphicExportFilter.hpp>
38 #include <com/sun/star/lang/XServiceName.hpp>
39 #include <com/sun/star/presentation/XPresentationPage.hpp>
40 #include <com/sun/star/text/XTextRange.hpp>
43 using namespace ::rtl
;
44 using namespace ::osl
;
45 using namespace ::com::sun::star
;
46 using namespace ::com::sun::star::uno
;
48 ImagePreparer::ImagePreparer(
49 const uno::Reference
<presentation::XSlideShowController
>& rxController
,
50 Transmitter
*aTransmitter
)
51 : xController( rxController
),
52 pTransmitter( aTransmitter
)
59 ImagePreparer::~ImagePreparer()
64 void ImagePreparer::Timeout()
66 sal_uInt32 aSlides
= xController
->getSlideCount();
67 // fprintf( stderr, "ImagePreparer: %d %d %d\n", xController->isRunning(),
68 // (int)mnSendingSlide, (int)aSlides);
69 if ( xController
->isRunning() && // not stopped/disposed of.
70 mnSendingSlide
< aSlides
)
72 sendPreview( mnSendingSlide
);
73 sendNotes( mnSendingSlide
);
81 void ImagePreparer::sendPreview( sal_uInt32 aSlideNumber
)
84 uno::Sequence
<sal_Int8
> aImageData
= preparePreview( aSlideNumber
, 320, 240,
86 if ( !xController
->isRunning() )
89 OUStringBuffer aStrBuffer
;
90 ::sax::Converter::encodeBase64( aStrBuffer
, aImageData
);
92 OString aEncodedShortString
= OUStringToOString(
93 aStrBuffer
.makeStringAndClear(), RTL_TEXTENCODING_UTF8
);
96 OStringBuffer aBuffer
;
98 aBuffer
.append( "slide_preview\n" );
100 aBuffer
.append( OString::valueOf( sal_Int32( aSlideNumber
) ).getStr() );
101 aBuffer
.append( "\n" );
103 aBuffer
.append( aEncodedShortString
.getStr() );
104 aBuffer
.append( "\n\n" );
105 pTransmitter
->addMessage( aBuffer
.makeStringAndClear(),
106 Transmitter::PRIORITY_LOW
);
110 uno::Sequence
<sal_Int8
> ImagePreparer::preparePreview(
111 sal_uInt32 aSlideNumber
, sal_uInt32 aWidth
, sal_uInt32 aHeight
,
115 FileBase::createTempFile( 0, 0, &aFileURL
);
117 uno::Reference
< drawing::XGraphicExportFilter
> xFilter
=
118 drawing::GraphicExportFilter::create( ::comphelper::getProcessComponentContext() );
120 if ( !xController
->isRunning() )
121 return uno::Sequence
<sal_Int8
>();
123 uno::Reference
< lang::XComponent
> xSourceDoc(
124 xController
->getSlideByIndex( aSlideNumber
),
125 uno::UNO_QUERY_THROW
);
127 xFilter
->setSourceDocument( xSourceDoc
);
129 uno::Sequence
< beans::PropertyValue
> aFilterData(3);
131 aFilterData
[0].Name
= "PixelWidth";
132 aFilterData
[0].Value
<<= aWidth
;
134 aFilterData
[1].Name
= "PixelHeight";
135 aFilterData
[1].Value
<<= aHeight
;
137 aFilterData
[2].Name
= "ColorMode";
138 aFilterData
[2].Value
<<= sal_Int32(0); // 0: Color, 1: B&W
140 uno::Sequence
< beans::PropertyValue
> aProps(3);
142 aProps
[0].Name
= "MediaType";
143 aProps
[0].Value
<<= OUString( "image/png" );
145 aProps
[1].Name
= "URL";
146 aProps
[1].Value
<<= aFileURL
;
148 aProps
[2].Name
= "FilterData";
149 aProps
[2].Value
<<= aFilterData
;
151 xFilter
->filter( aProps
);
153 // FIXME: error handling.
155 File
aFile( aFileURL
);
159 aFile
.getSize( rSize
);
160 uno::Sequence
<sal_Int8
> aContents( rSize
);
162 aFile
.read( aContents
.getArray(), rSize
, aRead
);
164 File::remove( aFileURL
);
169 void ImagePreparer::sendNotes( sal_uInt32 aSlideNumber
)
172 OString aNotes
= prepareNotes( aSlideNumber
);
174 if ( aNotes
.isEmpty() )
177 // OUStringBuffer aStrBuffer;
178 // ::sax::Converter::encodeBase64( aStrBuffer, aTemp );
180 // OString aNotes = OUStringToOString(
181 // aStrBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8 );
183 if ( !xController
->isRunning() )
187 OStringBuffer aBuffer
;
189 aBuffer
.append( "slide_notes\n" );
191 aBuffer
.append( OString::valueOf( sal_Int32( aSlideNumber
) ).getStr() );
192 aBuffer
.append( "\n" );
194 aBuffer
.append( "<html><body>" );
195 aBuffer
.append( aNotes
);
196 aBuffer
.append( "</html></body>" );
197 aBuffer
.append( "\n\n" );
198 pTransmitter
->addMessage( aBuffer
.makeStringAndClear(),
199 Transmitter::PRIORITY_LOW
);
202 sal_Bool
ExportTo( uno::Reference
< drawing::XDrawPage
>& aNotesPage
, String aUrl
);
204 // Code copied from sdremote/source/presenter/PresenterNotesView.cxx
205 OString
ImagePreparer::prepareNotes( sal_uInt32 aSlideNumber
)
209 if ( !xController
->isRunning() )
212 uno::Reference
<css::drawing::XDrawPage
> aNotesPage
;
213 uno::Reference
< drawing::XDrawPage
> xSourceDoc(
214 xController
->getSlideByIndex( aSlideNumber
),
215 uno::UNO_QUERY_THROW
);
216 uno::Reference
<presentation::XPresentationPage
> xPresentationPage(
217 xSourceDoc
, UNO_QUERY
);
218 if (xPresentationPage
.is())
219 aNotesPage
= xPresentationPage
->getNotesPage();
224 static const OUString
sNotesShapeName (
225 "com.sun.star.presentation.NotesShape" );
226 static const OUString
sTextShapeName (
227 "com.sun.star.drawing.TextShape" );
229 uno::Reference
<container::XIndexAccess
> xIndexAccess ( aNotesPage
, UNO_QUERY
);
230 if (xIndexAccess
.is())
233 // Iterate over all shapes and find the one that holds the text.
234 sal_Int32
nCount (xIndexAccess
->getCount());
235 for (sal_Int32 nIndex
=0; nIndex
<nCount
; ++nIndex
)
238 uno::Reference
<lang::XServiceName
> xServiceName (
239 xIndexAccess
->getByIndex(nIndex
), UNO_QUERY
);
240 if (xServiceName
.is()
241 && xServiceName
->getServiceName().equals(sNotesShapeName
))
243 uno::Reference
<text::XTextRange
> xText (xServiceName
, UNO_QUERY
);
246 aRet
.append(xText
->getString());
247 aRet
.append("<br/>");
252 uno::Reference
<drawing::XShapeDescriptor
> xShapeDescriptor (
253 xIndexAccess
->getByIndex(nIndex
), UNO_QUERY
);
254 if (xShapeDescriptor
.is())
256 OUString
sType (xShapeDescriptor
->getShapeType());
257 if (sType
.equals(sNotesShapeName
) || sType
.equals(sTextShapeName
))
259 uno::Reference
<text::XTextRange
> xText (
260 xIndexAccess
->getByIndex(nIndex
), UNO_QUERY
);
263 aRet
.append(xText
->getString());
264 aRet
.append("<br/>");
271 // Replace all newlines with <br\> tags
272 for ( sal_Int32 i
= 0; i
< aRet
.getLength(); i
++ )
274 if ( aRet
[i
] == '\n' )
277 aRet
.insert( i
+1, "br/>" );
280 return OUStringToOString(
281 aRet
.makeStringAndClear(), RTL_TEXTENCODING_UTF8
);
284 sal_Bool
ExportTo( uno::Reference
< drawing::XDrawPage
>& aNotesPage
, String aUrl
)
286 OUString
aFilterName( "XHTML Draw File" );
287 uno::Reference
< document::XExporter
> xExporter
;
290 uno::Reference
< lang::XMultiServiceFactory
> xMan
= ::comphelper::getProcessServiceFactory();
291 uno::Reference
< lang::XMultiServiceFactory
> xFilterFact (
292 xMan
->createInstance( "com.sun.star.document.FilterFactory" ), uno::UNO_QUERY
);
294 uno::Sequence
< beans::PropertyValue
> aProps
;
295 uno::Reference
< container::XNameAccess
> xFilters ( xFilterFact
, uno::UNO_QUERY
);
296 if ( xFilters
->hasByName( aFilterName
) )
297 xFilters
->getByName( aFilterName
) >>= aProps
;
299 fprintf( stderr
, "Couldn't find by name.\n" );
301 OUString aFilterImplName
;
302 sal_Int32 nFilterProps
= aProps
.getLength();
303 for ( sal_Int32 nFilterProp
= 0; nFilterProp
<nFilterProps
; nFilterProp
++ )
305 const beans::PropertyValue
& rFilterProp
= aProps
[nFilterProp
];
306 if ( rFilterProp
.Name
.compareToAscii("FilterService") == 0 )
308 rFilterProp
.Value
>>= aFilterImplName
;
313 fprintf( stderr
, "aName%s\n", OUStringToOString(aFilterImplName
, RTL_TEXTENCODING_UTF8
).getStr() );
314 if ( !aFilterImplName
.isEmpty() )
317 xExporter
= uno::Reference
< document::XExporter
>
318 ( xFilterFact
->createInstanceWithArguments( aFilterName
, uno::Sequence
< uno::Any
>() ), uno::UNO_QUERY
);
319 }catch(const uno::Exception
&)
322 fprintf( stderr
, "Couldn't create instance of filter.\n" );
327 if ( xExporter
.is() )
330 uno::Reference
< lang::XComponent
> xComp( aNotesPage
, uno::UNO_QUERY_THROW
);
331 uno::Reference
< document::XFilter
> xFilter( xExporter
, uno::UNO_QUERY_THROW
);
332 xExporter
->setSourceDocument( xComp
);
334 com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
> aOldArgs ( 2 );
335 aOldArgs
[0].Name
= "FileName";
336 aOldArgs
[0].Value
<<= OUString( aUrl
);
337 aOldArgs
[1].Name
= "FilterName";
338 aOldArgs
[1].Value
<<= OUString("com.sun.star.documentconversion.XSLTFilter");
340 SfxMedium
rMedium( aUrl
, STREAM_STD_WRITE
);
342 const com::sun::star::beans::PropertyValue
* pOldValue
= aOldArgs
.getConstArray();
343 com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
> aArgs ( aOldArgs
.getLength() );
344 com::sun::star::beans::PropertyValue
* pNewValue
= aArgs
.getArray();
347 // put in the REAL file name, and copy all PropertyValues
348 const OUString
sOutputStream ( "OutputStream" );
349 const OUString
sStream ( "StreamForOutput" );
350 sal_Bool bHasOutputStream
= sal_False
;
351 sal_Bool bHasStream
= sal_False
;
352 sal_Bool bHasBaseURL
= sal_False
;
354 sal_Int32 nEnd
= aOldArgs
.getLength();
356 for ( i
= 0; i
< nEnd
; i
++ )
358 pNewValue
[i
] = pOldValue
[i
];
359 if ( pOldValue
[i
].Name
== "FileName" )
360 pNewValue
[i
].Value
<<= OUString ( rMedium
.GetName() );
361 else if ( pOldValue
[i
].Name
== sOutputStream
)
362 bHasOutputStream
= sal_True
;
363 else if ( pOldValue
[i
].Name
== sStream
)
364 bHasStream
= sal_True
;
365 else if ( pOldValue
[i
].Name
== "DocumentBaseURL" )
366 bHasBaseURL
= sal_True
;
369 if ( !bHasOutputStream
)
371 aArgs
.realloc ( ++nEnd
);
372 aArgs
[nEnd
-1].Name
= sOutputStream
;
373 aArgs
[nEnd
-1].Value
<<= uno::Reference
< io::XOutputStream
> ( new utl::OOutputStreamWrapper ( *rMedium
.GetOutStream() ) );
376 // add stream as well, for OOX export and maybe others
379 aArgs
.realloc ( ++nEnd
);
380 aArgs
[nEnd
-1].Name
= sStream
;
381 aArgs
[nEnd
-1].Value
<<= com::sun::star::uno::Reference
< com::sun::star::io::XStream
> ( new utl::OStreamWrapper ( *rMedium
.GetOutStream() ) );
386 aArgs
.realloc ( ++nEnd
);
387 aArgs
[nEnd
-1].Name
= OUString( "DocumentBaseURL" );
388 aArgs
[nEnd
-1].Value
<<= rMedium
.GetBaseURL( sal_True
);
391 return xFilter
->filter( aArgs
);
392 }catch(const uno::Exception
&)
399 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */