xref: /trunk/main/svx/source/unodraw/UnoGraphicExporter.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 
27 #include <vector>
28 #include <vos/mutex.hxx>
29 #include <com/sun/star/io/XOutputStream.hpp>
30 #include <com/sun/star/container/XChild.hpp>
31 #include <com/sun/star/frame/XModel.hpp>
32 #include <com/sun/star/document/XFilter.hpp>
33 #include <com/sun/star/document/XExporter.hpp>
34 #include <com/sun/star/document/XMimeTypeInfo.hpp>
35 #include <com/sun/star/lang/XServiceInfo.hpp>
36 #include <com/sun/star/lang/XComponent.hpp>
37 #include <com/sun/star/drawing/XShape.hpp>
38 #include <com/sun/star/drawing/XDrawPage.hpp>
39 #include <com/sun/star/graphic/XGraphic.hpp>
40 #include <com/sun/star/graphic/XGraphicRenderer.hpp>
41 #include <com/sun/star/task/XStatusIndicator.hpp>
42 #include <com/sun/star/task/XInteractionHandler.hpp>
43 #include <com/sun/star/task/XInteractionContinuation.hpp>
44 
45 #include <comphelper/interaction.hxx>
46 #include <framework/interaction.hxx>
47 #include <com/sun/star/drawing/GraphicFilterRequest.hpp>
48 #include <com/sun/star/util/URL.hpp>
49 #include <cppuhelper/implbase4.hxx>
50 #include <osl/diagnose.h>
51 #include <osl/mutex.hxx>
52 #include <vcl/metaact.hxx>
53 #include <vcl/svapp.hxx>
54 #include <vcl/virdev.hxx>
55 #include <svtools/FilterConfigItem.hxx>
56 #include <svl/outstrm.hxx>
57 #include <svx/sdr/contact/objectcontactofobjlistpainter.hxx>
58 #include <svx/sdr/contact/viewobjectcontact.hxx>
59 #include <svx/sdr/contact/viewcontact.hxx>
60 #include <svx/sdr/contact/displayinfo.hxx>
61 #include <svx/sdr/contact/viewcontactofsdrobj.hxx>
62 #include <editeng/numitem.hxx>
63 #include <svx/svdpagv.hxx>
64 #include <svx/svdograf.hxx>
65 #include "svx/xoutbmp.hxx"
66 #include "svtools/filter.hxx"
67 #include "svx/unoapi.hxx"
68 #include <svx/svdpage.hxx>
69 #include <svx/svdmodel.hxx>
70 #include <svx/fmview.hxx>
71 #include <svx/fmmodel.hxx>
72 #include <svx/unopage.hxx>
73 #include <svx/pageitem.hxx>
74 #include <editeng/eeitem.hxx>
75 #include <svx/svdoutl.hxx>
76 #include <editeng/flditem.hxx>
77 
78 #include "boost/scoped_ptr.hpp"
79 
80 #define MAX_EXT_PIX         2048
81 
82 using namespace ::comphelper;
83 using namespace ::osl;
84 using namespace ::vos;
85 using ::rtl::OUString;
86 using namespace ::cppu;
87 using namespace ::com::sun::star;
88 using namespace ::com::sun::star::uno;
89 using namespace ::com::sun::star::util;
90 using namespace ::com::sun::star::container;
91 using namespace ::com::sun::star::drawing;
92 using namespace ::com::sun::star::lang;
93 using namespace ::com::sun::star::document;
94 using namespace ::com::sun::star::frame;
95 using namespace ::com::sun::star::beans;
96 using namespace ::com::sun::star::task;
97 #include <svx/sdr/contact/viewobjectcontactredirector.hxx>
98 #include <svx/sdr/contact/viewobjectcontact.hxx>
99 #include <svx/sdr/contact/viewcontact.hxx>
100 
101 // #i102251#
102 #include <editeng/editstat.hxx>
103 
104 //////////////////////////////////////////////////////////////////////////////
105 
106 namespace svx
107 {
108     struct ExportSettings
109     {
110         OUString maFilterName;
111         OUString maMediaType;
112         URL maURL;
113         com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > mxOutputStream;
114         com::sun::star::uno::Reference< com::sun::star::graphic::XGraphicRenderer > mxGraphicRenderer;
115         com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator >    mxStatusIndicator;
116         com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler > mxInteractionHandler;
117 
118         sal_Int32 mnWidth;
119         sal_Int32 mnHeight;
120         sal_Bool mbExportOnlyBackground;
121         sal_Bool mbVerboseComments;
122         sal_Bool mbScrollText;
123         sal_Bool mbUseHighContrast;
124         sal_Bool mbTranslucent;
125 
126         Sequence< PropertyValue >   maFilterData;
127 
128         Fraction    maScaleX;
129         Fraction    maScaleY;
130 
131         ExportSettings( SdrModel* pDoc );
132     };
133 
ExportSettings(SdrModel * pDoc)134     ExportSettings::ExportSettings( SdrModel* pDoc )
135     : mnWidth( 0 )
136     , mnHeight( 0 )
137     , mbExportOnlyBackground( false )
138     , mbVerboseComments( false )
139     , mbScrollText( false )
140     , mbUseHighContrast( false )
141     , mbTranslucent( sal_False )
142     , maScaleX( 1, 1 )
143     , maScaleY( 1, 1 )
144     {
145         if( pDoc )
146         {
147             maScaleX = pDoc->GetScaleFraction();
148             maScaleY = pDoc->GetScaleFraction();
149         }
150     }
151 
152     /** implements a component to export shapes or pages to external graphic formats.
153 
154         @implements com.sun.star.drawing.GraphicExportFilter
155     */
156     class GraphicExporter : public WeakImplHelper4< XFilter, XExporter, XServiceInfo, XMimeTypeInfo >
157     {
158     public:
159         GraphicExporter();
160         virtual ~GraphicExporter();
161 
162         // XFilter
163         virtual sal_Bool SAL_CALL filter( const Sequence< PropertyValue >& aDescriptor );
164         virtual void SAL_CALL cancel(  );
165 
166         // XExporter
167         virtual void SAL_CALL setSourceDocument( const Reference< XComponent >& xDoc );
168 
169         // XServiceInfo
170         virtual OUString SAL_CALL getImplementationName(  );
171         virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName );
172         virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(  );
173 
174         // XMimeTypeInfo
175         virtual sal_Bool SAL_CALL supportsMimeType( const ::rtl::OUString& MimeTypeName );
176         virtual Sequence< OUString > SAL_CALL getSupportedMimeTypeNames(  );
177 
178         VirtualDevice* CreatePageVDev( SdrPage* pPage, sal_uIntPtr nWidthPixel, sal_uIntPtr nHeightPixel ) const;
179 
180         DECL_LINK( CalcFieldValueHdl, EditFieldInfo* );
181 
182         void ParseSettings( const Sequence< PropertyValue >& aDescriptor, ExportSettings& rSettings );
183         bool GetGraphic( ExportSettings& rSettings, Graphic& aGraphic, sal_Bool bVectorType );
184 
185     private:
186         Reference< XShape >     mxShape;
187         Reference< XDrawPage >  mxPage;
188         Reference< XShapes >    mxShapes;
189 
190         SvxDrawPage*        mpUnoPage;
191 
192         Link                maOldCalcFieldValueHdl;
193         sal_Int32           mnPageNumber;
194         SdrPage*            mpCurrentPage;
195         SdrModel*           mpDoc;
196     };
197 
GraphicExporter_createInstance(const Reference<XMultiServiceFactory> &)198     SVX_DLLPUBLIC Reference< XInterface > SAL_CALL GraphicExporter_createInstance(const Reference< XMultiServiceFactory > & )
199     {
200         return (XWeak*)new GraphicExporter();
201     }
202 
GraphicExporter_getSupportedServiceNames()203     SVX_DLLPUBLIC Sequence< OUString > SAL_CALL GraphicExporter_getSupportedServiceNames()
204         throw()
205     {
206         Sequence< OUString > aSupportedServiceNames( 1 );
207         aSupportedServiceNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.GraphicExportFilter" ) );
208         return aSupportedServiceNames;
209     }
210 
GraphicExporter_getImplementationName()211     SVX_DLLPUBLIC OUString SAL_CALL GraphicExporter_getImplementationName()
212         throw()
213     {
214         return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Draw.GraphicExporter" ) );
215     }
216 
217     /** creates a bitmap that is optionaly transparent from a metafile
218     */
GetBitmapFromMetaFile(const GDIMetaFile & rMtf,sal_Bool bTransparent,const Size * pSize)219     BitmapEx GetBitmapFromMetaFile( const GDIMetaFile& rMtf, sal_Bool bTransparent, const Size* pSize )
220     {
221         BitmapEx aBmpEx;
222 
223         if(bTransparent)
224         {
225             // use new primitive conversion tooling
226             basegfx::B2DRange aRange(basegfx::B2DPoint(0.0, 0.0));
227             sal_uInt32 nMaximumQuadraticPixels(500000);
228 
229             if(pSize)
230             {
231                 // use 100th mm for primitive bitmap converter tool, input is pixel
232                 // use a real OutDev to get the correct DPI, the static LogicToLogic assumes 72dpi which is wrong (!)
233                 const Size aSize100th(Application::GetDefaultDevice()->PixelToLogic(*pSize, MapMode(MAP_100TH_MM)));
234 
235                 aRange.expand(basegfx::B2DPoint(aSize100th.Width(), aSize100th.Height()));
236 
237                 // when explicitly pixels are requested from the GraphicExporter, use a *very* high limit
238                 // of 16gb (4096x4096 pixels), else use the default for the converters
239                 nMaximumQuadraticPixels = std::min(sal_uInt32(4096 * 4096), sal_uInt32(pSize->Width() * pSize->Height()));
240             }
241             else
242             {
243                 // use 100th mm for primitive bitmap converter tool
244                 const Size aSize100th(Application::GetDefaultDevice()->LogicToLogic(rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), MapMode(MAP_100TH_MM)));
245 
246                 aRange.expand(basegfx::B2DPoint(aSize100th.Width(), aSize100th.Height()));
247             }
248 
249             aBmpEx = convertMetafileToBitmapEx(rMtf, aRange, nMaximumQuadraticPixels);
250         }
251         else
252         {
253             const SvtOptionsDrawinglayer aDrawinglayerOpt;
254             Size aTargetSize(0, 0);
255 
256             if(pSize)
257             {
258                 // #122820# If a concrete target size in pixels is given, use it
259                 aTargetSize = *pSize;
260 
261                 // get hairline and full bound rect to evtl. reduce given target pixel size when
262                 // it is known that it will be expanded to get the right and bottom hairlines right
263                 Rectangle aHairlineRect;
264                 const Rectangle aRect(rMtf.GetBoundRect(*Application::GetDefaultDevice(), &aHairlineRect));
265 
266                 if(!aRect.IsEmpty() && !aHairlineRect.IsEmpty())
267                 {
268                     if(aRect.Right() == aHairlineRect.Right() || aRect.Bottom() == aHairlineRect.Bottom())
269                     {
270                         if(aTargetSize.Width())
271                         {
272                             aTargetSize.Width() -= 1;
273                         }
274 
275                         if(aTargetSize.Height())
276                         {
277                             aTargetSize.Height() -= 1;
278                         }
279                     }
280                 }
281             }
282 
283             const GraphicConversionParameters aParameters(
284                 aTargetSize,
285                 true, // allow unlimited size
286                 aDrawinglayerOpt.IsAntiAliasing(),
287                 aDrawinglayerOpt.IsSnapHorVerLinesToDiscrete());
288             const Graphic aGraphic(rMtf);
289 
290             aBmpEx = BitmapEx(aGraphic.GetBitmap(aParameters));
291             aBmpEx.SetPrefMapMode( rMtf.GetPrefMapMode() );
292             aBmpEx.SetPrefSize( rMtf.GetPrefSize() );
293         }
294 
295         return aBmpEx;
296     }
297 
CalcSize(sal_Int32 nWidth,sal_Int32 nHeight,const Size & aBoundSize,Size & aOutSize)298     Size* CalcSize( sal_Int32 nWidth, sal_Int32 nHeight, const Size& aBoundSize, Size& aOutSize )
299     {
300         if( (nWidth == 0) && (nHeight == 0) )
301             return NULL;
302 
303         if( (nWidth == 0) && (nHeight != 0) && (aBoundSize.Height() != 0) )
304         {
305             nWidth = ( nHeight * aBoundSize.Width() ) / aBoundSize.Height();
306         }
307         else if( (nWidth != 0) && (nHeight == 0) && (aBoundSize.Width() != 0) )
308         {
309             nHeight = ( nWidth * aBoundSize.Height() ) / aBoundSize.Width();
310         }
311 
312         aOutSize.Width() = nWidth;
313         aOutSize.Height() = nHeight;
314 
315         return &aOutSize;
316     }
317 }
318 
319 class ImplExportCheckVisisbilityRedirector : public ::sdr::contact::ViewObjectContactRedirector
320 {
321 public:
322     ImplExportCheckVisisbilityRedirector( SdrPage* pCurrentPage );
323     virtual ~ImplExportCheckVisisbilityRedirector();
324 
325     virtual drawinglayer::primitive2d::Primitive2DSequence createRedirectedPrimitive2DSequence(
326         const sdr::contact::ViewObjectContact& rOriginal,
327         const sdr::contact::DisplayInfo& rDisplayInfo);
328 
329 private:
330     SdrPage*    mpCurrentPage;
331 };
332 
ImplExportCheckVisisbilityRedirector(SdrPage * pCurrentPage)333 ImplExportCheckVisisbilityRedirector::ImplExportCheckVisisbilityRedirector( SdrPage* pCurrentPage )
334 :   ViewObjectContactRedirector(), mpCurrentPage( pCurrentPage )
335 {
336 }
337 
~ImplExportCheckVisisbilityRedirector()338 ImplExportCheckVisisbilityRedirector::~ImplExportCheckVisisbilityRedirector()
339 {
340 }
341 
createRedirectedPrimitive2DSequence(const sdr::contact::ViewObjectContact & rOriginal,const sdr::contact::DisplayInfo & rDisplayInfo)342 drawinglayer::primitive2d::Primitive2DSequence ImplExportCheckVisisbilityRedirector::createRedirectedPrimitive2DSequence(
343     const sdr::contact::ViewObjectContact& rOriginal,
344     const sdr::contact::DisplayInfo& rDisplayInfo)
345 {
346     SdrObject* pObject = rOriginal.GetViewContact().TryToGetSdrObject();
347 
348     if(pObject)
349     {
350         SdrPage* pPage = mpCurrentPage;
351         if( pPage == 0 )
352             pPage = pObject->GetPage();
353 
354         if( (pPage == 0) || pPage->checkVisibility(rOriginal, rDisplayInfo, false) )
355         {
356             return ::sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(rOriginal, rDisplayInfo);
357         }
358 
359         return drawinglayer::primitive2d::Primitive2DSequence();
360     }
361     else
362     {
363         // not an object, maybe a page
364         return ::sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(rOriginal, rDisplayInfo);
365     }
366 }
367 
368 using namespace ::svx;
369 
GraphicExporter()370 GraphicExporter::GraphicExporter()
371 : mpUnoPage( NULL ), mnPageNumber(-1), mpCurrentPage(0), mpDoc( NULL )
372 {
373 }
374 
~GraphicExporter()375 GraphicExporter::~GraphicExporter()
376 {
377 }
378 
IMPL_LINK(GraphicExporter,CalcFieldValueHdl,EditFieldInfo *,pInfo)379 IMPL_LINK(GraphicExporter, CalcFieldValueHdl, EditFieldInfo*, pInfo)
380 {
381     if( pInfo )
382     {
383         if( mpCurrentPage )
384         {
385             pInfo->SetSdrPage( mpCurrentPage );
386         }
387         else if( mnPageNumber != -1 )
388         {
389             const SvxFieldData* pField = pInfo->GetField().GetField();
390             if( pField && pField->ISA( SvxPageField ) )
391             {
392                 String aPageNumValue;
393                 sal_Bool bUpper = sal_False;
394 
395                 switch(mpDoc->GetPageNumType())
396                 {
397                     case SVX_CHARS_UPPER_LETTER:
398                         aPageNumValue += (sal_Unicode)(char)((mnPageNumber - 1) % 26 + 'A');
399                         break;
400                     case SVX_CHARS_LOWER_LETTER:
401                         aPageNumValue += (sal_Unicode)(char)((mnPageNumber - 1) % 26 + 'a');
402                         break;
403                     case SVX_ROMAN_UPPER:
404                         bUpper = sal_True;
405                     case SVX_ROMAN_LOWER:
406                         aPageNumValue += SvxNumberFormat::CreateRomanString(mnPageNumber, bUpper);
407                         break;
408                     case SVX_NUMBER_NONE:
409                         aPageNumValue.Erase();
410                         aPageNumValue += sal_Unicode(' ');
411                         break;
412                     default:
413                         aPageNumValue += String::CreateFromInt32( (sal_Int32)mnPageNumber );
414                 }
415 
416                 pInfo->SetRepresentation( aPageNumValue );
417 
418                 return(0);
419             }
420         }
421     }
422 
423     long nRet = maOldCalcFieldValueHdl.Call( pInfo );
424 
425     if( pInfo && mpCurrentPage )
426         pInfo->SetSdrPage( 0 );
427 
428     return nRet;
429 }
430 
431 /** creates an virtual device for the given page
432 
433     @return the returned VirtualDevice is owned by the caller
434 */
CreatePageVDev(SdrPage * pPage,sal_uIntPtr nWidthPixel,sal_uIntPtr nHeightPixel) const435 VirtualDevice* GraphicExporter::CreatePageVDev( SdrPage* pPage, sal_uIntPtr nWidthPixel, sal_uIntPtr nHeightPixel ) const
436 {
437     VirtualDevice*  pVDev = new VirtualDevice();
438     MapMode         aMM( MAP_100TH_MM );
439 
440     Point aPoint( 0, 0 );
441     Size aPageSize(pPage->GetSize());
442 
443     // use scaling?
444     if( nWidthPixel )
445     {
446         const Fraction aFrac( (long) nWidthPixel, pVDev->LogicToPixel( aPageSize, aMM ).Width() );
447 
448         aMM.SetScaleX( aFrac );
449 
450         if( nHeightPixel == 0 )
451             aMM.SetScaleY( aFrac );
452     }
453 
454     if( nHeightPixel )
455     {
456         const Fraction aFrac( (long) nHeightPixel, pVDev->LogicToPixel( aPageSize, aMM ).Height() );
457 
458         if( nWidthPixel == 0 )
459             aMM.SetScaleX( aFrac );
460 
461         aMM.SetScaleY( aFrac );
462     }
463 
464     pVDev->SetMapMode( aMM );
465     bool bSuccess(false);
466 
467     // #122820# If available, use pixel size directly
468     if(nWidthPixel && nHeightPixel)
469     {
470         bSuccess = pVDev->SetOutputSizePixel(Size(nWidthPixel, nHeightPixel));
471     }
472     else
473     {
474         bSuccess = pVDev->SetOutputSize(aPageSize);
475     }
476 
477     if(bSuccess)
478     {
479         SdrView* pView = new SdrView(mpDoc, pVDev);
480         pView->SetPageVisible( sal_False );
481         pView->SetBordVisible( sal_False );
482         pView->SetGridVisible( sal_False );
483         pView->SetHlplVisible( sal_False );
484         pView->SetGlueVisible( sal_False );
485         pView->ShowSdrPage(pPage);
486         Region aRegion (Rectangle( aPoint, aPageSize ) );
487 
488         ImplExportCheckVisisbilityRedirector aRedirector( mpCurrentPage );
489 
490         pView->CompleteRedraw(pVDev, aRegion, &aRedirector);
491         delete pView;
492     }
493     else
494     {
495         OSL_ENSURE(false, "Could not get a VirtualDevice of requested size (!)");
496     }
497 
498     return pVDev;
499 }
500 
ParseSettings(const Sequence<PropertyValue> & aDescriptor,ExportSettings & rSettings)501 void GraphicExporter::ParseSettings( const Sequence< PropertyValue >& aDescriptor, ExportSettings& rSettings )
502 {
503     sal_Int32 nArgs = aDescriptor.getLength();
504     const PropertyValue* pValues = aDescriptor.getConstArray();
505     while( nArgs-- )
506     {
507         if( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "FilterName" ) ) )
508         {
509             pValues->Value >>= rSettings.maFilterName;
510         }
511         else if( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) )
512         {
513             pValues->Value >>= rSettings.maMediaType;
514         }
515         else if( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "URL" ) ) )
516         {
517             if( !( pValues->Value >>= rSettings.maURL ) )
518             {
519                 pValues->Value >>= rSettings.maURL.Complete;
520             }
521         }
522         else if( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "OutputStream" ) ) )
523         {
524             pValues->Value >>= rSettings.mxOutputStream;
525         }
526         else if( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "GraphicRenderer" ) ) )
527         {
528             pValues->Value >>= rSettings.mxGraphicRenderer;
529         }
530         else if ( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "StatusIndicator" ) ) )
531         {
532             pValues->Value >>= rSettings.mxStatusIndicator;
533         }
534         else if ( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "InteractionHandler" ) ) )
535         {
536             pValues->Value >>= rSettings.mxInteractionHandler;
537         }
538         else if( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Width" ) ) )  // for compatibility reasons, deprecated
539         {
540             pValues->Value >>= rSettings.mnWidth;
541         }
542         else if( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Height" ) ) ) // for compatibility reasons, deprecated
543         {
544             pValues->Value >>= rSettings.mnHeight;
545         }
546         else if( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ExportOnlyBackground" ) ) )   // for compatibility reasons, deprecated
547         {
548             pValues->Value >>= rSettings.mbExportOnlyBackground;
549         }
550         else if ( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "FilterData" ) ) )
551         {
552             pValues->Value >>= rSettings.maFilterData;
553 
554             sal_Int32 nFilterArgs = rSettings.maFilterData.getLength();
555             PropertyValue* pDataValues = rSettings.maFilterData.getArray();
556             while( nFilterArgs-- )
557             {
558                 if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Translucent" ) ) )
559                 {
560                     if ( !( pDataValues->Value >>= rSettings.mbTranslucent ) )  // SJ: TODO: The GIF Transparency is stored as int32 in
561                     {                                               // configuration files, this has to be changed to boolean
562                         sal_Int32 nTranslucent = 0;
563                         if ( pDataValues->Value >>= nTranslucent )
564                             rSettings.mbTranslucent = nTranslucent != 0;
565                     }
566                 }
567                 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "PixelWidth" ) ) )
568                 {
569                     pDataValues->Value >>= rSettings.mnWidth;
570                 }
571                 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "PixelHeight" ) ) )
572                 {
573                     pDataValues->Value >>= rSettings.mnHeight;
574                 }
575                 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Width" ) ) )  // for compatibility reasons, deprecated
576                 {
577                     pDataValues->Value >>= rSettings.mnWidth;
578                     pDataValues->Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "PixelWidth" ) );
579                 }
580                 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Height" ) ) ) // for compatibility reasons, deprecated
581                 {
582                     pDataValues->Value >>= rSettings.mnHeight;
583                     pDataValues->Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "PixelHeight" ) );
584                 }
585                 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ExportOnlyBackground" ) ) )
586                 {
587                     pDataValues->Value >>= rSettings.mbExportOnlyBackground;
588                 }
589                 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "HighContrast" ) ) )
590                 {
591                     pDataValues->Value >>= rSettings.mbUseHighContrast;
592                 }
593                 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "PageNumber" ) ) )
594                 {
595                     pDataValues->Value >>= mnPageNumber;
596                 }
597                 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "VerboseComments" ) ) )
598                 {
599                     // #110496# Read flag for verbose metafile comments
600                     pDataValues->Value >>= rSettings.mbVerboseComments;
601                 }
602                 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScrollText" ) ) )
603                 {
604                     // #110496# Read flag solitary scroll text metafile
605                     pDataValues->Value >>= rSettings.mbScrollText;
606                 }
607                 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CurrentPage" ) ) )
608                 {
609                     Reference< XDrawPage >  xPage;
610                     pDataValues->Value >>= xPage;
611                     if( xPage.is() )
612                     {
613                         SvxDrawPage* pUnoPage = SvxDrawPage::getImplementation( xPage );
614                         if( pUnoPage && pUnoPage->GetSdrPage() )
615                             mpCurrentPage = pUnoPage->GetSdrPage();
616                     }
617                 }
618                 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleXNumerator" ) ) )
619                 {
620                     sal_Int32 nVal = 1;
621                     if( pDataValues->Value >>= nVal )
622                         rSettings.maScaleX = Fraction( nVal, rSettings.maScaleX.GetDenominator() );
623                 }
624                 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleXDenominator" ) ) )
625                 {
626                     sal_Int32 nVal = 1;
627                     if( pDataValues->Value >>= nVal )
628                         rSettings.maScaleX = Fraction( rSettings.maScaleX.GetNumerator(), nVal );
629                 }
630                 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleYNumerator" ) ) )
631                 {
632                     sal_Int32 nVal = 1;
633                     if( pDataValues->Value >>= nVal )
634                         rSettings.maScaleY = Fraction( nVal, rSettings.maScaleY.GetDenominator() );
635                 }
636                 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleYDenominator" ) ) )
637                 {
638                     sal_Int32 nVal = 1;
639                     if( pDataValues->Value >>= nVal )
640                         rSettings.maScaleY = Fraction( rSettings.maScaleY.GetNumerator(), nVal );
641                 }
642 
643                 pDataValues++;
644             }
645         }
646 
647         pValues++;
648     }
649 
650     // putting the StatusIndicator that we got from the MediaDescriptor into our local FilterData copy
651     if ( rSettings.mxStatusIndicator.is() )
652     {
653         rtl::OUString sStatusIndicator( RTL_CONSTASCII_USTRINGPARAM( "StatusIndicator" ) );
654         int i = rSettings.maFilterData.getLength();
655         rSettings.maFilterData.realloc( i + 1 );
656         rSettings.maFilterData[ i ].Name = sStatusIndicator;
657         rSettings.maFilterData[ i ].Value <<= rSettings.mxStatusIndicator;
658     }
659 }
660 
GetGraphic(ExportSettings & rSettings,Graphic & aGraphic,sal_Bool bVectorType)661 bool GraphicExporter::GetGraphic( ExportSettings& rSettings, Graphic& aGraphic, sal_Bool bVectorType )
662 {
663     if( !mpDoc || !mpUnoPage )
664         return false;
665 
666     SdrPage* pPage = mpUnoPage->GetSdrPage();
667     if( !pPage )
668         return false;
669 
670     VirtualDevice       aVDev;
671     const MapMode       aMap( mpDoc->GetScaleUnit(), Point(), rSettings.maScaleX, rSettings.maScaleY );
672 
673     SdrOutliner& rOutl=mpDoc->GetDrawOutliner(NULL);
674     maOldCalcFieldValueHdl = rOutl.GetCalcFieldValueHdl();
675     rOutl.SetCalcFieldValueHdl( LINK(this, GraphicExporter, CalcFieldValueHdl) );
676     rOutl.SetBackgroundColor( pPage->GetPageBackgroundColor() );
677 
678     // #i102251#
679     const sal_uInt32 nOldCntrl(rOutl.GetControlWord());
680     sal_uInt32 nCntrl = nOldCntrl & ~EE_CNTRL_ONLINESPELLING;
681     rOutl.SetControlWord(nCntrl);
682 
683     SdrObject* pTempBackgroundShape = 0;
684     std::vector< SdrObject* > aShapes;
685     bool bRet = true;
686 
687     // export complete page?
688     if ( !mxShape.is() )
689     {
690         if( rSettings.mbExportOnlyBackground )
691         {
692             const SdrPageProperties* pCorrectProperties = pPage->getCorrectSdrPageProperties();
693 
694             if(pCorrectProperties)
695             {
696                 pTempBackgroundShape = new SdrRectObj(Rectangle(Point(0,0), pPage->GetSize()));
697                 pTempBackgroundShape->SetMergedItemSet(pCorrectProperties->GetItemSet());
698                 pTempBackgroundShape->SetMergedItem(XLineStyleItem(XLINE_NONE));
699                 pTempBackgroundShape->NbcSetStyleSheet(pCorrectProperties->GetStyleSheet(), true);
700                 aShapes.push_back(pTempBackgroundShape);
701             }
702         }
703         else
704         {
705             const Size aSize( pPage->GetSize() );
706 
707             // generate a bitmap to convert it to a pixel format.
708             // For gif pictures there can also be a vector format used (bTranslucent)
709             if ( !bVectorType && !rSettings.mbTranslucent )
710             {
711                 long nWidthPix = 0;
712                 long nHeightPix = 0;
713                 if ( rSettings.mnWidth > 0 && rSettings.mnHeight > 0 )
714                 {
715                     nWidthPix = rSettings.mnWidth;
716                     nHeightPix = rSettings.mnHeight;
717                 }
718                 else
719                 {
720                     const Size aSizePix( Application::GetDefaultDevice()->LogicToPixel( aSize, aMap ) );
721                     if (aSizePix.Width() > MAX_EXT_PIX || aSizePix.Height() > MAX_EXT_PIX)
722                     {
723                         if (aSizePix.Width() > MAX_EXT_PIX)
724                             nWidthPix = MAX_EXT_PIX;
725                         else
726                             nWidthPix = aSizePix.Width();
727                         if (aSizePix.Height() > MAX_EXT_PIX)
728                             nHeightPix = MAX_EXT_PIX;
729                         else
730                             nHeightPix = aSizePix.Height();
731 
732                         double fWidthDif = aSizePix.Width() / nWidthPix;
733                         double fHeightDif = aSizePix.Height() / nHeightPix;
734 
735                         if (fWidthDif > fHeightDif)
736                             nHeightPix = static_cast<long>(aSizePix.Height() / fWidthDif);
737                         else
738                             nWidthPix = static_cast<long>(aSizePix.Width() / fHeightDif);
739                     }
740                     else
741                     {
742                         nWidthPix = aSizePix.Width();
743                         nHeightPix = aSizePix.Height();
744                     }
745                 }
746 
747                 boost::scoped_ptr< SdrView > pLocalView;
748                 if( PTR_CAST( FmFormModel, mpDoc ) )
749                 {
750                     pLocalView.reset( new FmFormView( PTR_CAST( FmFormModel, mpDoc ), &aVDev ) );
751                 }
752                 else
753                 {
754                     pLocalView.reset( new SdrView( mpDoc, &aVDev ) );
755                 }
756 
757 
758                 VirtualDevice*  pVDev = CreatePageVDev( pPage, nWidthPix, nHeightPix );
759 
760                 if( pVDev )
761                 {
762                     aGraphic = pVDev->GetBitmap( Point(), pVDev->GetOutputSize() );
763                     aGraphic.SetPrefMapMode( aMap );
764                     aGraphic.SetPrefSize( aSize );
765                     delete pVDev;
766                 }
767             }
768             // create a metafile to export a vector format
769             else
770             {
771                 GDIMetaFile aMtf;
772 
773                 aVDev.SetMapMode( aMap );
774                 if( rSettings.mbUseHighContrast )
775                     aVDev.SetDrawMode( aVDev.GetDrawMode() | DRAWMODE_SETTINGSLINE | DRAWMODE_SETTINGSFILL | DRAWMODE_SETTINGSTEXT | DRAWMODE_SETTINGSGRADIENT );
776                 aVDev.EnableOutput( sal_False );
777                 aMtf.Record( &aVDev );
778                 Size aNewSize;
779 
780                 // create a view
781                 SdrView*        pView;
782 
783                 if( PTR_CAST( FmFormModel, mpDoc ) )
784                 {
785                     pView = new FmFormView( PTR_CAST( FmFormModel, mpDoc ), &aVDev );
786                 }
787                 else
788                 {
789                     pView = new SdrView( mpDoc, &aVDev );
790                 }
791 
792                 pView->SetBordVisible( sal_False );
793                 pView->SetPageVisible( sal_False );
794                 pView->ShowSdrPage( pPage );
795 
796                 if ( pView && pPage )
797                 {
798                     pView->SetBordVisible( sal_False );
799                     pView->SetPageVisible( sal_False );
800                     pView->ShowSdrPage( pPage );
801 
802                     const Point aNewOrg( pPage->GetLftBorder(), pPage->GetUppBorder() );
803                     aNewSize = Size( aSize.Width() - pPage->GetLftBorder() - pPage->GetRgtBorder(),
804                                           aSize.Height() - pPage->GetUppBorder() - pPage->GetLwrBorder() );
805                     const Rectangle aClipRect( aNewOrg, aNewSize );
806                     MapMode         aVMap( aMap );
807 
808                     aVDev.Push();
809                     aVMap.SetOrigin( Point( -aNewOrg.X(), -aNewOrg.Y() ) );
810                     aVDev.SetRelativeMapMode( aVMap );
811                     aVDev.IntersectClipRegion( aClipRect );
812 
813                     // Use new StandardCheckVisisbilityRedirector
814                     ImplExportCheckVisisbilityRedirector aRedirector( mpCurrentPage );
815 
816                     pView->CompleteRedraw(&aVDev, Region(Rectangle(Point(), aNewSize)), &aRedirector);
817 
818                     aVDev.Pop();
819 
820                     aMtf.Stop();
821                     aMtf.WindStart();
822                     aMtf.SetPrefMapMode( aMap );
823                     aMtf.SetPrefSize( aNewSize );
824 
825                     // AW: Here the current version was filtering out the META_CLIPREGION_ACTIONs
826                     // from the metafile. I asked some other developers why this was done, but no
827                     // one knew a direct reason. Since it's in for long time, it may be an old
828                     // piece of code. MetaFiles save and load ClipRegions with polygons with preserving
829                     // the polygons, so a resolution-indepent roundtrip is supported. Removed this
830                     // code since it destroys some MetaFiles where ClipRegions are used. Anyways,
831                     // just filtering them out is a hack, at least the encapsulated content would need
832                     // to be clipped geometrically.
833                     aGraphic = Graphic(aMtf);
834                 }
835 
836                 if ( pView )
837                 {
838                     pView->HideSdrPage();
839                     delete pView;
840                 }
841 
842                 if( rSettings.mbTranslucent )
843                 {
844                     Size aOutSize;
845                     aGraphic = GetBitmapFromMetaFile( aGraphic.GetGDIMetaFile(), sal_True, CalcSize( rSettings.mnWidth, rSettings.mnHeight, aNewSize, aOutSize ) );
846                 }
847             }
848         }
849     }
850 
851     // export only single shape or shape collection
852     else
853     {
854         // build list of SdrObject
855         if( mxShapes.is() )
856         {
857             Reference< XShape > xShape;
858             const sal_Int32 nCount = mxShapes->getCount();
859 
860             for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ )
861             {
862                 mxShapes->getByIndex( nIndex ) >>= xShape;
863                 SdrObject* pObj = GetSdrObjectFromXShape( xShape );
864                 if( pObj )
865                     aShapes.push_back( pObj );
866             }
867         }
868         else
869         {
870             // only one shape
871             SdrObject* pObj = GetSdrObjectFromXShape( mxShape );
872             if( pObj )
873                 aShapes.push_back( pObj );
874         }
875 
876         if( aShapes.empty() )
877             bRet = false;
878     }
879 
880     if( bRet && !aShapes.empty() )
881     {
882         // special treatment for only one SdrGrafObj that has text
883         sal_Bool bSingleGraphic = sal_False;
884 
885         if( 1 == aShapes.size() )
886         {
887             if( !bVectorType )
888             {
889                 SdrObject* pObj = aShapes.front();
890                 if( pObj && pObj->ISA( SdrGrafObj ) && !( (SdrGrafObj*) pObj )->HasText() )
891                 {
892                     aGraphic = ( (SdrGrafObj*) pObj )->GetTransformedGraphic();
893                     if ( aGraphic.GetType() == GRAPHIC_BITMAP )
894                     {
895                         Size aSizePixel( aGraphic.GetSizePixel() );
896                         if( rSettings.mnWidth && rSettings.mnHeight &&
897                             ( ( rSettings.mnWidth != aSizePixel.Width() ) ||
898                               ( rSettings.mnHeight != aSizePixel.Height() ) ) )
899                         {
900                             BitmapEx aBmpEx( aGraphic.GetBitmapEx() );
901                             // export: use highest quality
902                             aBmpEx.Scale( Size( rSettings.mnWidth, rSettings.mnHeight ), BMP_SCALE_LANCZOS );
903                             aGraphic = aBmpEx;
904                         }
905 
906                         // #118804# only accept for bitmap graphics, else the
907                         // conversion to bitmap will happen anywhere without size control
908                         // as evtl. defined in rSettings.mnWidth/mnHeight
909                         bSingleGraphic = sal_True;
910                     }
911                 }
912             }
913             else if( rSettings.mbScrollText )
914             {
915                 SdrObject* pObj = aShapes.front();
916                 if( pObj && pObj->ISA( SdrTextObj )
917                     && ( (SdrTextObj*) pObj )->HasText() )
918                 {
919                     Rectangle aScrollRectangle;
920                     Rectangle aPaintRectangle;
921 
922                     const boost::scoped_ptr< GDIMetaFile > pMtf(
923                         ( (SdrTextObj*) pObj )->GetTextScrollMetaFileAndRectangle(
924                         aScrollRectangle, aPaintRectangle ) );
925 
926                     // take the larger one of the two rectangles (that
927                     // should be the bound rect of the retrieved
928                     // metafile)
929                     Rectangle aTextRect;
930 
931                     if( aScrollRectangle.IsInside( aPaintRectangle ) )
932                         aTextRect = aScrollRectangle;
933                     else
934                         aTextRect = aPaintRectangle;
935 
936                     // setup pref size and mapmode
937                     pMtf->SetPrefSize( aTextRect.GetSize() );
938 
939                     // set actual origin (mtf is at actual shape
940                     // output position)
941                     MapMode aLocalMapMode( aMap );
942                     aLocalMapMode.SetOrigin(
943                         Point( -aPaintRectangle.Left(),
944                                -aPaintRectangle.Top() ) );
945                     pMtf->SetPrefMapMode( aLocalMapMode );
946 
947                     pMtf->AddAction( new MetaCommentAction(
948                                          "XTEXT_SCROLLRECT", 0,
949                                          reinterpret_cast<sal_uInt8 const*>(&aScrollRectangle),
950                                          sizeof( Rectangle ) ) );
951                     pMtf->AddAction( new MetaCommentAction(
952                                          "XTEXT_PAINTRECT", 0,
953                                          reinterpret_cast<sal_uInt8 const*>(&aPaintRectangle),
954                                          sizeof( Rectangle ) ) );
955 
956                     aGraphic = Graphic( *pMtf );
957 
958                     bSingleGraphic = sal_True;
959                 }
960             }
961         }
962 
963         if( !bSingleGraphic )
964         {
965             // create a metafile for all shapes
966             VirtualDevice   aOut;
967 
968             // calculate bound rect for all shapes
969             Rectangle aBound;
970 
971             {
972                 std::vector< SdrObject* >::iterator aIter = aShapes.begin();
973                 const std::vector< SdrObject* >::iterator aEnd = aShapes.end();
974 
975                 while( aIter != aEnd )
976                 {
977                     SdrObject* pObj = (*aIter++);
978                     Rectangle aR1(pObj->GetCurrentBoundRect());
979                     if (aBound.IsEmpty())
980                         aBound=aR1;
981                     else
982                         aBound.Union(aR1);
983                 }
984             }
985 
986             aOut.EnableOutput( sal_False );
987             aOut.SetMapMode( aMap );
988             if( rSettings.mbUseHighContrast )
989                 aOut.SetDrawMode( aVDev.GetDrawMode() | DRAWMODE_SETTINGSLINE | DRAWMODE_SETTINGSFILL | DRAWMODE_SETTINGSTEXT | DRAWMODE_SETTINGSGRADIENT );
990 
991             GDIMetaFile aMtf;
992             aMtf.Clear();
993             aMtf.Record( &aOut );
994 
995             MapMode aOutMap( aMap );
996             aOutMap.SetOrigin( Point( -aBound.TopLeft().X(), -aBound.TopLeft().Y() ) );
997             aOut.SetRelativeMapMode( aOutMap );
998 
999             sdr::contact::DisplayInfo aDisplayInfo;
1000 
1001             if(mpCurrentPage)
1002             {
1003                 if(mpCurrentPage->TRG_HasMasterPage() && pPage->IsMasterPage())
1004                 {
1005                     // MasterPage is processed as another page's SubContent
1006                     aDisplayInfo.SetProcessLayers(mpCurrentPage->TRG_GetMasterPageVisibleLayers());
1007                     aDisplayInfo.SetSubContentActive(true);
1008                 }
1009             }
1010 
1011             if(!aShapes.empty())
1012             {
1013                 // more effective way to paint a vector of SdrObjects. Hand over the processed page
1014                 // to have it in the
1015                 sdr::contact::ObjectContactOfObjListPainter aMultiObjectPainter(aOut, aShapes, mpCurrentPage);
1016                 ImplExportCheckVisisbilityRedirector aCheckVisibilityRedirector(mpCurrentPage);
1017                 aMultiObjectPainter.SetViewObjectContactRedirector(&aCheckVisibilityRedirector);
1018 
1019                 aMultiObjectPainter.ProcessDisplay(aDisplayInfo);
1020             }
1021 
1022             aMtf.Stop();
1023             aMtf.WindStart();
1024 
1025             const Size  aExtSize( aOut.PixelToLogic( Size( 0, 0  ) ) );
1026             Size        aBoundSize( aBound.GetWidth() + ( aExtSize.Width() ),
1027                                     aBound.GetHeight() + ( aExtSize.Height() ) );
1028 
1029             aMtf.SetPrefMapMode( aMap );
1030             aMtf.SetPrefSize( aBoundSize );
1031 
1032             if( !bVectorType )
1033             {
1034                 Size aOutSize;
1035                 aGraphic = GetBitmapFromMetaFile( aMtf, rSettings.mbTranslucent, CalcSize( rSettings.mnWidth, rSettings.mnHeight, aBoundSize, aOutSize ) );
1036             }
1037             else
1038             {
1039                 aGraphic = aMtf;
1040             }
1041         }
1042     }
1043 
1044     if(pTempBackgroundShape)
1045     {
1046         SdrObject::Free(pTempBackgroundShape);
1047     }
1048 
1049     rOutl.SetCalcFieldValueHdl( maOldCalcFieldValueHdl );
1050 
1051     // #i102251#
1052     rOutl.SetControlWord(nOldCntrl);
1053 
1054     return bRet;
1055 
1056 }
1057 
1058 // XFilter
filter(const Sequence<PropertyValue> & aDescriptor)1059 sal_Bool SAL_CALL GraphicExporter::filter( const Sequence< PropertyValue >& aDescriptor )
1060 {
1061     OGuard aGuard( Application::GetSolarMutex() );
1062 
1063     if( NULL == mpUnoPage )
1064         return sal_False;
1065 
1066     GraphicFilter*              pFilter = GraphicFilter::GetGraphicFilter();
1067 
1068     if( NULL == pFilter || NULL == mpUnoPage->GetSdrPage() || NULL == mpDoc )
1069         return sal_False;
1070 
1071     // get the arguments from the descriptor
1072     ExportSettings aSettings( mpDoc );
1073     ParseSettings( aDescriptor, aSettings );
1074 
1075     const sal_uInt16    nFilter = aSettings.maMediaType.getLength()
1076                             ? pFilter->GetExportFormatNumberForMediaType( aSettings.maMediaType )
1077                             : pFilter->GetExportFormatNumberForShortName( aSettings.maFilterName );
1078     sal_Bool            bVectorType = !pFilter->IsExportPixelFormat( nFilter );
1079 
1080     // create the output stuff
1081     Graphic aGraphic;
1082 
1083     sal_uInt16 nStatus = GetGraphic( aSettings, aGraphic, bVectorType ) ? GRFILTER_OK : GRFILTER_FILTERERROR;
1084 
1085     if( nStatus == GRFILTER_OK )
1086     {
1087         // export graphic only if it has a size
1088         const Size aGraphSize( aGraphic.GetPrefSize() );
1089         if ( ( aGraphSize.Width() == 0 ) || ( aGraphSize.Height() == 0 ) )
1090         {
1091             nStatus = GRFILTER_FILTERERROR;
1092         }
1093         else
1094         {
1095             // now we have a graphic, so export it
1096             if( aSettings.mxGraphicRenderer.is() )
1097             {
1098                 // render graphic directly into given renderer
1099                 aSettings.mxGraphicRenderer->render( aGraphic.GetXGraphic() );
1100             }
1101             else if( aSettings.mxOutputStream.is() )
1102             {
1103                 // TODO: Either utilize optional XSeekable functionality for the
1104                 // SvOutputStream, or adapt the graphic filter to not seek anymore.
1105                 SvMemoryStream aStream( 1024, 1024 );
1106 
1107                 nStatus = pFilter->ExportGraphic( aGraphic, String(), aStream, nFilter, &aSettings.maFilterData );
1108 
1109                 // copy temp stream to XOutputStream
1110                 SvOutputStream aOutputStream( aSettings.mxOutputStream );
1111                 aStream.Seek(0);
1112                 aOutputStream << aStream;
1113             }
1114             else
1115             {
1116                 INetURLObject aURLObject( aSettings.maURL.Complete );
1117                 DBG_ASSERT( aURLObject.GetProtocol() != INET_PROT_NOT_VALID, "invalid URL" );
1118 
1119                 nStatus = XOutBitmap::ExportGraphic( aGraphic, aURLObject, *pFilter, nFilter, &aSettings.maFilterData );
1120             }
1121         }
1122     }
1123 
1124     if ( aSettings.mxInteractionHandler.is() && ( nStatus != GRFILTER_OK ) )
1125     {
1126         Any aInteraction;
1127         Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionContinuation > > lContinuations(1);
1128         ::comphelper::OInteractionApprove* pApprove = new ::comphelper::OInteractionApprove();
1129         lContinuations[0] = Reference< XInteractionContinuation >(static_cast< XInteractionContinuation* >(pApprove), UNO_QUERY);
1130 
1131         GraphicFilterRequest aErrorCode;
1132         aErrorCode.ErrCode = nStatus;
1133         aInteraction <<= aErrorCode;
1134         aSettings.mxInteractionHandler->handle( framework::InteractionRequest::CreateRequest( aInteraction, lContinuations ) );
1135     }
1136     return nStatus == GRFILTER_OK;
1137 }
1138 
cancel()1139 void SAL_CALL GraphicExporter::cancel()
1140 {
1141 }
1142 
1143 // XExporter
1144 
1145 /** the source 'document' could be a XDrawPage, a XShape or a generic XShapes */
setSourceDocument(const Reference<lang::XComponent> & xComponent)1146 void SAL_CALL GraphicExporter::setSourceDocument( const Reference< lang::XComponent >& xComponent )
1147 {
1148     OGuard aGuard( Application::GetSolarMutex() );
1149 
1150     mxShapes = NULL;
1151     mpUnoPage = NULL;
1152 
1153     try
1154     {
1155     // any break inside this one loop while will throw a IllegalArgumentException
1156     do
1157     {
1158         mxPage = Reference< XDrawPage >::query( xComponent );
1159         mxShapes = Reference< XShapes >::query( xComponent );
1160         mxShape = Reference< XShape >::query( xComponent );
1161 
1162         // Step 1: try a generic XShapes
1163         if( !mxPage.is() && !mxShape.is() && mxShapes.is() )
1164         {
1165             // we do not support empty shape collections
1166             if( 0 == mxShapes->getCount() )
1167                 break;
1168 
1169             // get first shape to detect corresponding page and model
1170             mxShapes->getByIndex(0) >>= mxShape;
1171         }
1172         else
1173         {
1174             mxShapes = NULL;
1175         }
1176 
1177         // Step 2: try a shape
1178         if( mxShape.is() )
1179         {
1180             if( NULL == GetSdrObjectFromXShape( mxShape ) )
1181                 break;
1182 
1183             // get page for this shape
1184             Reference< XChild > xChild( mxShape, UNO_QUERY );
1185             if( !xChild.is() )
1186                 break;
1187 
1188             Reference< XInterface > xInt;
1189             do
1190             {
1191                 xInt = xChild->getParent();
1192                 mxPage = Reference< XDrawPage >::query( xInt );
1193                 if( !mxPage.is() )
1194                     xChild = Reference< XChild >::query( xInt );
1195             }
1196             while( !mxPage.is() && xChild.is() );
1197 
1198             if( !mxPage.is() )
1199                 break;
1200         }
1201 
1202         // Step 3: check the page
1203         if( !mxPage.is() )
1204             break;
1205 
1206         mpUnoPage = SvxDrawPage::getImplementation( mxPage );
1207 
1208         if( NULL == mpUnoPage || NULL == mpUnoPage->GetSdrPage() )
1209             break;
1210 
1211         mpDoc = mpUnoPage->GetSdrPage()->GetModel();
1212 
1213         // Step 4:  If we got a generic XShapes test all contained shapes
1214         //          if they belong to the same XDrawPage
1215 
1216         if( mxShapes.is() )
1217         {
1218             SdrPage* pPage = mpUnoPage->GetSdrPage();
1219             SdrObject* pObj;
1220             Reference< XShape > xShape;
1221 
1222             sal_Bool bOk = sal_True;
1223 
1224             const sal_Int32 nCount = mxShapes->getCount();
1225 
1226             // test all but the first shape if they have the same page than
1227             // the first shape
1228             for( sal_Int32 nIndex = 1; bOk && ( nIndex < nCount ); nIndex++ )
1229             {
1230                 mxShapes->getByIndex( nIndex ) >>= xShape;
1231                 pObj = GetSdrObjectFromXShape( xShape );
1232                 bOk = pObj && pObj->GetPage() == pPage;
1233             }
1234 
1235             if( !bOk )
1236                 break;
1237         }
1238 
1239         // no errors so far
1240         return;
1241     }
1242     while( 0 );
1243     }
1244     catch( Exception& )
1245     {
1246     }
1247 
1248     throw IllegalArgumentException();
1249 }
1250 
1251 // XServiceInfo
getImplementationName()1252 OUString SAL_CALL GraphicExporter::getImplementationName(  )
1253 {
1254     return GraphicExporter_getImplementationName();
1255 }
1256 
supportsService(const OUString & ServiceName)1257 sal_Bool SAL_CALL GraphicExporter::supportsService( const OUString& ServiceName )
1258 {
1259     Sequence< OUString > aSeq( GraphicExporter_getSupportedServiceNames() );
1260     sal_Int32 nArgs = aSeq.getLength();
1261     const OUString* pService = aSeq.getConstArray();
1262     while( nArgs-- )
1263         if( *pService++ == ServiceName )
1264             return sal_True;
1265 
1266     return sal_False;
1267 }
1268 
getSupportedServiceNames()1269 Sequence< OUString > SAL_CALL GraphicExporter::getSupportedServiceNames(  )
1270 {
1271     return GraphicExporter_getSupportedServiceNames();
1272 }
1273 
1274 // XMimeTypeInfo
supportsMimeType(const OUString & MimeTypeName)1275 sal_Bool SAL_CALL GraphicExporter::supportsMimeType( const OUString& MimeTypeName )
1276 {
1277     const String aMimeTypeName( MimeTypeName );
1278 
1279     GraphicFilter*  pFilter = GraphicFilter::GetGraphicFilter();
1280     sal_uInt16 nCount = pFilter->GetExportFormatCount();
1281     sal_uInt16 nFilter;
1282     for( nFilter = 0; nFilter < nCount; nFilter++ )
1283     {
1284         if( aMimeTypeName.Equals( pFilter->GetExportFormatMediaType( nFilter ) ) )
1285         {
1286             return sal_True;
1287         }
1288     }
1289 
1290     return sal_False;
1291 }
1292 
getSupportedMimeTypeNames()1293 Sequence< OUString > SAL_CALL GraphicExporter::getSupportedMimeTypeNames(  )
1294 {
1295     GraphicFilter*  pFilter = GraphicFilter::GetGraphicFilter();
1296     sal_uInt16 nCount = pFilter->GetExportFormatCount();
1297     sal_uInt16 nFilter;
1298     sal_uInt16 nFound = 0;
1299 
1300     Sequence< OUString > aSeq( nCount );
1301     OUString* pStr = aSeq.getArray();
1302 
1303     for( nFilter = 0; nFilter < nCount; nFilter++ )
1304     {
1305         OUString aMimeType( pFilter->GetExportFormatMediaType( nFilter ) );
1306         if( aMimeType.getLength() )
1307         {
1308             *pStr++ = aMimeType;
1309             nFound++;
1310         }
1311     }
1312 
1313     if( nFound < nCount )
1314         aSeq.realloc( nFound );
1315 
1316     return aSeq;
1317 }
1318 
SvxGetGraphicForShape(SdrObject & rShape,bool bVector)1319 Graphic SvxGetGraphicForShape( SdrObject& rShape, bool bVector )
1320 {
1321     Graphic aGraphic;
1322     try
1323     {
1324         rtl::Reference< GraphicExporter > xExporter( new GraphicExporter() );
1325         Reference< XComponent > xComp( rShape.getUnoShape(), UNO_QUERY_THROW );
1326         xExporter->setSourceDocument( xComp );
1327         ExportSettings aSettings( rShape.GetModel() );
1328         xExporter->GetGraphic( aSettings, aGraphic, bVector );
1329     }
1330     catch( Exception& )
1331     {
1332         DBG_ERROR("SvxGetGraphicForShape(), exception caught!");
1333     }
1334     return aGraphic;
1335 }
1336