1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: UnoGraphicExporter.cxx,v $
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"
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"
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>
108 #include <editstat.hxx>
110 //////////////////////////////////////////////////////////////////////////////
114 struct ExportSettings
116 OUString maFilterName
;
117 OUString maMediaType
;
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
;
126 sal_Bool mbExportOnlyBackground
;
127 sal_Bool mbVerboseComments
;
128 sal_Bool mbScrollText
;
129 sal_Bool mbUseHighContrast
;
130 sal_Bool mbTranslucent
;
132 Sequence
< PropertyValue
> maFilterData
;
137 ExportSettings( SdrModel
* pDoc
);
140 ExportSettings::ExportSettings( SdrModel
* pDoc
)
143 , mbExportOnlyBackground( false )
144 , mbVerboseComments( false )
145 , mbScrollText( false )
146 , mbUseHighContrast( false )
147 , mbTranslucent( sal_False
)
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
>
166 virtual ~GraphicExporter();
169 virtual sal_Bool SAL_CALL
filter( const Sequence
< PropertyValue
>& aDescriptor
) throw(RuntimeException
);
170 virtual void SAL_CALL
cancel( ) throw(RuntimeException
);
173 virtual void SAL_CALL
setSourceDocument( const Reference
< XComponent
>& xDoc
) throw(IllegalArgumentException
, RuntimeException
);
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
);
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
);
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
;
204 SVX_DLLPUBLIC Reference
< XInterface
> SAL_CALL
GraphicExporter_createInstance(const Reference
< XMultiServiceFactory
> & )
207 return (XWeak
*)new GraphicExporter();
210 SVX_DLLPUBLIC Sequence
< OUString
> SAL_CALL
GraphicExporter_getSupportedServiceNames()
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()
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
);
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());
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
);
250 aBmpEx
= BitmapEx(aGraphic
.GetBitmap(aParameters
));
253 aBmpEx
.SetPrefMapMode( rMtf
.GetPrefMapMode() );
254 aBmpEx
.SetPrefSize( rMtf
.GetPrefSize() );
259 Size
* CalcSize( sal_Int32 nWidth
, sal_Int32 nHeight
, const Size
& aBoundSize
, Size
& aOutSize
)
261 if( (nWidth
== 0) && (nHeight
== 0) )
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
;
280 class ImplExportCheckVisisbilityRedirector
: public ::sdr::contact::ViewObjectContactRedirector
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
);
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();
311 SdrPage
* pPage
= mpCurrentPage
;
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();
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
)
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
;
356 switch(mpDoc
->GetPageNumType())
358 case SVX_CHARS_UPPER_LETTER
:
359 aPageNumValue
+= (sal_Unicode
)(char)((mnPageNumber
- 1) % 26 + 'A');
361 case SVX_CHARS_LOWER_LETTER
:
362 aPageNumValue
+= (sal_Unicode
)(char)((mnPageNumber
- 1) % 26 + 'a');
364 case SVX_ROMAN_UPPER
:
366 case SVX_ROMAN_LOWER
:
367 aPageNumValue
+= SvxNumberFormat::CreateRomanString(mnPageNumber
, bUpper
);
369 case SVX_NUMBER_NONE
:
370 aPageNumValue
.Erase();
371 aPageNumValue
+= sal_Unicode(' ');
374 aPageNumValue
+= String::CreateFromInt32( (sal_Int32
)mnPageNumber
);
377 pInfo
->SetRepresentation( aPageNumValue
);
384 long nRet
= maOldCalcFieldValueHdl
.Call( pInfo
);
386 if( pInfo
&& mpCurrentPage
)
387 pInfo
->SetSdrPage( 0 );
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());
407 const Fraction
aFrac( (long) nWidthPixel
, pVDev
->LogicToPixel( aPageSize
, aMM
).Width() );
409 aMM
.SetScaleX( aFrac
);
411 if( nHeightPixel
== 0 )
412 aMM
.SetScaleY( aFrac
);
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
);
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
);
449 void GraphicExporter::ParseSettings( const Sequence
< PropertyValue
>& aDescriptor
, ExportSettings
& rSettings
)
451 sal_Int32 nArgs
= aDescriptor
.getLength();
452 const PropertyValue
* pValues
= aDescriptor
.getConstArray();
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
;
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" ) ) )
569 if( pDataValues
->Value
>>= nVal
)
570 rSettings
.maScaleX
= Fraction( nVal
, rSettings
.maScaleX
.GetDenominator() );
572 else if( pDataValues
->Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleXDenominator" ) ) )
575 if( pDataValues
->Value
>>= nVal
)
576 rSettings
.maScaleX
= Fraction( rSettings
.maScaleX
.GetNumerator(), nVal
);
578 else if( pDataValues
->Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleYNumerator" ) ) )
581 if( pDataValues
->Value
>>= nVal
)
582 rSettings
.maScaleY
= Fraction( nVal
, rSettings
.maScaleY
.GetDenominator() );
584 else if( pDataValues
->Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleYDenominator" ) ) )
587 if( pDataValues
->Value
>>= nVal
)
588 rSettings
.maScaleY
= Fraction( rSettings
.maScaleY
.GetNumerator(), nVal
);
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
)
614 SdrPage
* pPage
= mpUnoPage
->GetSdrPage();
619 const MapMode
aMap( mpDoc
->GetScaleUnit(), Point(), rSettings
.maScaleX
, rSettings
.maScaleY
);
624 if( PTR_CAST( FmFormModel
, mpDoc
) )
626 pView
= new FmFormView( PTR_CAST( FmFormModel
, mpDoc
), &aVDev
);
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()) );
643 const sal_uInt32
nOldCntrl(rOutl
.GetControlWord());
644 sal_uInt32 nCntrl
= nOldCntrl
& ~EE_CNTRL_ONLINESPELLING
;
645 rOutl
.SetControlWord(nCntrl
);
647 std::vector
< SdrObject
* > aShapes
;
650 // export complete page?
653 if( rSettings
.mbExportOnlyBackground
)
655 SdrObject
* pShape
= 0;
656 if( pPage
->IsMasterPage() )
658 if( pPage
->GetObjCount() > 0 )
659 pShape
= pPage
->GetObj(0);
663 pShape
= pPage
->GetBackgroundObj();
667 aShapes
.push_back( pShape
);
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
)
679 if ( rSettings
.mnWidth
> 0 && rSettings
.mnHeight
> 0 )
681 nWidthPix
= rSettings
.mnWidth
;
682 nHeightPix
= rSettings
.mnHeight
;
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
;
692 nWidthPix
= aSizePix
.Width();
693 if (aSizePix
.Height() > MAX_EXT_PIX
)
694 nHeightPix
= MAX_EXT_PIX
;
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
);
704 nWidthPix
= static_cast<long>(aSizePix
.Width() / fHeightDif
);
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
) );
720 pLocalView
.reset( new SdrView( mpDoc
, &aVDev
) );
724 VirtualDevice
* pVDev
= CreatePageVDev( pPage
, nWidthPix
, nHeightPix
);
728 aGraphic
= pVDev
->GetBitmap( Point(), pVDev
->GetOutputSize() );
729 aGraphic
.SetPrefMapMode( aMap
);
730 aGraphic
.SetPrefSize( aSize
);
734 // create a metafile to export a vector format
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
);
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
);
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
);
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
)
789 aGraphic
= GetBitmapFromMetaFile( aGraphic
.GetGDIMetaFile(), TRUE
, CalcSize( rSettings
.mnWidth
, rSettings
.mnHeight
, aNewSize
, aOutSize
) );
795 // export only single shape or shape collection
798 // build list of SdrObject
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
);
809 aShapes
.push_back( pObj
);
815 SdrObject
* pObj
= GetSdrObjectFromXShape( mxShape
);
817 aShapes
.push_back( pObj
);
820 if( 0 == aShapes
.size() )
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() )
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
) );
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
868 if( aScrollRectangle
.IsInside( aPaintRectangle
) )
869 aTextRect
= aScrollRectangle
;
871 aTextRect
= aPaintRectangle
;
873 // setup pref size and mapmode
874 pMtf
->SetPrefSize( aTextRect
.GetSize() );
876 // set actual origin (mtf is at actual shape
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
905 // calculate bound rect for all shapes
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());
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())
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
);
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
;
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);
959 // more effective way to paint a vector of SdrObjects. Hand over the processed page
961 sdr::contact::ObjectContactOfObjListPainter
aMultiObjectPainter(aOut
, aShapes
, mpCurrentPage
);
962 ImplExportCheckVisisbilityRedirector
aCheckVisibilityRedirector(mpCurrentPage
);
963 aMultiObjectPainter
.SetViewObjectContactRedirector(&aCheckVisibilityRedirector
);
965 aMultiObjectPainter
.ProcessDisplay(aDisplayInfo
);
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
);
981 aGraphic
= GetBitmapFromMetaFile( aMtf
, rSettings
.mbTranslucent
, CalcSize( rSettings
.mnWidth
, rSettings
.mnHeight
, aBoundSize
, aOutSize
) );
992 pView
->HideSdrPage();
996 rOutl
.SetCalcFieldValueHdl( maOldCalcFieldValueHdl
);
999 rOutl
.SetControlWord(nOldCntrl
);
1006 sal_Bool SAL_CALL
GraphicExporter::filter( const Sequence
< PropertyValue
>& aDescriptor
)
1007 throw(RuntimeException
)
1009 OGuard
aGuard( Application::GetSolarMutex() );
1011 if( NULL
== mpUnoPage
)
1014 GraphicFilter
* pFilter
= GetGrfFilter();
1016 if( NULL
== pFilter
|| NULL
== mpUnoPage
->GetSdrPage() || NULL
== mpDoc
)
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
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
;
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
);
1060 aOutputStream
<< aStream
;
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
) )
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
)
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() );
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() )
1121 // get first shape to detect corresponding page and model
1122 mxShapes
->getByIndex(0) >>= mxShape
;
1129 // Step 2: try a shape
1132 if( NULL
== GetSdrObjectFromXShape( mxShape
) )
1135 // get page for this shape
1136 Reference
< XChild
> xChild( mxShape
, UNO_QUERY
);
1140 Reference
< XInterface
> xInt
;
1143 xInt
= xChild
->getParent();
1144 mxPage
= Reference
< XDrawPage
>::query( xInt
);
1146 xChild
= Reference
< XChild
>::query( xInt
);
1148 while( !mxPage
.is() && xChild
.is() );
1154 // Step 3: check the page
1158 mpUnoPage
= SvxDrawPage::getImplementation( mxPage
);
1160 if( NULL
== mpUnoPage
|| NULL
== mpUnoPage
->GetSdrPage() )
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
1170 SdrPage
* pPage
= mpUnoPage
->GetSdrPage();
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
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
;
1200 throw IllegalArgumentException();
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();
1217 if( *pService
++ == ServiceName
)
1223 Sequence
< OUString
> SAL_CALL
GraphicExporter::getSupportedServiceNames( )
1224 throw(RuntimeException
)
1226 return GraphicExporter_getSupportedServiceNames();
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();
1237 for( nFilter
= 0; nFilter
< nCount
; nFilter
++ )
1239 if( aMimeTypeName
.Equals( pFilter
->GetExportFormatMediaType( nFilter
) ) )
1248 Sequence
< OUString
> SAL_CALL
GraphicExporter::getSupportedMimeTypeNames( ) throw (RuntimeException
)
1250 GraphicFilter
* pFilter
= GetGrfFilter();
1251 sal_uInt16 nCount
= pFilter
->GetExportFormatCount();
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
;
1268 if( nFound
< nCount
)
1269 aSeq
.realloc( nFound
);
1274 Graphic
SvxGetGraphicForShape( SdrObject
& rShape
, bool bVector
)
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
);
1287 DBG_ERROR("SvxGetGraphicForShape(), exception caught!");