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