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

Tomaž Vajngerl (via logerrit) logerrit at kemper.freedesktop.org
Sun Nov 22 23:50:30 UTC 2020


 vcl/inc/pdf/objectcopier.hxx       |    5 +
 vcl/source/gdi/pdfobjectcopier.cxx |  164 +++++++++++++------------------------
 2 files changed, 65 insertions(+), 104 deletions(-)

New commits:
commit 50bc6db73466121744848e04f21c934c3b596897
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Mon Nov 9 19:16:27 2020 +0100
Commit:     Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Mon Nov 23 00:49:51 2020 +0100

    pdf: improve PDFObjectCopier, copy arrays/dicts recursively
    
    Change-Id: Ia2f8d86ae012b530f3e9c39842bb75ef8ca27718
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105493
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>

diff --git a/vcl/inc/pdf/objectcopier.hxx b/vcl/inc/pdf/objectcopier.hxx
index 65dbbb49aef4..3880d739bb10 100644
--- a/vcl/inc/pdf/objectcopier.hxx
+++ b/vcl/inc/pdf/objectcopier.hxx
@@ -25,6 +25,7 @@ class PDFObjectContainer;
 namespace filter
 {
 class PDFObjectElement;
+class PDFElement;
 }
 
 /// Copies objects from one PDF file into another one.
@@ -32,6 +33,10 @@ class PDFObjectCopier
 {
     PDFObjectContainer& m_rContainer;
 
+    void copyRecursively(OStringBuffer& rLine, filter::PDFElement* pInputElement,
+                         SvMemoryStream& rDocBuffer,
+                         std::map<sal_Int32, sal_Int32>& rCopiedResources);
+
 public:
     PDFObjectCopier(PDFObjectContainer& rContainer);
 
diff --git a/vcl/source/gdi/pdfobjectcopier.cxx b/vcl/source/gdi/pdfobjectcopier.cxx
index 129a4c8bda35..d6323a17e91c 100644
--- a/vcl/source/gdi/pdfobjectcopier.cxx
+++ b/vcl/source/gdi/pdfobjectcopier.cxx
@@ -26,14 +26,62 @@ PDFObjectCopier::PDFObjectCopier(PDFObjectContainer& rContainer)
 {
 }
 
+void PDFObjectCopier::copyRecursively(OStringBuffer& rLine, filter::PDFElement* pInputElement,
+                                      SvMemoryStream& rDocBuffer,
+                                      std::map<sal_Int32, sal_Int32>& rCopiedResources)
+{
+    if (auto pReference = dynamic_cast<filter::PDFReferenceElement*>(pInputElement))
+    {
+        filter::PDFObjectElement* pReferenced = pReference->LookupObject();
+        if (pReferenced)
+        {
+            // Copy the referenced object.
+            sal_Int32 nRef = copyExternalResource(rDocBuffer, *pReferenced, rCopiedResources);
+
+            // Write the updated reference.
+            rLine.append(nRef);
+            rLine.append(" 0 R");
+        }
+    }
+    else if (auto pInputArray = dynamic_cast<filter::PDFArrayElement*>(pInputElement))
+    {
+        rLine.append("[ ");
+        for (auto const& pElement : pInputArray->GetElements())
+        {
+            copyRecursively(rLine, pElement, rDocBuffer, rCopiedResources);
+            rLine.append(" ");
+        }
+        rLine.append("] ");
+    }
+    else if (auto pInputDictionary = dynamic_cast<filter::PDFDictionaryElement*>(pInputElement))
+    {
+        rLine.append("<< ");
+        for (auto const& pPair : pInputDictionary->GetItems())
+        {
+            rLine.append("/");
+            rLine.append(pPair.first);
+            rLine.append(" ");
+            copyRecursively(rLine, pPair.second, rDocBuffer, rCopiedResources);
+            rLine.append(" ");
+        }
+        rLine.append(">> ");
+    }
+    else
+    {
+        pInputElement->writeString(rLine);
+    }
+}
+
 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.
@@ -50,62 +98,19 @@ sal_Int32 PDFObjectCopier::copyExternalResource(SvMemoryStream& rDocBuffer,
     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*>(pObjectStream->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;
-                }
-            }
-        }
+        aLine.append("<< ");
 
-        if (bDone)
+        for (auto const& rPair : rObject.GetDictionaryItems())
         {
-            // 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*>(pObjectStream->GetData()) + nCopyStart, nLen);
+            aLine.append("/");
+            aLine.append(rPair.first);
+            aLine.append(" ");
+            copyRecursively(aLine, rPair.second, rDocBuffer, rCopiedResources);
+            aLine.append(" ");
         }
-        else
-            // Can copy it as-is.
-            aLine.append(static_cast<const char*>(pObjectStream->GetData())
-                             + rObject.GetDictionaryOffset(),
-                         rObject.GetDictionaryLength());
 
         aLine.append(">>\n");
     }
@@ -120,64 +125,15 @@ sal_Int32 PDFObjectCopier::copyExternalResource(SvMemoryStream& rDocBuffer,
 
     if (filter::PDFArrayElement* pArray = rObject.GetArray())
     {
-        aLine.append("[");
+        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*>(pObjectStream->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)
+        for (auto const& pElement : rElements)
         {
-            // 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*>(pObjectStream->GetData()) + nCopyStart, nLen);
+            copyRecursively(aLine, pElement, rDocBuffer, rCopiedResources);
+            aLine.append(" ");
         }
-        else
-            // Can copy it as-is.
-            aLine.append(static_cast<const char*>(pObjectStream->GetData())
-                             + rObject.GetArrayOffset(),
-                         rObject.GetArrayLength());
-
         aLine.append("]\n");
     }
 


More information about the Libreoffice-commits mailing list