Commit 83144b29a9408b42b2cda4ad3eda64689cc3a7ff

Authored by m-holger
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.
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&amp;&amp;... args) @@ -887,79 +1014,9 @@ QPDFWriter::write_no_qdf(Args&amp;&amp;... 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&amp; pp) @@ -991,11 +1048,11 @@ QPDFWriter::pushEncryptionFilter(PipelinePopper&amp; 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&amp; pp) @@ -1012,8 +1069,8 @@ QPDFWriter::pushMD5Pipeline(PipelinePopper&amp; 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());