update credits
[LibreOffice.git] / filter / source / pdf / pdfexport.cxx
blobe771a0d249b08a05a67515e1d80f1d3a4fb2b84b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "pdfexport.hxx"
22 #include "impdialog.hxx"
24 #include "pdf.hrc"
25 #include "tools/urlobj.hxx"
26 #include "tools/fract.hxx"
27 #include "tools/poly.hxx"
28 #include "vcl/mapmod.hxx"
29 #include "vcl/virdev.hxx"
30 #include "vcl/metaact.hxx"
31 #include "vcl/gdimtf.hxx"
32 #include "vcl/jobset.hxx"
33 #include "vcl/bmpacc.hxx"
34 #include "vcl/svapp.hxx"
35 #include "toolkit/awt/vclxdevice.hxx"
36 #include "unotools/localfilehelper.hxx"
37 #include <vcl/FilterConfigItem.hxx>
38 #include <vcl/graphicfilter.hxx>
39 #include "svl/solar.hrc"
40 #include "comphelper/string.hxx"
41 #include "comphelper/storagehelper.hxx"
42 #include "unotools/streamwrap.hxx"
43 #include "com/sun/star/io/XSeekable.hpp"
45 #include "basegfx/polygon/b2dpolygon.hxx"
46 #include "basegfx/polygon/b2dpolypolygon.hxx"
47 #include "basegfx/polygon/b2dpolygontools.hxx"
49 #include "unotools/saveopt.hxx" // only for testing of relative saving options in PDF
51 #include "vcl/graphictools.hxx"
52 #include "com/sun/star/beans/XPropertySet.hpp"
53 #include "com/sun/star/configuration/theDefaultProvider.hpp"
54 #include "com/sun/star/awt/Rectangle.hpp"
55 #include "com/sun/star/awt/XDevice.hpp"
56 #include "com/sun/star/util/MeasureUnit.hpp"
57 #include "com/sun/star/frame/XModel.hpp"
58 #include "com/sun/star/frame/ModuleManager.hpp"
59 #include "com/sun/star/frame/XStorable.hpp"
60 #include "com/sun/star/frame/XController.hpp"
61 #include "com/sun/star/document/XDocumentProperties.hpp"
62 #include "com/sun/star/document/XDocumentPropertiesSupplier.hpp"
63 #include "com/sun/star/container/XNameAccess.hpp"
64 #include "com/sun/star/view/XViewSettingsSupplier.hpp"
65 #include "com/sun/star/task/XInteractionRequest.hpp"
66 #include "com/sun/star/task/PDFExportException.hpp"
68 #include "unotools/configmgr.hxx"
69 #include "cppuhelper/exc_hlp.hxx"
70 #include "cppuhelper/compbase1.hxx"
71 #include "cppuhelper/basemutex.hxx"
73 #include "com/sun/star/lang/XServiceInfo.hpp"
74 #include "com/sun/star/drawing/XShapes.hpp"
75 #include "com/sun/star/graphic/XGraphicProvider.hpp"
77 using namespace ::rtl;
78 using namespace ::vcl;
79 using namespace ::com::sun::star;
80 using namespace ::com::sun::star::uno;
81 using namespace ::com::sun::star::lang;
82 using namespace ::com::sun::star::beans;
83 using namespace ::com::sun::star::view;
84 using namespace ::com::sun::star::graphic;
86 // -------------
87 // - PDFExport -
88 // -------------
90 PDFExport::PDFExport( const Reference< XComponent >& rxSrcDoc,
91 const Reference< task::XStatusIndicator >& rxStatusIndicator,
92 const Reference< task::XInteractionHandler >& rxIH,
93 const Reference< lang::XMultiServiceFactory >& xFactory ) :
94 mxSrcDoc ( rxSrcDoc ),
95 mxMSF ( xFactory ),
96 mxStatusIndicator ( rxStatusIndicator ),
97 mxIH ( rxIH ),
98 mbUseTaggedPDF ( sal_False ),
99 mnPDFTypeSelection ( 0 ),
100 mbExportNotes ( sal_True ),
101 mbViewPDF ( sal_True ),
102 mbExportNotesPages ( sal_False ),
103 mbEmbedStandardFonts ( sal_False ),//in preparation for i54636 and i76458.
104 //already used for i59651 (PDF/A-1)
105 mbUseTransitionEffects ( sal_True ),
106 mbExportBookmarks ( sal_True ),
107 mbExportHiddenSlides ( sal_False ),
108 mnOpenBookmarkLevels ( -1 ),
109 mbUseLosslessCompression ( sal_False ),
110 mbReduceImageResolution ( sal_False ),
111 mbSkipEmptyPages ( sal_True ),
112 mbAddStream ( sal_False ),
113 mnMaxImageResolution ( 300 ),
114 mnQuality ( 90 ),
115 mnFormsFormat ( 0 ),
116 mbExportFormFields ( sal_True ),
117 mbAllowDuplicateFieldNames ( sal_False ),
118 mnProgressValue ( 0 ),
119 mbRemoveTransparencies ( sal_False ),
120 mbWatermark ( sal_False ),
122 mbHideViewerToolbar ( sal_False ),
123 mbHideViewerMenubar ( sal_False ),
124 mbHideViewerWindowControls ( sal_False ),
125 mbFitWindow ( sal_False ),
126 mbCenterWindow ( sal_False ),
127 mbOpenInFullScreenMode ( sal_False ),
128 mbDisplayPDFDocumentTitle ( sal_True ),
129 mnPDFDocumentMode ( 0 ),
130 mnPDFDocumentAction ( 0 ),
131 mnZoom ( 100 ),
132 mnInitialPage ( 1 ),
133 mnPDFPageLayout ( 0 ),
134 mbFirstPageLeft ( sal_False ),
136 mbEncrypt ( sal_False ),
137 mbRestrictPermissions ( sal_False ),
138 mnPrintAllowed ( 2 ),
139 mnChangesAllowed ( 4 ),
140 mbCanCopyOrExtract ( sal_True ),
141 mbCanExtractForAccessibility( sal_True ),
143 //--->i56629
144 mbExportRelativeFsysLinks ( sal_False ),
145 mnDefaultLinkAction ( 0 ),
146 mbConvertOOoTargetToPDFTarget( sal_False ),
147 mbExportBmkToDest ( sal_False ),
148 mbSignPDF ( false )
152 // -----------------------------------------------------------------------------
154 PDFExport::~PDFExport()
158 // -----------------------------------------------------------------------------
160 sal_Bool PDFExport::ExportSelection( vcl::PDFWriter& rPDFWriter,
161 Reference< com::sun::star::view::XRenderable >& rRenderable,
162 const Any& rSelection,
163 const StringRangeEnumerator& rRangeEnum,
164 Sequence< PropertyValue >& rRenderOptions,
165 sal_Int32 nPageCount )
167 sal_Bool bRet = sal_False;
170 Any* pFirstPage = NULL;
171 Any* pLastPage = NULL;
173 sal_Bool bExportNotesPages = sal_False;
175 for( sal_Int32 nData = 0, nDataCount = rRenderOptions.getLength(); nData < nDataCount; ++nData )
177 if ( rRenderOptions[ nData ].Name == "IsFirstPage" )
178 pFirstPage = &rRenderOptions[ nData ].Value;
179 else if ( rRenderOptions[ nData ].Name == "IsLastPage" )
180 pLastPage = &rRenderOptions[ nData ].Value;
181 else if ( rRenderOptions[ nData ].Name == "ExportNotesPages" )
182 rRenderOptions[ nData ].Value >>= bExportNotesPages;
185 OutputDevice* pOut = rPDFWriter.GetReferenceDevice();
187 if( pOut )
189 vcl::PDFExtOutDevData* pPDFExtOutDevData = PTR_CAST( vcl::PDFExtOutDevData, pOut->GetExtOutDevData() );
190 if ( nPageCount )
192 pPDFExtOutDevData->SetIsExportNotesPages( bExportNotesPages );
194 sal_Int32 nCurrentPage(0);
195 StringRangeEnumerator::Iterator aIter = rRangeEnum.begin();
196 StringRangeEnumerator::Iterator aEnd = rRangeEnum.end();
197 while ( aIter != aEnd )
199 Sequence< PropertyValue > aRenderer( rRenderable->getRenderer( *aIter, rSelection, rRenderOptions ) );
200 awt::Size aPageSize;
202 for( sal_Int32 nProperty = 0, nPropertyCount = aRenderer.getLength(); nProperty < nPropertyCount; ++nProperty )
204 if ( aRenderer[ nProperty ].Name == "PageSize" )
205 aRenderer[ nProperty].Value >>= aPageSize;
208 pPDFExtOutDevData->SetCurrentPageNumber( nCurrentPage );
210 GDIMetaFile aMtf;
211 const MapMode aMapMode( MAP_100TH_MM );
212 const Size aMtfSize( aPageSize.Width, aPageSize.Height );
214 pOut->Push();
215 pOut->EnableOutput( sal_False );
216 pOut->SetMapMode( aMapMode );
218 aMtf.SetPrefSize( aMtfSize );
219 aMtf.SetPrefMapMode( aMapMode );
220 aMtf.Record( pOut );
222 // #i35176#
223 // IsLastPage property.
224 const sal_Int32 nCurrentRenderer = *aIter;
225 ++aIter;
226 if ( pLastPage && aIter == aEnd )
227 *pLastPage <<= sal_True;
229 rRenderable->render( nCurrentRenderer, rSelection, rRenderOptions );
231 aMtf.Stop();
232 aMtf.WindStart();
234 if( aMtf.GetActionSize() &&
235 ( !mbSkipEmptyPages || aPageSize.Width || aPageSize.Height ) )
236 bRet = ImplExportPage( rPDFWriter, *pPDFExtOutDevData, aMtf ) || bRet;
238 pOut->Pop();
240 if ( mxStatusIndicator.is() )
241 mxStatusIndicator->setValue( mnProgressValue );
242 if ( pFirstPage )
243 *pFirstPage <<= sal_False;
245 ++mnProgressValue;
246 ++nCurrentPage;
249 else
251 bRet = sal_True; // #i18334# SJ: nPageCount == 0,
252 rPDFWriter.NewPage( 10000, 10000 ); // creating dummy page
253 rPDFWriter.SetMapMode( MAP_100TH_MM ); //
257 catch(const RuntimeException &)
260 return bRet;
263 class PDFExportStreamDoc : public vcl::PDFOutputStream
265 Reference< XComponent > m_xSrcDoc;
266 Sequence< beans::NamedValue > m_aPreparedPassword;
267 public:
268 PDFExportStreamDoc( const Reference< XComponent >& xDoc, const Sequence<beans::NamedValue>& rPwd )
269 : m_xSrcDoc( xDoc ),
270 m_aPreparedPassword( rPwd )
272 virtual ~PDFExportStreamDoc();
274 virtual void write( const Reference< XOutputStream >& xStream );
277 PDFExportStreamDoc::~PDFExportStreamDoc()
281 void PDFExportStreamDoc::write( const Reference< XOutputStream >& xStream )
283 Reference< com::sun::star::frame::XStorable > xStore( m_xSrcDoc, UNO_QUERY );
284 if( xStore.is() )
286 Sequence< beans::PropertyValue > aArgs( 2 + ((m_aPreparedPassword.getLength() > 0) ? 1 : 0) );
287 aArgs.getArray()[0].Name = "FilterName";
288 aArgs.getArray()[1].Name = "OutputStream";
289 aArgs.getArray()[1].Value <<= xStream;
290 if( m_aPreparedPassword.getLength() )
292 aArgs.getArray()[2].Name = "EncryptionData";
293 aArgs.getArray()[2].Value <<= m_aPreparedPassword;
298 xStore->storeToURL( "private:stream", aArgs );
300 catch( const IOException& )
306 static OUString getMimetypeForDocument( const Reference< XMultiServiceFactory >& xFactory,
307 const Reference< XComponent >& xDoc ) throw()
309 OUString aDocMimetype;
310 // get document service name
311 Reference< com::sun::star::frame::XStorable > xStore( xDoc, UNO_QUERY );
312 Reference< frame::XModuleManager2 > xModuleManager( frame::ModuleManager::create(comphelper::getComponentContext( xFactory )) );
313 if( xStore.is() )
315 OUString aDocServiceName = xModuleManager->identify( Reference< XInterface >( xStore, uno::UNO_QUERY ) );
316 if ( !aDocServiceName.isEmpty() )
318 // get the actual filter name
319 OUString aFilterName;
320 Reference< lang::XMultiServiceFactory > xConfigProvider(
321 configuration::theDefaultProvider::get(
322 comphelper::getComponentContext( xFactory ) ) );
323 uno::Sequence< uno::Any > aArgs( 1 );
324 beans::NamedValue aPathProp;
325 aPathProp.Name = "nodepath";
326 aPathProp.Value <<= OUString( "/org.openoffice.Setup/Office/Factories/" );
327 aArgs[0] <<= aPathProp;
329 Reference< container::XNameAccess > xSOFConfig(
330 xConfigProvider->createInstanceWithArguments(
331 "com.sun.star.configuration.ConfigurationAccess", aArgs ),
332 uno::UNO_QUERY );
334 Reference< container::XNameAccess > xApplConfig;
335 xSOFConfig->getByName( aDocServiceName ) >>= xApplConfig;
336 if ( xApplConfig.is() )
338 xApplConfig->getByName( "ooSetupFactoryActualFilter" ) >>= aFilterName;
339 if( !aFilterName.isEmpty() )
341 // find the related type name
342 OUString aTypeName;
343 Reference< container::XNameAccess > xFilterFactory(
344 xFactory->createInstance( "com.sun.star.document.FilterFactory" ),
345 uno::UNO_QUERY );
347 Sequence< beans::PropertyValue > aFilterData;
348 xFilterFactory->getByName( aFilterName ) >>= aFilterData;
349 for ( sal_Int32 nInd = 0; nInd < aFilterData.getLength(); nInd++ )
350 if ( aFilterData[nInd].Name == "Type" )
351 aFilterData[nInd].Value >>= aTypeName;
353 if ( !aTypeName.isEmpty() )
355 // find the mediatype
356 Reference< container::XNameAccess > xTypeDetection(
357 xFactory->createInstance( "com.sun.star.document.TypeDetection" ),
358 UNO_QUERY );
360 Sequence< beans::PropertyValue > aTypeData;
361 xTypeDetection->getByName( aTypeName ) >>= aTypeData;
362 for ( sal_Int32 nInd = 0; nInd < aTypeData.getLength(); nInd++ )
363 if ( aTypeData[nInd].Name == "MediaType" )
364 aTypeData[nInd].Value >>= aDocMimetype;
370 return aDocMimetype;
373 sal_Bool PDFExport::Export( const OUString& rFile, const Sequence< PropertyValue >& rFilterData )
375 INetURLObject aURL( rFile );
376 sal_Bool bRet = sal_False;
378 std::set< PDFWriter::ErrorCode > aErrors;
380 if( aURL.GetProtocol() != INET_PROT_FILE )
382 OUString aTmp;
384 if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( rFile, aTmp ) )
385 aURL = INetURLObject(aTmp);
388 if( aURL.GetProtocol() == INET_PROT_FILE )
390 Reference< XRenderable > xRenderable( mxSrcDoc, UNO_QUERY );
392 if( xRenderable.is() )
394 VCLXDevice* pXDevice = new VCLXDevice;
395 OUString aPageRange;
396 Any aSelection;
397 PDFWriter::PDFWriterContext aContext;
398 OUString aOpenPassword, aPermissionPassword;
399 Reference< beans::XMaterialHolder > xEnc;
400 Sequence< beans::NamedValue > aPreparedPermissionPassword;
403 // getting the string for the creator
404 OUString aCreator;
405 Reference< XServiceInfo > xInfo( mxSrcDoc, UNO_QUERY );
406 if ( xInfo.is() )
408 if ( xInfo->supportsService( "com.sun.star.presentation.PresentationDocument" ) )
409 aCreator += "Impress";
410 else if ( xInfo->supportsService( "com.sun.star.drawing.DrawingDocument" ) )
411 aCreator += "Draw";
412 else if ( xInfo->supportsService( "com.sun.star.text.TextDocument" ) )
413 aCreator += "Writer";
414 else if ( xInfo->supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) )
415 aCreator += "Calc";
416 else if ( xInfo->supportsService( "com.sun.star.formula.FormulaProperties" ) )
417 aCreator += "Math";
420 Reference< document::XDocumentPropertiesSupplier > xDocumentPropsSupplier( mxSrcDoc, UNO_QUERY );
421 if ( xDocumentPropsSupplier.is() )
423 Reference< document::XDocumentProperties > xDocumentProps( xDocumentPropsSupplier->getDocumentProperties() );
424 if ( xDocumentProps.is() )
426 aContext.DocumentInfo.Title = xDocumentProps->getTitle();
427 aContext.DocumentInfo.Author = xDocumentProps->getAuthor();
428 aContext.DocumentInfo.Subject = xDocumentProps->getSubject();
429 aContext.DocumentInfo.Keywords = ::comphelper::string::convertCommaSeparated(xDocumentProps->getKeywords());
432 // getting the string for the producer
433 aContext.DocumentInfo.Producer =
434 utl::ConfigManager::getProductName() +
435 " " +
436 utl::ConfigManager::getProductVersion();
437 aContext.DocumentInfo.Creator = aCreator;
439 for( sal_Int32 nData = 0, nDataCount = rFilterData.getLength(); nData < nDataCount; ++nData )
441 if ( rFilterData[ nData ].Name == "PageRange" )
442 rFilterData[ nData ].Value >>= aPageRange;
443 else if ( rFilterData[ nData ].Name == "Selection" )
444 rFilterData[ nData ].Value >>= aSelection;
445 else if ( rFilterData[ nData ].Name == "UseLosslessCompression" )
446 rFilterData[ nData ].Value >>= mbUseLosslessCompression;
447 else if ( rFilterData[ nData ].Name == "Quality" )
448 rFilterData[ nData ].Value >>= mnQuality;
449 else if ( rFilterData[ nData ].Name == "ReduceImageResolution" )
450 rFilterData[ nData ].Value >>= mbReduceImageResolution;
451 else if ( rFilterData[ nData ].Name == "IsSkipEmptyPages" )
452 rFilterData[ nData ].Value >>= mbSkipEmptyPages;
453 else if ( rFilterData[ nData ].Name == "MaxImageResolution" )
454 rFilterData[ nData ].Value >>= mnMaxImageResolution;
455 else if ( rFilterData[ nData ].Name == "UseTaggedPDF" )
456 rFilterData[ nData ].Value >>= mbUseTaggedPDF;
457 else if ( rFilterData[ nData ].Name == "SelectPdfVersion" )
458 rFilterData[ nData ].Value >>= mnPDFTypeSelection;
459 else if ( rFilterData[ nData ].Name == "ExportNotes" )
460 rFilterData[ nData ].Value >>= mbExportNotes;
461 else if ( rFilterData[ nData ].Name == "ViewPDFAfterExport" )
462 rFilterData[ nData ].Value >>= mbViewPDF;
463 else if ( rFilterData[ nData ].Name == "ExportNotesPages" )
464 rFilterData[ nData ].Value >>= mbExportNotesPages;
465 else if ( rFilterData[ nData ].Name == "EmbedStandardFonts" )
466 rFilterData[ nData ].Value >>= mbEmbedStandardFonts;
467 else if ( rFilterData[ nData ].Name == "UseTransitionEffects" )
468 rFilterData[ nData ].Value >>= mbUseTransitionEffects;
469 else if ( rFilterData[ nData ].Name == "ExportFormFields" )
470 rFilterData[ nData ].Value >>= mbExportFormFields;
471 else if ( rFilterData[ nData ].Name == "FormsType" )
472 rFilterData[ nData ].Value >>= mnFormsFormat;
473 else if ( rFilterData[ nData ].Name == "AllowDuplicateFieldNames" )
474 rFilterData[ nData ].Value >>= mbAllowDuplicateFieldNames;
475 //viewer properties
476 else if ( rFilterData[ nData ].Name == "HideViewerToolbar" )
477 rFilterData[ nData ].Value >>= mbHideViewerToolbar;
478 else if ( rFilterData[ nData ].Name == "HideViewerMenubar" )
479 rFilterData[ nData ].Value >>= mbHideViewerMenubar;
480 else if ( rFilterData[ nData ].Name == "HideViewerWindowControls" )
481 rFilterData[ nData ].Value >>= mbHideViewerWindowControls;
482 else if ( rFilterData[ nData ].Name == "ResizeWindowToInitialPage" )
483 rFilterData[ nData ].Value >>= mbFitWindow;
484 else if ( rFilterData[ nData ].Name == "CenterWindow" )
485 rFilterData[ nData ].Value >>= mbCenterWindow;
486 else if ( rFilterData[ nData ].Name == "OpenInFullScreenMode" )
487 rFilterData[ nData ].Value >>= mbOpenInFullScreenMode;
488 else if ( rFilterData[ nData ].Name == "DisplayPDFDocumentTitle" )
489 rFilterData[ nData ].Value >>= mbDisplayPDFDocumentTitle;
490 else if ( rFilterData[ nData ].Name == "InitialView" )
491 rFilterData[ nData ].Value >>= mnPDFDocumentMode;
492 else if ( rFilterData[ nData ].Name == "Magnification" )
493 rFilterData[ nData ].Value >>= mnPDFDocumentAction;
494 else if ( rFilterData[ nData ].Name == "Zoom" )
495 rFilterData[ nData ].Value >>= mnZoom;
496 else if ( rFilterData[ nData ].Name == "InitialPage" )
497 rFilterData[ nData ].Value >>= mnInitialPage;
498 else if ( rFilterData[ nData ].Name == "PageLayout" )
499 rFilterData[ nData ].Value >>= mnPDFPageLayout;
500 else if ( rFilterData[ nData ].Name == "FirstPageOnLeft" )
501 rFilterData[ nData ].Value >>= aContext.FirstPageLeft;
502 else if ( rFilterData[ nData ].Name == "IsAddStream" )
503 rFilterData[ nData ].Value >>= mbAddStream;
504 else if ( rFilterData[ nData ].Name == "Watermark" )
506 maWatermark = rFilterData[ nData ].Value;
507 mbWatermark = sal_True;
509 //now all the security related properties...
510 else if ( rFilterData[ nData ].Name == "EncryptFile" )
511 rFilterData[ nData ].Value >>= mbEncrypt;
512 else if ( rFilterData[ nData ].Name == "DocumentOpenPassword" )
513 rFilterData[ nData ].Value >>= aOpenPassword;
514 else if ( rFilterData[ nData ].Name == "RestrictPermissions" )
515 rFilterData[ nData ].Value >>= mbRestrictPermissions;
516 else if ( rFilterData[ nData ].Name == "PermissionPassword" )
517 rFilterData[ nData ].Value >>= aPermissionPassword;
518 else if ( rFilterData[ nData ].Name == "PreparedPasswords" )
519 rFilterData[ nData ].Value >>= xEnc;
520 else if ( rFilterData[ nData ].Name == "PreparedPermissionPassword" )
521 rFilterData[ nData ].Value >>= aPreparedPermissionPassword;
522 else if ( rFilterData[ nData ].Name == "Printing" )
523 rFilterData[ nData ].Value >>= mnPrintAllowed;
524 else if ( rFilterData[ nData ].Name == "Changes" )
525 rFilterData[ nData ].Value >>= mnChangesAllowed;
526 else if ( rFilterData[ nData ].Name == "EnableCopyingOfContent" )
527 rFilterData[ nData ].Value >>= mbCanCopyOrExtract;
528 else if ( rFilterData[ nData ].Name == "EnableTextAccessForAccessibilityTools" )
529 rFilterData[ nData ].Value >>= mbCanExtractForAccessibility;
530 //--->i56629 links extra (relative links and other related stuff)
531 else if ( rFilterData[ nData ].Name == "ExportLinksRelativeFsys" )
532 rFilterData[ nData ].Value >>= mbExportRelativeFsysLinks;
533 else if ( rFilterData[ nData ].Name == "PDFViewSelection" )
534 rFilterData[ nData ].Value >>= mnDefaultLinkAction;
535 else if ( rFilterData[ nData ].Name == "ConvertOOoTargetToPDFTarget" )
536 rFilterData[ nData ].Value >>= mbConvertOOoTargetToPDFTarget;
537 else if ( rFilterData[ nData ].Name == "ExportBookmarksToPDFDestination" )
538 rFilterData[ nData ].Value >>= mbExportBmkToDest;
539 else if ( rFilterData[ nData ].Name == "ExportBookmarks" )
540 rFilterData[ nData ].Value >>= mbExportBookmarks;
541 else if ( rFilterData[ nData ].Name == "ExportHiddenSlides" )
542 rFilterData[ nData ].Value >>= mbExportHiddenSlides;
543 else if ( rFilterData[ nData ].Name == "OpenBookmarkLevels" )
544 rFilterData[ nData ].Value >>= mnOpenBookmarkLevels;
545 else if ( rFilterData[ nData ].Name == "SignPDF" )
546 rFilterData[ nData ].Value >>= mbSignPDF;
547 else if ( rFilterData[ nData ].Name == "SignatureLocation" )
548 rFilterData[ nData ].Value >>= msSignLocation;
549 else if ( rFilterData[ nData ].Name == "SignatureReason" )
550 rFilterData[ nData ].Value >>= msSignReason;
551 else if ( rFilterData[ nData ].Name == "SignatureContactInfo" )
552 rFilterData[ nData ].Value >>= msSignContact;
553 else if ( rFilterData[ nData ].Name == "SignaturePassword" )
554 rFilterData[ nData ].Value >>= msSignPassword;
555 else if ( rFilterData[ nData ].Name == "SignatureCertificate" )
556 rFilterData[ nData ].Value >>= maSignCertificate;
558 aContext.URL = aURL.GetMainURL(INetURLObject::DECODE_TO_IURI);
560 //set the correct version, depending on user request
561 switch( mnPDFTypeSelection )
563 default:
564 case 0:
565 aContext.Version = PDFWriter::PDF_1_4;
566 break;
567 case 1:
568 aContext.Version = PDFWriter::PDF_A_1;
569 //force the tagged PDF as well
570 mbUseTaggedPDF = sal_True;
571 //force embedding of standard fonts
572 mbEmbedStandardFonts = sal_True;
573 //force disabling of form conversion
574 mbExportFormFields = sal_False;
575 // PDF/A does not allow transparencies
576 mbRemoveTransparencies = sal_True;
577 // no encryption
578 mbEncrypt = sal_False;
579 xEnc.clear();
580 break;
583 //copy in context the values default in the contructor or set by the FilterData sequence of properties
584 aContext.Tagged = mbUseTaggedPDF;
586 //values used in viewer
587 aContext.HideViewerToolbar = mbHideViewerToolbar;
588 aContext.HideViewerMenubar = mbHideViewerMenubar;
589 aContext.HideViewerWindowControls = mbHideViewerWindowControls;
590 aContext.FitWindow = mbFitWindow;
591 aContext.CenterWindow = mbCenterWindow;
592 aContext.OpenInFullScreenMode = mbOpenInFullScreenMode;
593 aContext.DisplayPDFDocumentTitle = mbDisplayPDFDocumentTitle;
594 aContext.InitialPage = mnInitialPage-1;
595 aContext.OpenBookmarkLevels = mnOpenBookmarkLevels;
596 aContext.EmbedStandardFonts = mbEmbedStandardFonts;
598 switch( mnPDFDocumentMode )
600 default:
601 case 0:
602 aContext.PDFDocumentMode = PDFWriter::ModeDefault;
603 break;
604 case 1:
605 aContext.PDFDocumentMode = PDFWriter::UseOutlines;
606 break;
607 case 2:
608 aContext.PDFDocumentMode = PDFWriter::UseThumbs;
609 break;
611 switch( mnPDFDocumentAction )
613 default:
614 case 0:
615 aContext.PDFDocumentAction = PDFWriter::ActionDefault;
616 break;
617 case 1:
618 aContext.PDFDocumentAction = PDFWriter::FitInWindow;
619 break;
620 case 2:
621 aContext.PDFDocumentAction = PDFWriter::FitWidth;
622 break;
623 case 3:
624 aContext.PDFDocumentAction = PDFWriter::FitVisible;
625 break;
626 case 4:
627 aContext.PDFDocumentAction = PDFWriter::ActionZoom;
628 aContext.Zoom = mnZoom;
629 break;
632 switch( mnPDFPageLayout )
634 default:
635 case 0:
636 aContext.PageLayout = PDFWriter::DefaultLayout;
637 break;
638 case 1:
639 aContext.PageLayout = PDFWriter::SinglePage;
640 break;
641 case 2:
642 aContext.PageLayout = PDFWriter::Continuous;
643 break;
644 case 3:
645 aContext.PageLayout = PDFWriter::ContinuousFacing;
646 break;
649 aContext.FirstPageLeft = mbFirstPageLeft;
651 //check if PDF/A, which does not allow encryption
652 if( aContext.Version != PDFWriter::PDF_A_1 )
654 //set values needed in encryption
655 //set encryption level, fixed, but here it can set by the UI if needed.
656 // true is 128 bit, false 40
657 //note that in 40 bit mode the UI needs reworking, since the current UI is meaningfull only for
658 //128bit security mode
659 aContext.Encryption.Security128bit = sal_True;
661 //set check for permission change password
662 // if not enabled and no permission password, force permissions to default as if PDF where without encryption
663 if( mbRestrictPermissions && (xEnc.is() || !aPermissionPassword.isEmpty()) )
665 mbEncrypt = sal_True;
666 //permission set as desired, done after
668 else
670 //force permission to default
671 mnPrintAllowed = 2 ;
672 mnChangesAllowed = 4 ;
673 mbCanCopyOrExtract = sal_True;
674 mbCanExtractForAccessibility = sal_True ;
677 switch( mnPrintAllowed )
679 case 0: //initialized when aContext is build, means no printing
680 break;
681 default:
682 case 2:
683 aContext.Encryption.CanPrintFull = sal_True;
684 case 1:
685 aContext.Encryption.CanPrintTheDocument = sal_True;
686 break;
689 switch( mnChangesAllowed )
691 case 0: //already in struct PDFSecPermissions CTOR
692 break;
693 case 1:
694 aContext.Encryption.CanAssemble = sal_True;
695 break;
696 case 2:
697 aContext.Encryption.CanFillInteractive = sal_True;
698 break;
699 case 3:
700 aContext.Encryption.CanAddOrModify = sal_True;
701 break;
702 default:
703 case 4:
704 aContext.Encryption.CanModifyTheContent =
705 aContext.Encryption.CanCopyOrExtract =
706 aContext.Encryption.CanAddOrModify =
707 aContext.Encryption.CanFillInteractive = sal_True;
708 break;
711 aContext.Encryption.CanCopyOrExtract = mbCanCopyOrExtract;
712 aContext.Encryption.CanExtractForAccessibility = mbCanExtractForAccessibility;
713 if( mbEncrypt && ! xEnc.is() )
714 xEnc = PDFWriter::InitEncryption( aPermissionPassword, aOpenPassword, aContext.Encryption.Security128bit );
715 if( mbEncrypt && !aPermissionPassword.isEmpty() && ! aPreparedPermissionPassword.getLength() )
716 aPreparedPermissionPassword = comphelper::OStorageHelper::CreatePackageEncryptionData( aPermissionPassword );
718 // after this point we don't need the legacy clear passwords anymore
719 // however they are still inside the passed filter data sequence
720 // which is sadly out out our control
721 aPermissionPassword = OUString();
722 aOpenPassword = OUString();
725 * FIXME: the entries are only implicitly defined by the resource file. Should there
726 * ever be an additional form submit format this could get invalid.
728 switch( mnFormsFormat )
730 case 1:
731 aContext.SubmitFormat = PDFWriter::PDF;
732 break;
733 case 2:
734 aContext.SubmitFormat = PDFWriter::HTML;
735 break;
736 case 3:
737 aContext.SubmitFormat = PDFWriter::XML;
738 break;
739 default:
740 case 0:
741 aContext.SubmitFormat = PDFWriter::FDF;
742 break;
744 aContext.AllowDuplicateFieldNames = mbAllowDuplicateFieldNames;
746 //get model
747 Reference< frame::XModel > xModel( mxSrcDoc, UNO_QUERY );
749 //---> i56629 Relative link stuff
750 //set the base URL of the file:
751 //then base URL
752 aContext.BaseURL = xModel->getURL();
753 //relative link option is private to PDF Export filter and limited to local filesystem only
754 aContext.RelFsys = mbExportRelativeFsysLinks;
755 //determine the default acton for PDF links
756 switch( mnDefaultLinkAction )
758 default:
759 //default: URI, without fragment conversion (the bookmark in PDF may not work)
760 case 0:
761 aContext.DefaultLinkAction = PDFWriter::URIAction;
762 break;
763 //view PDF through the reader application
764 case 1:
765 aContext.ForcePDFAction = sal_True;
766 aContext.DefaultLinkAction = PDFWriter::LaunchAction;
767 break;
768 //view PDF through an Internet browser
769 case 2:
770 aContext.DefaultLinkAction = PDFWriter::URIActionDestination;
771 break;
773 aContext.ConvertOOoTargetToPDFTarget = mbConvertOOoTargetToPDFTarget;
774 // check for Link Launch action, not allowed on PDF/A-1
775 // this code chunk checks when the filter is called from scripting
776 if( aContext.Version == PDFWriter::PDF_A_1 &&
777 aContext.DefaultLinkAction == PDFWriter::LaunchAction )
778 { //force the similar allowed URI action
779 aContext.DefaultLinkAction = PDFWriter::URIActionDestination;
780 //and remove the remote goto action forced on PDF file
781 aContext.ForcePDFAction = sal_False;
785 aContext.SignPDF = mbSignPDF;
786 aContext.SignLocation = msSignLocation;
787 aContext.SignContact = msSignContact;
788 aContext.SignReason = msSignReason;
789 aContext.SignPassword = msSignPassword;
790 aContext.SignCertificate = maSignCertificate;
792 // all context data set, time to create the printing device
793 PDFWriter* pPDFWriter = new PDFWriter( aContext, xEnc );
794 OutputDevice* pOut = pPDFWriter->GetReferenceDevice();
795 vcl::PDFExtOutDevData* pPDFExtOutDevData = NULL;
797 DBG_ASSERT( pOut, "PDFExport::Export: no reference device" );
798 pXDevice->SetOutputDevice( pOut );
800 if( mbAddStream )
802 // export stream
803 // get mimetype
804 OUString aSrcMimetype = getMimetypeForDocument( mxMSF, mxSrcDoc );
805 pPDFWriter->AddStream( aSrcMimetype,
806 new PDFExportStreamDoc( mxSrcDoc, aPreparedPermissionPassword ),
807 false
811 if ( pOut )
813 DBG_ASSERT( pOut->GetExtOutDevData() == NULL, "PDFExport: ExtOutDevData already set!!!" );
814 pPDFExtOutDevData = new vcl::PDFExtOutDevData( *pOut );
815 pOut->SetExtOutDevData( pPDFExtOutDevData );
816 pPDFExtOutDevData->SetIsExportNotes( mbExportNotes );
817 pPDFExtOutDevData->SetIsExportTaggedPDF( mbUseTaggedPDF );
818 pPDFExtOutDevData->SetIsExportTransitionEffects( mbUseTransitionEffects );
819 pPDFExtOutDevData->SetFormsFormat( mnFormsFormat );
820 pPDFExtOutDevData->SetIsExportFormFields( mbExportFormFields );
821 pPDFExtOutDevData->SetIsExportBookmarks( mbExportBookmarks );
822 pPDFExtOutDevData->SetIsExportHiddenSlides( mbExportHiddenSlides );
823 pPDFExtOutDevData->SetIsLosslessCompression( mbUseLosslessCompression );
824 pPDFExtOutDevData->SetIsReduceImageResolution( mbReduceImageResolution );
825 pPDFExtOutDevData->SetIsExportNamedDestinations( mbExportBmkToDest );
827 Sequence< PropertyValue > aRenderOptions( 6 );
828 aRenderOptions[ 0 ].Name = "RenderDevice";
829 aRenderOptions[ 0 ].Value <<= Reference< awt::XDevice >( pXDevice );
830 aRenderOptions[ 1 ].Name = "ExportNotesPages";
831 aRenderOptions[ 1 ].Value <<= sal_False;
832 Any& rExportNotesValue = aRenderOptions[ 1 ].Value;
833 aRenderOptions[ 2 ].Name = "IsFirstPage";
834 aRenderOptions[ 2 ].Value <<= sal_True;
835 aRenderOptions[ 3 ].Name = "IsLastPage";
836 aRenderOptions[ 3 ].Value <<= sal_False;
837 aRenderOptions[ 4 ].Name = "IsSkipEmptyPages";
838 aRenderOptions[ 4 ].Value <<= mbSkipEmptyPages;
839 aRenderOptions[ 5 ].Name = "PageRange";
840 aRenderOptions[ 5 ].Value <<= aPageRange;
842 if( !aPageRange.isEmpty() || !aSelection.hasValue() )
844 aSelection = Any();
845 aSelection <<= mxSrcDoc;
847 sal_Bool bSecondPassForImpressNotes = sal_False;
848 bool bReChangeToNormalView = false;
849 OUString sShowOnlineLayout( "ShowOnlineLayout" );
850 uno::Reference< beans::XPropertySet > xViewProperties;
852 if ( aCreator.equalsAscii( "Writer" ) )
854 //i92835 if Writer is in web layout mode this has to be switched to normal view and back to web view in the end
857 Reference< view::XViewSettingsSupplier > xVSettingsSupplier( xModel->getCurrentController(), uno::UNO_QUERY_THROW );
858 xViewProperties = xVSettingsSupplier->getViewSettings();
859 xViewProperties->getPropertyValue( sShowOnlineLayout ) >>= bReChangeToNormalView;
860 if( bReChangeToNormalView )
862 xViewProperties->setPropertyValue( sShowOnlineLayout, uno::makeAny( false ) );
865 catch( const uno::Exception& )
871 const sal_Int32 nPageCount = xRenderable->getRendererCount( aSelection, aRenderOptions );
873 if ( mbExportNotesPages && aCreator.equalsAscii( "Impress" ) )
875 uno::Reference< drawing::XShapes > xShapes; // sj: do not allow to export notes when
876 if ( ! ( aSelection >>= xShapes ) ) // exporting a selection -> todo: in the dialog
877 bSecondPassForImpressNotes = sal_True; // the export notes checkbox needs to be disabled
880 if( aPageRange.isEmpty() )
882 aPageRange = OUString::number( 1 ) + "-" + OUString::number(nPageCount );
884 StringRangeEnumerator aRangeEnum( aPageRange, 0, nPageCount-1 );
886 if ( mxStatusIndicator.is() )
888 ResMgr* pResMgr = ResMgr::CreateResMgr( "pdffilter", Application::GetSettings().GetUILanguageTag() );
889 if ( pResMgr )
891 sal_Int32 nTotalPageCount = aRangeEnum.size();
892 if ( bSecondPassForImpressNotes )
893 nTotalPageCount *= 2;
894 mxStatusIndicator->start( String( ResId( PDF_PROGRESS_BAR, *pResMgr ) ), nTotalPageCount );
895 delete pResMgr;
899 if( nPageCount > 0 )
900 bRet = ExportSelection( *pPDFWriter, xRenderable, aSelection, aRangeEnum, aRenderOptions, nPageCount );
901 else
902 bRet = sal_False;
904 if ( bRet && bSecondPassForImpressNotes )
906 rExportNotesValue <<= sal_True;
907 bRet = ExportSelection( *pPDFWriter, xRenderable, aSelection, aRangeEnum, aRenderOptions, nPageCount );
909 if ( mxStatusIndicator.is() )
910 mxStatusIndicator->end();
912 // if during the export the doc locale was set copy it to PDF writer
913 const com::sun::star::lang::Locale& rLoc( pPDFExtOutDevData->GetDocumentLocale() );
914 if( !rLoc.Language.isEmpty() )
915 pPDFWriter->SetDocumentLocale( rLoc );
917 if( bRet )
919 pPDFExtOutDevData->PlayGlobalActions( *pPDFWriter );
920 pPDFWriter->Emit();
921 aErrors = pPDFWriter->GetErrors();
923 pOut->SetExtOutDevData( NULL );
924 if( bReChangeToNormalView )
928 xViewProperties->setPropertyValue( sShowOnlineLayout, uno::makeAny( true ) );
930 catch( const uno::Exception& )
936 delete pPDFExtOutDevData;
937 delete pPDFWriter;
941 // show eventual errors during export
942 showErrors( aErrors );
944 return bRet;
947 namespace
950 typedef cppu::WeakComponentImplHelper1< task::XInteractionRequest > PDFErrorRequestBase;
952 class PDFErrorRequest : private cppu::BaseMutex,
953 public PDFErrorRequestBase
955 task::PDFExportException maExc;
956 public:
957 PDFErrorRequest( const task::PDFExportException& i_rExc );
959 // XInteractionRequest
960 virtual uno::Any SAL_CALL getRequest() throw (uno::RuntimeException);
961 virtual uno::Sequence< uno::Reference< task::XInteractionContinuation > > SAL_CALL getContinuations() throw (uno::RuntimeException);
964 PDFErrorRequest::PDFErrorRequest( const task::PDFExportException& i_rExc ) :
965 PDFErrorRequestBase( m_aMutex ),
966 maExc( i_rExc )
970 uno::Any SAL_CALL PDFErrorRequest::getRequest() throw (uno::RuntimeException)
972 osl::MutexGuard const guard( m_aMutex );
974 uno::Any aRet;
975 aRet <<= maExc;
976 return aRet;
979 uno::Sequence< uno::Reference< task::XInteractionContinuation > > SAL_CALL PDFErrorRequest::getContinuations() throw (uno::RuntimeException)
981 return uno::Sequence< uno::Reference< task::XInteractionContinuation > >();
984 } // namespace
986 void PDFExport::showErrors( const std::set< PDFWriter::ErrorCode >& rErrors )
988 if( ! rErrors.empty() && mxIH.is() )
990 task::PDFExportException aExc;
991 aExc.ErrorCodes.realloc( sal_Int32(rErrors.size()) );
992 sal_Int32 i = 0;
993 for( std::set< PDFWriter::ErrorCode >::const_iterator it = rErrors.begin();
994 it != rErrors.end(); ++it, i++ )
996 aExc.ErrorCodes.getArray()[i] = (sal_Int32)*it;
998 Reference< task::XInteractionRequest > xReq( new PDFErrorRequest( aExc ) );
999 mxIH->handle( xReq );
1003 // -----------------------------------------------------------------------------
1005 sal_Bool PDFExport::ImplExportPage( PDFWriter& rWriter, PDFExtOutDevData& rPDFExtOutDevData, const GDIMetaFile& rMtf )
1007 const Size aSizePDF( OutputDevice::LogicToLogic( rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), MAP_POINT ) );
1008 Point aOrigin;
1009 Rectangle aPageRect( aOrigin, rMtf.GetPrefSize() );
1010 sal_Bool bRet = sal_True;
1012 rWriter.NewPage( aSizePDF.Width(), aSizePDF.Height() );
1013 rWriter.SetMapMode( rMtf.GetPrefMapMode() );
1015 vcl::PDFWriter::PlayMetafileContext aCtx;
1016 GDIMetaFile aMtf;
1017 if( mbRemoveTransparencies )
1019 aCtx.m_bTransparenciesWereRemoved = rWriter.GetReferenceDevice()->
1020 RemoveTransparenciesFromMetaFile( rMtf, aMtf, mnMaxImageResolution, mnMaxImageResolution,
1021 false, true, mbReduceImageResolution );
1023 else
1025 aMtf = rMtf;
1027 aCtx.m_nMaxImageResolution = mbReduceImageResolution ? mnMaxImageResolution : 0;
1028 aCtx.m_bOnlyLosslessCompression = mbUseLosslessCompression;
1029 aCtx.m_nJPEGQuality = mnQuality;
1032 basegfx::B2DRectangle aB2DRect( aPageRect.Left(), aPageRect.Top(), aPageRect.Right(), aPageRect.Bottom() );
1033 rWriter.SetClipRegion( basegfx::B2DPolyPolygon( basegfx::tools::createPolygonFromRect( aB2DRect ) ) );
1035 rWriter.PlayMetafile( aMtf, aCtx, &rPDFExtOutDevData );
1037 rPDFExtOutDevData.ResetSyncData();
1039 if( mbWatermark )
1040 ImplWriteWatermark( rWriter, aSizePDF );
1042 return bRet;
1045 // -----------------------------------------------------------------------------
1047 void PDFExport::ImplWriteWatermark( PDFWriter& rWriter, const Size& rPageSize )
1049 OUString aText( "Watermark" );
1050 Font aFont( OUString( "Helvetica" ), Size( 0, 3*rPageSize.Height()/4 ) );
1051 aFont.SetItalic( ITALIC_NONE );
1052 aFont.SetWidthType( WIDTH_NORMAL );
1053 aFont.SetWeight( WEIGHT_NORMAL );
1054 aFont.SetAlign( ALIGN_BOTTOM );
1055 long nTextWidth = rPageSize.Width();
1056 if( rPageSize.Width() < rPageSize.Height() )
1058 nTextWidth = rPageSize.Height();
1059 aFont.SetOrientation( 2700 );
1062 if( ! ( maWatermark >>= aText ) )
1064 // more complicated watermark ?
1067 // adjust font height for text to fit
1068 OutputDevice* pDev = rWriter.GetReferenceDevice();
1069 pDev->Push( PUSH_ALL );
1070 pDev->SetFont( aFont );
1071 pDev->SetMapMode( MapMode( MAP_POINT ) );
1072 int w = 0;
1073 while( ( w = pDev->GetTextWidth( aText ) ) > nTextWidth )
1075 long nNewHeight = aFont.GetHeight() * nTextWidth / w;
1076 if( nNewHeight == aFont.GetHeight() )
1078 nNewHeight--;
1079 if( nNewHeight <= 0 )
1080 break;
1082 aFont.SetHeight( nNewHeight );
1083 pDev->SetFont( aFont );
1085 long nTextHeight = pDev->GetTextHeight();
1086 // leave some maneuvering room for rounding issues, also
1087 // some fonts go a little outside ascent/descent
1088 nTextHeight += nTextHeight/20;
1089 pDev->Pop();
1091 rWriter.Push( PUSH_ALL );
1092 rWriter.SetMapMode( MapMode( MAP_POINT ) );
1093 rWriter.SetFont( aFont );
1094 rWriter.SetTextColor( COL_LIGHTGREEN );
1095 Point aTextPoint;
1096 Rectangle aTextRect;
1097 if( rPageSize.Width() > rPageSize.Height() )
1099 aTextPoint = Point( (rPageSize.Width()-w)/2,
1100 rPageSize.Height()-(rPageSize.Height()-nTextHeight)/2 );
1101 aTextRect = Rectangle( Point( (rPageSize.Width()-w)/2,
1102 (rPageSize.Height()-nTextHeight)/2 ),
1103 Size( w, nTextHeight ) );
1105 else
1107 aTextPoint = Point( (rPageSize.Width()-nTextHeight)/2,
1108 (rPageSize.Height()-w)/2 );
1109 aTextRect = Rectangle( aTextPoint, Size( nTextHeight, w ) );
1111 rWriter.SetClipRegion();
1112 rWriter.BeginTransparencyGroup();
1113 rWriter.DrawText( aTextPoint, aText );
1114 rWriter.EndTransparencyGroup( aTextRect, 50 );
1115 rWriter.Pop();
1119 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */