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