[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