summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2020-06-18 12:12:52 +0200
committerMiklos Vajna <vmiklos@collabora.com>2020-06-18 14:36:29 +0200
commit8277073ce3e33788d93b3df490a8f03d1814863b (patch)
tree51094d52c1a629ddbb6d3e24d9b583ba74e5f042 /vcl
parenta60a5e769a407fa13b087a111123ceff5a96bc03 (diff)
sd signature line: extract copyExternalResources() from the pdf export code
Because I would like to reuse this in the "sign existing pdf" code, in vcl::filter::PDFDocument::WriteAppearanceObject(). Change-Id: Ia5e5c1e452bb0d0486bde2a082375b5131eea8c7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/96595 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins
Diffstat (limited to 'vcl')
-rw-r--r--vcl/Library_vcl.mk1
-rw-r--r--vcl/inc/pdf/objectcontainer.hxx36
-rw-r--r--vcl/inc/pdf/objectcopier.hxx48
-rw-r--r--vcl/source/gdi/pdfobjectcopier.cxx273
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx233
-rw-r--r--vcl/source/gdi/pdfwriter_impl.hxx22
6 files changed, 368 insertions, 245 deletions
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 430cc4d9c0b5..b294042fb90b 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -297,6 +297,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/source/gdi/pdfwriter \
vcl/source/gdi/pdfwriter_impl2 \
vcl/source/gdi/pdfwriter_impl \
+ vcl/source/gdi/pdfobjectcopier \
vcl/source/gdi/print2 \
vcl/source/gdi/print3 \
vcl/source/gdi/print \
diff --git a/vcl/inc/pdf/objectcontainer.hxx b/vcl/inc/pdf/objectcontainer.hxx
new file mode 100644
index 000000000000..ca4898737e10
--- /dev/null
+++ b/vcl/inc/pdf/objectcontainer.hxx
@@ -0,0 +1,36 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <sal/types.h>
+
+namespace vcl
+{
+/// Allows creating, updating and writing PDF objects in a container.
+class SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI PDFObjectContainer
+{
+public:
+ /* adds an entry to m_aObjects and returns its index+1,
+ * sets the offset to ~0
+ */
+ virtual sal_Int32 createObject() = 0;
+ /* sets the offset of object n to the current position of output file+1
+ */
+ virtual bool updateObject(sal_Int32 n) = 0;
+
+ // Write pBuffer to the end of the output.
+ virtual bool writeBuffer(const void* pBuffer, sal_uInt64 nBytes) = 0;
+
+protected:
+ ~PDFObjectContainer() noexcept = default;
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/pdf/objectcopier.hxx b/vcl/inc/pdf/objectcopier.hxx
new file mode 100644
index 000000000000..b99fbb4886b3
--- /dev/null
+++ b/vcl/inc/pdf/objectcopier.hxx
@@ -0,0 +1,48 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <map>
+
+#include <rtl/string.hxx>
+#include <sal/types.h>
+#include <vcl/dllapi.h>
+
+class SvMemoryStream;
+
+namespace vcl
+{
+class PDFObjectContainer;
+namespace filter
+{
+class PDFObjectElement;
+}
+
+/// Copies objects from one PDF file into an other one.
+class VCL_DLLPUBLIC PDFObjectCopier
+{
+ PDFObjectContainer& m_rContainer;
+
+public:
+ PDFObjectCopier(PDFObjectContainer& rContainer);
+
+ /// Copies resources of a given kind from an external page to the output,
+ /// returning what has to be included in the new resource dictionary.
+ OString copyExternalResources(filter::PDFObjectElement& rPage, const OString& rKind,
+ std::map<sal_Int32, sal_Int32>& rCopiedResources);
+
+ /// Copies a single resource from an external document, returns the new
+ /// object ID in our document.
+ sal_Int32 copyExternalResource(SvMemoryStream& rDocBuffer, filter::PDFObjectElement& rObject,
+ std::map<sal_Int32, sal_Int32>& rCopiedResources);
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/gdi/pdfobjectcopier.cxx b/vcl/source/gdi/pdfobjectcopier.cxx
new file mode 100644
index 000000000000..4ba93b3a746d
--- /dev/null
+++ b/vcl/source/gdi/pdfobjectcopier.cxx
@@ -0,0 +1,273 @@
+/* -*- 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/.
+ */
+
+#include <pdf/objectcopier.hxx>
+
+#include <rtl/strbuf.hxx>
+#include <sal/log.hxx>
+#include <sal/types.h>
+#include <tools/stream.hxx>
+#include <vcl/filter/pdfdocument.hxx>
+
+#include <pdf/objectcontainer.hxx>
+
+namespace vcl
+{
+PDFObjectCopier::PDFObjectCopier(PDFObjectContainer& rContainer)
+ : m_rContainer(rContainer)
+{
+}
+
+sal_Int32 PDFObjectCopier::copyExternalResource(SvMemoryStream& rDocBuffer,
+ filter::PDFObjectElement& rObject,
+ std::map<sal_Int32, sal_Int32>& rCopiedResources)
+{
+ auto it = rCopiedResources.find(rObject.GetObjectValue());
+ if (it != rCopiedResources.end())
+ // This resource was already copied once, nothing to do.
+ return it->second;
+
+ sal_Int32 nObject = m_rContainer.createObject();
+ // Remember what is the ID of this object in our output.
+ rCopiedResources[rObject.GetObjectValue()] = nObject;
+ SAL_INFO("vcl.pdfwriter", "PDFWriterImpl::copyExternalResource: " << rObject.GetObjectValue()
+ << " -> " << nObject);
+
+ OStringBuffer aLine;
+ aLine.append(nObject);
+ aLine.append(" 0 obj\n");
+ if (rObject.GetDictionary())
+ {
+ aLine.append("<<");
+
+ // Complex case: can't copy the dictionary byte array as is, as it may contain references.
+ bool bDone = false;
+ sal_uInt64 nCopyStart = 0;
+ for (auto pReference : rObject.GetDictionaryReferences())
+ {
+ if (pReference)
+ {
+ filter::PDFObjectElement* pReferenced = pReference->LookupObject();
+ if (pReferenced)
+ {
+ // Copy the referenced object.
+ sal_Int32 nRef
+ = copyExternalResource(rDocBuffer, *pReferenced, rCopiedResources);
+
+ sal_uInt64 nReferenceStart = pReference->GetObjectElement().GetLocation();
+ sal_uInt64 nReferenceEnd = pReference->GetOffset();
+ sal_uInt64 nOffset = 0;
+ if (nCopyStart == 0)
+ // Dict start -> reference start.
+ nOffset = rObject.GetDictionaryOffset();
+ else
+ // Previous reference end -> reference start.
+ nOffset = nCopyStart;
+ aLine.append(static_cast<const char*>(rDocBuffer.GetData()) + nOffset,
+ nReferenceStart - nOffset);
+ // Write the updated reference.
+ aLine.append(" ");
+ aLine.append(nRef);
+ aLine.append(" 0 R");
+ // Start copying here next time.
+ nCopyStart = nReferenceEnd;
+
+ bDone = true;
+ }
+ }
+ }
+
+ if (bDone)
+ {
+ // Copy the last part here, in the complex case.
+ sal_uInt64 nDictEnd = rObject.GetDictionaryOffset() + rObject.GetDictionaryLength();
+ const sal_Int32 nLen = nDictEnd - nCopyStart;
+ if (nLen < 0)
+ SAL_WARN("vcl.pdfwriter", "copyExternalResource() failed");
+ else
+ aLine.append(static_cast<const char*>(rDocBuffer.GetData()) + nCopyStart, nLen);
+ }
+ else
+ // Can copy it as-is.
+ aLine.append(static_cast<const char*>(rDocBuffer.GetData())
+ + rObject.GetDictionaryOffset(),
+ rObject.GetDictionaryLength());
+
+ aLine.append(">>\n");
+ }
+
+ if (filter::PDFStreamElement* pStream = rObject.GetStream())
+ {
+ aLine.append("stream\n");
+ SvMemoryStream& rStream = pStream->GetMemory();
+ aLine.append(static_cast<const char*>(rStream.GetData()), rStream.GetSize());
+ aLine.append("\nendstream\n");
+ }
+
+ if (filter::PDFArrayElement* pArray = rObject.GetArray())
+ {
+ aLine.append("[");
+
+ const std::vector<filter::PDFElement*>& rElements = pArray->GetElements();
+ bool bDone = false;
+ // Complex case: can't copy the array byte array as is, as it may contain references.
+ sal_uInt64 nCopyStart = 0;
+ for (const auto pElement : rElements)
+ {
+ auto pReference = dynamic_cast<filter::PDFReferenceElement*>(pElement);
+ if (pReference)
+ {
+ filter::PDFObjectElement* pReferenced = pReference->LookupObject();
+ if (pReferenced)
+ {
+ // Copy the referenced object.
+ sal_Int32 nRef
+ = copyExternalResource(rDocBuffer, *pReferenced, rCopiedResources);
+
+ sal_uInt64 nReferenceStart = pReference->GetObjectElement().GetLocation();
+ sal_uInt64 nReferenceEnd = pReference->GetOffset();
+ sal_uInt64 nOffset = 0;
+ if (nCopyStart == 0)
+ // Array start -> reference start.
+ nOffset = rObject.GetArrayOffset();
+ else
+ // Previous reference end -> reference start.
+ nOffset = nCopyStart;
+ aLine.append(static_cast<const char*>(rDocBuffer.GetData()) + nOffset,
+ nReferenceStart - nOffset);
+
+ // Write the updated reference.
+ aLine.append(" ");
+ aLine.append(nRef);
+ aLine.append(" 0 R");
+ // Start copying here next time.
+ nCopyStart = nReferenceEnd;
+
+ bDone = true;
+ }
+ }
+ }
+
+ if (bDone)
+ {
+ // Copy the last part here, in the complex case.
+ sal_uInt64 nArrEnd = rObject.GetArrayOffset() + rObject.GetArrayLength();
+ const sal_Int32 nLen = nArrEnd - nCopyStart;
+ if (nLen < 0)
+ SAL_WARN("vcl.pdfwriter", "copyExternalResource() failed");
+ else
+ aLine.append(static_cast<const char*>(rDocBuffer.GetData()) + nCopyStart, nLen);
+ }
+ else
+ // Can copy it as-is.
+ aLine.append(static_cast<const char*>(rDocBuffer.GetData()) + rObject.GetArrayOffset(),
+ rObject.GetArrayLength());
+
+ aLine.append("]\n");
+ }
+
+ // If the object has a number element outside a dictionary or array, copy that.
+ if (filter::PDFNumberElement* pNumber = rObject.GetNumberElement())
+ {
+ aLine.append(static_cast<const char*>(rDocBuffer.GetData()) + pNumber->GetLocation(),
+ pNumber->GetLength());
+ aLine.append("\n");
+ }
+
+ aLine.append("endobj\n\n");
+
+ // We have the whole object, now write it to the output.
+ if (!m_rContainer.updateObject(nObject))
+ return -1;
+ if (!m_rContainer.writeBuffer(aLine.getStr(), aLine.getLength()))
+ return -1;
+
+ return nObject;
+}
+
+OString PDFObjectCopier::copyExternalResources(filter::PDFObjectElement& rPage,
+ const OString& rKind,
+ std::map<sal_Int32, sal_Int32>& rCopiedResources)
+{
+ // A name - object ID map, IDs as they appear in our output, not the
+ // original ones.
+ std::map<OString, sal_Int32> aRet;
+
+ // Get the rKind subset of the resource dictionary.
+ std::map<OString, filter::PDFElement*> aItems;
+ if (auto pResources = dynamic_cast<filter::PDFDictionaryElement*>(rPage.Lookup("Resources")))
+ {
+ // Resources is a direct dictionary.
+ filter::PDFElement* pLookup = pResources->LookupElement(rKind);
+ if (auto pDictionary = dynamic_cast<filter::PDFDictionaryElement*>(pLookup))
+ {
+ // rKind is an inline dictionary.
+ aItems = pDictionary->GetItems();
+ }
+ else if (auto pReference = dynamic_cast<filter::PDFReferenceElement*>(pLookup))
+ {
+ // rKind refers to a dictionary.
+ filter::PDFObjectElement* pReferenced = pReference->LookupObject();
+ if (!pReferenced)
+ {
+ return OString();
+ }
+
+ aItems = pReferenced->GetDictionaryItems();
+ }
+ }
+ else if (filter::PDFObjectElement* pPageResources = rPage.LookupObject("Resources"))
+ {
+ // Resources is an indirect object.
+ filter::PDFElement* pValue = pPageResources->Lookup(rKind);
+ if (auto pDictionary = dynamic_cast<filter::PDFDictionaryElement*>(pValue))
+ // Kind is a direct dictionary.
+ aItems = pDictionary->GetItems();
+ else if (filter::PDFObjectElement* pObject = pPageResources->LookupObject(rKind))
+ // Kind is an indirect object.
+ aItems = pObject->GetDictionaryItems();
+ }
+ if (aItems.empty())
+ return OString();
+
+ SvMemoryStream& rDocBuffer = rPage.GetDocument().GetEditBuffer();
+
+ for (const auto& rItem : aItems)
+ {
+ // For each item copy it over to our output then insert it into aRet.
+ auto pReference = dynamic_cast<filter::PDFReferenceElement*>(rItem.second);
+ if (!pReference)
+ continue;
+
+ filter::PDFObjectElement* pValue = pReference->LookupObject();
+ if (!pValue)
+ continue;
+
+ // Then copying over an object copy its dictionary and its stream.
+ sal_Int32 nObject = copyExternalResource(rDocBuffer, *pValue, rCopiedResources);
+ aRet[rItem.first] = nObject;
+ }
+
+ // Build the dictionary entry string.
+ OStringBuffer sRet("/" + rKind + "<<");
+ for (const auto& rPair : aRet)
+ {
+ sRet.append("/")
+ .append(rPair.first)
+ .append(" ")
+ .append(OString::number(rPair.second))
+ .append(" 0 R");
+ }
+ sRet.append(">>");
+
+ return sRet.makeStringAndClear();
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 304ae011ee72..44c21afb2214 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -76,6 +76,7 @@
#include <bitmapwriteaccess.hxx>
#include <impglyphitem.hxx>
#include <pdf/XmpMetadata.hxx>
+#include <pdf/objectcopier.hxx>
#include "pdfwriter_impl.hxx"
@@ -8344,235 +8345,6 @@ void PDFWriterImpl::writeJPG( JPGEmit& rObject )
writeReferenceXObject(rObject.m_aReferenceXObject);
}
-sal_Int32 PDFWriterImpl::copyExternalResource(SvMemoryStream& rDocBuffer, filter::PDFObjectElement& rObject, std::map<sal_Int32, sal_Int32>& rCopiedResources)
-{
- auto it = rCopiedResources.find(rObject.GetObjectValue());
- if (it != rCopiedResources.end())
- // This resource was already copied once, nothing to do.
- return it->second;
-
- sal_Int32 nObject = createObject();
- // Remember what is the ID of this object in our output.
- rCopiedResources[rObject.GetObjectValue()] = nObject;
- SAL_INFO("vcl.pdfwriter", "PDFWriterImpl::copyExternalResource: " << rObject.GetObjectValue() << " -> " << nObject);
-
- OStringBuffer aLine;
- aLine.append(nObject);
- aLine.append(" 0 obj\n");
- if (rObject.GetDictionary())
- {
- aLine.append("<<");
-
- // Complex case: can't copy the dictionary byte array as is, as it may contain references.
- bool bDone = false;
- sal_uInt64 nCopyStart = 0;
- for (auto pReference : rObject.GetDictionaryReferences())
- {
- if (pReference)
- {
- filter::PDFObjectElement* pReferenced = pReference->LookupObject();
- if (pReferenced)
- {
- // Copy the referenced object.
- sal_Int32 nRef = copyExternalResource(rDocBuffer, *pReferenced, rCopiedResources);
-
- sal_uInt64 nReferenceStart = pReference->GetObjectElement().GetLocation();
- sal_uInt64 nReferenceEnd = pReference->GetOffset();
- sal_uInt64 nOffset = 0;
- if (nCopyStart == 0)
- // Dict start -> reference start.
- nOffset = rObject.GetDictionaryOffset();
- else
- // Previous reference end -> reference start.
- nOffset = nCopyStart;
- aLine.append(static_cast<const char*>(rDocBuffer.GetData()) + nOffset, nReferenceStart - nOffset);
- // Write the updated reference.
- aLine.append(" ");
- aLine.append(nRef);
- aLine.append(" 0 R");
- // Start copying here next time.
- nCopyStart = nReferenceEnd;
-
- bDone = true;
- }
- }
- }
-
- if (bDone)
- {
- // Copy the last part here, in the complex case.
- sal_uInt64 nDictEnd = rObject.GetDictionaryOffset() + rObject.GetDictionaryLength();
- const sal_Int32 nLen = nDictEnd - nCopyStart;
- if (nLen < 0)
- SAL_WARN("vcl.pdfwriter", "copyExternalResource() failed");
- else
- aLine.append(static_cast<const char*>(rDocBuffer.GetData()) + nCopyStart, nLen);
- }
- else
- // Can copy it as-is.
- aLine.append(static_cast<const char*>(rDocBuffer.GetData()) + rObject.GetDictionaryOffset(), rObject.GetDictionaryLength());
-
- aLine.append(">>\n");
- }
-
- if (filter::PDFStreamElement* pStream = rObject.GetStream())
- {
- aLine.append("stream\n");
- SvMemoryStream& rStream = pStream->GetMemory();
- aLine.append(static_cast<const char*>(rStream.GetData()), rStream.GetSize());
- aLine.append("\nendstream\n");
- }
-
- if (filter::PDFArrayElement* pArray = rObject.GetArray())
- {
- aLine.append("[");
-
- const std::vector<filter::PDFElement*>& rElements = pArray->GetElements();
- bool bDone = false;
- // Complex case: can't copy the array byte array as is, as it may contain references.
- sal_uInt64 nCopyStart = 0;
- for (const auto pElement : rElements)
- {
- auto pReference = dynamic_cast<filter::PDFReferenceElement*>(pElement);
- if (pReference)
- {
- filter::PDFObjectElement* pReferenced = pReference->LookupObject();
- if (pReferenced)
- {
- // Copy the referenced object.
- sal_Int32 nRef = copyExternalResource(rDocBuffer, *pReferenced, rCopiedResources);
-
- sal_uInt64 nReferenceStart = pReference->GetObjectElement().GetLocation();
- sal_uInt64 nReferenceEnd = pReference->GetOffset();
- sal_uInt64 nOffset = 0;
- if (nCopyStart == 0)
- // Array start -> reference start.
- nOffset = rObject.GetArrayOffset();
- else
- // Previous reference end -> reference start.
- nOffset = nCopyStart;
- aLine.append(static_cast<const char*>(rDocBuffer.GetData()) + nOffset, nReferenceStart - nOffset);
-
- // Write the updated reference.
- aLine.append(" ");
- aLine.append(nRef);
- aLine.append(" 0 R");
- // Start copying here next time.
- nCopyStart = nReferenceEnd;
-
- bDone = true;
- }
- }
- }
-
- if (bDone)
- {
- // Copy the last part here, in the complex case.
- sal_uInt64 nArrEnd = rObject.GetArrayOffset() + rObject.GetArrayLength();
- const sal_Int32 nLen = nArrEnd - nCopyStart;
- if (nLen < 0)
- SAL_WARN("vcl.pdfwriter", "copyExternalResource() failed");
- else
- aLine.append(static_cast<const char*>(rDocBuffer.GetData()) + nCopyStart, nLen);
- }
- else
- // Can copy it as-is.
- aLine.append(static_cast<const char*>(rDocBuffer.GetData()) + rObject.GetArrayOffset(), rObject.GetArrayLength());
-
- aLine.append("]\n");
- }
-
- // If the object has a number element outside a dictionary or array, copy that.
- if (filter::PDFNumberElement* pNumber = rObject.GetNumberElement())
- {
- aLine.append(static_cast<const char*>(rDocBuffer.GetData()) + pNumber->GetLocation(), pNumber->GetLength());
- aLine.append("\n");
- }
-
-
- aLine.append("endobj\n\n");
-
- // We have the whole object, now write it to the output.
- if (!updateObject(nObject))
- return -1;
- if (!writeBuffer(aLine.getStr(), aLine.getLength()))
- return -1;
-
- return nObject;
-}
-
-OString PDFWriterImpl::copyExternalResources(filter::PDFObjectElement& rPage, const OString& rKind, std::map<sal_Int32, sal_Int32>& rCopiedResources)
-{
- // A name - object ID map, IDs as they appear in our output, not the
- // original ones.
- std::map<OString, sal_Int32> aRet;
-
- // Get the rKind subset of the resource dictionary.
- std::map<OString, filter::PDFElement*> aItems;
- if (auto pResources = dynamic_cast<filter::PDFDictionaryElement*>(rPage.Lookup("Resources")))
- {
- // Resources is a direct dictionary.
- filter::PDFElement* pLookup = pResources->LookupElement(rKind);
- if (auto pDictionary = dynamic_cast<filter::PDFDictionaryElement*>(pLookup))
- {
- // rKind is an inline dictionary.
- aItems = pDictionary->GetItems();
- }
- else if (auto pReference = dynamic_cast<filter::PDFReferenceElement*>(pLookup))
- {
- // rKind refers to a dictionary.
- filter::PDFObjectElement* pReferenced = pReference->LookupObject();
- if (!pReferenced)
- {
- return OString();
- }
-
- aItems = pReferenced->GetDictionaryItems();
- }
- }
- else if (filter::PDFObjectElement* pPageResources = rPage.LookupObject("Resources"))
- {
- // Resources is an indirect object.
- filter::PDFElement* pValue = pPageResources->Lookup(rKind);
- if (auto pDictionary = dynamic_cast<filter::PDFDictionaryElement*>(pValue))
- // Kind is a direct dictionary.
- aItems = pDictionary->GetItems();
- else if (filter::PDFObjectElement* pObject = pPageResources->LookupObject(rKind))
- // Kind is an indirect object.
- aItems = pObject->GetDictionaryItems();
- }
- if (aItems.empty())
- return OString();
-
- SvMemoryStream& rDocBuffer = rPage.GetDocument().GetEditBuffer();
-
- for (const auto& rItem : aItems)
- {
- // For each item copy it over to our output then insert it into aRet.
- auto pReference = dynamic_cast<filter::PDFReferenceElement*>(rItem.second);
- if (!pReference)
- continue;
-
- filter::PDFObjectElement* pValue = pReference->LookupObject();
- if (!pValue)
- continue;
-
- // Then copying over an object copy its dictionary and its stream.
- sal_Int32 nObject = copyExternalResource(rDocBuffer, *pValue, rCopiedResources);
- aRet[rItem.first] = nObject;
- }
-
- // Build the dictionary entry string.
- OStringBuffer sRet("/" + rKind + "<<");
- for (const auto& rPair : aRet)
- {
- sRet.append("/").append(rPair.first).append(" ").append(OString::number(rPair.second)).append(" 0 R");
- }
- sRet.append(">>");
-
- return sRet.makeStringAndClear();
-}
-
void PDFWriterImpl::writeReferenceXObject(ReferenceXObjectEmit& rEmit)
{
if (rEmit.m_nFormObject <= 0)
@@ -8694,8 +8466,9 @@ void PDFWriterImpl::writeReferenceXObject(ReferenceXObjectEmit& rEmit)
"XObject",
"Shading"
};
+ PDFObjectCopier aCopier(*this);
for (const auto& rKey : aKeys)
- aLine.append(copyExternalResources(*pPage, rKey, aCopiedResources));
+ aLine.append(aCopier.copyExternalResources(*pPage, rKey, aCopiedResources));
aLine.append(">>");
aLine.append(" /BBox [ 0 0 ");
aLine.append(nWidth);
diff --git a/vcl/source/gdi/pdfwriter_impl.hxx b/vcl/source/gdi/pdfwriter_impl.hxx
index 6261a391ba3c..4aaa6c873ce1 100644
--- a/vcl/source/gdi/pdfwriter_impl.hxx
+++ b/vcl/source/gdi/pdfwriter_impl.hxx
@@ -51,6 +51,7 @@
#include <tools/stream.hxx>
#include <outdata.hxx>
+#include <pdf/objectcontainer.hxx>
#include "pdffontcache.hxx"
#include "pdfbuildin_fonts.hxx"
@@ -609,7 +610,7 @@ enum class Mode { DEFAULT, NOWRITE };
}
-class PDFWriterImpl : public VirtualDevice
+class PDFWriterImpl : public VirtualDevice, public PDFObjectContainer
{
friend class PDFStreamIf;
@@ -816,12 +817,6 @@ i12626
void writeJPG( JPGEmit& rEmit );
/// Writes the form XObject proxy for the image.
void writeReferenceXObject(ReferenceXObjectEmit& rEmit);
- /// Copies resources of a given kind from an external page to the output,
- /// returning what has to be included in the new resource dictionary.
- OString copyExternalResources(filter::PDFObjectElement& rPage, const OString& rKind, std::map<sal_Int32, sal_Int32>& rCopiedResources);
- /// Copies a single resource from an external document, returns the new
- /// object ID in our document.
- sal_Int32 copyExternalResource(SvMemoryStream& rDocBuffer, filter::PDFObjectElement& rObject, std::map<sal_Int32, sal_Int32>& rCopiedResources);
/* tries to find the bitmap by its id and returns its emit data if exists,
else creates a new emit data block */
@@ -949,15 +944,12 @@ i12626
/* ensure proper escapement and uniqueness of field names */
void createWidgetFieldName( sal_Int32 i_nWidgetsIndex, const PDFWriter::AnyWidget& i_rInWidget );
- /* adds an entry to m_aObjects and returns its index+1,
- * sets the offset to ~0
- */
- sal_Int32 createObject();
- /* sets the offset of object n to the current position of output file+1
- */
- bool updateObject( sal_Int32 n );
+ /// See vcl::PDFObjectContainer::createObject().
+ sal_Int32 createObject() override;
+ /// See vcl::PDFObjectContainer::updateObject().
+ bool updateObject( sal_Int32 n ) override;
- bool writeBuffer( const void* pBuffer, sal_uInt64 nBytes );
+ bool writeBuffer( const void* pBuffer, sal_uInt64 nBytes ) override;
void beginCompression();
void endCompression();
void beginRedirect( SvStream* pStream, const tools::Rectangle& );