[Libreoffice-commits] core.git: vcl/source
Miklos Vajna
vmiklos at collabora.co.uk
Thu Mar 23 15:59:40 UTC 2017
vcl/source/gdi/pdfwriter_impl.cxx | 126 +++++++++++++++++++++++++-------------
1 file changed, 84 insertions(+), 42 deletions(-)
New commits:
commit d0c24cbb027130f3781bfc3475dd225190afd560
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date: Thu Mar 23 14:26:42 2017 +0100
tdf#106693 vcl PDF export, norefxobj: handle compressed page stream
Since we want to avoid re-compressing the page stream create two form
XObjects: one that resets the graphic state to the default (e.g. line
width) and an other one that contains the original page stream as-is.
With this PDF images where the page stream is compressed are handled
correctly.
Change-Id: Ib44dae2e167e4d5604a0a3a3cf91e09795137343
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 9e40b3fe5539..597b6996d6fe 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -10863,10 +10863,6 @@ void PDFWriterImpl::writeReferenceXObject(ReferenceXObjectEmit& rEmit)
if (rEmit.m_nFormObject <= 0)
return;
- OStringBuffer aLine;
- if (!updateObject(rEmit.m_nFormObject))
- return;
-
// Count /Matrix and /BBox.
// vcl::ImportPDF() works with 96 DPI so use the same values here, too.
sal_Int32 nOldDPIX = getReferenceDevice()->GetDPIX();
@@ -10879,15 +10875,92 @@ void PDFWriterImpl::writeReferenceXObject(ReferenceXObjectEmit& rEmit)
double fScaleX = 1.0 / aSize.Width();
double fScaleY = 1.0 / aSize.Height();
+ sal_Int32 nWrappedFormObject = 0;
+ if (!m_aContext.UseReferenceXObject)
+ {
+ nWrappedFormObject = createObject();
+ // Write the form XObject wrapped below. This is a separate object from
+ // the wrapper, this way there is no need to alter the stream contents.
+ if (!updateObject(nWrappedFormObject))
+ return;
+
+ // Parse the PDF data, we need that to write the PDF dictionary of our
+ // object.
+ SvMemoryStream aPDFStream;
+ aPDFStream.WriteBytes(rEmit.m_aPDFData.getArray(), rEmit.m_aPDFData.getLength());
+ aPDFStream.Seek(0);
+ filter::PDFDocument aPDFDocument;
+ if (!aPDFDocument.Read(aPDFStream))
+ {
+ SAL_WARN("vcl.pdfwriter", "PDFWriterImpl::writeReferenceXObject: reading the PDF document failed");
+ return;
+ }
+ std::vector<filter::PDFObjectElement*> aPages = aPDFDocument.GetPages();
+ if (aPages.empty() || !aPages[0])
+ {
+ SAL_WARN("vcl.pdfwriter", "PDFWriterImpl::writeReferenceXObject: no pages");
+ return;
+ }
+
+ filter::PDFObjectElement* pPageContents = aPages[0]->LookupObject("Contents");
+ if (!pPageContents)
+ {
+ SAL_WARN("vcl.pdfwriter", "PDFWriterImpl::writeReferenceXObject: page has no contents");
+ return;
+ }
+
+ OStringBuffer aLine;
+ aLine.append(nWrappedFormObject);
+ aLine.append(" 0 obj\n");
+ aLine.append("<< /Type /XObject");
+ aLine.append(" /Subtype /Form");
+ aLine.append(" /BBox [ 0 0 ");
+ aLine.append(aSize.Width());
+ aLine.append(" ");
+ aLine.append(aSize.Height());
+ aLine.append(" ]");
+
+ auto pFilter = dynamic_cast<filter::PDFNameElement*>(pPageContents->Lookup("Filter"));
+ if (pFilter)
+ {
+ aLine.append(" /Filter /");
+ aLine.append(pFilter->GetValue());
+ }
+
+ aLine.append(" /Length ");
+
+ filter::PDFStreamElement* pPageStream = pPageContents->GetStream();
+ if (!pPageStream)
+ {
+ SAL_WARN("vcl.pdfwriter", "PDFWriterImpl::writeReferenceXObject: contents has no stream");
+ return;
+ }
+
+ SvMemoryStream& rPageStream = pPageStream->GetMemory();
+
+ aLine.append(static_cast<sal_Int32>(rPageStream.GetSize()));
+
+ aLine.append(">>\nstream\n");
+ // Copy the original page stream to the form XObject stream.
+ aLine.append(static_cast<const sal_Char*>(rPageStream.GetData()), rPageStream.GetSize());
+ aLine.append("\nendstream\nendobj\n\n");
+ CHECK_RETURN2(writeBuffer(aLine.getStr(), aLine.getLength()));
+ }
+
+ OStringBuffer aLine;
+ if (!updateObject(rEmit.m_nFormObject))
+ return;
+
// Now have all the info to write the form XObject.
aLine.append(rEmit.m_nFormObject);
aLine.append(" 0 obj\n");
aLine.append("<< /Type /XObject");
aLine.append(" /Subtype /Form");
aLine.append(" /Resources << /XObject<</Im");
- aLine.append(rEmit.m_nBitmapObject);
+ sal_Int32 nObject = m_aContext.UseReferenceXObject ? rEmit.m_nBitmapObject : nWrappedFormObject;
+ aLine.append(nObject);
aLine.append(" ");
- aLine.append(rEmit.m_nBitmapObject);
+ aLine.append(nObject);
aLine.append(" 0 R>> >>");
aLine.append(" /Matrix [ ");
appendDouble(fScaleX, aLine);
@@ -10926,44 +10999,13 @@ void PDFWriterImpl::writeReferenceXObject(ReferenceXObjectEmit& rEmit)
}
else
{
- // No reference XObject, include the original page stream.
// Reset line width to the default.
aStream.append(" 1 w\n");
- SvMemoryStream aPDFStream;
- aPDFStream.WriteBytes(rEmit.m_aPDFData.getArray(), rEmit.m_aPDFData.getLength());
- aPDFStream.Seek(0);
- filter::PDFDocument aPDFDocument;
- if (!aPDFDocument.Read(aPDFStream))
- {
- SAL_WARN("vcl.pdfwriter", "PDFWriterImpl::writeReferenceXObject: reading the PDF document failed");
- return;
- }
- std::vector<filter::PDFObjectElement*> aPages = aPDFDocument.GetPages();
- if (aPages.empty() || !aPages[0])
- {
- SAL_WARN("vcl.pdfwriter", "PDFWriterImpl::writeReferenceXObject: no pages");
- return;
- }
-
- filter::PDFObjectElement* pPageContents = aPages[0]->LookupObject("Contents");
- if (!pPageContents)
- {
- SAL_WARN("vcl.pdfwriter", "PDFWriterImpl::writeReferenceXObject: page has no contents");
- return;
- }
-
- filter::PDFStreamElement* pPageStream = pPageContents->GetStream();
- if (!pPageStream)
- {
- SAL_WARN("vcl.pdfwriter", "PDFWriterImpl::writeReferenceXObject: contents has no stream");
- return;
- }
-
- SvMemoryStream& rPageStream = pPageStream->GetMemory();
-
- // Copy the original page stream to the end of the form XObject stream.
- aStream.append(static_cast<const sal_Char*>(rPageStream.GetData()), rPageStream.GetSize());
- aStream.append("\n");
+ // No reference XObject, draw the form XObject containing the original
+ // page stream.
+ aStream.append("/Im");
+ aStream.append(nWrappedFormObject);
+ aStream.append(" Do\n");
}
aStream.append("Q");
aLine.append(aStream.getLength());
More information about the Libreoffice-commits
mailing list