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