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,6 +447,7 @@ class QPDFWriter | ||
| 447 | struct NewObject; | 447 | struct NewObject; |
| 448 | class ObjTable; | 448 | class ObjTable; |
| 449 | class NewObjTable; | 449 | class NewObjTable; |
| 450 | + class PipelinePopper; | ||
| 450 | 451 | ||
| 451 | private: | 452 | private: |
| 452 | // flags used by unparseObject | 453 | // flags used by unparseObject |
| @@ -458,28 +459,6 @@ class QPDFWriter | @@ -458,28 +459,6 @@ class QPDFWriter | ||
| 458 | 459 | ||
| 459 | enum trailer_e { t_normal, t_lin_first, t_lin_second }; | 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 | unsigned int bytesNeeded(long long n); | 462 | unsigned int bytesNeeded(long long n); |
| 484 | void writeBinary(unsigned long long val, unsigned int bytes); | 463 | void writeBinary(unsigned long long val, unsigned int bytes); |
| 485 | QPDFWriter& write(std::string_view str); | 464 | QPDFWriter& write(std::string_view str); |
| @@ -588,15 +567,6 @@ class QPDFWriter | @@ -588,15 +567,6 @@ class QPDFWriter | ||
| 588 | // When filtering subsections, push additional pipelines to the stack. When ready to switch, | 567 | // When filtering subsections, push additional pipelines to the stack. When ready to switch, |
| 589 | // activate the pipeline stack. When the passed in PipelinePopper goes out of scope, the stack | 568 | // activate the pipeline stack. When the passed in PipelinePopper goes out of scope, the stack |
| 590 | // is popped. | 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 | void adjustAESStreamLength(size_t& length); | 571 | void adjustAESStreamLength(size_t& length); |
| 602 | void pushEncryptionFilter(PipelinePopper&); | 572 | void pushEncryptionFilter(PipelinePopper&); |
libqpdf/QPDFWriter.cc
| @@ -47,9 +47,137 @@ QPDFWriter::FunctionProgressReporter::~FunctionProgressReporter() // NOLINT | @@ -47,9 +47,137 @@ QPDFWriter::FunctionProgressReporter::~FunctionProgressReporter() // NOLINT | ||
| 47 | void | 47 | void |
| 48 | QPDFWriter::FunctionProgressReporter::reportProgress(int progress) | 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 | class QPDFWriter::Members | 181 | class QPDFWriter::Members |
| 54 | { | 182 | { |
| 55 | friend class QPDFWriter; | 183 | friend class QPDFWriter; |
| @@ -116,9 +244,7 @@ class QPDFWriter::Members | @@ -116,9 +244,7 @@ class QPDFWriter::Members | ||
| 116 | std::map<QPDFObjGen, int> page_object_to_seq; | 244 | std::map<QPDFObjGen, int> page_object_to_seq; |
| 117 | std::map<QPDFObjGen, int> contents_to_page_seq; | 245 | std::map<QPDFObjGen, int> contents_to_page_seq; |
| 118 | std::map<int, std::vector<QPDFObjGen>> object_stream_to_objects; | 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 | bool deterministic_id{false}; | 248 | bool deterministic_id{false}; |
| 123 | Pl_MD5* md5_pipeline{nullptr}; | 249 | Pl_MD5* md5_pipeline{nullptr}; |
| 124 | std::string deterministic_id_data; | 250 | std::string deterministic_id_data; |
| @@ -136,7 +262,8 @@ class QPDFWriter::Members | @@ -136,7 +262,8 @@ class QPDFWriter::Members | ||
| 136 | 262 | ||
| 137 | QPDFWriter::Members::Members(QPDF& pdf) : | 263 | QPDFWriter::Members::Members(QPDF& pdf) : |
| 138 | pdf(pdf), | 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,7 +319,7 @@ QPDFWriter::setOutputFile(char const* description, FILE* file, bool close_file) | ||
| 192 | m->close_file = close_file; | 319 | m->close_file = close_file; |
| 193 | std::shared_ptr<Pipeline> p = std::make_shared<Pl_StdioFile>("qpdf output", file); | 320 | std::shared_ptr<Pipeline> p = std::make_shared<Pl_StdioFile>("qpdf output", file); |
| 194 | m->to_delete.push_back(p); | 321 | m->to_delete.push_back(p); |
| 195 | - initializePipelineStack(p.get()); | 322 | + m->pipeline_stack.initialize(p.get()); |
| 196 | } | 323 | } |
| 197 | 324 | ||
| 198 | void | 325 | void |
| @@ -201,7 +328,7 @@ QPDFWriter::setOutputMemory() | @@ -201,7 +328,7 @@ QPDFWriter::setOutputMemory() | ||
| 201 | m->filename = "memory buffer"; | 328 | m->filename = "memory buffer"; |
| 202 | m->buffer_pipeline = new Pl_Buffer("qpdf output"); | 329 | m->buffer_pipeline = new Pl_Buffer("qpdf output"); |
| 203 | m->to_delete.push_back(std::shared_ptr<Pipeline>(m->buffer_pipeline)); | 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 | Buffer* | 334 | Buffer* |
| @@ -222,7 +349,7 @@ void | @@ -222,7 +349,7 @@ void | ||
| 222 | QPDFWriter::setOutputPipeline(Pipeline* p) | 349 | QPDFWriter::setOutputPipeline(Pipeline* p) |
| 223 | { | 350 | { |
| 224 | m->filename = "custom pipeline"; | 351 | m->filename = "custom pipeline"; |
| 225 | - initializePipelineStack(p); | 352 | + m->pipeline_stack.initialize(p); |
| 226 | } | 353 | } |
| 227 | 354 | ||
| 228 | void | 355 | void |
| @@ -887,79 +1014,9 @@ QPDFWriter::write_no_qdf(Args&&... args) | @@ -887,79 +1014,9 @@ QPDFWriter::write_no_qdf(Args&&... args) | ||
| 887 | return *this; | 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 | QPDFWriter::PipelinePopper::~PipelinePopper() | 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 | void | 1022 | void |
| @@ -991,11 +1048,11 @@ QPDFWriter::pushEncryptionFilter(PipelinePopper& pp) | @@ -991,11 +1048,11 @@ QPDFWriter::pushEncryptionFilter(PipelinePopper& pp) | ||
| 991 | QUtil::unsigned_char_pointer(m->cur_data_key), | 1048 | QUtil::unsigned_char_pointer(m->cur_data_key), |
| 992 | QIntC::to_int(m->cur_data_key.length())); | 1049 | QIntC::to_int(m->cur_data_key.length())); |
| 993 | } | 1050 | } |
| 994 | - pushPipeline(p); | 1051 | + m->pipeline_stack.push(p); |
| 995 | } | 1052 | } |
| 996 | // Must call this unconditionally so we can call popPipelineStack to balance | 1053 | // Must call this unconditionally so we can call popPipelineStack to balance |
| 997 | // pushEncryptionFilter(). | 1054 | // pushEncryptionFilter(). |
| 998 | - activatePipelineStack(pp); | 1055 | + m->pipeline_stack.activate(pp); |
| 999 | } | 1056 | } |
| 1000 | 1057 | ||
| 1001 | void | 1058 | void |
| @@ -1012,8 +1069,8 @@ QPDFWriter::pushMD5Pipeline(PipelinePopper& pp) | @@ -1012,8 +1069,8 @@ QPDFWriter::pushMD5Pipeline(PipelinePopper& pp) | ||
| 1012 | m->md5_pipeline = new Pl_MD5("qpdf md5", m->pipeline); | 1069 | m->md5_pipeline = new Pl_MD5("qpdf md5", m->pipeline); |
| 1013 | m->md5_pipeline->persistAcrossFinish(true); | 1070 | m->md5_pipeline->persistAcrossFinish(true); |
| 1014 | // Special case code in popPipelineStack clears m->md5_pipeline upon deletion. | 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 | void | 1076 | void |
| @@ -1273,9 +1330,9 @@ QPDFWriter::willFilterStream( | @@ -1273,9 +1330,9 @@ QPDFWriter::willFilterStream( | ||
| 1273 | for (bool first_attempt: {true, false}) { | 1330 | for (bool first_attempt: {true, false}) { |
| 1274 | PipelinePopper pp_stream_data(this); | 1331 | PipelinePopper pp_stream_data(this); |
| 1275 | if (stream_data != nullptr) { | 1332 | if (stream_data != nullptr) { |
| 1276 | - activatePipelineStack(pp_stream_data, *stream_data); | 1333 | + m->pipeline_stack.activate(pp_stream_data, *stream_data); |
| 1277 | } else { | 1334 | } else { |
| 1278 | - activatePipelineStack(pp_stream_data, true); | 1335 | + m->pipeline_stack.activate(pp_stream_data, true); |
| 1279 | } | 1336 | } |
| 1280 | try { | 1337 | try { |
| 1281 | filtered = stream.pipeStreamData( | 1338 | filtered = stream.pipeStreamData( |
| @@ -1627,7 +1684,7 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) | @@ -1627,7 +1684,7 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) | ||
| 1627 | { | 1684 | { |
| 1628 | // Pass 1 | 1685 | // Pass 1 |
| 1629 | PipelinePopper pp_ostream_pass1(this); | 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 | int count = -1; | 1689 | int count = -1; |
| 1633 | for (auto const& obj: m->object_stream_to_objects[old_id]) { | 1690 | for (auto const& obj: m->object_stream_to_objects[old_id]) { |
| @@ -1679,19 +1736,19 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) | @@ -1679,19 +1736,19 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) | ||
| 1679 | // Take one pass at writing pairs of numbers so we can get their size information | 1736 | // Take one pass at writing pairs of numbers so we can get their size information |
| 1680 | { | 1737 | { |
| 1681 | PipelinePopper pp_discard(this); | 1738 | PipelinePopper pp_discard(this); |
| 1682 | - activatePipelineStack(pp_discard, true); | 1739 | + m->pipeline_stack.activate(pp_discard, true); |
| 1683 | writeObjectStreamOffsets(offsets, first_obj); | 1740 | writeObjectStreamOffsets(offsets, first_obj); |
| 1684 | first += m->pipeline->getCount(); | 1741 | first += m->pipeline->getCount(); |
| 1685 | } | 1742 | } |
| 1686 | 1743 | ||
| 1687 | // Set up a stream to write the stream data into a buffer. | 1744 | // Set up a stream to write the stream data into a buffer. |
| 1688 | if (compressed) { | 1745 | if (compressed) { |
| 1689 | - activatePipelineStack( | 1746 | + m->pipeline_stack.activate( |
| 1690 | pp_ostream, | 1747 | pp_ostream, |
| 1691 | pl::create<Pl_Flate>( | 1748 | pl::create<Pl_Flate>( |
| 1692 | pl::create<pl::String>(stream_buffer_pass2), Pl_Flate::a_deflate)); | 1749 | pl::create<pl::String>(stream_buffer_pass2), Pl_Flate::a_deflate)); |
| 1693 | } else { | 1750 | } else { |
| 1694 | - activatePipelineStack(pp_ostream, stream_buffer_pass2); | 1751 | + m->pipeline_stack.activate(pp_ostream, stream_buffer_pass2); |
| 1695 | } | 1752 | } |
| 1696 | writeObjectStreamOffsets(offsets, first_obj); | 1753 | writeObjectStreamOffsets(offsets, first_obj); |
| 1697 | write(stream_buffer_pass1); | 1754 | write(stream_buffer_pass1); |
| @@ -2449,17 +2506,17 @@ QPDFWriter::writeXRefStream( | @@ -2449,17 +2506,17 @@ QPDFWriter::writeXRefStream( | ||
| 2449 | { | 2506 | { |
| 2450 | PipelinePopper pp_xref(this); | 2507 | PipelinePopper pp_xref(this); |
| 2451 | if (compressed) { | 2508 | if (compressed) { |
| 2452 | - m->count_buffer.clear(); | 2509 | + m->pipeline_stack.clear_buffer(); |
| 2453 | auto link = pl::create<pl::String>(xref_data); | 2510 | auto link = pl::create<pl::String>(xref_data); |
| 2454 | if (!skip_compression) { | 2511 | if (!skip_compression) { |
| 2455 | // Write the stream dictionary for compression but don't actually compress. This | 2512 | // Write the stream dictionary for compression but don't actually compress. This |
| 2456 | // helps us with computation of padding for pass 1 of linearization. | 2513 | // helps us with computation of padding for pass 1 of linearization. |
| 2457 | link = pl::create<Pl_Flate>(std::move(link), Pl_Flate::a_deflate); | 2514 | link = pl::create<Pl_Flate>(std::move(link), Pl_Flate::a_deflate); |
| 2458 | } | 2515 | } |
| 2459 | - activatePipelineStack( | 2516 | + m->pipeline_stack.activate( |
| 2460 | pp_xref, pl::create<Pl_PNGFilter>(std::move(link), Pl_PNGFilter::a_encode, esize)); | 2517 | pp_xref, pl::create<Pl_PNGFilter>(std::move(link), Pl_PNGFilter::a_encode, esize)); |
| 2461 | } else { | 2518 | } else { |
| 2462 | - activatePipelineStack(pp_xref, xref_data); | 2519 | + m->pipeline_stack.activate(pp_xref, xref_data); |
| 2463 | } | 2520 | } |
| 2464 | 2521 | ||
| 2465 | for (int i = first; i <= last; ++i) { | 2522 | for (int i = first; i <= last; ++i) { |
| @@ -2660,10 +2717,10 @@ QPDFWriter::writeLinearized() | @@ -2660,10 +2717,10 @@ QPDFWriter::writeLinearized() | ||
| 2660 | if (pass == 1) { | 2717 | if (pass == 1) { |
| 2661 | if (!m->lin_pass1_filename.empty()) { | 2718 | if (!m->lin_pass1_filename.empty()) { |
| 2662 | lin_pass1_file = QUtil::safe_fopen(m->lin_pass1_filename.c_str(), "wb"); | 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 | } else { | 2722 | } else { |
| 2666 | - activatePipelineStack(*pp_pass1, true); | 2723 | + m->pipeline_stack.activate(*pp_pass1, true); |
| 2667 | } | 2724 | } |
| 2668 | if (m->deterministic_id) { | 2725 | if (m->deterministic_id) { |
| 2669 | pushMD5Pipeline(*pp_md5); | 2726 | pushMD5Pipeline(*pp_md5); |
| @@ -2855,7 +2912,7 @@ QPDFWriter::writeLinearized() | @@ -2855,7 +2912,7 @@ QPDFWriter::writeLinearized() | ||
| 2855 | // Write hint stream to a buffer | 2912 | // Write hint stream to a buffer |
| 2856 | { | 2913 | { |
| 2857 | PipelinePopper pp_hint(this); | 2914 | PipelinePopper pp_hint(this); |
| 2858 | - activatePipelineStack(pp_hint, hint_buffer); | 2915 | + m->pipeline_stack.activate(pp_hint, hint_buffer); |
| 2859 | writeHintStream(hint_id); | 2916 | writeHintStream(hint_id); |
| 2860 | } | 2917 | } |
| 2861 | hint_length = QIntC::to_offset(hint_buffer.size()); | 2918 | hint_length = QIntC::to_offset(hint_buffer.size()); |