Add API for creating signature field without signing immediately
Currently Poppler allows to create a signature and sign it in one step
as well as singing an unsinged field. However there is no way to
create an unsigned field and sign it later.
This adds a SignatureAnnotation class that can be added like any
annotation and signed later
diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc
index 1cbcb7f..6970355 100644
--- a/poppler/PDFDoc.cc
+++ b/poppler/PDFDoc.cc
@@ -56,6 +56,7 @@
// Copyright (C) 2022 Erich E. Hoover <erich.e.hoover@gmail.com>
// Copyright (C) 2023, 2024 g10 Code GmbH, Author: Sune Stolborg Vuorela <sune@vuorela.dk>
// Copyright (C) 2024 Vincent Lefevre <vincent@vinc17.net>
+// Copyright (C) 2024 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by Technische Universität Dresden
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -2185,26 +2186,26 @@
return jsInfo.containsJS();
}
-bool PDFDoc::sign(const std::string &saveFilename, const std::string &certNickname, const std::string &password, GooString *partialFieldName, int page, const PDFRectangle &rect, const GooString &signatureText,
- const GooString &signatureTextLeft, double fontSize, double leftFontSize, std::unique_ptr<AnnotColor> &&fontColor, double borderWidth, std::unique_ptr<AnnotColor> &&borderColor,
- std::unique_ptr<AnnotColor> &&backgroundColor, const GooString *reason, const GooString *location, const std::string &imagePath, const std::optional<GooString> &ownerPassword, const std::optional<GooString> &userPassword)
+std::optional<PDFDoc::SignatureData> PDFDoc::createSignature(::Page *destPage, GooString *partialFieldName, const PDFRectangle &rect, const GooString &signatureText, const GooString &signatureTextLeft, double fontSize, double leftFontSize,
+ std::unique_ptr<AnnotColor> &&fontColor, double borderWidth, std::unique_ptr<AnnotColor> &&borderColor, std::unique_ptr<AnnotColor> &&backgroundColor,
+ const std::string &imagePath)
{
- ::Page *destPage = getPage(page);
if (destPage == nullptr) {
- return false;
+ return std::nullopt;
}
+
Ref imageResourceRef = Ref::INVALID();
if (!imagePath.empty()) {
imageResourceRef = ImageEmbeddingUtils::embed(xref, imagePath);
if (imageResourceRef == Ref::INVALID()) {
- return false;
+ return std::nullopt;
}
}
Form *form = catalog->getCreateForm();
const std::string pdfFontName = form->findPdfFontNameToUseForSigning();
if (pdfFontName.empty()) {
- return false;
+ return std::nullopt;
}
const DefaultAppearance da { { objName, pdfFontName.c_str() }, fontSize, std::move(fontColor) };
@@ -2226,8 +2227,6 @@
const Ref ref = getXRef()->addIndirectObject(annotObj);
catalog->addFormToAcroForm(ref);
- // say that there a now signatures and that we should append only
- catalog->getAcroForm()->dictSet("SigFlags", Object(3));
catalog->setAcroFormModified();
form->ensureFontsForAllCharacters(&signatureText, pdfFontName);
@@ -2241,7 +2240,7 @@
Object refObj(ref);
AnnotWidget *signatureAnnot = new AnnotWidget(this, field->getObj(), &refObj, field.get());
- signatureAnnot->setFlags(signatureAnnot->getFlags() | Annot::flagPrint | Annot::flagLocked | Annot::flagNoRotate);
+ signatureAnnot->setFlags(signatureAnnot->getFlags() | Annot::flagPrint | /*Annot::flagLocked | TODO */ Annot::flagNoRotate);
Dict dummy(getXRef());
auto appearCharacs = std::make_unique<AnnotAppearanceCharacs>(&dummy);
appearCharacs->setBorderColor(std::move(borderColor));
@@ -2254,25 +2253,49 @@
FormWidget *formWidget = field->getWidget(field->getNumWidgets() - 1);
formWidget->setWidgetAnnotation(signatureAnnot);
- destPage->addAnnot(signatureAnnot);
-
std::unique_ptr<AnnotBorder> border(new AnnotBorderArray());
border->setWidth(borderWidth);
signatureAnnot->setBorder(std::move(border));
- FormWidgetSignature *fws = dynamic_cast<FormWidgetSignature *>(formWidget);
+ return SignatureData { { ref.num, ref.gen }, signatureAnnot, formWidget, std::move(field) };
+}
+
+bool PDFDoc::sign(const std::string &saveFilename, const std::string &certNickname, const std::string &password, GooString *partialFieldName, int page, const PDFRectangle &rect, const GooString &signatureText,
+ const GooString &signatureTextLeft, double fontSize, double leftFontSize, std::unique_ptr<AnnotColor> &&fontColor, double borderWidth, std::unique_ptr<AnnotColor> &&borderColor,
+ std::unique_ptr<AnnotColor> &&backgroundColor, const GooString *reason, const GooString *location, const std::string &imagePath, const std::optional<GooString> &ownerPassword, const std::optional<GooString> &userPassword)
+{
+ ::Page *destPage = getPage(page);
+ if (destPage == nullptr) {
+ return false;
+ }
+
+ std::optional<SignatureData> sig =
+ createSignature(destPage, partialFieldName, rect, signatureText, signatureTextLeft, fontSize, leftFontSize, std::move(fontColor), borderWidth, std::move(borderColor), std::move(backgroundColor), imagePath);
+
+ if (!sig) {
+ return false;
+ }
+
+ sig->annotWidget->setFlags(sig->annotWidget->getFlags() | Annot::flagLocked);
+
+ // say that there a now signatures and that we should append only
+ catalog->getAcroForm()->dictSet("SigFlags", Object(3));
+
+ destPage->addAnnot(sig->annotWidget);
+
+ FormWidgetSignature *fws = dynamic_cast<FormWidgetSignature *>(sig->formWidget);
if (fws) {
const bool res = fws->signDocument(saveFilename, certNickname, password, reason, location, ownerPassword, userPassword);
// Now remove the signature stuff in case the user wants to continue editing stuff
// So the document object is clean
- const Object &vRefObj = field->getObj()->dictLookupNF("V");
+ const Object &vRefObj = sig->field->getObj()->dictLookupNF("V");
if (vRefObj.isRef()) {
getXRef()->removeIndirectObject(vRefObj.getRef());
}
- destPage->removeAnnot(signatureAnnot);
- catalog->removeFormFromAcroForm(ref);
- getXRef()->removeIndirectObject(ref);
+ destPage->removeAnnot(sig->annotWidget);
+ catalog->removeFormFromAcroForm(sig->ref);
+ getXRef()->removeIndirectObject(sig->ref);
return res;
}
diff --git a/poppler/PDFDoc.h b/poppler/PDFDoc.h
index 61aae61..a27b25f 100644
--- a/poppler/PDFDoc.h
+++ b/poppler/PDFDoc.h
@@ -40,6 +40,7 @@
// Copyright (C) 2022 Felix Jung <fxjung@posteo.de>
// Copyright (C) 2022 crt <chluo@cse.cuhk.edu.hk>
// Copyright 2023 g10 Code GmbH, Author: Sune Stolborg Vuorela <sune@vuorela.dk>
+// Copyright (C) 2024 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by Technische Universität Dresden
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -343,6 +344,17 @@
const GooString &signatureTextLeft, double fontSize, double leftFontSize, std::unique_ptr<AnnotColor> &&fontColor, double borderWidth, std::unique_ptr<AnnotColor> &&borderColor, std::unique_ptr<AnnotColor> &&backgroundColor,
const GooString *reason = nullptr, const GooString *location = nullptr, const std::string &imagePath = "", const std::optional<GooString> &ownerPassword = {}, const std::optional<GooString> &userPassword = {});
+ struct SignatureData
+ {
+ Ref ref;
+ AnnotWidget *annotWidget = nullptr;
+ FormWidget *formWidget = nullptr;
+ std::unique_ptr<::FormFieldSignature> field = nullptr;
+ };
+
+ std::optional<SignatureData> createSignature(::Page *destPage, GooString *partialFieldName, const PDFRectangle &rect, const GooString &signatureText, const GooString &signatureTextLeft, double fontSize, double leftFontSize,
+ std::unique_ptr<AnnotColor> &&fontColor, double borderWidth, std::unique_ptr<AnnotColor> &&borderColor, std::unique_ptr<AnnotColor> &&backgroundColor, const std::string &imagePath);
+
private:
// insert referenced objects in XRef
bool markDictionary(Dict *dict, XRef *xRef, XRef *countRef, unsigned int numOffset, int oldRefNum, int newRefNum, std::set<Dict *> *alreadyMarkedDicts);
diff --git a/qt6/src/CMakeLists.txt b/qt6/src/CMakeLists.txt
index 40c43e5..8b3484b 100644
--- a/qt6/src/CMakeLists.txt
+++ b/qt6/src/CMakeLists.txt
@@ -61,6 +61,7 @@
poppler-optcontent.h
poppler-page-transition.h
poppler-media.h
+ poppler-converter.h
${CMAKE_CURRENT_BINARY_DIR}/poppler-export.h
${CMAKE_CURRENT_BINARY_DIR}/poppler-version.h
DESTINATION include/poppler/qt6)
diff --git a/qt6/src/poppler-annotation.cc b/qt6/src/poppler-annotation.cc
index 1a3c813..39a5a4f 100644
--- a/qt6/src/poppler-annotation.cc
+++ b/qt6/src/poppler-annotation.cc
@@ -13,7 +13,7 @@
* Copyright (C) 2020-2022 Oliver Sander <oliver.sander@tu-dresden.de>
* Copyright (C) 2020 Katarina Behrens <Katarina.Behrens@cib.de>
* Copyright (C) 2020 Thorsten Behrens <Thorsten.Behrens@CIB.de>
- * Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by Technische Universität Dresden
+ * Copyright (C) 2020, 2024 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by Technische Universität Dresden
* Copyright (C) 2021 Mahmoud Ahmed Khalil <mahmoudkhalil11@gmail.com>
* Adapting code from
* Copyright (C) 2004 by Enrico Ros <eros.kde@email.it>
@@ -47,6 +47,7 @@
#include "poppler-annotation-private.h"
#include "poppler-page-private.h"
#include "poppler-private.h"
+#include "poppler-form.h"
// poppler includes
#include <Page.h>
@@ -2906,6 +2907,206 @@
stampann->setCustomImage(annotCustomImage);
}
+/** SignatureAnnotation [Annotation] */
+class SignatureAnnotationPrivate : public AnnotationPrivate
+{
+public:
+ SignatureAnnotationPrivate();
+ Annotation *makeAlias() override;
+ Annot *createNativeAnnot(::Page *destPage, DocumentData *doc) override;
+
+ // data fields
+ QString text;
+ QString leftText;
+ double fontSize = 10.0;
+ double leftFontSize = 20.0;
+ QColor fontColor = Qt::red;
+ QColor borderColor = Qt::red;
+ double borderWidth = 1.5;
+ QColor backgroundColor = QColor(240, 240, 240);
+ QString imagePath;
+ QString fieldPartialName;
+ std::unique_ptr<::FormFieldSignature> field = nullptr;
+};
+
+SignatureAnnotationPrivate::SignatureAnnotationPrivate() : AnnotationPrivate() { }
+
+Annotation *SignatureAnnotationPrivate::makeAlias()
+{
+ return new SignatureAnnotation(*this);
+}
+
+Annot *SignatureAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
+{
+ SignatureAnnotation *q = static_cast<SignatureAnnotation *>(makeAlias());
+
+ // Set page and document
+ pdfPage = destPage;
+ parentDoc = doc;
+
+ // Set pdfAnnot
+ PDFRectangle rect = boundaryToPdfRectangle(boundary, flags);
+
+ GooString signatureText(text.toStdString());
+ GooString signatureTextLeft(leftText.toStdString());
+
+ std::optional<PDFDoc::SignatureData> sig = destPage->getDoc()->createSignature(destPage, QStringToGooString(fieldPartialName), rect, signatureText, signatureTextLeft, fontSize, leftFontSize, convertQColor(fontColor), borderWidth,
+ convertQColor(borderColor), convertQColor(backgroundColor), imagePath.toStdString());
+
+ if (!sig) {
+ return nullptr;
+ }
+
+ sig->formWidget->updateWidgetAppearance();
+ field = std::move(sig->field);
+
+ // Set properties
+ flushBaseAnnotationProperties();
+
+ pdfAnnot = sig->annotWidget;
+
+ delete q;
+
+ return pdfAnnot;
+}
+
+SignatureAnnotation::SignatureAnnotation() : Annotation(*new SignatureAnnotationPrivate()) { }
+
+SignatureAnnotation::SignatureAnnotation(SignatureAnnotationPrivate &dd) : Annotation(dd) { }
+
+SignatureAnnotation::~SignatureAnnotation() { }
+
+Annotation::SubType SignatureAnnotation::subType() const
+{
+ return AWidget;
+}
+
+void SignatureAnnotation::setText(const QString &text)
+{
+ Q_D(SignatureAnnotation);
+ d->text = text;
+}
+
+void SignatureAnnotation::setLeftText(const QString &text)
+{
+ Q_D(SignatureAnnotation);
+ d->leftText = text;
+}
+
+double SignatureAnnotation::fontSize() const
+{
+ Q_D(const SignatureAnnotation);
+ return d->fontSize;
+}
+
+void SignatureAnnotation::setFontSize(double fontSize)
+{
+ Q_D(SignatureAnnotation);
+ d->fontSize = fontSize;
+}
+
+double SignatureAnnotation::leftFontSize() const
+{
+ Q_D(const SignatureAnnotation);
+ return d->leftFontSize;
+}
+
+void SignatureAnnotation::setLeftFontSize(double fontSize)
+{
+ Q_D(SignatureAnnotation);
+ d->leftFontSize = fontSize;
+}
+
+QColor SignatureAnnotation::fontColor() const
+{
+ Q_D(const SignatureAnnotation);
+ return d->fontColor;
+}
+
+void SignatureAnnotation::setFontColor(const QColor &color)
+{
+ Q_D(SignatureAnnotation);
+ d->fontColor = color;
+}
+
+QColor SignatureAnnotation::borderColor() const
+{
+ Q_D(const SignatureAnnotation);
+ return d->borderColor;
+}
+
+void SignatureAnnotation::setBorderColor(const QColor &color)
+{
+ Q_D(SignatureAnnotation);
+ d->borderColor = color;
+}
+
+QColor SignatureAnnotation::backgroundColor() const
+{
+ Q_D(const SignatureAnnotation);
+ return d->backgroundColor;
+}
+
+double SignatureAnnotation::borderWidth() const
+{
+ Q_D(const SignatureAnnotation);
+ return d->borderWidth;
+}
+
+void SignatureAnnotation::setBorderWidth(double width)
+{
+ Q_D(SignatureAnnotation);
+ d->borderWidth = width;
+}
+
+void SignatureAnnotation::setBackgroundColor(const QColor &color)
+{
+ Q_D(SignatureAnnotation);
+ d->backgroundColor = color;
+}
+
+QString SignatureAnnotation::imagePath() const
+{
+ Q_D(const SignatureAnnotation);
+ return d->imagePath;
+}
+
+void SignatureAnnotation::setImagePath(const QString &imagePath)
+{
+ Q_D(SignatureAnnotation);
+ d->imagePath = imagePath;
+}
+
+QString SignatureAnnotation::fieldPartialName() const
+{
+ Q_D(const SignatureAnnotation);
+ return d->fieldPartialName;
+}
+
+void SignatureAnnotation::setFieldPartialName(const QString &fieldPartialName)
+{
+ Q_D(SignatureAnnotation);
+ d->fieldPartialName = fieldPartialName;
+}
+
+SignatureAnnotation::SigningResult SignatureAnnotation::sign(const QString &outputFileName, const PDFConverter::NewSignatureData &data)
+{
+ Q_D(SignatureAnnotation);
+ auto formField = std::make_unique<FormFieldSignature>(d->parentDoc, d->pdfPage, static_cast<::FormWidgetSignature *>(d->field->getCreateWidget()));
+
+ const auto result = formField->sign(outputFileName, data);
+
+ switch (result) {
+ case FormFieldSignature::SigningSuccess:
+ return SigningSuccess;
+ case FormFieldSignature::FieldAlreadySigned:
+ return FieldAlreadySigned;
+ case FormFieldSignature::GenericSigningError:
+ return GenericSigningError;
+ }
+ return GenericSigningError;
+}
+
/** InkAnnotation [Annotation] */
class InkAnnotationPrivate : public AnnotationPrivate
{
diff --git a/qt6/src/poppler-annotation.h b/qt6/src/poppler-annotation.h
index 16f2eda..6f93f44 100644
--- a/qt6/src/poppler-annotation.h
+++ b/qt6/src/poppler-annotation.h
@@ -9,7 +9,7 @@
* Copyright (C) 2013, Anthony Granger <grangeranthony@gmail.com>
* Copyright (C) 2018, Dileep Sankhla <sankhla.dileep96@gmail.com>
* Copyright (C) 2020, Katarina Behrens <Katarina.Behrens@cib.de>
- * Copyright (C) 2020, Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by Technische Universität Dresden
+ * Copyright (C) 2020, 2024, Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by Technische Universität Dresden
* Copyright (C) 2021, Oliver Sander <oliver.sander@tu-dresden.de>
* Copyright (C) 2021, Mahmoud Ahmed Khalil <mahmoudkhalil11@gmail.com>
* Adapting code from
@@ -43,6 +43,7 @@
#include <QtGui/QColor>
#include <QtGui/QFont>
#include "poppler-export.h"
+#include "poppler-converter.h"
#include <memory>
@@ -56,6 +57,7 @@
class GeomAnnotationPrivate;
class HighlightAnnotationPrivate;
class StampAnnotationPrivate;
+class SignatureAnnotationPrivate;
class InkAnnotationPrivate;
class LinkAnnotationPrivate;
class CaretAnnotationPrivate;
@@ -772,6 +774,90 @@
};
/**
+ * \short Signature annotation.
+ *
+ * A signature annotation. By creating one and adding it to the page you can create
+ * an unsigned signature field.
+ *
+ * To read existing signature fields use FormFieldSignature.
+ *
+ * \since 24.10
+ */
+class POPPLER_QT6_EXPORT SignatureAnnotation : public Annotation
+{
+ friend class AnnotationPrivate;
+
+public:
+ /**
+ * \since 24.10
+ */
+ enum SigningResult
+ {
+ SigningSuccess,
+ FieldAlreadySigned, ///< Trying to sign a field that is already signed
+ GenericSigningError,
+ };
+
+ SignatureAnnotation();
+ ~SignatureAnnotation() override;
+ SubType subType() const override;
+
+ void setText(const QString &text);
+ void setLeftText(const QString &text);
+
+ /**
+ * Default: 10
+ */
+ double fontSize() const;
+ void setFontSize(double fontSize);
+
+ /**
+ * Default: 20
+ */
+ double leftFontSize() const;
+ void setLeftFontSize(double fontSize);
+
+ /**
+ * Default: red
+ */
+ QColor fontColor() const;
+ void setFontColor(const QColor &color);
+
+ /**
+ * Default: red
+ */
+ QColor borderColor() const;
+ void setBorderColor(const QColor &color);
+
+ /**
+ * border width in points
+ *
+ * Default: 1.5
+ */
+ double borderWidth() const;
+ void setBorderWidth(double width);
+
+ /**
+ * Default: QColor(240, 240, 240)
+ */
+ QColor backgroundColor() const;
+ void setBackgroundColor(const QColor &color);
+
+ QString imagePath() const;
+ void setImagePath(const QString &imagePath);
+
+ QString fieldPartialName() const;
+ void setFieldPartialName(const QString &fieldPartialName);
+
+ [[nodiscard]] SigningResult sign(const QString &outputFileName, const PDFConverter::NewSignatureData &data);
+
+private:
+ explicit SignatureAnnotation(SignatureAnnotationPrivate &dd);
+ Q_DECLARE_PRIVATE(SignatureAnnotation)
+ Q_DISABLE_COPY(SignatureAnnotation)
+};
+
+/**
* \short Ink Annotation.
*
* Annotation representing an ink path on a page.
diff --git a/qt6/src/poppler-converter.h b/qt6/src/poppler-converter.h
new file mode 100644
index 0000000..e7394cd
--- /dev/null
+++ b/qt6/src/poppler-converter.h
@@ -0,0 +1,465 @@
+/* poppler-converter.h: qt interface to poppler
+ * Copyright (C) 2005, Net Integration Technologies, Inc.
+ * Copyright (C) 2005, 2007, Brad Hards <bradh@frogmouth.net>
+ * Copyright (C) 2005-2015, 2017-2022, Albert Astals Cid <aacid@kde.org>
+ * Copyright (C) 2005, Stefan Kebekus <stefan.kebekus@math.uni-koeln.de>
+ * Copyright (C) 2006-2011, Pino Toscano <pino@kde.org>
+ * Copyright (C) 2009 Shawn Rutledge <shawn.t.rutledge@gmail.com>
+ * Copyright (C) 2010 Suzuki Toshiya <mpsuzuki@hiroshima-u.ac.jp>
+ * Copyright (C) 2010 Matthias Fauconneau <matthias.fauconneau@gmail.com>
+ * Copyright (C) 2011 Andreas Hartmetz <ahartmetz@gmail.com>
+ * Copyright (C) 2011 Glad Deschrijver <glad.deschrijver@gmail.com>
+ * Copyright (C) 2012, Guillermo A. Amaral B. <gamaral@kde.org>
+ * Copyright (C) 2012, Fabio D'Urso <fabiodurso@hotmail.it>
+ * Copyright (C) 2012, Tobias Koenig <tobias.koenig@kdab.com>
+ * Copyright (C) 2012, 2014, 2015, 2018, 2019 Adam Reichold <adamreichold@myopera.com>
+ * Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
+ * Copyright (C) 2013 Anthony Granger <grangeranthony@gmail.com>
+ * Copyright (C) 2016 Jakub Alba <jakubalba@gmail.com>
+ * Copyright (C) 2017, 2020, 2021 Oliver Sander <oliver.sander@tu-dresden.de>
+ * Copyright (C) 2017, 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by the LiMux project of the city of Munich
+ * Copyright (C) 2018, 2021 Nelson Benítez León <nbenitezl@gmail.com>
+ * Copyright (C) 2019 Jan Grulich <jgrulich@redhat.com>
+ * Copyright (C) 2019 Alexander Volkov <a.volkov@rusbitech.ru>
+ * Copyright (C) 2020 Philipp Knechtges <philipp-dev@knechtges.com>
+ * Copyright (C) 2020 Katarina Behrens <Katarina.Behrens@cib.de>
+ * Copyright (C) 2020 Thorsten Behrens <Thorsten.Behrens@CIB.de>
+ * Copyright (C) 2020, 2024 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by Technische Universität Dresden
+ * Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>.
+ * Copyright (C) 2021 Mahmoud Khalil <mahmoudkhalil11@gmail.com>
+ * Copyright (C) 2021 Georgiy Sgibnev <georgiy@sgibnev.com>. Work sponsored by lab50.net.
+ * Copyright (C) 2022 Martin <martinbts@gmx.net>
+ * Copyright (C) 2023 Kevin Ottens <kevin.ottens@enioka.com>. Work sponsored by De Bortoli Wines
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __POPPLER_CONVERTER_H__
+#define __POPPLER_CONVERTER_H__
+
+#include <QtCore/QByteArray>
+#include <QtCore/QIODevice>
+
+#include "poppler-export.h"
+
+namespace Poppler {
+
+class DocumentData;
+
+class BaseConverterPrivate;
+class PSConverterPrivate;
+class PDFConverterPrivate;
+
+/**
+ \brief Base converter.
+
+ This is the base class for the converters.
+*/
+class POPPLER_QT6_EXPORT BaseConverter
+{
+ friend class Document;
+
+public:
+ /**
+ Destructor.
+ */
+ virtual ~BaseConverter();
+
+ /** Sets the output file name. You must set this or the output device. */
+ void setOutputFileName(const QString &outputFileName);
+
+ /**
+ * Sets the output device. You must set this or the output file name.
+ */
+ void setOutputDevice(QIODevice *device);
+
+ /**
+ Does the conversion.
+
+ \return whether the conversion succeeded
+ */
+ virtual bool convert() = 0;
+
+ enum Error
+ {
+ NoError,
+ FileLockedError,
+ OpenOutputError,
+ NotSupportedInputFileError
+ };
+
+ /**
+ Returns the last error
+ */
+ Error lastError() const;
+
+protected:
+ /// \cond PRIVATE
+ explicit BaseConverter(BaseConverterPrivate &dd);
+ Q_DECLARE_PRIVATE(BaseConverter)
+ BaseConverterPrivate *d_ptr;
+ /// \endcond
+
+private:
+ Q_DISABLE_COPY(BaseConverter)
+};
+
+/**
+ Converts a PDF to PS
+
+ Sizes have to be in Points (1/72 inch)
+
+ If you are using QPrinter you can get paper size by doing:
+ \code
+QPrinter dummy(QPrinter::PrinterResolution);
+dummy.setFullPage(true);
+dummy.setPageSize(myPageSize);
+width = dummy.width();
+height = dummy.height();
+ \endcode
+*/
+class POPPLER_QT6_EXPORT PSConverter : public BaseConverter
+{
+ friend class Document;
+
+public:
+ /**
+ Options for the PS export.
+ */
+ enum PSOption
+ {
+ Printing = 0x00000001, ///< The PS is generated for printing purposes
+ StrictMargins = 0x00000002,
+ ForceRasterization = 0x00000004,
+ PrintToEPS = 0x00000008, ///< Output EPS instead of PS
+ HideAnnotations = 0x00000010, ///< Don't print annotations
+ ForceOverprintPreview = 0x00000020 ///< Force rasterized overprint preview during conversion \since 23.09
+ };
+ Q_DECLARE_FLAGS(PSOptions, PSOption)
+
+ /**
+ Destructor.
+ */
+ ~PSConverter() override;
+
+ /** Sets the list of pages to print. Mandatory. */
+ void setPageList(const QList<int> &pageList);
+
+ /**
+ Sets the title of the PS Document. Optional
+ */
+ void setTitle(const QString &title);
+
+ /**
+ Sets the horizontal DPI. Defaults to 72.0
+ */
+ void setHDPI(double hDPI);
+
+ /**
+ Sets the vertical DPI. Defaults to 72.0
+ */
+ void setVDPI(double vDPI);
+
+ /**
+ Sets the rotate. Defaults to not rotated
+ */
+ void setRotate(int rotate);
+
+ /**
+ Sets the output paper width. Has to be set.
+ */
+ void setPaperWidth(int paperWidth);
+
+ /**
+ Sets the output paper height. Has to be set.
+ */
+ void setPaperHeight(int paperHeight);
+
+ /**
+ Sets the output right margin. Defaults to 0
+ */
+ void setRightMargin(int marginRight);
+
+ /**
+ Sets the output bottom margin. Defaults to 0
+ */
+ void setBottomMargin(int marginBottom);
+
+ /**
+ Sets the output left margin. Defaults to 0
+ */
+ void setLeftMargin(int marginLeft);
+
+ /**
+ Sets the output top margin. Defaults to 0
+ */
+ void setTopMargin(int marginTop);
+
+ /**
+ Defines if margins have to be strictly followed (even if that
+ means changing aspect ratio), or if the margins can be adapted
+ to keep aspect ratio.
+
+ Defaults to false.
+ */
+ void setStrictMargins(bool strictMargins);
+
+ /**
+ Defines if the page will be rasterized to an image with overprint
+ preview enabled before printing.
+
+ Defaults to false
+
+ \since 23.09
+ */
+ void setForceOverprintPreview(bool forceOverprintPreview);
+
+ /** Defines if the page will be rasterized to an image before printing. Defaults to false */
+ void setForceRasterize(bool forceRasterize);
+
+ /**
+ Sets the options for the PS export.
+ */
+ void setPSOptions(PSOptions options);
+
+ /**
+ The currently set options for the PS export.
+
+ The default flags are: Printing.
+ */
+ PSOptions psOptions() const;
+
+ /**
+ Sets a function that will be called each time a page is converted.
+
+ The payload belongs to the caller.
+ */
+ void setPageConvertedCallback(void (*callback)(int page, void *payload), void *payload);
+
+ bool convert() override;
+
+private:
+ Q_DECLARE_PRIVATE(PSConverter)
+ Q_DISABLE_COPY(PSConverter)
+
+ explicit PSConverter(DocumentData *document);
+};
+
+/**
+ Converts a PDF to PDF (thus saves a copy of the document).
+*/
+class POPPLER_QT6_EXPORT PDFConverter : public BaseConverter
+{
+ friend class Document;
+
+public:
+ /**
+ Options for the PDF export.
+ */
+ enum PDFOption
+ {
+ WithChanges = 0x00000001 ///< The changes done to the document are saved as well
+ };
+ Q_DECLARE_FLAGS(PDFOptions, PDFOption)
+
+ /**
+ Destructor.
+ */
+ ~PDFConverter() override;
+
+ /**
+ Sets the options for the PDF export.
+ */
+ void setPDFOptions(PDFOptions options);
+ /**
+ The currently set options for the PDF export.
+ */
+ PDFOptions pdfOptions() const;
+
+ /**
+ * Holds data for a new signature
+ * - Common Name of cert to sign (aka nickname)
+ * - password for the cert
+ * - page where to add the signature
+ * - rect for the signature annotation
+ * - text that will be shown inside the rect
+ * - font size and color
+ * - border width and color
+ * - background color
+ * \since 21.01
+ */
+ class POPPLER_QT6_EXPORT NewSignatureData
+ {
+ public:
+ NewSignatureData();
+ ~NewSignatureData();
+ NewSignatureData(const NewSignatureData &) = delete;
+ NewSignatureData &operator=(const NewSignatureData &) = delete;
+
+ QString certNickname() const;
+ void setCertNickname(const QString &certNickname);
+
+ QString password() const;
+ void setPassword(const QString &password);
+
+ int page() const;
+ void setPage(int page);
+
+ QRectF boundingRectangle() const;
+ void setBoundingRectangle(const QRectF &rect);
+
+ QString signatureText() const;
+ void setSignatureText(const QString &text);
+
+ /**
+ * If this text is not empty, the signature representation
+ * will split in two, with this text on the left and signatureText
+ * on the right
+ *
+ * \since 21.06
+ */
+ QString signatureLeftText() const;
+ void setSignatureLeftText(const QString &text);
+
+ /**
+ * Signature's property Reason.
+ *
+ * Default: an empty string.
+ *
+ * \since 21.10
+ */
+ QString reason() const;
+ void setReason(const QString &reason);
+
+ /**
+ * Signature's property Location.
+ *
+ * Default: an empty string.
+ *
+ * \since 21.10
+ */
+ QString location() const;
+ void setLocation(const QString &location);
+
+ /**
+ * Default: 10
+ */
+ double fontSize() const;
+ void setFontSize(double fontSize);
+
+ /**
+ * Default: 20
+ *
+ * \since 21.06
+ */
+ double leftFontSize() const;
+ void setLeftFontSize(double fontSize);
+
+ /**
+ * Default: red
+ */
+ QColor fontColor() const;
+ void setFontColor(const QColor &color);
+
+ /**
+ * Default: red
+ */
+ QColor borderColor() const;
+ void setBorderColor(const QColor &color);
+
+ /**
+ * border width in points
+ *
+ * Default: 1.5
+ *
+ * \since 21.05
+ */
+ double borderWidth() const;
+ void setBorderWidth(double width);
+
+ /**
+ * Default: QColor(240, 240, 240)
+ */
+ QColor backgroundColor() const;
+ void setBackgroundColor(const QColor &color);
+
+ /**
+ * Default: QUuid::createUuid().toString()
+ */
+ QString fieldPartialName() const;
+ void setFieldPartialName(const QString &name);
+
+ /**
+ * Document owner password (needed if the document that is being signed is password protected)
+ *
+ * Default: no password
+ *
+ * \since 22.02
+ */
+ QByteArray documentOwnerPassword() const;
+ void setDocumentOwnerPassword(const QByteArray &password);
+
+ /**
+ * Document user password (needed if the document that is being signed is password protected)
+ *
+ * Default: no password
+ *
+ * \since 22.02
+ */
+ QByteArray documentUserPassword() const;
+ void setDocumentUserPassword(const QByteArray &password);
+
+ /**
+ * Filesystem path to an image file to be used as background
+ * image for the signature annotation widget.
+ *
+ * Default: empty
+ *
+ * \since 22.02
+ */
+ QString imagePath() const;
+ void setImagePath(const QString &path);
+
+ private:
+ struct NewSignatureDataPrivate;
+ NewSignatureDataPrivate *const d;
+ };
+
+ /**
+ Sign PDF at given Annotation / signature form
+
+ \param data new signature data
+
+ \return whether the signing succeeded
+
+ \since 21.01
+ */
+ bool sign(const NewSignatureData &data);
+
+ bool convert() override;
+
+private:
+ Q_DECLARE_PRIVATE(PDFConverter)
+ Q_DISABLE_COPY(PDFConverter)
+
+ explicit PDFConverter(DocumentData *document);
+};
+
+}
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(Poppler::PDFConverter::PDFOptions)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Poppler::PSConverter::PSOptions)
+
+#endif
diff --git a/qt6/src/poppler-qt6.h b/qt6/src/poppler-qt6.h
index eda10da..2350e3f 100644
--- a/qt6/src/poppler-qt6.h
+++ b/qt6/src/poppler-qt6.h
@@ -24,7 +24,7 @@
* Copyright (C) 2020 Philipp Knechtges <philipp-dev@knechtges.com>
* Copyright (C) 2020 Katarina Behrens <Katarina.Behrens@cib.de>
* Copyright (C) 2020 Thorsten Behrens <Thorsten.Behrens@CIB.de>
- * Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by Technische Universität Dresden
+ * Copyright (C) 2020, 2024 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by Technische Universität Dresden
* Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>.
* Copyright (C) 2021 Mahmoud Khalil <mahmoudkhalil11@gmail.com>
* Copyright (C) 2021 Georgiy Sgibnev <georgiy@sgibnev.com>. Work sponsored by lab50.net.
@@ -58,6 +58,7 @@
#include "poppler-link.h"
#include "poppler-optcontent.h"
#include "poppler-page-transition.h"
+#include "poppler-converter.h"
#include <QtCore/QByteArray>
#include <QtCore/QDateTime>
@@ -1771,404 +1772,6 @@
explicit Document(DocumentData *dataA);
};
-class BaseConverterPrivate;
-class PSConverterPrivate;
-class PDFConverterPrivate;
-/**
- \brief Base converter.
-
- This is the base class for the converters.
-*/
-class POPPLER_QT6_EXPORT BaseConverter
-{
- friend class Document;
-
-public:
- /**
- Destructor.
- */
- virtual ~BaseConverter();
-
- /** Sets the output file name. You must set this or the output device. */
- void setOutputFileName(const QString &outputFileName);
-
- /**
- * Sets the output device. You must set this or the output file name.
- */
- void setOutputDevice(QIODevice *device);
-
- /**
- Does the conversion.
-
- \return whether the conversion succeeded
- */
- virtual bool convert() = 0;
-
- enum Error
- {
- NoError,
- FileLockedError,
- OpenOutputError,
- NotSupportedInputFileError
- };
-
- /**
- Returns the last error
- */
- Error lastError() const;
-
-protected:
- /// \cond PRIVATE
- explicit BaseConverter(BaseConverterPrivate &dd);
- Q_DECLARE_PRIVATE(BaseConverter)
- BaseConverterPrivate *d_ptr;
- /// \endcond
-
-private:
- Q_DISABLE_COPY(BaseConverter)
-};
-
-/**
- Converts a PDF to PS
-
- Sizes have to be in Points (1/72 inch)
-
- If you are using QPrinter you can get paper size by doing:
- \code
-QPrinter dummy(QPrinter::PrinterResolution);
-dummy.setFullPage(true);
-dummy.setPageSize(myPageSize);
-width = dummy.width();
-height = dummy.height();
- \endcode
-*/
-class POPPLER_QT6_EXPORT PSConverter : public BaseConverter
-{
- friend class Document;
-
-public:
- /**
- Options for the PS export.
- */
- enum PSOption
- {
- Printing = 0x00000001, ///< The PS is generated for printing purposes
- StrictMargins = 0x00000002,
- ForceRasterization = 0x00000004,
- PrintToEPS = 0x00000008, ///< Output EPS instead of PS
- HideAnnotations = 0x00000010, ///< Don't print annotations
- ForceOverprintPreview = 0x00000020 ///< Force rasterized overprint preview during conversion \since 23.09
- };
- Q_DECLARE_FLAGS(PSOptions, PSOption)
-
- /**
- Destructor.
- */
- ~PSConverter() override;
-
- /** Sets the list of pages to print. Mandatory. */
- void setPageList(const QList<int> &pageList);
-
- /**
- Sets the title of the PS Document. Optional
- */
- void setTitle(const QString &title);
-
- /**
- Sets the horizontal DPI. Defaults to 72.0
- */
- void setHDPI(double hDPI);
-
- /**
- Sets the vertical DPI. Defaults to 72.0
- */
- void setVDPI(double vDPI);
-
- /**
- Sets the rotate. Defaults to not rotated
- */
- void setRotate(int rotate);
-
- /**
- Sets the output paper width. Has to be set.
- */
- void setPaperWidth(int paperWidth);
-
- /**
- Sets the output paper height. Has to be set.
- */
- void setPaperHeight(int paperHeight);
-
- /**
- Sets the output right margin. Defaults to 0
- */
- void setRightMargin(int marginRight);
-
- /**
- Sets the output bottom margin. Defaults to 0
- */
- void setBottomMargin(int marginBottom);
-
- /**
- Sets the output left margin. Defaults to 0
- */
- void setLeftMargin(int marginLeft);
-
- /**
- Sets the output top margin. Defaults to 0
- */
- void setTopMargin(int marginTop);
-
- /**
- Defines if margins have to be strictly followed (even if that
- means changing aspect ratio), or if the margins can be adapted
- to keep aspect ratio.
-
- Defaults to false.
- */
- void setStrictMargins(bool strictMargins);
-
- /**
- Defines if the page will be rasterized to an image with overprint
- preview enabled before printing.
-
- Defaults to false
-
- \since 23.09
- */
- void setForceOverprintPreview(bool forceOverprintPreview);
-
- /** Defines if the page will be rasterized to an image before printing. Defaults to false */
- void setForceRasterize(bool forceRasterize);
-
- /**
- Sets the options for the PS export.
- */
- void setPSOptions(PSOptions options);
-
- /**
- The currently set options for the PS export.
-
- The default flags are: Printing.
- */
- PSOptions psOptions() const;
-
- /**
- Sets a function that will be called each time a page is converted.
-
- The payload belongs to the caller.
- */
- void setPageConvertedCallback(void (*callback)(int page, void *payload), void *payload);
-
- bool convert() override;
-
-private:
- Q_DECLARE_PRIVATE(PSConverter)
- Q_DISABLE_COPY(PSConverter)
-
- explicit PSConverter(DocumentData *document);
-};
-
-/**
- Converts a PDF to PDF (thus saves a copy of the document).
-*/
-class POPPLER_QT6_EXPORT PDFConverter : public BaseConverter
-{
- friend class Document;
-
-public:
- /**
- Options for the PDF export.
- */
- enum PDFOption
- {
- WithChanges = 0x00000001 ///< The changes done to the document are saved as well
- };
- Q_DECLARE_FLAGS(PDFOptions, PDFOption)
-
- /**
- Destructor.
- */
- ~PDFConverter() override;
-
- /**
- Sets the options for the PDF export.
- */
- void setPDFOptions(PDFOptions options);
- /**
- The currently set options for the PDF export.
- */
- PDFOptions pdfOptions() const;
-
- /**
- * Holds data for a new signature
- * - Common Name of cert to sign (aka nickname)
- * - password for the cert
- * - page where to add the signature
- * - rect for the signature annotation
- * - text that will be shown inside the rect
- * - font size and color
- * - border width and color
- * - background color
- * \since 21.01
- */
- class POPPLER_QT6_EXPORT NewSignatureData
- {
- public:
- NewSignatureData();
- ~NewSignatureData();
- NewSignatureData(const NewSignatureData &) = delete;
- NewSignatureData &operator=(const NewSignatureData &) = delete;
-
- QString certNickname() const;
- void setCertNickname(const QString &certNickname);
-
- QString password() const;
- void setPassword(const QString &password);
-
- int page() const;
- void setPage(int page);
-
- QRectF boundingRectangle() const;
- void setBoundingRectangle(const QRectF &rect);
-
- QString signatureText() const;
- void setSignatureText(const QString &text);
-
- /**
- * If this text is not empty, the signature representation
- * will split in two, with this text on the left and signatureText
- * on the right
- *
- * \since 21.06
- */
- QString signatureLeftText() const;
- void setSignatureLeftText(const QString &text);
-
- /**
- * Signature's property Reason.
- *
- * Default: an empty string.
- *
- * \since 21.10
- */
- QString reason() const;
- void setReason(const QString &reason);
-
- /**
- * Signature's property Location.
- *
- * Default: an empty string.
- *
- * \since 21.10
- */
- QString location() const;
- void setLocation(const QString &location);
-
- /**
- * Default: 10
- */
- double fontSize() const;
- void setFontSize(double fontSize);
-
- /**
- * Default: 20
- *
- * \since 21.06
- */
- double leftFontSize() const;
- void setLeftFontSize(double fontSize);
-
- /**
- * Default: red
- */
- QColor fontColor() const;
- void setFontColor(const QColor &color);
-
- /**
- * Default: red
- */
- QColor borderColor() const;
- void setBorderColor(const QColor &color);
-
- /**
- * border width in points
- *
- * Default: 1.5
- *
- * \since 21.05
- */
- double borderWidth() const;
- void setBorderWidth(double width);
-
- /**
- * Default: QColor(240, 240, 240)
- */
- QColor backgroundColor() const;
- void setBackgroundColor(const QColor &color);
-
- /**
- * Default: QUuid::createUuid().toString()
- */
- QString fieldPartialName() const;
- void setFieldPartialName(const QString &name);
-
- /**
- * Document owner password (needed if the document that is being signed is password protected)
- *
- * Default: no password
- *
- * \since 22.02
- */
- QByteArray documentOwnerPassword() const;
- void setDocumentOwnerPassword(const QByteArray &password);
-
- /**
- * Document user password (needed if the document that is being signed is password protected)
- *
- * Default: no password
- *
- * \since 22.02
- */
- QByteArray documentUserPassword() const;
- void setDocumentUserPassword(const QByteArray &password);
-
- /**
- * Filesystem path to an image file to be used as background
- * image for the signature annotation widget.
- *
- * Default: empty
- *
- * \since 22.02
- */
- QString imagePath() const;
- void setImagePath(const QString &path);
-
- private:
- struct NewSignatureDataPrivate;
- NewSignatureDataPrivate *const d;
- };
-
- /**
- Sign PDF at given Annotation / signature form
-
- \param data new signature data
-
- \return whether the signing succeeded
-
- \since 21.01
- */
- bool sign(const NewSignatureData &data);
-
- bool convert() override;
-
-private:
- Q_DECLARE_PRIVATE(PDFConverter)
- Q_DISABLE_COPY(PDFConverter)
-
- explicit PDFConverter(DocumentData *document);
-};
-
/**
Conversion from PDF date string format to QDateTime
*/
@@ -2338,7 +1941,5 @@
Q_DECLARE_OPERATORS_FOR_FLAGS(Poppler::Page::PainterFlags)
Q_DECLARE_OPERATORS_FOR_FLAGS(Poppler::Page::SearchFlags)
Q_DECLARE_OPERATORS_FOR_FLAGS(Poppler::Document::RenderHints)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Poppler::PDFConverter::PDFOptions)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Poppler::PSConverter::PSOptions)
#endif