Commit 83144b29a9408b42b2cda4ad3eda64689cc3a7ff
1 parent
f7e07240
Refactor QPDFWriter pipeline stack logic for improved encapsulation
Encapsulated pipeline stack management into a dedicated `Pl_stack` class within `QPDFWriter::Members`. Reorganized related methods to streamline and simplify initialization and activation of pipelines, removing redundant code.
Showing
2 changed files
with
154 additions
and
127 deletions
include/qpdf/QPDFWriter.hh
| ... | ... | @@ -447,6 +447,7 @@ class QPDFWriter |
| 447 | 447 | struct NewObject; |
| 448 | 448 | class ObjTable; |
| 449 | 449 | class NewObjTable; |
| 450 | + class PipelinePopper; | |
| 450 | 451 | |
| 451 | 452 | private: |
| 452 | 453 | // flags used by unparseObject |
| ... | ... | @@ -458,28 +459,6 @@ class QPDFWriter |
| 458 | 459 | |
| 459 | 460 | enum trailer_e { t_normal, t_lin_first, t_lin_second }; |
| 460 | 461 | |
| 461 | - // An reference to a PipelinePopper instance is passed into activatePipelineStack. When the | |
| 462 | - // PipelinePopper goes out of scope, the pipeline stack is popped. PipelinePopper's destructor | |
| 463 | - // calls finish on the current pipeline and pops the pipeline stack until the top of stack is a | |
| 464 | - // previous active top of stack, and restores the pipeline to that point. It deletes any | |
| 465 | - // pipelines that it pops. If the bp argument is non-null and any of the stack items are of type | |
| 466 | - // Pl_Buffer, the buffer is retrieved. | |
| 467 | - class PipelinePopper | |
| 468 | - { | |
| 469 | - friend class QPDFWriter; | |
| 470 | - | |
| 471 | - public: | |
| 472 | - PipelinePopper(QPDFWriter* qw) : | |
| 473 | - qw(qw) | |
| 474 | - { | |
| 475 | - } | |
| 476 | - ~PipelinePopper(); | |
| 477 | - | |
| 478 | - private: | |
| 479 | - QPDFWriter* qw{nullptr}; | |
| 480 | - unsigned long stack_id{0}; | |
| 481 | - }; | |
| 482 | - | |
| 483 | 462 | unsigned int bytesNeeded(long long n); |
| 484 | 463 | void writeBinary(unsigned long long val, unsigned int bytes); |
| 485 | 464 | QPDFWriter& write(std::string_view str); |
| ... | ... | @@ -588,15 +567,6 @@ class QPDFWriter |
| 588 | 567 | // When filtering subsections, push additional pipelines to the stack. When ready to switch, |
| 589 | 568 | // activate the pipeline stack. When the passed in PipelinePopper goes out of scope, the stack |
| 590 | 569 | // is popped. |
| 591 | - Pipeline* pushPipeline(Pipeline*); | |
| 592 | - void activatePipelineStack(PipelinePopper& pp, std::string& str); | |
| 593 | - void activatePipelineStack(PipelinePopper& pp, std::unique_ptr<qpdf::pl::Link> link); | |
| 594 | - void activatePipelineStack( | |
| 595 | - PipelinePopper& pp, | |
| 596 | - bool discard = false, | |
| 597 | - std::string* str = nullptr, | |
| 598 | - std::unique_ptr<qpdf::pl::Link> link = nullptr); | |
| 599 | - void initializePipelineStack(Pipeline*); | |
| 600 | 570 | |
| 601 | 571 | void adjustAESStreamLength(size_t& length); |
| 602 | 572 | void pushEncryptionFilter(PipelinePopper&); | ... | ... |
libqpdf/QPDFWriter.cc
| ... | ... | @@ -47,9 +47,137 @@ QPDFWriter::FunctionProgressReporter::~FunctionProgressReporter() // NOLINT |
| 47 | 47 | void |
| 48 | 48 | QPDFWriter::FunctionProgressReporter::reportProgress(int progress) |
| 49 | 49 | { |
| 50 | - this->handler(progress); | |
| 50 | + handler(progress); | |
| 51 | 51 | } |
| 52 | 52 | |
| 53 | +// An reference to a PipelinePopper instance is passed into activatePipelineStack. When the | |
| 54 | +// PipelinePopper goes out of scope, the pipeline stack is popped. PipelinePopper's destructor | |
| 55 | +// calls finish on the current pipeline and pops the pipeline stack until the top of stack is a | |
| 56 | +// previous active top of stack, and restores the pipeline to that point. It deletes any | |
| 57 | +// pipelines that it pops. If the bp argument is non-null and any of the stack items are of type | |
| 58 | +// Pl_Buffer, the buffer is retrieved. | |
| 59 | +class QPDFWriter::PipelinePopper | |
| 60 | +{ | |
| 61 | + public: | |
| 62 | + PipelinePopper(QPDFWriter* qw) : | |
| 63 | + qw(qw) | |
| 64 | + { | |
| 65 | + } | |
| 66 | + ~PipelinePopper(); | |
| 67 | + | |
| 68 | + QPDFWriter* qw{nullptr}; | |
| 69 | + unsigned long stack_id{0}; | |
| 70 | +}; | |
| 71 | + | |
| 72 | +namespace | |
| 73 | +{ | |
| 74 | + class Pl_stack | |
| 75 | + { | |
| 76 | + using PP = QPDFWriter::PipelinePopper; | |
| 77 | + | |
| 78 | + public: | |
| 79 | + Pl_stack(pl::Count*& top, Pl_MD5*& md5_pipeline) : | |
| 80 | + top(top), | |
| 81 | + md5_pipeline(md5_pipeline) | |
| 82 | + { | |
| 83 | + } | |
| 84 | + | |
| 85 | + void | |
| 86 | + initialize(Pipeline* p) | |
| 87 | + { | |
| 88 | + top = new pl::Count(1, p); | |
| 89 | + to_delete.emplace_back(std::unique_ptr<Pipeline>(top)); | |
| 90 | + stack.emplace_back(top); | |
| 91 | + } | |
| 92 | + | |
| 93 | + void | |
| 94 | + activate(PP& pp, std::string& str) | |
| 95 | + { | |
| 96 | + activate(pp, false, &str, nullptr); | |
| 97 | + } | |
| 98 | + | |
| 99 | + void | |
| 100 | + activate(PP& pp, std::unique_ptr<pl::Link> link) | |
| 101 | + { | |
| 102 | + count_buffer.clear(); | |
| 103 | + activate(pp, false, &count_buffer, std::move(link)); | |
| 104 | + } | |
| 105 | + | |
| 106 | + void | |
| 107 | + activate( | |
| 108 | + PP& pp, | |
| 109 | + bool discard = false, | |
| 110 | + std::string* str = nullptr, | |
| 111 | + std::unique_ptr<pl::Link> link = nullptr) | |
| 112 | + { | |
| 113 | + pl::Count* c; | |
| 114 | + if (link) { | |
| 115 | + c = new pl::Count(next_stack_id, count_buffer, std::move(link)); | |
| 116 | + } else if (discard) { | |
| 117 | + c = new pl::Count(next_stack_id, nullptr); | |
| 118 | + } else if (!str) { | |
| 119 | + c = new pl::Count(next_stack_id, stack.back()); | |
| 120 | + } else { | |
| 121 | + c = new pl::Count(next_stack_id, *str); | |
| 122 | + } | |
| 123 | + pp.stack_id = next_stack_id; | |
| 124 | + stack.emplace_back(c); | |
| 125 | + top = c; | |
| 126 | + ++next_stack_id; | |
| 127 | + } | |
| 128 | + Pipeline* | |
| 129 | + push(Pipeline* p) | |
| 130 | + { | |
| 131 | + qpdf_assert_debug(!dynamic_cast<pl::Count*>(p)); | |
| 132 | + stack.emplace_back(p); | |
| 133 | + return p; | |
| 134 | + } | |
| 135 | + | |
| 136 | + void | |
| 137 | + pop(unsigned long stack_id) | |
| 138 | + | |
| 139 | + { | |
| 140 | + if (!stack_id) { | |
| 141 | + return; | |
| 142 | + } | |
| 143 | + qpdf_assert_debug(stack.size() >= 2); | |
| 144 | + top->finish(); | |
| 145 | + qpdf_assert_debug(dynamic_cast<pl::Count*>(stack.back()) == top); | |
| 146 | + // It might be possible for this assertion to fail if writeLinearized exits by exception | |
| 147 | + // when deterministic ID, but I don't think so. As of this writing, this is the only | |
| 148 | + // case in which two dynamically allocated PipelinePopper objects ever exist at the same | |
| 149 | + // time, so the assertion will fail if they get popped out of order from automatic | |
| 150 | + // destruction. | |
| 151 | + qpdf_assert_debug(top->id() == stack_id); | |
| 152 | + delete stack.back(); | |
| 153 | + stack.pop_back(); | |
| 154 | + while (!dynamic_cast<pl::Count*>(stack.back())) { | |
| 155 | + Pipeline* p = stack.back(); | |
| 156 | + if (dynamic_cast<Pl_MD5*>(p) == md5_pipeline) { | |
| 157 | + md5_pipeline = nullptr; | |
| 158 | + } | |
| 159 | + stack.pop_back(); | |
| 160 | + delete p; | |
| 161 | + } | |
| 162 | + top = dynamic_cast<pl::Count*>(stack.back()); | |
| 163 | + } | |
| 164 | + | |
| 165 | + void | |
| 166 | + clear_buffer() | |
| 167 | + { | |
| 168 | + count_buffer.clear(); | |
| 169 | + } | |
| 170 | + | |
| 171 | + private: | |
| 172 | + std::vector<Pipeline*> stack; | |
| 173 | + pl::Count*& top; | |
| 174 | + Pl_MD5*& md5_pipeline; | |
| 175 | + std::vector<std::unique_ptr<Pipeline>> to_delete; | |
| 176 | + unsigned long next_stack_id{2}; | |
| 177 | + std::string count_buffer; | |
| 178 | + }; | |
| 179 | +} // namespace | |
| 180 | + | |
| 53 | 181 | class QPDFWriter::Members |
| 54 | 182 | { |
| 55 | 183 | friend class QPDFWriter; |
| ... | ... | @@ -116,9 +244,7 @@ class QPDFWriter::Members |
| 116 | 244 | std::map<QPDFObjGen, int> page_object_to_seq; |
| 117 | 245 | std::map<QPDFObjGen, int> contents_to_page_seq; |
| 118 | 246 | std::map<int, std::vector<QPDFObjGen>> object_stream_to_objects; |
| 119 | - std::vector<Pipeline*> pipeline_stack; | |
| 120 | - unsigned long next_stack_id{2}; | |
| 121 | - std::string count_buffer; | |
| 247 | + Pl_stack pipeline_stack; | |
| 122 | 248 | bool deterministic_id{false}; |
| 123 | 249 | Pl_MD5* md5_pipeline{nullptr}; |
| 124 | 250 | std::string deterministic_id_data; |
| ... | ... | @@ -136,7 +262,8 @@ class QPDFWriter::Members |
| 136 | 262 | |
| 137 | 263 | QPDFWriter::Members::Members(QPDF& pdf) : |
| 138 | 264 | pdf(pdf), |
| 139 | - root_og(pdf.getRoot().getObjGen().isIndirect() ? pdf.getRoot().getObjGen() : QPDFObjGen(-1, 0)) | |
| 265 | + root_og(pdf.getRoot().getObjGen().isIndirect() ? pdf.getRoot().getObjGen() : QPDFObjGen(-1, 0)), | |
| 266 | + pipeline_stack(pipeline, md5_pipeline) | |
| 140 | 267 | { |
| 141 | 268 | } |
| 142 | 269 | |
| ... | ... | @@ -192,7 +319,7 @@ QPDFWriter::setOutputFile(char const* description, FILE* file, bool close_file) |
| 192 | 319 | m->close_file = close_file; |
| 193 | 320 | std::shared_ptr<Pipeline> p = std::make_shared<Pl_StdioFile>("qpdf output", file); |
| 194 | 321 | m->to_delete.push_back(p); |
| 195 | - initializePipelineStack(p.get()); | |
| 322 | + m->pipeline_stack.initialize(p.get()); | |
| 196 | 323 | } |
| 197 | 324 | |
| 198 | 325 | void |
| ... | ... | @@ -201,7 +328,7 @@ QPDFWriter::setOutputMemory() |
| 201 | 328 | m->filename = "memory buffer"; |
| 202 | 329 | m->buffer_pipeline = new Pl_Buffer("qpdf output"); |
| 203 | 330 | m->to_delete.push_back(std::shared_ptr<Pipeline>(m->buffer_pipeline)); |
| 204 | - initializePipelineStack(m->buffer_pipeline); | |
| 331 | + m->pipeline_stack.initialize(m->buffer_pipeline); | |
| 205 | 332 | } |
| 206 | 333 | |
| 207 | 334 | Buffer* |
| ... | ... | @@ -222,7 +349,7 @@ void |
| 222 | 349 | QPDFWriter::setOutputPipeline(Pipeline* p) |
| 223 | 350 | { |
| 224 | 351 | m->filename = "custom pipeline"; |
| 225 | - initializePipelineStack(p); | |
| 352 | + m->pipeline_stack.initialize(p); | |
| 226 | 353 | } |
| 227 | 354 | |
| 228 | 355 | void |
| ... | ... | @@ -887,79 +1014,9 @@ QPDFWriter::write_no_qdf(Args&&... args) |
| 887 | 1014 | return *this; |
| 888 | 1015 | } |
| 889 | 1016 | |
| 890 | -Pipeline* | |
| 891 | -QPDFWriter::pushPipeline(Pipeline* p) | |
| 892 | -{ | |
| 893 | - qpdf_assert_debug(!dynamic_cast<pl::Count*>(p)); | |
| 894 | - m->pipeline_stack.emplace_back(p); | |
| 895 | - return p; | |
| 896 | -} | |
| 897 | - | |
| 898 | -void | |
| 899 | -QPDFWriter::initializePipelineStack(Pipeline* p) | |
| 900 | -{ | |
| 901 | - m->pipeline = new pl::Count(1, p); | |
| 902 | - m->to_delete.emplace_back(std::shared_ptr<Pipeline>(m->pipeline)); | |
| 903 | - m->pipeline_stack.emplace_back(m->pipeline); | |
| 904 | -} | |
| 905 | - | |
| 906 | -void | |
| 907 | -QPDFWriter::activatePipelineStack(PipelinePopper& pp, std::string& str) | |
| 908 | -{ | |
| 909 | - activatePipelineStack(pp, false, &str, nullptr); | |
| 910 | -} | |
| 911 | - | |
| 912 | -void | |
| 913 | -QPDFWriter::activatePipelineStack(PipelinePopper& pp, std::unique_ptr<pl::Link> link) | |
| 914 | -{ | |
| 915 | - m->count_buffer.clear(); | |
| 916 | - activatePipelineStack(pp, false, &m->count_buffer, std::move(link)); | |
| 917 | -} | |
| 918 | - | |
| 919 | -void | |
| 920 | -QPDFWriter::activatePipelineStack( | |
| 921 | - PipelinePopper& pp, bool discard, std::string* str, std::unique_ptr<pl::Link> link) | |
| 922 | -{ | |
| 923 | - pl::Count* c; | |
| 924 | - if (link) { | |
| 925 | - c = new pl::Count(m->next_stack_id, m->count_buffer, std::move(link)); | |
| 926 | - } else if (discard) { | |
| 927 | - c = new pl::Count(m->next_stack_id, nullptr); | |
| 928 | - } else if (!str) { | |
| 929 | - c = new pl::Count(m->next_stack_id, m->pipeline_stack.back()); | |
| 930 | - } else { | |
| 931 | - c = new pl::Count(m->next_stack_id, *str); | |
| 932 | - } | |
| 933 | - pp.stack_id = m->next_stack_id; | |
| 934 | - m->pipeline_stack.emplace_back(c); | |
| 935 | - m->pipeline = c; | |
| 936 | - ++m->next_stack_id; | |
| 937 | -} | |
| 938 | - | |
| 939 | 1017 | QPDFWriter::PipelinePopper::~PipelinePopper() |
| 940 | 1018 | { |
| 941 | - if (!stack_id) { | |
| 942 | - return; | |
| 943 | - } | |
| 944 | - qpdf_assert_debug(qw->m->pipeline_stack.size() >= 2); | |
| 945 | - qw->m->pipeline->finish(); | |
| 946 | - qpdf_assert_debug(dynamic_cast<pl::Count*>(qw->m->pipeline_stack.back()) == qw->m->pipeline); | |
| 947 | - // It might be possible for this assertion to fail if writeLinearized exits by exception when | |
| 948 | - // deterministic ID, but I don't think so. As of this writing, this is the only case in which | |
| 949 | - // two dynamically allocated PipelinePopper objects ever exist at the same time, so the | |
| 950 | - // assertion will fail if they get popped out of order from automatic destruction. | |
| 951 | - qpdf_assert_debug(qw->m->pipeline->id() == stack_id); | |
| 952 | - delete qw->m->pipeline_stack.back(); | |
| 953 | - qw->m->pipeline_stack.pop_back(); | |
| 954 | - while (!dynamic_cast<pl::Count*>(qw->m->pipeline_stack.back())) { | |
| 955 | - Pipeline* p = qw->m->pipeline_stack.back(); | |
| 956 | - if (dynamic_cast<Pl_MD5*>(p) == qw->m->md5_pipeline) { | |
| 957 | - qw->m->md5_pipeline = nullptr; | |
| 958 | - } | |
| 959 | - qw->m->pipeline_stack.pop_back(); | |
| 960 | - delete p; | |
| 961 | - } | |
| 962 | - qw->m->pipeline = dynamic_cast<pl::Count*>(qw->m->pipeline_stack.back()); | |
| 1019 | + qw->m->pipeline_stack.pop(stack_id); | |
| 963 | 1020 | } |
| 964 | 1021 | |
| 965 | 1022 | void |
| ... | ... | @@ -991,11 +1048,11 @@ QPDFWriter::pushEncryptionFilter(PipelinePopper& pp) |
| 991 | 1048 | QUtil::unsigned_char_pointer(m->cur_data_key), |
| 992 | 1049 | QIntC::to_int(m->cur_data_key.length())); |
| 993 | 1050 | } |
| 994 | - pushPipeline(p); | |
| 1051 | + m->pipeline_stack.push(p); | |
| 995 | 1052 | } |
| 996 | 1053 | // Must call this unconditionally so we can call popPipelineStack to balance |
| 997 | 1054 | // pushEncryptionFilter(). |
| 998 | - activatePipelineStack(pp); | |
| 1055 | + m->pipeline_stack.activate(pp); | |
| 999 | 1056 | } |
| 1000 | 1057 | |
| 1001 | 1058 | void |
| ... | ... | @@ -1012,8 +1069,8 @@ QPDFWriter::pushMD5Pipeline(PipelinePopper& pp) |
| 1012 | 1069 | m->md5_pipeline = new Pl_MD5("qpdf md5", m->pipeline); |
| 1013 | 1070 | m->md5_pipeline->persistAcrossFinish(true); |
| 1014 | 1071 | // Special case code in popPipelineStack clears m->md5_pipeline upon deletion. |
| 1015 | - pushPipeline(m->md5_pipeline); | |
| 1016 | - activatePipelineStack(pp); | |
| 1072 | + m->pipeline_stack.push(m->md5_pipeline); | |
| 1073 | + m->pipeline_stack.activate(pp); | |
| 1017 | 1074 | } |
| 1018 | 1075 | |
| 1019 | 1076 | void |
| ... | ... | @@ -1273,9 +1330,9 @@ QPDFWriter::willFilterStream( |
| 1273 | 1330 | for (bool first_attempt: {true, false}) { |
| 1274 | 1331 | PipelinePopper pp_stream_data(this); |
| 1275 | 1332 | if (stream_data != nullptr) { |
| 1276 | - activatePipelineStack(pp_stream_data, *stream_data); | |
| 1333 | + m->pipeline_stack.activate(pp_stream_data, *stream_data); | |
| 1277 | 1334 | } else { |
| 1278 | - activatePipelineStack(pp_stream_data, true); | |
| 1335 | + m->pipeline_stack.activate(pp_stream_data, true); | |
| 1279 | 1336 | } |
| 1280 | 1337 | try { |
| 1281 | 1338 | filtered = stream.pipeStreamData( |
| ... | ... | @@ -1627,7 +1684,7 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) |
| 1627 | 1684 | { |
| 1628 | 1685 | // Pass 1 |
| 1629 | 1686 | PipelinePopper pp_ostream_pass1(this); |
| 1630 | - activatePipelineStack(pp_ostream_pass1, stream_buffer_pass1); | |
| 1687 | + m->pipeline_stack.activate(pp_ostream_pass1, stream_buffer_pass1); | |
| 1631 | 1688 | |
| 1632 | 1689 | int count = -1; |
| 1633 | 1690 | for (auto const& obj: m->object_stream_to_objects[old_id]) { |
| ... | ... | @@ -1679,19 +1736,19 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) |
| 1679 | 1736 | // Take one pass at writing pairs of numbers so we can get their size information |
| 1680 | 1737 | { |
| 1681 | 1738 | PipelinePopper pp_discard(this); |
| 1682 | - activatePipelineStack(pp_discard, true); | |
| 1739 | + m->pipeline_stack.activate(pp_discard, true); | |
| 1683 | 1740 | writeObjectStreamOffsets(offsets, first_obj); |
| 1684 | 1741 | first += m->pipeline->getCount(); |
| 1685 | 1742 | } |
| 1686 | 1743 | |
| 1687 | 1744 | // Set up a stream to write the stream data into a buffer. |
| 1688 | 1745 | if (compressed) { |
| 1689 | - activatePipelineStack( | |
| 1746 | + m->pipeline_stack.activate( | |
| 1690 | 1747 | pp_ostream, |
| 1691 | 1748 | pl::create<Pl_Flate>( |
| 1692 | 1749 | pl::create<pl::String>(stream_buffer_pass2), Pl_Flate::a_deflate)); |
| 1693 | 1750 | } else { |
| 1694 | - activatePipelineStack(pp_ostream, stream_buffer_pass2); | |
| 1751 | + m->pipeline_stack.activate(pp_ostream, stream_buffer_pass2); | |
| 1695 | 1752 | } |
| 1696 | 1753 | writeObjectStreamOffsets(offsets, first_obj); |
| 1697 | 1754 | write(stream_buffer_pass1); |
| ... | ... | @@ -2449,17 +2506,17 @@ QPDFWriter::writeXRefStream( |
| 2449 | 2506 | { |
| 2450 | 2507 | PipelinePopper pp_xref(this); |
| 2451 | 2508 | if (compressed) { |
| 2452 | - m->count_buffer.clear(); | |
| 2509 | + m->pipeline_stack.clear_buffer(); | |
| 2453 | 2510 | auto link = pl::create<pl::String>(xref_data); |
| 2454 | 2511 | if (!skip_compression) { |
| 2455 | 2512 | // Write the stream dictionary for compression but don't actually compress. This |
| 2456 | 2513 | // helps us with computation of padding for pass 1 of linearization. |
| 2457 | 2514 | link = pl::create<Pl_Flate>(std::move(link), Pl_Flate::a_deflate); |
| 2458 | 2515 | } |
| 2459 | - activatePipelineStack( | |
| 2516 | + m->pipeline_stack.activate( | |
| 2460 | 2517 | pp_xref, pl::create<Pl_PNGFilter>(std::move(link), Pl_PNGFilter::a_encode, esize)); |
| 2461 | 2518 | } else { |
| 2462 | - activatePipelineStack(pp_xref, xref_data); | |
| 2519 | + m->pipeline_stack.activate(pp_xref, xref_data); | |
| 2463 | 2520 | } |
| 2464 | 2521 | |
| 2465 | 2522 | for (int i = first; i <= last; ++i) { |
| ... | ... | @@ -2660,10 +2717,10 @@ QPDFWriter::writeLinearized() |
| 2660 | 2717 | if (pass == 1) { |
| 2661 | 2718 | if (!m->lin_pass1_filename.empty()) { |
| 2662 | 2719 | lin_pass1_file = QUtil::safe_fopen(m->lin_pass1_filename.c_str(), "wb"); |
| 2663 | - pushPipeline(new Pl_StdioFile("linearization pass1", lin_pass1_file)); | |
| 2664 | - activatePipelineStack(*pp_pass1); | |
| 2720 | + m->pipeline_stack.push(new Pl_StdioFile("linearization pass1", lin_pass1_file)); | |
| 2721 | + m->pipeline_stack.activate(*pp_pass1); | |
| 2665 | 2722 | } else { |
| 2666 | - activatePipelineStack(*pp_pass1, true); | |
| 2723 | + m->pipeline_stack.activate(*pp_pass1, true); | |
| 2667 | 2724 | } |
| 2668 | 2725 | if (m->deterministic_id) { |
| 2669 | 2726 | pushMD5Pipeline(*pp_md5); |
| ... | ... | @@ -2855,7 +2912,7 @@ QPDFWriter::writeLinearized() |
| 2855 | 2912 | // Write hint stream to a buffer |
| 2856 | 2913 | { |
| 2857 | 2914 | PipelinePopper pp_hint(this); |
| 2858 | - activatePipelineStack(pp_hint, hint_buffer); | |
| 2915 | + m->pipeline_stack.activate(pp_hint, hint_buffer); | |
| 2859 | 2916 | writeHintStream(hint_id); |
| 2860 | 2917 | } |
| 2861 | 2918 | hint_length = QIntC::to_offset(hint_buffer.size()); | ... | ... |