Commit 61879f9a09073e1e18e29676b95ba1b11003d375

Authored by m-holger
1 parent 8486b9de

Refactor `QPDFWriter`: replace `pdf` with `qpdf`, streamline `Writer` class, and…

… improve encapsulation.
Showing 1 changed file with 29 additions and 28 deletions
libqpdf/QPDFWriter.cc
@@ -27,7 +27,8 @@ @@ -27,7 +27,8 @@
27 using namespace std::literals; 27 using namespace std::literals;
28 using namespace qpdf; 28 using namespace qpdf;
29 29
30 -using Encryption = QPDF::Doc::Encryption; 30 +using Doc = QPDF::Doc;
  31 +using Encryption = Doc::Encryption;
31 32
32 QPDFWriter::ProgressReporter::~ProgressReporter() // NOLINT (modernize-use-equals-default) 33 QPDFWriter::ProgressReporter::~ProgressReporter() // NOLINT (modernize-use-equals-default)
33 { 34 {
@@ -262,13 +263,13 @@ Pl_stack::Popper::pop() @@ -262,13 +263,13 @@ Pl_stack::Popper::pop()
262 } 263 }
263 264
264 // Writer class is restricted to QPDFWriter so that only it can call certain methods. 265 // Writer class is restricted to QPDFWriter so that only it can call certain methods.
265 -class QPDF::Doc::Writer 266 +class Doc::Writer: Doc::Common
266 { 267 {
267 friend class QPDFWriter; 268 friend class QPDFWriter;
268 - Writer(QPDF& pdf) :  
269 - pdf(pdf),  
270 - lin(pdf.m->lin),  
271 - objects(pdf.m->objects) 269 + Writer(QPDF& qpdf) :
  270 + Common(qpdf, qpdf.doc().m),
  271 + lin(m->lin),
  272 + objects(m->objects)
272 { 273 {
273 } 274 }
274 275
@@ -326,10 +327,9 @@ class QPDF::Doc::Writer @@ -326,10 +327,9 @@ class QPDF::Doc::Writer
326 size_t 327 size_t
327 tableSize() 328 tableSize()
328 { 329 {
329 - return pdf.m->objects.tableSize(); 330 + return qpdf.m->objects.tableSize();
330 } 331 }
331 332
332 - QPDF& pdf;  
333 QPDF::Doc::Linearization& lin; 333 QPDF::Doc::Linearization& lin;
334 QPDF::Doc::Objects& objects; 334 QPDF::Doc::Objects& objects;
335 }; 335 };
@@ -352,7 +352,8 @@ class QPDFWriter::Members: QPDF::Doc::Writer @@ -352,7 +352,8 @@ class QPDFWriter::Members: QPDF::Doc::Writer
352 QPDF::Doc::Writer(pdf), 352 QPDF::Doc::Writer(pdf),
353 w(w), 353 w(w),
354 root_og( 354 root_og(
355 - pdf.getRoot().getObjGen().isIndirect() ? pdf.getRoot().getObjGen() : QPDFObjGen(-1, 0)), 355 + qpdf.getRoot().getObjGen().isIndirect() ? qpdf.getRoot().getObjGen()
  356 + : QPDFObjGen(-1, 0)),
356 pipeline_stack(pipeline) 357 pipeline_stack(pipeline)
357 { 358 {
358 } 359 }
@@ -1372,7 +1373,7 @@ QPDFWriter::Members::enqueueObject(QPDFObjectHandle object) @@ -1372,7 +1373,7 @@ QPDFWriter::Members::enqueueObject(QPDFObjectHandle object)
1372 // object to have an owning QPDF that is from another file if a direct QPDFObjectHandle from 1373 // object to have an owning QPDF that is from another file if a direct QPDFObjectHandle from
1373 // one file was insert into another file without copying. Doing that is safe even if the 1374 // one file was insert into another file without copying. Doing that is safe even if the
1374 // original QPDF gets destroyed, which just disconnects the QPDFObjectHandle from its owner. 1375 // original QPDF gets destroyed, which just disconnects the QPDFObjectHandle from its owner.
1375 - if (object.getOwningQPDF() != &pdf) { 1376 + if (object.getOwningQPDF() != &qpdf) {
1376 throw std::logic_error( 1377 throw std::logic_error(
1377 "QPDFObjectHandle from different QPDF found while writing. Use " 1378 "QPDFObjectHandle from different QPDF found while writing. Use "
1378 "QPDF::copyForeignObject to add objects from another file."); 1379 "QPDF::copyForeignObject to add objects from another file.");
@@ -1396,7 +1397,7 @@ QPDFWriter::Members::enqueueObject(QPDFObjectHandle object) @@ -1396,7 +1397,7 @@ QPDFWriter::Members::enqueueObject(QPDFObjectHandle object)
1396 // stream. Object streams always have generation 0. 1397 // stream. Object streams always have generation 0.
1397 // Detect loops by storing invalid object ID -1, which will get overwritten later. 1398 // Detect loops by storing invalid object ID -1, which will get overwritten later.
1398 o.renumber = -1; 1399 o.renumber = -1;
1399 - enqueueObject(pdf.getObject(o.object_stream, 0)); 1400 + enqueueObject(qpdf.getObject(o.object_stream, 0));
1400 } else { 1401 } else {
1401 object_queue.emplace_back(object); 1402 object_queue.emplace_back(object);
1402 o.renumber = next_objid++; 1403 o.renumber = next_objid++;
@@ -1907,7 +1908,7 @@ QPDFWriter::Members::writeObjectStream(QPDFObjectHandle object) @@ -1907,7 +1908,7 @@ QPDFWriter::Members::writeObjectStream(QPDFObjectHandle object)
1907 // reporting, decrement in pass 1. 1908 // reporting, decrement in pass 1.
1908 indicateProgress(true, false); 1909 indicateProgress(true, false);
1909 1910
1910 - QPDFObjectHandle obj_to_write = pdf.getObject(og); 1911 + QPDFObjectHandle obj_to_write = qpdf.getObject(og);
1911 if (obj_to_write.isStream()) { 1912 if (obj_to_write.isStream()) {
1912 // This condition occurred in a fuzz input. Ideally we should block it at parse 1913 // This condition occurred in a fuzz input. Ideally we should block it at parse
1913 // time, but it's not clear to me how to construct a case for this. 1914 // time, but it's not clear to me how to construct a case for this.
@@ -2024,7 +2025,7 @@ QPDFWriter::Members::writeObject(QPDFObjectHandle object, int object_stream_inde @@ -2024,7 +2025,7 @@ QPDFWriter::Members::writeObject(QPDFObjectHandle object, int object_stream_inde
2024 std::string 2025 std::string
2025 QPDFWriter::Members::getOriginalID1() 2026 QPDFWriter::Members::getOriginalID1()
2026 { 2027 {
2027 - QPDFObjectHandle trailer = pdf.getTrailer(); 2028 + QPDFObjectHandle trailer = qpdf.getTrailer();
2028 if (trailer.hasKey("/ID")) { 2029 if (trailer.hasKey("/ID")) {
2029 return trailer.getKey("/ID").getArrayItem(0).getStringValue(); 2030 return trailer.getKey("/ID").getArrayItem(0).getStringValue();
2030 } else { 2031 } else {
@@ -2042,7 +2043,7 @@ QPDFWriter::Members::generateID(bool encrypted) @@ -2042,7 +2043,7 @@ QPDFWriter::Members::generateID(bool encrypted)
2042 return; 2043 return;
2043 } 2044 }
2044 2045
2045 - QPDFObjectHandle trailer = pdf.getTrailer(); 2046 + QPDFObjectHandle trailer = qpdf.getTrailer();
2046 2047
2047 std::string result; 2048 std::string result;
2048 2049
@@ -2126,7 +2127,7 @@ void @@ -2126,7 +2127,7 @@ void
2126 QPDFWriter::Members::initializeSpecialStreams() 2127 QPDFWriter::Members::initializeSpecialStreams()
2127 { 2128 {
2128 // Mark all page content streams in case we are filtering or normalizing. 2129 // Mark all page content streams in case we are filtering or normalizing.
2129 - std::vector<QPDFObjectHandle> pages = pdf.getAllPages(); 2130 + std::vector<QPDFObjectHandle> pages = qpdf.getAllPages();
2130 int num = 0; 2131 int num = 0;
2131 for (auto& page: pages) { 2132 for (auto& page: pages) {
2132 page_object_to_seq[page.getObjGen()] = ++num; 2133 page_object_to_seq[page.getObjGen()] = ++num;
@@ -2220,13 +2221,13 @@ QPDFWriter::Members::generateObjectStreams() @@ -2220,13 +2221,13 @@ QPDFWriter::Members::generateObjectStreams()
2220 ++n_per; 2221 ++n_per;
2221 } 2222 }
2222 unsigned int n = 0; 2223 unsigned int n = 0;
2223 - int cur_ostream = pdf.newIndirectNull().getObjectID(); 2224 + int cur_ostream = qpdf.newIndirectNull().getObjectID();
2224 for (auto const& item: eligible) { 2225 for (auto const& item: eligible) {
2225 if (n == n_per) { 2226 if (n == n_per) {
2226 n = 0; 2227 n = 0;
2227 // Construct a new null object as the "original" object stream. The rest of the code 2228 // Construct a new null object as the "original" object stream. The rest of the code
2228 // knows that this means we're creating the object stream from scratch. 2229 // knows that this means we're creating the object stream from scratch.
2229 - cur_ostream = pdf.newIndirectNull().getObjectID(); 2230 + cur_ostream = qpdf.newIndirectNull().getObjectID();
2230 } 2231 }
2231 auto& o = obj[item]; 2232 auto& o = obj[item];
2232 o.object_stream = cur_ostream; 2233 o.object_stream = cur_ostream;
@@ -2240,7 +2241,7 @@ QPDFWriter::Members::trimmed_trailer() @@ -2240,7 +2241,7 @@ QPDFWriter::Members::trimmed_trailer()
2240 { 2241 {
2241 // Remove keys from the trailer that necessarily have to be replaced when writing the file. 2242 // Remove keys from the trailer that necessarily have to be replaced when writing the file.
2242 2243
2243 - Dictionary trailer = pdf.getTrailer().unsafeShallowCopy(); 2244 + Dictionary trailer = qpdf.getTrailer().unsafeShallowCopy();
2244 2245
2245 // Remove encryption keys 2246 // Remove encryption keys
2246 trailer.erase("/ID"); 2247 trailer.erase("/ID");
@@ -2265,8 +2266,8 @@ QPDFWriter::Members::trimmed_trailer() @@ -2265,8 +2266,8 @@ QPDFWriter::Members::trimmed_trailer()
2265 void 2266 void
2266 QPDFWriter::Members::prepareFileForWrite() 2267 QPDFWriter::Members::prepareFileForWrite()
2267 { 2268 {
2268 - pdf.fixDanglingReferences();  
2269 - auto root = pdf.getRoot(); 2269 + qpdf.fixDanglingReferences();
  2270 + auto root = qpdf.getRoot();
2270 auto oh = root.getKey("/Extensions"); 2271 auto oh = root.getKey("/Extensions");
2271 if (oh.isDictionary()) { 2272 if (oh.isDictionary()) {
2272 const bool extensions_indirect = oh.isIndirect(); 2273 const bool extensions_indirect = oh.isIndirect();
@@ -2335,7 +2336,7 @@ QPDFWriter::Members::doWriteSetup() @@ -2335,7 +2336,7 @@ QPDFWriter::Members::doWriteSetup()
2335 } 2336 }
2336 2337
2337 if (preserve_encryption) { 2338 if (preserve_encryption) {
2338 - copyEncryptionParameters(pdf); 2339 + copyEncryptionParameters(qpdf);
2339 } 2340 }
2340 2341
2341 if (!forced_pdf_version.empty()) { 2342 if (!forced_pdf_version.empty()) {
@@ -2380,7 +2381,7 @@ QPDFWriter::Members::doWriteSetup() @@ -2380,7 +2381,7 @@ QPDFWriter::Members::doWriteSetup()
2380 if (!obj.streams_empty) { 2381 if (!obj.streams_empty) {
2381 if (linearized) { 2382 if (linearized) {
2382 // Page dictionaries are not allowed to be compressed objects. 2383 // Page dictionaries are not allowed to be compressed objects.
2383 - for (auto& page: pdf.getAllPages()) { 2384 + for (auto& page: qpdf.getAllPages()) {
2384 if (obj[page].object_stream > 0) { 2385 if (obj[page].object_stream > 0) {
2385 obj[page].object_stream = 0; 2386 obj[page].object_stream = 0;
2386 } 2387 }
@@ -2416,7 +2417,7 @@ QPDFWriter::Members::doWriteSetup() @@ -2416,7 +2417,7 @@ QPDFWriter::Members::doWriteSetup()
2416 } 2417 }
2417 } 2418 }
2418 2419
2419 - setMinimumPDFVersion(pdf.getPDFVersion(), pdf.getExtensionLevel()); 2420 + setMinimumPDFVersion(qpdf.getPDFVersion(), qpdf.getExtensionLevel());
2420 final_pdf_version = min_pdf_version; 2421 final_pdf_version = min_pdf_version;
2421 final_extension_level = min_extension_level; 2422 final_extension_level = min_extension_level;
2422 if (!forced_pdf_version.empty()) { 2423 if (!forced_pdf_version.empty()) {
@@ -2438,7 +2439,7 @@ QPDFWriter::Members::write() @@ -2438,7 +2439,7 @@ QPDFWriter::Members::write()
2438 2439
2439 // Set up progress reporting. For linearized files, we write two passes. events_expected is an 2440 // Set up progress reporting. For linearized files, we write two passes. events_expected is an
2440 // approximation, but it's good enough for progress reporting, which is mostly a guess anyway. 2441 // approximation, but it's good enough for progress reporting, which is mostly a guess anyway.
2441 - events_expected = QIntC::to_int(pdf.getObjectCount() * (linearized ? 2 : 1)); 2442 + events_expected = QIntC::to_int(qpdf.getObjectCount() * (linearized ? 2 : 1));
2442 2443
2443 prepareFileForWrite(); 2444 prepareFileForWrite();
2444 2445
@@ -2910,7 +2911,7 @@ QPDFWriter::Members::writeLinearized() @@ -2910,7 +2911,7 @@ QPDFWriter::Members::writeLinearized()
2910 openObject(lindict_id); 2911 openObject(lindict_id);
2911 write("<<"); 2912 write("<<");
2912 if (pass == 2) { 2913 if (pass == 2) {
2913 - std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages(); 2914 + std::vector<QPDFObjectHandle> const& pages = qpdf.getAllPages();
2914 int first_page_object = obj[pages.at(0)].renumber; 2915 int first_page_object = obj[pages.at(0)].renumber;
2915 2916
2916 write(" /Linearized 1 /L ").write(file_size + hint_length); 2917 write(" /Linearized 1 /L ").write(file_size + hint_length);
@@ -3110,7 +3111,7 @@ void @@ -3110,7 +3111,7 @@ void
3110 QPDFWriter::Members::enqueueObjectsStandard() 3111 QPDFWriter::Members::enqueueObjectsStandard()
3111 { 3112 {
3112 if (preserve_unreferenced_objects) { 3113 if (preserve_unreferenced_objects) {
3113 - for (auto const& oh: pdf.getAllObjects()) { 3114 + for (auto const& oh: qpdf.getAllObjects()) {
3114 enqueueObject(oh); 3115 enqueueObject(oh);
3115 } 3116 }
3116 } 3117 }
@@ -3136,7 +3137,7 @@ QPDFWriter::Members::enqueueObjectsPCLm() @@ -3136,7 +3137,7 @@ QPDFWriter::Members::enqueueObjectsPCLm()
3136 std::string image_transform_content = "q /image Do Q\n"; 3137 std::string image_transform_content = "q /image Do Q\n";
3137 3138
3138 // enqueue all pages first 3139 // enqueue all pages first
3139 - std::vector<QPDFObjectHandle> all = pdf.getAllPages(); 3140 + std::vector<QPDFObjectHandle> all = qpdf.getAllPages();
3140 for (auto& page: all) { 3141 for (auto& page: all) {
3141 // enqueue page 3142 // enqueue page
3142 enqueueObject(page); 3143 enqueueObject(page);
@@ -3149,7 +3150,7 @@ QPDFWriter::Members::enqueueObjectsPCLm() @@ -3149,7 +3150,7 @@ QPDFWriter::Members::enqueueObjectsPCLm()
3149 for (auto& image: strips.as_dictionary()) { 3150 for (auto& image: strips.as_dictionary()) {
3150 if (!image.second.null()) { 3151 if (!image.second.null()) {
3151 enqueueObject(image.second); 3152 enqueueObject(image.second);
3152 - enqueueObject(QPDFObjectHandle::newStream(&pdf, image_transform_content)); 3153 + enqueueObject(QPDFObjectHandle::newStream(&qpdf, image_transform_content));
3153 } 3154 }
3154 } 3155 }
3155 } 3156 }