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