summaryrefslogtreecommitdiffstats
path: root/filter/source/pdf
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /filter/source/pdf
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'filter/source/pdf')
-rw-r--r--filter/source/pdf/impdialog.cxx1638
-rw-r--r--filter/source/pdf/impdialog.hxx419
-rw-r--r--filter/source/pdf/pdfdecomposer.cxx123
-rw-r--r--filter/source/pdf/pdfdialog.cxx139
-rw-r--r--filter/source/pdf/pdfdialog.hxx72
-rw-r--r--filter/source/pdf/pdfexport.cxx1374
-rw-r--r--filter/source/pdf/pdfexport.hxx145
-rw-r--r--filter/source/pdf/pdffilter.component38
-rw-r--r--filter/source/pdf/pdffilter.cxx295
-rw-r--r--filter/source/pdf/pdffilter.hxx70
-rw-r--r--filter/source/pdf/pdfinteract.cxx97
-rw-r--r--filter/source/pdf/pdfinteract.hxx61
12 files changed, 4471 insertions, 0 deletions
diff --git a/filter/source/pdf/impdialog.cxx b/filter/source/pdf/impdialog.cxx
new file mode 100644
index 000000000..bd8db8369
--- /dev/null
+++ b/filter/source/pdf/impdialog.cxx
@@ -0,0 +1,1638 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "impdialog.hxx"
+#include <strings.hrc>
+#include <officecfg/Office/Common.hxx>
+#include <vcl/errinf.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <sfx2/passwd.hxx>
+#include <unotools/resmgr.hxx>
+#include <tools/diagnose_ex.h>
+#include <sfx2/objsh.hxx>
+#include <svx/AccessibilityCheckDialog.hxx>
+
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/storagehelper.hxx>
+
+#include <com/sun/star/text/XTextRange.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <com/sun/star/security/DocumentDigitalSignatures.hpp>
+#include <com/sun/star/beans/XMaterialHolder.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+static OUString PDFFilterResId(TranslateId aId)
+{
+ return Translate::get(aId, Translate::Create("flt"));
+}
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+/** Tabbed PDF dialog implementation
+ Please note: the default used here are the same as per specification,
+ They should be the same in PDFFilter::implExport and in PDFExport::PDFExport
+ */
+ImpPDFTabDialog::ImpPDFTabDialog(weld::Window* pParent, const Sequence< PropertyValue >& rFilterData,
+ const Reference< XComponent >& rxDoc)
+ : SfxTabDialogController(pParent, "filter/ui/pdfoptionsdialog.ui", "PdfOptionsDialog"),
+ mrDoc(rxDoc),
+ mpParent(pParent),
+ maConfigItem( u"Office.Common/Filter/PDF/Export/", &rFilterData ),
+ maConfigI18N( u"Office.Common/I18N/CTL/" ),
+ mbIsPresentation( false ),
+ mbIsSpreadsheet( false ),
+ mbIsWriter( false ),
+
+ mbSelectionPresent( false ),
+ mbUseCTLFont( false ),
+ mbUseLosslessCompression( true ),
+ mnQuality( 90 ),
+ mbReduceImageResolution( false ),
+ mnMaxImageResolution( 300 ),
+ mbUseTaggedPDF( false ),
+ mbUseTaggedPDFUserSelection( false ),
+ mbExportNotes( true ),
+ mbViewPDF( false ),
+ mbUseReferenceXObject( false ),
+ mbExportNotesPages( false ),
+ mbExportOnlyNotesPages( false ),
+ mbUseTransitionEffects( false ),
+ mbIsSkipEmptyPages( true ),
+ mbIsExportPlaceholders( false ),
+ mbAddStream( false ),
+ mnFormsType( 0 ),
+ mbExportFormFields( true ),
+ mbAllowDuplicateFieldNames( false ),
+ mbExportBookmarks( true ),
+ mbExportHiddenSlides ( false ),
+ mbSinglePageSheets ( false ),
+ mnOpenBookmarkLevels( -1 ),
+
+ mbHideViewerToolbar( false ),
+ mbHideViewerMenubar( false ),
+ mbHideViewerWindowControls( false ),
+ mbResizeWinToInit( false ),
+ mbCenterWindow( false ),
+ mbOpenInFullScreenMode( false ),
+ mbDisplayPDFDocumentTitle( false ),
+ mnMagnification( 0 ),
+ mnInitialView( 0 ),
+ mnZoom( 0 ),
+ mnInitialPage( 1 ),
+ mnPageLayout( 0 ),
+ mbFirstPageLeft( false ),
+
+ mbEncrypt( false ),
+ mbRestrictPermissions( false ),
+ mnPrint( 0 ),
+ mnChangesAllowed( 0 ),
+ mbCanCopyOrExtract( false ),
+ mbCanExtractForAccessibility( true ),
+
+ mbIsRangeChecked( false ),
+ msPageRange( ' ' ),
+
+ mbSelectionIsChecked( false ),
+ mbExportRelativeFsysLinks( false ),
+ mnViewPDFMode( 0 ),
+ mbConvertOOoTargets( false ),
+ mbExportBmkToPDFDestination( false ),
+
+ mbSignPDF( false )
+{
+ // check for selection
+ try
+ {
+ Reference< frame::XController > xController( Reference< frame::XModel >( rxDoc, UNO_QUERY_THROW )->getCurrentController() );
+ if( xController.is() )
+ {
+ Reference< view::XSelectionSupplier > xView( xController, UNO_QUERY );
+ if( xView.is() )
+ maSelection = xView->getSelection();
+ }
+ }
+ catch(const RuntimeException &)
+ {
+ }
+ mbSelectionPresent = maSelection.hasValue();
+ if ( mbSelectionPresent )
+ {
+ Reference< drawing::XShapes > xShapes;
+ if ( !( maSelection >>= xShapes ) ) // XShapes is always a selection
+ {
+ // even if nothing is selected in writer the selection is not empty
+ Reference< container::XIndexAccess > xIndexAccess;
+ if ( maSelection >>= xIndexAccess )
+ {
+ sal_Int32 nLen = xIndexAccess->getCount();
+ if ( !nLen )
+ mbSelectionPresent = false;
+ else if ( nLen == 1 )
+ {
+ Reference< text::XTextRange > xTextRange( xIndexAccess->getByIndex( 0 ), UNO_QUERY );
+ if ( xTextRange.is() && ( xTextRange->getString().isEmpty() ) )
+ mbSelectionPresent = false;
+ }
+ }
+ }
+ }
+
+ // check if source document is a presentation or a spreadsheet or a textdocument
+ try
+ {
+ Reference< XServiceInfo > xInfo( rxDoc, UNO_QUERY );
+ if ( xInfo.is() )
+ {
+ if ( xInfo->supportsService( "com.sun.star.presentation.PresentationDocument" ) )
+ mbIsPresentation = true;
+ if ( xInfo->supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) )
+ mbIsSpreadsheet = true;
+ if ( xInfo->supportsService( "com.sun.star.text.GenericTextDocument" ) )
+ mbIsWriter = true;
+ }
+ }
+ catch(const RuntimeException &)
+ {
+ }
+
+ // get the CTL (Complex Text Layout) from general options, returns sal_True if we have a CTL font on our hands.
+ mbUseCTLFont = maConfigI18N.ReadBool( "CTLFont", false );
+
+ mbUseLosslessCompression = maConfigItem.ReadBool( "UseLosslessCompression", false );
+ mnQuality = maConfigItem.ReadInt32( "Quality", 90 );
+ mbReduceImageResolution = maConfigItem.ReadBool( "ReduceImageResolution", false );
+ mnMaxImageResolution = maConfigItem.ReadInt32( "MaxImageResolution", 300 );
+
+ // this is always the user selection, independent from the PDF/A forced selection
+ mbUseTaggedPDF = maConfigItem.ReadBool( "UseTaggedPDF", false );
+ mbUseTaggedPDFUserSelection = mbUseTaggedPDF;
+
+ mnPDFTypeSelection = maConfigItem.ReadInt32( "SelectPdfVersion", 0 );
+ mbPDFUACompliance = maConfigItem.ReadBool("PDFUACompliance", false);
+
+ if ( mbIsPresentation )
+ {
+ mbExportNotesPages = maConfigItem.ReadBool( "ExportNotesPages", false );
+ mbExportOnlyNotesPages = maConfigItem.ReadBool( "ExportOnlyNotesPages", false );
+ }
+ mbExportNotes = maConfigItem.ReadBool( "ExportNotes", false );
+ mbViewPDF = maConfigItem.ReadBool( "ViewPDFAfterExport", false );
+
+ mbExportBookmarks = maConfigItem.ReadBool( "ExportBookmarks", true );
+ if ( mbIsPresentation )
+ mbExportHiddenSlides = maConfigItem.ReadBool( "ExportHiddenSlides", false );
+ if ( mbIsSpreadsheet )
+ mbSinglePageSheets = maConfigItem.ReadBool( "SinglePageSheets", false );
+ mnOpenBookmarkLevels = maConfigItem.ReadInt32( "OpenBookmarkLevels", -1 );
+ mbUseTransitionEffects = maConfigItem.ReadBool( "UseTransitionEffects", true );
+ mbIsSkipEmptyPages = maConfigItem.ReadBool( "IsSkipEmptyPages", false );
+ mbIsExportPlaceholders = maConfigItem.ReadBool( "ExportPlaceholders", false );
+ mbAddStream = maConfigItem.ReadBool( "IsAddStream", false );
+
+ mbExportFormFields = maConfigItem.ReadBool( "ExportFormFields", true );
+ mnFormsType = maConfigItem.ReadInt32( "FormsType", 0 );
+ if ( ( mnFormsType < 0 ) || ( mnFormsType > 3 ) )
+ mnFormsType = 0;
+ mbAllowDuplicateFieldNames = maConfigItem.ReadBool( "AllowDuplicateFieldNames", false );
+
+ // prepare values for the Viewer tab page
+ mbHideViewerToolbar = maConfigItem.ReadBool( "HideViewerToolbar", false );
+ mbHideViewerMenubar = maConfigItem.ReadBool( "HideViewerMenubar", false );
+ mbHideViewerWindowControls = maConfigItem.ReadBool( "HideViewerWindowControls", false );
+ mbResizeWinToInit = maConfigItem.ReadBool( "ResizeWindowToInitialPage", false );
+ mbCenterWindow = maConfigItem.ReadBool( "CenterWindow", false );
+ mbOpenInFullScreenMode = maConfigItem.ReadBool( "OpenInFullScreenMode", false );
+ mbDisplayPDFDocumentTitle = maConfigItem.ReadBool( "DisplayPDFDocumentTitle", true );
+
+ mnInitialView = maConfigItem.ReadInt32( "InitialView", 0 );
+ mnMagnification = maConfigItem.ReadInt32( "Magnification", 0 );
+ mnZoom = maConfigItem.ReadInt32( "Zoom", 100 );
+ mnPageLayout = maConfigItem.ReadInt32( "PageLayout", 0 );
+ mbFirstPageLeft = maConfigItem.ReadBool( "FirstPageOnLeft", false );
+ mnInitialPage = maConfigItem.ReadInt32( "InitialPage", 1 );
+ if( mnInitialPage < 1 )
+ mnInitialPage = 1;
+
+ // prepare values for the security tab page
+ mnPrint = maConfigItem.ReadInt32( "Printing", 2 );
+ mnChangesAllowed = maConfigItem.ReadInt32( "Changes", 4 );
+ mbCanCopyOrExtract = maConfigItem.ReadBool( "EnableCopyingOfContent", true );
+ mbCanExtractForAccessibility = maConfigItem.ReadBool( "EnableTextAccessForAccessibilityTools", true );
+
+ // prepare values for relative links
+ mbExportRelativeFsysLinks = maConfigItem.ReadBool( "ExportLinksRelativeFsys", false );
+
+ mnViewPDFMode = maConfigItem.ReadInt32( "PDFViewSelection", 0 );
+
+ mbConvertOOoTargets = maConfigItem.ReadBool( "ConvertOOoTargetToPDFTarget", false );
+ mbExportBmkToPDFDestination = maConfigItem.ReadBool( "ExportBookmarksToPDFDestination", false );
+
+ // prepare values for digital signatures
+ mbSignPDF = maConfigItem.ReadBool( "SignPDF", false );
+
+ // queue the tab pages for later creation (created when first shown)
+ AddTabPage("general", ImpPDFTabGeneralPage::Create, nullptr );
+ AddTabPage("digitalsignatures", ImpPDFTabSigningPage::Create, nullptr);
+ AddTabPage("security", ImpPDFTabSecurityPage::Create, nullptr);
+ AddTabPage("links", ImpPDFTabLinksPage::Create, nullptr);
+ AddTabPage("userinterface", ImpPDFTabViewerPage::Create, nullptr);
+ AddTabPage("initialview", ImpPDFTabOpnFtrPage::Create, nullptr);
+
+ SetCurPageId("general");
+
+ // get the string property value (from sfx2/source/dialog/mailmodel.cxx) to overwrite the text for the Ok button
+ OUString sOkButtonText = maConfigItem.ReadString( "_OkButtonString", OUString() );
+
+ // change text on the Ok button: get the relevant string from resources, update it on the button
+ // according to the exported pdf file destination: send as e-mail or write to file?
+ if (!sOkButtonText.isEmpty())
+ GetOKButton().set_label(sOkButtonText);
+
+ GetCancelButton().connect_clicked(LINK(this, ImpPDFTabDialog, CancelHdl));
+ GetOKButton().connect_clicked(LINK(this, ImpPDFTabDialog, OkHdl));
+
+ // remove the reset button, not needed in this tabbed dialog
+ RemoveResetButton();
+}
+
+ImpPDFTabSecurityPage* ImpPDFTabDialog::getSecurityPage() const
+{
+ SfxTabPage* pSecurityPage = GetTabPage("security");
+ if (pSecurityPage)
+ {
+ return static_cast<ImpPDFTabSecurityPage*>(pSecurityPage);
+ }
+ return nullptr;
+}
+
+
+ImpPDFTabLinksPage* ImpPDFTabDialog::getLinksPage() const
+{
+ SfxTabPage* pLinksPage = GetTabPage("links");
+ if (pLinksPage)
+ {
+ return static_cast<ImpPDFTabLinksPage*>(pLinksPage);
+ }
+ return nullptr;
+}
+
+
+ImpPDFTabGeneralPage* ImpPDFTabDialog::getGeneralPage() const
+{
+ SfxTabPage* pGeneralPage = GetTabPage("general");
+ if (pGeneralPage)
+ {
+ return static_cast<ImpPDFTabGeneralPage*>(pGeneralPage);
+ }
+ return nullptr;
+}
+
+IMPL_LINK_NOARG(ImpPDFTabDialog, CancelHdl, weld::Button&, void)
+{
+ m_xDialog->response(RET_CANCEL);
+}
+
+IMPL_LINK_NOARG(ImpPDFTabDialog, OkHdl, weld::Button&, void)
+{
+ if (getGeneralPage()->IsPdfUaSelected())
+ {
+ SfxObjectShell* pShell = SfxObjectShell::GetShellFromComponent(mrDoc);
+ if (pShell)
+ {
+ sfx::AccessibilityIssueCollection aCollection = pShell->runAccessibilityCheck();
+ if (!aCollection.getIssues().empty())
+ {
+ mpAccessibilityCheckDialog = std::make_shared<svx::AccessibilityCheckDialog>(mpParent, aCollection);
+ weld::DialogController::runAsync(mpAccessibilityCheckDialog, [this](sal_Int32 retValue){
+ m_xDialog->response(retValue);
+ });
+ }
+ else
+ {
+ m_xDialog->response(RET_OK);
+ }
+ }
+ else
+ {
+ m_xDialog->response(RET_OK);
+ }
+ }
+ else
+ {
+ m_xDialog->response(RET_OK);
+ }
+}
+
+ImpPDFTabDialog::~ImpPDFTabDialog()
+{
+ maConfigItem.WriteModifiedConfig();
+ maConfigI18N.WriteModifiedConfig();
+ if (mpAccessibilityCheckDialog)
+ {
+ mpAccessibilityCheckDialog->response(RET_CANCEL);
+ }
+}
+
+void ImpPDFTabDialog::PageCreated(const OString& rId, SfxTabPage& rPage)
+{
+ if (rId == "general")
+ static_cast<ImpPDFTabGeneralPage&>(rPage).SetFilterConfigItem(this);
+ else if (rId == "userinterface")
+ {
+ static_cast<ImpPDFTabViewerPage&>(rPage).SetFilterConfigItem(this);
+ }
+ else if (rId == "initialview")
+ {
+ static_cast<ImpPDFTabOpnFtrPage&>(rPage).SetFilterConfigItem(this);
+ }
+ else if (rId == "links")
+ {
+ static_cast<ImpPDFTabLinksPage&>(rPage).SetFilterConfigItem(this);
+ }
+ else if (rId == "security")
+ {
+ static_cast<ImpPDFTabSecurityPage&>(rPage).SetFilterConfigItem(this);
+ }
+ else if (rId == "digitalsignatures")
+ {
+ static_cast<ImpPDFTabSigningPage&>(rPage).SetFilterConfigItem(this);
+ }
+}
+
+
+Sequence< PropertyValue > ImpPDFTabDialog::GetFilterData()
+{
+ // updating the FilterData sequence and storing FilterData to configuration
+ if (ImpPDFTabGeneralPage* pPage = static_cast<ImpPDFTabGeneralPage*>(GetTabPage("general")))
+ pPage->GetFilterConfigItem(this);
+ if (ImpPDFTabViewerPage* pPage = static_cast<ImpPDFTabViewerPage*>(GetTabPage("userinterface")))
+ pPage->GetFilterConfigItem(this);
+ if (ImpPDFTabOpnFtrPage* pPage = static_cast<ImpPDFTabOpnFtrPage*>(GetTabPage("initialview")))
+ pPage->GetFilterConfigItem(this);
+ if (ImpPDFTabLinksPage* pPage = static_cast<ImpPDFTabLinksPage*>(GetTabPage("links")))
+ pPage->GetFilterConfigItem(this);
+ if (ImpPDFTabSecurityPage* pPage = static_cast<ImpPDFTabSecurityPage*>( GetTabPage("security")))
+ pPage->GetFilterConfigItem(this);
+ if (ImpPDFTabSigningPage* pPage = static_cast<ImpPDFTabSigningPage*>(GetTabPage("digitalsignatures")))
+ pPage->GetFilterConfigItem(this);
+
+ // prepare the items to be returned
+ maConfigItem.WriteBool( "UseLosslessCompression", mbUseLosslessCompression );
+ maConfigItem.WriteInt32("Quality", mnQuality );
+ maConfigItem.WriteBool( "ReduceImageResolution", mbReduceImageResolution );
+ maConfigItem.WriteInt32("MaxImageResolution", mnMaxImageResolution );
+
+ // always write the user selection, never the overridden value
+ const bool bIsPDFUA = mbPDFUACompliance;
+ const bool bIsPDFA = (1 == mnPDFTypeSelection) || (2 == mnPDFTypeSelection) || (3 == mnPDFTypeSelection);
+ const bool bUserSelectionTags = bIsPDFA || bIsPDFUA;
+ maConfigItem.WriteBool("UseTaggedPDF", bUserSelectionTags ? mbUseTaggedPDFUserSelection : mbUseTaggedPDF);
+ maConfigItem.WriteInt32("SelectPdfVersion", mnPDFTypeSelection );
+ maConfigItem.WriteBool("PDFUACompliance", mbPDFUACompliance);
+
+ if ( mbIsPresentation )
+ {
+ maConfigItem.WriteBool( "ExportNotesPages", mbExportNotesPages );
+ maConfigItem.WriteBool( "ExportOnlyNotesPages", mbExportOnlyNotesPages );
+ }
+ maConfigItem.WriteBool( "ExportNotes", mbExportNotes );
+ maConfigItem.WriteBool( "ViewPDFAfterExport", mbViewPDF );
+
+ maConfigItem.WriteBool( "ExportBookmarks", mbExportBookmarks );
+ if ( mbIsPresentation )
+ maConfigItem.WriteBool( "ExportHiddenSlides", mbExportHiddenSlides );
+ if ( mbIsSpreadsheet )
+ maConfigItem.WriteBool( "SinglePageSheets", mbSinglePageSheets );
+ maConfigItem.WriteBool( "UseTransitionEffects", mbUseTransitionEffects );
+ maConfigItem.WriteBool( "IsSkipEmptyPages", mbIsSkipEmptyPages );
+ maConfigItem.WriteBool( "ExportPlaceholders", mbIsExportPlaceholders );
+ maConfigItem.WriteBool( "IsAddStream", mbAddStream );
+
+ /*
+ * FIXME: the entries are only implicitly defined by the resource file. Should there
+ * ever be an additional form submit format this could get invalid.
+ */
+ maConfigItem.WriteInt32( "FormsType", mnFormsType );
+ maConfigItem.WriteBool( "ExportFormFields", mbExportFormFields );
+ maConfigItem.WriteBool( "AllowDuplicateFieldNames", mbAllowDuplicateFieldNames );
+
+ maConfigItem.WriteBool( "HideViewerToolbar", mbHideViewerToolbar );
+ maConfigItem.WriteBool( "HideViewerMenubar", mbHideViewerMenubar );
+ maConfigItem.WriteBool( "HideViewerWindowControls", mbHideViewerWindowControls );
+ maConfigItem.WriteBool( "ResizeWindowToInitialPage", mbResizeWinToInit );
+ maConfigItem.WriteBool( "CenterWindow", mbCenterWindow );
+ maConfigItem.WriteBool( "OpenInFullScreenMode", mbOpenInFullScreenMode );
+ maConfigItem.WriteBool( "DisplayPDFDocumentTitle", mbDisplayPDFDocumentTitle );
+ maConfigItem.WriteInt32( "InitialView", mnInitialView );
+ maConfigItem.WriteInt32( "Magnification", mnMagnification);
+ maConfigItem.WriteInt32( "Zoom", mnZoom );
+ maConfigItem.WriteInt32( "InitialPage", mnInitialPage );
+ maConfigItem.WriteInt32( "PageLayout", mnPageLayout );
+ maConfigItem.WriteBool( "FirstPageOnLeft", mbFirstPageLeft );
+ maConfigItem.WriteInt32( "OpenBookmarkLevels", mnOpenBookmarkLevels );
+
+ maConfigItem.WriteBool( "ExportLinksRelativeFsys", mbExportRelativeFsysLinks );
+ maConfigItem.WriteInt32("PDFViewSelection", mnViewPDFMode );
+ maConfigItem.WriteBool( "ConvertOOoTargetToPDFTarget", mbConvertOOoTargets );
+ maConfigItem.WriteBool( "ExportBookmarksToPDFDestination", mbExportBmkToPDFDestination );
+
+ maConfigItem.WriteBool( "SignPDF", mbSignPDF );
+
+ maConfigItem.WriteInt32( "Printing", mnPrint );
+ maConfigItem.WriteInt32( "Changes", mnChangesAllowed );
+ maConfigItem.WriteBool( "EnableCopyingOfContent", mbCanCopyOrExtract );
+ maConfigItem.WriteBool( "EnableTextAccessForAccessibilityTools", mbCanExtractForAccessibility );
+
+ std::vector<beans::PropertyValue> aRet
+ {
+ comphelper::makePropertyValue("Watermark", maWatermarkText),
+ comphelper::makePropertyValue("EncryptFile", mbEncrypt),
+ comphelper::makePropertyValue("PreparedPasswords", mxPreparedPasswords),
+ comphelper::makePropertyValue("RestrictPermissions", mbRestrictPermissions),
+ comphelper::makePropertyValue("PreparedPermissionPassword", maPreparedOwnerPassword)
+ };
+ if( mbIsRangeChecked )
+ aRet.push_back(comphelper::makePropertyValue("PageRange", msPageRange));
+ else if( mbSelectionIsChecked )
+ aRet.push_back(comphelper::makePropertyValue("Selection", maSelection));
+
+ aRet.push_back(comphelper::makePropertyValue("SignatureLocation", msSignLocation));
+ aRet.push_back(comphelper::makePropertyValue("SignatureReason", msSignReason));
+ aRet.push_back(comphelper::makePropertyValue("SignatureContactInfo", msSignContact));
+ aRet.push_back(comphelper::makePropertyValue("SignaturePassword", msSignPassword));
+ aRet.push_back(comphelper::makePropertyValue("SignatureCertificate", maSignCertificate));
+ aRet.push_back(comphelper::makePropertyValue("SignatureTSA", msSignTSA));
+ aRet.push_back(comphelper::makePropertyValue("UseReferenceXObject", mbUseReferenceXObject));
+
+ return comphelper::concatSequences(maConfigItem.GetFilterData(), comphelper::containerToSequence(aRet));
+}
+
+
+ImpPDFTabGeneralPage::ImpPDFTabGeneralPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreSet)
+ : SfxTabPage(pPage, pController, "filter/ui/pdfgeneralpage.ui", "PdfGeneralPage", &rCoreSet)
+ , mbUseTaggedPDFUserSelection(false)
+ , mbIsPresentation(false)
+ , mbIsSpreadsheet(false)
+ , mbIsWriter(false)
+ , mpParent(nullptr)
+ , mxRbAll(m_xBuilder->weld_radio_button("all"))
+ , mxRbRange(m_xBuilder->weld_radio_button("range"))
+ , mxRbSelection(m_xBuilder->weld_radio_button("selection"))
+ , mxEdPages(m_xBuilder->weld_entry("pages"))
+ , mxSelectedSheets(m_xBuilder->weld_label("selectedsheets"))
+ , mxRbLosslessCompression(m_xBuilder->weld_radio_button("losslesscompress"))
+ , mxRbJPEGCompression(m_xBuilder->weld_radio_button("jpegcompress"))
+ , mxQualityFrame(m_xBuilder->weld_widget("qualityframe"))
+ , mxNfQuality(m_xBuilder->weld_metric_spin_button("quality", FieldUnit::PERCENT))
+ , mxCbReduceImageResolution(m_xBuilder->weld_check_button("reduceresolution"))
+ , mxCoReduceImageResolution(m_xBuilder->weld_combo_box("resolution"))
+ , mxCbPDFA(m_xBuilder->weld_check_button("pdfa"))
+ , mxCbPDFUA(m_xBuilder->weld_check_button("pdfua"))
+ , mxRbPDFAVersion(m_xBuilder->weld_combo_box("pdfaversion"))
+ , mxCbTaggedPDF(m_xBuilder->weld_check_button("tagged"))
+ , mxCbExportFormFields(m_xBuilder->weld_check_button("forms"))
+ , mxFormsFrame(m_xBuilder->weld_widget("formsframe"))
+ , mxLbFormsFormat(m_xBuilder->weld_combo_box("format"))
+ , mxCbAllowDuplicateFieldNames(m_xBuilder->weld_check_button("allowdups"))
+ , mxCbExportBookmarks(m_xBuilder->weld_check_button("bookmarks"))
+ , mxCbExportHiddenSlides(m_xBuilder->weld_check_button("hiddenpages"))
+ , mxCbSinglePageSheets(m_xBuilder->weld_check_button("singlepagesheets"))
+ , mxCbExportNotes(m_xBuilder->weld_check_button("comments"))
+ , mxCbViewPDF(m_xBuilder->weld_check_button("viewpdf"))
+ , mxCbUseReferenceXObject(m_xBuilder->weld_check_button("usereferencexobject"))
+ , mxCbExportNotesPages(m_xBuilder->weld_check_button("notes"))
+ , mxCbExportOnlyNotesPages(m_xBuilder->weld_check_button("onlynotes"))
+ , mxCbExportEmptyPages(m_xBuilder->weld_check_button("emptypages"))
+ , mxCbExportPlaceholders(m_xBuilder->weld_check_button("exportplaceholders"))
+ , mxCbAddStream(m_xBuilder->weld_check_button("embed"))
+ , mxCbWatermark(m_xBuilder->weld_check_button("watermark"))
+ , mxFtWatermark(m_xBuilder->weld_label("watermarklabel"))
+ , mxEdWatermark(m_xBuilder->weld_entry("watermarkentry"))
+ , mxSlidesFt(m_xBuilder->weld_label("slides"))
+ , mxSheetsFt(m_xBuilder->weld_label("selectedsheets"))
+{
+}
+
+ImpPDFTabGeneralPage::~ImpPDFTabGeneralPage()
+{
+}
+
+void ImpPDFTabGeneralPage::SetFilterConfigItem(ImpPDFTabDialog* pParent)
+{
+ mpParent = pParent;
+
+ // init this class data
+ mxRbRange->connect_toggled( LINK( this, ImpPDFTabGeneralPage, TogglePagesHdl ) );
+
+ mxRbAll->set_active(true);
+ mxRbAll->connect_toggled( LINK( this, ImpPDFTabGeneralPage, ToggleAllHdl ) );
+ TogglePagesHdl();
+
+ const bool bSelectionPresent = pParent->mbSelectionPresent;
+ mxRbSelection->set_sensitive( bSelectionPresent );
+ if ( bSelectionPresent )
+ mxRbSelection->connect_toggled( LINK( this, ImpPDFTabGeneralPage, ToggleSelectionHdl ) );
+ mbIsPresentation = pParent->mbIsPresentation;
+ mbIsWriter = pParent->mbIsWriter;
+ mbIsSpreadsheet = pParent->mbIsSpreadsheet;
+
+ mxCbExportEmptyPages->set_sensitive( mbIsWriter );
+ mxCbExportPlaceholders->set_sensitive( mbIsWriter );
+
+ mxRbLosslessCompression->connect_toggled( LINK( this, ImpPDFTabGeneralPage, ToggleCompressionHdl ) );
+ const bool bUseLosslessCompression = pParent->mbUseLosslessCompression;
+ if ( bUseLosslessCompression )
+ mxRbLosslessCompression->set_active(true);
+ else
+ mxRbJPEGCompression->set_active(true);
+
+ mxNfQuality->set_value( pParent->mnQuality, FieldUnit::PERCENT );
+ mxQualityFrame->set_sensitive(!bUseLosslessCompression);
+
+ mxCbReduceImageResolution->connect_toggled(LINK(this, ImpPDFTabGeneralPage, ToggleReduceImageResolutionHdl));
+ const bool bReduceImageResolution = pParent->mbReduceImageResolution;
+ mxCbReduceImageResolution->set_active( bReduceImageResolution );
+ OUString aStrRes = OUString::number( pParent->mnMaxImageResolution ) + " DPI";
+ mxCoReduceImageResolution->set_entry_text(aStrRes);
+ mxCoReduceImageResolution->set_sensitive( bReduceImageResolution );
+ mxCbWatermark->connect_toggled( LINK( this, ImpPDFTabGeneralPage, ToggleWatermarkHdl ) );
+ mxFtWatermark->set_sensitive(false );
+ mxEdWatermark->set_sensitive( false );
+ mxCbPDFA->connect_toggled(LINK(this, ImpPDFTabGeneralPage, TogglePDFVersionOrUniversalAccessibilityHandle));
+
+ const bool bIsPDFA = (pParent->mnPDFTypeSelection>=1) && (pParent->mnPDFTypeSelection <= 3);
+ mxCbPDFA->set_active(bIsPDFA);
+ switch( pParent->mnPDFTypeSelection )
+ {
+ case 1: // PDF/A-1
+ mxRbPDFAVersion->set_active_id("1");
+ break;
+ case 2: // PDF/A-2
+ mxRbPDFAVersion->set_active_id("2");
+ break;
+ case 3: // PDF/A-3
+ default: // PDF 1.x
+ mxRbPDFAVersion->set_active_id("3");
+ break;
+ }
+
+ const bool bIsPDFUA = pParent->mbPDFUACompliance;
+ mxCbPDFUA->set_active(bIsPDFUA);
+ mxCbPDFUA->connect_toggled(LINK(this, ImpPDFTabGeneralPage, TogglePDFVersionOrUniversalAccessibilityHandle));
+
+ // the TogglePDFVersionOrUniversalAccessibilityHandle handler will read or write the *UserSelection based
+ // on the mxCbPDFA (= bIsPDFA) state, so we have to prepare the correct input state.
+ if (bIsPDFA || bIsPDFUA)
+ mxCbTaggedPDF->set_active(pParent->mbUseTaggedPDFUserSelection);
+ else
+ mbUseTaggedPDFUserSelection = pParent->mbUseTaggedPDFUserSelection;
+ TogglePDFVersionOrUniversalAccessibilityHandle(*mxCbPDFA);
+
+ mxCbExportFormFields->set_active(pParent->mbExportFormFields);
+ mxCbExportFormFields->connect_toggled( LINK( this, ImpPDFTabGeneralPage, ToggleExportFormFieldsHdl ) );
+
+ mxLbFormsFormat->set_active(static_cast<sal_uInt16>(pParent->mnFormsType));
+ mxCbAllowDuplicateFieldNames->set_active( pParent->mbAllowDuplicateFieldNames );
+ mxFormsFrame->set_sensitive(pParent->mbExportFormFields);
+
+ mxCbExportBookmarks->set_active( pParent->mbExportBookmarks );
+
+ mxCbExportNotes->set_active( pParent->mbExportNotes );
+ mxCbViewPDF->set_active( pParent->mbViewPDF);
+
+ if ( mbIsPresentation )
+ {
+ mxRbRange->set_label(mxSlidesFt->get_label());
+ mxCbExportNotesPages->show();
+ mxCbExportNotesPages->set_active(pParent->mbExportNotesPages);
+ mxCbExportNotesPages->connect_toggled( LINK(this, ImpPDFTabGeneralPage, ToggleExportNotesPagesHdl ) );
+ mxCbExportOnlyNotesPages->show();
+ mxCbExportOnlyNotesPages->set_active(pParent->mbExportOnlyNotesPages);
+ // tdf#116473 Initially enable Export only note pages option depending on the checked state of Export notes pages option
+ mxCbExportOnlyNotesPages->set_sensitive(mxCbExportNotesPages->get_active());
+ mxCbExportHiddenSlides->show();
+ mxCbExportHiddenSlides->set_active(pParent->mbExportHiddenSlides);
+ }
+ else
+ {
+ mxCbExportNotesPages->hide();
+ mxCbExportNotesPages->set_active(false);
+ mxCbExportOnlyNotesPages->hide();
+ mxCbExportOnlyNotesPages->set_active(false);
+ mxCbExportHiddenSlides->hide();
+ mxCbExportHiddenSlides->set_active(false);
+ }
+
+ if( mbIsSpreadsheet )
+ {
+ mxRbSelection->set_label(mxSheetsFt->get_label());
+ // tdf#105965 Make Selection/Selected sheets the default PDF export range setting for spreadsheets
+ mxRbSelection->set_active(true);
+
+ mxCbSinglePageSheets->show();
+ mxCbSinglePageSheets->set_active(pParent->mbSinglePageSheets);
+ }
+ else
+ {
+ mxCbSinglePageSheets->hide();
+ mxCbSinglePageSheets->set_active(false);
+ }
+
+ mxCbExportPlaceholders->set_visible(mbIsWriter);
+ if( mbIsWriter )
+ {
+ // tdf#54908 Make selection active if there is a selection in Writer's version
+ mxRbSelection->set_active( bSelectionPresent );
+ }
+ else
+ {
+ mxCbExportPlaceholders->set_active(false);
+ }
+ mxCbExportEmptyPages->set_active(!pParent->mbIsSkipEmptyPages);
+ mxCbExportPlaceholders->set_active(pParent->mbIsExportPlaceholders);
+
+ mxCbAddStream->show();
+ mxCbAddStream->set_active(pParent->mbAddStream);
+
+ mxCbAddStream->connect_toggled(LINK(this, ImpPDFTabGeneralPage, ToggleAddStreamHdl));
+ ToggleAddStreamHdl(*mxCbAddStream); // init addstream dependencies
+}
+
+void ImpPDFTabGeneralPage::GetFilterConfigItem( ImpPDFTabDialog* pParent )
+{
+ // updating the FilterData sequence and storing FilterData to configuration
+ pParent->mbUseLosslessCompression = mxRbLosslessCompression->get_active();
+ pParent->mnQuality = static_cast<sal_Int32>(mxNfQuality->get_value(FieldUnit::PERCENT));
+ pParent->mbReduceImageResolution = mxCbReduceImageResolution->get_active();
+ pParent->mnMaxImageResolution = mxCoReduceImageResolution->get_active_text().toInt32();
+ pParent->mbExportNotes = mxCbExportNotes->get_active();
+ pParent->mbViewPDF = mxCbViewPDF->get_active();
+ pParent->mbUseReferenceXObject = mxCbUseReferenceXObject->get_active();
+ if ( mbIsPresentation )
+ {
+ pParent->mbExportNotesPages = mxCbExportNotesPages->get_active();
+ pParent->mbExportOnlyNotesPages = mxCbExportOnlyNotesPages->get_active();
+ }
+ pParent->mbExportBookmarks = mxCbExportBookmarks->get_active();
+ if ( mbIsPresentation )
+ pParent->mbExportHiddenSlides = mxCbExportHiddenSlides->get_active();
+
+ if (mbIsSpreadsheet)
+ pParent->mbSinglePageSheets = mxCbSinglePageSheets->get_active();
+
+ pParent->mbIsSkipEmptyPages = !mxCbExportEmptyPages->get_active();
+ pParent->mbIsExportPlaceholders = mxCbExportPlaceholders->get_active();
+ pParent->mbAddStream = mxCbAddStream->get_visible() && mxCbAddStream->get_active();
+
+ pParent->mbIsRangeChecked = false;
+ if( mxRbRange->get_active() )
+ {
+ pParent->mbIsRangeChecked = true;
+ pParent->msPageRange = mxEdPages->get_text(); //FIXME all right on other languages ?
+ }
+ else if( mxRbSelection->get_active() )
+ {
+ pParent->mbSelectionIsChecked = mxRbSelection->get_active();
+ }
+
+ pParent->mnPDFTypeSelection = 0;
+ pParent->mbUseTaggedPDF = mxCbTaggedPDF->get_active();
+
+ const bool bIsPDFA = mxCbPDFA->get_active();
+ const bool bIsPDFUA = mxCbPDFUA->get_active();
+
+ if (bIsPDFA)
+ {
+ pParent->mnPDFTypeSelection = 3;
+ OUString currentPDFAMode = mxRbPDFAVersion->get_active_id();
+ if( currentPDFAMode == "1" )
+ pParent->mnPDFTypeSelection = 1;
+ else if(currentPDFAMode == "2")
+ pParent->mnPDFTypeSelection = 2;
+ }
+
+ pParent->mbPDFUACompliance = bIsPDFUA;
+
+ if (!bIsPDFA && !bIsPDFUA)
+ mbUseTaggedPDFUserSelection = pParent->mbUseTaggedPDF;
+
+ pParent->mbUseTaggedPDFUserSelection = mbUseTaggedPDFUserSelection;
+ pParent->mbExportFormFields = mxCbExportFormFields->get_active();
+
+ if( mxCbWatermark->get_active() )
+ pParent->maWatermarkText = mxEdWatermark->get_text();
+
+ /*
+ * FIXME: the entries are only implicitly defined by the resource file. Should there
+ * ever be an additional form submit format this could get invalid.
+ */
+ pParent->mnFormsType = mxLbFormsFormat->get_active();
+ pParent->mbAllowDuplicateFieldNames = mxCbAllowDuplicateFieldNames->get_active();
+}
+
+std::unique_ptr<SfxTabPage> ImpPDFTabGeneralPage::Create( weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rAttrSet)
+{
+ return std::make_unique<ImpPDFTabGeneralPage>(pPage, pController, *rAttrSet);
+}
+
+IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleAllHdl, weld::Toggleable&, void)
+{
+ EnableExportNotesPages();
+}
+
+IMPL_LINK_NOARG(ImpPDFTabGeneralPage, TogglePagesHdl, weld::Toggleable&, void)
+{
+ TogglePagesHdl();
+ EnableExportNotesPages();
+}
+
+IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleSelectionHdl, weld::Toggleable&, void)
+{
+ EnableExportNotesPages();
+}
+
+void ImpPDFTabGeneralPage::TogglePagesHdl()
+{
+ mxEdPages->set_sensitive( mxRbRange->get_active() );
+ if (mxRbRange->get_active())
+ mxEdPages->grab_focus();
+}
+
+void ImpPDFTabGeneralPage::EnableExportNotesPages()
+{
+ if ( mbIsPresentation )
+ {
+ mxCbExportNotesPages->set_sensitive( !mxRbSelection->get_active() );
+ mxCbExportOnlyNotesPages->set_sensitive( !mxRbSelection->get_active() && mxCbExportNotesPages->get_active() );
+ }
+}
+
+IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleExportFormFieldsHdl, weld::Toggleable&, void)
+{
+ mxFormsFrame->set_sensitive(mxCbExportFormFields->get_active());
+}
+
+IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleExportNotesPagesHdl, weld::Toggleable&, void)
+{
+ mxCbExportOnlyNotesPages->set_sensitive(mxCbExportNotesPages->get_active());
+}
+
+IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleCompressionHdl, weld::Toggleable&, void)
+{
+ mxQualityFrame->set_sensitive(mxRbJPEGCompression->get_active());
+}
+
+IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleReduceImageResolutionHdl, weld::Toggleable&, void)
+{
+ mxCoReduceImageResolution->set_sensitive(mxCbReduceImageResolution->get_active());
+}
+
+IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleWatermarkHdl, weld::Toggleable&, void)
+{
+ mxEdWatermark->set_sensitive(mxCbWatermark->get_active());
+ mxFtWatermark->set_sensitive(mxCbWatermark->get_active());
+ if (mxCbWatermark->get_active())
+ mxEdWatermark->grab_focus();
+}
+
+IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleAddStreamHdl, weld::Toggleable&, void)
+{
+ if (!mxCbAddStream->get_visible())
+ return;
+
+ if( mxCbAddStream->get_active() )
+ {
+ mxRbAll->set_active(true);
+ mxRbRange->set_sensitive( false );
+ mxRbSelection->set_sensitive( false );
+ mxEdPages->set_sensitive( false );
+ mxRbAll->set_sensitive( false );
+ }
+ else
+ {
+ mxRbAll->set_sensitive(true);
+ mxRbRange->set_sensitive(true);
+ mxRbSelection->set_sensitive(true);
+ }
+}
+
+IMPL_LINK_NOARG(ImpPDFTabGeneralPage, TogglePDFVersionOrUniversalAccessibilityHandle, weld::Toggleable&, void)
+{
+ const bool bIsPDFA = mxCbPDFA->get_active();
+ const bool bIsPDFUA = mxCbPDFUA->get_active();
+
+ // set the security page status (and its controls as well)
+ ImpPDFTabSecurityPage* pSecPage = mpParent ? mpParent->getSecurityPage() : nullptr;
+ if (pSecPage)
+ pSecPage->ImplPDFASecurityControl(!bIsPDFA);
+
+ mxCbTaggedPDF->set_sensitive(!bIsPDFA && !bIsPDFUA);
+ mxRbPDFAVersion->set_sensitive(bIsPDFA);
+
+ if (bIsPDFA || bIsPDFUA)
+ {
+ // store the users selection of subordinate controls and set required PDF/A values
+ mbUseTaggedPDFUserSelection = mxCbTaggedPDF->get_active();
+ mxCbTaggedPDF->set_active(true);
+
+ // if a password was set, inform the user that this will not be used
+ if (pSecPage && pSecPage->hasPassword())
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xContainer.get(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ PDFFilterResId(STR_WARN_PASSWORD_PDFA)));
+ xBox->run();
+ }
+ }
+ else
+ {
+ // restore the users values of subordinate controls
+ mxCbTaggedPDF->set_active(mbUseTaggedPDFUserSelection);
+ }
+
+ // PDF/A doesn't allow launch action, so enable/disable the selection on the Link page
+ ImpPDFTabLinksPage* pLinksPage = mpParent ? mpParent->getLinksPage() : nullptr;
+ if (pLinksPage)
+ pLinksPage->ImplPDFALinkControl(!bIsPDFA);
+}
+
+/// The option features tab page
+ImpPDFTabOpnFtrPage::ImpPDFTabOpnFtrPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreSet)
+ : SfxTabPage(pPage, pController, "filter/ui/pdfviewpage.ui", "PdfViewPage", &rCoreSet)
+ , mbUseCTLFont(false)
+ , mxRbOpnPageOnly(m_xBuilder->weld_radio_button("pageonly"))
+ , mxRbOpnOutline(m_xBuilder->weld_radio_button("outline"))
+ , mxRbOpnThumbs(m_xBuilder->weld_radio_button("thumbs"))
+ , mxNumInitialPage(m_xBuilder->weld_spin_button("page"))
+ , mxRbMagnDefault(m_xBuilder->weld_radio_button("fitdefault"))
+ , mxRbMagnFitWin(m_xBuilder->weld_radio_button("fitwin"))
+ , mxRbMagnFitWidth(m_xBuilder->weld_radio_button("fitwidth"))
+ , mxRbMagnFitVisible(m_xBuilder->weld_radio_button("fitvis"))
+ , mxRbMagnZoom(m_xBuilder->weld_radio_button("fitzoom"))
+ , mxNumZoom(m_xBuilder->weld_spin_button("zoom"))
+ , mxRbPgLyDefault(m_xBuilder->weld_radio_button("defaultlayout"))
+ , mxRbPgLySinglePage(m_xBuilder->weld_radio_button("singlelayout"))
+ , mxRbPgLyContinue(m_xBuilder->weld_radio_button("contlayout"))
+ , mxRbPgLyContinueFacing(m_xBuilder->weld_radio_button("contfacinglayout"))
+ , mxCbPgLyFirstOnLeft(m_xBuilder->weld_check_button("firstonleft"))
+{
+ mxRbMagnDefault->connect_toggled( LINK( this, ImpPDFTabOpnFtrPage, ToggleRbMagnHdl ) );
+ mxRbMagnFitWin->connect_toggled( LINK( this, ImpPDFTabOpnFtrPage, ToggleRbMagnHdl ) );
+ mxRbMagnFitWidth->connect_toggled( LINK( this, ImpPDFTabOpnFtrPage, ToggleRbMagnHdl ) );
+ mxRbMagnFitVisible->connect_toggled( LINK( this, ImpPDFTabOpnFtrPage, ToggleRbMagnHdl ) );
+ mxRbMagnZoom->connect_toggled( LINK( this, ImpPDFTabOpnFtrPage, ToggleRbMagnHdl ) );
+}
+
+ImpPDFTabOpnFtrPage::~ImpPDFTabOpnFtrPage()
+{
+}
+
+std::unique_ptr<SfxTabPage> ImpPDFTabOpnFtrPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet)
+{
+ return std::make_unique<ImpPDFTabOpnFtrPage>(pPage, pController, *rAttrSet);
+}
+
+void ImpPDFTabOpnFtrPage::GetFilterConfigItem( ImpPDFTabDialog* pParent )
+{
+ pParent->mnInitialView = 0;
+ if( mxRbOpnOutline->get_active() )
+ pParent->mnInitialView = 1;
+ else if( mxRbOpnThumbs->get_active() )
+ pParent->mnInitialView = 2;
+
+ pParent->mnMagnification = 0;
+ if( mxRbMagnFitWin->get_active() )
+ pParent->mnMagnification = 1;
+ else if( mxRbMagnFitWidth->get_active() )
+ pParent->mnMagnification = 2;
+ else if( mxRbMagnFitVisible->get_active() )
+ pParent->mnMagnification = 3;
+ else if( mxRbMagnZoom->get_active() )
+ {
+ pParent->mnMagnification = 4;
+ pParent->mnZoom = mxNumZoom->get_value();
+ }
+
+ pParent->mnInitialPage = mxNumInitialPage->get_value();
+
+ pParent->mnPageLayout = 0;
+ if( mxRbPgLySinglePage->get_active() )
+ pParent->mnPageLayout = 1;
+ else if( mxRbPgLyContinue->get_active() )
+ pParent->mnPageLayout = 2;
+ else if( mxRbPgLyContinueFacing->get_active() )
+ pParent->mnPageLayout = 3;
+
+ pParent->mbFirstPageLeft = mbUseCTLFont && mxCbPgLyFirstOnLeft->get_active();
+}
+
+void ImpPDFTabOpnFtrPage::SetFilterConfigItem( const ImpPDFTabDialog* pParent )
+{
+ mbUseCTLFont = pParent->mbUseCTLFont;
+ switch( pParent->mnPageLayout )
+ {
+ default:
+ case 0:
+ mxRbPgLyDefault->set_active(true);
+ break;
+ case 1:
+ mxRbPgLySinglePage->set_active(true);
+ break;
+ case 2:
+ mxRbPgLyContinue->set_active(true);
+ break;
+ case 3:
+ mxRbPgLyContinueFacing->set_active(true);
+ break;
+ }
+
+ switch( pParent->mnInitialView )
+ {
+ default:
+ case 0:
+ mxRbOpnPageOnly->set_active(true);
+ break;
+ case 1:
+ mxRbOpnOutline->set_active(true);
+ break;
+ case 2:
+ mxRbOpnThumbs->set_active(true);
+ break;
+ }
+
+ switch( pParent->mnMagnification )
+ {
+ default:
+ case 0:
+ mxRbMagnDefault->set_active(true);
+ mxNumZoom->set_sensitive(false);
+ break;
+ case 1:
+ mxRbMagnFitWin->set_active(true);
+ mxNumZoom->set_sensitive(false);
+ break;
+ case 2:
+ mxRbMagnFitWidth->set_active(true);
+ mxNumZoom->set_sensitive(false);
+ break;
+ case 3:
+ mxRbMagnFitVisible->set_active(true);
+ mxNumZoom->set_sensitive(false);
+ break;
+ case 4:
+ mxRbMagnZoom->set_active(true);
+ mxNumZoom->set_sensitive(true);
+ break;
+ }
+
+ mxNumZoom->set_value(pParent->mnZoom);
+ mxNumInitialPage->set_value(pParent->mnInitialPage);
+
+ if (!mbUseCTLFont)
+ mxCbPgLyFirstOnLeft->hide();
+ else
+ {
+ mxRbPgLyContinueFacing->connect_toggled(LINK(this, ImpPDFTabOpnFtrPage, ToggleRbPgLyContinueFacingHdl));
+ mxCbPgLyFirstOnLeft->set_active(pParent->mbFirstPageLeft);
+ ToggleRbPgLyContinueFacingHdl();
+ }
+}
+
+IMPL_LINK_NOARG(ImpPDFTabOpnFtrPage, ToggleRbPgLyContinueFacingHdl, weld::Toggleable&, void)
+{
+ ToggleRbPgLyContinueFacingHdl();
+}
+
+void ImpPDFTabOpnFtrPage::ToggleRbPgLyContinueFacingHdl()
+{
+ mxCbPgLyFirstOnLeft->set_sensitive(mxRbPgLyContinueFacing->get_active());
+}
+
+IMPL_LINK_NOARG( ImpPDFTabOpnFtrPage, ToggleRbMagnHdl, weld::Toggleable&, void )
+{
+ mxNumZoom->set_sensitive(mxRbMagnZoom->get_active());
+}
+
+/// The Viewer preferences tab page
+ImpPDFTabViewerPage::ImpPDFTabViewerPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreSet )
+ : SfxTabPage(pPage, pController, "filter/ui/pdfuserinterfacepage.ui", "PdfUserInterfacePage", &rCoreSet)
+ , mbIsPresentation(false)
+ , m_xCbResWinInit(m_xBuilder->weld_check_button("resize"))
+ , m_xCbCenterWindow(m_xBuilder->weld_check_button("center"))
+ , m_xCbOpenFullScreen(m_xBuilder->weld_check_button("open"))
+ , m_xCbDispDocTitle(m_xBuilder->weld_check_button("display"))
+ , m_xCbHideViewerMenubar(m_xBuilder->weld_check_button("menubar"))
+ , m_xCbHideViewerToolbar(m_xBuilder->weld_check_button("toolbar"))
+ , m_xCbHideViewerWindowControls(m_xBuilder->weld_check_button("window"))
+ , m_xCbTransitionEffects(m_xBuilder->weld_check_button("effects"))
+ , m_xRbAllBookmarkLevels(m_xBuilder->weld_radio_button("allbookmarks"))
+ , m_xRbVisibleBookmarkLevels(m_xBuilder->weld_radio_button("visiblebookmark"))
+ , m_xNumBookmarkLevels(m_xBuilder->weld_spin_button("visiblelevel"))
+{
+ m_xRbAllBookmarkLevels->connect_toggled(LINK(this, ImpPDFTabViewerPage, ToggleRbBookmarksHdl));
+ m_xRbVisibleBookmarkLevels->connect_toggled(LINK(this, ImpPDFTabViewerPage, ToggleRbBookmarksHdl));
+}
+
+ImpPDFTabViewerPage::~ImpPDFTabViewerPage()
+{
+}
+
+IMPL_LINK_NOARG( ImpPDFTabViewerPage, ToggleRbBookmarksHdl, weld::Toggleable&, void )
+{
+ m_xNumBookmarkLevels->set_sensitive(m_xRbVisibleBookmarkLevels->get_active());
+}
+
+std::unique_ptr<SfxTabPage> ImpPDFTabViewerPage::Create( weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rAttrSet)
+{
+ return std::make_unique<ImpPDFTabViewerPage>(pPage, pController, *rAttrSet);
+}
+
+void ImpPDFTabViewerPage::GetFilterConfigItem( ImpPDFTabDialog* pParent )
+{
+ pParent->mbHideViewerMenubar = m_xCbHideViewerMenubar->get_active();
+ pParent->mbHideViewerToolbar = m_xCbHideViewerToolbar->get_active();
+ pParent->mbHideViewerWindowControls = m_xCbHideViewerWindowControls->get_active();
+ pParent->mbResizeWinToInit = m_xCbResWinInit->get_active();
+ pParent->mbOpenInFullScreenMode = m_xCbOpenFullScreen->get_active();
+ pParent->mbCenterWindow = m_xCbCenterWindow->get_active();
+ pParent->mbDisplayPDFDocumentTitle = m_xCbDispDocTitle->get_active();
+ pParent->mbUseTransitionEffects = m_xCbTransitionEffects->get_active();
+ pParent->mnOpenBookmarkLevels = m_xRbAllBookmarkLevels->get_active() ?
+ -1 : static_cast<sal_Int32>(m_xNumBookmarkLevels->get_value());
+}
+
+void ImpPDFTabViewerPage::SetFilterConfigItem( const ImpPDFTabDialog* pParent )
+{
+ m_xCbHideViewerMenubar->set_active( pParent->mbHideViewerMenubar );
+ m_xCbHideViewerToolbar->set_active( pParent->mbHideViewerToolbar );
+ m_xCbHideViewerWindowControls->set_active( pParent->mbHideViewerWindowControls );
+
+ m_xCbResWinInit->set_active( pParent->mbResizeWinToInit );
+ m_xCbOpenFullScreen->set_active( pParent->mbOpenInFullScreenMode );
+ m_xCbCenterWindow->set_active( pParent->mbCenterWindow );
+ m_xCbDispDocTitle->set_active( pParent->mbDisplayPDFDocumentTitle );
+ mbIsPresentation = pParent->mbIsPresentation;
+ m_xCbTransitionEffects->set_active( pParent->mbUseTransitionEffects );
+ m_xCbTransitionEffects->set_sensitive( mbIsPresentation );
+ if( pParent->mnOpenBookmarkLevels < 0 )
+ {
+ m_xRbAllBookmarkLevels->set_active(true);
+ m_xNumBookmarkLevels->set_sensitive( false );
+ }
+ else
+ {
+ m_xRbVisibleBookmarkLevels->set_active(true);
+ m_xNumBookmarkLevels->set_sensitive(true);
+ m_xNumBookmarkLevels->set_value(pParent->mnOpenBookmarkLevels);
+ }
+}
+
+/// The Security preferences tab page
+ImpPDFTabSecurityPage::ImpPDFTabSecurityPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& i_rCoreSet)
+ : SfxTabPage(pPage, pController, "filter/ui/pdfsecuritypage.ui", "PdfSecurityPage", &i_rCoreSet)
+ , msUserPwdTitle( PDFFilterResId( STR_PDF_EXPORT_UDPWD ) )
+ , mbHaveOwnerPassword( false )
+ , mbHaveUserPassword( false )
+ , msOwnerPwdTitle( PDFFilterResId( STR_PDF_EXPORT_ODPWD ) )
+ , mxPbSetPwd(m_xBuilder->weld_button("setpassword"))
+ , mxUserPwdSet(m_xBuilder->weld_widget("userpwdset"))
+ , mxUserPwdUnset(m_xBuilder->weld_widget("userpwdunset"))
+ , mxUserPwdPdfa(m_xBuilder->weld_widget("userpwdpdfa"))
+ , mxOwnerPwdSet(m_xBuilder->weld_widget("ownerpwdset"))
+ , mxOwnerPwdUnset(m_xBuilder->weld_widget("ownerpwdunset"))
+ , mxOwnerPwdPdfa(m_xBuilder->weld_widget("ownerpwdpdfa"))
+ , mxPrintPermissions(m_xBuilder->weld_widget("printing"))
+ , mxRbPrintNone(m_xBuilder->weld_radio_button("printnone"))
+ , mxRbPrintLowRes(m_xBuilder->weld_radio_button("printlow"))
+ , mxRbPrintHighRes(m_xBuilder->weld_radio_button("printhigh"))
+ , mxChangesAllowed(m_xBuilder->weld_widget("changes"))
+ , mxRbChangesNone(m_xBuilder->weld_radio_button("changenone"))
+ , mxRbChangesInsDel(m_xBuilder->weld_radio_button("changeinsdel"))
+ , mxRbChangesFillForm(m_xBuilder->weld_radio_button("changeform"))
+ , mxRbChangesComment(m_xBuilder->weld_radio_button("changecomment"))
+ , mxRbChangesAnyNoCopy(m_xBuilder->weld_radio_button("changeany"))
+ , mxContent(m_xBuilder->weld_widget("content"))
+ , mxCbEnableCopy(m_xBuilder->weld_check_button("enablecopy"))
+ , mxCbEnableAccessibility(m_xBuilder->weld_check_button("enablea11y"))
+ , mxPasswordTitle(m_xBuilder->weld_label("setpasswordstitle"))
+{
+ msStrSetPwd = mxPasswordTitle->get_label();
+ mxPbSetPwd->connect_clicked(LINK(this, ImpPDFTabSecurityPage, ClickmaPbSetPwdHdl));
+}
+
+ImpPDFTabSecurityPage::~ImpPDFTabSecurityPage()
+{
+}
+
+std::unique_ptr<SfxTabPage> ImpPDFTabSecurityPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet)
+{
+ return std::make_unique<ImpPDFTabSecurityPage>(pPage, pController, *rAttrSet);
+}
+
+void ImpPDFTabSecurityPage::GetFilterConfigItem( ImpPDFTabDialog* pParent )
+{
+ // please note that in PDF/A-1a mode even if this are copied back,
+ // the security settings are forced disabled in PDFExport::Export
+ pParent->mbEncrypt = mbHaveUserPassword;
+ pParent->mxPreparedPasswords = mxPreparedPasswords;
+
+ pParent->mbRestrictPermissions = mbHaveOwnerPassword;
+ pParent->maPreparedOwnerPassword = maPreparedOwnerPassword;
+
+ // verify print status
+ pParent->mnPrint = 0;
+ if (mxRbPrintLowRes->get_active())
+ pParent->mnPrint = 1;
+ else if (mxRbPrintHighRes->get_active())
+ pParent->mnPrint = 2;
+
+ // verify changes permitted
+ pParent->mnChangesAllowed = 0;
+
+ if( mxRbChangesInsDel->get_active() )
+ pParent->mnChangesAllowed = 1;
+ else if( mxRbChangesFillForm->get_active() )
+ pParent->mnChangesAllowed = 2;
+ else if( mxRbChangesComment->get_active() )
+ pParent->mnChangesAllowed = 3;
+ else if( mxRbChangesAnyNoCopy->get_active() )
+ pParent->mnChangesAllowed = 4;
+
+ pParent->mbCanCopyOrExtract = mxCbEnableCopy->get_active();
+ pParent->mbCanExtractForAccessibility = mxCbEnableAccessibility->get_active();
+}
+
+void ImpPDFTabSecurityPage::SetFilterConfigItem( const ImpPDFTabDialog* pParent )
+{
+ switch( pParent->mnPrint )
+ {
+ default:
+ case 0:
+ mxRbPrintNone->set_active(true);
+ break;
+ case 1:
+ mxRbPrintLowRes->set_active(true);
+ break;
+ case 2:
+ mxRbPrintHighRes->set_active(true);
+ break;
+ }
+
+ switch( pParent->mnChangesAllowed )
+ {
+ default:
+ case 0:
+ mxRbChangesNone->set_active(true);
+ break;
+ case 1:
+ mxRbChangesInsDel->set_active(true);
+ break;
+ case 2:
+ mxRbChangesFillForm->set_active(true);
+ break;
+ case 3:
+ mxRbChangesComment->set_active(true);
+ break;
+ case 4:
+ mxRbChangesAnyNoCopy->set_active(true);
+ break;
+ }
+
+ mxCbEnableCopy->set_active(pParent->mbCanCopyOrExtract);
+ mxCbEnableAccessibility->set_active(pParent->mbCanExtractForAccessibility);
+
+ // set the status of this windows, according to the PDFA selection
+ enablePermissionControls();
+
+ ImpPDFTabGeneralPage* pGeneralPage = pParent->getGeneralPage();
+
+ if (pGeneralPage)
+ ImplPDFASecurityControl(!pGeneralPage->IsPdfaSelected());
+}
+
+IMPL_LINK_NOARG(ImpPDFTabSecurityPage, ClickmaPbSetPwdHdl, weld::Button&, void)
+{
+ SfxPasswordDialog aPwdDialog(m_xContainer.get(), &msUserPwdTitle);
+ aPwdDialog.SetMinLen(0);
+ aPwdDialog.ShowMinLengthText(false);
+ aPwdDialog.ShowExtras( SfxShowExtras::CONFIRM | SfxShowExtras::PASSWORD2 | SfxShowExtras::CONFIRM2 );
+ aPwdDialog.set_title(msStrSetPwd);
+ aPwdDialog.SetGroup2Text(msOwnerPwdTitle);
+ aPwdDialog.AllowAsciiOnly();
+ if (aPwdDialog.run() == RET_OK) // OK issued get password and set it
+ {
+ OUString aUserPW(aPwdDialog.GetPassword());
+ OUString aOwnerPW(aPwdDialog.GetPassword2());
+
+ mbHaveUserPassword = !aUserPW.isEmpty();
+ mbHaveOwnerPassword = !aOwnerPW.isEmpty();
+
+ mxPreparedPasswords = vcl::PDFWriter::InitEncryption( aOwnerPW, aUserPW );
+ if (!mxPreparedPasswords.is()) {
+ OUString msg;
+ ErrorHandler::GetErrorString(ERRCODE_IO_NOTSUPPORTED, msg); //TODO: handle failure
+ std::unique_ptr<weld::MessageDialog>(
+ Application::CreateMessageDialog(
+ GetFrameWeld(), VclMessageType::Error, VclButtonsType::Ok, msg))
+ ->run();
+ return;
+ }
+
+ if( mbHaveOwnerPassword )
+ {
+ maPreparedOwnerPassword = comphelper::OStorageHelper::CreatePackageEncryptionData( aOwnerPW );
+ }
+ else
+ maPreparedOwnerPassword = Sequence< NamedValue >();
+ }
+ enablePermissionControls();
+}
+
+void ImpPDFTabSecurityPage::enablePermissionControls()
+{
+ bool bIsPDFASel = false;
+ ImpPDFTabDialog* pParent = static_cast<ImpPDFTabDialog*>(GetDialogController());
+ ImpPDFTabGeneralPage* pGeneralPage = pParent ? pParent->getGeneralPage() : nullptr;
+ if (pGeneralPage)
+ {
+ bIsPDFASel = pGeneralPage->IsPdfaSelected();
+ }
+ if (bIsPDFASel)
+ {
+ mxUserPwdPdfa->show();
+ mxUserPwdSet->hide();
+ mxUserPwdUnset->hide();
+ }
+ else
+ {
+ if (mbHaveUserPassword && m_xContainer->get_sensitive())
+ {
+ mxUserPwdSet->show();
+ mxUserPwdUnset->hide();
+ mxUserPwdPdfa->hide();
+ }
+ else
+ {
+ mxUserPwdUnset->show();
+ mxUserPwdSet->hide();
+ mxUserPwdPdfa->hide();
+ }
+ }
+
+ bool bLocalEnable = mbHaveOwnerPassword && m_xContainer->get_sensitive();
+ if (bIsPDFASel)
+ {
+ mxOwnerPwdPdfa->show();
+ mxOwnerPwdSet->hide();
+ mxOwnerPwdUnset->hide();
+ }
+ else
+ {
+ if (bLocalEnable)
+ {
+ mxOwnerPwdSet->show();
+ mxOwnerPwdUnset->hide();
+ mxOwnerPwdPdfa->hide();
+ }
+ else
+ {
+ mxOwnerPwdUnset->show();
+ mxOwnerPwdSet->hide();
+ mxOwnerPwdPdfa->hide();
+ }
+ }
+
+ mxPrintPermissions->set_sensitive(bLocalEnable);
+ mxChangesAllowed->set_sensitive(bLocalEnable);
+ mxContent->set_sensitive(bLocalEnable);
+}
+
+// This tab page is under control of the PDF/A-1a checkbox:
+// TODO: implement a method to do it.
+void ImpPDFTabSecurityPage::ImplPDFASecurityControl( bool bEnableSecurity )
+{
+ m_xContainer->set_sensitive(bEnableSecurity);
+ // after enable, check the status of control as if the dialog was initialized
+ enablePermissionControls();
+}
+
+/// The link preferences tab page (relative and other stuff)
+ImpPDFTabLinksPage::ImpPDFTabLinksPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreSet)
+ : SfxTabPage(pPage, pController, "filter/ui/pdflinkspage.ui", "PdfLinksPage", &rCoreSet)
+ , mbOpnLnksDefaultUserState(false)
+ , mbOpnLnksLaunchUserState(false)
+ , mbOpnLnksBrowserUserState(false)
+ , m_xCbExprtBmkrToNmDst(m_xBuilder->weld_check_button("export"))
+ , m_xCbOOoToPDFTargets(m_xBuilder->weld_check_button("convert"))
+ , m_xCbExportRelativeFsysLinks(m_xBuilder->weld_check_button("exporturl"))
+ , m_xRbOpnLnksDefault(m_xBuilder->weld_radio_button("default"))
+ , m_xRbOpnLnksLaunch(m_xBuilder->weld_radio_button("openpdf"))
+ , m_xRbOpnLnksBrowser(m_xBuilder->weld_radio_button("openinternet"))
+{
+}
+
+ImpPDFTabLinksPage::~ImpPDFTabLinksPage()
+{
+}
+
+std::unique_ptr<SfxTabPage> ImpPDFTabLinksPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet)
+{
+ return std::make_unique<ImpPDFTabLinksPage>(pPage, pController, *rAttrSet);
+}
+
+void ImpPDFTabLinksPage::GetFilterConfigItem( ImpPDFTabDialog* pParent )
+{
+ pParent->mbExportRelativeFsysLinks = m_xCbExportRelativeFsysLinks->get_active();
+
+ bool bIsPDFASel = false;
+ ImpPDFTabGeneralPage* pGeneralPage = pParent->getGeneralPage();
+ if (pGeneralPage)
+ bIsPDFASel = pGeneralPage->IsPdfaSelected();
+ // if PDF/A-1 was not selected while exiting dialog...
+ if( !bIsPDFASel )
+ {
+ // ...get the control states
+ mbOpnLnksDefaultUserState = m_xRbOpnLnksDefault->get_active();
+ mbOpnLnksLaunchUserState = m_xRbOpnLnksLaunch->get_active();
+ mbOpnLnksBrowserUserState = m_xRbOpnLnksBrowser->get_active();
+ }
+ // the control states, or the saved is used
+ // to form the stored selection
+ pParent->mnViewPDFMode = 0;
+ if( mbOpnLnksBrowserUserState )
+ pParent->mnViewPDFMode = 2;
+ else if( mbOpnLnksLaunchUserState )
+ pParent->mnViewPDFMode = 1;
+
+ pParent->mbConvertOOoTargets = m_xCbOOoToPDFTargets->get_active();
+ pParent->mbExportBmkToPDFDestination = m_xCbExprtBmkrToNmDst->get_active();
+}
+
+void ImpPDFTabLinksPage::SetFilterConfigItem( const ImpPDFTabDialog* pParent )
+{
+ m_xCbOOoToPDFTargets->set_active(pParent->mbConvertOOoTargets);
+ m_xCbExprtBmkrToNmDst->set_active(pParent->mbExportBmkToPDFDestination);
+
+ m_xRbOpnLnksDefault->connect_toggled(LINK(this, ImpPDFTabLinksPage, ClickRbOpnLnksDefaultHdl));
+ m_xRbOpnLnksBrowser->connect_toggled(LINK(this, ImpPDFTabLinksPage, ClickRbOpnLnksBrowserHdl));
+
+ m_xCbExportRelativeFsysLinks->set_active(pParent->mbExportRelativeFsysLinks);
+ switch( pParent->mnViewPDFMode )
+ {
+ default:
+ case 0:
+ m_xRbOpnLnksDefault->set_active(true);
+ mbOpnLnksDefaultUserState = true;
+ break;
+ case 1:
+ m_xRbOpnLnksLaunch->set_active(true);
+ mbOpnLnksLaunchUserState = true;
+ break;
+ case 2:
+ m_xRbOpnLnksBrowser->set_active(true);
+ mbOpnLnksBrowserUserState = true;
+ break;
+ }
+
+ // now check the status of PDF/A selection
+ // and set the link action accordingly
+ // PDF/A-2 doesn't allow launch action on links
+
+ ImpPDFTabGeneralPage* pGeneralPage = pParent->getGeneralPage();
+ if (pGeneralPage)
+ ImplPDFALinkControl(!pGeneralPage->mxCbPDFA->get_active());
+}
+
+
+/** Called from general tab, with PDFA/1 selection status.
+ Retrieves/store the status of Launch action selection.
+ */
+void ImpPDFTabLinksPage::ImplPDFALinkControl( bool bEnableLaunch )
+{
+ // set the value and position of link type selection
+ if( bEnableLaunch )
+ {
+ m_xRbOpnLnksLaunch->set_sensitive(true);
+ // restore user state with no PDF/A-1 selected
+ m_xRbOpnLnksDefault->set_active(mbOpnLnksDefaultUserState);
+ m_xRbOpnLnksLaunch->set_active(mbOpnLnksLaunchUserState);
+ m_xRbOpnLnksBrowser->set_active(mbOpnLnksBrowserUserState);
+ }
+ else
+ {
+ // save user state with no PDF/A-1 selected
+ mbOpnLnksDefaultUserState = m_xRbOpnLnksDefault->get_active();
+ mbOpnLnksLaunchUserState = m_xRbOpnLnksLaunch->get_active();
+ mbOpnLnksBrowserUserState = m_xRbOpnLnksBrowser->get_active();
+ m_xRbOpnLnksLaunch->set_sensitive(false);
+ if (mbOpnLnksLaunchUserState)
+ m_xRbOpnLnksBrowser->set_active(true);
+ }
+}
+
+/// Reset the memory of Launch action present when PDF/A-1 was requested
+IMPL_LINK_NOARG(ImpPDFTabLinksPage, ClickRbOpnLnksDefaultHdl, weld::Toggleable&, void)
+{
+ mbOpnLnksDefaultUserState = m_xRbOpnLnksDefault->get_active();
+ mbOpnLnksLaunchUserState = m_xRbOpnLnksLaunch->get_active();
+ mbOpnLnksBrowserUserState = m_xRbOpnLnksBrowser->get_active();
+}
+
+/// Reset the memory of a launch action present when PDF/A-1 was requested
+IMPL_LINK_NOARG(ImpPDFTabLinksPage, ClickRbOpnLnksBrowserHdl, weld::Toggleable&, void)
+{
+ mbOpnLnksDefaultUserState = m_xRbOpnLnksDefault->get_active();
+ mbOpnLnksLaunchUserState = m_xRbOpnLnksLaunch->get_active();
+ mbOpnLnksBrowserUserState = m_xRbOpnLnksBrowser->get_active();
+}
+
+ImplErrorDialog::ImplErrorDialog(weld::Window* pParent, const std::set<vcl::PDFWriter::ErrorCode>& rErrors)
+ : MessageDialogController(pParent, "filter/ui/warnpdfdialog.ui", "WarnPDFDialog", "grid")
+ , m_xErrors(m_xBuilder->weld_tree_view("errors"))
+ , m_xExplanation(m_xBuilder->weld_label("message"))
+{
+ int nWidth = m_xErrors->get_approximate_digit_width() * 26;
+ int nHeight = m_xErrors->get_height_rows(9);
+ m_xErrors->set_size_request(nWidth, nHeight);
+ m_xExplanation->set_size_request(nWidth, nHeight);
+
+ for (auto const& error : rErrors)
+ {
+ switch(error)
+ {
+ case vcl::PDFWriter::Warning_Transparency_Omitted_PDFA:
+ m_xErrors->append(PDFFilterResId(STR_WARN_TRANSP_PDFA), PDFFilterResId(STR_WARN_TRANSP_PDFA_SHORT), "dialog-warning");
+ break;
+ case vcl::PDFWriter::Warning_Transparency_Omitted_PDF13:
+ m_xErrors->append(PDFFilterResId(STR_WARN_TRANSP_VERSION), PDFFilterResId(STR_WARN_TRANSP_VERSION_SHORT), "dialog-warning");
+ break;
+ case vcl::PDFWriter::Warning_FormAction_Omitted_PDFA:
+ m_xErrors->append(PDFFilterResId(STR_WARN_FORMACTION_PDFA), PDFFilterResId(STR_WARN_FORMACTION_PDFA_SHORT), "dialog-warning");
+ break;
+ case vcl::PDFWriter::Warning_Transparency_Converted:
+ m_xErrors->append(PDFFilterResId(STR_WARN_TRANSP_CONVERTED), PDFFilterResId(STR_WARN_TRANSP_CONVERTED_SHORT), "dialog-warning");
+ break;
+ case vcl::PDFWriter::Error_Signature_Failed:
+ m_xErrors->append(PDFFilterResId(STR_ERR_PDF_EXPORT_ABORTED), PDFFilterResId(STR_ERR_SIGNATURE_FAILED), "dialog-error");
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (m_xErrors->n_children() > 0)
+ {
+ m_xErrors->select(0);
+ m_xExplanation->set_label(m_xErrors->get_id(0));
+ }
+
+ m_xErrors->connect_changed(LINK(this, ImplErrorDialog, SelectHdl));
+}
+
+IMPL_LINK_NOARG(ImplErrorDialog, SelectHdl, weld::TreeView&, void)
+{
+ OUString aExplanation = m_xErrors->get_selected_id();
+ m_xExplanation->set_label(aExplanation);
+}
+
+/// The digital signatures tab page
+ImpPDFTabSigningPage::ImpPDFTabSigningPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreSet)
+ : SfxTabPage(pPage, pController, "filter/ui/pdfsignpage.ui", "PdfSignPage", &rCoreSet)
+ , mxEdSignCert(m_xBuilder->weld_entry("cert"))
+ , mxPbSignCertSelect(m_xBuilder->weld_button("select"))
+ , mxPbSignCertClear(m_xBuilder->weld_button("clear"))
+ , mxEdSignPassword(m_xBuilder->weld_entry("password"))
+ , mxEdSignLocation(m_xBuilder->weld_entry("location"))
+ , mxEdSignContactInfo(m_xBuilder->weld_entry("contact"))
+ , mxEdSignReason(m_xBuilder->weld_entry("reason"))
+ , mxLBSignTSA(m_xBuilder->weld_combo_box("tsa"))
+{
+ mxPbSignCertSelect->set_sensitive(true);
+ mxPbSignCertSelect->connect_clicked(LINK(this, ImpPDFTabSigningPage, ClickmaPbSignCertSelect));
+ mxPbSignCertClear->connect_clicked(LINK(this, ImpPDFTabSigningPage, ClickmaPbSignCertClear));
+}
+
+ImpPDFTabSigningPage::~ImpPDFTabSigningPage()
+{
+}
+
+IMPL_LINK_NOARG(ImpPDFTabSigningPage, ClickmaPbSignCertSelect, weld::Button&, void)
+{
+ Reference< security::XDocumentDigitalSignatures > xSigner(
+ security::DocumentDigitalSignatures::createDefault(
+ comphelper::getProcessComponentContext()));
+ xSigner->setParentWindow(GetFrameWeld()->GetXWindow());
+
+ // The use may provide a description while choosing a certificate.
+ OUString aDescription;
+ maSignCertificate = xSigner->selectSigningCertificateWithType(
+ security::CertificateKind::CertificateKind_X509, aDescription);
+
+ if (!maSignCertificate.is())
+ return;
+
+ mxEdSignCert->set_text(maSignCertificate->getSubjectName());
+ mxPbSignCertClear->set_sensitive(true);
+ mxEdSignLocation->set_sensitive(true);
+ mxEdSignPassword->set_sensitive(true);
+ mxEdSignContactInfo->set_sensitive(true);
+ mxEdSignReason->set_sensitive(true);
+ mxEdSignReason->set_text(aDescription);
+
+ try
+ {
+ std::optional<css::uno::Sequence<OUString>> aTSAURLs(officecfg::Office::Common::Security::Scripting::TSAURLs::get());
+ if (aTSAURLs)
+ {
+ const css::uno::Sequence<OUString>& rTSAURLs = *aTSAURLs;
+ for (auto const& elem : rTSAURLs)
+ {
+ mxLBSignTSA->append_text(elem);
+ }
+ }
+ }
+ catch (const uno::Exception &)
+ {
+ TOOLS_INFO_EXCEPTION("filter.pdf", "TSAURLsDialog::TSAURLsDialog()");
+ }
+
+ // If more than only the "None" entry is there, enable the ListBox
+ if (mxLBSignTSA->get_count() > 1)
+ mxLBSignTSA->set_sensitive(true);
+}
+
+IMPL_LINK_NOARG(ImpPDFTabSigningPage, ClickmaPbSignCertClear, weld::Button&, void)
+{
+ mxEdSignCert->set_text("");
+ maSignCertificate.clear();
+ mxPbSignCertClear->set_sensitive(false);
+ mxEdSignLocation->set_sensitive(false);
+ mxEdSignPassword->set_sensitive(false);
+ mxEdSignContactInfo->set_sensitive(false);
+ mxEdSignReason->set_sensitive(false);
+ mxLBSignTSA->set_sensitive(false);
+}
+
+std::unique_ptr<SfxTabPage> ImpPDFTabSigningPage::Create( weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rAttrSet)
+{
+ return std::make_unique<ImpPDFTabSigningPage>(pPage, pController, *rAttrSet);
+}
+
+void ImpPDFTabSigningPage::GetFilterConfigItem( ImpPDFTabDialog* pParent )
+{
+ pParent->mbSignPDF = maSignCertificate.is();
+ pParent->maSignCertificate = maSignCertificate;
+ pParent->msSignLocation = mxEdSignLocation->get_text();
+ pParent->msSignPassword = mxEdSignPassword->get_text();
+ pParent->msSignContact = mxEdSignContactInfo->get_text();
+ pParent->msSignReason = mxEdSignReason->get_text();
+ // Entry 0 is 'None'
+ if (mxLBSignTSA->get_active() >= 1)
+ pParent->msSignTSA = mxLBSignTSA->get_active_text();
+}
+
+void ImpPDFTabSigningPage::SetFilterConfigItem( const ImpPDFTabDialog* pParent )
+{
+ mxEdSignLocation->set_sensitive(false);
+ mxEdSignPassword->set_sensitive(false);
+ mxEdSignContactInfo->set_sensitive(false);
+ mxEdSignReason->set_sensitive(false);
+ mxLBSignTSA->set_sensitive(false);
+ mxPbSignCertClear->set_sensitive(false);
+
+ if (pParent->mbSignPDF)
+ {
+ mxEdSignPassword->set_text(pParent->msSignPassword);
+ mxEdSignLocation->set_text(pParent->msSignLocation);
+ mxEdSignContactInfo->set_text(pParent->msSignContact);
+ mxEdSignReason->set_text(pParent->msSignReason);
+ maSignCertificate = pParent->maSignCertificate;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/pdf/impdialog.hxx b/filter/source/pdf/impdialog.hxx
new file mode 100644
index 000000000..219d47e6d
--- /dev/null
+++ b/filter/source/pdf/impdialog.hxx
@@ -0,0 +1,419 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+#include <svx/AccessibilityCheckDialog.hxx>
+
+#include <vcl/pdfwriter.hxx>
+#include <vcl/FilterConfigItem.hxx>
+#include <vcl/weld.hxx>
+
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+
+class ImpPDFTabGeneralPage;
+class ImpPDFTabViewerPage;
+class ImpPDFTabOpnFtrPage;
+class ImpPDFTabLinksPage;
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+
+class ImplErrorDialog : public weld::MessageDialogController
+{
+private:
+ std::unique_ptr<weld::TreeView> m_xErrors;
+ std::unique_ptr<weld::Label> m_xExplanation;
+
+ DECL_LINK(SelectHdl, weld::TreeView&, void);
+
+public:
+ explicit ImplErrorDialog(weld::Window* pParent, const std::set<vcl::PDFWriter::ErrorCode>& rErrorCodes);
+};
+
+
+class ImpPDFTabSecurityPage;
+class ImpPDFTabLinksPage;
+
+
+/// Class tabbed dialog
+class ImpPDFTabDialog final : public SfxTabDialogController
+{
+ css::uno::Reference<css::lang::XComponent> mrDoc;
+ weld::Window* mpParent;
+
+ FilterConfigItem maConfigItem;
+ FilterConfigItem maConfigI18N;
+
+ Any maSelection;
+
+ DECL_LINK(CancelHdl, weld::Button&, void);
+ DECL_LINK(OkHdl, weld::Button&, void);
+
+ // the following data are the configuration used throughout the dialog and pages
+ bool mbIsPresentation;
+ bool mbIsSpreadsheet;
+ bool mbIsWriter;
+ bool mbSelectionPresent;
+ bool mbUseCTLFont;
+ bool mbUseLosslessCompression;
+ sal_Int32 mnQuality;
+ bool mbReduceImageResolution;
+ sal_Int32 mnMaxImageResolution;
+ bool mbUseTaggedPDF;
+ bool mbUseTaggedPDFUserSelection;
+ sal_Int32 mnPDFTypeSelection;
+ bool mbPDFUACompliance;
+ bool mbExportNotes;
+ bool mbViewPDF;
+ bool mbUseReferenceXObject;
+ bool mbExportNotesPages;
+ bool mbExportOnlyNotesPages;
+ bool mbUseTransitionEffects;
+ bool mbIsSkipEmptyPages;
+ bool mbIsExportPlaceholders;
+ bool mbAddStream;
+ sal_Int32 mnFormsType;
+ bool mbExportFormFields;
+ bool mbAllowDuplicateFieldNames;
+ bool mbExportBookmarks;
+ bool mbExportHiddenSlides;
+ bool mbSinglePageSheets;
+ sal_Int32 mnOpenBookmarkLevels;
+
+ bool mbHideViewerToolbar;
+ bool mbHideViewerMenubar;
+ bool mbHideViewerWindowControls;
+ bool mbResizeWinToInit;
+ bool mbCenterWindow;
+ bool mbOpenInFullScreenMode;
+ bool mbDisplayPDFDocumentTitle;
+ sal_Int32 mnMagnification;
+ sal_Int32 mnInitialView;
+ sal_Int32 mnZoom;
+ sal_Int32 mnInitialPage;
+
+ sal_Int32 mnPageLayout;
+ bool mbFirstPageLeft;
+
+ bool mbEncrypt;
+
+ bool mbRestrictPermissions;
+ css::uno::Sequence< css::beans::NamedValue > maPreparedOwnerPassword;
+ sal_Int32 mnPrint;
+ sal_Int32 mnChangesAllowed;
+ bool mbCanCopyOrExtract;
+ bool mbCanExtractForAccessibility;
+ css::uno::Reference< css::beans::XMaterialHolder > mxPreparedPasswords;
+
+ std::shared_ptr< svx::AccessibilityCheckDialog > mpAccessibilityCheckDialog;
+
+ bool mbIsRangeChecked;
+ OUString msPageRange;
+ bool mbSelectionIsChecked;
+
+ bool mbExportRelativeFsysLinks;
+ sal_Int32 mnViewPDFMode;
+ bool mbConvertOOoTargets;
+ bool mbExportBmkToPDFDestination;
+
+ bool mbSignPDF;
+ OUString msSignPassword;
+ OUString msSignLocation;
+ OUString msSignContact;
+ OUString msSignReason;
+ css::uno::Reference< css::security::XCertificate > maSignCertificate;
+ OUString msSignTSA;
+
+ OUString maWatermarkText;
+
+public:
+
+ friend class ImpPDFTabGeneralPage;
+ friend class ImpPDFTabViewerPage;
+ friend class ImpPDFTabOpnFtrPage;
+ friend class ImpPDFTabSecurityPage;
+ friend class ImpPDFTabLinksPage;
+ friend class ImpPDFTabSigningPage;
+
+ ImpPDFTabDialog(weld::Window* pParent, const Sequence< PropertyValue >& rFilterData,
+ const css::uno::Reference< XComponent >& rDoc);
+ virtual ~ImpPDFTabDialog() override;
+
+ Sequence< PropertyValue > GetFilterData();
+
+ ImpPDFTabSecurityPage* getSecurityPage() const;
+ ImpPDFTabLinksPage* getLinksPage() const;
+ ImpPDFTabGeneralPage* getGeneralPage() const;
+
+private:
+ virtual void PageCreated(const OString& rId, SfxTabPage& rPage) override;
+};
+
+
+/// Class tab page general
+class ImpPDFTabGeneralPage : public SfxTabPage
+{
+ friend class ImpPDFTabLinksPage;
+
+ bool mbUseTaggedPDFUserSelection;
+ bool mbIsPresentation;
+ bool mbIsSpreadsheet;
+ bool mbIsWriter;
+ ImpPDFTabDialog* mpParent;
+
+ std::unique_ptr<weld::RadioButton> mxRbAll;
+ std::unique_ptr<weld::RadioButton> mxRbRange;
+ std::unique_ptr<weld::RadioButton> mxRbSelection;
+ std::unique_ptr<weld::Entry> mxEdPages;
+ std::unique_ptr<weld::Label> mxSelectedSheets;
+ std::unique_ptr<weld::RadioButton> mxRbLosslessCompression;
+ std::unique_ptr<weld::RadioButton> mxRbJPEGCompression;
+ std::unique_ptr<weld::Widget> mxQualityFrame;
+ std::unique_ptr<weld::MetricSpinButton> mxNfQuality;
+ std::unique_ptr<weld::CheckButton> mxCbReduceImageResolution;
+ std::unique_ptr<weld::ComboBox> mxCoReduceImageResolution;
+ std::unique_ptr<weld::CheckButton> mxCbPDFA;
+ std::unique_ptr<weld::CheckButton> mxCbPDFUA;
+ std::unique_ptr<weld::ComboBox> mxRbPDFAVersion;
+ std::unique_ptr<weld::CheckButton> mxCbTaggedPDF;
+ std::unique_ptr<weld::CheckButton> mxCbExportFormFields;
+ std::unique_ptr<weld::Widget> mxFormsFrame;
+ std::unique_ptr<weld::ComboBox> mxLbFormsFormat;
+ std::unique_ptr<weld::CheckButton> mxCbAllowDuplicateFieldNames;
+ std::unique_ptr<weld::CheckButton> mxCbExportBookmarks;
+ std::unique_ptr<weld::CheckButton> mxCbExportHiddenSlides;
+ std::unique_ptr<weld::CheckButton> mxCbSinglePageSheets;
+ std::unique_ptr<weld::CheckButton> mxCbExportNotes;
+ std::unique_ptr<weld::CheckButton> mxCbViewPDF;
+ std::unique_ptr<weld::CheckButton> mxCbUseReferenceXObject;
+ std::unique_ptr<weld::CheckButton> mxCbExportNotesPages;
+ std::unique_ptr<weld::CheckButton> mxCbExportOnlyNotesPages;
+ std::unique_ptr<weld::CheckButton> mxCbExportEmptyPages;
+ std::unique_ptr<weld::CheckButton> mxCbExportPlaceholders;
+ std::unique_ptr<weld::CheckButton> mxCbAddStream;
+ std::unique_ptr<weld::CheckButton> mxCbWatermark;
+ std::unique_ptr<weld::Label> mxFtWatermark;
+ std::unique_ptr<weld::Entry> mxEdWatermark;
+ std::unique_ptr<weld::Label> mxSlidesFt;
+ std::unique_ptr<weld::Label> mxSheetsFt;
+
+ DECL_LINK(ToggleAllHdl, weld::Toggleable&, void);
+ DECL_LINK(TogglePagesHdl, weld::Toggleable&, void);
+ DECL_LINK(ToggleSelectionHdl, weld::Toggleable&, void);
+ DECL_LINK(ToggleCompressionHdl, weld::Toggleable&, void);
+ DECL_LINK(ToggleReduceImageResolutionHdl, weld::Toggleable&, void);
+ DECL_LINK(ToggleWatermarkHdl, weld::Toggleable&, void);
+ DECL_LINK(ToggleAddStreamHdl, weld::Toggleable&, void);
+ DECL_LINK(ToggleExportFormFieldsHdl, weld::Toggleable&, void);
+ DECL_LINK(ToggleExportNotesPagesHdl, weld::Toggleable&, void);
+
+ void TogglePagesHdl();
+ void EnableExportNotesPages();
+
+ DECL_LINK(TogglePDFVersionOrUniversalAccessibilityHandle, weld::Toggleable&, void);
+
+public:
+
+ ImpPDFTabGeneralPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~ImpPDFTabGeneralPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet);
+
+ void GetFilterConfigItem(ImpPDFTabDialog* paParent);
+ void SetFilterConfigItem(ImpPDFTabDialog* paParent);
+ bool IsPdfaSelected() const { return mxCbPDFA->get_active(); }
+ bool IsPdfUaSelected() const { return mxCbPDFUA->get_active(); }
+};
+
+/// Class tab page viewer
+class ImpPDFTabOpnFtrPage : public SfxTabPage
+{
+ bool mbUseCTLFont;
+
+ std::unique_ptr<weld::RadioButton> mxRbOpnPageOnly;
+ std::unique_ptr<weld::RadioButton> mxRbOpnOutline;
+ std::unique_ptr<weld::RadioButton> mxRbOpnThumbs;
+ std::unique_ptr<weld::SpinButton> mxNumInitialPage;
+ std::unique_ptr<weld::RadioButton> mxRbMagnDefault;
+ std::unique_ptr<weld::RadioButton> mxRbMagnFitWin;
+ std::unique_ptr<weld::RadioButton> mxRbMagnFitWidth;
+ std::unique_ptr<weld::RadioButton> mxRbMagnFitVisible;
+ std::unique_ptr<weld::RadioButton> mxRbMagnZoom;
+ std::unique_ptr<weld::SpinButton> mxNumZoom;
+ std::unique_ptr<weld::RadioButton> mxRbPgLyDefault;
+ std::unique_ptr<weld::RadioButton> mxRbPgLySinglePage;
+ std::unique_ptr<weld::RadioButton> mxRbPgLyContinue;
+ std::unique_ptr<weld::RadioButton> mxRbPgLyContinueFacing;
+ std::unique_ptr<weld::CheckButton> mxCbPgLyFirstOnLeft;
+
+ DECL_LINK(ToggleRbPgLyContinueFacingHdl, weld::Toggleable&, void);
+ DECL_LINK(ToggleRbMagnHdl, weld::Toggleable&, void);
+
+ void ToggleRbPgLyContinueFacingHdl();
+
+public:
+ ImpPDFTabOpnFtrPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~ImpPDFTabOpnFtrPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet );
+
+ void GetFilterConfigItem( ImpPDFTabDialog* paParent);
+ void SetFilterConfigItem( const ImpPDFTabDialog* paParent );
+};
+
+/// Class tab page viewer
+class ImpPDFTabViewerPage : public SfxTabPage
+{
+ bool mbIsPresentation;
+
+ std::unique_ptr<weld::CheckButton> m_xCbResWinInit;
+ std::unique_ptr<weld::CheckButton> m_xCbCenterWindow;
+ std::unique_ptr<weld::CheckButton> m_xCbOpenFullScreen;
+ std::unique_ptr<weld::CheckButton> m_xCbDispDocTitle;
+ std::unique_ptr<weld::CheckButton> m_xCbHideViewerMenubar;
+ std::unique_ptr<weld::CheckButton> m_xCbHideViewerToolbar;
+ std::unique_ptr<weld::CheckButton> m_xCbHideViewerWindowControls;
+ std::unique_ptr<weld::CheckButton> m_xCbTransitionEffects;
+ std::unique_ptr<weld::RadioButton> m_xRbAllBookmarkLevels;
+ std::unique_ptr<weld::RadioButton> m_xRbVisibleBookmarkLevels;
+ std::unique_ptr<weld::SpinButton>m_xNumBookmarkLevels;
+
+ DECL_LINK(ToggleRbBookmarksHdl, weld::Toggleable&, void);
+
+public:
+ ImpPDFTabViewerPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~ImpPDFTabViewerPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet );
+
+ void GetFilterConfigItem( ImpPDFTabDialog* paParent);
+ void SetFilterConfigItem( const ImpPDFTabDialog* paParent );
+};
+
+/// Class security tab page
+class ImpPDFTabSecurityPage : public SfxTabPage
+{
+ OUString msStrSetPwd;
+ OUString msUserPwdTitle;
+ bool mbHaveOwnerPassword;
+ bool mbHaveUserPassword;
+ css::uno::Sequence< css::beans::NamedValue > maPreparedOwnerPassword;
+ OUString msOwnerPwdTitle;
+
+ css::uno::Reference< css::beans::XMaterialHolder > mxPreparedPasswords;
+
+ std::unique_ptr<weld::Button> mxPbSetPwd;
+ std::unique_ptr<weld::Widget> mxUserPwdSet;
+ std::unique_ptr<weld::Widget> mxUserPwdUnset;
+ std::unique_ptr<weld::Widget> mxUserPwdPdfa;
+ std::unique_ptr<weld::Widget> mxOwnerPwdSet;
+ std::unique_ptr<weld::Widget> mxOwnerPwdUnset;
+ std::unique_ptr<weld::Widget> mxOwnerPwdPdfa;
+ std::unique_ptr<weld::Widget> mxPrintPermissions;
+ std::unique_ptr<weld::RadioButton> mxRbPrintNone;
+ std::unique_ptr<weld::RadioButton> mxRbPrintLowRes;
+ std::unique_ptr<weld::RadioButton> mxRbPrintHighRes;
+ std::unique_ptr<weld::Widget> mxChangesAllowed;
+ std::unique_ptr<weld::RadioButton> mxRbChangesNone;
+ std::unique_ptr<weld::RadioButton> mxRbChangesInsDel;
+ std::unique_ptr<weld::RadioButton> mxRbChangesFillForm;
+ std::unique_ptr<weld::RadioButton> mxRbChangesComment;
+ std::unique_ptr<weld::RadioButton> mxRbChangesAnyNoCopy;
+ std::unique_ptr<weld::Widget> mxContent;
+ std::unique_ptr<weld::CheckButton> mxCbEnableCopy;
+ std::unique_ptr<weld::CheckButton> mxCbEnableAccessibility;
+ std::unique_ptr<weld::Label> mxPasswordTitle;
+
+ DECL_LINK(ClickmaPbSetPwdHdl, weld::Button&, void);
+
+ void enablePermissionControls();
+
+public:
+ ImpPDFTabSecurityPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~ImpPDFTabSecurityPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet);
+
+ void GetFilterConfigItem( ImpPDFTabDialog* paParent);
+ void SetFilterConfigItem( const ImpPDFTabDialog* paParent );
+ void ImplPDFASecurityControl( bool bEnableSecurity );
+ bool hasPassword() const { return mbHaveOwnerPassword || mbHaveUserPassword; }
+};
+
+/// Implements the relative link stuff
+class ImpPDFTabLinksPage : public SfxTabPage
+{
+ bool mbOpnLnksDefaultUserState;
+ bool mbOpnLnksLaunchUserState;
+ bool mbOpnLnksBrowserUserState;
+
+ std::unique_ptr<weld::CheckButton> m_xCbExprtBmkrToNmDst;
+ std::unique_ptr<weld::CheckButton> m_xCbOOoToPDFTargets;
+ std::unique_ptr<weld::CheckButton> m_xCbExportRelativeFsysLinks;
+ std::unique_ptr<weld::RadioButton> m_xRbOpnLnksDefault;
+ std::unique_ptr<weld::RadioButton> m_xRbOpnLnksLaunch;
+ std::unique_ptr<weld::RadioButton> m_xRbOpnLnksBrowser;
+
+ DECL_LINK(ClickRbOpnLnksDefaultHdl, weld::Toggleable&, void);
+ DECL_LINK(ClickRbOpnLnksBrowserHdl, weld::Toggleable&, void);
+
+public:
+ ImpPDFTabLinksPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~ImpPDFTabLinksPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet);
+
+ void GetFilterConfigItem( ImpPDFTabDialog* paParent);
+ void SetFilterConfigItem( const ImpPDFTabDialog* paParent );
+
+ void ImplPDFALinkControl( bool bEnableLaunch );
+};
+
+//class to implement the digital signing
+class ImpPDFTabSigningPage : public SfxTabPage
+{
+ css::uno::Reference< css::security::XCertificate > maSignCertificate;
+
+ std::unique_ptr<weld::Entry> mxEdSignCert;
+ std::unique_ptr<weld::Button> mxPbSignCertSelect;
+ std::unique_ptr<weld::Button> mxPbSignCertClear;
+ std::unique_ptr<weld::Entry> mxEdSignPassword;
+ std::unique_ptr<weld::Entry> mxEdSignLocation;
+ std::unique_ptr<weld::Entry> mxEdSignContactInfo;
+ std::unique_ptr<weld::Entry> mxEdSignReason;
+ std::unique_ptr<weld::ComboBox> mxLBSignTSA;
+
+ DECL_LINK(ClickmaPbSignCertSelect, weld::Button&, void);
+ DECL_LINK(ClickmaPbSignCertClear, weld::Button&, void);
+
+public:
+ ImpPDFTabSigningPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~ImpPDFTabSigningPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet );
+
+ void GetFilterConfigItem( ImpPDFTabDialog* paParent);
+ void SetFilterConfigItem( const ImpPDFTabDialog* paParent );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/pdf/pdfdecomposer.cxx b/filter/source/pdf/pdfdecomposer.cxx
new file mode 100644
index 000000000..7a032bf36
--- /dev/null
+++ b/filter/source/pdf/pdfdecomposer.cxx
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <vector>
+
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <cppuhelper/implbase2.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <drawinglayer/primitive2d/Primitive2DContainer.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/pdfread.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/BinaryDataContainer.hxx>
+#include <vcl/BinaryDataContainerTools.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+
+#include <com/sun/star/graphic/XPdfDecomposer.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/util/XBinaryDataContainer.hpp>
+
+using namespace css;
+
+namespace
+{
+/// Class to convert the PDF data into a XPrimitive2D (containing only a bitmap).
+class XPdfDecomposer
+ : public ::cppu::WeakAggImplHelper2<graphic::XPdfDecomposer, lang::XServiceInfo>
+{
+public:
+ explicit XPdfDecomposer(uno::Reference<uno::XComponentContext> const& context);
+ XPdfDecomposer(const XPdfDecomposer&) = delete;
+ XPdfDecomposer& operator=(const XPdfDecomposer&) = delete;
+
+ // XPdfDecomposer
+ uno::Sequence<uno::Reference<graphic::XPrimitive2D>> SAL_CALL
+ getDecomposition(const uno::Reference<util::XBinaryDataContainer>& xDataContainer,
+ const uno::Sequence<beans::PropertyValue>& xDecompositionParameters) override;
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ sal_Bool SAL_CALL supportsService(const OUString&) override;
+ uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+XPdfDecomposer::XPdfDecomposer(uno::Reference<uno::XComponentContext> const&) {}
+
+uno::Sequence<uno::Reference<graphic::XPrimitive2D>> SAL_CALL
+XPdfDecomposer::getDecomposition(const uno::Reference<util::XBinaryDataContainer>& xDataContainer,
+ const uno::Sequence<beans::PropertyValue>& xParameters)
+{
+ sal_Int32 nPageIndex = -1;
+
+ for (const beans::PropertyValue& rProperty : xParameters)
+ {
+ if (rProperty.Name == "PageIndex")
+ {
+ rProperty.Value >>= nPageIndex;
+ break;
+ }
+ }
+
+ if (nPageIndex < 0)
+ nPageIndex = 0;
+
+ BinaryDataContainer aDataContainer = vcl::convertUnoBinaryDataContainer(xDataContainer);
+
+ std::vector<BitmapEx> aBitmaps;
+ int rv = vcl::RenderPDFBitmaps(aDataContainer.getData(), aDataContainer.getSize(), aBitmaps,
+ nPageIndex, 1);
+ if (rv == 0)
+ return {}; // happens if we do not have PDFium
+
+ BitmapEx aReplacement(aBitmaps[0]);
+
+ // short form for scale and translate transformation
+ const Size aBitmapSize(aReplacement.GetSizePixel());
+ // ImpGraphic::getPrefMapMode() requires mm100 for bitmaps rendered from vector graphic data.
+ const Size aMM100(
+ Application::GetDefaultDevice()->PixelToLogic(aBitmapSize, MapMode(MapUnit::Map100thMM)));
+ const basegfx::B2DHomMatrix aBitmapTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(
+ aMM100.getWidth(), aMM100.getHeight(), 0, 0));
+
+ // create primitive
+ return drawinglayer::primitive2d::Primitive2DContainer{
+ new drawinglayer::primitive2d::BitmapPrimitive2D(
+ VCLUnoHelper::CreateVCLXBitmap(aReplacement), aBitmapTransform)
+ }
+ .toSequence();
+}
+
+OUString SAL_CALL XPdfDecomposer::getImplementationName()
+{
+ return "com.sun.star.comp.PDF.PDFDecomposer";
+}
+
+sal_Bool SAL_CALL XPdfDecomposer::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL XPdfDecomposer::getSupportedServiceNames()
+{
+ return { "com.sun.star.graphic.PdfTools" };
+}
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_PdfDecomposer_get_implementation(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new XPdfDecomposer(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/filter/source/pdf/pdfdialog.cxx b/filter/source/pdf/pdfdialog.cxx
new file mode 100644
index 000000000..7c3e5dda1
--- /dev/null
+++ b/filter/source/pdf/pdfdialog.cxx
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "pdfdialog.hxx"
+#include "impdialog.hxx"
+#include <vcl/svapp.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+
+PDFDialog::PDFDialog( const Reference< XComponentContext > &rxContext )
+: PDFDialog_Base( rxContext )
+{
+}
+
+
+PDFDialog::~PDFDialog()
+{
+}
+
+
+Sequence< sal_Int8 > SAL_CALL PDFDialog::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+
+OUString SAL_CALL PDFDialog::getImplementationName()
+{
+ return "com.sun.star.comp.PDF.PDFDialog";
+}
+
+
+Sequence< OUString > SAL_CALL PDFDialog::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.PDFDialog" };
+}
+
+std::unique_ptr<weld::DialogController> PDFDialog::createDialog(const css::uno::Reference<css::awt::XWindow>& rParent)
+{
+ if( mxSrcDoc.is() )
+ return std::make_unique<ImpPDFTabDialog>(Application::GetFrameWeld(rParent), maFilterData, mxSrcDoc);
+ return nullptr;
+}
+
+void PDFDialog::executedDialog( sal_Int16 nExecutionResult )
+{
+ if (nExecutionResult && m_xDialog)
+ maFilterData = static_cast<ImpPDFTabDialog*>(m_xDialog.get())->GetFilterData();
+ destroyDialog();
+}
+
+Reference< XPropertySetInfo > SAL_CALL PDFDialog::getPropertySetInfo()
+{
+ Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+::cppu::IPropertyArrayHelper& PDFDialog::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+::cppu::IPropertyArrayHelper* PDFDialog::createArrayHelper() const
+{
+ Sequence< Property > aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper( aProps );
+}
+
+
+Sequence< PropertyValue > SAL_CALL PDFDialog::getPropertyValues()
+{
+ sal_Int32 i, nCount;
+
+ for( i = 0, nCount = maMediaDescriptor.getLength(); i < nCount; i++ )
+ {
+ if ( maMediaDescriptor[ i ].Name == "FilterData" )
+ break;
+ }
+
+ if( i == nCount )
+ maMediaDescriptor.realloc( ++nCount );
+ auto pMediaDescriptor = maMediaDescriptor.getArray();
+
+ pMediaDescriptor[ i ].Name = "FilterData";
+ pMediaDescriptor[ i ].Value <<= maFilterData;
+
+ return maMediaDescriptor;
+}
+
+
+void SAL_CALL PDFDialog::setPropertyValues( const Sequence< PropertyValue >& rProps )
+{
+ maMediaDescriptor = rProps;
+
+ for( const PropertyValue& rProp : std::as_const(maMediaDescriptor) )
+ {
+ if ( rProp.Name == "FilterData" )
+ {
+ rProp.Value >>= maFilterData;
+ break;
+ }
+ }
+}
+
+
+void SAL_CALL PDFDialog::setSourceDocument( const Reference< XComponent >& xDoc )
+{
+ mxSrcDoc = xDoc;
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_PDFDialog_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new PDFDialog(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/pdf/pdfdialog.hxx b/filter/source/pdf/pdfdialog.hxx
new file mode 100644
index 000000000..fcfd1d097
--- /dev/null
+++ b/filter/source/pdf/pdfdialog.hxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <svtools/genericunodialog.hxx>
+
+#include <comphelper/proparrhlp.hxx>
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/beans/XPropertyAccess.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+
+typedef ::cppu::ImplInheritanceHelper < ::svt::OGenericUnoDialog, XPropertyAccess, XExporter > PDFDialog_Base;
+
+class PDFDialog final:
+ public PDFDialog_Base,
+ public ::comphelper::OPropertyArrayUsageHelper< PDFDialog >
+{
+private:
+ Sequence< PropertyValue > maMediaDescriptor;
+ Sequence< PropertyValue > maFilterData;
+ Reference< XComponent > mxSrcDoc;
+
+ // OGenericUnoDialog
+ virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+ virtual std::unique_ptr<weld::DialogController> createDialog(const css::uno::Reference<css::awt::XWindow>& rParent) override;
+ virtual void executedDialog( sal_Int16 nExecutionResult ) override;
+ virtual Reference< XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+
+ // XPropertyAccess
+ using OPropertySetHelper::getPropertyValues;
+ virtual Sequence< PropertyValue > SAL_CALL getPropertyValues( ) override;
+ using OPropertySetHelper::setPropertyValues;
+ virtual void SAL_CALL setPropertyValues( const Sequence< PropertyValue >& aProps ) override;
+
+ // XExporter
+ virtual void SAL_CALL setSourceDocument( const Reference< XComponent >& xDoc ) override;
+
+public:
+
+ explicit PDFDialog( const Reference< XComponentContext >& rxContext );
+ virtual ~PDFDialog() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/pdf/pdfexport.cxx b/filter/source/pdf/pdfexport.cxx
new file mode 100644
index 000000000..7a233aad0
--- /dev/null
+++ b/filter/source/pdf/pdfexport.cxx
@@ -0,0 +1,1374 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <osl/file.hxx>
+#include <tools/debug.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/poly.hxx>
+#include <tools/diagnose_ex.h>
+#include <unotools/resmgr.hxx>
+#include <utility>
+#include <vcl/canvastools.hxx>
+#include <vcl/mapmod.hxx>
+#include <vcl/gdimtf.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/string.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <toolkit/awt/vclxdevice.hxx>
+#include <unotools/configmgr.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+
+#include "pdfexport.hxx"
+#include <strings.hrc>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/configuration/theDefaultProvider.hpp>
+#include <com/sun/star/awt/XDevice.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/frame/ModuleManager.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/view/XViewSettingsSupplier.hpp>
+#include <com/sun/star/task/XInteractionRequest.hpp>
+#include <com/sun/star/task/PDFExportException.hpp>
+#include <com/sun/star/io/IOException.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/security/XCertificate.hpp>
+#include <com/sun/star/beans/XMaterialHolder.hpp>
+#include <com/sun/star/xml/crypto/SEInitializer.hpp>
+
+#include <memory>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::view;
+using namespace ::com::sun::star::graphic;
+
+
+PDFExport::PDFExport( const Reference< XComponent >& rxSrcDoc,
+ const Reference< task::XStatusIndicator >& rxStatusIndicator,
+ const Reference< task::XInteractionHandler >& rxIH,
+ const Reference< XComponentContext >& xContext ) :
+ mxSrcDoc ( rxSrcDoc ),
+ mxContext ( xContext ),
+ mxStatusIndicator ( rxStatusIndicator ),
+ mxIH ( rxIH ),
+ mbUseTaggedPDF ( false ),
+ mnPDFTypeSelection ( 0 ),
+ mbPDFUACompliance ( false),
+ mbExportNotes ( true ),
+ mbExportPlaceholders ( false ),
+ mbUseReferenceXObject ( false ),
+ mbExportNotesPages ( false ),
+ mbExportOnlyNotesPages ( false ),
+ mbUseTransitionEffects ( true ),
+ mbExportBookmarks ( true ),
+ mbExportHiddenSlides ( false ),
+ mbSinglePageSheets ( false ),
+ mnOpenBookmarkLevels ( -1 ),
+ mbUseLosslessCompression ( false ),
+ mbReduceImageResolution ( true ),
+ mbSkipEmptyPages ( true ),
+ mbAddStream ( false ),
+ mnMaxImageResolution ( 300 ),
+ mnQuality ( 80 ),
+ mnFormsFormat ( 0 ),
+ mbExportFormFields ( true ),
+ mbAllowDuplicateFieldNames ( false ),
+ mnProgressValue ( 0 ),
+ mbRemoveTransparencies ( false ),
+
+ mbIsRedactMode ( false ),
+ maWatermarkColor ( COL_LIGHTGREEN ),
+ maWatermarkFontName ( "Helvetica" ),
+
+ mbHideViewerToolbar ( false ),
+ mbHideViewerMenubar ( false ),
+ mbHideViewerWindowControls ( false ),
+ mbFitWindow ( false ),
+ mbCenterWindow ( false ),
+ mbOpenInFullScreenMode ( false ),
+ mbDisplayPDFDocumentTitle ( true ),
+ mnPDFDocumentMode ( 0 ),
+ mnPDFDocumentAction ( 0 ),
+ mnZoom ( 100 ),
+ mnInitialPage ( 1 ),
+ mnPDFPageLayout ( 0 ),
+
+ mbEncrypt ( false ),
+ mbRestrictPermissions ( false ),
+ mnPrintAllowed ( 2 ),
+ mnChangesAllowed ( 4 ),
+ mbCanCopyOrExtract ( true ),
+ mbCanExtractForAccessibility( true ),
+
+ // #i56629
+ mbExportRelativeFsysLinks ( false ),
+ mnDefaultLinkAction ( 0 ),
+ mbConvertOOoTargetToPDFTarget( false ),
+ mbExportBmkToDest ( false ),
+ mbSignPDF ( false )
+{
+}
+
+
+PDFExport::~PDFExport()
+{
+}
+
+
+bool PDFExport::ExportSelection( vcl::PDFWriter& rPDFWriter,
+ Reference< css::view::XRenderable > const & rRenderable,
+ const Any& rSelection,
+ const StringRangeEnumerator& rRangeEnum,
+ Sequence< PropertyValue >& rRenderOptions,
+ sal_Int32 nPageCount )
+{
+ bool bRet = false;
+ try
+ {
+ Any* pFirstPage = nullptr;
+ Any* pLastPage = nullptr;
+
+ bool bExportNotesPages = false;
+
+ auto rRenderOptionsRange = asNonConstRange(rRenderOptions);
+ for( sal_Int32 nData = 0, nDataCount = rRenderOptions.getLength(); nData < nDataCount; ++nData )
+ {
+ if ( rRenderOptions[ nData ].Name == "IsFirstPage" )
+ pFirstPage = &rRenderOptionsRange[ nData ].Value;
+ else if ( rRenderOptions[ nData ].Name == "IsLastPage" )
+ pLastPage = &rRenderOptionsRange[ nData ].Value;
+ else if ( rRenderOptions[ nData ].Name == "ExportNotesPages" )
+ rRenderOptionsRange[ nData ].Value >>= bExportNotesPages;
+ }
+
+ OutputDevice* pOut = rPDFWriter.GetReferenceDevice();
+
+ if( pOut )
+ {
+ if ( nPageCount )
+ {
+ vcl::PDFExtOutDevData& rPDFExtOutDevData = dynamic_cast<vcl::PDFExtOutDevData&>(*pOut->GetExtOutDevData());
+ rPDFExtOutDevData.SetIsExportNotesPages( bExportNotesPages );
+
+ sal_Int32 nCurrentPage(0);
+ StringRangeEnumerator::Iterator aIter = rRangeEnum.begin();
+ StringRangeEnumerator::Iterator aEnd = rRangeEnum.end();
+ while ( aIter != aEnd )
+ {
+ const Sequence< PropertyValue > aRenderer( rRenderable->getRenderer( *aIter, rSelection, rRenderOptions ) );
+ awt::Size aPageSize;
+
+ for( const PropertyValue& rProp : aRenderer )
+ {
+ if ( rProp.Name == "PageSize" )
+ {
+ rProp.Value >>= aPageSize;
+ break;
+ }
+ }
+
+ rPDFExtOutDevData.SetCurrentPageNumber( nCurrentPage );
+
+ GDIMetaFile aMtf;
+ const MapMode aMapMode( MapUnit::Map100thMM );
+ const Size aMtfSize( aPageSize.Width, aPageSize.Height );
+
+ pOut->Push();
+ pOut->EnableOutput( false );
+ pOut->SetMapMode( aMapMode );
+
+ aMtf.SetPrefSize( aMtfSize );
+ aMtf.SetPrefMapMode( aMapMode );
+ aMtf.Record( pOut );
+
+ // #i35176#
+ // IsLastPage property.
+ const sal_Int32 nCurrentRenderer = *aIter;
+ ++aIter;
+ if ( pLastPage && aIter == aEnd )
+ *pLastPage <<= true;
+
+ rRenderable->render( nCurrentRenderer, rSelection, rRenderOptions );
+
+ aMtf.Stop();
+ aMtf.WindStart();
+
+ bool bEmptyPage = false;
+ if( aMtf.GetActionSize() &&
+ ( !mbSkipEmptyPages || aPageSize.Width || aPageSize.Height ) )
+ {
+ // We convert the whole metafile into a bitmap to get rid of the
+ // text covered by redaction shapes
+ if (mbIsRedactMode)
+ {
+ try
+ {
+ Graphic aGraph(aMtf);
+ // use antialiasing to improve how graphic objects look
+ BitmapEx bmp = aGraph.GetBitmapEx(GraphicConversionParameters(Size(0, 0), false, true, false));
+ Graphic bgraph(bmp);
+ aMtf = bgraph.GetGDIMetaFile();
+ }
+ catch(const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("filter.pdf", "Something went wrong while converting metafile to bitmap");
+ }
+ }
+
+ ImplExportPage(rPDFWriter, rPDFExtOutDevData, aMtf);
+ bRet = true;
+ }
+ else
+ {
+ bEmptyPage = true;
+ }
+
+ pOut->Pop();
+
+ if ( mxStatusIndicator.is() )
+ mxStatusIndicator->setValue( mnProgressValue );
+ if ( pFirstPage )
+ *pFirstPage <<= false;
+
+ ++mnProgressValue;
+ if (!bEmptyPage)
+ {
+ // Calculate the page number in the PDF output, which may be smaller than the page number in
+ // case of hidden slides or a partial export.
+ ++nCurrentPage;
+ }
+ }
+ }
+ else
+ {
+ bRet = true; // #i18334# nPageCount == 0,
+ rPDFWriter.NewPage( 10000, 10000 ); // creating dummy page
+ rPDFWriter.SetMapMode(MapMode(MapUnit::Map100thMM));
+ }
+ }
+ }
+ catch(const RuntimeException &)
+ {
+ }
+ return bRet;
+}
+
+namespace {
+
+class PDFExportStreamDoc : public vcl::PDFOutputStream
+{
+private:
+
+ Reference< XComponent > m_xSrcDoc;
+ Sequence< beans::NamedValue > m_aPreparedPassword;
+
+public:
+
+ PDFExportStreamDoc( const Reference< XComponent >& xDoc, const Sequence<beans::NamedValue>& rPwd )
+ : m_xSrcDoc( xDoc ),
+ m_aPreparedPassword( rPwd )
+ {}
+
+ virtual void write( const Reference< XOutputStream >& xStream ) override;
+};
+
+}
+
+void PDFExportStreamDoc::write( const Reference< XOutputStream >& xStream )
+{
+ Reference< css::frame::XStorable > xStore( m_xSrcDoc, UNO_QUERY );
+ if( !xStore.is() )
+ return;
+
+ Sequence< beans::PropertyValue > aArgs( 2 + (m_aPreparedPassword.hasElements() ? 1 : 0) );
+ aArgs.getArray()[0].Name = "FilterName";
+ aArgs.getArray()[1].Name = "OutputStream";
+ aArgs.getArray()[1].Value <<= xStream;
+ if( m_aPreparedPassword.hasElements() )
+ {
+ aArgs.getArray()[2].Name = "EncryptionData";
+ aArgs.getArray()[2].Value <<= m_aPreparedPassword;
+ }
+
+ try
+ {
+ xStore->storeToURL( "private:stream", aArgs );
+ }
+ catch( const IOException& )
+ {
+ }
+}
+
+
+static OUString getMimetypeForDocument( const Reference< XComponentContext >& xContext,
+ const Reference< XComponent >& xDoc ) noexcept
+{
+ OUString aDocMimetype;
+ try
+ {
+ // get document service name
+ Reference< css::frame::XStorable > xStore( xDoc, UNO_QUERY );
+ Reference< frame::XModuleManager2 > xModuleManager = frame::ModuleManager::create(xContext);
+ if( xStore.is() )
+ {
+ OUString aDocServiceName = xModuleManager->identify( Reference< XInterface >( xStore, uno::UNO_QUERY ) );
+ if ( !aDocServiceName.isEmpty() )
+ {
+ // get the actual filter name
+ Reference< lang::XMultiServiceFactory > xConfigProvider =
+ configuration::theDefaultProvider::get( xContext );
+ beans::NamedValue aPathProp;
+ aPathProp.Name = "nodepath";
+ aPathProp.Value <<= OUString( "/org.openoffice.Setup/Office/Factories/" );
+ uno::Sequence< uno::Any > aArgs{ uno::Any(aPathProp) };
+
+ Reference< container::XNameAccess > xSOFConfig(
+ xConfigProvider->createInstanceWithArguments(
+ "com.sun.star.configuration.ConfigurationAccess", aArgs ),
+ uno::UNO_QUERY );
+
+ Reference< container::XNameAccess > xApplConfig;
+ xSOFConfig->getByName( aDocServiceName ) >>= xApplConfig;
+ if ( xApplConfig.is() )
+ {
+ OUString aFilterName;
+ xApplConfig->getByName( "ooSetupFactoryActualFilter" ) >>= aFilterName;
+ if( !aFilterName.isEmpty() )
+ {
+ // find the related type name
+ OUString aTypeName;
+ Reference< container::XNameAccess > xFilterFactory(
+ xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", xContext),
+ uno::UNO_QUERY );
+
+ Sequence< beans::PropertyValue > aFilterData;
+ xFilterFactory->getByName( aFilterName ) >>= aFilterData;
+ for ( const beans::PropertyValue& rProp : std::as_const(aFilterData) )
+ if ( rProp.Name == "Type" )
+ rProp.Value >>= aTypeName;
+
+ if ( !aTypeName.isEmpty() )
+ {
+ // find the mediatype
+ Reference< container::XNameAccess > xTypeDetection(
+ xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", xContext),
+ UNO_QUERY );
+
+ Sequence< beans::PropertyValue > aTypeData;
+ xTypeDetection->getByName( aTypeName ) >>= aTypeData;
+ for ( const beans::PropertyValue& rProp : std::as_const(aTypeData) )
+ if ( rProp.Name == "MediaType" )
+ rProp.Value >>= aDocMimetype;
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (...)
+ {
+ }
+ return aDocMimetype;
+}
+
+uno::Reference<security::XCertificate>
+PDFExport::GetCertificateFromSubjectName(const std::u16string_view& rSubjectName) const
+{
+ uno::Reference<xml::crypto::XSEInitializer> xSEInitializer
+ = xml::crypto::SEInitializer::create(mxContext);
+ uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext
+ = xSEInitializer->createSecurityContext(OUString());
+ uno::Reference<xml::crypto::XSecurityEnvironment> xSecurityEnvironment
+ = xSecurityContext->getSecurityEnvironment();
+ for (const auto& xCertificate : xSecurityEnvironment->getPersonalCertificates())
+ {
+ if (xCertificate->getSubjectName() == rSubjectName)
+ {
+ return xCertificate;
+ }
+ }
+
+ return {};
+}
+
+bool PDFExport::Export( const OUString& rFile, const Sequence< PropertyValue >& rFilterData )
+{
+ INetURLObject aURL( rFile );
+ bool bRet = false;
+
+ std::set< vcl::PDFWriter::ErrorCode > aErrors;
+
+ if( aURL.GetProtocol() != INetProtocol::File )
+ {
+ OUString aTmp;
+
+ if( osl::FileBase::getFileURLFromSystemPath( rFile, aTmp ) == osl::FileBase::E_None )
+ aURL = INetURLObject(aTmp);
+ }
+
+ if( aURL.GetProtocol() == INetProtocol::File )
+ {
+ Reference< XRenderable > xRenderable( mxSrcDoc, UNO_QUERY );
+
+ if( xRenderable.is() )
+ {
+ rtl::Reference<VCLXDevice> xDevice(new VCLXDevice);
+ OUString aPageRange;
+ Any aSelection;
+ vcl::PDFWriter::PDFWriterContext aContext;
+ OUString aOpenPassword, aPermissionPassword;
+ Reference< beans::XMaterialHolder > xEnc;
+ Sequence< beans::NamedValue > aPreparedPermissionPassword;
+
+
+ // getting the string for the creator
+ OUString aCreator;
+ Reference< XServiceInfo > xInfo( mxSrcDoc, UNO_QUERY );
+ if ( xInfo.is() )
+ {
+ if ( xInfo->supportsService( "com.sun.star.presentation.PresentationDocument" ) )
+ aCreator += "Impress";
+ else if ( xInfo->supportsService( "com.sun.star.drawing.DrawingDocument" ) )
+ aCreator += "Draw";
+ else if ( xInfo->supportsService( "com.sun.star.text.TextDocument" ) )
+ aCreator += "Writer";
+ else if ( xInfo->supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) )
+ aCreator += "Calc";
+ else if ( xInfo->supportsService( "com.sun.star.formula.FormulaProperties" ) )
+ aCreator += "Math";
+ }
+
+ Reference< document::XDocumentPropertiesSupplier > xDocumentPropsSupplier( mxSrcDoc, UNO_QUERY );
+ if ( xDocumentPropsSupplier.is() )
+ {
+ Reference< document::XDocumentProperties > xDocumentProps( xDocumentPropsSupplier->getDocumentProperties() );
+ if ( xDocumentProps.is() )
+ {
+ aContext.DocumentInfo.Title = xDocumentProps->getTitle();
+ aContext.DocumentInfo.Author = xDocumentProps->getAuthor();
+ aContext.DocumentInfo.Subject = xDocumentProps->getSubject();
+ aContext.DocumentInfo.Keywords = ::comphelper::string::convertCommaSeparated(xDocumentProps->getKeywords());
+ }
+ }
+ // getting the string for the producer
+ OUString aProducerOverride = officecfg::Office::Common::Save::Document::GeneratorOverride::get();
+ if( !aProducerOverride.isEmpty())
+ aContext.DocumentInfo.Producer = aProducerOverride;
+ else
+ aContext.DocumentInfo.Producer =
+ utl::ConfigManager::getProductName() +
+ " " +
+ utl::ConfigManager::getProductVersion();
+
+ aContext.DocumentInfo.Creator = aCreator;
+
+ OUString aSignCertificateSubjectName;
+ for ( const beans::PropertyValue& rProp : rFilterData )
+ {
+ if ( rProp.Name == "PageRange" )
+ rProp.Value >>= aPageRange;
+ else if ( rProp.Name == "Selection" )
+ aSelection = rProp.Value;
+ else if ( rProp.Name == "UseLosslessCompression" )
+ rProp.Value >>= mbUseLosslessCompression;
+ else if ( rProp.Name == "Quality" )
+ rProp.Value >>= mnQuality;
+ else if ( rProp.Name == "ReduceImageResolution" )
+ rProp.Value >>= mbReduceImageResolution;
+ else if ( rProp.Name == "IsSkipEmptyPages" )
+ rProp.Value >>= mbSkipEmptyPages;
+ else if ( rProp.Name == "MaxImageResolution" )
+ rProp.Value >>= mnMaxImageResolution;
+ else if ( rProp.Name == "UseTaggedPDF" )
+ rProp.Value >>= mbUseTaggedPDF;
+ else if ( rProp.Name == "SelectPdfVersion" )
+ rProp.Value >>= mnPDFTypeSelection;
+ else if ( rProp.Name == "PDFUACompliance" )
+ rProp.Value >>= mbPDFUACompliance;
+ else if ( rProp.Name == "ExportNotes" )
+ rProp.Value >>= mbExportNotes;
+ else if ( rProp.Name == "ExportNotesPages" )
+ rProp.Value >>= mbExportNotesPages;
+ else if ( rProp.Name == "ExportOnlyNotesPages" )
+ rProp.Value >>= mbExportOnlyNotesPages;
+ else if ( rProp.Name == "UseTransitionEffects" )
+ rProp.Value >>= mbUseTransitionEffects;
+ else if ( rProp.Name == "ExportFormFields" )
+ rProp.Value >>= mbExportFormFields;
+ else if ( rProp.Name == "FormsType" )
+ rProp.Value >>= mnFormsFormat;
+ else if ( rProp.Name == "AllowDuplicateFieldNames" )
+ rProp.Value >>= mbAllowDuplicateFieldNames;
+ // viewer properties
+ else if ( rProp.Name == "HideViewerToolbar" )
+ rProp.Value >>= mbHideViewerToolbar;
+ else if ( rProp.Name == "HideViewerMenubar" )
+ rProp.Value >>= mbHideViewerMenubar;
+ else if ( rProp.Name == "HideViewerWindowControls" )
+ rProp.Value >>= mbHideViewerWindowControls;
+ else if ( rProp.Name == "ResizeWindowToInitialPage" )
+ rProp.Value >>= mbFitWindow;
+ else if ( rProp.Name == "CenterWindow" )
+ rProp.Value >>= mbCenterWindow;
+ else if ( rProp.Name == "OpenInFullScreenMode" )
+ rProp.Value >>= mbOpenInFullScreenMode;
+ else if ( rProp.Name == "DisplayPDFDocumentTitle" )
+ rProp.Value >>= mbDisplayPDFDocumentTitle;
+ else if ( rProp.Name == "InitialView" )
+ rProp.Value >>= mnPDFDocumentMode;
+ else if ( rProp.Name == "Magnification" )
+ rProp.Value >>= mnPDFDocumentAction;
+ else if ( rProp.Name == "Zoom" )
+ rProp.Value >>= mnZoom;
+ else if ( rProp.Name == "InitialPage" )
+ rProp.Value >>= mnInitialPage;
+ else if ( rProp.Name == "PageLayout" )
+ rProp.Value >>= mnPDFPageLayout;
+ else if ( rProp.Name == "FirstPageOnLeft" )
+ rProp.Value >>= aContext.FirstPageLeft;
+ else if ( rProp.Name == "IsAddStream" )
+ rProp.Value >>= mbAddStream;
+ else if ( rProp.Name == "Watermark" )
+ rProp.Value >>= msWatermark;
+ else if ( rProp.Name == "WatermarkColor" )
+ {
+ sal_Int32 nColor{};
+ if (rProp.Value >>= nColor)
+ {
+ maWatermarkColor = Color(ColorTransparency, nColor);
+ }
+ }
+ else if (rProp.Name == "WatermarkFontHeight")
+ {
+ sal_Int32 nFontHeight{};
+ if (rProp.Value >>= nFontHeight)
+ {
+ moWatermarkFontHeight = nFontHeight;
+ }
+ }
+ else if (rProp.Name == "WatermarkRotateAngle")
+ {
+ sal_Int32 nRotateAngle{};
+ if (rProp.Value >>= nRotateAngle)
+ {
+ moWatermarkRotateAngle = Degree10(nRotateAngle);
+ }
+ }
+ else if (rProp.Name == "WatermarkFontName")
+ {
+ OUString aFontName{};
+ if (rProp.Value >>= aFontName)
+ {
+ maWatermarkFontName = aFontName;
+ }
+ }
+ else if ( rProp.Name == "TiledWatermark" )
+ rProp.Value >>= msTiledWatermark;
+ // now all the security related properties...
+ else if ( rProp.Name == "EncryptFile" )
+ rProp.Value >>= mbEncrypt;
+ else if ( rProp.Name == "DocumentOpenPassword" )
+ rProp.Value >>= aOpenPassword;
+ else if ( rProp.Name == "RestrictPermissions" )
+ rProp.Value >>= mbRestrictPermissions;
+ else if ( rProp.Name == "PermissionPassword" )
+ rProp.Value >>= aPermissionPassword;
+ else if ( rProp.Name == "PreparedPasswords" )
+ rProp.Value >>= xEnc;
+ else if ( rProp.Name == "PreparedPermissionPassword" )
+ rProp.Value >>= aPreparedPermissionPassword;
+ else if ( rProp.Name == "Printing" )
+ rProp.Value >>= mnPrintAllowed;
+ else if ( rProp.Name == "Changes" )
+ rProp.Value >>= mnChangesAllowed;
+ else if ( rProp.Name == "EnableCopyingOfContent" )
+ rProp.Value >>= mbCanCopyOrExtract;
+ else if ( rProp.Name == "EnableTextAccessForAccessibilityTools" )
+ rProp.Value >>= mbCanExtractForAccessibility;
+ // i56629 links extra (relative links and other related stuff)
+ else if ( rProp.Name == "ExportLinksRelativeFsys" )
+ rProp.Value >>= mbExportRelativeFsysLinks;
+ else if ( rProp.Name == "PDFViewSelection" )
+ rProp.Value >>= mnDefaultLinkAction;
+ else if ( rProp.Name == "ConvertOOoTargetToPDFTarget" )
+ rProp.Value >>= mbConvertOOoTargetToPDFTarget;
+ else if ( rProp.Name == "ExportBookmarksToPDFDestination" )
+ rProp.Value >>= mbExportBmkToDest;
+ else if ( rProp.Name == "ExportBookmarks" )
+ rProp.Value >>= mbExportBookmarks;
+ else if ( rProp.Name == "ExportHiddenSlides" )
+ rProp.Value >>= mbExportHiddenSlides;
+ else if ( rProp.Name == "SinglePageSheets" )
+ rProp.Value >>= mbSinglePageSheets;
+ else if ( rProp.Name == "OpenBookmarkLevels" )
+ rProp.Value >>= mnOpenBookmarkLevels;
+ else if ( rProp.Name == "SignPDF" )
+ rProp.Value >>= mbSignPDF;
+ else if ( rProp.Name == "SignatureLocation" )
+ rProp.Value >>= msSignLocation;
+ else if ( rProp.Name == "SignatureReason" )
+ rProp.Value >>= msSignReason;
+ else if ( rProp.Name == "SignatureContactInfo" )
+ rProp.Value >>= msSignContact;
+ else if ( rProp.Name == "SignaturePassword" )
+ rProp.Value >>= msSignPassword;
+ else if ( rProp.Name == "SignatureCertificate" )
+ rProp.Value >>= maSignCertificate;
+ else if (rProp.Name == "SignCertificateSubjectName")
+ rProp.Value >>= aSignCertificateSubjectName;
+ else if ( rProp.Name == "SignatureTSA" )
+ rProp.Value >>= msSignTSA;
+ else if ( rProp.Name == "ExportPlaceholders" )
+ rProp.Value >>= mbExportPlaceholders;
+ else if ( rProp.Name == "UseReferenceXObject" )
+ rProp.Value >>= mbUseReferenceXObject;
+ // Redaction & bitmap related stuff
+ else if ( rProp.Name == "IsRedactMode" )
+ rProp.Value >>= mbIsRedactMode;
+ }
+
+ if (!maSignCertificate.is() && !aSignCertificateSubjectName.isEmpty())
+ {
+ maSignCertificate = GetCertificateFromSubjectName(aSignCertificateSubjectName);
+ }
+
+ aContext.URL = aURL.GetMainURL(INetURLObject::DecodeMechanism::ToIUri);
+
+ // set the correct version, depending on user request
+ switch( mnPDFTypeSelection )
+ {
+ default:
+ case 0:
+ aContext.Version = vcl::PDFWriter::PDFVersion::PDF_1_6;
+ break;
+ case 1:
+ aContext.Version = vcl::PDFWriter::PDFVersion::PDF_A_1;
+ mbUseTaggedPDF = true; // force the tagged PDF as well
+ mbRemoveTransparencies = true; // does not allow transparencies
+ mbEncrypt = false; // no encryption
+ xEnc.clear();
+ break;
+ case 2:
+ aContext.Version = vcl::PDFWriter::PDFVersion::PDF_A_2;
+ mbUseTaggedPDF = true; // force the tagged PDF as well
+ mbRemoveTransparencies = false; // does allow transparencies
+ mbEncrypt = false; // no encryption
+ xEnc.clear();
+ break;
+ case 3:
+ aContext.Version = vcl::PDFWriter::PDFVersion::PDF_A_3;
+ mbUseTaggedPDF = true; // force the tagged PDF as well
+ mbRemoveTransparencies = false; // does allow transparencies
+ mbEncrypt = false; // no encryption
+ xEnc.clear();
+ break;
+ case 15:
+ aContext.Version = vcl::PDFWriter::PDFVersion::PDF_1_5;
+ break;
+ case 16:
+ aContext.Version = vcl::PDFWriter::PDFVersion::PDF_1_6;
+ break;
+ }
+
+ // PDF/UA support
+ aContext.UniversalAccessibilityCompliance = mbPDFUACompliance;
+ if (mbPDFUACompliance)
+ {
+ mbUseTaggedPDF = true;
+ }
+
+ // copy in context the values default in the constructor or set by the FilterData sequence of properties
+ aContext.Tagged = mbUseTaggedPDF;
+
+ // values used in viewer
+ aContext.HideViewerToolbar = mbHideViewerToolbar;
+ aContext.HideViewerMenubar = mbHideViewerMenubar;
+ aContext.HideViewerWindowControls = mbHideViewerWindowControls;
+ aContext.FitWindow = mbFitWindow;
+ aContext.CenterWindow = mbCenterWindow;
+ aContext.OpenInFullScreenMode = mbOpenInFullScreenMode;
+ aContext.DisplayPDFDocumentTitle = mbDisplayPDFDocumentTitle;
+ aContext.InitialPage = mnInitialPage-1;
+ aContext.OpenBookmarkLevels = mnOpenBookmarkLevels;
+
+ switch( mnPDFDocumentMode )
+ {
+ default:
+ case 0:
+ aContext.PDFDocumentMode = vcl::PDFWriter::ModeDefault;
+ break;
+ case 1:
+ aContext.PDFDocumentMode = vcl::PDFWriter::UseOutlines;
+ break;
+ case 2:
+ aContext.PDFDocumentMode = vcl::PDFWriter::UseThumbs;
+ break;
+ }
+ switch( mnPDFDocumentAction )
+ {
+ default:
+ case 0:
+ aContext.PDFDocumentAction = vcl::PDFWriter::ActionDefault;
+ break;
+ case 1:
+ aContext.PDFDocumentAction = vcl::PDFWriter::FitInWindow;
+ break;
+ case 2:
+ aContext.PDFDocumentAction = vcl::PDFWriter::FitWidth;
+ break;
+ case 3:
+ aContext.PDFDocumentAction = vcl::PDFWriter::FitVisible;
+ break;
+ case 4:
+ aContext.PDFDocumentAction = vcl::PDFWriter::ActionZoom;
+ aContext.Zoom = mnZoom;
+ break;
+ }
+
+ switch( mnPDFPageLayout )
+ {
+ default:
+ case 0:
+ aContext.PageLayout = vcl::PDFWriter::DefaultLayout;
+ break;
+ case 1:
+ aContext.PageLayout = vcl::PDFWriter::SinglePage;
+ break;
+ case 2:
+ aContext.PageLayout = vcl::PDFWriter::Continuous;
+ break;
+ case 3:
+ aContext.PageLayout = vcl::PDFWriter::ContinuousFacing;
+ break;
+ }
+
+ aContext.FirstPageLeft = false;
+
+ // check if PDF/A, which does not allow encryption
+ if( aContext.Version != vcl::PDFWriter::PDFVersion::PDF_A_1 )
+ {
+ // set check for permission change password
+ // if not enabled and no permission password, force permissions to default as if PDF where without encryption
+ if( mbRestrictPermissions && (xEnc.is() || !aPermissionPassword.isEmpty()) )
+ {
+ mbEncrypt = true; // permission set as desired, done after
+ }
+ else
+ {
+ // force permission to default
+ mnPrintAllowed = 2 ;
+ mnChangesAllowed = 4 ;
+ mbCanCopyOrExtract = true;
+ mbCanExtractForAccessibility = true ;
+ }
+
+ switch( mnPrintAllowed )
+ {
+ case 0: // initialized when aContext is build, means no printing
+ break;
+ default:
+ case 2:
+ aContext.Encryption.CanPrintFull = true;
+ [[fallthrough]];
+ case 1:
+ aContext.Encryption.CanPrintTheDocument = true;
+ break;
+ }
+
+ switch( mnChangesAllowed )
+ {
+ case 0: // already in struct PDFSecPermissions CTOR
+ break;
+ case 1:
+ aContext.Encryption.CanAssemble = true;
+ break;
+ case 2:
+ aContext.Encryption.CanFillInteractive = true;
+ break;
+ case 3:
+ aContext.Encryption.CanAddOrModify = true;
+ break;
+ default:
+ case 4:
+ aContext.Encryption.CanModifyTheContent =
+ aContext.Encryption.CanCopyOrExtract =
+ aContext.Encryption.CanAddOrModify =
+ aContext.Encryption.CanFillInteractive = true;
+ break;
+ }
+
+ aContext.Encryption.CanCopyOrExtract = mbCanCopyOrExtract;
+ aContext.Encryption.CanExtractForAccessibility = mbCanExtractForAccessibility;
+ if( mbEncrypt && ! xEnc.is() )
+ xEnc = vcl::PDFWriter::InitEncryption( aPermissionPassword, aOpenPassword );
+ if( mbEncrypt && !aPermissionPassword.isEmpty() && ! aPreparedPermissionPassword.hasElements() )
+ aPreparedPermissionPassword = comphelper::OStorageHelper::CreatePackageEncryptionData( aPermissionPassword );
+ }
+ // after this point we don't need the legacy clear passwords anymore
+ // however they are still inside the passed filter data sequence
+ // which is sadly out of our control
+ aPermissionPassword.clear();
+ aOpenPassword.clear();
+
+ /*
+ * FIXME: the entries are only implicitly defined by the resource file. Should there
+ * ever be an additional form submit format this could get invalid.
+ */
+ switch( mnFormsFormat )
+ {
+ case 1:
+ aContext.SubmitFormat = vcl::PDFWriter::PDF;
+ break;
+ case 2:
+ aContext.SubmitFormat = vcl::PDFWriter::HTML;
+ break;
+ case 3:
+ aContext.SubmitFormat = vcl::PDFWriter::XML;
+ break;
+ default:
+ case 0:
+ aContext.SubmitFormat = vcl::PDFWriter::FDF;
+ break;
+ }
+ aContext.AllowDuplicateFieldNames = mbAllowDuplicateFieldNames;
+
+ // get model
+ Reference< frame::XModel > xModel( mxSrcDoc, UNO_QUERY );
+ {
+ // #i56629: Relative link stuff
+ // set the base URL of the file: then base URL
+ aContext.BaseURL = xModel->getURL();
+ // relative link option is private to PDF Export filter and limited to local filesystem only
+ aContext.RelFsys = mbExportRelativeFsysLinks;
+ // determine the default acton for PDF links
+ switch( mnDefaultLinkAction )
+ {
+ default:
+ // default: URI, without fragment conversion (the bookmark in PDF may not work)
+ case 0:
+ aContext.DefaultLinkAction = vcl::PDFWriter::URIAction;
+ break;
+ case 1:
+ // view PDF through the reader application
+ aContext.ForcePDFAction = true;
+ aContext.DefaultLinkAction = vcl::PDFWriter::LaunchAction;
+ break;
+ case 2:
+ // view PDF through an Internet browser
+ aContext.DefaultLinkAction = vcl::PDFWriter::URIActionDestination;
+ break;
+ }
+ aContext.ConvertOOoTargetToPDFTarget = mbConvertOOoTargetToPDFTarget;
+
+ // check for Link Launch action, not allowed on PDF/A-1
+ // this code chunk checks when the filter is called from scripting
+ if( aContext.Version == vcl::PDFWriter::PDFVersion::PDF_A_1 &&
+ aContext.DefaultLinkAction == vcl::PDFWriter::LaunchAction )
+ {
+ // force the similar allowed URI action
+ aContext.DefaultLinkAction = vcl::PDFWriter::URIActionDestination;
+ // and remove the remote goto action forced on PDF file
+ aContext.ForcePDFAction = false;
+ }
+ }
+
+ aContext.SignPDF = mbSignPDF;
+ aContext.SignLocation = msSignLocation;
+ aContext.SignContact = msSignContact;
+ aContext.SignReason = msSignReason;
+ aContext.SignPassword = msSignPassword;
+ aContext.SignCertificate = maSignCertificate;
+ aContext.SignTSA = msSignTSA;
+ aContext.UseReferenceXObject = mbUseReferenceXObject;
+
+ // all context data set, time to create the printing device
+ vcl::PDFWriter aPDFWriter( aContext, xEnc );
+ OutputDevice* pOut = aPDFWriter.GetReferenceDevice();
+
+ DBG_ASSERT( pOut, "PDFExport::Export: no reference device" );
+ xDevice->SetOutputDevice(pOut);
+
+ if( mbAddStream )
+ {
+ // export stream
+ // get mimetype
+ OUString aSrcMimetype = getMimetypeForDocument( mxContext, mxSrcDoc );
+ aPDFWriter.AddStream( aSrcMimetype,
+ new PDFExportStreamDoc( mxSrcDoc, aPreparedPermissionPassword )
+ );
+ }
+
+ if ( pOut )
+ {
+ DBG_ASSERT( pOut->GetExtOutDevData() == nullptr, "PDFExport: ExtOutDevData already set!!!" );
+ vcl::PDFExtOutDevData aPDFExtOutDevData( *pOut );
+ pOut->SetExtOutDevData( &aPDFExtOutDevData );
+ aPDFExtOutDevData.SetIsExportNotes( mbExportNotes );
+ aPDFExtOutDevData.SetIsExportTaggedPDF( mbUseTaggedPDF );
+ aPDFExtOutDevData.SetIsExportTransitionEffects( mbUseTransitionEffects );
+ aPDFExtOutDevData.SetIsExportFormFields( mbExportFormFields );
+ aPDFExtOutDevData.SetIsExportBookmarks( mbExportBookmarks );
+ aPDFExtOutDevData.SetIsExportHiddenSlides( mbExportHiddenSlides );
+ aPDFExtOutDevData.SetIsSinglePageSheets( mbSinglePageSheets );
+ aPDFExtOutDevData.SetIsLosslessCompression( mbUseLosslessCompression );
+ aPDFExtOutDevData.SetCompressionQuality( mnQuality );
+ aPDFExtOutDevData.SetIsReduceImageResolution( mbReduceImageResolution );
+ aPDFExtOutDevData.SetIsExportNamedDestinations( mbExportBmkToDest );
+
+ Sequence< PropertyValue > aRenderOptions{
+ comphelper::makePropertyValue("RenderDevice", uno::Reference<awt::XDevice>(xDevice)),
+ comphelper::makePropertyValue("ExportNotesPages", false),
+ comphelper::makePropertyValue("IsFirstPage", true),
+ comphelper::makePropertyValue("IsLastPage", false),
+ comphelper::makePropertyValue("IsSkipEmptyPages", mbSkipEmptyPages),
+ comphelper::makePropertyValue("PageRange", aPageRange),
+ comphelper::makePropertyValue("ExportPlaceholders", mbExportPlaceholders),
+ comphelper::makePropertyValue("SinglePageSheets", mbSinglePageSheets)
+ };
+ Any& rExportNotesValue = aRenderOptions.getArray()[ 1 ].Value;
+
+ if( !aPageRange.isEmpty() || !aSelection.hasValue() )
+ {
+ aSelection = Any();
+ aSelection <<= mxSrcDoc;
+ }
+ bool bExportNotesPages = false;
+ bool bReChangeToNormalView = false;
+ static const OUStringLiteral sShowOnlineLayout( u"ShowOnlineLayout" );
+ bool bReHideWhitespace = false;
+ static const OUStringLiteral sHideWhitespace(u"HideWhitespace");
+ uno::Reference< beans::XPropertySet > xViewProperties;
+
+ if ( aCreator == "Writer" )
+ {
+ // #i92835: if Writer is in web layout mode this has to be switched to normal view and back to web view in the end
+ try
+ {
+ Reference< view::XViewSettingsSupplier > xVSettingsSupplier( xModel->getCurrentController(), uno::UNO_QUERY_THROW );
+ xViewProperties = xVSettingsSupplier->getViewSettings();
+ xViewProperties->getPropertyValue( sShowOnlineLayout ) >>= bReChangeToNormalView;
+ if( bReChangeToNormalView )
+ {
+ xViewProperties->setPropertyValue( sShowOnlineLayout, uno::Any( false ) );
+ }
+
+ // Also, disable hide-whitespace during export.
+ xViewProperties->getPropertyValue(sHideWhitespace) >>= bReHideWhitespace;
+ if (bReHideWhitespace)
+ {
+ xViewProperties->setPropertyValue(sHideWhitespace, uno::Any(false));
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ }
+
+ }
+
+ const sal_Int32 nPageCount = xRenderable->getRendererCount( aSelection, aRenderOptions );
+
+ if ( mbExportNotesPages && aCreator == "Impress" )
+ {
+ uno::Reference< drawing::XShapes > xShapes; // do not allow to export notes when exporting a selection
+ if ( ! ( aSelection >>= xShapes ) )
+ bExportNotesPages = true;
+ }
+ const bool bExportPages = !bExportNotesPages || !mbExportOnlyNotesPages;
+
+ if( aPageRange.isEmpty() || mbSinglePageSheets)
+ {
+ aPageRange = OUString::number( 1 ) + "-" + OUString::number(nPageCount );
+ }
+ StringRangeEnumerator aRangeEnum( aPageRange, 0, nPageCount-1 );
+
+ if ( mxStatusIndicator.is() )
+ {
+ std::locale loc(Translate::Create("flt"));
+ sal_Int32 nTotalPageCount = aRangeEnum.size();
+ if ( bExportPages && bExportNotesPages )
+ nTotalPageCount *= 2;
+ mxStatusIndicator->start(Translate::get(PDF_PROGRESS_BAR, loc), nTotalPageCount);
+ }
+
+ bRet = nPageCount > 0;
+
+ if ( bRet && bExportPages )
+ bRet = ExportSelection( aPDFWriter, xRenderable, aSelection, aRangeEnum, aRenderOptions, nPageCount );
+
+ if ( bRet && bExportNotesPages )
+ {
+ rExportNotesValue <<= true;
+ bRet = ExportSelection( aPDFWriter, xRenderable, aSelection, aRangeEnum, aRenderOptions, nPageCount );
+ }
+ if ( mxStatusIndicator.is() )
+ mxStatusIndicator->end();
+
+ // if during the export the doc locale was set copy it to PDF writer
+ const css::lang::Locale& rLoc( aPDFExtOutDevData.GetDocumentLocale() );
+ if( !rLoc.Language.isEmpty() )
+ aPDFWriter.SetDocumentLocale( rLoc );
+
+ if( bRet )
+ {
+ aPDFExtOutDevData.PlayGlobalActions( aPDFWriter );
+ bRet = aPDFWriter.Emit();
+ aErrors = aPDFWriter.GetErrors();
+ }
+ pOut->SetExtOutDevData( nullptr );
+ if( bReChangeToNormalView )
+ {
+ try
+ {
+ xViewProperties->setPropertyValue( sShowOnlineLayout, uno::Any( true ) );
+ }
+ catch( const uno::Exception& )
+ {
+ }
+ }
+ if( bReHideWhitespace )
+ {
+ try
+ {
+ xViewProperties->setPropertyValue( sHideWhitespace, uno::Any( true ) );
+ }
+ catch( const uno::Exception& )
+ {
+ }
+ }
+ }
+ }
+ }
+
+ // show eventual errors during export
+ showErrors( aErrors );
+
+ return bRet;
+}
+
+
+namespace
+{
+
+typedef cppu::WeakComponentImplHelper< task::XInteractionRequest > PDFErrorRequestBase;
+
+class PDFErrorRequest : private cppu::BaseMutex,
+ public PDFErrorRequestBase
+{
+ task::PDFExportException maExc;
+public:
+ explicit PDFErrorRequest( task::PDFExportException aExc );
+
+ // XInteractionRequest
+ virtual uno::Any SAL_CALL getRequest() override;
+ virtual uno::Sequence< uno::Reference< task::XInteractionContinuation > > SAL_CALL getContinuations() override;
+};
+
+
+PDFErrorRequest::PDFErrorRequest( task::PDFExportException aExc ) :
+ PDFErrorRequestBase( m_aMutex ),
+ maExc(std::move( aExc ))
+{
+}
+
+
+uno::Any SAL_CALL PDFErrorRequest::getRequest()
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ uno::Any aRet;
+ aRet <<= maExc;
+ return aRet;
+}
+
+
+uno::Sequence< uno::Reference< task::XInteractionContinuation > > SAL_CALL PDFErrorRequest::getContinuations()
+{
+ return uno::Sequence< uno::Reference< task::XInteractionContinuation > >();
+}
+
+} // end anonymous namespace
+
+
+void PDFExport::showErrors( const std::set< vcl::PDFWriter::ErrorCode >& rErrors )
+{
+ if( ! rErrors.empty() && mxIH.is() )
+ {
+ task::PDFExportException aExc;
+ aExc.ErrorCodes = comphelper::containerToSequence<sal_Int32>( rErrors );
+ Reference< task::XInteractionRequest > xReq( new PDFErrorRequest( std::move(aExc) ) );
+ mxIH->handle( xReq );
+ }
+}
+
+
+void PDFExport::ImplExportPage( vcl::PDFWriter& rWriter, vcl::PDFExtOutDevData& rPDFExtOutDevData, const GDIMetaFile& rMtf )
+{
+ //Rectangle(Point, Size) creates a rectangle off by 1, use Rectangle(long, long, long, long) instead
+ basegfx::B2DPolygon aSize(tools::Polygon(tools::Rectangle(0, 0, rMtf.GetPrefSize().Width(), rMtf.GetPrefSize().Height())).getB2DPolygon());
+ basegfx::B2DPolygon aSizePDF(OutputDevice::LogicToLogic(aSize, rMtf.GetPrefMapMode(), MapMode(MapUnit::MapPoint)));
+ basegfx::B2DRange aRangePDF(aSizePDF.getB2DRange());
+ tools::Rectangle aPageRect( Point(), rMtf.GetPrefSize() );
+
+ rWriter.NewPage( aRangePDF.getWidth(), aRangePDF.getHeight() );
+ rWriter.SetMapMode( rMtf.GetPrefMapMode() );
+
+ vcl::PDFWriter::PlayMetafileContext aCtx;
+ GDIMetaFile aMtf;
+ if( mbRemoveTransparencies )
+ {
+ aCtx.m_bTransparenciesWereRemoved = rWriter.GetReferenceDevice()->
+ RemoveTransparenciesFromMetaFile( rMtf, aMtf, mnMaxImageResolution, mnMaxImageResolution,
+ false, true, mbReduceImageResolution );
+ // tdf#134736 if the metafile was replaced then rPDFExtOutDevData's PageSyncData mActions
+ // all still point to MetaAction indexes in the original metafile that are now invalid.
+ // Throw them all away in the absence of a way to reposition them to new positions of
+ // their replacements.
+ if (aCtx.m_bTransparenciesWereRemoved)
+ rPDFExtOutDevData.ResetSyncData();
+ }
+ else
+ {
+ aMtf = rMtf;
+ }
+ aCtx.m_nMaxImageResolution = mbReduceImageResolution ? mnMaxImageResolution : 0;
+ aCtx.m_bOnlyLosslessCompression = mbUseLosslessCompression;
+ aCtx.m_nJPEGQuality = mnQuality;
+
+
+ rWriter.SetClipRegion( basegfx::B2DPolyPolygon(
+ basegfx::utils::createPolygonFromRect( vcl::unotools::b2DRectangleFromRectangle(aPageRect) ) ) );
+
+ rWriter.PlayMetafile( aMtf, aCtx, &rPDFExtOutDevData );
+
+ rPDFExtOutDevData.ResetSyncData();
+
+ if (!msWatermark.isEmpty())
+ {
+ ImplWriteWatermark( rWriter, Size(aRangePDF.getWidth(), aRangePDF.getHeight()) );
+ }
+ else if (!msTiledWatermark.isEmpty())
+ {
+ ImplWriteTiledWatermark( rWriter, Size(aRangePDF.getWidth(), aRangePDF.getHeight()) );
+ }
+}
+
+
+void PDFExport::ImplWriteWatermark( vcl::PDFWriter& rWriter, const Size& rPageSize )
+{
+ vcl::Font aFont( maWatermarkFontName, Size( 0, moWatermarkFontHeight ? *moWatermarkFontHeight : 3*rPageSize.Height()/4 ) );
+ aFont.SetItalic( ITALIC_NONE );
+ aFont.SetWidthType( WIDTH_NORMAL );
+ aFont.SetWeight( WEIGHT_NORMAL );
+ aFont.SetAlignment( ALIGN_BOTTOM );
+ tools::Long nTextWidth = rPageSize.Width();
+ if( rPageSize.Width() < rPageSize.Height() )
+ {
+ nTextWidth = rPageSize.Height();
+ aFont.SetOrientation( 2700_deg10 );
+ }
+
+ if (moWatermarkRotateAngle)
+ {
+ aFont.SetOrientation(*moWatermarkRotateAngle);
+ if (rPageSize.Width() < rPageSize.Height())
+ {
+ // Set text width based on the shorter side, so rotation can't push text outside the
+ // page boundaries.
+ nTextWidth = rPageSize.Width();
+ }
+ }
+
+ // adjust font height for text to fit
+ OutputDevice* pDev = rWriter.GetReferenceDevice();
+ pDev->Push();
+ pDev->SetFont( aFont );
+ pDev->SetMapMode( MapMode( MapUnit::MapPoint ) );
+ int w = 0;
+ if (moWatermarkFontHeight)
+ {
+ w = pDev->GetTextWidth(msWatermark);
+ }
+ else
+ {
+ while( ( w = pDev->GetTextWidth( msWatermark ) ) > nTextWidth )
+ {
+ if (w == 0)
+ break;
+ tools::Long nNewHeight = aFont.GetFontHeight() * nTextWidth / w;
+ if( nNewHeight == aFont.GetFontHeight() )
+ {
+ nNewHeight--;
+ if( nNewHeight <= 0 )
+ break;
+ }
+ aFont.SetFontHeight( nNewHeight );
+ pDev->SetFont( aFont );
+ }
+ }
+ tools::Long nTextHeight = pDev->GetTextHeight();
+ // leave some maneuvering room for rounding issues, also
+ // some fonts go a little outside ascent/descent
+ nTextHeight += nTextHeight/20;
+ pDev->Pop();
+
+ rWriter.Push();
+ rWriter.SetMapMode( MapMode( MapUnit::MapPoint ) );
+ rWriter.SetFont( aFont );
+ rWriter.SetTextColor(maWatermarkColor);
+ Point aTextPoint;
+ tools::Rectangle aTextRect;
+ if( rPageSize.Width() > rPageSize.Height() )
+ {
+ aTextPoint = Point( (rPageSize.Width()-w)/2,
+ rPageSize.Height()-(rPageSize.Height()-nTextHeight)/2 );
+ aTextRect = tools::Rectangle( Point( (rPageSize.Width()-w)/2,
+ (rPageSize.Height()-nTextHeight)/2 ),
+ Size( w, nTextHeight ) );
+ }
+ else
+ {
+ aTextPoint = Point( (rPageSize.Width()-nTextHeight)/2,
+ (rPageSize.Height()-w)/2 );
+ aTextRect = tools::Rectangle( aTextPoint, Size( nTextHeight, w ) );
+ }
+
+ if (moWatermarkRotateAngle)
+ {
+ // First set the text's starting point to the center of the page.
+ tools::Rectangle aPageRectangle(Point(0, 0), rPageSize);
+ aTextPoint = aPageRectangle.Center();
+ // Then adjust it so that the text remains centered, based on the rotation angle.
+ basegfx::B2DPolygon aTextPolygon
+ = basegfx::utils::createPolygonFromRect(basegfx::B2DRectangle(0, -nTextHeight, w, 0));
+ basegfx::B2DHomMatrix aMatrix;
+ aMatrix.rotate(-1 * toRadians(*moWatermarkRotateAngle));
+ aTextPolygon.transform(aMatrix);
+ basegfx::B2DPoint aPolygonCenter = aTextPolygon.getB2DRange().getCenter();
+ aTextPoint.AdjustX(-aPolygonCenter.getX());
+ aTextPoint.AdjustY(-aPolygonCenter.getY());
+
+ aTextRect = aPageRectangle;
+ }
+
+ rWriter.SetClipRegion();
+ rWriter.BeginTransparencyGroup();
+ rWriter.DrawText( aTextPoint, msWatermark );
+ rWriter.EndTransparencyGroup( aTextRect, 50 );
+ rWriter.Pop();
+}
+
+void PDFExport::ImplWriteTiledWatermark( vcl::PDFWriter& rWriter, const Size& rPageSize )
+{
+ OUString watermark = msTiledWatermark;
+ // Maximum number of characters in one line.
+ // it is set to 21 to make it look like tiled watermarks as online in secure view
+ const int lineLength = 21;
+ vcl::Font aFont( "Liberation Sans", Size( 0, 40 ) );
+ aFont.SetItalic( ITALIC_NONE );
+ aFont.SetWidthType( WIDTH_NORMAL );
+ aFont.SetWeight( WEIGHT_NORMAL );
+ aFont.SetAlignment( ALIGN_BOTTOM );
+ aFont.SetFontHeight(40);
+ aFont.SetOrientation(450_deg10);
+
+ OutputDevice* pDev = rWriter.GetReferenceDevice();
+ pDev->SetFont(aFont);
+ pDev->Push();
+ pDev->SetFont(aFont);
+ pDev->SetMapMode( MapMode( MapUnit::MapPoint ) );
+ int w = 0;
+ int watermarkcount = ((rPageSize.Width()) / 200)+1;
+ tools::Long nTextWidth = rPageSize.Width() / (watermarkcount*1.5);
+ OUString oneLineText = watermark;
+
+ if(watermark.getLength() > lineLength)
+ oneLineText = watermark.copy(0, lineLength);
+
+ while((w = pDev->GetTextWidth(oneLineText)) > nTextWidth)
+ {
+ if(w==0)
+ break;
+
+ tools::Long nNewHeight = aFont.GetFontHeight() * nTextWidth / w;
+ aFont.SetFontHeight(nNewHeight);
+ pDev->SetFont( aFont );
+ }
+ // maximum number of watermark count for the width
+ if(watermarkcount > 8)
+ watermarkcount = 8;
+
+ pDev->Pop();
+
+ rWriter.Push();
+ rWriter.SetMapMode( MapMode( MapUnit::MapPoint ) );
+ rWriter.SetFont(aFont);
+ rWriter.SetTextColor( Color(19,20,22) );
+ // center watermarks horizontally
+ Point aTextPoint( (rPageSize.Width()/2) - (((nTextWidth*watermarkcount)+(watermarkcount-1)*nTextWidth)/2),
+ pDev->GetTextHeight());
+
+ for( int i = 0; i < watermarkcount; i ++)
+ {
+ while(aTextPoint.getY()+pDev->GetTextHeight()*3 <= rPageSize.Height())
+ {
+ tools::Rectangle aTextRect(aTextPoint, Size(nTextWidth*2,pDev->GetTextHeight()*4));
+
+ pDev->Push();
+ rWriter.SetClipRegion();
+ rWriter.BeginTransparencyGroup();
+ rWriter.SetTextColor( Color(19,20,22) );
+ rWriter.DrawText(aTextRect, watermark, DrawTextFlags::MultiLine|DrawTextFlags::Center|DrawTextFlags::VCenter|DrawTextFlags::WordBreak|DrawTextFlags::Bottom);
+ rWriter.EndTransparencyGroup( aTextRect, 50 );
+ pDev->Pop();
+
+ pDev->Push();
+ rWriter.SetClipRegion();
+ rWriter.BeginTransparencyGroup();
+ rWriter.SetTextColor( Color(236,235,233) );
+ rWriter.DrawText(aTextRect, watermark, DrawTextFlags::MultiLine|DrawTextFlags::Center|DrawTextFlags::VCenter|DrawTextFlags::WordBreak|DrawTextFlags::Bottom);
+ rWriter.EndTransparencyGroup( aTextRect, 50 );
+ pDev->Pop();
+
+ aTextPoint.Move(0, pDev->GetTextHeight()*3);
+ }
+ aTextPoint=Point( aTextPoint.getX(), pDev->GetTextHeight() );
+ aTextPoint.Move( nTextWidth*1.5, 0 );
+ }
+
+ rWriter.Pop();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/pdf/pdfexport.hxx b/filter/source/pdf/pdfexport.hxx
new file mode 100644
index 000000000..dfd371c31
--- /dev/null
+++ b/filter/source/pdf/pdfexport.hxx
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <tools/multisel.hxx>
+#include <vcl/pdfwriter.hxx>
+#include <vcl/pdfextoutdevdata.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include <com/sun/star/task/XStatusIndicator.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/view/XRenderable.hpp>
+
+class GDIMetaFile;
+class Size;
+
+namespace vcl { class PDFWriter; }
+
+class PDFExport
+{
+private:
+
+ css::uno::Reference< css::lang::XComponent > mxSrcDoc;
+ css::uno::Reference< css::uno::XComponentContext > mxContext;
+ css::uno::Reference< css::task::XStatusIndicator > mxStatusIndicator;
+ css::uno::Reference< css::task::XInteractionHandler > mxIH;
+
+ bool mbUseTaggedPDF;
+ sal_Int32 mnPDFTypeSelection;
+ bool mbPDFUACompliance;
+ bool mbExportNotes;
+ bool mbExportPlaceholders;
+ bool mbUseReferenceXObject;
+ bool mbExportNotesPages;
+ bool mbExportOnlyNotesPages;
+ bool mbUseTransitionEffects;
+ bool mbExportBookmarks;
+ bool mbExportHiddenSlides;
+ bool mbSinglePageSheets;
+ sal_Int32 mnOpenBookmarkLevels;
+
+ bool mbUseLosslessCompression;
+ bool mbReduceImageResolution;
+ bool mbSkipEmptyPages;
+ bool mbAddStream;
+ sal_Int32 mnMaxImageResolution;
+ sal_Int32 mnQuality;
+ sal_Int32 mnFormsFormat;
+ bool mbExportFormFields;
+ bool mbAllowDuplicateFieldNames;
+ sal_Int32 mnProgressValue;
+ bool mbRemoveTransparencies;
+
+ bool mbIsRedactMode;
+
+ OUString msWatermark;
+ Color maWatermarkColor;
+ std::optional<sal_Int32> moWatermarkFontHeight;
+ OUString maWatermarkFontName;
+ std::optional<Degree10> moWatermarkRotateAngle;
+ OUString msTiledWatermark;
+
+ // these variable are here only to have a location in filter/pdf to set the default
+ // to be used by the macro (when the FilterData are set by the macro itself)
+ bool mbHideViewerToolbar;
+ bool mbHideViewerMenubar;
+ bool mbHideViewerWindowControls;
+ bool mbFitWindow;
+ bool mbCenterWindow;
+ bool mbOpenInFullScreenMode;
+ bool mbDisplayPDFDocumentTitle;
+ sal_Int32 mnPDFDocumentMode;
+ sal_Int32 mnPDFDocumentAction;
+ sal_Int32 mnZoom;
+ sal_Int32 mnInitialPage;
+ sal_Int32 mnPDFPageLayout;
+
+ bool mbEncrypt;
+ bool mbRestrictPermissions;
+ sal_Int32 mnPrintAllowed;
+ sal_Int32 mnChangesAllowed;
+ bool mbCanCopyOrExtract;
+ bool mbCanExtractForAccessibility;
+
+ // #i56629
+ bool mbExportRelativeFsysLinks;
+ sal_Int32 mnDefaultLinkAction;
+ bool mbConvertOOoTargetToPDFTarget;
+ bool mbExportBmkToDest;
+ void ImplExportPage( vcl::PDFWriter& rWriter, vcl::PDFExtOutDevData& rPDFExtOutDevData,
+ const GDIMetaFile& rMtf );
+
+ bool mbSignPDF;
+ OUString msSignLocation;
+ OUString msSignContact;
+ OUString msSignReason;
+ OUString msSignPassword;
+ css::uno::Reference< css::security::XCertificate > maSignCertificate;
+ OUString msSignTSA;
+
+ void ImplWriteWatermark( vcl::PDFWriter& rWriter, const Size& rPageSize );
+ void ImplWriteTiledWatermark( vcl::PDFWriter& rWriter, const Size& rPageSize );
+ css::uno::Reference<css::security::XCertificate> GetCertificateFromSubjectName(const std::u16string_view& rSubjectName) const;
+
+
+public:
+
+ PDFExport( const css::uno::Reference< css::lang::XComponent >& rxSrcDoc,
+ const css::uno::Reference< css::task::XStatusIndicator >& xStatusIndicator,
+ const css::uno::Reference< css::task::XInteractionHandler >& xIH,
+ const css::uno::Reference< css::uno::XComponentContext >& xFact );
+ ~PDFExport();
+
+ bool ExportSelection( vcl::PDFWriter& rPDFWriter,
+ css::uno::Reference< css::view::XRenderable > const & rRenderable,
+ const css::uno::Any& rSelection,
+ const StringRangeEnumerator& rRangeEnum,
+ css::uno::Sequence< css::beans::PropertyValue >& rRenderOptions,
+ sal_Int32 nPageCount );
+
+ bool Export( const OUString& rFile, const css::uno::Sequence< css::beans::PropertyValue >& rFilterData );
+
+ void showErrors( const std::set<vcl::PDFWriter::ErrorCode>& );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/pdf/pdffilter.component b/filter/source/pdf/pdffilter.component
new file mode 100644
index 000000000..5f3dc7879
--- /dev/null
+++ b/filter/source/pdf/pdffilter.component
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.PDF.PDFDialog"
+ constructor="filter_PDFDialog_get_implementation">
+ <service name="com.sun.star.document.PDFDialog"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.PDF.PDFFilter"
+ constructor="filter_PDFFilter_get_implementation">
+ <service name="com.sun.star.document.PDFFilter"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.PDF.PDFExportInteractionHandler"
+ constructor="filter_PDFExportInteractionHandler_get_implementation">
+ <service name="com.sun.star.filter.pdfexport.PDFExportInteractionHandler"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.PDF.PDFDecomposer"
+ constructor="filter_PdfDecomposer_get_implementation">
+ <service name="com.sun.star.graphic.PdfTools"/>
+ </implementation>
+</component>
diff --git a/filter/source/pdf/pdffilter.cxx b/filter/source/pdf/pdffilter.cxx
new file mode 100644
index 000000000..746a1dd9b
--- /dev/null
+++ b/filter/source/pdf/pdffilter.cxx
@@ -0,0 +1,295 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "pdffilter.hxx"
+#include "pdfexport.hxx"
+#include <cppuhelper/supportsservice.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <svl/outstrm.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <unotools/tempfile.hxx>
+#include <vcl/FilterConfigItem.hxx>
+#include <memory>
+
+#include <com/sun/star/io/XOutputStream.hpp>
+
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/sequence.hxx>
+
+#include <boost/property_tree/json_parser/error.hpp>
+
+using namespace ::com::sun::star::io;
+
+PDFFilter::PDFFilter( const Reference< XComponentContext > &rxContext ) :
+ mxContext( rxContext )
+{
+}
+
+
+PDFFilter::~PDFFilter()
+{
+}
+
+
+bool PDFFilter::implExport( const Sequence< PropertyValue >& rDescriptor )
+{
+ Reference< XOutputStream > xOStm;
+ Sequence< PropertyValue > aFilterData;
+ OUString aFilterOptions;
+ sal_Int32 nLength = rDescriptor.getLength();
+ const PropertyValue* pValue = rDescriptor.getConstArray();
+ bool bIsRedactMode = false;
+ bool bRet = false;
+ Reference< task::XStatusIndicator > xStatusIndicator;
+ Reference< task::XInteractionHandler > xIH;
+
+ for (sal_Int32 i = 0; i < nLength; ++i)
+ {
+ if ( pValue[ i ].Name == "OutputStream" )
+ pValue[ i ].Value >>= xOStm;
+ else if ( pValue[ i ].Name == "FilterData" )
+ pValue[ i ].Value >>= aFilterData;
+ else if ( pValue[ i ].Name == "FilterOptions" )
+ pValue[ i ].Value >>= aFilterOptions;
+ else if ( pValue[ i ].Name == "StatusIndicator" )
+ pValue[ i ].Value >>= xStatusIndicator;
+ else if ( pValue[i].Name == "InteractionHandler" )
+ pValue[i].Value >>= xIH;
+ }
+
+ for (sal_Int32 i = 0 ; i < nLength; ++i)
+ {
+ if ( pValue[i].Name == "IsRedactMode")
+ pValue[i].Value >>= bIsRedactMode;
+ }
+
+ if (!aFilterData.hasElements() && aFilterOptions.startsWith("{"))
+ {
+ try
+ {
+ // Allow setting filter data keys from the cmdline.
+ std::vector<PropertyValue> aData
+ = comphelper::JsonToPropertyValues(aFilterOptions.toUtf8());
+ aFilterData = comphelper::containerToSequence(aData);
+ }
+ catch (const boost::property_tree::json_parser::json_parser_error& e)
+ {
+ // This wasn't a valid json; maybe came from import filter (tdf#150846)
+ SAL_WARN("filter.pdf", "error parsing FilterOptions: " << e.message());
+ }
+ }
+
+ /* we don't get FilterData if we are exporting directly
+ to pdf, but we have to use the last user settings (especially for the CompressMode) */
+ if ( !aFilterData.hasElements() )
+ {
+ FilterConfigItem aCfgItem( u"Office.Common/Filter/PDF/Export/" );
+ aCfgItem.ReadBool( "UseLosslessCompression", false );
+ aCfgItem.ReadInt32( "Quality", 90 );
+ aCfgItem.ReadBool( "ReduceImageResolution", false );
+ aCfgItem.ReadInt32( "MaxImageResolution", 300 );
+ aCfgItem.ReadBool( "UseTaggedPDF", false );
+ aCfgItem.ReadInt32( "SelectPdfVersion", 0 );
+ aCfgItem.ReadBool("PDFUACompliance", false);
+ aCfgItem.ReadBool( "ExportNotes", false );
+ aCfgItem.ReadBool( "ExportPlaceholders", false );
+ aCfgItem.ReadBool( "ExportNotesPages", false );
+ aCfgItem.ReadBool( "ExportOnlyNotesPages", false );
+ aCfgItem.ReadBool( "UseTransitionEffects", true );
+ aCfgItem.ReadBool( "IsSkipEmptyPages", false );
+ aCfgItem.ReadBool( "ExportFormFields", true );
+ aCfgItem.ReadInt32( "FormsType", 0 );
+ aCfgItem.ReadBool( "HideViewerToolbar", false );
+ aCfgItem.ReadBool( "HideViewerMenubar", false );
+ aCfgItem.ReadBool( "HideViewerWindowControls", false );
+ aCfgItem.ReadBool( "ResizeWindowToInitialPage", false );
+ aCfgItem.ReadBool( "CenterWindow", false );
+ aCfgItem.ReadBool( "OpenInFullScreenMode", false );
+ aCfgItem.ReadBool( "DisplayPDFDocumentTitle", true );
+ aCfgItem.ReadInt32( "InitialView", 0 );
+ aCfgItem.ReadInt32( "Magnification", 0 );
+ aCfgItem.ReadInt32( "Zoom", 100 );
+ aCfgItem.ReadInt32( "PageLayout", 0 );
+ aCfgItem.ReadBool( "FirstPageOnLeft", false );
+ aCfgItem.ReadInt32( "InitialPage", 1 );
+ aCfgItem.ReadBool( "IsAddStream", false );
+
+ // the encryption is not available when exporting directly, since the encryption is off by default and the selection
+ // (encrypt or not) is not persistent; it's available through macro though,
+ // provided the correct property values are set, see help
+
+ // now, the relative link stuff
+ aCfgItem.ReadBool( "ExportLinksRelativeFsys", false );
+ aCfgItem.ReadInt32("PDFViewSelection", 0 );
+ aCfgItem.ReadBool( "ConvertOOoTargetToPDFTarget", false );
+ aCfgItem.ReadBool( "ExportBookmarksToPDFDestination", false );
+
+ aCfgItem.ReadBool( "ExportBookmarks", true );
+ aCfgItem.ReadBool( "ExportHiddenSlides", false );
+ aCfgItem.ReadBool( "SinglePageSheets", false );
+ aCfgItem.ReadInt32( "OpenBookmarkLevels", -1 );
+
+ aCfgItem.ReadBool( "IsRedactMode", false);
+
+ aFilterData = aCfgItem.GetFilterData();
+ }
+
+
+ if (bIsRedactMode)
+ {
+ bool bFound = false;
+
+ for (PropertyValue& rProp : asNonConstRange(aFilterData))
+ {
+ if (rProp.Name == "IsRedactMode")
+ {
+ rProp.Value <<= bIsRedactMode;
+ bFound = true;
+ break;
+ }
+ }
+
+ if (!bFound)
+ {
+ sal_Int32 nNewSize = aFilterData.getLength() + 1;
+ aFilterData.realloc( nNewSize );
+ auto pFilterData = aFilterData.getArray();
+ pFilterData[nNewSize - 1].Name = "IsRedactMode";
+ pFilterData[nNewSize - 1].Value <<= bIsRedactMode;
+ }
+ }
+
+ if( mxSrcDoc.is() && xOStm.is() )
+ {
+ PDFExport aExport( mxSrcDoc, xStatusIndicator, xIH, mxContext );
+ ::utl::TempFile aTempFile;
+
+ aTempFile.EnableKillingFile();
+ bRet = aExport.Export( aTempFile.GetURL(), aFilterData );
+
+ if( bRet )
+ {
+ std::unique_ptr<SvStream> pIStm(::utl::UcbStreamHelper::CreateStream( aTempFile.GetURL(), StreamMode::READ ));
+
+ if( pIStm )
+ {
+ SvOutputStream aOStm( xOStm );
+
+ aOStm.WriteStream( *pIStm );
+ bRet = ( aOStm.Tell() && ( aOStm.GetError() == ERRCODE_NONE ) );
+ }
+ }
+ }
+
+ return bRet;
+}
+
+namespace {
+
+class FocusWindowWaitCursor
+{
+private:
+
+ VclPtr<vcl::Window> m_pFocusWindow;
+
+public:
+ FocusWindowWaitCursor() :
+ m_pFocusWindow( Application::GetFocusWindow() )
+ {
+ if( m_pFocusWindow )
+ {
+ m_pFocusWindow->AddEventListener( LINK( this, FocusWindowWaitCursor, DestroyedLink ) );
+ m_pFocusWindow->EnterWait();
+ }
+ }
+
+ ~FocusWindowWaitCursor()
+ {
+ if( m_pFocusWindow )
+ {
+ m_pFocusWindow->LeaveWait();
+ m_pFocusWindow->RemoveEventListener( LINK( this, FocusWindowWaitCursor, DestroyedLink ) );
+ }
+ }
+
+ DECL_LINK( DestroyedLink, VclWindowEvent&, void );
+};
+
+}
+
+IMPL_LINK( FocusWindowWaitCursor, DestroyedLink, VclWindowEvent&, rEvent, void )
+{
+ if( rEvent.GetId() == VclEventId::ObjectDying )
+ m_pFocusWindow = nullptr;
+}
+
+
+sal_Bool SAL_CALL PDFFilter::filter( const Sequence< PropertyValue >& rDescriptor )
+{
+ FocusWindowWaitCursor aCur;
+
+ const bool bRet = implExport( rDescriptor );
+
+ return bRet;
+}
+
+
+void SAL_CALL PDFFilter::cancel( )
+{
+}
+
+
+void SAL_CALL PDFFilter::setSourceDocument( const Reference< XComponent >& xDoc )
+{
+ mxSrcDoc = xDoc;
+}
+
+
+void SAL_CALL PDFFilter::initialize( const css::uno::Sequence< css::uno::Any >& )
+{
+}
+
+
+OUString SAL_CALL PDFFilter::getImplementationName()
+{
+ return "com.sun.star.comp.PDF.PDFFilter";
+}
+
+
+sal_Bool SAL_CALL PDFFilter::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService( this, rServiceName );
+}
+
+
+css::uno::Sequence< OUString > SAL_CALL PDFFilter::getSupportedServiceNames( )
+{
+ return { "com.sun.star.document.PDFFilter" };
+}
+
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_PDFFilter_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new PDFFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/pdf/pdffilter.hxx b/filter/source/pdf/pdffilter.hxx
new file mode 100644
index 000000000..28869272c
--- /dev/null
+++ b/filter/source/pdf/pdffilter.hxx
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::document;
+
+
+class PDFFilter : public cppu::WeakImplHelper < XFilter, XExporter, XInitialization, XServiceInfo >
+{
+private:
+
+ Reference< XComponentContext > mxContext;
+ Reference< XComponent > mxSrcDoc;
+
+ bool implExport( const Sequence< PropertyValue >& rDescriptor );
+
+protected:
+
+ // XFilter
+ virtual sal_Bool SAL_CALL filter( const Sequence< PropertyValue >& rDescriptor ) override;
+ virtual void SAL_CALL cancel( ) override;
+
+ // XExporter
+ virtual void SAL_CALL setSourceDocument( const Reference< XComponent >& xDoc ) override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+public:
+
+ explicit PDFFilter( const Reference< XComponentContext >& rxContext );
+ virtual ~PDFFilter() override;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/pdf/pdfinteract.cxx b/filter/source/pdf/pdfinteract.cxx
new file mode 100644
index 000000000..cf38cf4a0
--- /dev/null
+++ b/filter/source/pdf/pdfinteract.cxx
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "pdfinteract.hxx"
+#include "impdialog.hxx"
+
+#include <com/sun/star/task/XInteractionRequest.hpp>
+#include <com/sun/star/task/PDFExportException.hpp>
+#include <comphelper/namedvaluecollection.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <vcl/svapp.hxx>
+
+PDFInteractionHandler::PDFInteractionHandler()
+{
+}
+
+PDFInteractionHandler::~PDFInteractionHandler()
+{
+}
+
+void SAL_CALL PDFInteractionHandler::handle( const Reference< task::XInteractionRequest >& i_xRequest )
+{
+ handleInteractionRequest( i_xRequest );
+}
+
+void SAL_CALL PDFInteractionHandler::initialize(const css::uno::Sequence<css::uno::Any>& rArguments)
+{
+ comphelper::NamedValueCollection aProperties(rArguments);
+ if (aProperties.has("Parent"))
+ aProperties.get("Parent") >>= m_xParent;
+}
+
+sal_Bool SAL_CALL PDFInteractionHandler::handleInteractionRequest( const Reference< task::XInteractionRequest >& i_xRequest )
+{
+ bool bHandled = false;
+
+ Any aRequest( i_xRequest->getRequest() );
+ task::PDFExportException aExc;
+ if( aRequest >>= aExc )
+ {
+ std::set< vcl::PDFWriter::ErrorCode > aCodes;
+ sal_Int32 nCodes = aExc.ErrorCodes.getLength();
+ for( sal_Int32 i = 0; i < nCodes; i++ )
+ aCodes.insert( static_cast<vcl::PDFWriter::ErrorCode>(aExc.ErrorCodes.getConstArray()[i]) );
+
+ ImplErrorDialog aDlg(Application::GetFrameWeld(m_xParent), aCodes);
+ aDlg.run();
+ bHandled = true;
+ }
+ return bHandled;
+}
+
+
+
+OUString SAL_CALL PDFInteractionHandler::getImplementationName()
+{
+ return "com.sun.star.comp.PDF.PDFExportInteractionHandler";
+}
+
+
+sal_Bool SAL_CALL PDFInteractionHandler::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService( this, rServiceName );
+}
+
+
+css::uno::Sequence< OUString > SAL_CALL PDFInteractionHandler::getSupportedServiceNames( )
+{
+ return { "com.sun.star.filter.pdfexport.PDFExportInteractionHandler" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_PDFExportInteractionHandler_get_implementation(
+ css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new PDFInteractionHandler());
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/pdf/pdfinteract.hxx b/filter/source/pdf/pdfinteract.hxx
new file mode 100644
index 000000000..0af5c260b
--- /dev/null
+++ b/filter/source/pdf/pdfinteract.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/task/XInteractionHandler2.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+
+
+class PDFInteractionHandler : public cppu::WeakImplHelper<css::lang::XInitialization,
+ css::task::XInteractionHandler2,
+ XServiceInfo>
+{
+private:
+ css::uno::Reference<css::awt::XWindow> m_xParent;
+protected:
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& rArguments) override;
+
+ // XInteractionHandler
+ virtual void SAL_CALL handle( const Reference< task::XInteractionRequest >& ) override;
+
+ // XInteractionHandler2
+ virtual sal_Bool SAL_CALL handleInteractionRequest( const Reference< task::XInteractionRequest >& ) override;
+
+public:
+
+ PDFInteractionHandler();
+ virtual ~PDFInteractionHandler() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */