vcl/Library_vcl.mk                 |    1 
 vcl/inc/pdf/objectcontainer.hxx    |   36 ++++
 vcl/inc/pdf/objectcopier.hxx       |   48 ++++++
 vcl/source/gdi/pdfobjectcopier.cxx |  273 +++++++++++++++++++++++++++++++++++++
 vcl/source/gdi/pdfwriter_impl.cxx  |  233 -------------------------------
 vcl/source/gdi/pdfwriter_impl.hxx  |   22 --
 6 files changed, 368 insertions(+), 245 deletions(-)

New commits:
commit 8277073ce3e33788d93b3df490a8f03d1814863b
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Thu Jun 18 12:12:52 2020 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Thu Jun 18 14:36:29 2020 +0200

    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 <vmik...@collabora.com>
    Tested-by: Jenkins

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& );
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to