summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.co.uk>2017-03-28 16:14:11 +0200
committerMiklos Vajna <vmiklos@collabora.co.uk>2017-03-28 15:52:49 +0000
commit30608c66374f8effa9d534f7f9a22d41daa9770f (patch)
tree9298896890717507fe01cdaf4545775d5b1010ca /vcl
parentb566f0d68804e97f9c73d1cc2beed568a4b74105 (diff)
tdf#106693 vcl PDF export, norefxobj: handle multiple refs in copied arrays
Also fix confusion about dictionaries in arrays and arrays in dictionaries. Change-Id: I0d71d5796b1eb4f89e3fd9a5b1f807d2a7340a35 Reviewed-on: https://gerrit.libreoffice.org/35806 Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk> Tested-by: Jenkins <ci@libreoffice.org>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/source/filter/ipdf/pdfdocument.cxx34
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx31
2 files changed, 48 insertions, 17 deletions
diff --git a/vcl/source/filter/ipdf/pdfdocument.cxx b/vcl/source/filter/ipdf/pdfdocument.cxx
index 1c132353e0a6..86aeade27137 100644
--- a/vcl/source/filter/ipdf/pdfdocument.cxx
+++ b/vcl/source/filter/ipdf/pdfdocument.cxx
@@ -939,7 +939,7 @@ bool PDFDocument::Tokenize(SvStream& rStream, TokenizeMode eMode, std::vector< s
}
case '[':
{
- auto pArr = new PDFArrayElement();
+ auto pArr = new PDFArrayElement(pObject);
rElements.push_back(std::unique_ptr<PDFElement>(pArr));
if (nDictionaryDepth == 0 && nArrayDepth == 0)
{
@@ -963,9 +963,10 @@ bool PDFDocument::Tokenize(SvStream& rStream, TokenizeMode eMode, std::vector< s
case ']':
{
rElements.push_back(std::unique_ptr<PDFElement>(new PDFEndArrayElement()));
- pArray = nullptr;
- rStream.SeekRel(-1);
--nArrayDepth;
+ if (nArrayDepth == 0)
+ pArray = nullptr;
+ rStream.SeekRel(-1);
if (nDictionaryDepth == 0 && nArrayDepth == 0)
{
if (pObject)
@@ -2127,18 +2128,25 @@ size_t PDFDictionaryElement::Parse(const std::vector< std::unique_ptr<PDFElement
PDFArrayElement* pArray = nullptr;
sal_uInt64 nDictionaryOffset = 0;
int nDictionaryDepth = 0;
+ // Toplevel dictionary found (not inside an array).
+ bool bDictionaryFound = false;
+ // Toplevel array found (not inside a dictionary).
+ bool bArrayFound = false;
for (size_t i = nIndex; i < rElements.size(); ++i)
{
// Dictionary tokens can be nested, track enter/leave.
if (auto pDictionary = dynamic_cast<PDFDictionaryElement*>(rElements[i].get()))
{
+ bDictionaryFound = true;
if (++nDictionaryDepth == 1)
{
// First dictionary start, track start offset.
nDictionaryOffset = pDictionary->m_nLocation;
if (pThisObject)
{
- pThisObject->SetDictionary(pDictionary);
+ if (!bArrayFound)
+ // The the toplevel dictionary of the object.
+ pThisObject->SetDictionary(pDictionary);
pThisDictionary = pDictionary;
pThisObject->SetDictionaryOffset(nDictionaryOffset);
}
@@ -2189,7 +2197,11 @@ size_t PDFDictionaryElement::Parse(const std::vector< std::unique_ptr<PDFElement
else
{
if (pArray)
- pArray->PushBack(pName);
+ {
+ if (bDictionaryFound)
+ // Array inside dictionary.
+ pArray->PushBack(pName);
+ }
else
{
// Name-name key-value.
@@ -2208,6 +2220,7 @@ size_t PDFDictionaryElement::Parse(const std::vector< std::unique_ptr<PDFElement
auto pArr = dynamic_cast<PDFArrayElement*>(rElements[i].get());
if (pArr)
{
+ bArrayFound = true;
pArray = pArr;
continue;
}
@@ -2248,7 +2261,9 @@ size_t PDFDictionaryElement::Parse(const std::vector< std::unique_ptr<PDFElement
}
else
{
- pArray->PushBack(pReference);
+ if (bDictionaryFound)
+ // Array inside dictionary.
+ pArray->PushBack(pReference);
}
aNumbers.clear();
continue;
@@ -2932,7 +2947,10 @@ bool PDFEndObjectElement::Read(SvStream& /*rStream*/)
return true;
}
-PDFArrayElement::PDFArrayElement() = default;
+PDFArrayElement::PDFArrayElement(PDFObjectElement* pObject)
+ : m_pObject(pObject)
+{
+}
bool PDFArrayElement::Read(SvStream& rStream)
{
@@ -2952,6 +2970,8 @@ bool PDFArrayElement::Read(SvStream& rStream)
void PDFArrayElement::PushBack(PDFElement* pElement)
{
+ if (m_pObject)
+ SAL_INFO("vcl.filter", "PDFArrayElement::PushBack: object is " << m_pObject->GetObjectValue());
m_aElements.push_back(pElement);
}
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 000e2875d95b..4b8b9542b46a 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -10855,6 +10855,7 @@ void PDFWriterImpl::writeJPG( JPGEmit& rObject )
sal_Int32 PDFWriterImpl::copyExternalResource(SvMemoryStream& rDocBuffer, filter::PDFObjectElement& rObject)
{
sal_Int32 nObject = createObject();
+ SAL_INFO("vcl.pdfwriter", "PDFWriterImpl::copyExternalResource: " << rObject.GetObjectValue() << " -> " << nObject);
OStringBuffer aLine;
aLine.append(nObject);
@@ -10927,7 +10928,8 @@ sal_Int32 PDFWriterImpl::copyExternalResource(SvMemoryStream& rDocBuffer, filter
const std::vector<filter::PDFElement*>& rElements = pArray->GetElements();
bool bDone = false;
- // Complex case: can't copy the array byte array as is, as it contains a reference.
+ // 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);
@@ -10939,28 +10941,37 @@ sal_Int32 PDFWriterImpl::copyExternalResource(SvMemoryStream& rDocBuffer, filter
// Copy the referenced object.
sal_Int32 nRef = copyExternalResource(rDocBuffer, *pReferenced);
- sal_uInt64 nArrStart = rObject.GetArrayOffset();
sal_uInt64 nReferenceStart = pReference->GetObjectElement().GetLocation();
sal_uInt64 nReferenceEnd = pReference->GetOffset();
- sal_uInt64 nArrEnd = nArrStart + rObject.GetArrayLength();
+ 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 sal_Char*>(rDocBuffer.GetData()) + nOffset, nReferenceStart - nOffset);
- // Array start -> reference start.
- aLine.append(static_cast<const sal_Char*>(rDocBuffer.GetData()) + nArrStart, nReferenceStart - nArrStart);
// Write the updated reference.
aLine.append(" ");
aLine.append(nRef);
aLine.append(" 0 R");
- // Reference end -> array end.
- aLine.append(static_cast<const sal_Char*>(rDocBuffer.GetData()) + nReferenceEnd, nArrEnd - nReferenceEnd);
+ // Start copying here next time.
+ nCopyStart = nReferenceEnd;
bDone = true;
- break;
}
}
}
- // Can copy it as-is.
- if (!bDone)
+ if (bDone)
+ {
+ // Copy the last part here, in the complex case.
+ sal_uInt64 nArrEnd = rObject.GetArrayOffset() + rObject.GetArrayLength();
+ aLine.append(static_cast<const sal_Char*>(rDocBuffer.GetData()) + nCopyStart, nArrEnd - nCopyStart);
+ }
+ else
+ // Can copy it as-is.
aLine.append(static_cast<const sal_Char*>(rDocBuffer.GetData()) + rObject.GetArrayOffset(), rObject.GetArrayLength());
aLine.append("]\n");