diff options
-rw-r--r-- | include/vcl/filter/pdfdocument.hxx | 4 | ||||
-rw-r--r-- | vcl/source/filter/ipdf/pdfdocument.cxx | 29 | ||||
-rw-r--r-- | vcl/source/gdi/pdfwriter_impl.cxx | 36 |
3 files changed, 52 insertions, 17 deletions
diff --git a/include/vcl/filter/pdfdocument.hxx b/include/vcl/filter/pdfdocument.hxx index 9ccbb43d0225..d6b44e88d027 100644 --- a/include/vcl/filter/pdfdocument.hxx +++ b/include/vcl/filter/pdfdocument.hxx @@ -80,10 +80,12 @@ public: sal_uInt64 GetDictionaryOffset(); void SetDictionaryLength(sal_uInt64 nDictionaryLength); sal_uInt64 GetDictionaryLength(); - PDFDictionaryElement* GetDictionary() const; + PDFDictionaryElement* GetDictionary(); void SetDictionary(PDFDictionaryElement* pDictionaryElement); /// Get access to the parsed key-value items from the object dictionary. const std::map<OString, PDFElement*>& GetDictionaryItems() const; + /// Same as GetDictionaryItems(), but entries are sorted by file offset. + std::vector< std::pair<OString, PDFElement*> > GetDictionaryItemsByOffset(); void SetArray(PDFArrayElement* pArrayElement); void SetStream(PDFStreamElement* pStreamElement); /// Access to the stream of the object, if it has any. 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 "); |