diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2020-06-19 14:08:44 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2020-06-19 15:27:46 +0200 |
commit | 9b7a890fd59744459692d7f66402c6bdd25acec4 (patch) | |
tree | 615ad3ed0c67b5f3d02d4bf6ac43f5e333b7917a /vcl | |
parent | 7cd5cddce02a6e005c0fcd45b9b720c2ca877cfc (diff) |
sd signature line: include shape in the appearance widget
With this, finally the following works:
1) file -> digital signatures -> sign existing pdf
2) file -> digital signatures -> signature line
3) draw a rectangle
4) popup appears, select signing certificate
5) click on the "finish signing" button on the infobar
The resulting pdf will have a signature on it, together with the pdf
export of the signature line shape.
Change-Id: Icef701aaa6fd4a625acb37094ad34b88283caf42
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/96730
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/source/filter/ipdf/pdfdocument.cxx | 55 |
1 files changed, 51 insertions, 4 deletions
diff --git a/vcl/source/filter/ipdf/pdfdocument.cxx b/vcl/source/filter/ipdf/pdfdocument.cxx index 09439604996d..06324f22b4fd 100644 --- a/vcl/source/filter/ipdf/pdfdocument.cxx +++ b/vcl/source/filter/ipdf/pdfdocument.cxx @@ -28,6 +28,8 @@ #include <vcl/pdfwriter.hxx> #include <o3tl/safeint.hxx> +#include <pdf/objectcopier.hxx> + using namespace com::sun::star; namespace vcl::filter @@ -269,6 +271,10 @@ sal_Int32 PDFDocument::WriteSignatureObject(const OUString& rDescription, bool b sal_Int32 PDFDocument::WriteAppearanceObject(tools::Rectangle& rSignatureRectangle) { + PDFDocument aPDFDocument; + filter::PDFObjectElement* pPage = nullptr; + std::vector<filter::PDFObjectElement*> aContentStreams; + if (!m_aSignatureLine.empty()) { // Parse the PDF data of signature line: we can set the signature rectangle to non-empty @@ -276,7 +282,6 @@ sal_Int32 PDFDocument::WriteAppearanceObject(tools::Rectangle& rSignatureRectang SvMemoryStream aPDFStream; aPDFStream.WriteBytes(m_aSignatureLine.data(), m_aSignatureLine.size()); aPDFStream.Seek(0); - filter::PDFDocument aPDFDocument; if (!aPDFDocument.Read(aPDFStream)) { SAL_WARN("vcl.filter", @@ -291,7 +296,7 @@ sal_Int32 PDFDocument::WriteAppearanceObject(tools::Rectangle& rSignatureRectang return -1; } - filter::PDFObjectElement* pPage = aPages[0]; + pPage = aPages[0]; if (!pPage) { SAL_WARN("vcl.filter", "PDFDocument::WriteAppearanceObject: no page"); @@ -322,6 +327,17 @@ sal_Int32 PDFDocument::WriteAppearanceObject(tools::Rectangle& rSignatureRectang return -1; } rSignatureRectangle.setHeight(pHeight->GetValue()); + + if (PDFObjectElement* pContentStream = pPage->LookupObject("Contents")) + { + aContentStreams.push_back(pContentStream); + } + + if (aContentStreams.empty()) + { + SAL_WARN("vcl.filter", "PDFDocument::WriteAppearanceObject: no content stream"); + return -1; + } } m_aSignatureLine.clear(); @@ -334,14 +350,45 @@ sal_Int32 PDFDocument::WriteAppearanceObject(tools::Rectangle& rSignatureRectang aEditBuffer.WriteUInt32AsString(nAppearanceId); aEditBuffer.WriteCharPtr(" 0 obj\n"); aEditBuffer.WriteCharPtr("<</Type/XObject\n/Subtype/Form\n"); + + PDFObjectCopier aCopier(*this); + if (!aContentStreams.empty()) + { + OStringBuffer aBuffer; + aCopier.copyPageResources(pPage, aBuffer); + aEditBuffer.WriteOString(aBuffer.makeStringAndClear()); + } + aEditBuffer.WriteCharPtr("/BBox[0 0 "); aEditBuffer.WriteOString(OString::number(rSignatureRectangle.getWidth())); aEditBuffer.WriteCharPtr(" "); aEditBuffer.WriteOString(OString::number(rSignatureRectangle.getHeight())); - aEditBuffer.WriteCharPtr("]\n/Length 0\n>>\n"); - aEditBuffer.WriteCharPtr("stream\n\nendstream\nendobj\n\n"); + aEditBuffer.WriteCharPtr("]\n/Length "); // Add the object to the doc-level edit buffer and update the offset. + SvMemoryStream aStream; + bool bCompressed = false; + sal_Int32 nLength = 0; + if (!aContentStreams.empty()) + { + nLength = PDFObjectCopier::copyPageStreams(aContentStreams, aStream, bCompressed); + } + aEditBuffer.WriteOString(OString::number(nLength)); + if (bCompressed) + { + aEditBuffer.WriteOString(" /Filter/FlateDecode"); + } + + aEditBuffer.WriteCharPtr("\n>>\n"); + + aEditBuffer.WriteCharPtr("stream\n"); + + // Copy the original page streams to the form XObject stream. + aStream.Seek(0); + aEditBuffer.WriteStream(aStream); + + aEditBuffer.WriteCharPtr("\nendstream\nendobj\n\n"); + aEditBuffer.Seek(0); XRefEntry aAppearanceEntry; aAppearanceEntry.SetOffset(m_aEditBuffer.Tell()); |