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 27 using namespace std::literals;
28 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 33 QPDFWriter::ProgressReporter::~ProgressReporter() // NOLINT (modernize-use-equals-default)
33 34 {
... ... @@ -262,13 +263,13 @@ Pl_stack::Popper::pop()
262 263 }
263 264  
264 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 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 327 size_t
327 328 tableSize()
328 329 {
329   - return pdf.m->objects.tableSize();
  330 + return qpdf.m->objects.tableSize();
330 331 }
331 332  
332   - QPDF& pdf;
333 333 QPDF::Doc::Linearization& lin;
334 334 QPDF::Doc::Objects& objects;
335 335 };
... ... @@ -352,7 +352,8 @@ class QPDFWriter::Members: QPDF::Doc::Writer
352 352 QPDF::Doc::Writer(pdf),
353 353 w(w),
354 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 357 pipeline_stack(pipeline)
357 358 {
358 359 }
... ... @@ -1372,7 +1373,7 @@ QPDFWriter::Members::enqueueObject(QPDFObjectHandle object)
1372 1373 // object to have an owning QPDF that is from another file if a direct QPDFObjectHandle from
1373 1374 // one file was insert into another file without copying. Doing that is safe even if the
1374 1375 // original QPDF gets destroyed, which just disconnects the QPDFObjectHandle from its owner.
1375   - if (object.getOwningQPDF() != &pdf) {
  1376 + if (object.getOwningQPDF() != &qpdf) {
1376 1377 throw std::logic_error(
1377 1378 "QPDFObjectHandle from different QPDF found while writing. Use "
1378 1379 "QPDF::copyForeignObject to add objects from another file.");
... ... @@ -1396,7 +1397,7 @@ QPDFWriter::Members::enqueueObject(QPDFObjectHandle object)
1396 1397 // stream. Object streams always have generation 0.
1397 1398 // Detect loops by storing invalid object ID -1, which will get overwritten later.
1398 1399 o.renumber = -1;
1399   - enqueueObject(pdf.getObject(o.object_stream, 0));
  1400 + enqueueObject(qpdf.getObject(o.object_stream, 0));
1400 1401 } else {
1401 1402 object_queue.emplace_back(object);
1402 1403 o.renumber = next_objid++;
... ... @@ -1907,7 +1908,7 @@ QPDFWriter::Members::writeObjectStream(QPDFObjectHandle object)
1907 1908 // reporting, decrement in pass 1.
1908 1909 indicateProgress(true, false);
1909 1910  
1910   - QPDFObjectHandle obj_to_write = pdf.getObject(og);
  1911 + QPDFObjectHandle obj_to_write = qpdf.getObject(og);
1911 1912 if (obj_to_write.isStream()) {
1912 1913 // This condition occurred in a fuzz input. Ideally we should block it at parse
1913 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 2025 std::string
2025 2026 QPDFWriter::Members::getOriginalID1()
2026 2027 {
2027   - QPDFObjectHandle trailer = pdf.getTrailer();
  2028 + QPDFObjectHandle trailer = qpdf.getTrailer();
2028 2029 if (trailer.hasKey("/ID")) {
2029 2030 return trailer.getKey("/ID").getArrayItem(0).getStringValue();
2030 2031 } else {
... ... @@ -2042,7 +2043,7 @@ QPDFWriter::Members::generateID(bool encrypted)
2042 2043 return;
2043 2044 }
2044 2045  
2045   - QPDFObjectHandle trailer = pdf.getTrailer();
  2046 + QPDFObjectHandle trailer = qpdf.getTrailer();
2046 2047  
2047 2048 std::string result;
2048 2049  
... ... @@ -2126,7 +2127,7 @@ void
2126 2127 QPDFWriter::Members::initializeSpecialStreams()
2127 2128 {
2128 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 2131 int num = 0;
2131 2132 for (auto& page: pages) {
2132 2133 page_object_to_seq[page.getObjGen()] = ++num;
... ... @@ -2220,13 +2221,13 @@ QPDFWriter::Members::generateObjectStreams()
2220 2221 ++n_per;
2221 2222 }
2222 2223 unsigned int n = 0;
2223   - int cur_ostream = pdf.newIndirectNull().getObjectID();
  2224 + int cur_ostream = qpdf.newIndirectNull().getObjectID();
2224 2225 for (auto const& item: eligible) {
2225 2226 if (n == n_per) {
2226 2227 n = 0;
2227 2228 // Construct a new null object as the "original" object stream. The rest of the code
2228 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 2232 auto& o = obj[item];
2232 2233 o.object_stream = cur_ostream;
... ... @@ -2240,7 +2241,7 @@ QPDFWriter::Members::trimmed_trailer()
2240 2241 {
2241 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 2246 // Remove encryption keys
2246 2247 trailer.erase("/ID");
... ... @@ -2265,8 +2266,8 @@ QPDFWriter::Members::trimmed_trailer()
2265 2266 void
2266 2267 QPDFWriter::Members::prepareFileForWrite()
2267 2268 {
2268   - pdf.fixDanglingReferences();
2269   - auto root = pdf.getRoot();
  2269 + qpdf.fixDanglingReferences();
  2270 + auto root = qpdf.getRoot();
2270 2271 auto oh = root.getKey("/Extensions");
2271 2272 if (oh.isDictionary()) {
2272 2273 const bool extensions_indirect = oh.isIndirect();
... ... @@ -2335,7 +2336,7 @@ QPDFWriter::Members::doWriteSetup()
2335 2336 }
2336 2337  
2337 2338 if (preserve_encryption) {
2338   - copyEncryptionParameters(pdf);
  2339 + copyEncryptionParameters(qpdf);
2339 2340 }
2340 2341  
2341 2342 if (!forced_pdf_version.empty()) {
... ... @@ -2380,7 +2381,7 @@ QPDFWriter::Members::doWriteSetup()
2380 2381 if (!obj.streams_empty) {
2381 2382 if (linearized) {
2382 2383 // Page dictionaries are not allowed to be compressed objects.
2383   - for (auto& page: pdf.getAllPages()) {
  2384 + for (auto& page: qpdf.getAllPages()) {
2384 2385 if (obj[page].object_stream > 0) {
2385 2386 obj[page].object_stream = 0;
2386 2387 }
... ... @@ -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 2421 final_pdf_version = min_pdf_version;
2421 2422 final_extension_level = min_extension_level;
2422 2423 if (!forced_pdf_version.empty()) {
... ... @@ -2438,7 +2439,7 @@ QPDFWriter::Members::write()
2438 2439  
2439 2440 // Set up progress reporting. For linearized files, we write two passes. events_expected is an
2440 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 2444 prepareFileForWrite();
2444 2445  
... ... @@ -2910,7 +2911,7 @@ QPDFWriter::Members::writeLinearized()
2910 2911 openObject(lindict_id);
2911 2912 write("<<");
2912 2913 if (pass == 2) {
2913   - std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages();
  2914 + std::vector<QPDFObjectHandle> const& pages = qpdf.getAllPages();
2914 2915 int first_page_object = obj[pages.at(0)].renumber;
2915 2916  
2916 2917 write(" /Linearized 1 /L ").write(file_size + hint_length);
... ... @@ -3110,7 +3111,7 @@ void
3110 3111 QPDFWriter::Members::enqueueObjectsStandard()
3111 3112 {
3112 3113 if (preserve_unreferenced_objects) {
3113   - for (auto const& oh: pdf.getAllObjects()) {
  3114 + for (auto const& oh: qpdf.getAllObjects()) {
3114 3115 enqueueObject(oh);
3115 3116 }
3116 3117 }
... ... @@ -3136,7 +3137,7 @@ QPDFWriter::Members::enqueueObjectsPCLm()
3136 3137 std::string image_transform_content = "q /image Do Q\n";
3137 3138  
3138 3139 // enqueue all pages first
3139   - std::vector<QPDFObjectHandle> all = pdf.getAllPages();
  3140 + std::vector<QPDFObjectHandle> all = qpdf.getAllPages();
3140 3141 for (auto& page: all) {
3141 3142 // enqueue page
3142 3143 enqueueObject(page);
... ... @@ -3149,7 +3150,7 @@ QPDFWriter::Members::enqueueObjectsPCLm()
3149 3150 for (auto& image: strips.as_dictionary()) {
3150 3151 if (!image.second.null()) {
3151 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 }
... ...