1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <com/sun/star/awt/Rectangle.hpp>
21 #include <com/sun/star/beans/PropertyValue.hpp>
22 #include <com/sun/star/drawing/GraphicExportFilter.hpp>
23 #include <com/sun/star/drawing/XMasterPageTarget.hpp>
24 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
25 #include <com/sun/star/container/XIndexAccess.hpp>
26 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
27 #include <com/sun/star/lang/XServiceInfo.hpp>
28 #include <vcl/gdimtf.hxx>
29 #include <unotools/tempfile.hxx>
30 #include <osl/diagnose.h>
31 #include <osl/file.hxx>
32 #include <vcl/metaact.hxx>
33 #include <vcl/wmf.hxx>
34 #include <vcl/graphicfilter.hxx>
35 #include <vcl/gdimetafiletools.hxx>
36 #include <memory>
37 
38 #include "swfexporter.hxx"
39 #include "swfwriter.hxx"
40 
41 using namespace ::com::sun::star::uno;
42 using namespace ::com::sun::star::drawing;
43 using namespace ::com::sun::star::task;
44 using namespace ::swf;
45 
46 using com::sun::star::io::XOutputStream;
47 using com::sun::star::beans::PropertyValue;
48 using com::sun::star::container::XIndexAccess;
49 using com::sun::star::beans::XPropertySet;
50 using com::sun::star::lang::XComponent;
51 using com::sun::star::lang::XServiceInfo;
52 
53 
PageInfo()54 PageInfo::PageInfo()
55         : mnBackgroundID( 0 )
56         , mnObjectsID( 0)
57         , mnForegroundID( 0)
58 {
59 }
60 
61 
~PageInfo()62 PageInfo::~PageInfo()
63 {
64 }
65 
66 
FlashExporter(const Reference<XComponentContext> & rxContext,const Reference<XShapes> & rxSelectedShapes,const Reference<XDrawPage> & rxSelectedDrawPage,sal_Int32 nJPEGCompressMode,bool bExportOLEAsJPEG)67 FlashExporter::FlashExporter(
68     const Reference< XComponentContext > &rxContext,
69 
70     // #i56084# variables for selection export
71     const Reference< XShapes >& rxSelectedShapes,
72     const Reference< XDrawPage >& rxSelectedDrawPage,
73 
74     sal_Int32 nJPEGCompressMode,
75     bool bExportOLEAsJPEG)
76     : mxContext(rxContext)
77     // #i56084# variables for selection export
78     , mxSelectedShapes(rxSelectedShapes)
79     , mxSelectedDrawPage(rxSelectedDrawPage)
80     , mbExportSelection(false)
81 
82     , mnDocWidth(0)
83     , mnDocHeight(0)
84     , mnJPEGcompressMode(nJPEGCompressMode)
85     , mbExportOLEAsJPEG(bExportOLEAsJPEG)
86     , mbPresentation(true)
87     , mnPageNumber(-1)
88 {
89     if(mxSelectedDrawPage.is() && mxSelectedShapes.is() && mxSelectedShapes->getCount())
90     {
91         // #i56084# determine export selection
92         mbExportSelection = true;
93     }
94 }
95 
96 
~FlashExporter()97 FlashExporter::~FlashExporter()
98 {
99     Flush();
100 }
101 
Flush()102 void FlashExporter::Flush()
103 {
104     mpWriter.reset();
105     maPagesMap.clear();
106 }
107 
108 
109 const sal_uInt16 cBackgroundDepth = 2;
110 const sal_uInt16 cBackgroundObjectsDepth = 3;
111 const sal_uInt16 cPageObjectsDepth = 4;
112 const sal_uInt16 cWaitButtonDepth = 10;
113 
exportAll(const Reference<XComponent> & xDoc,Reference<XOutputStream> const & xOutputStream,Reference<XStatusIndicator> const & xStatusIndicator)114 bool FlashExporter::exportAll( const Reference< XComponent >& xDoc, Reference< XOutputStream > const &xOutputStream, Reference< XStatusIndicator> const &xStatusIndicator )
115 {
116     Reference< XServiceInfo > xDocServInfo( xDoc, UNO_QUERY );
117     if( xDocServInfo.is() )
118         mbPresentation = xDocServInfo->supportsService( "com.sun.star.presentation.PresentationDocument" );
119 
120     Reference< XDrawPagesSupplier > xDrawPagesSupplier(xDoc, UNO_QUERY);
121     if(!xDrawPagesSupplier.is())
122         return false;
123 
124     Reference< XIndexAccess > xDrawPages = xDrawPagesSupplier->getDrawPages();
125     if(!xDrawPages.is())
126         return false;
127 
128     Reference< XDrawPage > xDrawPage;
129 
130     // #i56084# set xDrawPage directly when exporting selection
131     if(mbExportSelection)
132     {
133         xDrawPage = mxSelectedDrawPage;
134     }
135     else
136     {
137         xDrawPages->getByIndex(0) >>= xDrawPage;
138     }
139 
140     Reference< XPropertySet > xProp( xDrawPage, UNO_QUERY );
141     try
142     {
143         xProp->getPropertyValue( "Width" ) >>= mnDocWidth;
144         xProp->getPropertyValue( "Height" )  >>= mnDocHeight;
145 
146         sal_Int32 nOutputWidth = 14400;
147         sal_Int32 nOutputHeight = (nOutputWidth * mnDocHeight ) / mnDocWidth;
148         mpWriter.reset(new Writer( nOutputWidth, nOutputHeight, mnDocWidth, mnDocHeight, mnJPEGcompressMode  ));
149     }
150     catch( const Exception& )
151     {
152         OSL_ASSERT( false );
153         return false; // no writer, no cookies
154     }
155 
156     // #i56084# nPageCount is 1 when exporting selection
157     const sal_Int32 nPageCount = mbExportSelection ? 1 : xDrawPages->getCount();
158 
159     if ( xStatusIndicator.is() )
160     {
161         xStatusIndicator->start("Macromedia Flash (SWF)", nPageCount);
162     }
163 
164     for( sal_Int32 nPage = 0; nPage < nPageCount; nPage++)
165     {
166         // #i56084# keep PageNumber? We could determine the PageNumber of the single to-be-exported page
167         // when exporting the selection, but this is only used for swf internal, so no need to do so (AFAIK)
168         mnPageNumber = nPage + 1;
169 
170         if ( xStatusIndicator.is() )
171             xStatusIndicator->setValue( nPage );
172 
173         // #i56084# get current xDrawPage when not exporting selection; else already set above
174         if(!mbExportSelection)
175         {
176             xDrawPages->getByIndex(nPage) >>= xDrawPage;
177         }
178 
179         if( !xDrawPage.is())
180             continue;
181 
182         Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY );
183         if( mbPresentation )
184         {
185             bool bVisible = false;
186             xPropSet->getPropertyValue( "Visible" ) >>= bVisible;
187             if( !bVisible )
188                 continue;
189         }
190 
191         // #i56084# no background when exporting selection
192         if(!mbExportSelection)
193         {
194             exportBackgrounds( xDrawPage, nPage, false );
195             exportBackgrounds( xDrawPage, nPage, true );
196         }
197 
198         maPagesMap[nPage].mnForegroundID = mpWriter->startSprite();
199 
200         // #i56084# directly export selection in export selection mode
201         if(mbExportSelection)
202         {
203             exportShapes( mxSelectedShapes, false, false );
204         }
205         else
206         {
207             exportDrawPageContents( xDrawPage, false, false );
208         }
209 
210         mpWriter->endSprite();
211 
212         // AS: If the background is different than the previous slide,
213         //  we have to remove the old one and place the new one.
214         if (nPage)
215         {
216             if (maPagesMap[nPage].mnBackgroundID != maPagesMap[nPage-1].mnBackgroundID)
217             {
218                 mpWriter->removeShape(cBackgroundDepth);
219                 mpWriter->placeShape( maPagesMap[nPage].mnBackgroundID, cBackgroundDepth, 0, 0 );
220             }
221 
222             if (maPagesMap[nPage].mnObjectsID != maPagesMap[nPage-1].mnObjectsID)
223             {
224                 mpWriter->removeShape(cBackgroundObjectsDepth);
225                 mpWriter->placeShape( maPagesMap[nPage].mnObjectsID, cBackgroundObjectsDepth, 0, 0 );
226             }
227 
228             // AS: Remove the Foreground of the previous slide.
229             mpWriter->removeShape(cPageObjectsDepth);
230         }
231         else
232         {
233             mpWriter->placeShape( maPagesMap[nPage].mnBackgroundID, cBackgroundDepth, 0, 0 );
234             mpWriter->placeShape( maPagesMap[nPage].mnObjectsID, cBackgroundObjectsDepth, 0, 0 );
235         }
236 
237         mpWriter->placeShape( maPagesMap[nPage].mnForegroundID, cPageObjectsDepth, 0, 0 );
238 
239         mpWriter->waitOnClick( cWaitButtonDepth );
240         mpWriter->showFrame();
241     }
242 
243     mpWriter->removeShape( cBackgroundDepth );
244     mpWriter->removeShape( cBackgroundObjectsDepth );
245     mpWriter->removeShape( cPageObjectsDepth );
246     mpWriter->gotoFrame( 0 );
247     mpWriter->showFrame();
248 
249     mpWriter->storeTo( xOutputStream );
250 
251     return true;
252 }
253 
254 
exportSlides(const Reference<XDrawPage> & xDrawPage,Reference<XOutputStream> const & xOutputStream)255 bool FlashExporter::exportSlides( const Reference< XDrawPage >& xDrawPage, Reference< XOutputStream > const &xOutputStream )
256 {
257     Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY );
258     if( !xDrawPage.is() || !xPropSet.is() )
259         return false;
260 
261     try
262     {
263         if( !mpWriter )
264         {
265             xPropSet->getPropertyValue( "Width" ) >>= mnDocWidth;
266             xPropSet->getPropertyValue( "Height" ) >>= mnDocHeight;
267 
268             mpWriter.reset(new Writer( 14400, 10800, mnDocWidth, mnDocHeight, mnJPEGcompressMode ));
269         }
270 
271         if( mbPresentation )
272         {
273             bool bVisible = false;
274             xPropSet->getPropertyValue( "Visible" ) >>= bVisible;
275             if( !bVisible )
276                 return false;
277         }
278     }
279     catch( const Exception& )
280     {
281         OSL_ASSERT( false );
282     }
283 
284     exportDrawPageContents(xDrawPage, true, false);
285 
286     mpWriter->storeTo( xOutputStream );
287 
288     return true;
289 }
290 
exportBackgrounds(const Reference<XDrawPage> & xDrawPage,Reference<XOutputStream> const & xOutputStream,sal_uInt16 nPage,bool bExportObjects)291 sal_uInt16 FlashExporter::exportBackgrounds( const Reference< XDrawPage >& xDrawPage, Reference< XOutputStream > const &xOutputStream, sal_uInt16 nPage, bool bExportObjects )
292 {
293     Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY );
294     if( !xDrawPage.is() || !xPropSet.is() )
295         return 0;
296 
297     if( !mpWriter )
298     {
299         xPropSet->getPropertyValue( "Width" ) >>= mnDocWidth;
300         xPropSet->getPropertyValue( "Height" ) >>= mnDocHeight;
301 
302         mpWriter.reset(new Writer( 14400, 10800, mnDocWidth, mnDocHeight, mnJPEGcompressMode ));
303     }
304 
305     sal_uInt16 ret = exportBackgrounds(xDrawPage, nPage, bExportObjects);
306 
307     if (ret != nPage)
308         return ret;
309 
310     if (bExportObjects)
311         mpWriter->placeShape( maPagesMap[nPage].mnObjectsID, uInt16_(1), 0, 0 );
312     else
313         mpWriter->placeShape( maPagesMap[nPage].mnBackgroundID, uInt16_(0), 0, 0 );
314 
315     mpWriter->storeTo( xOutputStream );
316 
317     return nPage;
318 }
319 
exportBackgrounds(Reference<XDrawPage> const & xDrawPage,sal_uInt16 nPage,bool bExportObjects)320 sal_uInt16 FlashExporter::exportBackgrounds( Reference< XDrawPage > const & xDrawPage, sal_uInt16 nPage, bool bExportObjects )
321 {
322     Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY );
323     if( !xDrawPage.is() || !xPropSet.is() )
324         return 0;
325 
326     bool bBackgroundVisible = true;
327     bool bBackgroundObjectsVisible = true;
328 
329     if( mbPresentation )
330     {
331         xPropSet->getPropertyValue( "IsBackgroundVisible" ) >>= bBackgroundVisible;
332         xPropSet->getPropertyValue( "IsBackgroundObjectsVisible" ) >>= bBackgroundObjectsVisible;
333     }
334 
335 
336     if (bExportObjects)
337     {
338         if (bBackgroundObjectsVisible)
339         {
340             Reference< XMasterPageTarget > xMasterPageTarget( xDrawPage, UNO_QUERY );
341             if( !xMasterPageTarget.is() )
342             {
343                 maPagesMap[nPage].mnObjectsID = 0xffff;
344                 return 0xffff;
345             }
346             Reference<XDrawPage> aTemp = xMasterPageTarget->getMasterPage();
347             sal_uInt16 ret = exportMasterPageObjects(nPage, aTemp);
348             if (ret != nPage)
349                 return ret;
350         }
351         else
352         {
353             maPagesMap[nPage].mnObjectsID = 0xffff;
354             return 0xffff;
355         }
356     }
357     else
358     {
359         if (bBackgroundVisible)
360         {
361             sal_uInt16 ret = exportDrawPageBackground(nPage, xDrawPage);
362 
363             if (ret != nPage)
364                 return ret;
365         }
366         else
367         {
368             maPagesMap[nPage].mnBackgroundID = 0xffff;
369             return 0xffff;
370         }
371     }
372 
373     return nPage;
374 }
375 
376 
377 static sal_Int32 nPlaceDepth;
378 // AS: A Slide can have a private background or use its masterpage's background.
379 //  We use the checksums on the metafiles to tell if backgrounds are the same and
380 //  should be reused.  The return value indicates which slide's background to use.
381 //  If the return value != nPage, then there is no background (if == -1) or the
382 //  background has already been exported.
exportDrawPageBackground(sal_uInt16 nPage,Reference<XDrawPage> const & xPage)383 sal_uInt16 FlashExporter::exportDrawPageBackground(sal_uInt16 nPage, Reference< XDrawPage > const & xPage)
384 {
385     sal_uInt16 rBackgroundID;
386 
387     GDIMetaFile aMtfPrivate, aMtfMaster;
388     Reference< XComponent > xComponent( xPage, UNO_QUERY );
389 
390     Reference< XMasterPageTarget > xMasterPageTarget( xPage, UNO_QUERY );
391     if( !xMasterPageTarget.is() )
392         return 0xffff;
393 
394     Reference< XDrawPage > xMasterPage = xMasterPageTarget->getMasterPage();
395     if( !xMasterPage.is())
396         return 0xffff;
397 
398     Reference< XComponent > xCompMaster( xMasterPage, UNO_QUERY );
399 
400     getMetaFile( xCompMaster, aMtfMaster, true );
401     getMetaFile( xComponent, aMtfPrivate, true );
402 
403     BitmapChecksum masterchecksum = aMtfMaster.GetChecksum();
404     BitmapChecksum privatechecksum = aMtfPrivate.GetChecksum();
405 
406     // AS: If the slide has its own background
407     if (privatechecksum)
408     {
409         ChecksumCache::iterator it = gPrivateCache.find(privatechecksum);
410 
411         // AS: and we've previously encountered this background, just return
412         //  the previous index.
413         if (gPrivateCache.end() != it)
414         {
415             maPagesMap[nPage].mnBackgroundID =
416                 maPagesMap[it->second].mnBackgroundID;
417             return it->second;
418         }
419         else
420         {
421             // AS: Otherwise, cache this checksum.
422             gPrivateCache[privatechecksum] = nPage;
423 
424             rBackgroundID = mpWriter->defineShape( aMtfPrivate );
425 
426             maPagesMap[nPage].mnBackgroundID = rBackgroundID;
427             return nPage;
428         }
429     }
430 
431     // AS: Ok, no private background.  Use the master page's.
432     // AS: Have we already exported this master page?
433     ChecksumCache::iterator it = gMasterCache.find(masterchecksum);
434 
435     if (gMasterCache.end() != it)
436     {
437         maPagesMap[nPage].mnBackgroundID =
438             maPagesMap[it->second].mnBackgroundID;
439 
440         return it->second;                // AS: Yes, so don't export it again.
441     }
442 
443     gMasterCache[masterchecksum] = nPage;
444 
445     rBackgroundID = mpWriter->defineShape( aMtfMaster );
446 
447     maPagesMap[nPage].mnBackgroundID = rBackgroundID;
448 
449     return nPage;
450 }
451 
exportMasterPageObjects(sal_uInt16 nPage,Reference<XDrawPage> const & xMasterPage)452 sal_uInt16 FlashExporter::exportMasterPageObjects(sal_uInt16 nPage, Reference< XDrawPage > const & xMasterPage)
453 {
454     BitmapChecksum shapesum = ActionSummer(xMasterPage);
455 
456     ChecksumCache::iterator it = gObjectCache.find(shapesum);
457 
458     if (gObjectCache.end() != it)
459     {
460         maPagesMap[nPage].mnObjectsID =
461             maPagesMap[it->second].mnObjectsID;
462 
463         return it->second;                // AS: Yes, so don't export it again.
464     }
465 
466     gObjectCache[shapesum] = nPage;
467 
468     sal_uInt16 rObjectsID = mpWriter->startSprite();
469     exportDrawPageContents( xMasterPage, false, true );
470     mpWriter->endSprite();
471 
472     maPagesMap[nPage].mnObjectsID = rObjectsID;
473 
474     return nPage;
475 }
476 
477 
478 /** export's the definition of the shapes inside this drawing page and adds the
479     shape infos to the current PageInfo */
exportDrawPageContents(const Reference<XDrawPage> & xPage,bool bStream,bool bMaster)480 void FlashExporter::exportDrawPageContents( const Reference< XDrawPage >& xPage, bool bStream, bool bMaster )
481 {
482     exportShapes(xPage, bStream, bMaster);
483 }
484 
485 
486 /** export's the definition of the shapes inside this XShapes container and adds the
487     shape infos to the current PageInfo */
exportShapes(const Reference<XShapes> & xShapes,bool bStream,bool bMaster)488 void FlashExporter::exportShapes( const Reference< XShapes >& xShapes, bool bStream, bool bMaster )
489 {
490     OSL_ENSURE( (xShapes->getCount() <= 0xffff), "overflow in FlashExporter::exportDrawPageContents()" );
491 
492     sal_uInt16 nShapeCount = static_cast<sal_uInt16>(std::min( xShapes->getCount(), sal_Int32(0xffff) ));
493     sal_uInt16 nShape;
494 
495     Reference< XShape > xShape;
496 
497     for( nShape = 0; nShape < nShapeCount; nShape++ )
498     {
499         xShapes->getByIndex( nShape ) >>= xShape;
500 
501         if( xShape.is() )
502         {
503             Reference< XShapes > xShapes2( xShape, UNO_QUERY );
504             if( xShapes2.is() && xShape->getShapeType() == "com.sun.star.drawing.GroupShape" )
505                 // export the contents of group shapes, but we only ever stream at the top
506                 // recursive level anyway, so pass false for streaming.
507                 exportShapes( xShapes2, false, bMaster);
508             else
509                 exportShape( xShape, bMaster);
510         }
511 
512         if (bStream)
513             mpWriter->showFrame();
514     }
515 }
516 
517 
518 /** export this shape definition and adds it's info to the current PageInfo */
exportShape(const Reference<XShape> & xShape,bool bMaster)519 void FlashExporter::exportShape( const Reference< XShape >& xShape, bool bMaster )
520 {
521     Reference< XPropertySet > xPropSet( xShape, UNO_QUERY );
522     if( !xPropSet.is() )
523         return;
524 
525     if( mbPresentation )
526     {
527         try
528         {
529             // skip empty presentation objects
530             bool bEmpty = false;
531             xPropSet->getPropertyValue( "IsEmptyPresentationObject" ) >>= bEmpty;
532             if( bEmpty )
533                 return;
534 
535             // don't export presentation placeholders on masterpage
536             // they can be non empty when user edits the default texts
537             if( bMaster )
538             {
539                 OUString aShapeType( xShape->getShapeType() );
540                 if( aShapeType == "com.sun.star.presentation.TitleTextShape" ||
541                     aShapeType == "com.sun.star.presentation.OutlinerShape"  ||
542                     aShapeType == "com.sun.star.presentation.HeaderShape"    ||
543                     aShapeType == "com.sun.star.presentation.FooterShape"    ||
544                     aShapeType == "com.sun.star.presentation.SlideNumberShape"  ||
545                     aShapeType == "com.sun.star.presentation.DateTimeShape" )
546                     return;
547             }
548         }
549         catch( const Exception& )
550         {
551             // TODO: If we are exporting a draw, this property is not available
552         }
553     }
554 
555     try
556     {
557             css::awt::Rectangle aBoundRect;
558             xPropSet->getPropertyValue( "BoundRect" ) >>= aBoundRect;
559 
560             std::unique_ptr<ShapeInfo> pShapeInfo(new ShapeInfo());
561             pShapeInfo->mnX = aBoundRect.X;
562             pShapeInfo->mnY = aBoundRect.Y;
563             pShapeInfo->mnWidth = aBoundRect.Width;
564             pShapeInfo->mnHeight = aBoundRect.Height;
565 
566             GDIMetaFile     aMtf;
567             Reference< XComponent > xComponent( xShape, UNO_QUERY );
568 
569             bool bIsOleObject = xShape->getShapeType() == "com.sun.star.presentation.OLE2Shape" || xShape->getShapeType() == "com.sun.star.drawing.OLE2Shape";
570 
571             getMetaFile( xComponent, aMtf );
572 
573             // AS: If it's an OLE object, then export a JPEG if the user requested.
574             //  In this case, we use the bounding rect info generated in the first getMetaFile
575             //  call, and then clear the metafile and add a BMP action.  This may be turned into
576             //  a JPEG, depending on what gives the best compression.
577             if (bIsOleObject && mbExportOLEAsJPEG)
578                 getMetaFile( xComponent, aMtf, false, true );
579 
580             sal_uInt16 nID;
581             BitmapChecksum checksum = aMtf.GetChecksum();
582 
583             ChecksumCache::iterator it = gMetafileCache.find(checksum);
584 
585             if (gMetafileCache.end() != it)
586                 nID = it->second;
587             else
588             {
589                 nID = mpWriter->defineShape( aMtf );
590                 gMetafileCache[checksum] = nID;
591             }
592 
593             if (!nID)
594                 return;
595 
596             pShapeInfo->mnID = nID;
597 
598 //          pPageInfo->addShape( pShapeInfo );
599 
600             mpWriter->placeShape( pShapeInfo->mnID, uInt16_(nPlaceDepth++), pShapeInfo->mnX, pShapeInfo->mnY );
601     }
602     catch( const Exception& )
603     {
604         OSL_ASSERT(false);
605     }
606 }
607 
608 
getMetaFile(Reference<XComponent> const & xComponent,GDIMetaFile & rMtf,bool bOnlyBackground,bool bExportAsJPEG)609 bool FlashExporter::getMetaFile( Reference< XComponent > const &xComponent, GDIMetaFile& rMtf, bool bOnlyBackground /* = false */, bool bExportAsJPEG /* = false */)
610 {
611     if( !mxGraphicExporter.is() )
612         mxGraphicExporter = GraphicExportFilter::create( mxContext );
613 
614     utl::TempFile aFile;
615     aFile.EnableKillingFile();
616 
617     Sequence< PropertyValue > aFilterData(bExportAsJPEG ? 3 : 2);
618     aFilterData[0].Name = "Version";
619     aFilterData[0].Value <<= sal_Int32(6000);
620     aFilterData[1].Name = "PageNumber";
621     aFilterData[1].Value <<= mnPageNumber;
622 
623     if(bExportAsJPEG)
624     {
625         aFilterData[2].Name = "Translucent";
626         aFilterData[2].Value <<= true;
627     }
628 
629     Sequence< PropertyValue > aDescriptor( bOnlyBackground ? 4 : 3 );
630     aDescriptor[0].Name = "FilterName";
631 
632     // AS: If we've been asked to export as an image, then use the BMP filter.
633     //  Otherwise, use SVM.  This is useful for things that don't convert well as
634     //  metafiles, like the occasional OLE object.
635     aDescriptor[0].Value <<= bExportAsJPEG ? OUString("PNG") : OUString("SVM");
636 
637     aDescriptor[1].Name = "URL";
638     aDescriptor[1].Value <<= aFile.GetURL();
639     aDescriptor[2].Name = "FilterData";
640     aDescriptor[2].Value <<= aFilterData;
641     if( bOnlyBackground )
642     {
643         aDescriptor[3].Name = "ExportOnlyBackground";
644         aDescriptor[3].Value <<= bOnlyBackground;
645     }
646     mxGraphicExporter->setSourceDocument( xComponent );
647     mxGraphicExporter->filter( aDescriptor );
648 
649     if (bExportAsJPEG)
650     {
651         Graphic aGraphic;
652         GraphicFilter aFilter(false);
653 
654         aFilter.ImportGraphic( aGraphic, aFile.GetURL(), *aFile.GetStream( StreamMode::READ ) );
655         BitmapEx rBitmapEx( aGraphic.GetBitmapEx().GetBitmap(), Color(255,255,255) );
656 
657         tools::Rectangle clipRect;
658         for( size_t i = 0, nCount = rMtf.GetActionSize(); i < nCount; i++ )
659         {
660             const MetaAction* pAction = rMtf.GetAction( i );
661             if (pAction->GetType() == MetaActionType::ISECTRECTCLIPREGION)
662             {
663                 const MetaISectRectClipRegionAction* pA = static_cast<const MetaISectRectClipRegionAction*>(pAction);
664                 clipRect = pA->GetRect();
665                 break;
666             }
667         }
668         MetaBmpExScaleAction *pmetaAct = new MetaBmpExScaleAction(Point(clipRect.Left(), clipRect.Top()), Size(clipRect.GetWidth(), clipRect.GetHeight()), rBitmapEx);
669 
670         rMtf.Clear();
671         rMtf.AddAction(pmetaAct);
672 
673     }
674     else
675     {
676         rMtf.Read( *aFile.GetStream( StreamMode::READ ) );
677 
678         if(usesClipActions(rMtf))
679         {
680             // #i121267# It is necessary to prepare the metafile since the export does *not* support
681             // clip regions. This tooling method clips the geometry content of the metafile internally
682             // against its own clip regions, so that the export is safe to ignore clip regions
683             clipMetafileContentAgainstOwnRegions(rMtf);
684         }
685     }
686 
687     return rMtf.GetActionSize() != 0;
688 }
689 
ActionSummer(Reference<XShape> const & xShape)690 BitmapChecksum FlashExporter::ActionSummer(Reference< XShape > const & xShape)
691 {
692     Reference< XShapes > xShapes( xShape, UNO_QUERY );
693 
694     if( xShapes.is() )
695     {
696         return ActionSummer(xShapes);
697     }
698     else
699     {
700         Reference< XComponent > xComponentShape( xShape, UNO_QUERY );
701 
702         GDIMetaFile aMtf;
703         getMetaFile( xComponentShape, aMtf);
704 
705         return aMtf.GetChecksum();
706     }
707 }
708 
ActionSummer(Reference<XShapes> const & xShapes)709 BitmapChecksum FlashExporter::ActionSummer(Reference< XShapes > const & xShapes)
710 {
711     sal_uInt32 nShapeCount = xShapes->getCount();
712     BitmapChecksum shapecount = 0;
713 
714     Reference< XShape > xShape2;
715 
716     for( sal_uInt32 nShape = 0; nShape < nShapeCount; nShape++ )
717     {
718         xShapes->getByIndex( nShape ) >>= xShape2;
719 
720         shapecount += ActionSummer(xShape2);
721     }
722 
723     return shapecount;
724 }
725 
726 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
727