Update ooo320-m1
[ooovba.git] / svx / source / unodraw / UnoGraphicExporter.cxx
blob691d23ab43c8c85d7de7792768e1185b7873ef61
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: UnoGraphicExporter.cxx,v $
10 * $Revision: 1.44 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 #include <vector>
35 #include <vos/mutex.hxx>
36 #include <com/sun/star/io/XOutputStream.hpp>
37 #include <com/sun/star/container/XChild.hpp>
38 #include <com/sun/star/frame/XModel.hpp>
39 #include <com/sun/star/document/XFilter.hpp>
40 #include <com/sun/star/document/XExporter.hpp>
41 #include <com/sun/star/document/XMimeTypeInfo.hpp>
42 #include <com/sun/star/lang/XServiceInfo.hpp>
43 #include <com/sun/star/lang/XComponent.hpp>
44 #include <com/sun/star/drawing/XShape.hpp>
45 #include <com/sun/star/drawing/XDrawPage.hpp>
46 #include <com/sun/star/graphic/XGraphic.hpp>
47 #include <com/sun/star/graphic/XGraphicRenderer.hpp>
48 #include <com/sun/star/task/XStatusIndicator.hpp>
49 #include <com/sun/star/task/XInteractionHandler.hpp>
50 #include <com/sun/star/task/XInteractionContinuation.hpp>
52 #include <framework/interaction.hxx>
53 #include <com/sun/star/drawing/GraphicFilterRequest.hpp>
54 #include <com/sun/star/util/URL.hpp>
55 #include <cppuhelper/implbase4.hxx>
56 #include <osl/diagnose.h>
57 #include <osl/mutex.hxx>
58 #include <vcl/metaact.hxx>
59 #include <vcl/svapp.hxx>
60 #include <vcl/virdev.hxx>
61 #include <svtools/FilterConfigItem.hxx>
62 #include <svtools/outstrm.hxx>
63 #include <svx/sdr/contact/objectcontactofobjlistpainter.hxx>
64 #include <svx/sdr/contact/viewobjectcontact.hxx>
65 #include <svx/sdr/contact/viewcontact.hxx>
66 #include <svx/sdr/contact/displayinfo.hxx>
67 #include <svx/sdr/contact/viewcontactofsdrobj.hxx>
68 #include <svx/numitem.hxx>
69 #include <svx/svdpagv.hxx>
70 #include <svx/svdograf.hxx>
71 #include "xoutbmp.hxx"
72 #include "impgrf.hxx"
73 #include "unoapi.hxx"
74 #include <svx/svdpage.hxx>
75 #include <svx/svdmodel.hxx>
76 #include <svx/fmview.hxx>
77 #include <svx/fmmodel.hxx>
78 #include <svx/unopage.hxx>
79 #include <svx/pageitem.hxx>
80 #include <svx/eeitem.hxx>
81 #include <svx/svdoutl.hxx>
82 #include <svx/flditem.hxx>
84 #include "boost/scoped_ptr.hpp"
86 #define MAX_EXT_PIX 2048
88 using namespace ::comphelper;
89 using namespace ::osl;
90 using namespace ::vos;
91 using ::rtl::OUString;
92 using namespace ::cppu;
93 using namespace ::com::sun::star;
94 using namespace ::com::sun::star::uno;
95 using namespace ::com::sun::star::util;
96 using namespace ::com::sun::star::container;
97 using namespace ::com::sun::star::drawing;
98 using namespace ::com::sun::star::lang;
99 using namespace ::com::sun::star::document;
100 using namespace ::com::sun::star::frame;
101 using namespace ::com::sun::star::beans;
102 using namespace ::com::sun::star::task;
103 #include <svx/sdr/contact/viewobjectcontactredirector.hxx>
104 #include <svx/sdr/contact/viewobjectcontact.hxx>
105 #include <svx/sdr/contact/viewcontact.hxx>
107 // #i102251#
108 #include <editstat.hxx>
110 //////////////////////////////////////////////////////////////////////////////
112 namespace svx
114 struct ExportSettings
116 OUString maFilterName;
117 OUString maMediaType;
118 URL maURL;
119 com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > mxOutputStream;
120 com::sun::star::uno::Reference< com::sun::star::graphic::XGraphicRenderer > mxGraphicRenderer;
121 com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > mxStatusIndicator;
122 com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler > mxInteractionHandler;
124 sal_Int32 mnWidth;
125 sal_Int32 mnHeight;
126 sal_Bool mbExportOnlyBackground;
127 sal_Bool mbVerboseComments;
128 sal_Bool mbScrollText;
129 sal_Bool mbUseHighContrast;
130 sal_Bool mbTranslucent;
132 Sequence< PropertyValue > maFilterData;
134 Fraction maScaleX;
135 Fraction maScaleY;
137 ExportSettings( SdrModel* pDoc );
140 ExportSettings::ExportSettings( SdrModel* pDoc )
141 : mnWidth( 0 )
142 , mnHeight( 0 )
143 , mbExportOnlyBackground( false )
144 , mbVerboseComments( false )
145 , mbScrollText( false )
146 , mbUseHighContrast( false )
147 , mbTranslucent( sal_False )
148 , maScaleX( 1, 1 )
149 , maScaleY( 1, 1 )
151 if( pDoc )
153 maScaleX = pDoc->GetScaleFraction();
154 maScaleY = pDoc->GetScaleFraction();
158 /** implements a component to export shapes or pages to external graphic formats.
160 @implements com.sun.star.drawing.GraphicExportFilter
162 class GraphicExporter : public WeakImplHelper4< XFilter, XExporter, XServiceInfo, XMimeTypeInfo >
164 public:
165 GraphicExporter();
166 virtual ~GraphicExporter();
168 // XFilter
169 virtual sal_Bool SAL_CALL filter( const Sequence< PropertyValue >& aDescriptor ) throw(RuntimeException);
170 virtual void SAL_CALL cancel( ) throw(RuntimeException);
172 // XExporter
173 virtual void SAL_CALL setSourceDocument( const Reference< XComponent >& xDoc ) throw(IllegalArgumentException, RuntimeException);
175 // XServiceInfo
176 virtual OUString SAL_CALL getImplementationName( ) throw(RuntimeException);
177 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(RuntimeException);
178 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) throw(RuntimeException);
180 // XMimeTypeInfo
181 virtual sal_Bool SAL_CALL supportsMimeType( const ::rtl::OUString& MimeTypeName ) throw (RuntimeException);
182 virtual Sequence< OUString > SAL_CALL getSupportedMimeTypeNames( ) throw (RuntimeException);
184 VirtualDevice* CreatePageVDev( SdrPage* pPage, ULONG nWidthPixel, ULONG nHeightPixel ) const;
186 DECL_LINK( CalcFieldValueHdl, EditFieldInfo* );
188 void ParseSettings( const Sequence< PropertyValue >& aDescriptor, ExportSettings& rSettings );
189 bool GetGraphic( ExportSettings& rSettings, Graphic& aGraphic, sal_Bool bVectorType );
191 private:
192 Reference< XShape > mxShape;
193 Reference< XDrawPage > mxPage;
194 Reference< XShapes > mxShapes;
196 SvxDrawPage* mpUnoPage;
198 Link maOldCalcFieldValueHdl;
199 sal_Int32 mnPageNumber;
200 SdrPage* mpCurrentPage;
201 SdrModel* mpDoc;
204 SVX_DLLPUBLIC Reference< XInterface > SAL_CALL GraphicExporter_createInstance(const Reference< XMultiServiceFactory > & )
205 throw( Exception )
207 return (XWeak*)new GraphicExporter();
210 SVX_DLLPUBLIC Sequence< OUString > SAL_CALL GraphicExporter_getSupportedServiceNames()
211 throw()
213 Sequence< OUString > aSupportedServiceNames( 1 );
214 aSupportedServiceNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.GraphicExportFilter" ) );
215 return aSupportedServiceNames;
218 SVX_DLLPUBLIC OUString SAL_CALL GraphicExporter_getImplementationName()
219 throw()
221 return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Draw.GraphicExporter" ) );
224 /** creates a bitmap that is optionaly transparent from a metafile
226 BitmapEx GetBitmapFromMetaFile( const GDIMetaFile& rMtf, BOOL bTransparent, const Size* pSize )
228 Graphic aGraphic( rMtf );
229 BitmapEx aBmpEx;
231 // #i102089# support user's settings of AA and LineSnap when the MetaFile gets
232 // rasterconverted to a bitmap
233 const SvtOptionsDrawinglayer aDrawinglayerOpt;
234 const GraphicConversionParameters aParameters(
235 pSize ? *pSize : Size(0, 0),
236 true, // allow unlimited size
237 aDrawinglayerOpt.IsAntiAliasing(),
238 aDrawinglayerOpt.IsSnapHorVerLinesToDiscrete());
240 if( bTransparent )
242 Graphic aMaskGraphic(rMtf.GetMonochromeMtf(COL_BLACK));
243 Bitmap aMaskBmp(aMaskGraphic.GetBitmap(aParameters));
245 aMaskBmp.Convert(BMP_CONVERSION_1BIT_THRESHOLD);
246 aBmpEx = BitmapEx(aGraphic.GetBitmap(aParameters), aMaskBmp);
248 else
250 aBmpEx = BitmapEx(aGraphic.GetBitmap(aParameters));
253 aBmpEx.SetPrefMapMode( rMtf.GetPrefMapMode() );
254 aBmpEx.SetPrefSize( rMtf.GetPrefSize() );
256 return aBmpEx;
259 Size* CalcSize( sal_Int32 nWidth, sal_Int32 nHeight, const Size& aBoundSize, Size& aOutSize )
261 if( (nWidth == 0) && (nHeight == 0) )
262 return NULL;
264 if( (nWidth == 0) && (nHeight != 0) && (aBoundSize.Height() != 0) )
266 nWidth = ( nHeight * aBoundSize.Width() ) / aBoundSize.Height();
268 else if( (nWidth != 0) && (nHeight == 0) && (aBoundSize.Width() != 0) )
270 nHeight = ( nWidth * aBoundSize.Height() ) / aBoundSize.Width();
273 aOutSize.Width() = nWidth;
274 aOutSize.Height() = nHeight;
276 return &aOutSize;
280 class ImplExportCheckVisisbilityRedirector : public ::sdr::contact::ViewObjectContactRedirector
282 public:
283 ImplExportCheckVisisbilityRedirector( SdrPage* pCurrentPage );
284 virtual ~ImplExportCheckVisisbilityRedirector();
286 virtual drawinglayer::primitive2d::Primitive2DSequence createRedirectedPrimitive2DSequence(
287 const sdr::contact::ViewObjectContact& rOriginal,
288 const sdr::contact::DisplayInfo& rDisplayInfo);
290 private:
291 SdrPage* mpCurrentPage;
294 ImplExportCheckVisisbilityRedirector::ImplExportCheckVisisbilityRedirector( SdrPage* pCurrentPage )
295 : ViewObjectContactRedirector(), mpCurrentPage( pCurrentPage )
299 ImplExportCheckVisisbilityRedirector::~ImplExportCheckVisisbilityRedirector()
303 drawinglayer::primitive2d::Primitive2DSequence ImplExportCheckVisisbilityRedirector::createRedirectedPrimitive2DSequence(
304 const sdr::contact::ViewObjectContact& rOriginal,
305 const sdr::contact::DisplayInfo& rDisplayInfo)
307 SdrObject* pObject = rOriginal.GetViewContact().TryToGetSdrObject();
309 if(pObject)
311 SdrPage* pPage = mpCurrentPage;
312 if( pPage == 0 )
313 pPage = pObject->GetPage();
315 if( (pPage == 0) || pPage->checkVisibility(rOriginal, rDisplayInfo, false) )
317 return ::sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(rOriginal, rDisplayInfo);
320 return drawinglayer::primitive2d::Primitive2DSequence();
322 else
324 // not an object, maybe a page
325 return ::sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(rOriginal, rDisplayInfo);
329 using namespace ::svx;
331 GraphicExporter::GraphicExporter()
332 : mpUnoPage( NULL ), mnPageNumber(-1), mpCurrentPage(0), mpDoc( NULL )
336 GraphicExporter::~GraphicExporter()
340 IMPL_LINK(GraphicExporter, CalcFieldValueHdl, EditFieldInfo*, pInfo)
342 if( pInfo )
344 if( mpCurrentPage )
346 pInfo->SetSdrPage( mpCurrentPage );
348 else if( mnPageNumber != -1 )
350 const SvxFieldData* pField = pInfo->GetField().GetField();
351 if( pField && pField->ISA( SvxPageField ) )
353 String aPageNumValue;
354 BOOL bUpper = FALSE;
356 switch(mpDoc->GetPageNumType())
358 case SVX_CHARS_UPPER_LETTER:
359 aPageNumValue += (sal_Unicode)(char)((mnPageNumber - 1) % 26 + 'A');
360 break;
361 case SVX_CHARS_LOWER_LETTER:
362 aPageNumValue += (sal_Unicode)(char)((mnPageNumber - 1) % 26 + 'a');
363 break;
364 case SVX_ROMAN_UPPER:
365 bUpper = TRUE;
366 case SVX_ROMAN_LOWER:
367 aPageNumValue += SvxNumberFormat::CreateRomanString(mnPageNumber, bUpper);
368 break;
369 case SVX_NUMBER_NONE:
370 aPageNumValue.Erase();
371 aPageNumValue += sal_Unicode(' ');
372 break;
373 default:
374 aPageNumValue += String::CreateFromInt32( (sal_Int32)mnPageNumber );
377 pInfo->SetRepresentation( aPageNumValue );
379 return(0);
384 long nRet = maOldCalcFieldValueHdl.Call( pInfo );
386 if( pInfo && mpCurrentPage )
387 pInfo->SetSdrPage( 0 );
389 return nRet;
392 /** creates an virtual device for the given page
394 @return the returned VirtualDevice is owned by the caller
396 VirtualDevice* GraphicExporter::CreatePageVDev( SdrPage* pPage, ULONG nWidthPixel, ULONG nHeightPixel ) const
398 VirtualDevice* pVDev = new VirtualDevice();
399 MapMode aMM( MAP_100TH_MM );
401 Point aPoint( 0, 0 );
402 Size aPageSize(pPage->GetSize());
404 // use scaling?
405 if( nWidthPixel )
407 const Fraction aFrac( (long) nWidthPixel, pVDev->LogicToPixel( aPageSize, aMM ).Width() );
409 aMM.SetScaleX( aFrac );
411 if( nHeightPixel == 0 )
412 aMM.SetScaleY( aFrac );
415 if( nHeightPixel )
417 const Fraction aFrac( (long) nHeightPixel, pVDev->LogicToPixel( aPageSize, aMM ).Height() );
419 if( nWidthPixel == 0 )
420 aMM.SetScaleX( aFrac );
422 aMM.SetScaleY( aFrac );
425 pVDev->SetMapMode( aMM );
426 #ifdef DBG_UTIL
427 BOOL bAbort = !
428 #endif
429 pVDev->SetOutputSize(aPageSize);
430 DBG_ASSERT(!bAbort, "virt. Device nicht korrekt erzeugt");
432 SdrView* pView = new SdrView(mpDoc, pVDev);
433 pView->SetPageVisible( FALSE );
434 pView->SetBordVisible( FALSE );
435 pView->SetGridVisible( FALSE );
436 pView->SetHlplVisible( FALSE );
437 pView->SetGlueVisible( FALSE );
438 pView->ShowSdrPage(pPage);
439 Region aRegion (Rectangle( aPoint, aPageSize ) );
441 ImplExportCheckVisisbilityRedirector aRedirector( mpCurrentPage );
443 pView->CompleteRedraw(pVDev, aRegion, &aRedirector);
445 delete pView;
446 return pVDev;
449 void GraphicExporter::ParseSettings( const Sequence< PropertyValue >& aDescriptor, ExportSettings& rSettings )
451 sal_Int32 nArgs = aDescriptor.getLength();
452 const PropertyValue* pValues = aDescriptor.getConstArray();
453 while( nArgs-- )
455 if( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "FilterName" ) ) )
457 pValues->Value >>= rSettings.maFilterName;
459 else if( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) )
461 pValues->Value >>= rSettings.maMediaType;
463 else if( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "URL" ) ) )
465 if( !( pValues->Value >>= rSettings.maURL ) )
467 pValues->Value >>= rSettings.maURL.Complete;
470 else if( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "OutputStream" ) ) )
472 pValues->Value >>= rSettings.mxOutputStream;
474 else if( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "GraphicRenderer" ) ) )
476 pValues->Value >>= rSettings.mxGraphicRenderer;
478 else if ( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "StatusIndicator" ) ) )
480 pValues->Value >>= rSettings.mxStatusIndicator;
482 else if ( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "InteractionHandler" ) ) )
484 pValues->Value >>= rSettings.mxInteractionHandler;
486 else if( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Width" ) ) ) // for compatibility reasons, deprecated
488 pValues->Value >>= rSettings.mnWidth;
490 else if( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Height" ) ) ) // for compatibility reasons, deprecated
492 pValues->Value >>= rSettings.mnHeight;
494 else if( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ExportOnlyBackground" ) ) ) // for compatibility reasons, deprecated
496 pValues->Value >>= rSettings.mbExportOnlyBackground;
498 else if ( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "FilterData" ) ) )
500 pValues->Value >>= rSettings.maFilterData;
502 sal_Int32 nFilterArgs = rSettings.maFilterData.getLength();
503 PropertyValue* pDataValues = rSettings.maFilterData.getArray();
504 while( nFilterArgs-- )
506 if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Translucent" ) ) )
508 if ( !( pDataValues->Value >>= rSettings.mbTranslucent ) ) // SJ: TODO: The GIF Transparency is stored as int32 in
509 { // configuration files, this has to be changed to boolean
510 sal_Int32 nTranslucent = 0;
511 if ( pDataValues->Value >>= nTranslucent )
512 rSettings.mbTranslucent = nTranslucent != 0;
515 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "PixelWidth" ) ) )
517 pDataValues->Value >>= rSettings.mnWidth;
519 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "PixelHeight" ) ) )
521 pDataValues->Value >>= rSettings.mnHeight;
523 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Width" ) ) ) // for compatibility reasons, deprecated
525 pDataValues->Value >>= rSettings.mnWidth;
526 pDataValues->Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "PixelWidth" ) );
528 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Height" ) ) ) // for compatibility reasons, deprecated
530 pDataValues->Value >>= rSettings.mnHeight;
531 pDataValues->Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "PixelHeight" ) );
533 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ExportOnlyBackground" ) ) )
535 pDataValues->Value >>= rSettings.mbExportOnlyBackground;
537 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "HighContrast" ) ) )
539 pDataValues->Value >>= rSettings.mbUseHighContrast;
541 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "PageNumber" ) ) )
543 pDataValues->Value >>= mnPageNumber;
545 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "VerboseComments" ) ) )
547 // #110496# Read flag for verbose metafile comments
548 pDataValues->Value >>= rSettings.mbVerboseComments;
550 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScrollText" ) ) )
552 // #110496# Read flag solitary scroll text metafile
553 pDataValues->Value >>= rSettings.mbScrollText;
555 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CurrentPage" ) ) )
557 Reference< XDrawPage > xPage;
558 pDataValues->Value >>= xPage;
559 if( xPage.is() )
561 SvxDrawPage* pUnoPage = SvxDrawPage::getImplementation( xPage );
562 if( pUnoPage && pUnoPage->GetSdrPage() )
563 mpCurrentPage = pUnoPage->GetSdrPage();
566 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleXNumerator" ) ) )
568 sal_Int32 nVal = 1;
569 if( pDataValues->Value >>= nVal )
570 rSettings.maScaleX = Fraction( nVal, rSettings.maScaleX.GetDenominator() );
572 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleXDenominator" ) ) )
574 sal_Int32 nVal = 1;
575 if( pDataValues->Value >>= nVal )
576 rSettings.maScaleX = Fraction( rSettings.maScaleX.GetNumerator(), nVal );
578 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleYNumerator" ) ) )
580 sal_Int32 nVal = 1;
581 if( pDataValues->Value >>= nVal )
582 rSettings.maScaleY = Fraction( nVal, rSettings.maScaleY.GetDenominator() );
584 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleYDenominator" ) ) )
586 sal_Int32 nVal = 1;
587 if( pDataValues->Value >>= nVal )
588 rSettings.maScaleY = Fraction( rSettings.maScaleY.GetNumerator(), nVal );
591 pDataValues++;
595 pValues++;
598 // putting the StatusIndicator that we got from the MediaDescriptor into our local FilterData copy
599 if ( rSettings.mxStatusIndicator.is() )
601 rtl::OUString sStatusIndicator( RTL_CONSTASCII_USTRINGPARAM( "StatusIndicator" ) );
602 int i = rSettings.maFilterData.getLength();
603 rSettings.maFilterData.realloc( i + 1 );
604 rSettings.maFilterData[ i ].Name = sStatusIndicator;
605 rSettings.maFilterData[ i ].Value <<= rSettings.mxStatusIndicator;
609 bool GraphicExporter::GetGraphic( ExportSettings& rSettings, Graphic& aGraphic, sal_Bool bVectorType )
611 if( !mpDoc || !mpUnoPage )
612 return false;
614 SdrPage* pPage = mpUnoPage->GetSdrPage();
615 if( !pPage )
616 return false;
618 VirtualDevice aVDev;
619 const MapMode aMap( mpDoc->GetScaleUnit(), Point(), rSettings.maScaleX, rSettings.maScaleY );
621 // create a view
622 SdrView* pView;
624 if( PTR_CAST( FmFormModel, mpDoc ) )
626 pView = new FmFormView( PTR_CAST( FmFormModel, mpDoc ), &aVDev );
628 else
630 pView = new SdrView( mpDoc, &aVDev );
633 pView->SetBordVisible( FALSE );
634 pView->SetPageVisible( FALSE );
635 pView->ShowSdrPage( pPage );
637 SdrOutliner& rOutl=mpDoc->GetDrawOutliner(NULL);
638 maOldCalcFieldValueHdl = rOutl.GetCalcFieldValueHdl();
639 rOutl.SetCalcFieldValueHdl( LINK(this, GraphicExporter, CalcFieldValueHdl) );
640 rOutl.SetBackgroundColor( pPage->GetPageBackgroundColor(pView->GetSdrPageView()) );
642 // #i102251#
643 const sal_uInt32 nOldCntrl(rOutl.GetControlWord());
644 sal_uInt32 nCntrl = nOldCntrl & ~EE_CNTRL_ONLINESPELLING;
645 rOutl.SetControlWord(nCntrl);
647 std::vector< SdrObject* > aShapes;
648 bool bRet = true;
650 // export complete page?
651 if ( !mxShape.is() )
653 if( rSettings.mbExportOnlyBackground )
655 SdrObject* pShape = 0;
656 if( pPage->IsMasterPage() )
658 if( pPage->GetObjCount() > 0 )
659 pShape = pPage->GetObj(0);
661 else
663 pShape = pPage->GetBackgroundObj();
666 if( pShape )
667 aShapes.push_back( pShape );
669 else
671 const Size aSize( pPage->GetSize() );
673 // generate a bitmap to convert it to a pixel format.
674 // For gif pictures there can also be a vector format used (bTranslucent)
675 if ( !bVectorType && !rSettings.mbTranslucent )
677 long nWidthPix = 0;
678 long nHeightPix = 0;
679 if ( rSettings.mnWidth > 0 && rSettings.mnHeight > 0 )
681 nWidthPix = rSettings.mnWidth;
682 nHeightPix = rSettings.mnHeight;
684 else
686 const Size aSizePix( Application::GetDefaultDevice()->LogicToPixel( aSize, aMap ) );
687 if (aSizePix.Width() > MAX_EXT_PIX || aSizePix.Height() > MAX_EXT_PIX)
689 if (aSizePix.Width() > MAX_EXT_PIX)
690 nWidthPix = MAX_EXT_PIX;
691 else
692 nWidthPix = aSizePix.Width();
693 if (aSizePix.Height() > MAX_EXT_PIX)
694 nHeightPix = MAX_EXT_PIX;
695 else
696 nHeightPix = aSizePix.Height();
698 double fWidthDif = aSizePix.Width() / nWidthPix;
699 double fHeightDif = aSizePix.Height() / nHeightPix;
701 if (fWidthDif > fHeightDif)
702 nHeightPix = static_cast<long>(aSizePix.Height() / fWidthDif);
703 else
704 nWidthPix = static_cast<long>(aSizePix.Width() / fHeightDif);
706 else
708 nWidthPix = aSizePix.Width();
709 nHeightPix = aSizePix.Height();
713 boost::scoped_ptr< SdrView > pLocalView;
714 if( PTR_CAST( FmFormModel, mpDoc ) )
716 pLocalView.reset( new FmFormView( PTR_CAST( FmFormModel, mpDoc ), &aVDev ) );
718 else
720 pLocalView.reset( new SdrView( mpDoc, &aVDev ) );
724 VirtualDevice* pVDev = CreatePageVDev( pPage, nWidthPix, nHeightPix );
726 if( pVDev )
728 aGraphic = pVDev->GetBitmap( Point(), pVDev->GetOutputSize() );
729 aGraphic.SetPrefMapMode( aMap );
730 aGraphic.SetPrefSize( aSize );
731 delete pVDev;
734 // create a metafile to export a vector format
735 else
737 GDIMetaFile aMtf;
739 aVDev.SetMapMode( aMap );
740 if( rSettings.mbUseHighContrast )
741 aVDev.SetDrawMode( aVDev.GetDrawMode() | DRAWMODE_SETTINGSLINE | DRAWMODE_SETTINGSFILL | DRAWMODE_SETTINGSTEXT | DRAWMODE_SETTINGSGRADIENT );
742 aVDev.EnableOutput( FALSE );
743 aMtf.Record( &aVDev );
745 Size aNewSize;
746 if ( pView && pPage )
748 pView->SetBordVisible( FALSE );
749 pView->SetPageVisible( FALSE );
750 pView->ShowSdrPage( pPage );
752 const Point aNewOrg( pPage->GetLftBorder(), pPage->GetUppBorder() );
753 aNewSize = Size( aSize.Width() - pPage->GetLftBorder() - pPage->GetRgtBorder(),
754 aSize.Height() - pPage->GetUppBorder() - pPage->GetLwrBorder() );
755 const Rectangle aClipRect( aNewOrg, aNewSize );
756 MapMode aVMap( aMap );
758 aVDev.Push();
759 aVMap.SetOrigin( Point( -aNewOrg.X(), -aNewOrg.Y() ) );
760 aVDev.SetRelativeMapMode( aVMap );
761 aVDev.IntersectClipRegion( aClipRect );
763 // Use new StandardCheckVisisbilityRedirector
764 ImplExportCheckVisisbilityRedirector aRedirector( mpCurrentPage );
766 pView->CompleteRedraw(&aVDev, Region(Rectangle(Point(), aNewSize)), &aRedirector);
768 aVDev.Pop();
770 aMtf.Stop();
771 aMtf.WindStart();
772 aMtf.SetPrefMapMode( aMap );
773 aMtf.SetPrefSize( aNewSize );
775 // AW: Here the current version was filtering out the META_CLIPREGION_ACTIONs
776 // from the metafile. I asked some other developers why this was done, but no
777 // one knew a direct reason. Since it's in for long time, it may be an old
778 // piece of code. MetaFiles save and load ClipRegions with polygons with preserving
779 // the polygons, so a resolution-indepent roundtrip is supported. Removed this
780 // code since it destroys some MetaFiles where ClipRegions are used. Anyways,
781 // just filtering them out is a hack, at least the encapsulated content would need
782 // to be clipped geometrically.
783 aGraphic = Graphic(aMtf);
786 if( rSettings.mbTranslucent )
788 Size aOutSize;
789 aGraphic = GetBitmapFromMetaFile( aGraphic.GetGDIMetaFile(), TRUE, CalcSize( rSettings.mnWidth, rSettings.mnHeight, aNewSize, aOutSize ) );
795 // export only single shape or shape collection
796 else
798 // build list of SdrObject
799 if( mxShapes.is() )
801 Reference< XShape > xShape;
802 const sal_Int32 nCount = mxShapes->getCount();
804 for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ )
806 mxShapes->getByIndex( nIndex ) >>= xShape;
807 SdrObject* pObj = GetSdrObjectFromXShape( xShape );
808 if( pObj )
809 aShapes.push_back( pObj );
812 else
814 // only one shape
815 SdrObject* pObj = GetSdrObjectFromXShape( mxShape );
816 if( pObj )
817 aShapes.push_back( pObj );
820 if( 0 == aShapes.size() )
821 bRet = false;
824 if( bRet && aShapes.size() )
826 // special treatment for only one SdrGrafObj that has text
827 sal_Bool bSingleGraphic = sal_False;
829 if( 1 == aShapes.size() )
831 if( !bVectorType )
833 SdrObject* pObj = aShapes.front();
834 if( pObj && pObj->ISA( SdrGrafObj ) && !( (SdrGrafObj*) pObj )->HasText() )
836 aGraphic = ( (SdrGrafObj*) pObj )->GetTransformedGraphic();
837 if ( aGraphic.GetType() == GRAPHIC_BITMAP )
839 Size aSizePixel( aGraphic.GetSizePixel() );
840 if ( rSettings.mnWidth && rSettings.mnHeight && ( rSettings.mnWidth != aSizePixel.Width() ) || ( rSettings.mnHeight != aSizePixel.Height() ) )
842 BitmapEx aBmpEx( aGraphic.GetBitmapEx() );
843 aBmpEx.Scale( Size( rSettings.mnWidth, rSettings.mnHeight ) );
844 aGraphic = aBmpEx;
847 bSingleGraphic = sal_True;
850 else if( rSettings.mbScrollText )
852 SdrObject* pObj = aShapes.front();
853 if( pObj && pObj->ISA( SdrTextObj )
854 && ( (SdrTextObj*) pObj )->HasText() )
856 Rectangle aScrollRectangle;
857 Rectangle aPaintRectangle;
859 const boost::scoped_ptr< GDIMetaFile > pMtf(
860 ( (SdrTextObj*) pObj )->GetTextScrollMetaFileAndRectangle(
861 aScrollRectangle, aPaintRectangle ) );
863 // take the larger one of the two rectangles (that
864 // should be the bound rect of the retrieved
865 // metafile)
866 Rectangle aTextRect;
868 if( aScrollRectangle.IsInside( aPaintRectangle ) )
869 aTextRect = aScrollRectangle;
870 else
871 aTextRect = aPaintRectangle;
873 // setup pref size and mapmode
874 pMtf->SetPrefSize( aTextRect.GetSize() );
876 // set actual origin (mtf is at actual shape
877 // output position)
878 MapMode aLocalMapMode( aMap );
879 aLocalMapMode.SetOrigin(
880 Point( -aPaintRectangle.Left(),
881 -aPaintRectangle.Top() ) );
882 pMtf->SetPrefMapMode( aLocalMapMode );
884 pMtf->AddAction( new MetaCommentAction(
885 "XTEXT_SCROLLRECT", 0,
886 reinterpret_cast<BYTE const*>(&aScrollRectangle),
887 sizeof( Rectangle ) ) );
888 pMtf->AddAction( new MetaCommentAction(
889 "XTEXT_PAINTRECT", 0,
890 reinterpret_cast<BYTE const*>(&aPaintRectangle),
891 sizeof( Rectangle ) ) );
893 aGraphic = Graphic( *pMtf );
895 bSingleGraphic = sal_True;
900 if( !bSingleGraphic )
902 // create a metafile for all shapes
903 VirtualDevice aOut;
905 // calculate bound rect for all shapes
906 Rectangle aBound;
908 if(rSettings.mbExportOnlyBackground)
910 // shape is MPBGO and if it's not yet set, it's size will
911 // be empty when using GetCurrentBoundRect(). Since anyways
912 // the page size is used by MPBGO and MPBGO is EOLd, get
913 // the wanted size from the page model directly
914 aBound = Rectangle(Point(0,0), pPage->GetSize());
916 else
918 std::vector< SdrObject* >::iterator aIter = aShapes.begin();
919 const std::vector< SdrObject* >::iterator aEnd = aShapes.end();
921 while( aIter != aEnd )
923 SdrObject* pObj = (*aIter++);
924 Rectangle aR1(pObj->GetCurrentBoundRect());
925 if (aBound.IsEmpty())
926 aBound=aR1;
927 else
928 aBound.Union(aR1);
932 aOut.EnableOutput( FALSE );
933 aOut.SetMapMode( aMap );
934 if( rSettings.mbUseHighContrast )
935 aOut.SetDrawMode( aVDev.GetDrawMode() | DRAWMODE_SETTINGSLINE | DRAWMODE_SETTINGSFILL | DRAWMODE_SETTINGSTEXT | DRAWMODE_SETTINGSGRADIENT );
937 GDIMetaFile aMtf;
938 aMtf.Clear();
939 aMtf.Record( &aOut );
941 MapMode aOutMap( aMap );
942 aOutMap.SetOrigin( Point( -aBound.TopLeft().X(), -aBound.TopLeft().Y() ) );
943 aOut.SetRelativeMapMode( aOutMap );
945 sdr::contact::DisplayInfo aDisplayInfo;
947 if(mpCurrentPage)
949 if(mpCurrentPage->TRG_HasMasterPage() && pPage->IsMasterPage())
951 // MasterPage is processed as another page's SubContent
952 aDisplayInfo.SetProcessLayers(mpCurrentPage->TRG_GetMasterPageVisibleLayers());
953 aDisplayInfo.SetSubContentActive(true);
957 if(aShapes.size())
959 // more effective way to paint a vector of SdrObjects. Hand over the processed page
960 // to have it in the
961 sdr::contact::ObjectContactOfObjListPainter aMultiObjectPainter(aOut, aShapes, mpCurrentPage);
962 ImplExportCheckVisisbilityRedirector aCheckVisibilityRedirector(mpCurrentPage);
963 aMultiObjectPainter.SetViewObjectContactRedirector(&aCheckVisibilityRedirector);
965 aMultiObjectPainter.ProcessDisplay(aDisplayInfo);
968 aMtf.Stop();
969 aMtf.WindStart();
971 const Size aExtSize( aOut.PixelToLogic( Size( 0, 0 ) ) );
972 Size aBoundSize( aBound.GetWidth() + ( aExtSize.Width() ),
973 aBound.GetHeight() + ( aExtSize.Height() ) );
975 aMtf.SetPrefMapMode( aMap );
976 aMtf.SetPrefSize( aBoundSize );
978 if( !bVectorType )
980 Size aOutSize;
981 aGraphic = GetBitmapFromMetaFile( aMtf, rSettings.mbTranslucent, CalcSize( rSettings.mnWidth, rSettings.mnHeight, aBoundSize, aOutSize ) );
983 else
985 aGraphic = aMtf;
990 if ( pView )
992 pView->HideSdrPage();
993 delete pView;
996 rOutl.SetCalcFieldValueHdl( maOldCalcFieldValueHdl );
998 // #i102251#
999 rOutl.SetControlWord(nOldCntrl);
1001 return bRet;
1005 // XFilter
1006 sal_Bool SAL_CALL GraphicExporter::filter( const Sequence< PropertyValue >& aDescriptor )
1007 throw(RuntimeException)
1009 OGuard aGuard( Application::GetSolarMutex() );
1011 if( NULL == mpUnoPage )
1012 return sal_False;
1014 GraphicFilter* pFilter = GetGrfFilter();
1016 if( NULL == pFilter || NULL == mpUnoPage->GetSdrPage() || NULL == mpDoc )
1017 return sal_False;
1019 // get the arguments from the descriptor
1020 ExportSettings aSettings( mpDoc );
1021 ParseSettings( aDescriptor, aSettings );
1023 const sal_uInt16 nFilter = aSettings.maMediaType.getLength()
1024 ? pFilter->GetExportFormatNumberForMediaType( aSettings.maMediaType )
1025 : pFilter->GetExportFormatNumberForShortName( aSettings.maFilterName );
1026 sal_Bool bVectorType = !pFilter->IsExportPixelFormat( nFilter );
1028 // create the output stuff
1029 Graphic aGraphic;
1031 USHORT nStatus = GetGraphic( aSettings, aGraphic, bVectorType ) ? GRFILTER_OK : GRFILTER_FILTERERROR;
1033 if( nStatus == GRFILTER_OK )
1035 // export graphic only if it has a size
1036 const Size aGraphSize( aGraphic.GetPrefSize() );
1037 if ( ( aGraphSize.Width() == 0 ) || ( aGraphSize.Height() == 0 ) )
1039 nStatus = GRFILTER_FILTERERROR;
1041 else
1043 // now we have a graphic, so export it
1044 if( aSettings.mxGraphicRenderer.is() )
1046 // render graphic directly into given renderer
1047 aSettings.mxGraphicRenderer->render( aGraphic.GetXGraphic() );
1049 else if( aSettings.mxOutputStream.is() )
1051 // TODO: Either utilize optional XSeekable functionality for the
1052 // SvOutputStream, or adapt the graphic filter to not seek anymore.
1053 SvMemoryStream aStream( 1024, 1024 );
1055 nStatus = pFilter->ExportGraphic( aGraphic, String(), aStream, nFilter, &aSettings.maFilterData );
1057 // copy temp stream to XOutputStream
1058 SvOutputStream aOutputStream( aSettings.mxOutputStream );
1059 aStream.Seek(0);
1060 aOutputStream << aStream;
1062 else
1064 INetURLObject aURLObject( aSettings.maURL.Complete );
1065 DBG_ASSERT( aURLObject.GetProtocol() != INET_PROT_NOT_VALID, "invalid URL" );
1067 nStatus = XOutBitmap::ExportGraphic( aGraphic, aURLObject, *pFilter, nFilter, &aSettings.maFilterData );
1072 if ( aSettings.mxInteractionHandler.is() && ( nStatus != GRFILTER_OK ) )
1074 Any aInteraction;
1075 Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionContinuation > > lContinuations(1);
1076 ::framework::ContinuationApprove* pApprove = new ::framework::ContinuationApprove();
1077 lContinuations[0] = Reference< XInteractionContinuation >(static_cast< XInteractionContinuation* >(pApprove), UNO_QUERY);
1079 GraphicFilterRequest aErrorCode;
1080 aErrorCode.ErrCode = nStatus;
1081 aInteraction <<= aErrorCode;
1082 framework::InteractionRequest* pRequest = new framework::InteractionRequest( aInteraction, lContinuations );
1083 Reference< XInteractionRequest >xRequest( static_cast< XInteractionRequest* >(pRequest), UNO_QUERY );
1084 aSettings.mxInteractionHandler->handle( xRequest );
1086 return nStatus == GRFILTER_OK;
1089 void SAL_CALL GraphicExporter::cancel()
1090 throw(RuntimeException)
1094 // XExporter
1096 /** the source 'document' could be a XDrawPage, a XShape or a generic XShapes */
1097 void SAL_CALL GraphicExporter::setSourceDocument( const Reference< lang::XComponent >& xComponent )
1098 throw(IllegalArgumentException, RuntimeException)
1100 OGuard aGuard( Application::GetSolarMutex() );
1102 mxShapes = NULL;
1103 mpUnoPage = NULL;
1107 // any break inside this one loop while will throw a IllegalArgumentException
1110 mxPage = Reference< XDrawPage >::query( xComponent );
1111 mxShapes = Reference< XShapes >::query( xComponent );
1112 mxShape = Reference< XShape >::query( xComponent );
1114 // Step 1: try a generic XShapes
1115 if( !mxPage.is() && !mxShape.is() && mxShapes.is() )
1117 // we do not support empty shape collections
1118 if( 0 == mxShapes->getCount() )
1119 break;
1121 // get first shape to detect corresponding page and model
1122 mxShapes->getByIndex(0) >>= mxShape;
1124 else
1126 mxShapes = NULL;
1129 // Step 2: try a shape
1130 if( mxShape.is() )
1132 if( NULL == GetSdrObjectFromXShape( mxShape ) )
1133 break;
1135 // get page for this shape
1136 Reference< XChild > xChild( mxShape, UNO_QUERY );
1137 if( !xChild.is() )
1138 break;
1140 Reference< XInterface > xInt;
1143 xInt = xChild->getParent();
1144 mxPage = Reference< XDrawPage >::query( xInt );
1145 if( !mxPage.is() )
1146 xChild = Reference< XChild >::query( xInt );
1148 while( !mxPage.is() && xChild.is() );
1150 if( !mxPage.is() )
1151 break;
1154 // Step 3: check the page
1155 if( !mxPage.is() )
1156 break;
1158 mpUnoPage = SvxDrawPage::getImplementation( mxPage );
1160 if( NULL == mpUnoPage || NULL == mpUnoPage->GetSdrPage() )
1161 break;
1163 mpDoc = mpUnoPage->GetSdrPage()->GetModel();
1165 // Step 4: If we got a generic XShapes test all contained shapes
1166 // if they belong to the same XDrawPage
1168 if( mxShapes.is() )
1170 SdrPage* pPage = mpUnoPage->GetSdrPage();
1171 SdrObject* pObj;
1172 Reference< XShape > xShape;
1174 sal_Bool bOk = sal_True;
1176 const sal_Int32 nCount = mxShapes->getCount();
1178 // test all but the first shape if they have the same page than
1179 // the first shape
1180 for( sal_Int32 nIndex = 1; bOk && ( nIndex < nCount ); nIndex++ )
1182 mxShapes->getByIndex( nIndex ) >>= xShape;
1183 pObj = GetSdrObjectFromXShape( xShape );
1184 bOk = pObj && pObj->GetPage() == pPage;
1187 if( !bOk )
1188 break;
1191 // no errors so far
1192 return;
1194 while( 0 );
1196 catch( Exception& )
1200 throw IllegalArgumentException();
1203 // XServiceInfo
1204 OUString SAL_CALL GraphicExporter::getImplementationName( )
1205 throw(RuntimeException)
1207 return GraphicExporter_getImplementationName();
1210 sal_Bool SAL_CALL GraphicExporter::supportsService( const OUString& ServiceName )
1211 throw(RuntimeException)
1213 Sequence< OUString > aSeq( GraphicExporter_getSupportedServiceNames() );
1214 sal_Int32 nArgs = aSeq.getLength();
1215 const OUString* pService = aSeq.getConstArray();
1216 while( nArgs-- )
1217 if( *pService++ == ServiceName )
1218 return sal_True;
1220 return sal_False;
1223 Sequence< OUString > SAL_CALL GraphicExporter::getSupportedServiceNames( )
1224 throw(RuntimeException)
1226 return GraphicExporter_getSupportedServiceNames();
1229 // XMimeTypeInfo
1230 sal_Bool SAL_CALL GraphicExporter::supportsMimeType( const OUString& MimeTypeName ) throw (RuntimeException)
1232 const String aMimeTypeName( MimeTypeName );
1234 GraphicFilter* pFilter = GetGrfFilter();
1235 sal_uInt16 nCount = pFilter->GetExportFormatCount();
1236 sal_uInt16 nFilter;
1237 for( nFilter = 0; nFilter < nCount; nFilter++ )
1239 if( aMimeTypeName.Equals( pFilter->GetExportFormatMediaType( nFilter ) ) )
1241 return sal_True;
1245 return sal_False;
1248 Sequence< OUString > SAL_CALL GraphicExporter::getSupportedMimeTypeNames( ) throw (RuntimeException)
1250 GraphicFilter* pFilter = GetGrfFilter();
1251 sal_uInt16 nCount = pFilter->GetExportFormatCount();
1252 sal_uInt16 nFilter;
1253 sal_uInt16 nFound = 0;
1255 Sequence< OUString > aSeq( nCount );
1256 OUString* pStr = aSeq.getArray();
1258 for( nFilter = 0; nFilter < nCount; nFilter++ )
1260 OUString aMimeType( pFilter->GetExportFormatMediaType( nFilter ) );
1261 if( aMimeType.getLength() )
1263 *pStr++ = aMimeType;
1264 nFound++;
1268 if( nFound < nCount )
1269 aSeq.realloc( nFound );
1271 return aSeq;
1274 Graphic SvxGetGraphicForShape( SdrObject& rShape, bool bVector )
1276 Graphic aGraphic;
1279 rtl::Reference< GraphicExporter > xExporter( new GraphicExporter() );
1280 Reference< XComponent > xComp( rShape.getUnoShape(), UNO_QUERY_THROW );
1281 xExporter->setSourceDocument( xComp );
1282 ExportSettings aSettings( rShape.GetModel() );
1283 xExporter->GetGraphic( aSettings, aGraphic, bVector );
1285 catch( Exception& )
1287 DBG_ERROR("SvxGetGraphicForShape(), exception caught!");
1289 return aGraphic;