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 <osl/file.hxx>
22 #include <tools/debug.hxx>
23 #include <tools/urlobj.hxx>
24 #include <tools/poly.hxx>
25 #include <comphelper/diagnose_ex.hxx>
27 #include <vcl/canvastools.hxx>
28 #include <vcl/mapmod.hxx>
29 #include <vcl/gdimtf.hxx>
30 #include <vcl/graphic/GraphicMetadata.hxx>
31 #include <vcl/pdf/PDFEncryptionInitialization.hxx>
32 #include <rtl/ustring.hxx>
33 #include <comphelper/propertyvalue.hxx>
34 #include <comphelper/sequence.hxx>
35 #include <comphelper/string.hxx>
36 #include <comphelper/storagehelper.hxx>
37 #include <basegfx/polygon/b2dpolygon.hxx>
38 #include <basegfx/polygon/b2dpolypolygon.hxx>
39 #include <basegfx/polygon/b2dpolygontools.hxx>
40 #include <toolkit/awt/vclxdevice.hxx>
41 #include <unotools/configmgr.hxx>
42 #include <comphelper/compbase.hxx>
43 #include <officecfg/Office/Common.hxx>
44 #include <sfx2/lokhelper.hxx>
46 #include "pdfexport.hxx"
47 #include <strings.hrc>
49 #include <com/sun/star/beans/XPropertySet.hpp>
50 #include <com/sun/star/configuration/theDefaultProvider.hpp>
51 #include <com/sun/star/awt/XDevice.hpp>
52 #include <com/sun/star/frame/XModel.hpp>
53 #include <com/sun/star/frame/ModuleManager.hpp>
54 #include <com/sun/star/frame/XStorable.hpp>
55 #include <com/sun/star/document/XDocumentProperties2.hpp>
56 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
57 #include <com/sun/star/container/XNameAccess.hpp>
58 #include <com/sun/star/view/XViewSettingsSupplier.hpp>
59 #include <com/sun/star/task/XInteractionRequest.hpp>
60 #include <com/sun/star/task/PDFExportException.hpp>
61 #include <com/sun/star/io/IOException.hpp>
62 #include <com/sun/star/io/XOutputStream.hpp>
63 #include <com/sun/star/lang/XServiceInfo.hpp>
64 #include <com/sun/star/drawing/XShapes.hpp>
65 #include <com/sun/star/sheet/XSheetRange.hpp>
66 #include <com/sun/star/security/XCertificate.hpp>
67 #include <com/sun/star/beans/XMaterialHolder.hpp>
68 #include <com/sun/star/xml/crypto/SEInitializer.hpp>
72 #include <rtl/bootstrap.hxx>
73 #include <config_features.h>
75 using namespace ::com::sun::star
;
76 using namespace ::com::sun::star::io
;
77 using namespace ::com::sun::star::uno
;
78 using namespace ::com::sun::star::lang
;
79 using namespace ::com::sun::star::beans
;
80 using namespace ::com::sun::star::view
;
83 PDFExport::PDFExport( const Reference
< XComponent
>& rxSrcDoc
,
84 const Reference
< task::XStatusIndicator
>& rxStatusIndicator
,
85 const Reference
< task::XInteractionHandler
>& rxIH
,
86 const Reference
< XComponentContext
>& xContext
) :
87 mxSrcDoc ( rxSrcDoc
),
88 mxContext ( xContext
),
89 mxStatusIndicator ( rxStatusIndicator
),
91 mbUseLosslessCompression ( false ),
92 mbReduceImageResolution ( true ),
93 mbSkipEmptyPages ( true ),
94 mnMaxImageResolution ( DefaultPDFImageDPI
),
95 mnQuality ( DefaultPDFJPEGQuality
),
96 mnProgressValue ( 0 ),
97 mbRemoveTransparencies ( false ),
99 mbIsRedactMode ( false ),
100 maWatermarkColor ( COL_LIGHTGREEN
),
101 maWatermarkFontName ( u
"Helvetica"_ustr
)
106 PDFExport::~PDFExport()
111 bool PDFExport::ExportSelection( vcl::PDFWriter
& rPDFWriter
,
112 Reference
< css::view::XRenderable
> const & rRenderable
,
113 const Any
& rSelection
,
114 const StringRangeEnumerator
& rRangeEnum
,
115 Sequence
< PropertyValue
>& rRenderOptions
,
116 sal_Int32 nPageCount
)
121 Any
* pFirstPage
= nullptr;
122 Any
* pLastPage
= nullptr;
124 bool bExportNotesPages
= false;
126 auto rRenderOptionsRange
= asNonConstRange(rRenderOptions
);
127 for( sal_Int32 nData
= 0, nDataCount
= rRenderOptions
.getLength(); nData
< nDataCount
; ++nData
)
129 if ( rRenderOptions
[ nData
].Name
== "IsFirstPage" )
130 pFirstPage
= &rRenderOptionsRange
[ nData
].Value
;
131 else if ( rRenderOptions
[ nData
].Name
== "IsLastPage" )
132 pLastPage
= &rRenderOptionsRange
[ nData
].Value
;
133 else if ( rRenderOptions
[ nData
].Name
== "ExportNotesPages" )
134 rRenderOptionsRange
[ nData
].Value
>>= bExportNotesPages
;
137 OutputDevice
* pOut
= rPDFWriter
.GetReferenceDevice();
143 vcl::PDFExtOutDevData
& rPDFExtOutDevData
= dynamic_cast<vcl::PDFExtOutDevData
&>(*pOut
->GetExtOutDevData());
144 rPDFExtOutDevData
.SetIsExportNotesPages( bExportNotesPages
);
146 sal_Int32
nCurrentPage(0);
147 StringRangeEnumerator::Iterator aIter
= rRangeEnum
.begin();
148 StringRangeEnumerator::Iterator aEnd
= rRangeEnum
.end();
149 while ( aIter
!= aEnd
)
151 const Sequence
< PropertyValue
> aRenderer( rRenderable
->getRenderer( *aIter
, rSelection
, rRenderOptions
) );
154 for( const PropertyValue
& rProp
: aRenderer
)
156 if ( rProp
.Name
== "PageSize" )
158 rProp
.Value
>>= aPageSize
;
163 rPDFExtOutDevData
.SetCurrentPageNumber( nCurrentPage
);
166 const MapMode
aMapMode( MapUnit::Map100thMM
);
167 const Size
aMtfSize( aPageSize
.Width
, aPageSize
.Height
);
170 pOut
->EnableOutput( false );
171 pOut
->SetMapMode( aMapMode
);
173 aMtf
.SetPrefSize( aMtfSize
);
174 aMtf
.SetPrefMapMode( aMapMode
);
178 // IsLastPage property.
179 const sal_Int32 nCurrentRenderer
= *aIter
;
181 if ( pLastPage
&& aIter
== aEnd
)
184 rRenderable
->render( nCurrentRenderer
, rSelection
, rRenderOptions
);
189 bool bEmptyPage
= false;
190 if( aMtf
.GetActionSize() &&
191 ( !mbSkipEmptyPages
|| aPageSize
.Width
|| aPageSize
.Height
) )
193 // We convert the whole metafile into a bitmap to get rid of the
194 // text covered by redaction shapes
199 Graphic
aGraph(aMtf
);
200 // use antialiasing to improve how graphic objects look
201 BitmapEx bmp
= aGraph
.GetBitmapEx(GraphicConversionParameters(Size(0, 0), false, true, false));
203 aMtf
= bgraph
.GetGDIMetaFile();
205 catch(const Exception
&)
207 TOOLS_WARN_EXCEPTION("filter.pdf", "Something went wrong while converting metafile to bitmap");
211 ImplExportPage(rPDFWriter
, rPDFExtOutDevData
, aMtf
);
221 if ( mxStatusIndicator
.is() )
222 mxStatusIndicator
->setValue( mnProgressValue
);
224 *pFirstPage
<<= false;
229 // Calculate the page number in the PDF output, which may be smaller than the page number in
230 // case of hidden slides or a partial export.
237 bRet
= true; // #i18334# nPageCount == 0,
238 rPDFWriter
.NewPage( 10000, 10000 ); // creating dummy page
239 rPDFWriter
.SetMapMode(MapMode(MapUnit::Map100thMM
));
243 catch(const RuntimeException
&)
251 class PDFExportStreamDoc
: public vcl::PDFOutputStream
255 Reference
< XComponent
> m_xSrcDoc
;
256 Sequence
< beans::NamedValue
> m_aPreparedPassword
;
260 PDFExportStreamDoc( const Reference
< XComponent
>& xDoc
, const Sequence
<beans::NamedValue
>& rPwd
)
262 m_aPreparedPassword( rPwd
)
265 virtual void write( const Reference
< XOutputStream
>& xStream
) override
;
270 void PDFExportStreamDoc::write( const Reference
< XOutputStream
>& xStream
)
272 Reference
< css::frame::XStorable
> xStore( m_xSrcDoc
, UNO_QUERY
);
276 std::vector
<beans::PropertyValue
> aArgs
{
277 comphelper::makePropertyValue(u
"FilterName"_ustr
, OUString()),
278 comphelper::makePropertyValue(u
"OutputStream"_ustr
, xStream
),
280 if (m_aPreparedPassword
.hasElements())
281 aArgs
.push_back(comphelper::makePropertyValue(u
"EncryptionData"_ustr
, m_aPreparedPassword
));
285 xStore
->storeToURL(u
"private:stream"_ustr
, comphelper::containerToSequence(aArgs
));
287 catch( const IOException
& )
293 static OUString
getMimetypeForDocument( const Reference
< XComponentContext
>& xContext
,
294 const Reference
< XComponent
>& xDoc
) noexcept
296 OUString aDocMimetype
;
299 // get document service name
300 Reference
< css::frame::XStorable
> xStore( xDoc
, UNO_QUERY
);
301 Reference
< frame::XModuleManager2
> xModuleManager
= frame::ModuleManager::create(xContext
);
304 OUString aDocServiceName
= xModuleManager
->identify( Reference
< XInterface
>( xStore
, uno::UNO_QUERY
) );
305 if ( !aDocServiceName
.isEmpty() )
307 // get the actual filter name
308 Reference
< lang::XMultiServiceFactory
> xConfigProvider
=
309 configuration::theDefaultProvider::get( xContext
);
310 beans::NamedValue aPathProp
;
311 aPathProp
.Name
= "nodepath";
312 aPathProp
.Value
<<= u
"/org.openoffice.Setup/Office/Factories/"_ustr
;
313 uno::Sequence
< uno::Any
> aArgs
{ uno::Any(aPathProp
) };
315 Reference
< container::XNameAccess
> xSOFConfig(
316 xConfigProvider
->createInstanceWithArguments(
317 u
"com.sun.star.configuration.ConfigurationAccess"_ustr
, aArgs
),
320 Reference
< container::XNameAccess
> xApplConfig
;
321 xSOFConfig
->getByName( aDocServiceName
) >>= xApplConfig
;
322 if ( xApplConfig
.is() )
324 OUString aFilterName
;
325 xApplConfig
->getByName( u
"ooSetupFactoryActualFilter"_ustr
) >>= aFilterName
;
326 if( !aFilterName
.isEmpty() )
328 // find the related type name
330 Reference
< container::XNameAccess
> xFilterFactory(
331 xContext
->getServiceManager()->createInstanceWithContext(u
"com.sun.star.document.FilterFactory"_ustr
, xContext
),
334 Sequence
< beans::PropertyValue
> aFilterData
;
335 xFilterFactory
->getByName( aFilterName
) >>= aFilterData
;
336 for (const beans::PropertyValue
& rProp
: aFilterData
)
337 if ( rProp
.Name
== "Type" )
338 rProp
.Value
>>= aTypeName
;
340 if ( !aTypeName
.isEmpty() )
342 // find the mediatype
343 Reference
< container::XNameAccess
> xTypeDetection(
344 xContext
->getServiceManager()->createInstanceWithContext(u
"com.sun.star.document.TypeDetection"_ustr
, xContext
),
347 Sequence
< beans::PropertyValue
> aTypeData
;
348 xTypeDetection
->getByName( aTypeName
) >>= aTypeData
;
349 for (const beans::PropertyValue
& rProp
: aTypeData
)
350 if ( rProp
.Name
== "MediaType" )
351 rProp
.Value
>>= aDocMimetype
;
364 uno::Reference
<security::XCertificate
>
365 PDFExport::GetCertificateFromSubjectName(std::u16string_view rSubjectName
) const
367 uno::Reference
<xml::crypto::XSEInitializer
> xSEInitializer
368 = xml::crypto::SEInitializer::create(mxContext
);
369 uno::Reference
<xml::crypto::XXMLSecurityContext
> xSecurityContext
370 = xSEInitializer
->createSecurityContext(OUString());
371 uno::Reference
<xml::crypto::XSecurityEnvironment
> xSecurityEnvironment
372 = xSecurityContext
->getSecurityEnvironment();
373 for (const auto& xCertificate
: xSecurityEnvironment
->getPersonalCertificates())
375 if (xCertificate
->getSubjectName() == rSubjectName
)
384 bool PDFExport::Export( const OUString
& rFile
, const Sequence
< PropertyValue
>& rFilterData
)
386 INetURLObject
aURL( rFile
);
389 std::set
< vcl::PDFWriter::ErrorCode
> aErrors
;
391 if( aURL
.GetProtocol() != INetProtocol::File
)
395 if( osl::FileBase::getFileURLFromSystemPath( rFile
, aTmp
) == osl::FileBase::E_None
)
396 aURL
= INetURLObject(aTmp
);
399 if( aURL
.GetProtocol() == INetProtocol::File
)
401 Reference
< XRenderable
> xRenderable( mxSrcDoc
, UNO_QUERY
);
403 if( xRenderable
.is() )
406 bool bUseTaggedPDF
= false;
407 sal_Int32 nPDFTypeSelection
= 0;
408 bool bPDFUACompliance
= false;
409 bool bExportNotes
= true;
410 bool bExportNotesInMargin
= false;
411 bool bExportNotesPages
= false;
412 bool bExportOnlyNotesPages
= false;
413 bool bUseTransitionEffects
= true;
414 bool bExportFormFields
= false;
415 sal_Int32 nFormsFormat
= 0;
416 bool bAllowDuplicateFieldNames
= false;
417 bool bHideViewerToolbar
= false;
418 bool bHideViewerMenubar
= false;
419 bool bHideViewerWindowControls
= false;
420 bool bFitWindow
= false;
421 bool bCenterWindow
= false;
422 bool bOpenInFullScreenMode
= false;
423 bool bDisplayPDFDocumentTitle
= true;
424 sal_Int32 nPDFDocumentMode
= 0;
425 sal_Int32 nPDFDocumentAction
= 0;
426 sal_Int32 nZoom
= 100;
427 sal_Int32 nInitialPage
= 1;
428 sal_Int32 nPDFPageLayout
= 0;
429 bool bAddStream
= false;
430 bool bEncrypt
= false;
431 bool bRestrictPermissions
= false;
432 sal_Int32 nPrintAllowed
= 2;
433 sal_Int32 nChangesAllowed
= 4;
434 bool bCanCopyOrExtract
= true;
435 bool bCanExtractForAccessibility
= true;
437 bool bExportRelativeFsysLinks
= false;
438 sal_Int32 nDefaultLinkAction
= 0;
439 bool bConvertOOoTargetToPDFTarget
= false;
440 bool bExportBmkToDest
= false;
441 bool bExportBookmarks
= true;
442 bool bExportHiddenSlides
= false;
443 bool bSinglePageSheets
= false;
444 sal_Int32 nOpenBookmarkLevels
= -1;
445 bool bSignPDF
= false;
446 OUString sSignLocation
, sSignReason
, sSignContact
, sSignPassword
;
447 css::uno::Reference
<css::security::XCertificate
> aSignCertificate
;
449 bool bExportPlaceholders
= false;
450 bool bUseReferenceXObject
= false;
452 rtl::Reference
<VCLXDevice
> xDevice(new VCLXDevice
);
455 vcl::PDFWriter::PDFWriterContext aContext
;
456 OUString aOpenPassword
, aPermissionPassword
;
457 Reference
< beans::XMaterialHolder
> xEnc
;
458 Sequence
< beans::NamedValue
> aPreparedPermissionPassword
;
459 std::optional
<PropertyValue
> oMathTitleRow
;
460 std::optional
<PropertyValue
> oMathFormulaText
;
461 std::optional
<PropertyValue
> oMathBorder
;
462 std::optional
<PropertyValue
> oMathPrintFormat
;
463 std::optional
<PropertyValue
> oMathPrintScale
;
465 // getting the string for the creator
467 Reference
< XServiceInfo
> xInfo( mxSrcDoc
, UNO_QUERY
);
470 if ( xInfo
->supportsService( u
"com.sun.star.presentation.PresentationDocument"_ustr
) )
471 aCreator
= u
"Impress"_ustr
;
472 else if ( xInfo
->supportsService( u
"com.sun.star.drawing.DrawingDocument"_ustr
) )
473 aCreator
= u
"Draw"_ustr
;
474 else if ( xInfo
->supportsService( u
"com.sun.star.text.TextDocument"_ustr
) )
475 aCreator
= u
"Writer"_ustr
;
476 else if ( xInfo
->supportsService( u
"com.sun.star.sheet.SpreadsheetDocument"_ustr
) )
477 aCreator
= u
"Calc"_ustr
;
478 else if ( xInfo
->supportsService( u
"com.sun.star.formula.FormulaProperties"_ustr
) )
479 aCreator
= u
"Math"_ustr
;
482 Reference
< document::XDocumentPropertiesSupplier
> xDocumentPropsSupplier( mxSrcDoc
, UNO_QUERY
);
483 if ( xDocumentPropsSupplier
.is() )
485 Reference
< document::XDocumentProperties2
> xDocumentProps( xDocumentPropsSupplier
->getDocumentProperties(), UNO_QUERY
);
486 if ( xDocumentProps
.is() )
488 aContext
.DocumentInfo
.Title
= xDocumentProps
->getTitle();
489 aContext
.DocumentInfo
.Author
= xDocumentProps
->getAuthor();
490 aContext
.DocumentInfo
.Subject
= xDocumentProps
->getSubject();
491 aContext
.DocumentInfo
.Keywords
= ::comphelper::string::convertCommaSeparated(xDocumentProps
->getKeywords());
492 aContext
.DocumentInfo
.ModificationDate
493 = xDocumentProps
->getEditingCycles() < 1
494 ? xDocumentProps
->getCreationDate()
495 : xDocumentProps
->getModificationDate();
496 aContext
.DocumentInfo
.Contributor
= xDocumentProps
->getContributor();
497 aContext
.DocumentInfo
.Coverage
= xDocumentProps
->getCoverage();
498 aContext
.DocumentInfo
.Identifier
= xDocumentProps
->getIdentifier();
499 aContext
.DocumentInfo
.Publisher
= xDocumentProps
->getPublisher();
500 aContext
.DocumentInfo
.Relation
= xDocumentProps
->getRelation();
501 aContext
.DocumentInfo
.Rights
= xDocumentProps
->getRights();
502 aContext
.DocumentInfo
.Source
= xDocumentProps
->getSource();
503 aContext
.DocumentInfo
.Type
= xDocumentProps
->getType();
507 if (!comphelper::IsFuzzing())
510 auto const ok
= rtl::Bootstrap::get(u
"_ARCH"_ustr
, arch
);
511 assert(ok
); (void) ok
;
512 // getting the string for the producer
513 OUString aProducerOverride
= officecfg::Office::Common::Save::Document::GeneratorOverride::get();
514 if (!aProducerOverride
.isEmpty())
515 aContext
.DocumentInfo
.Producer
= aProducerOverride
;
517 aContext
.DocumentInfo
.Producer
=
518 utl::ConfigManager::getProductName() +
520 utl::ConfigManager::getAboutBoxProductVersion() +
522 #if HAVE_FEATURE_COMMUNITY_FLAVOR
523 " / LibreOffice Community"
528 aContext
.DocumentInfo
.Creator
= aCreator
;
530 OUString aSignCertificateSubjectName
;
531 OUString aSignCertificateCertPem
;
532 OUString aSignCertificateKeyPem
;
533 OUString aSignCertificateCaPem
;
534 for ( const beans::PropertyValue
& rProp
: rFilterData
)
536 if ( rProp
.Name
== "PageRange" )
537 rProp
.Value
>>= aPageRange
;
538 else if ( rProp
.Name
== "SheetRange" )
540 Reference
< frame::XController
> xController( Reference
< frame::XModel
>( mxSrcDoc
, UNO_QUERY_THROW
)->getCurrentController() );
541 Reference
< sheet::XSheetRange
> xView( xController
, UNO_QUERY
);
542 OUString aSheetRange
;
543 rProp
.Value
>>= aSheetRange
;
544 aSelection
= xView
->getSelectionFromString(aSheetRange
);
546 else if ( rProp
.Name
== "Selection" )
547 aSelection
= rProp
.Value
;
548 else if ( rProp
.Name
== "UseLosslessCompression" )
549 rProp
.Value
>>= mbUseLosslessCompression
;
550 else if ( rProp
.Name
== "Quality" )
551 rProp
.Value
>>= mnQuality
;
552 else if ( rProp
.Name
== "ReduceImageResolution" )
553 rProp
.Value
>>= mbReduceImageResolution
;
554 else if ( rProp
.Name
== "IsSkipEmptyPages" )
555 rProp
.Value
>>= mbSkipEmptyPages
;
556 else if ( rProp
.Name
== "MaxImageResolution" )
557 rProp
.Value
>>= mnMaxImageResolution
;
558 else if ( rProp
.Name
== "UseTaggedPDF" )
559 rProp
.Value
>>= bUseTaggedPDF
;
560 else if ( rProp
.Name
== "SelectPdfVersion" )
561 rProp
.Value
>>= nPDFTypeSelection
;
562 else if ( rProp
.Name
== "PDFUACompliance" )
563 rProp
.Value
>>= bPDFUACompliance
;
564 else if ( rProp
.Name
== "ExportNotes" )
565 rProp
.Value
>>= bExportNotes
;
566 else if ( rProp
.Name
== "ExportNotesInMargin" )
567 rProp
.Value
>>= bExportNotesInMargin
;
568 else if ( rProp
.Name
== "ExportNotesPages" )
569 rProp
.Value
>>= bExportNotesPages
;
570 else if ( rProp
.Name
== "ExportOnlyNotesPages" )
571 rProp
.Value
>>= bExportOnlyNotesPages
;
572 else if ( rProp
.Name
== "UseTransitionEffects" )
573 rProp
.Value
>>= bUseTransitionEffects
;
574 else if ( rProp
.Name
== "ExportFormFields" )
575 rProp
.Value
>>= bExportFormFields
;
576 else if ( rProp
.Name
== "FormsType" )
577 rProp
.Value
>>= nFormsFormat
;
578 else if ( rProp
.Name
== "AllowDuplicateFieldNames" )
579 rProp
.Value
>>= bAllowDuplicateFieldNames
;
581 else if ( rProp
.Name
== "HideViewerToolbar" )
582 rProp
.Value
>>= bHideViewerToolbar
;
583 else if ( rProp
.Name
== "HideViewerMenubar" )
584 rProp
.Value
>>= bHideViewerMenubar
;
585 else if ( rProp
.Name
== "HideViewerWindowControls" )
586 rProp
.Value
>>= bHideViewerWindowControls
;
587 else if ( rProp
.Name
== "ResizeWindowToInitialPage" )
588 rProp
.Value
>>= bFitWindow
;
589 else if ( rProp
.Name
== "CenterWindow" )
590 rProp
.Value
>>= bCenterWindow
;
591 else if ( rProp
.Name
== "OpenInFullScreenMode" )
592 rProp
.Value
>>= bOpenInFullScreenMode
;
593 else if ( rProp
.Name
== "DisplayPDFDocumentTitle" )
594 rProp
.Value
>>= bDisplayPDFDocumentTitle
;
595 else if ( rProp
.Name
== "InitialView" )
596 rProp
.Value
>>= nPDFDocumentMode
;
597 else if ( rProp
.Name
== "Magnification" )
598 rProp
.Value
>>= nPDFDocumentAction
;
599 else if ( rProp
.Name
== "Zoom" )
600 rProp
.Value
>>= nZoom
;
601 else if ( rProp
.Name
== "InitialPage" )
602 rProp
.Value
>>= nInitialPage
;
603 else if ( rProp
.Name
== "PageLayout" )
604 rProp
.Value
>>= nPDFPageLayout
;
605 else if ( rProp
.Name
== "FirstPageOnLeft" )
606 rProp
.Value
>>= aContext
.FirstPageLeft
;
607 else if ( rProp
.Name
== "IsAddStream" )
608 rProp
.Value
>>= bAddStream
;
609 else if ( rProp
.Name
== "Watermark" )
610 rProp
.Value
>>= msWatermark
;
611 else if ( rProp
.Name
== "WatermarkColor" )
614 if (rProp
.Value
>>= nColor
)
616 maWatermarkColor
= Color(ColorTransparency
, nColor
);
619 else if (rProp
.Name
== "WatermarkFontHeight")
621 sal_Int32 nFontHeight
{};
622 if (rProp
.Value
>>= nFontHeight
)
624 moWatermarkFontHeight
= nFontHeight
;
627 else if (rProp
.Name
== "WatermarkRotateAngle")
629 sal_Int32 nRotateAngle
{};
630 if (rProp
.Value
>>= nRotateAngle
)
632 moWatermarkRotateAngle
= Degree10(nRotateAngle
);
635 else if (rProp
.Name
== "WatermarkFontName")
637 OUString aFontName
{};
638 if (rProp
.Value
>>= aFontName
)
640 maWatermarkFontName
= aFontName
;
643 else if ( rProp
.Name
== "TiledWatermark" )
644 rProp
.Value
>>= msTiledWatermark
;
645 // now all the security related properties...
646 else if ( rProp
.Name
== "EncryptFile" )
647 rProp
.Value
>>= bEncrypt
;
648 else if ( rProp
.Name
== "DocumentOpenPassword" )
649 rProp
.Value
>>= aOpenPassword
;
650 else if ( rProp
.Name
== "RestrictPermissions" )
651 rProp
.Value
>>= bRestrictPermissions
;
652 else if ( rProp
.Name
== "PermissionPassword" )
653 rProp
.Value
>>= aPermissionPassword
;
654 else if ( rProp
.Name
== "PreparedPasswords" )
655 rProp
.Value
>>= xEnc
;
656 else if ( rProp
.Name
== "PreparedPermissionPassword" )
657 rProp
.Value
>>= aPreparedPermissionPassword
;
658 else if ( rProp
.Name
== "Printing" )
659 rProp
.Value
>>= nPrintAllowed
;
660 else if ( rProp
.Name
== "Changes" )
661 rProp
.Value
>>= nChangesAllowed
;
662 else if ( rProp
.Name
== "EnableCopyingOfContent" )
663 rProp
.Value
>>= bCanCopyOrExtract
;
664 else if ( rProp
.Name
== "EnableTextAccessForAccessibilityTools" )
665 rProp
.Value
>>= bCanExtractForAccessibility
;
666 // i56629 links extra (relative links and other related stuff)
667 else if ( rProp
.Name
== "ExportLinksRelativeFsys" )
668 rProp
.Value
>>= bExportRelativeFsysLinks
;
669 else if ( rProp
.Name
== "PDFViewSelection" )
670 rProp
.Value
>>= nDefaultLinkAction
;
671 else if ( rProp
.Name
== "ConvertOOoTargetToPDFTarget" )
672 rProp
.Value
>>= bConvertOOoTargetToPDFTarget
;
673 else if ( rProp
.Name
== "ExportBookmarksToPDFDestination" )
674 rProp
.Value
>>= bExportBmkToDest
;
675 else if ( rProp
.Name
== "ExportBookmarks" )
676 rProp
.Value
>>= bExportBookmarks
;
677 else if ( rProp
.Name
== "ExportHiddenSlides" )
678 rProp
.Value
>>= bExportHiddenSlides
;
679 else if ( rProp
.Name
== "SinglePageSheets" )
680 rProp
.Value
>>= bSinglePageSheets
;
681 else if ( rProp
.Name
== "OpenBookmarkLevels" )
682 rProp
.Value
>>= nOpenBookmarkLevels
;
683 else if ( rProp
.Name
== "SignPDF" )
684 rProp
.Value
>>= bSignPDF
;
685 else if ( rProp
.Name
== "SignatureLocation" )
686 rProp
.Value
>>= sSignLocation
;
687 else if ( rProp
.Name
== "SignatureReason" )
688 rProp
.Value
>>= sSignReason
;
689 else if ( rProp
.Name
== "SignatureContactInfo" )
690 rProp
.Value
>>= sSignContact
;
691 else if ( rProp
.Name
== "SignaturePassword" )
692 rProp
.Value
>>= sSignPassword
;
693 else if ( rProp
.Name
== "SignatureCertificate" )
694 rProp
.Value
>>= aSignCertificate
;
695 else if (rProp
.Name
== "SignCertificateSubjectName")
696 rProp
.Value
>>= aSignCertificateSubjectName
;
697 else if (rProp
.Name
== "SignCertificateCertPem")
698 rProp
.Value
>>= aSignCertificateCertPem
;
699 else if (rProp
.Name
== "SignCertificateKeyPem")
700 rProp
.Value
>>= aSignCertificateKeyPem
;
701 else if (rProp
.Name
== "SignCertificateCaPem")
702 rProp
.Value
>>= aSignCertificateCaPem
;
703 else if ( rProp
.Name
== "SignatureTSA" )
704 rProp
.Value
>>= sSignTSA
;
705 else if ( rProp
.Name
== "ExportPlaceholders" )
706 rProp
.Value
>>= bExportPlaceholders
;
707 else if ( rProp
.Name
== "UseReferenceXObject" )
708 rProp
.Value
>>= bUseReferenceXObject
;
709 // Redaction & bitmap related stuff
710 else if ( rProp
.Name
== "IsRedactMode" )
711 rProp
.Value
>>= mbIsRedactMode
;
712 // Math-specific render options
713 else if (rProp
.Name
== "TitleRow")
714 oMathTitleRow
= rProp
;
715 else if (rProp
.Name
== "FormulaText")
716 oMathFormulaText
= rProp
;
717 else if (rProp
.Name
== "Border")
719 else if (rProp
.Name
== "PrintFormat")
720 oMathPrintFormat
= rProp
;
721 else if (rProp
.Name
== "PrintScale")
722 oMathPrintScale
= rProp
;
725 if (!aSignCertificate
.is() && !aSignCertificateSubjectName
.isEmpty())
727 aSignCertificate
= GetCertificateFromSubjectName(aSignCertificateSubjectName
);
730 if (!aSignCertificate
.is())
732 // Still no signing certificate configured, see if we got a ca/cert/key in PEM
734 if (!aSignCertificateCaPem
.isEmpty())
736 std::string
aSignatureCa(aSignCertificateCaPem
.toUtf8());
737 std::vector
<std::string
> aCerts
= SfxLokHelper::extractCertificates(aSignatureCa
);
738 SfxLokHelper::addCertificates(aCerts
);
740 if (!aSignCertificateCertPem
.isEmpty() && !aSignCertificateKeyPem
.isEmpty())
742 std::string
aSignatureCert(aSignCertificateCertPem
.toUtf8());
743 std::string
aSignatureKey(aSignCertificateKeyPem
.toUtf8());
744 aSignCertificate
= SfxLokHelper::getSigningCertificate(aSignatureCert
, aSignatureKey
);
748 aContext
.URL
= aURL
.GetMainURL(INetURLObject::DecodeMechanism::ToIUri
);
750 // set the correct version, depending on user request
751 switch( nPDFTypeSelection
)
755 aContext
.Version
= vcl::PDFWriter::PDFVersion::Default
;
758 aContext
.Version
= vcl::PDFWriter::PDFVersion::PDF_A_1
;
759 bUseTaggedPDF
= true; // force the tagged PDF as well
760 mbRemoveTransparencies
= true; // does not allow transparencies
761 bEncrypt
= false; // no encryption
765 aContext
.Version
= vcl::PDFWriter::PDFVersion::PDF_A_2
;
766 bUseTaggedPDF
= true; // force the tagged PDF as well
767 mbRemoveTransparencies
= false; // does allow transparencies
768 bEncrypt
= false; // no encryption
772 aContext
.Version
= vcl::PDFWriter::PDFVersion::PDF_A_3
;
773 bUseTaggedPDF
= true; // force the tagged PDF as well
774 mbRemoveTransparencies
= false; // does allow transparencies
775 bEncrypt
= false; // no encryption
779 // TODO - determine what is allowed for PDFA/4
780 aContext
.Version
= vcl::PDFWriter::PDFVersion::PDF_A_4
;
781 bUseTaggedPDF
= true; // force the tagged PDF as well
782 mbRemoveTransparencies
= false; // does allow transparencies
783 bEncrypt
= false; // no encryption
787 aContext
.Version
= vcl::PDFWriter::PDFVersion::PDF_1_5
;
790 aContext
.Version
= vcl::PDFWriter::PDFVersion::PDF_1_6
;
793 aContext
.Version
= vcl::PDFWriter::PDFVersion::PDF_1_7
;
796 aContext
.Version
= vcl::PDFWriter::PDFVersion::PDF_2_0
;
801 aContext
.UniversalAccessibilityCompliance
= bPDFUACompliance
;
802 if (bPDFUACompliance
)
804 // ISO 14289-1:2014, Clause: 7.1
805 bUseTaggedPDF
= true;
806 // ISO 14289-1:2014, Clause: 7.16
807 bCanExtractForAccessibility
= true;
808 // ISO 14289-1:2014, Clause: 7.20
809 bUseReferenceXObject
= false;
812 // copy in context the values default in the constructor or set by the FilterData sequence of properties
813 aContext
.Tagged
= bUseTaggedPDF
;
815 // values used in viewer
816 aContext
.HideViewerToolbar
= bHideViewerToolbar
;
817 aContext
.HideViewerMenubar
= bHideViewerMenubar
;
818 aContext
.HideViewerWindowControls
= bHideViewerWindowControls
;
819 aContext
.FitWindow
= bFitWindow
;
820 aContext
.CenterWindow
= bCenterWindow
;
821 aContext
.OpenInFullScreenMode
= bOpenInFullScreenMode
;
822 aContext
.DisplayPDFDocumentTitle
= bDisplayPDFDocumentTitle
;
823 aContext
.InitialPage
= nInitialPage
-1;
824 aContext
.OpenBookmarkLevels
= nOpenBookmarkLevels
;
826 switch( nPDFDocumentMode
)
830 aContext
.PDFDocumentMode
= vcl::PDFWriter::ModeDefault
;
833 aContext
.PDFDocumentMode
= vcl::PDFWriter::UseOutlines
;
836 aContext
.PDFDocumentMode
= vcl::PDFWriter::UseThumbs
;
839 switch( nPDFDocumentAction
)
843 aContext
.PDFDocumentAction
= vcl::PDFWriter::ActionDefault
;
846 aContext
.PDFDocumentAction
= vcl::PDFWriter::FitInWindow
;
849 aContext
.PDFDocumentAction
= vcl::PDFWriter::FitWidth
;
852 aContext
.PDFDocumentAction
= vcl::PDFWriter::FitVisible
;
855 aContext
.PDFDocumentAction
= vcl::PDFWriter::ActionZoom
;
856 aContext
.Zoom
= nZoom
;
860 switch( nPDFPageLayout
)
864 aContext
.PageLayout
= vcl::PDFWriter::DefaultLayout
;
867 aContext
.PageLayout
= vcl::PDFWriter::SinglePage
;
870 aContext
.PageLayout
= vcl::PDFWriter::Continuous
;
873 aContext
.PageLayout
= vcl::PDFWriter::ContinuousFacing
;
877 aContext
.FirstPageLeft
= false;
879 // check if PDF/A, which does not allow encryption
880 if( aContext
.Version
!= vcl::PDFWriter::PDFVersion::PDF_A_1
)
882 // set check for permission change password
883 // if not enabled and no permission password, force permissions to default as if PDF where without encryption
884 if( bRestrictPermissions
&& (xEnc
.is() || !aPermissionPassword
.isEmpty()) )
886 bEncrypt
= true; // permission set as desired, done after
890 // force permission to default
892 nChangesAllowed
= 4 ;
893 bCanCopyOrExtract
= true;
894 bCanExtractForAccessibility
= true ;
897 switch( nPrintAllowed
)
899 case 0: // initialized when aContext is build, means no printing
903 aContext
.Encryption
.CanPrintFull
= true;
906 aContext
.Encryption
.CanPrintTheDocument
= true;
910 switch( nChangesAllowed
)
912 case 0: // already in struct PDFSecPermissions CTOR
915 aContext
.Encryption
.CanAssemble
= true;
918 aContext
.Encryption
.CanFillInteractive
= true;
921 aContext
.Encryption
.CanAddOrModify
= true;
925 aContext
.Encryption
.CanModifyTheContent
=
926 aContext
.Encryption
.CanCopyOrExtract
=
927 aContext
.Encryption
.CanAddOrModify
=
928 aContext
.Encryption
.CanFillInteractive
= true;
932 aContext
.Encryption
.CanCopyOrExtract
= bCanCopyOrExtract
;
933 aContext
.Encryption
.CanExtractForAccessibility
= bCanExtractForAccessibility
;
934 if( bEncrypt
&& ! xEnc
.is() )
935 xEnc
= vcl::pdf::initEncryption(aPermissionPassword
, aOpenPassword
);
936 if( bEncrypt
&& !aPermissionPassword
.isEmpty() && ! aPreparedPermissionPassword
.hasElements() )
937 aPreparedPermissionPassword
= comphelper::OStorageHelper::CreatePackageEncryptionData( aPermissionPassword
);
939 // after this point we don't need the legacy clear passwords anymore
940 // however they are still inside the passed filter data sequence
941 // which is sadly out of our control
942 aPermissionPassword
.clear();
943 aOpenPassword
.clear();
946 * FIXME: the entries are only implicitly defined by the resource file. Should there
947 * ever be an additional form submit format this could get invalid.
949 switch( nFormsFormat
)
952 aContext
.SubmitFormat
= vcl::PDFWriter::PDF
;
955 aContext
.SubmitFormat
= vcl::PDFWriter::HTML
;
958 aContext
.SubmitFormat
= vcl::PDFWriter::XML
;
962 aContext
.SubmitFormat
= vcl::PDFWriter::FDF
;
965 aContext
.AllowDuplicateFieldNames
= bAllowDuplicateFieldNames
;
968 Reference
< frame::XModel
> xModel( mxSrcDoc
, UNO_QUERY
);
970 // #i56629: Relative link stuff
971 // set the base URL of the file: then base URL
972 aContext
.BaseURL
= xModel
->getURL();
973 // relative link option is private to PDF Export filter and limited to local filesystem only
974 aContext
.RelFsys
= bExportRelativeFsysLinks
;
975 // determine the default action for PDF links
976 switch( nDefaultLinkAction
)
979 // default: URI, without fragment conversion (the bookmark in PDF may not work)
981 aContext
.DefaultLinkAction
= vcl::PDFWriter::URIAction
;
984 // view PDF through the reader application
985 aContext
.ForcePDFAction
= true;
986 aContext
.DefaultLinkAction
= vcl::PDFWriter::LaunchAction
;
989 // view PDF through an Internet browser
990 aContext
.DefaultLinkAction
= vcl::PDFWriter::URIActionDestination
;
993 aContext
.ConvertOOoTargetToPDFTarget
= bConvertOOoTargetToPDFTarget
;
995 // check for Link Launch action, not allowed on PDF/A-1
996 // this code chunk checks when the filter is called from scripting
997 if( aContext
.Version
== vcl::PDFWriter::PDFVersion::PDF_A_1
&&
998 aContext
.DefaultLinkAction
== vcl::PDFWriter::LaunchAction
)
1000 // force the similar allowed URI action
1001 aContext
.DefaultLinkAction
= vcl::PDFWriter::URIActionDestination
;
1002 // and remove the remote goto action forced on PDF file
1003 aContext
.ForcePDFAction
= false;
1007 aContext
.SignPDF
= bSignPDF
;
1008 aContext
.SignLocation
= sSignLocation
;
1009 aContext
.SignContact
= sSignContact
;
1010 aContext
.SignReason
= sSignReason
;
1011 aContext
.SignPassword
= sSignPassword
;
1012 aContext
.SignCertificate
= std::move(aSignCertificate
);
1013 aContext
.SignTSA
= sSignTSA
;
1014 aContext
.UseReferenceXObject
= bUseReferenceXObject
;
1016 // all context data set, time to create the printing device
1017 vcl::PDFWriter
aPDFWriter( aContext
, xEnc
);
1018 OutputDevice
* pOut
= aPDFWriter
.GetReferenceDevice();
1020 DBG_ASSERT( pOut
, "PDFExport::Export: no reference device" );
1021 xDevice
->SetOutputDevice(pOut
);
1027 OUString aSrcMimetype
= getMimetypeForDocument( mxContext
, mxSrcDoc
);
1029 if (aSrcMimetype
== "application/vnd.oasis.opendocument.text")
1031 else if (aSrcMimetype
== "application/vnd.oasis.opendocument.presentation")
1033 else if (aSrcMimetype
== "application/vnd.oasis.opendocument.spreadsheet")
1035 else if (aSrcMimetype
== "application/vnd.oasis.opendocument.graphics")
1037 std::unique_ptr
<vcl::PDFOutputStream
> pStream(new PDFExportStreamDoc(mxSrcDoc
, aPreparedPermissionPassword
));
1038 aPDFWriter
.AddAttachedFile("Original" + aExt
, aSrcMimetype
, u
"Embedded original document of this PDF file"_ustr
, std::move(pStream
));
1043 DBG_ASSERT( pOut
->GetExtOutDevData() == nullptr, "PDFExport: ExtOutDevData already set!!!" );
1044 vcl::PDFExtOutDevData
aPDFExtOutDevData( *pOut
);
1045 pOut
->SetExtOutDevData( &aPDFExtOutDevData
);
1046 aPDFExtOutDevData
.SetIsExportNotes( bExportNotes
);
1047 aPDFExtOutDevData
.SetIsExportNotesInMargin( bExportNotesInMargin
);
1048 aPDFExtOutDevData
.SetIsExportTaggedPDF( bUseTaggedPDF
);
1049 aPDFExtOutDevData
.SetIsExportTransitionEffects( bUseTransitionEffects
);
1050 aPDFExtOutDevData
.SetIsExportFormFields( bExportFormFields
);
1051 aPDFExtOutDevData
.SetIsExportBookmarks( bExportBookmarks
);
1052 aPDFExtOutDevData
.SetIsExportHiddenSlides( bExportHiddenSlides
);
1053 aPDFExtOutDevData
.SetIsSinglePageSheets( bSinglePageSheets
);
1054 aPDFExtOutDevData
.SetIsLosslessCompression( mbUseLosslessCompression
);
1055 aPDFExtOutDevData
.SetCompressionQuality( mnQuality
);
1056 aPDFExtOutDevData
.SetIsReduceImageResolution( mbReduceImageResolution
);
1057 aPDFExtOutDevData
.SetIsExportNamedDestinations( bExportBmkToDest
);
1059 std::vector
<PropertyValue
> aRenderOptionsVector
{
1060 comphelper::makePropertyValue(u
"RenderDevice"_ustr
, uno::Reference
<awt::XDevice
>(xDevice
)),
1061 comphelper::makePropertyValue(u
"ExportNotesPages"_ustr
, false),
1062 comphelper::makePropertyValue(u
"IsFirstPage"_ustr
, true),
1063 comphelper::makePropertyValue(u
"IsLastPage"_ustr
, false),
1064 comphelper::makePropertyValue(u
"IsSkipEmptyPages"_ustr
, mbSkipEmptyPages
),
1065 comphelper::makePropertyValue(u
"PageRange"_ustr
, aPageRange
),
1066 comphelper::makePropertyValue(u
"ExportPlaceholders"_ustr
, bExportPlaceholders
),
1067 comphelper::makePropertyValue(u
"SinglePageSheets"_ustr
, bSinglePageSheets
),
1068 comphelper::makePropertyValue(u
"ExportNotesInMargin"_ustr
, bExportNotesInMargin
)
1071 aRenderOptionsVector
.push_back(*oMathTitleRow
);
1072 if (oMathFormulaText
)
1073 aRenderOptionsVector
.push_back(*oMathFormulaText
);
1075 aRenderOptionsVector
.push_back(*oMathBorder
);
1076 if (oMathPrintFormat
)
1077 aRenderOptionsVector
.push_back(*oMathPrintFormat
);
1078 if (oMathPrintScale
)
1079 aRenderOptionsVector
.push_back(*oMathPrintScale
);
1080 Sequence aRenderOptions
= comphelper::containerToSequence(aRenderOptionsVector
);
1081 Any
& rExportNotesValue
= aRenderOptions
.getArray()[ 1 ].Value
;
1083 if( !aPageRange
.isEmpty() || !aSelection
.hasValue() )
1086 aSelection
<<= mxSrcDoc
;
1088 bool bReChangeToNormalView
= false;
1089 static constexpr OUString
sShowOnlineLayout( u
"ShowOnlineLayout"_ustr
);
1090 bool bReHideWhitespace
= false;
1091 static constexpr OUString
sHideWhitespace(u
"HideWhitespace"_ustr
);
1092 uno::Reference
< beans::XPropertySet
> xViewProperties
;
1094 if ( aCreator
== "Writer" )
1096 // #i92835: if Writer is in web layout mode this has to be switched to normal view and back to web view in the end
1099 Reference
< view::XViewSettingsSupplier
> xVSettingsSupplier( xModel
->getCurrentController(), uno::UNO_QUERY_THROW
);
1100 xViewProperties
= xVSettingsSupplier
->getViewSettings();
1101 xViewProperties
->getPropertyValue( sShowOnlineLayout
) >>= bReChangeToNormalView
;
1102 if( bReChangeToNormalView
)
1104 xViewProperties
->setPropertyValue( sShowOnlineLayout
, uno::Any( false ) );
1107 // Also, disable hide-whitespace during export.
1108 xViewProperties
->getPropertyValue(sHideWhitespace
) >>= bReHideWhitespace
;
1109 if (bReHideWhitespace
)
1111 xViewProperties
->setPropertyValue(sHideWhitespace
, uno::Any(false));
1114 catch( const uno::Exception
& )
1120 const sal_Int32 nPageCount
= xRenderable
->getRendererCount( aSelection
, aRenderOptions
);
1122 if ( bExportNotesPages
&& aCreator
== "Impress" )
1124 uno::Reference
< drawing::XShapes
> xShapes
; // do not allow to export notes when exporting a selection
1125 if ( aSelection
>>= xShapes
)
1126 bExportNotesPages
= false;
1129 bExportNotesPages
= false;
1130 const bool bExportPages
= !bExportNotesPages
|| !bExportOnlyNotesPages
;
1132 if( aPageRange
.isEmpty() || bSinglePageSheets
)
1134 aPageRange
= OUString::number( 1 ) + "-" + OUString::number(nPageCount
);
1136 StringRangeEnumerator
aRangeEnum( aPageRange
, 0, nPageCount
-1 );
1138 if ( mxStatusIndicator
.is() )
1140 sal_Int32 nTotalPageCount
= aRangeEnum
.size();
1141 if ( bExportPages
&& bExportNotesPages
)
1142 nTotalPageCount
*= 2;
1143 mxStatusIndicator
->start(FilterResId(PDF_PROGRESS_BAR
), nTotalPageCount
);
1146 bRet
= nPageCount
> 0;
1148 if ( bRet
&& bExportPages
)
1149 bRet
= ExportSelection( aPDFWriter
, xRenderable
, aSelection
, aRangeEnum
, aRenderOptions
, nPageCount
);
1151 if ( bRet
&& bExportNotesPages
)
1153 rExportNotesValue
<<= true;
1154 bRet
= ExportSelection( aPDFWriter
, xRenderable
, aSelection
, aRangeEnum
, aRenderOptions
, nPageCount
);
1156 if ( mxStatusIndicator
.is() )
1157 mxStatusIndicator
->end();
1159 // if during the export the doc locale was set copy it to PDF writer
1160 const css::lang::Locale
& rLoc( aPDFExtOutDevData
.GetDocumentLocale() );
1161 if( !rLoc
.Language
.isEmpty() )
1162 aPDFWriter
.SetDocumentLocale( rLoc
);
1166 aPDFExtOutDevData
.PlayGlobalActions( aPDFWriter
);
1167 bRet
= aPDFWriter
.Emit();
1168 aErrors
= aPDFWriter
.GetErrors();
1170 pOut
->SetExtOutDevData( nullptr );
1171 if( bReChangeToNormalView
)
1175 xViewProperties
->setPropertyValue( sShowOnlineLayout
, uno::Any( true ) );
1177 catch( const uno::Exception
& )
1181 if( bReHideWhitespace
)
1185 xViewProperties
->setPropertyValue( sHideWhitespace
, uno::Any( true ) );
1187 catch( const uno::Exception
& )
1195 // show eventual errors during export
1196 showErrors( aErrors
);
1205 typedef comphelper::WeakComponentImplHelper
< task::XInteractionRequest
> PDFErrorRequestBase
;
1207 class PDFErrorRequest
: public PDFErrorRequestBase
1209 task::PDFExportException maExc
;
1211 explicit PDFErrorRequest( task::PDFExportException aExc
);
1213 // XInteractionRequest
1214 virtual uno::Any SAL_CALL
getRequest() override
;
1215 virtual uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > SAL_CALL
getContinuations() override
;
1219 PDFErrorRequest::PDFErrorRequest( task::PDFExportException aExc
) :
1220 maExc(std::move( aExc
))
1225 uno::Any SAL_CALL
PDFErrorRequest::getRequest()
1227 std::unique_lock
guard( m_aMutex
);
1235 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > SAL_CALL
PDFErrorRequest::getContinuations()
1237 return uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> >();
1240 } // end anonymous namespace
1243 void PDFExport::showErrors( const std::set
< vcl::PDFWriter::ErrorCode
>& rErrors
)
1245 if( ! rErrors
.empty() && mxIH
.is() )
1247 task::PDFExportException aExc
;
1248 aExc
.ErrorCodes
= comphelper::containerToSequence
<sal_Int32
>( rErrors
);
1249 Reference
< task::XInteractionRequest
> xReq( new PDFErrorRequest( std::move(aExc
) ) );
1250 mxIH
->handle( xReq
);
1255 void PDFExport::ImplExportPage( vcl::PDFWriter
& rWriter
, vcl::PDFExtOutDevData
& rPDFExtOutDevData
, const GDIMetaFile
& rMtf
)
1257 //Rectangle(Point, Size) creates a rectangle off by 1, use Rectangle(long, long, long, long) instead
1258 basegfx::B2DPolygon
aSize(tools::Polygon(tools::Rectangle(0, 0, rMtf
.GetPrefSize().Width(), rMtf
.GetPrefSize().Height())).getB2DPolygon());
1259 basegfx::B2DPolygon
aSizePDF(OutputDevice::LogicToLogic(aSize
, rMtf
.GetPrefMapMode(), MapMode(MapUnit::MapPoint
)));
1260 basegfx::B2DRange
aRangePDF(aSizePDF
.getB2DRange());
1261 tools::Rectangle
aPageRect( Point(), rMtf
.GetPrefSize() );
1263 rWriter
.NewPage( aRangePDF
.getWidth(), aRangePDF
.getHeight() );
1264 rWriter
.SetMapMode( rMtf
.GetPrefMapMode() );
1266 vcl::PDFWriter::PlayMetafileContext aCtx
;
1268 if( mbRemoveTransparencies
)
1270 aCtx
.m_bTransparenciesWereRemoved
= rWriter
.GetReferenceDevice()->
1271 RemoveTransparenciesFromMetaFile( rMtf
, aMtf
, mnMaxImageResolution
, mnMaxImageResolution
,
1272 false, true, mbReduceImageResolution
);
1273 // tdf#134736 if the metafile was replaced then rPDFExtOutDevData's PageSyncData mActions
1274 // all still point to MetaAction indexes in the original metafile that are now invalid.
1275 // Throw them all away in the absence of a way to reposition them to new positions of
1276 // their replacements.
1277 if (aCtx
.m_bTransparenciesWereRemoved
)
1278 rPDFExtOutDevData
.ResetSyncData(&rWriter
);
1284 aCtx
.m_nMaxImageResolution
= mbReduceImageResolution
? mnMaxImageResolution
: 0;
1285 aCtx
.m_bOnlyLosslessCompression
= mbUseLosslessCompression
;
1286 aCtx
.m_nJPEGQuality
= mnQuality
;
1289 rWriter
.SetClipRegion( basegfx::B2DPolyPolygon(
1290 basegfx::utils::createPolygonFromRect( vcl::unotools::b2DRectangleFromRectangle(aPageRect
) ) ) );
1292 rWriter
.PlayMetafile( aMtf
, aCtx
, &rPDFExtOutDevData
);
1294 rPDFExtOutDevData
.ResetSyncData(nullptr);
1296 if (!msWatermark
.isEmpty())
1298 ImplWriteWatermark( rWriter
, Size(aRangePDF
.getWidth(), aRangePDF
.getHeight()) );
1300 else if (!msTiledWatermark
.isEmpty())
1302 ImplWriteTiledWatermark( rWriter
, Size(aRangePDF
.getWidth(), aRangePDF
.getHeight()) );
1307 void PDFExport::ImplWriteWatermark( vcl::PDFWriter
& rWriter
, const Size
& rPageSize
)
1309 vcl::Font
aFont( maWatermarkFontName
, Size( 0, moWatermarkFontHeight
? *moWatermarkFontHeight
: 3*rPageSize
.Height()/4 ) );
1310 aFont
.SetItalic( ITALIC_NONE
);
1311 aFont
.SetWidthType( WIDTH_NORMAL
);
1312 aFont
.SetWeight( WEIGHT_NORMAL
);
1313 aFont
.SetAlignment( ALIGN_BOTTOM
);
1314 tools::Long nTextWidth
= rPageSize
.Width();
1315 if( rPageSize
.Width() < rPageSize
.Height() )
1317 nTextWidth
= rPageSize
.Height();
1318 aFont
.SetOrientation( 2700_deg10
);
1321 if (moWatermarkRotateAngle
)
1323 aFont
.SetOrientation(*moWatermarkRotateAngle
);
1324 if (rPageSize
.Width() < rPageSize
.Height())
1326 // Set text width based on the shorter side, so rotation can't push text outside the
1328 nTextWidth
= rPageSize
.Width();
1332 // adjust font height for text to fit
1333 OutputDevice
* pDev
= rWriter
.GetReferenceDevice();
1335 pDev
->SetFont( aFont
);
1336 pDev
->SetMapMode( MapMode( MapUnit::MapPoint
) );
1338 if (moWatermarkFontHeight
)
1340 w
= pDev
->GetTextWidth(msWatermark
);
1344 while( ( w
= pDev
->GetTextWidth( msWatermark
) ) > nTextWidth
)
1348 tools::Long nNewHeight
= aFont
.GetFontHeight() * nTextWidth
/ w
;
1349 if( nNewHeight
== aFont
.GetFontHeight() )
1352 if( nNewHeight
<= 0 )
1355 aFont
.SetFontHeight( nNewHeight
);
1356 pDev
->SetFont( aFont
);
1359 tools::Long nTextHeight
= pDev
->GetTextHeight();
1360 // leave some maneuvering room for rounding issues, also
1361 // some fonts go a little outside ascent/descent
1362 nTextHeight
+= nTextHeight
/20;
1366 // tdf#152235 tag around the reference to the XObject on the page
1367 sal_Int32
const id
= rWriter
.EnsureStructureElement();
1368 rWriter
.InitStructureElement(id
, vcl::pdf::StructElement::NonStructElement
, ::std::u16string_view());
1369 rWriter
.BeginStructureElement(id
);
1370 rWriter
.SetStructureAttribute(vcl::PDFWriter::Type
, vcl::PDFWriter::Pagination
);
1371 rWriter
.SetStructureAttribute(vcl::PDFWriter::Subtype
, vcl::PDFWriter::Watermark
);
1372 // HACK: this should produce *nothing* itself but is necessary to output
1373 // the Artifact tag here, not inside the XObject
1374 rWriter
.DrawPolyLine({});
1375 rWriter
.SetMapMode( MapMode( MapUnit::MapPoint
) );
1376 rWriter
.SetFont( aFont
);
1377 rWriter
.SetTextColor(maWatermarkColor
);
1379 tools::Rectangle aTextRect
;
1380 if( rPageSize
.Width() > rPageSize
.Height() )
1382 aTextPoint
= Point( (rPageSize
.Width()-w
)/2,
1383 rPageSize
.Height()-(rPageSize
.Height()-nTextHeight
)/2 );
1384 aTextRect
= tools::Rectangle( Point( (rPageSize
.Width()-w
)/2,
1385 (rPageSize
.Height()-nTextHeight
)/2 ),
1386 Size( w
, nTextHeight
) );
1390 aTextPoint
= Point( (rPageSize
.Width()-nTextHeight
)/2,
1391 (rPageSize
.Height()-w
)/2 );
1392 aTextRect
= tools::Rectangle( aTextPoint
, Size( nTextHeight
, w
) );
1395 if (moWatermarkRotateAngle
)
1397 // First set the text's starting point to the center of the page.
1398 tools::Rectangle
aPageRectangle(Point(0, 0), rPageSize
);
1399 aTextPoint
= aPageRectangle
.Center();
1400 // Then adjust it so that the text remains centered, based on the rotation angle.
1401 basegfx::B2DPolygon aTextPolygon
1402 = basegfx::utils::createPolygonFromRect(basegfx::B2DRectangle(0, -nTextHeight
, w
, 0));
1403 basegfx::B2DHomMatrix aMatrix
;
1404 aMatrix
.rotate(-1 * toRadians(*moWatermarkRotateAngle
));
1405 aTextPolygon
.transform(aMatrix
);
1406 basegfx::B2DPoint aPolygonCenter
= aTextPolygon
.getB2DRange().getCenter();
1407 aTextPoint
.AdjustX(-aPolygonCenter
.getX());
1408 aTextPoint
.AdjustY(-aPolygonCenter
.getY());
1410 aTextRect
= aPageRectangle
;
1413 rWriter
.SetClipRegion();
1414 rWriter
.BeginTransparencyGroup();
1415 rWriter
.DrawText( aTextPoint
, msWatermark
);
1416 rWriter
.EndTransparencyGroup( aTextRect
, 50 );
1417 rWriter
.EndStructureElement();
1421 void PDFExport::ImplWriteTiledWatermark( vcl::PDFWriter
& rWriter
, const Size
& rPageSize
)
1423 OUString watermark
= msTiledWatermark
;
1424 // Maximum number of characters in one line.
1425 // it is set to 21 to make it look like tiled watermarks as online in secure view
1426 const int lineLength
= 21;
1427 vcl::Font
aFont( u
"Liberation Sans"_ustr
, Size( 0, 40 ) );
1428 aFont
.SetItalic( ITALIC_NONE
);
1429 aFont
.SetWidthType( WIDTH_NORMAL
);
1430 aFont
.SetWeight( WEIGHT_NORMAL
);
1431 aFont
.SetAlignment( ALIGN_BOTTOM
);
1432 aFont
.SetFontHeight(40);
1433 aFont
.SetOrientation(450_deg10
);
1435 OutputDevice
* pDev
= rWriter
.GetReferenceDevice();
1436 pDev
->SetFont(aFont
);
1438 pDev
->SetFont(aFont
);
1439 pDev
->SetMapMode( MapMode( MapUnit::MapPoint
) );
1441 int watermarkcount
= ((rPageSize
.Width()) / 200)+1;
1442 tools::Long nTextWidth
= rPageSize
.Width() / (watermarkcount
*1.5);
1443 OUString oneLineText
= watermark
;
1445 if(watermark
.getLength() > lineLength
)
1446 oneLineText
= watermark
.copy(0, lineLength
);
1448 while((w
= pDev
->GetTextWidth(oneLineText
)) > nTextWidth
)
1453 tools::Long nNewHeight
= aFont
.GetFontHeight() * nTextWidth
/ w
;
1454 aFont
.SetFontHeight(nNewHeight
);
1455 pDev
->SetFont( aFont
);
1457 // maximum number of watermark count for the width
1458 if(watermarkcount
> 8)
1464 // tdf#152235 tag around the reference to the XObject on the page
1465 sal_Int32
const id
= rWriter
.EnsureStructureElement();
1466 rWriter
.InitStructureElement(id
, vcl::pdf::StructElement::NonStructElement
, ::std::u16string_view());
1467 rWriter
.BeginStructureElement(id
);
1468 rWriter
.SetStructureAttribute(vcl::PDFWriter::Type
, vcl::PDFWriter::Pagination
);
1469 rWriter
.SetStructureAttribute(vcl::PDFWriter::Subtype
, vcl::PDFWriter::Watermark
);
1470 // HACK: this should produce *nothing* itself but is necessary to output
1471 // the Artifact tag here, not inside the XObject
1472 rWriter
.DrawPolyLine({});
1473 rWriter
.SetMapMode( MapMode( MapUnit::MapPoint
) );
1474 rWriter
.SetFont(aFont
);
1475 rWriter
.SetTextColor( Color(19,20,22) );
1476 // center watermarks horizontally
1477 Point
aTextPoint( (rPageSize
.Width()/2) - (((nTextWidth
*watermarkcount
)+(watermarkcount
-1)*nTextWidth
)/2),
1478 pDev
->GetTextHeight());
1480 for( int i
= 0; i
< watermarkcount
; i
++)
1482 while(aTextPoint
.getY()+pDev
->GetTextHeight()*3 <= rPageSize
.Height())
1484 tools::Rectangle
aTextRect(aTextPoint
, Size(nTextWidth
*2,pDev
->GetTextHeight()*4));
1487 rWriter
.SetClipRegion();
1488 rWriter
.BeginTransparencyGroup();
1489 rWriter
.SetTextColor( Color(19,20,22) );
1490 rWriter
.DrawText(aTextRect
, watermark
, DrawTextFlags::MultiLine
|DrawTextFlags::Center
|DrawTextFlags::VCenter
|DrawTextFlags::WordBreak
|DrawTextFlags::Bottom
);
1491 rWriter
.EndTransparencyGroup( aTextRect
, 50 );
1495 rWriter
.SetClipRegion();
1496 rWriter
.BeginTransparencyGroup();
1497 rWriter
.SetTextColor( Color(236,235,233) );
1498 rWriter
.DrawText(aTextRect
, watermark
, DrawTextFlags::MultiLine
|DrawTextFlags::Center
|DrawTextFlags::VCenter
|DrawTextFlags::WordBreak
|DrawTextFlags::Bottom
);
1499 rWriter
.EndTransparencyGroup( aTextRect
, 50 );
1502 aTextPoint
.Move(0, pDev
->GetTextHeight()*3);
1504 aTextPoint
=Point( aTextPoint
.getX(), pDev
->GetTextHeight() );
1505 aTextPoint
.Move( nTextWidth
*1.5, 0 );
1508 rWriter
.EndStructureElement();
1512 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */