[Libreoffice-commits] core.git: include/vcl vcl/source

Miklos Vajna (via logerrit) logerrit at kemper.freedesktop.org
Wed Jun 17 15:35:27 UTC 2020


 include/vcl/filter/pdfdocument.hxx     |   10 +++-
 vcl/source/filter/ipdf/pdfdocument.cxx |   77 ++++++++++++++++++++++++++++++---
 2 files changed, 79 insertions(+), 8 deletions(-)

New commits:
commit 4db25ccc736185c304f1bd090b8539868932700a
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Wed Jun 17 16:05:36 2020 +0200
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Wed Jun 17 17:34:51 2020 +0200

    sd signature line: implement non-empty geometry during pdf sign
    
    Parse the pdf output which contains just the signature line shape on a
    page, take the same from it and use it at both places where previously
    the position / size was just a stub.
    
    Change-Id: Ifb2e0ebf7b3514ee027701b9bf360a0c996cdc82
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/96540
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
    Tested-by: Jenkins

diff --git a/include/vcl/filter/pdfdocument.hxx b/include/vcl/filter/pdfdocument.hxx
index 8700e4892df2..aaf64ae908fe 100644
--- a/include/vcl/filter/pdfdocument.hxx
+++ b/include/vcl/filter/pdfdocument.hxx
@@ -29,6 +29,11 @@ namespace com::sun::star::uno
 template <class interface_type> class Reference;
 }
 
+namespace tools
+{
+class Rectangle;
+}
+
 namespace vcl::filter
 {
 class PDFTrailerElement;
@@ -353,10 +358,11 @@ class VCL_DLLPUBLIC PDFDocument
     sal_Int32 WriteSignatureObject(const OUString& rDescription, bool bAdES,
                                    sal_uInt64& rLastByteRangeOffset, sal_Int64& rContentOffset);
     /// Write the appearance object as part of signing.
-    sal_Int32 WriteAppearanceObject();
+    sal_Int32 WriteAppearanceObject(tools::Rectangle& rSignatureRectangle);
     /// Write the annot object as part of signing.
     sal_Int32 WriteAnnotObject(PDFObjectElement const& rFirstPage, sal_Int32 nSignatureId,
-                               sal_Int32 nAppearanceId);
+                               sal_Int32 nAppearanceId,
+                               const tools::Rectangle& rSignatureRectangle);
     /// Write the updated Page object as part of signing.
     bool WritePageObject(PDFObjectElement& rFirstPage, sal_Int32 nAnnotId);
     /// Write the updated Catalog object as part of signing.
diff --git a/vcl/source/filter/ipdf/pdfdocument.cxx b/vcl/source/filter/ipdf/pdfdocument.cxx
index 316b8c74d169..928f22d8a8c7 100644
--- a/vcl/source/filter/ipdf/pdfdocument.cxx
+++ b/vcl/source/filter/ipdf/pdfdocument.cxx
@@ -236,8 +236,62 @@ sal_Int32 PDFDocument::WriteSignatureObject(const OUString& rDescription, bool b
     return nSignatureId;
 }
 
-sal_Int32 PDFDocument::WriteAppearanceObject()
+sal_Int32 PDFDocument::WriteAppearanceObject(tools::Rectangle& rSignatureRectangle)
 {
+    if (!m_aSignatureLine.empty())
+    {
+        // Parse the PDF data of signature line: we can set the signature rectangle to non-empty
+        // based on it.
+        SvMemoryStream aPDFStream;
+        aPDFStream.WriteBytes(m_aSignatureLine.data(), m_aSignatureLine.size());
+        aPDFStream.Seek(0);
+        filter::PDFDocument aPDFDocument;
+        if (!aPDFDocument.Read(aPDFStream))
+        {
+            SAL_WARN("vcl.filter",
+                     "PDFDocument::WriteAppearanceObject: failed to read the PDF document");
+            return -1;
+        }
+
+        std::vector<filter::PDFObjectElement*> aPages = aPDFDocument.GetPages();
+        if (aPages.empty())
+        {
+            SAL_WARN("vcl.filter", "PDFDocument::WriteAppearanceObject: no pages");
+            return -1;
+        }
+
+        filter::PDFObjectElement* pPage = aPages[0];
+        if (!pPage)
+        {
+            SAL_WARN("vcl.filter", "PDFDocument::WriteAppearanceObject: no page");
+            return -1;
+        }
+
+        // Calculate the bounding box.
+        PDFElement* pMediaBox = pPage->Lookup("MediaBox");
+        auto pMediaBoxArray = dynamic_cast<PDFArrayElement*>(pMediaBox);
+        if (!pMediaBoxArray || pMediaBoxArray->GetElements().size() < 4)
+        {
+            SAL_WARN("vcl.filter",
+                     "PDFDocument::WriteAppearanceObject: MediaBox is not an array of 4");
+            return -1;
+        }
+        const std::vector<PDFElement*>& rMediaBoxElements = pMediaBoxArray->GetElements();
+        auto pWidth = dynamic_cast<PDFNumberElement*>(rMediaBoxElements[2]);
+        if (!pWidth)
+        {
+            SAL_WARN("vcl.filter", "PDFDocument::WriteAppearanceObject: MediaBox has no width");
+            return -1;
+        }
+        rSignatureRectangle.setWidth(pWidth->GetValue());
+        auto pHeight = dynamic_cast<PDFNumberElement*>(rMediaBoxElements[3]);
+        if (!pHeight)
+        {
+            SAL_WARN("vcl.filter", "PDFDocument::WriteAppearanceObject: MediaBox has no height");
+            return -1;
+        }
+        rSignatureRectangle.setHeight(pHeight->GetValue());
+    }
     m_aSignatureLine.clear();
 
     // Write appearance object.
@@ -249,14 +303,19 @@ sal_Int32 PDFDocument::WriteAppearanceObject()
     m_aEditBuffer.WriteUInt32AsString(nAppearanceId);
     m_aEditBuffer.WriteCharPtr(" 0 obj\n");
     m_aEditBuffer.WriteCharPtr("<</Type/XObject\n/Subtype/Form\n");
-    m_aEditBuffer.WriteCharPtr("/BBox[0 0 0 0]\n/Length 0\n>>\n");
+    m_aEditBuffer.WriteCharPtr("/BBox[0 0 ");
+    m_aEditBuffer.WriteOString(OString::number(rSignatureRectangle.getWidth()));
+    m_aEditBuffer.WriteCharPtr(" ");
+    m_aEditBuffer.WriteOString(OString::number(rSignatureRectangle.getHeight()));
+    m_aEditBuffer.WriteCharPtr("]\n/Length 0\n>>\n");
     m_aEditBuffer.WriteCharPtr("stream\n\nendstream\nendobj\n\n");
 
     return nAppearanceId;
 }
 
 sal_Int32 PDFDocument::WriteAnnotObject(PDFObjectElement const& rFirstPage, sal_Int32 nSignatureId,
-                                        sal_Int32 nAppearanceId)
+                                        sal_Int32 nAppearanceId,
+                                        const tools::Rectangle& rSignatureRectangle)
 {
     // Decide what identifier to use for the new signature.
     sal_uInt32 nNextSignature = GetNextSignature();
@@ -270,7 +329,11 @@ sal_Int32 PDFDocument::WriteAnnotObject(PDFObjectElement const& rFirstPage, sal_
     m_aEditBuffer.WriteUInt32AsString(nAnnotId);
     m_aEditBuffer.WriteCharPtr(" 0 obj\n");
     m_aEditBuffer.WriteCharPtr("<</Type/Annot/Subtype/Widget/F 132\n");
-    m_aEditBuffer.WriteCharPtr("/Rect[0 0 0 0]\n");
+    m_aEditBuffer.WriteCharPtr("/Rect[0 0 ");
+    m_aEditBuffer.WriteOString(OString::number(rSignatureRectangle.getWidth()));
+    m_aEditBuffer.WriteCharPtr(" ");
+    m_aEditBuffer.WriteOString(OString::number(rSignatureRectangle.getHeight()));
+    m_aEditBuffer.WriteCharPtr("]\n");
     m_aEditBuffer.WriteCharPtr("/FT/Sig\n");
     m_aEditBuffer.WriteCharPtr("/P ");
     m_aEditBuffer.WriteUInt32AsString(rFirstPage.GetObjectValue());
@@ -807,7 +870,8 @@ bool PDFDocument::Sign(const uno::Reference<security::XCertificate>& xCertificat
     sal_Int32 nSignatureId = WriteSignatureObject(
         rDescription, bAdES, nSignatureLastByteRangeOffset, nSignatureContentOffset);
 
-    sal_Int32 nAppearanceId = WriteAppearanceObject();
+    tools::Rectangle aSignatureRectangle;
+    sal_Int32 nAppearanceId = WriteAppearanceObject(aSignatureRectangle);
 
     std::vector<PDFObjectElement*> aPages = GetPages();
     if (aPages.empty() || !aPages[0])
@@ -817,7 +881,8 @@ bool PDFDocument::Sign(const uno::Reference<security::XCertificate>& xCertificat
     }
 
     PDFObjectElement& rFirstPage = *aPages[0];
-    sal_Int32 nAnnotId = WriteAnnotObject(rFirstPage, nSignatureId, nAppearanceId);
+    sal_Int32 nAnnotId
+        = WriteAnnotObject(rFirstPage, nSignatureId, nAppearanceId, aSignatureRectangle);
 
     if (!WritePageObject(rFirstPage, nAnnotId))
     {


More information about the Libreoffice-commits mailing list