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