summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.co.uk>2017-03-27 15:39:04 +0200
committerMiklos Vajna <vmiklos@collabora.co.uk>2017-03-27 15:31:13 +0000
commit2ba9d58d5978c94352c4c6cf9c47aa3de79d05fe (patch)
tree6a17246ed941468bdb59ba0f8642cbff50ad9251 /vcl
parent4bb389319ec4510e16a519d229a452211112a04f (diff)
tdf#106693 vcl PDF export, norefxobj: handle multiple refs in copied dicts
When copying font definitions the dictionary has multiple values where the type is a reference. Improve PDFWriterImpl::copyExternalResource(), so that multiple references are copied correctly as well. With this the bugdoc (from comment 5) text appears in the output. Change-Id: I2343e616d8b36e3cdcbd4e713bd3f7fa7bce6d3b Reviewed-on: https://gerrit.libreoffice.org/35760 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.cxx29
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx36
2 files changed, 49 insertions, 16 deletions
diff --git a/vcl/source/filter/ipdf/pdfdocument.cxx b/vcl/source/filter/ipdf/pdfdocument.cxx
index 926ebb0500fd..1a85c4f3fd5e 100644
--- a/vcl/source/filter/ipdf/pdfdocument.cxx
+++ b/vcl/source/filter/ipdf/pdfdocument.cxx
@@ -1933,7 +1933,7 @@ bool PDFNumberElement::Read(SvStream& rStream)
return false;
}
if (!rtl::isAsciiDigit(static_cast<unsigned char>(ch)) && ch != '-'
- && ch != '.')
+ && ch != '.')
{
rStream.SeekRel(-1);
return false;
@@ -1941,7 +1941,7 @@ bool PDFNumberElement::Read(SvStream& rStream)
while (!rStream.IsEof())
{
if (!rtl::isAsciiDigit(static_cast<unsigned char>(ch)) && ch != '-'
- && ch != '.')
+ && ch != '.')
{
rStream.SeekRel(-1);
m_nLength = rStream.Tell() - m_nOffset;
@@ -2446,8 +2446,10 @@ sal_uInt64 PDFObjectElement::GetArrayLength()
return m_nArrayLength;
}
-PDFDictionaryElement* PDFObjectElement::GetDictionary() const
+PDFDictionaryElement* PDFObjectElement::GetDictionary()
{
+ if (m_aDictionary.empty())
+ PDFDictionaryElement::Parse(m_rDoc.GetElements(), this, m_aDictionary);
return m_pDictionaryElement;
}
@@ -2456,6 +2458,25 @@ void PDFObjectElement::SetDictionary(PDFDictionaryElement* pDictionaryElement)
m_pDictionaryElement = pDictionaryElement;
}
+std::vector< std::pair<OString, PDFElement*> > PDFObjectElement::GetDictionaryItemsByOffset()
+{
+ std::vector< std::pair<OString, PDFElement*> > aRet;
+
+ for (const auto& rItem : m_aDictionary)
+ aRet.push_back(rItem);
+
+ PDFDictionaryElement* pDictionary = GetDictionary();
+ if (!pDictionary)
+ return aRet;
+
+ std::sort(aRet.begin(), aRet.end(), [pDictionary](const std::pair<OString, PDFElement*>& a, const std::pair<OString, PDFElement*>& b) -> bool
+ {
+ return pDictionary->GetKeyOffset(a.first) < pDictionary->GetKeyOffset(b.first);
+ });
+
+ return aRet;
+}
+
const std::map<OString, PDFElement*>& PDFObjectElement::GetDictionaryItems() const
{
return m_aDictionary;
@@ -2841,7 +2862,7 @@ bool PDFNameElement::Read(SvStream& rStream)
while (!rStream.IsEof())
{
if (rtl::isAsciiWhiteSpace(static_cast<unsigned char>(ch)) || ch == '/'
- || ch == '[' || ch == ']' || ch == '<' || ch == '>' || ch == '(')
+ || ch == '[' || ch == ']' || ch == '<' || ch == '>' || ch == '(')
{
rStream.SeekRel(-1);
m_aValue = aBuf.makeStringAndClear();
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index eb9d00cac010..7d435e404837 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -10863,10 +10863,11 @@ sal_Int32 PDFWriterImpl::copyExternalResource(SvMemoryStream& rDocBuffer, filter
{
aLine.append("<<");
- // Complex case: can't copy the dictionary byte array as is, as it contains a reference.
+ // Complex case: can't copy the dictionary byte array as is, as it may contain references.
bool bDone = false;
- const std::map<OString, filter::PDFElement*>& rItems = rObject.GetDictionaryItems();
- for (const auto& rItem : rItems)
+ std::vector< std::pair<OString, filter::PDFElement*> > aItems = rObject.GetDictionaryItemsByOffset();
+ sal_uInt64 nCopyStart = 0;
+ for (const auto& rItem : aItems)
{
auto pReference = dynamic_cast<filter::PDFReferenceElement*>(rItem.second);
if (pReference)
@@ -10877,27 +10878,36 @@ sal_Int32 PDFWriterImpl::copyExternalResource(SvMemoryStream& rDocBuffer, filter
// Copy the referenced object.
sal_Int32 nRef = copyExternalResource(rDocBuffer, *pReferenced);
- sal_uInt64 nDictStart = rObject.GetDictionaryOffset();
sal_uInt64 nReferenceStart = pDictionary->GetKeyOffset(rItem.first) + rItem.first.getLength();
sal_uInt64 nReferenceEnd = pDictionary->GetKeyOffset(rItem.first) + pDictionary->GetKeyValueLength(rItem.first);
- sal_uInt64 nDictEnd = nDictStart + rObject.GetDictionaryLength();
- // Dict start -> reference start.
- aLine.append(static_cast<const sal_Char*>(rDocBuffer.GetData()) + nDictStart, nReferenceStart - nDictStart);
+ 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 sal_Char*>(rDocBuffer.GetData()) + nOffset, nReferenceStart - nOffset);
// Write the updated reference.
aLine.append(" ");
aLine.append(nRef);
aLine.append(" 0 R");
- // Reference end -> dict end.
- aLine.append(static_cast<const sal_Char*>(rDocBuffer.GetData()) + nReferenceEnd, nDictEnd - 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 nDictEnd = rObject.GetDictionaryOffset() + rObject.GetDictionaryLength();
+ aLine.append(static_cast<const sal_Char*>(rDocBuffer.GetData()) + nCopyStart, nDictEnd - nCopyStart);
+ }
+ else
+ // Can copy it as-is.
aLine.append(static_cast<const sal_Char*>(rDocBuffer.GetData()) + rObject.GetDictionaryOffset(), rObject.GetDictionaryLength());
aLine.append(">>\n");
@@ -11057,6 +11067,7 @@ void PDFWriterImpl::writeReferenceXObject(ReferenceXObjectEmit& rEmit)
return;
}
+ OString sFonts = copyExternalResources(*pPage, "Font");
OString sXObjects = copyExternalResources(*pPage, "XObject");
filter::PDFObjectElement* pPageContents = pPage->LookupObject("Contents");
@@ -11078,6 +11089,7 @@ void PDFWriterImpl::writeReferenceXObject(ReferenceXObjectEmit& rEmit)
aLine.append("<< /Type /XObject");
aLine.append(" /Subtype /Form");
aLine.append(" /Resources <<");
+ aLine.append(sFonts);
aLine.append(sXObjects);
aLine.append(">>");
aLine.append(" /BBox [ 0 0 ");