1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
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
;
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
),
96 mxStatusIndicator ( rxStatusIndicator
),
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 ),
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 ),
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
),
144 mbExportRelativeFsysLinks ( sal_False
),
145 mnDefaultLinkAction ( 0 ),
146 mbConvertOOoTargetToPDFTarget( sal_False
),
147 mbExportBmkToDest ( sal_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();
189 vcl::PDFExtOutDevData
* pPDFExtOutDevData
= PTR_CAST( vcl::PDFExtOutDevData
, pOut
->GetExtOutDevData() );
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
) );
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
);
211 const MapMode
aMapMode( MAP_100TH_MM
);
212 const Size
aMtfSize( aPageSize
.Width
, aPageSize
.Height
);
215 pOut
->EnableOutput( sal_False
);
216 pOut
->SetMapMode( aMapMode
);
218 aMtf
.SetPrefSize( aMtfSize
);
219 aMtf
.SetPrefMapMode( aMapMode
);
223 // IsLastPage property.
224 const sal_Int32 nCurrentRenderer
= *aIter
;
226 if ( pLastPage
&& aIter
== aEnd
)
227 *pLastPage
<<= sal_True
;
229 rRenderable
->render( nCurrentRenderer
, rSelection
, rRenderOptions
);
234 if( aMtf
.GetActionSize() &&
235 ( !mbSkipEmptyPages
|| aPageSize
.Width
|| aPageSize
.Height
) )
236 bRet
= ImplExportPage( rPDFWriter
, *pPDFExtOutDevData
, aMtf
) || bRet
;
240 if ( mxStatusIndicator
.is() )
241 mxStatusIndicator
->setValue( mnProgressValue
);
243 *pFirstPage
<<= sal_False
;
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
&)
263 class PDFExportStreamDoc
: public vcl::PDFOutputStream
265 Reference
< XComponent
> m_xSrcDoc
;
266 Sequence
< beans::NamedValue
> m_aPreparedPassword
;
268 PDFExportStreamDoc( const Reference
< XComponent
>& xDoc
, const Sequence
<beans::NamedValue
>& rPwd
)
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
);
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
)) );
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
),
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
343 Reference
< container::XNameAccess
> xFilterFactory(
344 xFactory
->createInstance( "com.sun.star.document.FilterFactory" ),
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" ),
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
;
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
)
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
;
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
405 Reference
< XServiceInfo
> xInfo( mxSrcDoc
, UNO_QUERY
);
408 if ( xInfo
->supportsService( "com.sun.star.presentation.PresentationDocument" ) )
409 aCreator
+= "Impress";
410 else if ( xInfo
->supportsService( "com.sun.star.drawing.DrawingDocument" ) )
412 else if ( xInfo
->supportsService( "com.sun.star.text.TextDocument" ) )
413 aCreator
+= "Writer";
414 else if ( xInfo
->supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) )
416 else if ( xInfo
->supportsService( "com.sun.star.formula.FormulaProperties" ) )
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() +
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
;
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
)
565 aContext
.Version
= PDFWriter::PDF_1_4
;
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
;
578 mbEncrypt
= sal_False
;
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
)
602 aContext
.PDFDocumentMode
= PDFWriter::ModeDefault
;
605 aContext
.PDFDocumentMode
= PDFWriter::UseOutlines
;
608 aContext
.PDFDocumentMode
= PDFWriter::UseThumbs
;
611 switch( mnPDFDocumentAction
)
615 aContext
.PDFDocumentAction
= PDFWriter::ActionDefault
;
618 aContext
.PDFDocumentAction
= PDFWriter::FitInWindow
;
621 aContext
.PDFDocumentAction
= PDFWriter::FitWidth
;
624 aContext
.PDFDocumentAction
= PDFWriter::FitVisible
;
627 aContext
.PDFDocumentAction
= PDFWriter::ActionZoom
;
628 aContext
.Zoom
= mnZoom
;
632 switch( mnPDFPageLayout
)
636 aContext
.PageLayout
= PDFWriter::DefaultLayout
;
639 aContext
.PageLayout
= PDFWriter::SinglePage
;
642 aContext
.PageLayout
= PDFWriter::Continuous
;
645 aContext
.PageLayout
= PDFWriter::ContinuousFacing
;
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
670 //force permission to default
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
683 aContext
.Encryption
.CanPrintFull
= sal_True
;
685 aContext
.Encryption
.CanPrintTheDocument
= sal_True
;
689 switch( mnChangesAllowed
)
691 case 0: //already in struct PDFSecPermissions CTOR
694 aContext
.Encryption
.CanAssemble
= sal_True
;
697 aContext
.Encryption
.CanFillInteractive
= sal_True
;
700 aContext
.Encryption
.CanAddOrModify
= sal_True
;
704 aContext
.Encryption
.CanModifyTheContent
=
705 aContext
.Encryption
.CanCopyOrExtract
=
706 aContext
.Encryption
.CanAddOrModify
=
707 aContext
.Encryption
.CanFillInteractive
= sal_True
;
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
)
731 aContext
.SubmitFormat
= PDFWriter::PDF
;
734 aContext
.SubmitFormat
= PDFWriter::HTML
;
737 aContext
.SubmitFormat
= PDFWriter::XML
;
741 aContext
.SubmitFormat
= PDFWriter::FDF
;
744 aContext
.AllowDuplicateFieldNames
= mbAllowDuplicateFieldNames
;
747 Reference
< frame::XModel
> xModel( mxSrcDoc
, UNO_QUERY
);
749 //---> i56629 Relative link stuff
750 //set the base URL of the file:
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
)
759 //default: URI, without fragment conversion (the bookmark in PDF may not work)
761 aContext
.DefaultLinkAction
= PDFWriter::URIAction
;
763 //view PDF through the reader application
765 aContext
.ForcePDFAction
= sal_True
;
766 aContext
.DefaultLinkAction
= PDFWriter::LaunchAction
;
768 //view PDF through an Internet browser
770 aContext
.DefaultLinkAction
= PDFWriter::URIActionDestination
;
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
);
804 OUString aSrcMimetype
= getMimetypeForDocument( mxMSF
, mxSrcDoc
);
805 pPDFWriter
->AddStream( aSrcMimetype
,
806 new PDFExportStreamDoc( mxSrcDoc
, aPreparedPermissionPassword
),
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() )
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() );
891 sal_Int32 nTotalPageCount
= aRangeEnum
.size();
892 if ( bSecondPassForImpressNotes
)
893 nTotalPageCount
*= 2;
894 mxStatusIndicator
->start( String( ResId( PDF_PROGRESS_BAR
, *pResMgr
) ), nTotalPageCount
);
900 bRet
= ExportSelection( *pPDFWriter
, xRenderable
, aSelection
, aRangeEnum
, aRenderOptions
, nPageCount
);
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
);
919 pPDFExtOutDevData
->PlayGlobalActions( *pPDFWriter
);
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
;
941 // show eventual errors during export
942 showErrors( aErrors
);
950 typedef cppu::WeakComponentImplHelper1
< task::XInteractionRequest
> PDFErrorRequestBase
;
952 class PDFErrorRequest
: private cppu::BaseMutex
,
953 public PDFErrorRequestBase
955 task::PDFExportException maExc
;
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
),
970 uno::Any SAL_CALL
PDFErrorRequest::getRequest() throw (uno::RuntimeException
)
972 osl::MutexGuard
const guard( m_aMutex
);
979 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > SAL_CALL
PDFErrorRequest::getContinuations() throw (uno::RuntimeException
)
981 return uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> >();
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()) );
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
) );
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
;
1017 if( mbRemoveTransparencies
)
1019 aCtx
.m_bTransparenciesWereRemoved
= rWriter
.GetReferenceDevice()->
1020 RemoveTransparenciesFromMetaFile( rMtf
, aMtf
, mnMaxImageResolution
, mnMaxImageResolution
,
1021 false, true, mbReduceImageResolution
);
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();
1040 ImplWriteWatermark( rWriter
, aSizePDF
);
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
) );
1073 while( ( w
= pDev
->GetTextWidth( aText
) ) > nTextWidth
)
1075 long nNewHeight
= aFont
.GetHeight() * nTextWidth
/ w
;
1076 if( nNewHeight
== aFont
.GetHeight() )
1079 if( nNewHeight
<= 0 )
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;
1091 rWriter
.Push( PUSH_ALL
);
1092 rWriter
.SetMapMode( MapMode( MAP_POINT
) );
1093 rWriter
.SetFont( aFont
);
1094 rWriter
.SetTextColor( COL_LIGHTGREEN
);
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
) );
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 );
1119 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */