update dev300-m58
[ooovba.git] / filter / source / pdf / pdfexport.cxx
blob58188f9584fa775bd52a5c57ea934ce0b1be6986
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 0
1063 if( mbRemoveTransparencies )
1065 bTransparenciesRemoved = rWriter.GetReferenceDevice()->
1066 RemoveTransparenciesFromMetaFile( rInMtf, aMtf, mnMaxImageResolution, mnMaxImageResolution,
1067 false, true, mbReduceImageResolution );
1069 else
1070 #endif
1072 aMtf = rInMtf;
1076 for( sal_uInt32 i = 0, nCount = aMtf.GetActionCount(); i < nCount; )
1078 if ( !pPDFExtOutDevData || !pPDFExtOutDevData->PlaySyncPageAct( rWriter, i ) )
1080 const MetaAction* pAction = aMtf.GetAction( i );
1081 const USHORT nType = pAction->GetType();
1083 switch( nType )
1085 case( META_PIXEL_ACTION ):
1087 const MetaPixelAction* pA = (const MetaPixelAction*) pAction;
1088 rWriter.DrawPixel( pA->GetPoint(), pA->GetColor() );
1090 break;
1092 case( META_POINT_ACTION ):
1094 const MetaPointAction* pA = (const MetaPointAction*) pAction;
1095 rWriter.DrawPixel( pA->GetPoint() );
1097 break;
1099 case( META_LINE_ACTION ):
1101 const MetaLineAction* pA = (const MetaLineAction*) pAction;
1102 if ( pA->GetLineInfo().IsDefault() )
1103 rWriter.DrawLine( pA->GetStartPoint(), pA->GetEndPoint() );
1104 else
1105 rWriter.DrawLine( pA->GetStartPoint(), pA->GetEndPoint(), pA->GetLineInfo() );
1107 break;
1109 case( META_RECT_ACTION ):
1111 const MetaRectAction* pA = (const MetaRectAction*) pAction;
1112 rWriter.DrawRect( pA->GetRect() );
1114 break;
1116 case( META_ROUNDRECT_ACTION ):
1118 const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pAction;
1119 rWriter.DrawRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() );
1121 break;
1123 case( META_ELLIPSE_ACTION ):
1125 const MetaEllipseAction* pA = (const MetaEllipseAction*) pAction;
1126 rWriter.DrawEllipse( pA->GetRect() );
1128 break;
1130 case( META_ARC_ACTION ):
1132 const MetaArcAction* pA = (const MetaArcAction*) pAction;
1133 rWriter.DrawArc( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
1135 break;
1137 case( META_PIE_ACTION ):
1139 const MetaArcAction* pA = (const MetaArcAction*) pAction;
1140 rWriter.DrawPie( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
1142 break;
1144 case( META_CHORD_ACTION ):
1146 const MetaChordAction* pA = (const MetaChordAction*) pAction;
1147 rWriter.DrawChord( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
1149 break;
1151 case( META_POLYGON_ACTION ):
1153 const MetaPolygonAction* pA = (const MetaPolygonAction*) pAction;
1154 rWriter.DrawPolygon( pA->GetPolygon() );
1156 break;
1158 case( META_POLYLINE_ACTION ):
1160 const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pAction;
1161 if ( pA->GetLineInfo().IsDefault() )
1162 rWriter.DrawPolyLine( pA->GetPolygon() );
1163 else
1164 rWriter.DrawPolyLine( pA->GetPolygon(), pA->GetLineInfo() );
1166 break;
1168 case( META_POLYPOLYGON_ACTION ):
1170 const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*) pAction;
1171 rWriter.DrawPolyPolygon( pA->GetPolyPolygon() );
1173 break;
1175 case( META_GRADIENT_ACTION ):
1177 const MetaGradientAction* pA = (const MetaGradientAction*) pAction;
1178 const PolyPolygon aPolyPoly( pA->GetRect() );
1180 ImplWriteGradient( rWriter, aPolyPoly, pA->GetGradient(), rDummyVDev );
1182 break;
1184 case( META_GRADIENTEX_ACTION ):
1186 const MetaGradientExAction* pA = (const MetaGradientExAction*) pAction;
1187 ImplWriteGradient( rWriter, pA->GetPolyPolygon(), pA->GetGradient(), rDummyVDev );
1189 break;
1191 case META_HATCH_ACTION:
1193 const MetaHatchAction* pA = (const MetaHatchAction*) pAction;
1194 rWriter.DrawHatch( pA->GetPolyPolygon(), pA->GetHatch() );
1196 break;
1198 case( META_TRANSPARENT_ACTION ):
1200 const MetaTransparentAction* pA = (const MetaTransparentAction*) pAction;
1201 rWriter.DrawTransparent( pA->GetPolyPolygon(), pA->GetTransparence() );
1203 break;
1205 case( META_FLOATTRANSPARENT_ACTION ):
1207 const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pAction;
1209 GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
1210 const Point& rPos = pA->GetPoint();
1211 const Size& rSize= pA->GetSize();
1212 const Gradient& rTransparenceGradient = pA->GetGradient();
1214 const Size aDstSizeTwip( rDummyVDev.PixelToLogic( rDummyVDev.LogicToPixel( rSize ), MAP_TWIP ) );
1215 sal_Int32 nMaxBmpDPI = mbUseLosslessCompression ? 300 : 72;
1216 if ( mbReduceImageResolution )
1218 if ( nMaxBmpDPI > mnMaxImageResolution )
1219 nMaxBmpDPI = mnMaxImageResolution;
1221 const sal_Int32 nPixelX = (sal_Int32)((double)aDstSizeTwip.Width() * (double)nMaxBmpDPI / 1440.0);
1222 const sal_Int32 nPixelY = (sal_Int32)((double)aDstSizeTwip.Height() * (double)nMaxBmpDPI / 1440.0);
1223 if ( nPixelX && nPixelY )
1225 Size aDstSizePixel( nPixelX, nPixelY );
1226 VirtualDevice* pVDev = new VirtualDevice;
1227 if( pVDev->SetOutputSizePixel( aDstSizePixel ) )
1229 Bitmap aPaint, aMask;
1230 AlphaMask aAlpha;
1231 Point aPoint;
1233 MapMode aMapMode( rDummyVDev.GetMapMode() );
1234 aMapMode.SetOrigin( aPoint );
1235 pVDev->SetMapMode( aMapMode );
1236 Size aDstSize( pVDev->PixelToLogic( aDstSizePixel ) );
1238 Point aMtfOrigin( aTmpMtf.GetPrefMapMode().GetOrigin() );
1239 if ( aMtfOrigin.X() || aMtfOrigin.Y() )
1240 aTmpMtf.Move( -aMtfOrigin.X(), -aMtfOrigin.Y() );
1241 double fScaleX = (double)aDstSize.Width() / (double)aTmpMtf.GetPrefSize().Width();
1242 double fScaleY = (double)aDstSize.Height() / (double)aTmpMtf.GetPrefSize().Height();
1243 if( fScaleX != 1.0 || fScaleY != 1.0 )
1244 aTmpMtf.Scale( fScaleX, fScaleY );
1245 aTmpMtf.SetPrefMapMode( aMapMode );
1247 // create paint bitmap
1248 aTmpMtf.WindStart();
1249 aTmpMtf.Play( pVDev, aPoint, aDstSize );
1250 aTmpMtf.WindStart();
1252 pVDev->EnableMapMode( FALSE );
1253 aPaint = pVDev->GetBitmap( aPoint, aDstSizePixel );
1254 pVDev->EnableMapMode( TRUE );
1256 // create mask bitmap
1257 pVDev->SetLineColor( COL_BLACK );
1258 pVDev->SetFillColor( COL_BLACK );
1259 pVDev->DrawRect( Rectangle( aPoint, aDstSize ) );
1260 pVDev->SetDrawMode( DRAWMODE_WHITELINE | DRAWMODE_WHITEFILL | DRAWMODE_WHITETEXT |
1261 DRAWMODE_WHITEBITMAP | DRAWMODE_WHITEGRADIENT );
1262 aTmpMtf.WindStart();
1263 aTmpMtf.Play( pVDev, aPoint, aDstSize );
1264 aTmpMtf.WindStart();
1265 pVDev->EnableMapMode( FALSE );
1266 aMask = pVDev->GetBitmap( aPoint, aDstSizePixel );
1267 pVDev->EnableMapMode( TRUE );
1269 // create alpha mask from gradient
1270 pVDev->SetDrawMode( DRAWMODE_GRAYGRADIENT );
1271 pVDev->DrawGradient( Rectangle( aPoint, aDstSize ), rTransparenceGradient );
1272 pVDev->SetDrawMode( DRAWMODE_DEFAULT );
1273 pVDev->EnableMapMode( FALSE );
1274 pVDev->DrawMask( aPoint, aDstSizePixel, aMask, Color( COL_WHITE ) );
1275 aAlpha = pVDev->GetBitmap( aPoint, aDstSizePixel );
1276 ImplWriteBitmapEx( rWriter, rDummyVDev, rPos, rSize, BitmapEx( aPaint, aAlpha ) );
1278 delete pVDev;
1281 break;
1283 case( META_EPS_ACTION ):
1285 const MetaEPSAction* pA = (const MetaEPSAction*) pAction;
1286 const GDIMetaFile aSubstitute( pA->GetSubstitute() );
1288 rWriter.Push();
1289 rDummyVDev.Push();
1291 MapMode aMapMode( aSubstitute.GetPrefMapMode() );
1292 Size aOutSize( rDummyVDev.LogicToLogic( pA->GetSize(), rDummyVDev.GetMapMode(), aMapMode ) );
1293 aMapMode.SetScaleX( Fraction( aOutSize.Width(), aSubstitute.GetPrefSize().Width() ) );
1294 aMapMode.SetScaleY( Fraction( aOutSize.Height(), aSubstitute.GetPrefSize().Height() ) );
1295 aMapMode.SetOrigin( rDummyVDev.LogicToLogic( pA->GetPoint(), rDummyVDev.GetMapMode(), aMapMode ) );
1297 rWriter.SetMapMode( aMapMode );
1298 rDummyVDev.SetMapMode( aMapMode );
1299 ImplWriteActions( rWriter, NULL, aSubstitute, rDummyVDev );
1300 rDummyVDev.Pop();
1301 rWriter.Pop();
1303 break;
1305 case( META_COMMENT_ACTION ):
1306 if( ! bTransparenciesRemoved )
1308 const MetaCommentAction* pA = (const MetaCommentAction*) pAction;
1309 String aSkipComment;
1311 if( pA->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_BEGIN" ) == COMPARE_EQUAL )
1313 const MetaGradientExAction* pGradAction = NULL;
1314 sal_Bool bDone = sal_False;
1316 while( !bDone && ( ++i < nCount ) )
1318 pAction = aMtf.GetAction( i );
1320 if( pAction->GetType() == META_GRADIENTEX_ACTION )
1321 pGradAction = (const MetaGradientExAction*) pAction;
1322 else if( ( pAction->GetType() == META_COMMENT_ACTION ) &&
1323 ( ( (const MetaCommentAction*) pAction )->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_END" ) == COMPARE_EQUAL ) )
1325 bDone = sal_True;
1329 if( pGradAction )
1330 ImplWriteGradient( rWriter, pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), rDummyVDev );
1332 else
1334 const BYTE* pData = pA->GetData();
1335 if ( pData )
1337 SvMemoryStream aMemStm( (void*)pData, pA->GetDataSize(), STREAM_READ );
1338 sal_Bool bSkipSequence = sal_False;
1339 ByteString sSeqEnd;
1341 if( pA->GetComment().Equals( "XPATHSTROKE_SEQ_BEGIN" ) )
1343 sSeqEnd = ByteString( "XPATHSTROKE_SEQ_END" );
1344 SvtGraphicStroke aStroke;
1345 aMemStm >> aStroke;
1347 Polygon aPath;
1348 aStroke.getPath( aPath );
1350 PolyPolygon aStartArrow;
1351 PolyPolygon aEndArrow;
1352 double fTransparency( aStroke.getTransparency() );
1353 double fStrokeWidth( aStroke.getStrokeWidth() );
1354 SvtGraphicStroke::JoinType eJT( aStroke.getJoinType() );
1355 SvtGraphicStroke::DashArray aDashArray;
1357 aStroke.getStartArrow( aStartArrow );
1358 aStroke.getEndArrow( aEndArrow );
1359 aStroke.getDashArray( aDashArray );
1361 bSkipSequence = sal_True;
1362 if ( aStartArrow.Count() || aEndArrow.Count() )
1363 bSkipSequence = sal_False;
1364 if ( (sal_uInt32)eJT > 2 )
1365 bSkipSequence = sal_False;
1366 if ( aDashArray.size() && ( fStrokeWidth != 0.0 ) && ( fTransparency == 0.0 ) )
1367 bSkipSequence = sal_False;
1368 if ( bSkipSequence )
1370 PDFWriter::ExtLineInfo aInfo;
1371 aInfo.m_fLineWidth = fStrokeWidth;
1372 aInfo.m_fTransparency = fTransparency;
1373 aInfo.m_fMiterLimit = aStroke.getMiterLimit();
1374 switch( aStroke.getCapType() )
1376 default:
1377 case SvtGraphicStroke::capButt: aInfo.m_eCap = PDFWriter::capButt;break;
1378 case SvtGraphicStroke::capRound: aInfo.m_eCap = PDFWriter::capRound;break;
1379 case SvtGraphicStroke::capSquare: aInfo.m_eCap = PDFWriter::capSquare;break;
1381 switch( aStroke.getJoinType() )
1383 default:
1384 case SvtGraphicStroke::joinMiter: aInfo.m_eJoin = PDFWriter::joinMiter;break;
1385 case SvtGraphicStroke::joinRound: aInfo.m_eJoin = PDFWriter::joinRound;break;
1386 case SvtGraphicStroke::joinBevel: aInfo.m_eJoin = PDFWriter::joinBevel;break;
1387 case SvtGraphicStroke::joinNone:
1388 aInfo.m_eJoin = PDFWriter::joinMiter;
1389 aInfo.m_fMiterLimit = 0.0;
1390 break;
1392 aInfo.m_aDashArray = aDashArray;
1393 rWriter.DrawPolyLine( aPath, aInfo );
1396 else if ( pA->GetComment().Equals( "XPATHFILL_SEQ_BEGIN" ) )
1398 sSeqEnd = ByteString( "XPATHFILL_SEQ_END" );
1399 SvtGraphicFill aFill;
1400 aMemStm >> aFill;
1402 if ( ( aFill.getFillType() == SvtGraphicFill::fillSolid ) && ( aFill.getFillRule() == SvtGraphicFill::fillEvenOdd ) )
1404 double fTransparency = aFill.getTransparency();
1405 if ( fTransparency == 0.0 )
1407 PolyPolygon aPath;
1408 aFill.getPath( aPath );
1410 bSkipSequence = sal_True;
1411 rWriter.DrawPolyPolygon( aPath );
1413 else if ( fTransparency == 1.0 )
1414 bSkipSequence = sal_True;
1416 /* #i81548# removing optimization for fill textures, because most of the texture settings are not
1417 exported properly. In OpenOffice 3.1 the drawing layer will support graphic primitives, then it
1418 will not be a problem to optimize the filltexture export. But for wysiwyg is more important than
1419 filesize.
1420 else if( aFill.getFillType() == SvtGraphicFill::fillTexture && aFill.isTiling() )
1422 sal_Int32 nPattern = mnCachePatternId;
1423 Graphic aPatternGraphic;
1424 aFill.getGraphic( aPatternGraphic );
1425 bool bUseCache = false;
1426 SvtGraphicFill::Transform aPatTransform;
1427 aFill.getTransform( aPatTransform );
1429 if( mnCachePatternId >= 0 )
1431 SvtGraphicFill::Transform aCacheTransform;
1432 maCacheFill.getTransform( aCacheTransform );
1433 if( aCacheTransform.matrix[0] == aPatTransform.matrix[0] &&
1434 aCacheTransform.matrix[1] == aPatTransform.matrix[1] &&
1435 aCacheTransform.matrix[2] == aPatTransform.matrix[2] &&
1436 aCacheTransform.matrix[3] == aPatTransform.matrix[3] &&
1437 aCacheTransform.matrix[4] == aPatTransform.matrix[4] &&
1438 aCacheTransform.matrix[5] == aPatTransform.matrix[5]
1441 Graphic aCacheGraphic;
1442 maCacheFill.getGraphic( aCacheGraphic );
1443 if( aCacheGraphic == aPatternGraphic )
1444 bUseCache = true;
1448 if( ! bUseCache )
1451 // paint graphic to metafile
1452 GDIMetaFile aPattern;
1453 rDummyVDev.SetConnectMetaFile( &aPattern );
1454 rDummyVDev.Push();
1455 rDummyVDev.SetMapMode( aPatternGraphic.GetPrefMapMode() );
1457 aPatternGraphic.Draw( &rDummyVDev, Point( 0, 0 ) );
1458 rDummyVDev.Pop();
1459 rDummyVDev.SetConnectMetaFile( NULL );
1460 aPattern.WindStart();
1462 MapMode aPatternMapMode( aPatternGraphic.GetPrefMapMode() );
1463 // prepare pattern from metafile
1464 Size aPrefSize( aPatternGraphic.GetPrefSize() );
1465 // FIXME: this magic -1 shouldn't be necessary
1466 aPrefSize.Width() -= 1;
1467 aPrefSize.Height() -= 1;
1468 aPrefSize = rWriter.GetReferenceDevice()->
1469 LogicToLogic( aPrefSize,
1470 &aPatternMapMode,
1471 &rWriter.GetReferenceDevice()->GetMapMode() );
1472 // build bounding rectangle of pattern
1473 Rectangle aBound( Point( 0, 0 ), aPrefSize );
1474 rWriter.BeginPattern( aBound );
1475 rWriter.Push();
1476 rDummyVDev.Push();
1477 rWriter.SetMapMode( aPatternMapMode );
1478 rDummyVDev.SetMapMode( aPatternMapMode );
1479 ImplWriteActions( rWriter, NULL, aPattern, rDummyVDev );
1480 rDummyVDev.Pop();
1481 rWriter.Pop();
1483 nPattern = rWriter.EndPattern( aPatTransform );
1485 // try some caching and reuse pattern
1486 mnCachePatternId = nPattern;
1487 maCacheFill = aFill;
1490 // draw polypolygon with pattern fill
1491 PolyPolygon aPath;
1492 aFill.getPath( aPath );
1493 rWriter.DrawPolyPolygon( aPath, nPattern, aFill.getFillRule() == SvtGraphicFill::fillEvenOdd );
1495 bSkipSequence = sal_True;
1499 if ( bSkipSequence )
1501 while( ++i < nCount )
1503 pAction = aMtf.GetAction( i );
1504 if ( pAction->GetType() == META_COMMENT_ACTION )
1506 ByteString sComment( ((MetaCommentAction*)pAction)->GetComment() );
1507 if ( sComment.Equals( sSeqEnd ) )
1508 break;
1510 // #i44496#
1511 // the replacement action for stroke is a filled rectangle
1512 // the set fillcolor of the replacement is part of the graphics
1513 // state and must not be skipped
1514 else if( pAction->GetType() == META_FILLCOLOR_ACTION )
1516 const MetaFillColorAction* pMA = (const MetaFillColorAction*) pAction;
1517 if( pMA->IsSetting() )
1518 rWriter.SetFillColor( pMA->GetColor() );
1519 else
1520 rWriter.SetFillColor();
1527 break;
1529 case( META_BMP_ACTION ):
1531 const MetaBmpAction* pA = (const MetaBmpAction*) pAction;
1532 BitmapEx aBitmapEx( pA->GetBitmap() );
1533 Size aSize( OutputDevice::LogicToLogic( aBitmapEx.GetPrefSize(),
1534 aBitmapEx.GetPrefMapMode(), rDummyVDev.GetMapMode() ) );
1535 if( ! ( aSize.Width() && aSize.Height() ) )
1536 aSize = rDummyVDev.PixelToLogic( aBitmapEx.GetSizePixel() );
1537 ImplWriteBitmapEx( rWriter, rDummyVDev, pA->GetPoint(), aSize, aBitmapEx );
1539 break;
1541 case( META_BMPSCALE_ACTION ):
1543 const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
1544 ImplWriteBitmapEx( rWriter, rDummyVDev, pA->GetPoint(), pA->GetSize(), BitmapEx( pA->GetBitmap() ) );
1546 break;
1548 case( META_BMPSCALEPART_ACTION ):
1550 const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pAction;
1551 BitmapEx aBitmapEx( pA->GetBitmap() );
1552 aBitmapEx.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
1553 ImplWriteBitmapEx( rWriter, rDummyVDev, pA->GetDestPoint(), pA->GetDestSize(), aBitmapEx );
1555 break;
1557 case( META_BMPEX_ACTION ):
1559 const MetaBmpExAction* pA = (const MetaBmpExAction*) pAction;
1560 BitmapEx aBitmapEx( pA->GetBitmapEx() );
1561 Size aSize( OutputDevice::LogicToLogic( aBitmapEx.GetPrefSize(),
1562 aBitmapEx.GetPrefMapMode(), rDummyVDev.GetMapMode() ) );
1563 ImplWriteBitmapEx( rWriter, rDummyVDev, pA->GetPoint(), aSize, aBitmapEx );
1565 break;
1567 case( META_BMPEXSCALE_ACTION ):
1569 const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
1570 ImplWriteBitmapEx( rWriter, rDummyVDev, pA->GetPoint(), pA->GetSize(), pA->GetBitmapEx() );
1572 break;
1574 case( META_BMPEXSCALEPART_ACTION ):
1576 const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pAction;
1577 BitmapEx aBitmapEx( pA->GetBitmapEx() );
1578 aBitmapEx.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
1579 ImplWriteBitmapEx( rWriter, rDummyVDev, pA->GetDestPoint(), pA->GetDestSize(), aBitmapEx );
1581 break;
1583 case( META_MASK_ACTION ):
1584 case( META_MASKSCALE_ACTION ):
1585 case( META_MASKSCALEPART_ACTION ):
1587 DBG_ERROR( "MetaMask...Action not supported yet" );
1589 break;
1591 case( META_TEXT_ACTION ):
1593 const MetaTextAction* pA = (const MetaTextAction*) pAction;
1594 rWriter.DrawText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ) );
1596 break;
1598 case( META_TEXTRECT_ACTION ):
1600 const MetaTextRectAction* pA = (const MetaTextRectAction*) pAction;
1601 rWriter.DrawText( pA->GetRect(), String( pA->GetText() ), pA->GetStyle() );
1603 break;
1605 case( META_TEXTARRAY_ACTION ):
1607 const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pAction;
1608 rWriter.DrawTextArray( pA->GetPoint(), pA->GetText(), pA->GetDXArray(), pA->GetIndex(), pA->GetLen() );
1610 break;
1612 case( META_STRETCHTEXT_ACTION ):
1614 const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pAction;
1615 rWriter.DrawStretchText( pA->GetPoint(), pA->GetWidth(), pA->GetText(), pA->GetIndex(), pA->GetLen() );
1617 break;
1620 case( META_TEXTLINE_ACTION ):
1622 const MetaTextLineAction* pA = (const MetaTextLineAction*) pAction;
1623 rWriter.DrawTextLine( pA->GetStartPoint(), pA->GetWidth(), pA->GetStrikeout(), pA->GetUnderline(), pA->GetOverline() );
1626 break;
1628 case( META_CLIPREGION_ACTION ):
1630 const MetaClipRegionAction* pA = (const MetaClipRegionAction*) pAction;
1632 if( pA->IsClipping() )
1633 rWriter.SetClipRegion( pA->GetRegion() );
1634 else
1635 rWriter.SetClipRegion();
1637 break;
1639 case( META_ISECTRECTCLIPREGION_ACTION ):
1641 const MetaISectRectClipRegionAction* pA = (const MetaISectRectClipRegionAction*) pAction;
1642 rWriter.IntersectClipRegion( pA->GetRect() );
1644 break;
1646 case( META_ISECTREGIONCLIPREGION_ACTION ):
1648 const MetaISectRegionClipRegionAction* pA = (const MetaISectRegionClipRegionAction*) pAction;
1649 rWriter.IntersectClipRegion( pA->GetRegion() );
1651 break;
1653 case( META_MOVECLIPREGION_ACTION ):
1655 const MetaMoveClipRegionAction* pA = (const MetaMoveClipRegionAction*) pAction;
1656 rWriter.MoveClipRegion( pA->GetHorzMove(), pA->GetVertMove() );
1658 break;
1660 case( META_MAPMODE_ACTION ):
1662 const_cast< MetaAction* >( pAction )->Execute( &rDummyVDev );
1663 rWriter.SetMapMode( rDummyVDev.GetMapMode() );
1665 break;
1667 case( META_LINECOLOR_ACTION ):
1669 const MetaLineColorAction* pA = (const MetaLineColorAction*) pAction;
1671 if( pA->IsSetting() )
1672 rWriter.SetLineColor( pA->GetColor() );
1673 else
1674 rWriter.SetLineColor();
1676 break;
1678 case( META_FILLCOLOR_ACTION ):
1680 const MetaFillColorAction* pA = (const MetaFillColorAction*) pAction;
1682 if( pA->IsSetting() )
1683 rWriter.SetFillColor( pA->GetColor() );
1684 else
1685 rWriter.SetFillColor();
1687 break;
1689 case( META_TEXTLINECOLOR_ACTION ):
1691 const MetaTextLineColorAction* pA = (const MetaTextLineColorAction*) pAction;
1693 if( pA->IsSetting() )
1694 rWriter.SetTextLineColor( pA->GetColor() );
1695 else
1696 rWriter.SetTextLineColor();
1698 break;
1700 case( META_OVERLINECOLOR_ACTION ):
1702 const MetaOverlineColorAction* pA = (const MetaOverlineColorAction*) pAction;
1704 if( pA->IsSetting() )
1705 rWriter.SetOverlineColor( pA->GetColor() );
1706 else
1707 rWriter.SetOverlineColor();
1709 break;
1711 case( META_TEXTFILLCOLOR_ACTION ):
1713 const MetaTextFillColorAction* pA = (const MetaTextFillColorAction*) pAction;
1715 if( pA->IsSetting() )
1716 rWriter.SetTextFillColor( pA->GetColor() );
1717 else
1718 rWriter.SetTextFillColor();
1720 break;
1722 case( META_TEXTCOLOR_ACTION ):
1724 const MetaTextColorAction* pA = (const MetaTextColorAction*) pAction;
1725 rWriter.SetTextColor( pA->GetColor() );
1727 break;
1729 case( META_TEXTALIGN_ACTION ):
1731 const MetaTextAlignAction* pA = (const MetaTextAlignAction*) pAction;
1732 rWriter.SetTextAlign( pA->GetTextAlign() );
1734 break;
1736 case( META_FONT_ACTION ):
1738 const MetaFontAction* pA = (const MetaFontAction*) pAction;
1739 rWriter.SetFont( pA->GetFont() );
1741 break;
1743 case( META_PUSH_ACTION ):
1745 const MetaPushAction* pA = (const MetaPushAction*) pAction;
1747 rDummyVDev.Push( pA->GetFlags() );
1748 rWriter.Push( pA->GetFlags() );
1750 break;
1752 case( META_POP_ACTION ):
1754 rDummyVDev.Pop();
1755 rWriter.Pop();
1757 break;
1759 case( META_LAYOUTMODE_ACTION ):
1761 const MetaLayoutModeAction* pA = (const MetaLayoutModeAction*) pAction;
1762 rWriter.SetLayoutMode( pA->GetLayoutMode() );
1764 break;
1766 case META_TEXTLANGUAGE_ACTION:
1768 const MetaTextLanguageAction* pA = (const MetaTextLanguageAction*) pAction;
1769 rWriter.SetDigitLanguage( pA->GetTextLanguage() );
1771 break;
1773 case( META_WALLPAPER_ACTION ):
1775 const MetaWallpaperAction* pA = (const MetaWallpaperAction*) pAction;
1776 rWriter.DrawWallpaper( pA->GetRect(), pA->GetWallpaper() );
1778 break;
1780 case( META_RASTEROP_ACTION ):
1782 // !!! >>> we don't want to support this actions
1784 break;
1786 case( META_REFPOINT_ACTION ):
1788 // !!! >>> we don't want to support this actions
1790 break;
1792 default:
1793 // #i24604# Made assertion fire only once per
1794 // metafile. The asserted actions here are all
1795 // deprecated
1796 if( !bAssertionFired )
1798 bAssertionFired = true;
1799 DBG_ERROR( "PDFExport::ImplWriteActions: deprecated and unsupported MetaAction encountered" );
1801 break;
1803 i++;
1807 return sal_True;
1810 // -----------------------------------------------------------------------------
1812 void PDFExport::ImplWriteGradient( PDFWriter& rWriter, const PolyPolygon& rPolyPoly, const Gradient& rGradient, VirtualDevice& rDummyVDev )
1814 GDIMetaFile aTmpMtf;
1816 rDummyVDev.AddGradientActions( rPolyPoly.GetBoundRect(), rGradient, aTmpMtf );
1818 rWriter.Push();
1819 rWriter.IntersectClipRegion( rPolyPoly );
1820 ImplWriteActions( rWriter, NULL, aTmpMtf, rDummyVDev );
1821 rWriter.Pop();
1824 // -----------------------------------------------------------------------------
1826 void PDFExport::ImplWriteBitmapEx( PDFWriter& rWriter, VirtualDevice& rDummyVDev,
1827 const Point& rPoint, const Size& rSize, const BitmapEx& rBitmapEx )
1829 if ( !rBitmapEx.IsEmpty() && rSize.Width() && rSize.Height() )
1831 BitmapEx aBitmapEx( rBitmapEx );
1832 Point aPoint( rPoint );
1833 Size aSize( rSize );
1835 // #i19065# Negative sizes have mirror semantics on
1836 // OutputDevice. BitmapEx and co. have no idea about that, so
1837 // perform that _before_ doing anything with aBitmapEx.
1838 ULONG nMirrorFlags(BMP_MIRROR_NONE);
1839 if( aSize.Width() < 0 )
1841 aSize.Width() *= -1;
1842 aPoint.X() -= aSize.Width();
1843 nMirrorFlags |= BMP_MIRROR_HORZ;
1845 if( aSize.Height() < 0 )
1847 aSize.Height() *= -1;
1848 aPoint.Y() -= aSize.Height();
1849 nMirrorFlags |= BMP_MIRROR_VERT;
1852 if( nMirrorFlags != BMP_MIRROR_NONE )
1854 aBitmapEx.Mirror( nMirrorFlags );
1856 if ( mbReduceImageResolution )
1858 // do downsampling if neccessary
1859 const Size aDstSizeTwip( rDummyVDev.PixelToLogic( rDummyVDev.LogicToPixel( aSize ), MAP_TWIP ) );
1860 const Size aBmpSize( aBitmapEx.GetSizePixel() );
1861 const double fBmpPixelX = aBmpSize.Width();
1862 const double fBmpPixelY = aBmpSize.Height();
1863 const double fMaxPixelX = aDstSizeTwip.Width() * mnMaxImageResolution / 1440.0;
1864 const double fMaxPixelY = aDstSizeTwip.Height() * mnMaxImageResolution / 1440.0;
1866 // check, if the bitmap DPI exceeds the maximum DPI (allow 4 pixel rounding tolerance)
1867 if( ( ( fBmpPixelX > ( fMaxPixelX + 4 ) ) ||
1868 ( fBmpPixelY > ( fMaxPixelY + 4 ) ) ) &&
1869 ( fBmpPixelY > 0.0 ) && ( fMaxPixelY > 0.0 ) )
1871 // do scaling
1872 Size aNewBmpSize;
1873 const double fBmpWH = fBmpPixelX / fBmpPixelY;
1874 const double fMaxWH = fMaxPixelX / fMaxPixelY;
1876 if( fBmpWH < fMaxWH )
1878 aNewBmpSize.Width() = FRound( fMaxPixelY * fBmpWH );
1879 aNewBmpSize.Height() = FRound( fMaxPixelY );
1881 else if( fBmpWH > 0.0 )
1883 aNewBmpSize.Width() = FRound( fMaxPixelX );
1884 aNewBmpSize.Height() = FRound( fMaxPixelX / fBmpWH);
1886 if( aNewBmpSize.Width() && aNewBmpSize.Height() )
1887 aBitmapEx.Scale( aNewBmpSize );
1888 else
1889 aBitmapEx.SetEmpty();
1893 const Size aSizePixel( aBitmapEx.GetSizePixel() );
1894 if ( aSizePixel.Width() && aSizePixel.Height() )
1896 sal_Bool bUseJPGCompression = !mbUseLosslessCompression;
1897 if ( ( aSizePixel.Width() < 32 ) || ( aSizePixel.Height() < 32 ) )
1898 bUseJPGCompression = sal_False;
1900 SvMemoryStream aStrm;
1901 Bitmap aMask;
1903 if ( bUseJPGCompression )
1905 sal_uInt32 nZippedFileSize; // sj: we will calculate the filesize of a zipped bitmap
1906 { // to determine if jpeg compression is usefull
1907 SvMemoryStream aTemp;
1908 aTemp.SetCompressMode( aTemp.GetCompressMode() | COMPRESSMODE_ZBITMAP );
1909 aTemp.SetVersion( SOFFICE_FILEFORMAT_40 ); // sj: up from version 40 our bitmap stream operator
1910 aTemp << aBitmapEx; // is capable of zlib stream compression
1911 aTemp.Seek( STREAM_SEEK_TO_END );
1912 nZippedFileSize = aTemp.Tell();
1914 if ( aBitmapEx.IsTransparent() )
1916 if ( aBitmapEx.IsAlpha() )
1917 aMask = aBitmapEx.GetAlpha().GetBitmap();
1918 else
1919 aMask = aBitmapEx.GetMask();
1921 GraphicFilter aGraphicFilter;
1922 Graphic aGraphic( aBitmapEx.GetBitmap() );
1923 sal_uInt16 nFormatName = aGraphicFilter.GetExportFormatNumberForShortName( OUString( RTL_CONSTASCII_USTRINGPARAM( "JPG" ) ) );
1924 sal_Int32 nColorMode = 0;
1926 Sequence< PropertyValue > aFilterData( 2 );
1927 aFilterData[ 0 ].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "Quality" ) );
1928 aFilterData[ 0 ].Value <<= mnQuality;
1929 aFilterData[ 1 ].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "ColorMode" ) );
1930 aFilterData[ 1 ].Value <<= nColorMode;
1932 /*sal_uInt16 nError =*/ aGraphicFilter.ExportGraphic( aGraphic, String(), aStrm, nFormatName, &aFilterData );
1933 aStrm.Seek( STREAM_SEEK_TO_END );
1934 if ( aStrm.Tell() > nZippedFileSize )
1935 bUseJPGCompression = sal_False;
1937 if ( bUseJPGCompression )
1938 rWriter.DrawJPGBitmap( aStrm, true, aSizePixel, Rectangle( aPoint, aSize ), aMask );
1939 else if ( aBitmapEx.IsTransparent() )
1940 rWriter.DrawBitmapEx( aPoint, aSize, aBitmapEx );
1941 else
1942 rWriter.DrawBitmap( aPoint, aSize, aBitmapEx.GetBitmap() );