Update ooo320-m1
[ooovba.git] / filter / source / pdf / pdfexport.cxx
blob8b45d4f988af8339e26f740dfcdcda474cff5fd3
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: pdfexport.cxx,v $
10 * $Revision: 1.69.36.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_filter.hxx"
34 #include "pdfexport.hxx"
35 #include "impdialog.hxx"
37 #include "pdf.hrc"
38 #include <tools/urlobj.hxx>
39 #include <tools/fract.hxx>
40 #include <tools/poly.hxx>
41 #include <vcl/mapmod.hxx>
42 #include <vcl/virdev.hxx>
43 #include <vcl/metaact.hxx>
44 #include <vcl/gdimtf.hxx>
45 #include <vcl/jobset.hxx>
46 #include <vcl/salbtype.hxx>
47 #include <vcl/bmpacc.hxx>
48 #include "vcl/svapp.hxx"
49 #include <toolkit/awt/vclxdevice.hxx>
50 #include <unotools/localfilehelper.hxx>
51 #include <unotools/processfactory.hxx>
52 #include <svtools/FilterConfigItem.hxx>
53 #include <svtools/filter.hxx>
54 #include <svtools/solar.hrc>
55 #include <comphelper/string.hxx>
57 #include <svtools/saveopt.hxx> // only for testing of relative saving options in PDF
59 #include <vcl/graphictools.hxx>
60 #include <com/sun/star/beans/XPropertySet.hpp>
61 #include <com/sun/star/awt/Rectangle.hpp>
62 #include <com/sun/star/awt/XDevice.hpp>
63 #include <com/sun/star/util/MeasureUnit.hpp>
64 #include <com/sun/star/frame/XModel.hpp>
65 #include <com/sun/star/frame/XModuleManager.hpp>
66 #include <com/sun/star/frame/XStorable.hpp>
67 #include <com/sun/star/frame/XController.hpp>
68 #include <com/sun/star/document/XDocumentProperties.hpp>
69 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
70 #include <com/sun/star/container/XNameAccess.hpp>
71 #include <com/sun/star/view/XViewSettingsSupplier.hpp>
72 #include <unotools/configmgr.hxx>
73 #include <com/sun/star/lang/XServiceInfo.hpp>
74 #include <com/sun/star/drawing/XShapes.hpp>
76 using namespace ::rtl;
77 using namespace ::vcl;
78 using namespace ::com::sun::star;
79 using namespace ::com::sun::star::uno;
80 using namespace ::com::sun::star::lang;
81 using namespace ::com::sun::star::beans;
82 using namespace ::com::sun::star::view;
84 sal_Bool GetPropertyValue( Any& rAny, const Reference< XPropertySet > & rXPropSet, const sal_Char* pName )
86 sal_Bool bRetValue = sal_True;
87 try
89 rAny = rXPropSet->getPropertyValue( String::CreateFromAscii( pName ) );
90 if ( !rAny.hasValue() )
91 bRetValue = sal_False;
93 catch( ::com::sun::star::uno::Exception& )
95 bRetValue = sal_False;
97 return bRetValue;
100 OUString GetProperty( const Reference< XPropertySet > & rXPropSet, const sal_Char* pName )
102 OUString aRetValue;
103 Any aAny;
104 if ( GetPropertyValue( aAny, rXPropSet, pName ) )
105 aAny >>= aRetValue;
106 return aRetValue;
109 // -------------
110 // - PDFExport -
111 // -------------
113 PDFExport::PDFExport( const Reference< XComponent >& rxSrcDoc, Reference< task::XStatusIndicator >& rxStatusIndicator, const Reference< lang::XMultiServiceFactory >& xFactory ) :
114 mxSrcDoc ( rxSrcDoc ),
115 mxMSF ( xFactory ),
116 mxStatusIndicator ( rxStatusIndicator ),
117 mbUseTaggedPDF ( sal_False ),
118 mnPDFTypeSelection ( 0 ),
119 mbExportNotes ( sal_True ),
120 mbExportNotesPages ( sal_False ),
121 mbEmbedStandardFonts ( sal_False ),//in preparation for i54636 and i76458.
122 //already used for i59651 (PDF/A-1)
123 mbUseTransitionEffects ( sal_True ),
124 mbExportBookmarks ( sal_True ),
125 mnOpenBookmarkLevels ( -1 ),
126 mbUseLosslessCompression ( sal_False ),
127 mbReduceImageResolution ( sal_False ),
128 mbSkipEmptyPages ( sal_True ),
129 mbAddStream ( sal_False ),
130 mnMaxImageResolution ( 300 ),
131 mnQuality ( 90 ),
132 mnFormsFormat ( 0 ),
133 mbExportFormFields ( sal_True ),
134 mnProgressValue ( 0 ),
135 mbRemoveTransparencies ( sal_False ),
136 mbWatermark ( sal_False ),
138 mbHideViewerToolbar ( sal_False ),
139 mbHideViewerMenubar ( sal_False ),
140 mbHideViewerWindowControls ( sal_False ),
141 mbFitWindow ( sal_False ),
142 mbCenterWindow ( sal_False ),
143 mbOpenInFullScreenMode ( sal_False ),
144 mbDisplayPDFDocumentTitle ( sal_True ),
145 mnPDFDocumentMode ( 0 ),
146 mnPDFDocumentAction ( 0 ),
147 mnZoom ( 100 ),
148 mnInitialPage ( 1 ),
149 mnPDFPageLayout ( 0 ),
150 mbFirstPageLeft ( sal_False ),
152 mbEncrypt ( sal_False ),
153 msOpenPassword (),
154 mbRestrictPermissions ( sal_False ),
155 msPermissionPassword (),
156 mnPrintAllowed ( 2 ),
157 mnChangesAllowed ( 4 ),
158 mbCanCopyOrExtract ( sal_True ),
159 mbCanExtractForAccessibility( sal_True ),
161 mnCachePatternId ( -1 ),
163 //--->i56629
164 mbExportRelativeFsysLinks ( sal_False ),
165 mnDefaultLinkAction ( 0 ),
166 mbConvertOOoTargetToPDFTarget( sal_False ),
167 mbExportBmkToDest ( sal_False )
168 //<---
172 // -----------------------------------------------------------------------------
174 PDFExport::~PDFExport()
178 // -----------------------------------------------------------------------------
180 sal_Bool PDFExport::ExportSelection( vcl::PDFWriter& rPDFWriter, Reference< com::sun::star::view::XRenderable >& rRenderable, Any& rSelection,
181 MultiSelection aMultiSelection, Sequence< PropertyValue >& rRenderOptions, sal_Int32 nPageCount )
183 sal_Bool bRet = sal_False;
186 Any* pFirstPage = NULL;
187 Any* pLastPage = NULL;
189 for( sal_Int32 nData = 0, nDataCount = rRenderOptions.getLength(); nData < nDataCount; ++nData )
191 if( rRenderOptions[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFirstPage" ) ) )
192 pFirstPage = &rRenderOptions[ nData ].Value;
193 else if( rRenderOptions[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "IsLastPage" ) ) )
194 pLastPage = &rRenderOptions[ nData ].Value;
197 OutputDevice* pOut = rPDFWriter.GetReferenceDevice();
199 if( pOut )
201 vcl::PDFExtOutDevData* pPDFExtOutDevData = PTR_CAST( vcl::PDFExtOutDevData, pOut->GetExtOutDevData() );
202 if ( nPageCount )
204 sal_Int32 nSel = aMultiSelection.FirstSelected();
205 while ( nSel != sal_Int32(SFX_ENDOFSELECTION) )
207 Sequence< PropertyValue > aRenderer( rRenderable->getRenderer( nSel - 1, rSelection, rRenderOptions ) );
208 awt::Size aPageSize;
210 for( sal_Int32 nProperty = 0, nPropertyCount = aRenderer.getLength(); nProperty < nPropertyCount; ++nProperty )
212 if( aRenderer[ nProperty ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "PageSize" ) ) )
213 aRenderer[ nProperty].Value >>= aPageSize;
216 pPDFExtOutDevData->SetCurrentPageNumber( nSel - 1 );
218 GDIMetaFile aMtf;
219 const MapMode aMapMode( MAP_100TH_MM );
220 const Size aMtfSize( aPageSize.Width, aPageSize.Height );
222 pOut->Push();
223 pOut->EnableOutput( FALSE );
224 pOut->SetMapMode( aMapMode );
226 aMtf.SetPrefSize( aMtfSize );
227 aMtf.SetPrefMapMode( aMapMode );
228 aMtf.Record( pOut );
230 // --> FME 2004-10-08 #i35176#
231 // IsLastPage property.
232 const sal_Int32 nCurrentRenderer = nSel - 1;
233 nSel = aMultiSelection.NextSelected();
234 if ( pLastPage && sal_Int32(SFX_ENDOFSELECTION) == nSel )
235 *pLastPage <<= sal_True;
236 // <--
238 rRenderable->render( nCurrentRenderer, rSelection, rRenderOptions );
240 aMtf.Stop();
241 aMtf.WindStart();
243 if( aMtf.GetActionCount() &&
244 ( !mbSkipEmptyPages || aPageSize.Width || aPageSize.Height ) )
245 bRet = ImplExportPage( rPDFWriter, *pPDFExtOutDevData, aMtf ) || bRet;
247 pOut->Pop();
249 if ( mxStatusIndicator.is() )
250 mxStatusIndicator->setValue( mnProgressValue );
251 if ( pFirstPage )
252 *pFirstPage <<= sal_False;
254 ++mnProgressValue;
257 else
259 bRet = sal_True; // #i18334# SJ: nPageCount == 0,
260 rPDFWriter.NewPage( 10000, 10000 ); // creating dummy page
261 rPDFWriter.SetMapMode( MAP_100TH_MM ); //
265 catch( RuntimeException )
268 return bRet;
271 class PDFExportStreamDoc : public vcl::PDFOutputStream
273 Reference< XComponent > m_xSrcDoc;
274 rtl::OUString m_aPassWd;
275 public:
276 PDFExportStreamDoc( const Reference< XComponent >& xDoc, const rtl::OUString& rPwd )
277 : m_xSrcDoc( xDoc ),
278 m_aPassWd( rPwd )
280 virtual ~PDFExportStreamDoc();
282 virtual void write( const Reference< XOutputStream >& xStream );
285 PDFExportStreamDoc::~PDFExportStreamDoc()
289 void PDFExportStreamDoc::write( const Reference< XOutputStream >& xStream )
291 Reference< com::sun::star::frame::XStorable > xStore( m_xSrcDoc, UNO_QUERY );
292 if( xStore.is() )
294 Sequence< beans::PropertyValue > aArgs( m_aPassWd.getLength() ? 3 : 2 );
295 aArgs.getArray()[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" ) );
296 aArgs.getArray()[1].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "OutputStream" ) );
297 aArgs.getArray()[1].Value <<= xStream;
298 if( m_aPassWd.getLength() )
300 aArgs.getArray()[2].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "Password" ) );
301 aArgs.getArray()[2].Value <<= m_aPassWd;
305 xStore->storeToURL( OUString( RTL_CONSTASCII_USTRINGPARAM( "private:stream" ) ),
306 aArgs );
308 catch( IOException& )
314 static OUString getMimetypeForDocument( const Reference< XMultiServiceFactory >& xFactory,
315 const Reference< XComponent >& xDoc ) throw()
317 OUString aDocMimetype;
318 // get document service name
319 Reference< com::sun::star::frame::XStorable > xStore( xDoc, UNO_QUERY );
320 Reference< frame::XModuleManager > xModuleManager(
321 xFactory->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.ModuleManager" ) ) ),
322 uno::UNO_QUERY );
323 if( xModuleManager.is() && xStore.is() )
325 OUString aDocServiceName = xModuleManager->identify( Reference< XInterface >( xStore, uno::UNO_QUERY ) );
326 if ( aDocServiceName.getLength() )
328 // get the actual filter name
329 OUString aFilterName;
330 Reference< lang::XMultiServiceFactory > xConfigProvider(
331 xFactory->createInstance(
332 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) ) ),
333 uno::UNO_QUERY );
334 if( xConfigProvider.is() )
336 uno::Sequence< uno::Any > aArgs( 1 );
337 beans::PropertyValue aPathProp;
338 aPathProp.Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) );
339 aPathProp.Value <<= OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Setup/Office/Factories/" ) );
340 aArgs[0] <<= aPathProp;
342 Reference< container::XNameAccess > xSOFConfig(
343 xConfigProvider->createInstanceWithArguments(
344 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationAccess" ) ),
345 aArgs ),
346 uno::UNO_QUERY );
348 Reference< container::XNameAccess > xApplConfig;
349 xSOFConfig->getByName( aDocServiceName ) >>= xApplConfig;
350 if ( xApplConfig.is() )
352 xApplConfig->getByName( OUString( RTL_CONSTASCII_USTRINGPARAM( "ooSetupFactoryActualFilter" ) ) ) >>= aFilterName;
353 if( aFilterName.getLength() )
355 // find the related type name
356 OUString aTypeName;
357 Reference< container::XNameAccess > xFilterFactory(
358 xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.document.FilterFactory" ) ),
359 uno::UNO_QUERY );
361 Sequence< beans::PropertyValue > aFilterData;
362 xFilterFactory->getByName( aFilterName ) >>= aFilterData;
363 for ( sal_Int32 nInd = 0; nInd < aFilterData.getLength(); nInd++ )
364 if ( aFilterData[nInd].Name.equalsAscii( "Type" ) )
365 aFilterData[nInd].Value >>= aTypeName;
367 if ( aTypeName.getLength() )
369 // find the mediatype
370 Reference< container::XNameAccess > xTypeDetection(
371 xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.document.TypeDetection" ) ),
372 UNO_QUERY );
374 Sequence< beans::PropertyValue > aTypeData;
375 xTypeDetection->getByName( aTypeName ) >>= aTypeData;
376 for ( sal_Int32 nInd = 0; nInd < aTypeData.getLength(); nInd++ )
377 if ( aTypeData[nInd].Name.equalsAscii( "MediaType" ) )
378 aTypeData[nInd].Value >>= aDocMimetype;
385 return aDocMimetype;
388 sal_Bool PDFExport::Export( const OUString& rFile, const Sequence< PropertyValue >& rFilterData )
390 INetURLObject aURL( rFile );
391 OUString aFile;
392 sal_Bool bRet = sal_False;
394 std::set< PDFWriter::ErrorCode > aErrors;
396 if( aURL.GetProtocol() != INET_PROT_FILE )
398 String aTmp;
400 if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( rFile, aTmp ) )
401 aURL = INetURLObject(aTmp);
404 if( aURL.GetProtocol() == INET_PROT_FILE )
406 Reference< XRenderable > xRenderable( mxSrcDoc, UNO_QUERY );
408 if( xRenderable.is() )
410 VCLXDevice* pXDevice = new VCLXDevice;
411 OUString aPageRange;
412 Any aSelection;
414 // getting the string for the creator
415 String aCreator;
416 Reference< XServiceInfo > xInfo( mxSrcDoc, UNO_QUERY );
417 if ( xInfo.is() )
419 if ( xInfo->supportsService( rtl::OUString::createFromAscii( "com.sun.star.presentation.PresentationDocument" ) ) )
420 aCreator.AppendAscii( "Impress" );
421 else if ( xInfo->supportsService( rtl::OUString::createFromAscii( "com.sun.star.drawing.DrawingDocument" ) ) )
422 aCreator.AppendAscii( "Draw" );
423 else if ( xInfo->supportsService( rtl::OUString::createFromAscii( "com.sun.star.text.TextDocument" ) ) )
424 aCreator.AppendAscii( "Writer" );
425 else if ( xInfo->supportsService( rtl::OUString::createFromAscii( "com.sun.star.sheet.SpreadsheetDocument" ) ) )
426 aCreator.AppendAscii( "Calc" );
427 else if ( xInfo->supportsService( rtl::OUString::createFromAscii( "com.sun.star.formula.FormulaProperties" ) ) )
428 aCreator.AppendAscii( "Math" );
431 PDFWriter::PDFWriterContext aContext;
433 for( sal_Int32 nData = 0, nDataCount = rFilterData.getLength(); nData < nDataCount; ++nData )
435 if( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "PageRange" ) ) )
436 rFilterData[ nData ].Value >>= aPageRange;
437 else if( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "Selection" ) ) )
438 rFilterData[ nData ].Value >>= aSelection;
439 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "UseLosslessCompression" ) ) )
440 rFilterData[ nData ].Value >>= mbUseLosslessCompression;
441 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "Quality" ) ) )
442 rFilterData[ nData ].Value >>= mnQuality;
443 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "ReduceImageResolution" ) ) )
444 rFilterData[ nData ].Value >>= mbReduceImageResolution;
445 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "IsSkipEmptyPages" ) ) )
446 rFilterData[ nData ].Value >>= mbSkipEmptyPages;
447 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "MaxImageResolution" ) ) )
448 rFilterData[ nData ].Value >>= mnMaxImageResolution;
449 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "UseTaggedPDF" ) ) )
450 rFilterData[ nData ].Value >>= mbUseTaggedPDF;
451 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "SelectPdfVersion" ) ) )
452 rFilterData[ nData ].Value >>= mnPDFTypeSelection;
453 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "ExportNotes" ) ) )
454 rFilterData[ nData ].Value >>= mbExportNotes;
455 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "ExportNotesPages" ) ) )
456 rFilterData[ nData ].Value >>= mbExportNotesPages;
457 // else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "EmbedStandardFonts" ) ) )
458 // rFilterData[ nData ].Value >>= mbEmbedStandardFonts;
459 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "UseTransitionEffects" ) ) )
460 rFilterData[ nData ].Value >>= mbUseTransitionEffects;
461 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "ExportFormFields" ) ) )
462 rFilterData[ nData ].Value >>= mbExportFormFields;
463 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "FormsType" ) ) )
464 rFilterData[ nData ].Value >>= mnFormsFormat;
465 //viewer properties
466 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "HideViewerToolbar" ) ) )
467 rFilterData[ nData ].Value >>= mbHideViewerToolbar;
468 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "HideViewerMenubar" ) ) )
469 rFilterData[ nData ].Value >>= mbHideViewerMenubar;
470 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "HideViewerWindowControls" ) ) )
471 rFilterData[ nData ].Value >>= mbHideViewerWindowControls;
472 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "ResizeWindowToInitialPage" ) ) )
473 rFilterData[ nData ].Value >>= mbFitWindow;
474 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "CenterWindow" ) ) )
475 rFilterData[ nData ].Value >>= mbCenterWindow;
476 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "OpenInFullScreenMode" ) ) )
477 rFilterData[ nData ].Value >>= mbOpenInFullScreenMode;
478 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "DisplayPDFDocumentTitle" ) ) )
479 rFilterData[ nData ].Value >>= mbDisplayPDFDocumentTitle;
480 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "InitialView" ) ) )
481 rFilterData[ nData ].Value >>= mnPDFDocumentMode;
482 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "Magnification" ) ) )
483 rFilterData[ nData ].Value >>= mnPDFDocumentAction;
484 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "Zoom" ) ) )
485 rFilterData[ nData ].Value >>= mnZoom;
486 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "InitialPage" ) ) )
487 rFilterData[ nData ].Value >>= mnInitialPage;
488 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "PageLayout" ) ) )
489 rFilterData[ nData ].Value >>= mnPDFPageLayout;
490 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "FirstPageOnLeft" ) ) )
491 rFilterData[ nData ].Value >>= aContext.FirstPageLeft;
492 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "IsAddStream" ) ) )
493 rFilterData[ nData ].Value >>= mbAddStream;
494 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "Watermark" ) ) )
496 maWatermark = rFilterData[ nData ].Value;
497 mbWatermark = sal_True;
499 //now all the security related properties...
500 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "EncryptFile" ) ) )
501 rFilterData[ nData ].Value >>= mbEncrypt;
502 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "DocumentOpenPassword" ) ) )
503 rFilterData[ nData ].Value >>= msOpenPassword;
504 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "RestrictPermissions" ) ) )
505 rFilterData[ nData ].Value >>= mbRestrictPermissions;
506 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "PermissionPassword" ) ) )
507 rFilterData[ nData ].Value >>= msPermissionPassword;
508 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "Printing" ) ) )
509 rFilterData[ nData ].Value >>= mnPrintAllowed;
510 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "Changes" ) ) )
511 rFilterData[ nData ].Value >>= mnChangesAllowed;
512 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "EnableCopyingOfContent" ) ) )
513 rFilterData[ nData ].Value >>= mbCanCopyOrExtract;
514 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "EnableTextAccessForAccessibilityTools" ) ) )
515 rFilterData[ nData ].Value >>= mbCanExtractForAccessibility;
516 //--->i56629 links extra (relative links and other related stuff)
517 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "ExportLinksRelativeFsys" ) ) )
518 rFilterData[ nData ].Value >>= mbExportRelativeFsysLinks;
519 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "PDFViewSelection" ) ) )
520 rFilterData[ nData ].Value >>= mnDefaultLinkAction;
521 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "ConvertOOoTargetToPDFTarget" ) ) )
522 rFilterData[ nData ].Value >>= mbConvertOOoTargetToPDFTarget;
523 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "ExportBookmarksToPDFDestination" ) ) )
524 rFilterData[ nData ].Value >>= mbExportBmkToDest;
525 //<---
526 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "ExportBookmarks" ) ) )
527 rFilterData[ nData ].Value >>= mbExportBookmarks;
528 else if ( rFilterData[ nData ].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "OpenBookmarkLevels" ) ) )
529 rFilterData[ nData ].Value >>= mnOpenBookmarkLevels;
531 aContext.URL = aURL.GetMainURL(INetURLObject::DECODE_TO_IURI);
533 //set the correct version, depending on user request
534 switch( mnPDFTypeSelection )
536 default:
537 case 0:
538 aContext.Version = PDFWriter::PDF_1_4;
539 break;
540 case 1:
541 aContext.Version = PDFWriter::PDF_A_1;
542 //force the tagged PDF as well
543 mbUseTaggedPDF = sal_True;
544 //force embedding of standard fonts
545 mbEmbedStandardFonts = sal_True;
546 //force disabling of form conversion
547 mbExportFormFields = sal_False;
548 // PDF/A does not allow transparencies
549 mbRemoveTransparencies = sal_True;
550 break;
553 //copy in context the values default in the contructor or set by the FilterData sequence of properties
554 aContext.Tagged = mbUseTaggedPDF;
556 //values used in viewer
557 aContext.HideViewerToolbar = mbHideViewerToolbar;
558 aContext.HideViewerMenubar = mbHideViewerMenubar;
559 aContext.HideViewerWindowControls = mbHideViewerWindowControls;
560 aContext.FitWindow = mbFitWindow;
561 aContext.CenterWindow = mbCenterWindow;
562 aContext.OpenInFullScreenMode = mbOpenInFullScreenMode;
563 aContext.DisplayPDFDocumentTitle = mbDisplayPDFDocumentTitle;
564 aContext.InitialPage = mnInitialPage-1;
565 aContext.OpenBookmarkLevels = mnOpenBookmarkLevels;
566 aContext.EmbedStandardFonts = mbEmbedStandardFonts;
568 switch( mnPDFDocumentMode )
570 default:
571 case 0:
572 aContext.PDFDocumentMode = PDFWriter::ModeDefault;
573 break;
574 case 1:
575 aContext.PDFDocumentMode = PDFWriter::UseOutlines;
576 break;
577 case 2:
578 aContext.PDFDocumentMode = PDFWriter::UseThumbs;
579 break;
581 switch( mnPDFDocumentAction )
583 default:
584 case 0:
585 aContext.PDFDocumentAction = PDFWriter::ActionDefault;
586 break;
587 case 1:
588 aContext.PDFDocumentAction = PDFWriter::FitInWindow;
589 break;
590 case 2:
591 aContext.PDFDocumentAction = PDFWriter::FitWidth;
592 break;
593 case 3:
594 aContext.PDFDocumentAction = PDFWriter::FitVisible;
595 break;
596 case 4:
597 aContext.PDFDocumentAction = PDFWriter::ActionZoom;
598 aContext.Zoom = mnZoom;
599 break;
602 switch( mnPDFPageLayout )
604 default:
605 case 0:
606 aContext.PageLayout = PDFWriter::DefaultLayout;
607 break;
608 case 1:
609 aContext.PageLayout = PDFWriter::SinglePage;
610 break;
611 case 2:
612 aContext.PageLayout = PDFWriter::Continuous;
613 break;
614 case 3:
615 aContext.PageLayout = PDFWriter::ContinuousFacing;
616 break;
619 aContext.FirstPageLeft = mbFirstPageLeft;
621 //check if PDF/A, which does not allow encryption
622 if( aContext.Version != PDFWriter::PDF_A_1 )
624 //set values needed in encryption
625 aContext.Encrypt = mbEncrypt;
626 //set encryption level, fixed, but here it can set by the UI if needed.
627 // true is 128 bit, false 40
628 //note that in 40 bit mode the UI needs reworking, since the current UI is meaningfull only for
629 //128bit security mode
630 aContext.Security128bit = sal_True;
632 //set the open password
633 if( aContext.Encrypt && msOpenPassword.getLength() > 0 )
634 aContext.UserPassword = msOpenPassword;
636 //set check for permission change password
637 // if not enabled and no permission password, force permissions to default as if PDF where without encryption
638 if( mbRestrictPermissions && msPermissionPassword.getLength() > 0 )
640 aContext.OwnerPassword = msPermissionPassword;
641 aContext.Encrypt = sal_True;
642 //permission set as desired, done after
644 else
646 //force permission to default
647 mnPrintAllowed = 2 ;
648 mnChangesAllowed = 4 ;
649 mbCanCopyOrExtract = sal_True;
650 mbCanExtractForAccessibility = sal_True ;
653 switch( mnPrintAllowed )
655 case 0: //initialized when aContext is build, means no printing
656 break;
657 default:
658 case 2:
659 aContext.AccessPermissions.CanPrintFull = sal_True;
660 case 1:
661 aContext.AccessPermissions.CanPrintTheDocument = sal_True;
662 break;
665 switch( mnChangesAllowed )
667 case 0: //already in struct PDFSecPermissions CTOR
668 break;
669 case 1:
670 aContext.AccessPermissions.CanAssemble = sal_True;
671 break;
672 case 2:
673 aContext.AccessPermissions.CanFillInteractive = sal_True;
674 break;
675 case 3:
676 aContext.AccessPermissions.CanAddOrModify = sal_True;
677 break;
678 default:
679 case 4:
680 aContext.AccessPermissions.CanModifyTheContent =
681 aContext.AccessPermissions.CanCopyOrExtract =
682 aContext.AccessPermissions.CanAddOrModify =
683 aContext.AccessPermissions.CanFillInteractive = sal_True;
684 break;
687 aContext.AccessPermissions.CanCopyOrExtract = mbCanCopyOrExtract;
688 aContext.AccessPermissions.CanExtractForAccessibility = mbCanExtractForAccessibility;
691 * FIXME: the entries are only implicitly defined by the resource file. Should there
692 * ever be an additional form submit format this could get invalid.
694 switch( mnFormsFormat )
696 case 1:
697 aContext.SubmitFormat = PDFWriter::PDF;
698 break;
699 case 2:
700 aContext.SubmitFormat = PDFWriter::HTML;
701 break;
702 case 3:
703 aContext.SubmitFormat = PDFWriter::XML;
704 break;
705 default:
706 case 0:
707 aContext.SubmitFormat = PDFWriter::FDF;
708 break;
711 //get model
712 Reference< frame::XModel > xModel( mxSrcDoc, UNO_QUERY );
714 //---> i56629 Relative link stuff
715 //set the base URL of the file:
716 //then base URL
717 aContext.BaseURL = xModel->getURL();
718 //relative link option is private to PDF Export filter and limited to local filesystem only
719 aContext.RelFsys = mbExportRelativeFsysLinks;
720 //determine the default acton for PDF links
721 switch( mnDefaultLinkAction )
723 default:
724 //default: URI, without fragment conversion (the bookmark in PDF may not work)
725 case 0:
726 aContext.DefaultLinkAction = PDFWriter::URIAction;
727 break;
728 //view PDF through the reader application
729 case 1:
730 aContext.ForcePDFAction = sal_True;
731 aContext.DefaultLinkAction = PDFWriter::LaunchAction;
732 break;
733 //view PDF through an Internet browser
734 case 2:
735 aContext.DefaultLinkAction = PDFWriter::URIActionDestination;
736 break;
738 aContext.ConvertOOoTargetToPDFTarget = mbConvertOOoTargetToPDFTarget;
739 // check for Link Launch action, not allowed on PDF/A-1
740 // this code chunk checks when the filter is called from scripting
741 if( aContext.Version == PDFWriter::PDF_A_1 &&
742 aContext.DefaultLinkAction == PDFWriter::LaunchAction )
743 { //force the similar allowed URI action
744 aContext.DefaultLinkAction = PDFWriter::URIActionDestination;
745 //and remove the remote goto action forced on PDF file
746 aContext.ForcePDFAction = sal_False;
748 //<---
750 // all context data set, time to create the printing device
751 PDFWriter* pPDFWriter = new PDFWriter( aContext );
752 OutputDevice* pOut = pPDFWriter->GetReferenceDevice();
753 vcl::PDFExtOutDevData* pPDFExtOutDevData = NULL;
755 DBG_ASSERT( pOut, "PDFExport::Export: no reference device" );
756 pXDevice->SetOutputDevice( pOut );
758 if( mbAddStream )
760 // export stream
761 // get mimetype
762 OUString aSrcMimetype = getMimetypeForDocument( mxMSF, mxSrcDoc );
763 pPDFWriter->AddStream( aSrcMimetype,
764 new PDFExportStreamDoc( mxSrcDoc, msPermissionPassword ),
765 false
768 PDFDocInfo aDocInfo;
769 Reference< document::XDocumentPropertiesSupplier > xDocumentPropsSupplier( mxSrcDoc, UNO_QUERY );
770 if ( xDocumentPropsSupplier.is() )
772 Reference< document::XDocumentProperties > xDocumentProps( xDocumentPropsSupplier->getDocumentProperties() );
773 if ( xDocumentProps.is() )
775 aDocInfo.Title = xDocumentProps->getTitle();
776 aDocInfo.Author = xDocumentProps->getAuthor();
777 aDocInfo.Subject = xDocumentProps->getSubject();
778 aDocInfo.Keywords = ::comphelper::string::convertCommaSeparated(xDocumentProps->getKeywords());
781 // getting the string for the producer
782 String aProducer;
783 ::utl::ConfigManager* pMgr = ::utl::ConfigManager::GetConfigManager();
784 if ( pMgr )
786 Any aProductName = pMgr->GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTNAME );
787 ::rtl::OUString sProductName;
788 aProductName >>= sProductName;
789 aProducer = sProductName;
790 aProductName = pMgr->GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTVERSION );
791 aProductName >>= sProductName;
792 aProducer.AppendAscii(" ");
793 aProducer += String( sProductName );
795 aDocInfo.Producer = aProducer;
796 aDocInfo.Creator = aCreator;
798 pPDFWriter->SetDocInfo( aDocInfo );
800 if ( pOut )
802 DBG_ASSERT( pOut->GetExtOutDevData() == NULL, "PDFExport: ExtOutDevData already set!!!" );
803 pPDFExtOutDevData = new vcl::PDFExtOutDevData( *pOut );
804 pOut->SetExtOutDevData( pPDFExtOutDevData );
805 pPDFExtOutDevData->SetIsExportNotes( mbExportNotes );
806 pPDFExtOutDevData->SetIsExportTaggedPDF( mbUseTaggedPDF );
807 pPDFExtOutDevData->SetIsExportTransitionEffects( mbUseTransitionEffects );
808 pPDFExtOutDevData->SetFormsFormat( mnFormsFormat );
809 pPDFExtOutDevData->SetIsExportFormFields( mbExportFormFields );
810 pPDFExtOutDevData->SetIsExportBookmarks( mbExportBookmarks );
811 pPDFExtOutDevData->SetIsLosslessCompression( mbUseLosslessCompression );
812 pPDFExtOutDevData->SetIsReduceImageResolution( mbReduceImageResolution );
813 pPDFExtOutDevData->SetIsExportNamedDestinations( mbExportBmkToDest );
815 Sequence< PropertyValue > aRenderOptions( 6 );
816 aRenderOptions[ 0 ].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "RenderDevice" ) );
817 aRenderOptions[ 0 ].Value <<= Reference< awt::XDevice >( pXDevice );
818 aRenderOptions[ 1 ].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "ExportNotesPages" ) );
819 aRenderOptions[ 1 ].Value <<= sal_False;
820 Any& rExportNotesValue = aRenderOptions[ 1 ].Value;
821 aRenderOptions[ 2 ].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFirstPage" ) );
822 aRenderOptions[ 2 ].Value <<= sal_True;
823 aRenderOptions[ 3 ].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "IsLastPage" ) );
824 aRenderOptions[ 3 ].Value <<= sal_False;
825 aRenderOptions[ 4 ].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "PageRange" ) );
826 aRenderOptions[ 4 ].Value <<= aPageRange;
827 aRenderOptions[ 5 ].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "IsSkipEmptyPages" ) );
828 aRenderOptions[ 5 ].Value <<= mbSkipEmptyPages;
830 if( aPageRange.getLength() || !aSelection.hasValue() )
832 aSelection = Any();
833 aSelection <<= mxSrcDoc;
835 sal_Bool bSecondPassForImpressNotes = sal_False;
836 bool bReChangeToNormalView = false;
837 ::rtl::OUString sShowOnlineLayout( RTL_CONSTASCII_USTRINGPARAM( "ShowOnlineLayout"));
838 uno::Reference< beans::XPropertySet > xViewProperties;
840 if ( aCreator.EqualsAscii( "Writer" ) )
842 //i92835 if Writer is in web layout mode this has to be switched to normal view and back to web view in the end
845 Reference< view::XViewSettingsSupplier > xVSettingsSupplier( xModel->getCurrentController(), uno::UNO_QUERY_THROW );
846 xViewProperties = xVSettingsSupplier->getViewSettings();
847 xViewProperties->getPropertyValue( sShowOnlineLayout ) >>= bReChangeToNormalView;
848 if( bReChangeToNormalView )
850 xViewProperties->setPropertyValue( sShowOnlineLayout, uno::makeAny( false ) );
853 catch( const uno::Exception& )
859 const sal_Int32 nPageCount = xRenderable->getRendererCount( aSelection, aRenderOptions );
860 const Range aRange( 1, nPageCount );
861 MultiSelection aMultiSelection;
863 if ( mbExportNotesPages && aCreator.EqualsAscii( "Impress" ) )
865 uno::Reference< drawing::XShapes > xShapes; // sj: do not allow to export notes when
866 if ( ! ( aSelection >>= xShapes ) ) // exporting a selection -> todo: in the dialog
867 bSecondPassForImpressNotes = sal_True; // the export notes checkbox needs to be disabled
870 if( !aPageRange.getLength() )
872 aMultiSelection.SetTotalRange( aRange );
873 aMultiSelection.Select( aRange );
875 else
877 aMultiSelection = MultiSelection( aPageRange );
878 aMultiSelection.SetTotalRange( aRange );
880 if ( mxStatusIndicator.is() )
882 ByteString aResMgrName( "pdffilter" );
883 ResMgr* pResMgr = ResMgr::CreateResMgr( aResMgrName.GetBuffer(), Application::GetSettings().GetUILocale() );
884 if ( pResMgr )
886 sal_Int32 nTotalPageCount = aMultiSelection.GetSelectCount();
887 if ( bSecondPassForImpressNotes )
888 nTotalPageCount *= 2;
889 mxStatusIndicator->start( String( ResId( PDF_PROGRESS_BAR, *pResMgr ) ), nTotalPageCount );
890 delete pResMgr;
894 bRet = ExportSelection( *pPDFWriter, xRenderable, aSelection, aMultiSelection, aRenderOptions, nPageCount );
896 if ( bRet && bSecondPassForImpressNotes )
898 rExportNotesValue <<= sal_True;
899 bRet = ExportSelection( *pPDFWriter, xRenderable, aSelection, aMultiSelection, aRenderOptions, nPageCount );
901 if ( mxStatusIndicator.is() )
902 mxStatusIndicator->end();
904 // if during the export the doc locale was set copy it to PDF writer
905 const com::sun::star::lang::Locale& rLoc( pPDFExtOutDevData->GetDocumentLocale() );
906 if( rLoc.Language.getLength() )
907 pPDFWriter->SetDocumentLocale( rLoc );
909 if( bRet )
911 pPDFExtOutDevData->PlayGlobalActions( *pPDFWriter );
912 pPDFWriter->Emit();
913 aErrors = pPDFWriter->GetErrors();
915 pOut->SetExtOutDevData( NULL );
916 if( bReChangeToNormalView )
920 xViewProperties->setPropertyValue( sShowOnlineLayout, uno::makeAny( true ) );
922 catch( const uno::Exception& )
928 delete pPDFExtOutDevData;
929 delete pPDFWriter;
933 // show eventual errors during export
934 showErrors( aErrors );
936 return bRet;
939 void PDFExport::showErrors( const std::set< PDFWriter::ErrorCode >& rErrors )
941 if( ! rErrors.empty() )
943 ByteString aResMgrName( "pdffilter" );
944 ResMgr* pResMgr = ResMgr::CreateResMgr( aResMgrName.GetBuffer(), Application::GetSettings().GetUILocale() );
945 if ( pResMgr )
947 ImplErrorDialog aDlg( rErrors, *pResMgr );
948 aDlg.Execute();
949 delete pResMgr;
954 // -----------------------------------------------------------------------------
956 sal_Bool PDFExport::ImplExportPage( PDFWriter& rWriter, PDFExtOutDevData& rPDFExtOutDevData, const GDIMetaFile& rMtf )
958 VirtualDevice aDummyVDev;
959 const Size aSizePDF( OutputDevice::LogicToLogic( rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), MAP_POINT ) );
960 Point aOrigin;
961 Rectangle aPageRect( aOrigin, rMtf.GetPrefSize() );
962 sal_Bool bRet = sal_False;
964 aDummyVDev.EnableOutput( sal_False );
965 aDummyVDev.SetMapMode( rMtf.GetPrefMapMode() );
967 rWriter.NewPage( aSizePDF.Width(), aSizePDF.Height() );
968 rWriter.SetMapMode( rMtf.GetPrefMapMode() );
970 rWriter.SetClipRegion( aPageRect );
971 bRet = ImplWriteActions( rWriter, &rPDFExtOutDevData, rMtf, aDummyVDev );
972 rPDFExtOutDevData.ResetSyncData();
974 if( mbWatermark )
975 ImplWriteWatermark( rWriter, aSizePDF );
977 return bRet;
980 // -----------------------------------------------------------------------------
982 void PDFExport::ImplWriteWatermark( PDFWriter& rWriter, const Size& rPageSize )
984 OUString aText( RTL_CONSTASCII_USTRINGPARAM( "Watermark" ) );
985 Font aFont( OUString( RTL_CONSTASCII_USTRINGPARAM( "Helvetica" ) ), Size( 0, 3*rPageSize.Height()/4 ) );
986 aFont.SetItalic( ITALIC_NONE );
987 aFont.SetWidthType( WIDTH_NORMAL );
988 aFont.SetWeight( WEIGHT_NORMAL );
989 aFont.SetAlign( ALIGN_BOTTOM );
990 long nTextWidth = rPageSize.Width();
991 if( rPageSize.Width() < rPageSize.Height() )
993 nTextWidth = rPageSize.Height();
994 aFont.SetOrientation( 2700 );
997 if( ! ( maWatermark >>= aText ) )
999 // more complicated watermark ?
1002 // adjust font height for text to fit
1003 OutputDevice* pDev = rWriter.GetReferenceDevice();
1004 pDev->Push( PUSH_ALL );
1005 pDev->SetFont( aFont );
1006 pDev->SetMapMode( MapMode( MAP_POINT ) );
1007 int w = 0;
1008 while( ( w = pDev->GetTextWidth( aText ) ) > nTextWidth )
1010 long nNewHeight = aFont.GetHeight() * nTextWidth / w;
1011 if( nNewHeight == aFont.GetHeight() )
1013 nNewHeight--;
1014 if( nNewHeight <= 0 )
1015 break;
1017 aFont.SetHeight( nNewHeight );
1018 pDev->SetFont( aFont );
1020 long nTextHeight = pDev->GetTextHeight();
1021 // leave some maneuvering room for rounding issues, also
1022 // some fonts go a little outside ascent/descent
1023 nTextHeight += nTextHeight/20;
1024 pDev->Pop();
1026 rWriter.Push( PUSH_ALL );
1027 rWriter.SetMapMode( MapMode( MAP_POINT ) );
1028 rWriter.SetFont( aFont );
1029 rWriter.SetTextColor( COL_RED );
1030 Point aTextPoint;
1031 Rectangle aTextRect;
1032 if( rPageSize.Width() > rPageSize.Height() )
1034 aTextPoint = Point( (rPageSize.Width()-w)/2,
1035 rPageSize.Height()-(rPageSize.Height()-nTextHeight)/2 );
1036 aTextRect = Rectangle( Point( (rPageSize.Width()-w)/2,
1037 (rPageSize.Height()-nTextHeight)/2 ),
1038 Size( w, nTextHeight ) );
1040 else
1042 aTextPoint = Point( (rPageSize.Width()-nTextHeight)/2,
1043 (rPageSize.Height()-w)/2 );
1044 aTextRect = Rectangle( aTextPoint, Size( nTextHeight, w ) );
1046 rWriter.SetClipRegion();
1047 rWriter.BeginTransparencyGroup();
1048 rWriter.DrawText( aTextPoint, aText );
1049 rWriter.EndTransparencyGroup( aTextRect, 50 );
1050 rWriter.Pop();
1053 // -----------------------------------------------------------------------------
1055 sal_Bool PDFExport::ImplWriteActions( PDFWriter& rWriter, PDFExtOutDevData* pPDFExtOutDevData,
1056 const GDIMetaFile& rInMtf, VirtualDevice& rDummyVDev )
1058 bool bAssertionFired( false );
1060 GDIMetaFile aMtf;
1061 bool bTransparenciesRemoved = false;
1062 if( mbRemoveTransparencies )
1064 bTransparenciesRemoved = rWriter.GetReferenceDevice()->
1065 RemoveTransparenciesFromMetaFile( rInMtf, aMtf, mnMaxImageResolution, mnMaxImageResolution,
1066 false, true, mbReduceImageResolution );
1068 else
1070 aMtf = rInMtf;
1074 for( sal_uInt32 i = 0, nCount = aMtf.GetActionCount(); i < nCount; )
1076 if ( !pPDFExtOutDevData || !pPDFExtOutDevData->PlaySyncPageAct( rWriter, i ) )
1078 const MetaAction* pAction = aMtf.GetAction( i );
1079 const USHORT nType = pAction->GetType();
1081 switch( nType )
1083 case( META_PIXEL_ACTION ):
1085 const MetaPixelAction* pA = (const MetaPixelAction*) pAction;
1086 rWriter.DrawPixel( pA->GetPoint(), pA->GetColor() );
1088 break;
1090 case( META_POINT_ACTION ):
1092 const MetaPointAction* pA = (const MetaPointAction*) pAction;
1093 rWriter.DrawPixel( pA->GetPoint() );
1095 break;
1097 case( META_LINE_ACTION ):
1099 const MetaLineAction* pA = (const MetaLineAction*) pAction;
1100 if ( pA->GetLineInfo().IsDefault() )
1101 rWriter.DrawLine( pA->GetStartPoint(), pA->GetEndPoint() );
1102 else
1103 rWriter.DrawLine( pA->GetStartPoint(), pA->GetEndPoint(), pA->GetLineInfo() );
1105 break;
1107 case( META_RECT_ACTION ):
1109 const MetaRectAction* pA = (const MetaRectAction*) pAction;
1110 rWriter.DrawRect( pA->GetRect() );
1112 break;
1114 case( META_ROUNDRECT_ACTION ):
1116 const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pAction;
1117 rWriter.DrawRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() );
1119 break;
1121 case( META_ELLIPSE_ACTION ):
1123 const MetaEllipseAction* pA = (const MetaEllipseAction*) pAction;
1124 rWriter.DrawEllipse( pA->GetRect() );
1126 break;
1128 case( META_ARC_ACTION ):
1130 const MetaArcAction* pA = (const MetaArcAction*) pAction;
1131 rWriter.DrawArc( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
1133 break;
1135 case( META_PIE_ACTION ):
1137 const MetaArcAction* pA = (const MetaArcAction*) pAction;
1138 rWriter.DrawPie( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
1140 break;
1142 case( META_CHORD_ACTION ):
1144 const MetaChordAction* pA = (const MetaChordAction*) pAction;
1145 rWriter.DrawChord( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
1147 break;
1149 case( META_POLYGON_ACTION ):
1151 const MetaPolygonAction* pA = (const MetaPolygonAction*) pAction;
1152 rWriter.DrawPolygon( pA->GetPolygon() );
1154 break;
1156 case( META_POLYLINE_ACTION ):
1158 const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pAction;
1159 if ( pA->GetLineInfo().IsDefault() )
1160 rWriter.DrawPolyLine( pA->GetPolygon() );
1161 else
1162 rWriter.DrawPolyLine( pA->GetPolygon(), pA->GetLineInfo() );
1164 break;
1166 case( META_POLYPOLYGON_ACTION ):
1168 const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*) pAction;
1169 rWriter.DrawPolyPolygon( pA->GetPolyPolygon() );
1171 break;
1173 case( META_GRADIENT_ACTION ):
1175 const MetaGradientAction* pA = (const MetaGradientAction*) pAction;
1176 const PolyPolygon aPolyPoly( pA->GetRect() );
1178 ImplWriteGradient( rWriter, aPolyPoly, pA->GetGradient(), rDummyVDev );
1180 break;
1182 case( META_GRADIENTEX_ACTION ):
1184 const MetaGradientExAction* pA = (const MetaGradientExAction*) pAction;
1185 ImplWriteGradient( rWriter, pA->GetPolyPolygon(), pA->GetGradient(), rDummyVDev );
1187 break;
1189 case META_HATCH_ACTION:
1191 const MetaHatchAction* pA = (const MetaHatchAction*) pAction;
1192 rWriter.DrawHatch( pA->GetPolyPolygon(), pA->GetHatch() );
1194 break;
1196 case( META_TRANSPARENT_ACTION ):
1198 const MetaTransparentAction* pA = (const MetaTransparentAction*) pAction;
1199 rWriter.DrawTransparent( pA->GetPolyPolygon(), pA->GetTransparence() );
1201 break;
1203 case( META_FLOATTRANSPARENT_ACTION ):
1205 const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pAction;
1207 GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
1208 const Point& rPos = pA->GetPoint();
1209 const Size& rSize= pA->GetSize();
1210 const Gradient& rTransparenceGradient = pA->GetGradient();
1212 const Size aDstSizeTwip( rDummyVDev.PixelToLogic( rDummyVDev.LogicToPixel( rSize ), MAP_TWIP ) );
1213 sal_Int32 nMaxBmpDPI = mbUseLosslessCompression ? 300 : 72;
1214 if ( mbReduceImageResolution )
1216 if ( nMaxBmpDPI > mnMaxImageResolution )
1217 nMaxBmpDPI = mnMaxImageResolution;
1219 const sal_Int32 nPixelX = (sal_Int32)((double)aDstSizeTwip.Width() * (double)nMaxBmpDPI / 1440.0);
1220 const sal_Int32 nPixelY = (sal_Int32)((double)aDstSizeTwip.Height() * (double)nMaxBmpDPI / 1440.0);
1221 if ( nPixelX && nPixelY )
1223 Size aDstSizePixel( nPixelX, nPixelY );
1224 VirtualDevice* pVDev = new VirtualDevice;
1225 if( pVDev->SetOutputSizePixel( aDstSizePixel ) )
1227 Bitmap aPaint, aMask;
1228 AlphaMask aAlpha;
1229 Point aPoint;
1231 MapMode aMapMode( rDummyVDev.GetMapMode() );
1232 aMapMode.SetOrigin( aPoint );
1233 pVDev->SetMapMode( aMapMode );
1234 Size aDstSize( pVDev->PixelToLogic( aDstSizePixel ) );
1236 Point aMtfOrigin( aTmpMtf.GetPrefMapMode().GetOrigin() );
1237 if ( aMtfOrigin.X() || aMtfOrigin.Y() )
1238 aTmpMtf.Move( -aMtfOrigin.X(), -aMtfOrigin.Y() );
1239 double fScaleX = (double)aDstSize.Width() / (double)aTmpMtf.GetPrefSize().Width();
1240 double fScaleY = (double)aDstSize.Height() / (double)aTmpMtf.GetPrefSize().Height();
1241 if( fScaleX != 1.0 || fScaleY != 1.0 )
1242 aTmpMtf.Scale( fScaleX, fScaleY );
1243 aTmpMtf.SetPrefMapMode( aMapMode );
1245 // create paint bitmap
1246 aTmpMtf.WindStart();
1247 aTmpMtf.Play( pVDev, aPoint, aDstSize );
1248 aTmpMtf.WindStart();
1250 pVDev->EnableMapMode( FALSE );
1251 aPaint = pVDev->GetBitmap( aPoint, aDstSizePixel );
1252 pVDev->EnableMapMode( TRUE );
1254 // create mask bitmap
1255 pVDev->SetLineColor( COL_BLACK );
1256 pVDev->SetFillColor( COL_BLACK );
1257 pVDev->DrawRect( Rectangle( aPoint, aDstSize ) );
1258 pVDev->SetDrawMode( DRAWMODE_WHITELINE | DRAWMODE_WHITEFILL | DRAWMODE_WHITETEXT |
1259 DRAWMODE_WHITEBITMAP | DRAWMODE_WHITEGRADIENT );
1260 aTmpMtf.WindStart();
1261 aTmpMtf.Play( pVDev, aPoint, aDstSize );
1262 aTmpMtf.WindStart();
1263 pVDev->EnableMapMode( FALSE );
1264 aMask = pVDev->GetBitmap( aPoint, aDstSizePixel );
1265 pVDev->EnableMapMode( TRUE );
1267 // create alpha mask from gradient
1268 pVDev->SetDrawMode( DRAWMODE_GRAYGRADIENT );
1269 pVDev->DrawGradient( Rectangle( aPoint, aDstSize ), rTransparenceGradient );
1270 pVDev->SetDrawMode( DRAWMODE_DEFAULT );
1271 pVDev->EnableMapMode( FALSE );
1272 pVDev->DrawMask( aPoint, aDstSizePixel, aMask, Color( COL_WHITE ) );
1273 aAlpha = pVDev->GetBitmap( aPoint, aDstSizePixel );
1274 ImplWriteBitmapEx( rWriter, rDummyVDev, rPos, rSize, BitmapEx( aPaint, aAlpha ) );
1276 delete pVDev;
1279 break;
1281 case( META_EPS_ACTION ):
1283 const MetaEPSAction* pA = (const MetaEPSAction*) pAction;
1284 const GDIMetaFile aSubstitute( pA->GetSubstitute() );
1286 rWriter.Push();
1287 rDummyVDev.Push();
1289 MapMode aMapMode( aSubstitute.GetPrefMapMode() );
1290 Size aOutSize( rDummyVDev.LogicToLogic( pA->GetSize(), rDummyVDev.GetMapMode(), aMapMode ) );
1291 aMapMode.SetScaleX( Fraction( aOutSize.Width(), aSubstitute.GetPrefSize().Width() ) );
1292 aMapMode.SetScaleY( Fraction( aOutSize.Height(), aSubstitute.GetPrefSize().Height() ) );
1293 aMapMode.SetOrigin( rDummyVDev.LogicToLogic( pA->GetPoint(), rDummyVDev.GetMapMode(), aMapMode ) );
1295 rWriter.SetMapMode( aMapMode );
1296 rDummyVDev.SetMapMode( aMapMode );
1297 ImplWriteActions( rWriter, NULL, aSubstitute, rDummyVDev );
1298 rDummyVDev.Pop();
1299 rWriter.Pop();
1301 break;
1303 case( META_COMMENT_ACTION ):
1304 if( ! bTransparenciesRemoved )
1306 const MetaCommentAction* pA = (const MetaCommentAction*) pAction;
1307 String aSkipComment;
1309 if( pA->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_BEGIN" ) == COMPARE_EQUAL )
1311 const MetaGradientExAction* pGradAction = NULL;
1312 sal_Bool bDone = sal_False;
1314 while( !bDone && ( ++i < nCount ) )
1316 pAction = aMtf.GetAction( i );
1318 if( pAction->GetType() == META_GRADIENTEX_ACTION )
1319 pGradAction = (const MetaGradientExAction*) pAction;
1320 else if( ( pAction->GetType() == META_COMMENT_ACTION ) &&
1321 ( ( (const MetaCommentAction*) pAction )->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_END" ) == COMPARE_EQUAL ) )
1323 bDone = sal_True;
1327 if( pGradAction )
1328 ImplWriteGradient( rWriter, pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), rDummyVDev );
1330 else
1332 const BYTE* pData = pA->GetData();
1333 if ( pData )
1335 SvMemoryStream aMemStm( (void*)pData, pA->GetDataSize(), STREAM_READ );
1336 sal_Bool bSkipSequence = sal_False;
1337 ByteString sSeqEnd;
1339 if( pA->GetComment().Equals( "XPATHSTROKE_SEQ_BEGIN" ) )
1341 sSeqEnd = ByteString( "XPATHSTROKE_SEQ_END" );
1342 SvtGraphicStroke aStroke;
1343 aMemStm >> aStroke;
1345 Polygon aPath;
1346 aStroke.getPath( aPath );
1348 PolyPolygon aStartArrow;
1349 PolyPolygon aEndArrow;
1350 double fTransparency( aStroke.getTransparency() );
1351 double fStrokeWidth( aStroke.getStrokeWidth() );
1352 SvtGraphicStroke::JoinType eJT( aStroke.getJoinType() );
1353 SvtGraphicStroke::DashArray aDashArray;
1355 aStroke.getStartArrow( aStartArrow );
1356 aStroke.getEndArrow( aEndArrow );
1357 aStroke.getDashArray( aDashArray );
1359 bSkipSequence = sal_True;
1360 if ( aStartArrow.Count() || aEndArrow.Count() )
1361 bSkipSequence = sal_False;
1362 if ( (sal_uInt32)eJT > 2 )
1363 bSkipSequence = sal_False;
1364 if ( aDashArray.size() && ( fStrokeWidth != 0.0 ) && ( fTransparency == 0.0 ) )
1365 bSkipSequence = sal_False;
1366 if ( bSkipSequence )
1368 PDFWriter::ExtLineInfo aInfo;
1369 aInfo.m_fLineWidth = fStrokeWidth;
1370 aInfo.m_fTransparency = fTransparency;
1371 aInfo.m_fMiterLimit = aStroke.getMiterLimit();
1372 switch( aStroke.getCapType() )
1374 default:
1375 case SvtGraphicStroke::capButt: aInfo.m_eCap = PDFWriter::capButt;break;
1376 case SvtGraphicStroke::capRound: aInfo.m_eCap = PDFWriter::capRound;break;
1377 case SvtGraphicStroke::capSquare: aInfo.m_eCap = PDFWriter::capSquare;break;
1379 switch( aStroke.getJoinType() )
1381 default:
1382 case SvtGraphicStroke::joinMiter: aInfo.m_eJoin = PDFWriter::joinMiter;break;
1383 case SvtGraphicStroke::joinRound: aInfo.m_eJoin = PDFWriter::joinRound;break;
1384 case SvtGraphicStroke::joinBevel: aInfo.m_eJoin = PDFWriter::joinBevel;break;
1385 case SvtGraphicStroke::joinNone:
1386 aInfo.m_eJoin = PDFWriter::joinMiter;
1387 aInfo.m_fMiterLimit = 0.0;
1388 break;
1390 aInfo.m_aDashArray = aDashArray;
1391 rWriter.DrawPolyLine( aPath, aInfo );
1394 else if ( pA->GetComment().Equals( "XPATHFILL_SEQ_BEGIN" ) )
1396 sSeqEnd = ByteString( "XPATHFILL_SEQ_END" );
1397 SvtGraphicFill aFill;
1398 aMemStm >> aFill;
1400 if ( ( aFill.getFillType() == SvtGraphicFill::fillSolid ) && ( aFill.getFillRule() == SvtGraphicFill::fillEvenOdd ) )
1402 double fTransparency = aFill.getTransparency();
1403 if ( fTransparency == 0.0 )
1405 PolyPolygon aPath;
1406 aFill.getPath( aPath );
1408 bSkipSequence = sal_True;
1409 rWriter.DrawPolyPolygon( aPath );
1411 else if ( fTransparency == 1.0 )
1412 bSkipSequence = sal_True;
1414 /* #i81548# removing optimization for fill textures, because most of the texture settings are not
1415 exported properly. In OpenOffice 3.1 the drawing layer will support graphic primitives, then it
1416 will not be a problem to optimize the filltexture export. But for wysiwyg is more important than
1417 filesize.
1418 else if( aFill.getFillType() == SvtGraphicFill::fillTexture && aFill.isTiling() )
1420 sal_Int32 nPattern = mnCachePatternId;
1421 Graphic aPatternGraphic;
1422 aFill.getGraphic( aPatternGraphic );
1423 bool bUseCache = false;
1424 SvtGraphicFill::Transform aPatTransform;
1425 aFill.getTransform( aPatTransform );
1427 if( mnCachePatternId >= 0 )
1429 SvtGraphicFill::Transform aCacheTransform;
1430 maCacheFill.getTransform( aCacheTransform );
1431 if( aCacheTransform.matrix[0] == aPatTransform.matrix[0] &&
1432 aCacheTransform.matrix[1] == aPatTransform.matrix[1] &&
1433 aCacheTransform.matrix[2] == aPatTransform.matrix[2] &&
1434 aCacheTransform.matrix[3] == aPatTransform.matrix[3] &&
1435 aCacheTransform.matrix[4] == aPatTransform.matrix[4] &&
1436 aCacheTransform.matrix[5] == aPatTransform.matrix[5]
1439 Graphic aCacheGraphic;
1440 maCacheFill.getGraphic( aCacheGraphic );
1441 if( aCacheGraphic == aPatternGraphic )
1442 bUseCache = true;
1446 if( ! bUseCache )
1449 // paint graphic to metafile
1450 GDIMetaFile aPattern;
1451 rDummyVDev.SetConnectMetaFile( &aPattern );
1452 rDummyVDev.Push();
1453 rDummyVDev.SetMapMode( aPatternGraphic.GetPrefMapMode() );
1455 aPatternGraphic.Draw( &rDummyVDev, Point( 0, 0 ) );
1456 rDummyVDev.Pop();
1457 rDummyVDev.SetConnectMetaFile( NULL );
1458 aPattern.WindStart();
1460 MapMode aPatternMapMode( aPatternGraphic.GetPrefMapMode() );
1461 // prepare pattern from metafile
1462 Size aPrefSize( aPatternGraphic.GetPrefSize() );
1463 // FIXME: this magic -1 shouldn't be necessary
1464 aPrefSize.Width() -= 1;
1465 aPrefSize.Height() -= 1;
1466 aPrefSize = rWriter.GetReferenceDevice()->
1467 LogicToLogic( aPrefSize,
1468 &aPatternMapMode,
1469 &rWriter.GetReferenceDevice()->GetMapMode() );
1470 // build bounding rectangle of pattern
1471 Rectangle aBound( Point( 0, 0 ), aPrefSize );
1472 rWriter.BeginPattern( aBound );
1473 rWriter.Push();
1474 rDummyVDev.Push();
1475 rWriter.SetMapMode( aPatternMapMode );
1476 rDummyVDev.SetMapMode( aPatternMapMode );
1477 ImplWriteActions( rWriter, NULL, aPattern, rDummyVDev );
1478 rDummyVDev.Pop();
1479 rWriter.Pop();
1481 nPattern = rWriter.EndPattern( aPatTransform );
1483 // try some caching and reuse pattern
1484 mnCachePatternId = nPattern;
1485 maCacheFill = aFill;
1488 // draw polypolygon with pattern fill
1489 PolyPolygon aPath;
1490 aFill.getPath( aPath );
1491 rWriter.DrawPolyPolygon( aPath, nPattern, aFill.getFillRule() == SvtGraphicFill::fillEvenOdd );
1493 bSkipSequence = sal_True;
1497 if ( bSkipSequence )
1499 while( ++i < nCount )
1501 pAction = aMtf.GetAction( i );
1502 if ( pAction->GetType() == META_COMMENT_ACTION )
1504 ByteString sComment( ((MetaCommentAction*)pAction)->GetComment() );
1505 if ( sComment.Equals( sSeqEnd ) )
1506 break;
1508 // #i44496#
1509 // the replacement action for stroke is a filled rectangle
1510 // the set fillcolor of the replacement is part of the graphics
1511 // state and must not be skipped
1512 else if( pAction->GetType() == META_FILLCOLOR_ACTION )
1514 const MetaFillColorAction* pMA = (const MetaFillColorAction*) pAction;
1515 if( pMA->IsSetting() )
1516 rWriter.SetFillColor( pMA->GetColor() );
1517 else
1518 rWriter.SetFillColor();
1525 break;
1527 case( META_BMP_ACTION ):
1529 const MetaBmpAction* pA = (const MetaBmpAction*) pAction;
1530 BitmapEx aBitmapEx( pA->GetBitmap() );
1531 Size aSize( OutputDevice::LogicToLogic( aBitmapEx.GetPrefSize(),
1532 aBitmapEx.GetPrefMapMode(), rDummyVDev.GetMapMode() ) );
1533 if( ! ( aSize.Width() && aSize.Height() ) )
1534 aSize = rDummyVDev.PixelToLogic( aBitmapEx.GetSizePixel() );
1535 ImplWriteBitmapEx( rWriter, rDummyVDev, pA->GetPoint(), aSize, aBitmapEx );
1537 break;
1539 case( META_BMPSCALE_ACTION ):
1541 const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
1542 ImplWriteBitmapEx( rWriter, rDummyVDev, pA->GetPoint(), pA->GetSize(), BitmapEx( pA->GetBitmap() ) );
1544 break;
1546 case( META_BMPSCALEPART_ACTION ):
1548 const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pAction;
1549 BitmapEx aBitmapEx( pA->GetBitmap() );
1550 aBitmapEx.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
1551 ImplWriteBitmapEx( rWriter, rDummyVDev, pA->GetDestPoint(), pA->GetDestSize(), aBitmapEx );
1553 break;
1555 case( META_BMPEX_ACTION ):
1557 const MetaBmpExAction* pA = (const MetaBmpExAction*) pAction;
1558 BitmapEx aBitmapEx( pA->GetBitmapEx() );
1559 Size aSize( OutputDevice::LogicToLogic( aBitmapEx.GetPrefSize(),
1560 aBitmapEx.GetPrefMapMode(), rDummyVDev.GetMapMode() ) );
1561 ImplWriteBitmapEx( rWriter, rDummyVDev, pA->GetPoint(), aSize, aBitmapEx );
1563 break;
1565 case( META_BMPEXSCALE_ACTION ):
1567 const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
1568 ImplWriteBitmapEx( rWriter, rDummyVDev, pA->GetPoint(), pA->GetSize(), pA->GetBitmapEx() );
1570 break;
1572 case( META_BMPEXSCALEPART_ACTION ):
1574 const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pAction;
1575 BitmapEx aBitmapEx( pA->GetBitmapEx() );
1576 aBitmapEx.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
1577 ImplWriteBitmapEx( rWriter, rDummyVDev, pA->GetDestPoint(), pA->GetDestSize(), aBitmapEx );
1579 break;
1581 case( META_MASK_ACTION ):
1582 case( META_MASKSCALE_ACTION ):
1583 case( META_MASKSCALEPART_ACTION ):
1585 DBG_ERROR( "MetaMask...Action not supported yet" );
1587 break;
1589 case( META_TEXT_ACTION ):
1591 const MetaTextAction* pA = (const MetaTextAction*) pAction;
1592 rWriter.DrawText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ) );
1594 break;
1596 case( META_TEXTRECT_ACTION ):
1598 const MetaTextRectAction* pA = (const MetaTextRectAction*) pAction;
1599 rWriter.DrawText( pA->GetRect(), String( pA->GetText() ), pA->GetStyle() );
1601 break;
1603 case( META_TEXTARRAY_ACTION ):
1605 const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pAction;
1606 rWriter.DrawTextArray( pA->GetPoint(), pA->GetText(), pA->GetDXArray(), pA->GetIndex(), pA->GetLen() );
1608 break;
1610 case( META_STRETCHTEXT_ACTION ):
1612 const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pAction;
1613 rWriter.DrawStretchText( pA->GetPoint(), pA->GetWidth(), pA->GetText(), pA->GetIndex(), pA->GetLen() );
1615 break;
1618 case( META_TEXTLINE_ACTION ):
1620 const MetaTextLineAction* pA = (const MetaTextLineAction*) pAction;
1621 rWriter.DrawTextLine( pA->GetStartPoint(), pA->GetWidth(), pA->GetStrikeout(), pA->GetUnderline(), pA->GetOverline() );
1624 break;
1626 case( META_CLIPREGION_ACTION ):
1628 const MetaClipRegionAction* pA = (const MetaClipRegionAction*) pAction;
1630 if( pA->IsClipping() )
1631 rWriter.SetClipRegion( pA->GetRegion() );
1632 else
1633 rWriter.SetClipRegion();
1635 break;
1637 case( META_ISECTRECTCLIPREGION_ACTION ):
1639 const MetaISectRectClipRegionAction* pA = (const MetaISectRectClipRegionAction*) pAction;
1640 rWriter.IntersectClipRegion( pA->GetRect() );
1642 break;
1644 case( META_ISECTREGIONCLIPREGION_ACTION ):
1646 const MetaISectRegionClipRegionAction* pA = (const MetaISectRegionClipRegionAction*) pAction;
1647 rWriter.IntersectClipRegion( pA->GetRegion() );
1649 break;
1651 case( META_MOVECLIPREGION_ACTION ):
1653 const MetaMoveClipRegionAction* pA = (const MetaMoveClipRegionAction*) pAction;
1654 rWriter.MoveClipRegion( pA->GetHorzMove(), pA->GetVertMove() );
1656 break;
1658 case( META_MAPMODE_ACTION ):
1660 const_cast< MetaAction* >( pAction )->Execute( &rDummyVDev );
1661 rWriter.SetMapMode( rDummyVDev.GetMapMode() );
1663 break;
1665 case( META_LINECOLOR_ACTION ):
1667 const MetaLineColorAction* pA = (const MetaLineColorAction*) pAction;
1669 if( pA->IsSetting() )
1670 rWriter.SetLineColor( pA->GetColor() );
1671 else
1672 rWriter.SetLineColor();
1674 break;
1676 case( META_FILLCOLOR_ACTION ):
1678 const MetaFillColorAction* pA = (const MetaFillColorAction*) pAction;
1680 if( pA->IsSetting() )
1681 rWriter.SetFillColor( pA->GetColor() );
1682 else
1683 rWriter.SetFillColor();
1685 break;
1687 case( META_TEXTLINECOLOR_ACTION ):
1689 const MetaTextLineColorAction* pA = (const MetaTextLineColorAction*) pAction;
1691 if( pA->IsSetting() )
1692 rWriter.SetTextLineColor( pA->GetColor() );
1693 else
1694 rWriter.SetTextLineColor();
1696 break;
1698 case( META_OVERLINECOLOR_ACTION ):
1700 const MetaOverlineColorAction* pA = (const MetaOverlineColorAction*) pAction;
1702 if( pA->IsSetting() )
1703 rWriter.SetOverlineColor( pA->GetColor() );
1704 else
1705 rWriter.SetOverlineColor();
1707 break;
1709 case( META_TEXTFILLCOLOR_ACTION ):
1711 const MetaTextFillColorAction* pA = (const MetaTextFillColorAction*) pAction;
1713 if( pA->IsSetting() )
1714 rWriter.SetTextFillColor( pA->GetColor() );
1715 else
1716 rWriter.SetTextFillColor();
1718 break;
1720 case( META_TEXTCOLOR_ACTION ):
1722 const MetaTextColorAction* pA = (const MetaTextColorAction*) pAction;
1723 rWriter.SetTextColor( pA->GetColor() );
1725 break;
1727 case( META_TEXTALIGN_ACTION ):
1729 const MetaTextAlignAction* pA = (const MetaTextAlignAction*) pAction;
1730 rWriter.SetTextAlign( pA->GetTextAlign() );
1732 break;
1734 case( META_FONT_ACTION ):
1736 const MetaFontAction* pA = (const MetaFontAction*) pAction;
1737 rWriter.SetFont( pA->GetFont() );
1739 break;
1741 case( META_PUSH_ACTION ):
1743 const MetaPushAction* pA = (const MetaPushAction*) pAction;
1745 rDummyVDev.Push( pA->GetFlags() );
1746 rWriter.Push( pA->GetFlags() );
1748 break;
1750 case( META_POP_ACTION ):
1752 rDummyVDev.Pop();
1753 rWriter.Pop();
1755 break;
1757 case( META_LAYOUTMODE_ACTION ):
1759 const MetaLayoutModeAction* pA = (const MetaLayoutModeAction*) pAction;
1760 rWriter.SetLayoutMode( pA->GetLayoutMode() );
1762 break;
1764 case META_TEXTLANGUAGE_ACTION:
1766 const MetaTextLanguageAction* pA = (const MetaTextLanguageAction*) pAction;
1767 rWriter.SetDigitLanguage( pA->GetTextLanguage() );
1769 break;
1771 case( META_WALLPAPER_ACTION ):
1773 const MetaWallpaperAction* pA = (const MetaWallpaperAction*) pAction;
1774 rWriter.DrawWallpaper( pA->GetRect(), pA->GetWallpaper() );
1776 break;
1778 case( META_RASTEROP_ACTION ):
1780 // !!! >>> we don't want to support this actions
1782 break;
1784 case( META_REFPOINT_ACTION ):
1786 // !!! >>> we don't want to support this actions
1788 break;
1790 default:
1791 // #i24604# Made assertion fire only once per
1792 // metafile. The asserted actions here are all
1793 // deprecated
1794 if( !bAssertionFired )
1796 bAssertionFired = true;
1797 DBG_ERROR( "PDFExport::ImplWriteActions: deprecated and unsupported MetaAction encountered" );
1799 break;
1801 i++;
1805 return sal_True;
1808 // -----------------------------------------------------------------------------
1810 void PDFExport::ImplWriteGradient( PDFWriter& rWriter, const PolyPolygon& rPolyPoly, const Gradient& rGradient, VirtualDevice& rDummyVDev )
1812 GDIMetaFile aTmpMtf;
1814 rDummyVDev.AddGradientActions( rPolyPoly.GetBoundRect(), rGradient, aTmpMtf );
1816 rWriter.Push();
1817 rWriter.IntersectClipRegion( rPolyPoly );
1818 ImplWriteActions( rWriter, NULL, aTmpMtf, rDummyVDev );
1819 rWriter.Pop();
1822 // -----------------------------------------------------------------------------
1824 void PDFExport::ImplWriteBitmapEx( PDFWriter& rWriter, VirtualDevice& rDummyVDev,
1825 const Point& rPoint, const Size& rSize, const BitmapEx& rBitmapEx )
1827 if ( !rBitmapEx.IsEmpty() && rSize.Width() && rSize.Height() )
1829 BitmapEx aBitmapEx( rBitmapEx );
1830 Point aPoint( rPoint );
1831 Size aSize( rSize );
1833 // #i19065# Negative sizes have mirror semantics on
1834 // OutputDevice. BitmapEx and co. have no idea about that, so
1835 // perform that _before_ doing anything with aBitmapEx.
1836 ULONG nMirrorFlags(BMP_MIRROR_NONE);
1837 if( aSize.Width() < 0 )
1839 aSize.Width() *= -1;
1840 aPoint.X() -= aSize.Width();
1841 nMirrorFlags |= BMP_MIRROR_HORZ;
1843 if( aSize.Height() < 0 )
1845 aSize.Height() *= -1;
1846 aPoint.Y() -= aSize.Height();
1847 nMirrorFlags |= BMP_MIRROR_VERT;
1850 if( nMirrorFlags != BMP_MIRROR_NONE )
1852 aBitmapEx.Mirror( nMirrorFlags );
1854 if ( mbReduceImageResolution )
1856 // do downsampling if neccessary
1857 const Size aDstSizeTwip( rDummyVDev.PixelToLogic( rDummyVDev.LogicToPixel( aSize ), MAP_TWIP ) );
1858 const Size aBmpSize( aBitmapEx.GetSizePixel() );
1859 const double fBmpPixelX = aBmpSize.Width();
1860 const double fBmpPixelY = aBmpSize.Height();
1861 const double fMaxPixelX = aDstSizeTwip.Width() * mnMaxImageResolution / 1440.0;
1862 const double fMaxPixelY = aDstSizeTwip.Height() * mnMaxImageResolution / 1440.0;
1864 // check, if the bitmap DPI exceeds the maximum DPI (allow 4 pixel rounding tolerance)
1865 if( ( ( fBmpPixelX > ( fMaxPixelX + 4 ) ) ||
1866 ( fBmpPixelY > ( fMaxPixelY + 4 ) ) ) &&
1867 ( fBmpPixelY > 0.0 ) && ( fMaxPixelY > 0.0 ) )
1869 // do scaling
1870 Size aNewBmpSize;
1871 const double fBmpWH = fBmpPixelX / fBmpPixelY;
1872 const double fMaxWH = fMaxPixelX / fMaxPixelY;
1874 if( fBmpWH < fMaxWH )
1876 aNewBmpSize.Width() = FRound( fMaxPixelY * fBmpWH );
1877 aNewBmpSize.Height() = FRound( fMaxPixelY );
1879 else if( fBmpWH > 0.0 )
1881 aNewBmpSize.Width() = FRound( fMaxPixelX );
1882 aNewBmpSize.Height() = FRound( fMaxPixelX / fBmpWH);
1884 if( aNewBmpSize.Width() && aNewBmpSize.Height() )
1885 aBitmapEx.Scale( aNewBmpSize );
1886 else
1887 aBitmapEx.SetEmpty();
1891 const Size aSizePixel( aBitmapEx.GetSizePixel() );
1892 if ( aSizePixel.Width() && aSizePixel.Height() )
1894 sal_Bool bUseJPGCompression = !mbUseLosslessCompression;
1895 if ( ( aSizePixel.Width() < 32 ) || ( aSizePixel.Height() < 32 ) )
1896 bUseJPGCompression = sal_False;
1898 SvMemoryStream aStrm;
1899 Bitmap aMask;
1901 if ( bUseJPGCompression )
1903 sal_uInt32 nZippedFileSize; // sj: we will calculate the filesize of a zipped bitmap
1904 { // to determine if jpeg compression is usefull
1905 SvMemoryStream aTemp;
1906 aTemp.SetCompressMode( aTemp.GetCompressMode() | COMPRESSMODE_ZBITMAP );
1907 aTemp.SetVersion( SOFFICE_FILEFORMAT_40 ); // sj: up from version 40 our bitmap stream operator
1908 aTemp << aBitmapEx; // is capable of zlib stream compression
1909 aTemp.Seek( STREAM_SEEK_TO_END );
1910 nZippedFileSize = aTemp.Tell();
1912 if ( aBitmapEx.IsTransparent() )
1914 if ( aBitmapEx.IsAlpha() )
1915 aMask = aBitmapEx.GetAlpha().GetBitmap();
1916 else
1917 aMask = aBitmapEx.GetMask();
1919 GraphicFilter aGraphicFilter;
1920 Graphic aGraphic( aBitmapEx.GetBitmap() );
1921 sal_uInt16 nFormatName = aGraphicFilter.GetExportFormatNumberForShortName( OUString( RTL_CONSTASCII_USTRINGPARAM( "JPG" ) ) );
1922 sal_Int32 nColorMode = 0;
1924 Sequence< PropertyValue > aFilterData( 2 );
1925 aFilterData[ 0 ].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "Quality" ) );
1926 aFilterData[ 0 ].Value <<= mnQuality;
1927 aFilterData[ 1 ].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "ColorMode" ) );
1928 aFilterData[ 1 ].Value <<= nColorMode;
1930 /*sal_uInt16 nError =*/ aGraphicFilter.ExportGraphic( aGraphic, String(), aStrm, nFormatName, &aFilterData );
1931 aStrm.Seek( STREAM_SEEK_TO_END );
1932 if ( aStrm.Tell() > nZippedFileSize )
1933 bUseJPGCompression = sal_False;
1935 if ( bUseJPGCompression )
1936 rWriter.DrawJPGBitmap( aStrm, true, aSizePixel, Rectangle( aPoint, aSize ), aMask );
1937 else if ( aBitmapEx.IsTransparent() )
1938 rWriter.DrawBitmapEx( aPoint, aSize, aBitmapEx );
1939 else
1940 rWriter.DrawBitmap( aPoint, aSize, aBitmapEx.GetBitmap() );