Commit 95a45263878f33a84afba7cd7826c8dc1ea5a5b5
Committed by
GitHub
Merge pull request #1404 from m-holger/writer
Refactor writing of object streams
Showing
2 changed files
with
40 additions
and
35 deletions
libqpdf/QPDFWriter.cc
| @@ -1646,36 +1646,12 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) | @@ -1646,36 +1646,12 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) | ||
| 1646 | std::shared_ptr<Buffer> stream_buffer; | 1646 | std::shared_ptr<Buffer> stream_buffer; |
| 1647 | int first_obj = -1; | 1647 | int first_obj = -1; |
| 1648 | bool compressed = false; | 1648 | bool compressed = false; |
| 1649 | - for (int pass = 1; pass <= 2; ++pass) { | ||
| 1650 | - // stream_buffer will be initialized only for pass 2 | ||
| 1651 | - PipelinePopper pp_ostream(this, &stream_buffer); | ||
| 1652 | - if (pass == 1) { | ||
| 1653 | - pushDiscardFilter(pp_ostream); | ||
| 1654 | - } else { | ||
| 1655 | - // Adjust offsets to skip over comment before first object | ||
| 1656 | - first = offsets.at(0); | ||
| 1657 | - for (auto& iter: offsets) { | ||
| 1658 | - iter -= first; | ||
| 1659 | - } | ||
| 1660 | - | ||
| 1661 | - // Take one pass at writing pairs of numbers so we can get their size information | ||
| 1662 | - { | ||
| 1663 | - PipelinePopper pp_discard(this); | ||
| 1664 | - pushDiscardFilter(pp_discard); | ||
| 1665 | - writeObjectStreamOffsets(offsets, first_obj); | ||
| 1666 | - first += m->pipeline->getCount(); | ||
| 1667 | - } | 1649 | + { |
| 1650 | + // Pass 1 | ||
| 1651 | + PipelinePopper pp_ostream_pass1(this, &stream_buffer); | ||
| 1668 | 1652 | ||
| 1669 | - // Set up a stream to write the stream data into a buffer. | ||
| 1670 | - Pipeline* next = pushPipeline(new Pl_Buffer("object stream")); | ||
| 1671 | - if (m->compress_streams && !m->qdf_mode) { | ||
| 1672 | - compressed = true; | ||
| 1673 | - next = | ||
| 1674 | - pushPipeline(new Pl_Flate("compress object stream", next, Pl_Flate::a_deflate)); | ||
| 1675 | - } | ||
| 1676 | - activatePipelineStack(pp_ostream); | ||
| 1677 | - writeObjectStreamOffsets(offsets, first_obj); | ||
| 1678 | - } | 1653 | + pushPipeline(new Pl_Buffer("object stream")); |
| 1654 | + activatePipelineStack(pp_ostream_pass1); | ||
| 1679 | 1655 | ||
| 1680 | int count = -1; | 1656 | int count = -1; |
| 1681 | for (auto const& obj: m->object_stream_to_objects[old_id]) { | 1657 | for (auto const& obj: m->object_stream_to_objects[old_id]) { |
| @@ -1700,12 +1676,12 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) | @@ -1700,12 +1676,12 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) | ||
| 1700 | } | 1676 | } |
| 1701 | writeString("\n"); | 1677 | writeString("\n"); |
| 1702 | } | 1678 | } |
| 1703 | - if (pass == 1) { | ||
| 1704 | - offsets.push_back(m->pipeline->getCount()); | ||
| 1705 | - // To avoid double-counting objects being written in object streams for progress | ||
| 1706 | - // reporting, decrement in pass 1. | ||
| 1707 | - indicateProgress(true, false); | ||
| 1708 | - } | 1679 | + |
| 1680 | + offsets.push_back(m->pipeline->getCount()); | ||
| 1681 | + // To avoid double-counting objects being written in object streams for progress | ||
| 1682 | + // reporting, decrement in pass 1. | ||
| 1683 | + indicateProgress(true, false); | ||
| 1684 | + | ||
| 1709 | QPDFObjectHandle obj_to_write = m->pdf.getObject(obj); | 1685 | QPDFObjectHandle obj_to_write = m->pdf.getObject(obj); |
| 1710 | if (obj_to_write.isStream()) { | 1686 | if (obj_to_write.isStream()) { |
| 1711 | // This condition occurred in a fuzz input. Ideally we should block it at parse | 1687 | // This condition occurred in a fuzz input. Ideally we should block it at parse |
| @@ -1718,6 +1694,32 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) | @@ -1718,6 +1694,32 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) | ||
| 1718 | m->new_obj[new_obj].xref = QPDFXRefEntry(new_stream_id, count); | 1694 | m->new_obj[new_obj].xref = QPDFXRefEntry(new_stream_id, count); |
| 1719 | } | 1695 | } |
| 1720 | } | 1696 | } |
| 1697 | + { | ||
| 1698 | + PipelinePopper pp_ostream(this, &stream_buffer); | ||
| 1699 | + // Adjust offsets to skip over comment before first object | ||
| 1700 | + first = offsets.at(0); | ||
| 1701 | + for (auto& iter: offsets) { | ||
| 1702 | + iter -= first; | ||
| 1703 | + } | ||
| 1704 | + | ||
| 1705 | + // Take one pass at writing pairs of numbers so we can get their size information | ||
| 1706 | + { | ||
| 1707 | + PipelinePopper pp_discard(this); | ||
| 1708 | + pushDiscardFilter(pp_discard); | ||
| 1709 | + writeObjectStreamOffsets(offsets, first_obj); | ||
| 1710 | + first += m->pipeline->getCount(); | ||
| 1711 | + } | ||
| 1712 | + | ||
| 1713 | + // Set up a stream to write the stream data into a buffer. | ||
| 1714 | + Pipeline* next = pushPipeline(new Pl_Buffer("object stream")); | ||
| 1715 | + if (m->compress_streams && !m->qdf_mode) { | ||
| 1716 | + compressed = true; | ||
| 1717 | + next = pushPipeline(new Pl_Flate("compress object stream", next, Pl_Flate::a_deflate)); | ||
| 1718 | + } | ||
| 1719 | + activatePipelineStack(pp_ostream); | ||
| 1720 | + writeObjectStreamOffsets(offsets, first_obj); | ||
| 1721 | + writeBuffer(stream_buffer); | ||
| 1722 | + } | ||
| 1721 | 1723 | ||
| 1722 | // Write the object | 1724 | // Write the object |
| 1723 | openObject(new_stream_id); | 1725 | openObject(new_stream_id); |
manual/release-notes.rst
| @@ -26,6 +26,9 @@ more detail. | @@ -26,6 +26,9 @@ more detail. | ||
| 26 | - There have been further enhancements to how files with damaged xref | 26 | - There have been further enhancements to how files with damaged xref |
| 27 | tables are recovered. | 27 | tables are recovered. |
| 28 | 28 | ||
| 29 | + - There has been some refactoring of how object streams are written with | ||
| 30 | + some performance improvement. | ||
| 31 | + | ||
| 29 | .. cSpell:ignore substract | 32 | .. cSpell:ignore substract |
| 30 | 33 | ||
| 31 | .. _r12-0-0: | 34 | .. _r12-0-0: |