Commit 7db44e260e5079b1b2647f185a852287ed10799c

Authored by m-holger
1 parent 6408d5cd

Refactor `QPDFWriter`: move configuration logic to `Config` methods, encapsulate…

… parameter handling, and adjust related method calls for improved maintainability and readability.
libqpdf/QPDFWriter.cc
... ... @@ -28,6 +28,7 @@ using namespace std::literals;
28 28 using namespace qpdf;
29 29  
30 30 using Encryption = impl::Doc::Encryption;
  31 +using Config = Writer::Config;
31 32  
32 33 QPDFWriter::ProgressReporter::~ProgressReporter() // NOLINT (modernize-use-equals-default)
33 34 {
... ... @@ -305,32 +306,32 @@ namespace qpdf::impl
305 306 void doWriteSetup();
306 307 void prepareFileForWrite();
307 308  
308   - void disableIncompatibleEncryption(int major, int minor, int extension_level);
309   - void interpretR3EncryptionParameters(
310   - bool allow_accessibility,
311   - bool allow_extract,
312   - bool allow_assemble,
313   - bool allow_annotate_and_form,
314   - bool allow_form_filling,
315   - bool allow_modify_other,
316   - qpdf_r3_print_e print,
317   - qpdf_r3_modify_e modify);
318   - void setEncryptionParameters(char const* user_password, char const* owner_password);
319   - void setEncryptionMinimumVersion();
320   - void parseVersion(std::string const& version, int& major, int& minor) const;
321   - int compareVersions(int major1, int minor1, int major2, int minor2) const;
322   - void generateID(bool encrypted);
323   - std::string getOriginalID1();
324   - void initializeTables(size_t extra = 0);
325   - void preserveObjectStreams();
326   - void generateObjectStreams();
327   - void initializeSpecialStreams();
328   - void enqueue(QPDFObjectHandle const& object);
329   - void enqueueObjectsStandard();
330   - void enqueueObjectsPCLm();
331   - void enqueuePart(std::vector<QPDFObjectHandle>& part);
332   - void assignCompressedObjectNumbers(QPDFObjGen og);
333   - Dictionary trimmed_trailer();
  309 + void disableIncompatibleEncryption(int major, int minor, int extension_level);
  310 + void interpretR3EncryptionParameters(
  311 + bool allow_accessibility,
  312 + bool allow_extract,
  313 + bool allow_assemble,
  314 + bool allow_annotate_and_form,
  315 + bool allow_form_filling,
  316 + bool allow_modify_other,
  317 + qpdf_r3_print_e print,
  318 + qpdf_r3_modify_e modify);
  319 + void setEncryptionParameters(char const* user_password, char const* owner_password);
  320 + void setEncryptionMinimumVersion();
  321 + void parseVersion(std::string const& version, int& major, int& minor) const;
  322 + int compareVersions(int major1, int minor1, int major2, int minor2) const;
  323 + void generateID(bool encrypted);
  324 + std::string getOriginalID1();
  325 + void initializeTables(size_t extra = 0);
  326 + void preserveObjectStreams();
  327 + void generateObjectStreams();
  328 + void initializeSpecialStreams();
  329 + void enqueue(QPDFObjectHandle const& object);
  330 + void enqueueObjectsStandard();
  331 + void enqueueObjectsPCLm();
  332 + void enqueuePart(std::vector<QPDFObjectHandle>& part);
  333 + void assignCompressedObjectNumbers(QPDFObjGen og);
  334 + Dictionary trimmed_trailer();
334 335  
335 336 // Returns tuple<filter, compress_stream, is_root_metadata>
336 337 std::tuple<const bool, const bool, const bool>
... ... @@ -557,75 +558,110 @@ QPDFWriter::setOutputPipeline(Pipeline* p)
557 558 void
558 559 QPDFWriter::setObjectStreamMode(qpdf_object_stream_e mode)
559 560 {
560   - m->cfg.object_stream_mode_ = mode;
  561 + m->cfg.object_streams(mode);
561 562 }
562 563  
563 564 void
564 565 QPDFWriter::setStreamDataMode(qpdf_stream_data_e mode)
565 566 {
  567 + m->cfg.stream_data(mode);
  568 +}
  569 +
  570 +Config&
  571 +Config::stream_data(qpdf_stream_data_e mode)
  572 +{
566 573 switch (mode) {
567 574 case qpdf_s_uncompress:
568   - m->cfg.stream_decode_level_ = std::max(qpdf_dl_generalized, m->cfg.stream_decode_level_);
569   - m->cfg.compress_streams_ = false;
570   - break;
  575 + stream_decode_level(std::max(qpdf_dl_generalized, stream_decode_level_));
  576 + compress_streams(false);
  577 + return *this;
571 578  
572 579 case qpdf_s_preserve:
573   - m->cfg.stream_decode_level_ = qpdf_dl_none;
574   - m->cfg.compress_streams_ = false;
575   - break;
  580 + stream_decode_level(qpdf_dl_none);
  581 + compress_streams(false);
  582 + return *this;
576 583  
577 584 case qpdf_s_compress:
578   - m->cfg.stream_decode_level_ = std::max(qpdf_dl_generalized, m->cfg.stream_decode_level_);
579   - m->cfg.compress_streams_ = true;
580   - break;
  585 + stream_decode_level(std::max(qpdf_dl_generalized, stream_decode_level_));
  586 + compress_streams(true);
581 587 }
582   - m->cfg.stream_decode_level_set_ = true;
583   - m->cfg.compress_streams_set_ = true;
  588 + return *this;
584 589 }
585 590  
586 591 void
587 592 QPDFWriter::setCompressStreams(bool val)
588 593 {
589   - m->cfg.compress_streams_ = val;
590   - m->cfg.compress_streams_set_ = true;
  594 + m->cfg.compress_streams(val);
  595 +}
  596 +
  597 +Config&
  598 +Config::compress_streams(bool val)
  599 +{
  600 + if (pclm_) {
  601 + usage("compress_streams cannot be set when pclm is set");
  602 + return *this;
  603 + }
  604 + compress_streams_set_ = true;
  605 + compress_streams_ = val;
  606 + return *this;
591 607 }
592 608  
593 609 void
594 610 QPDFWriter::setDecodeLevel(qpdf_stream_decode_level_e val)
595 611 {
596   - m->cfg.stream_decode_level_ = val;
597   - m->cfg.stream_decode_level_set_ = true;
  612 + m->cfg.stream_decode_level(val);
  613 +}
  614 +
  615 +Config&
  616 +Config::stream_decode_level(qpdf_stream_decode_level_e val)
  617 +{
  618 + if (pclm_) {
  619 + usage("stream_decode_level cannot be set when pclm is set");
  620 + return *this;
  621 + }
  622 + stream_decode_level_set_ = true;
  623 + stream_decode_level_ = val;
  624 + return *this;
598 625 }
599 626  
600 627 void
601 628 QPDFWriter::setRecompressFlate(bool val)
602 629 {
603   - m->cfg.recompress_flate_ = val;
  630 + m->cfg.recompress_flate(val);
604 631 }
605 632  
606 633 void
607 634 QPDFWriter::setContentNormalization(bool val)
608 635 {
609   - m->cfg.normalize_content_set_ = true;
610   - m->cfg.normalize_content_ = val;
  636 + m->cfg.normalize_content(val);
611 637 }
612 638  
613 639 void
614 640 QPDFWriter::setQDFMode(bool val)
615 641 {
616   - m->cfg.qdf_mode_ = val;
  642 + m->cfg.qdf(val);
  643 +}
  644 +
  645 +Config&
  646 +Config::qdf(bool val)
  647 +{
  648 + if (pclm_ || linearize_) {
  649 + usage("qdf cannot be set when linearize or pclm are set");
  650 + }
  651 + qdf_ = val;
  652 + return *this;
617 653 }
618 654  
619 655 void
620 656 QPDFWriter::setPreserveUnreferencedObjects(bool val)
621 657 {
622   - m->cfg.preserve_unreferenced_objects_ = val;
  658 + m->cfg.preserve_unreferenced(val);
623 659 }
624 660  
625 661 void
626 662 QPDFWriter::setNewlineBeforeEndstream(bool val)
627 663 {
628   - m->cfg.newline_before_endstream_ = val;
  664 + m->cfg.newline_before_endstream(val);
629 665 }
630 666  
631 667 void
... ... @@ -681,31 +717,37 @@ QPDFWriter::setMinimumPDFVersion(PDFVersion const&amp; v)
681 717 void
682 718 QPDFWriter::forcePDFVersion(std::string const& version, int extension_level)
683 719 {
684   - m->cfg.forced_pdf_version_ = version;
685   - m->cfg.forced_extension_level_ = extension_level;
  720 + m->cfg.forced_pdf_version(version, extension_level);
686 721 }
687 722  
688 723 void
689 724 QPDFWriter::setExtraHeaderText(std::string const& text)
690 725 {
691   - m->cfg.extra_header_text_ = text;
692   - if (!m->cfg.extra_header_text_.empty() && m->cfg.extra_header_text_.back() != '\n') {
693   - m->cfg.extra_header_text_ += "\n";
  726 + m->cfg.extra_header_text(text);
  727 +}
  728 +
  729 +Config&
  730 +Config::extra_header_text(std::string const& val)
  731 +{
  732 + extra_header_text_ = val;
  733 + if (!extra_header_text_.empty() && extra_header_text_.back() != '\n') {
  734 + extra_header_text_ += "\n";
694 735 } else {
695 736 QTC::TC("qpdf", "QPDFWriter extra header text no newline");
696 737 }
  738 + return *this;
697 739 }
698 740  
699 741 void
700 742 QPDFWriter::setStaticID(bool val)
701 743 {
702   - m->cfg.static_id_ = val;
  744 + m->cfg.static_id(val);
703 745 }
704 746  
705 747 void
706 748 QPDFWriter::setDeterministicID(bool val)
707 749 {
708   - m->cfg.deterministic_id_ = val;
  750 + m->cfg.deterministic_id(val);
709 751 }
710 752  
711 753 void
... ... @@ -719,37 +761,61 @@ QPDFWriter::setStaticAesIV(bool val)
719 761 void
720 762 QPDFWriter::setSuppressOriginalObjectIDs(bool val)
721 763 {
722   - m->cfg.suppress_original_object_ids_ = val;
  764 + m->cfg.suppress_original_object_ids(val);
723 765 }
724 766  
725 767 void
726 768 QPDFWriter::setPreserveEncryption(bool val)
727 769 {
728   - m->cfg.preserve_encryption_ = val;
  770 + m->cfg.preserve_encryption(val);
729 771 }
730 772  
731 773 void
732 774 QPDFWriter::setLinearization(bool val)
733 775 {
734   - m->cfg.linearized_ = val;
735   - if (val) {
736   - m->cfg.pclm_ = false;
  776 + m->cfg.linearize(val);
  777 +}
  778 +
  779 +Config&
  780 +Config::linearize(bool val)
  781 +{
  782 + if (pclm_ || qdf_) {
  783 + usage("linearize cannot be set when qdf or pclm are set");
  784 + return *this;
737 785 }
  786 + linearize_ = val;
  787 + return *this;
738 788 }
739 789  
740 790 void
741 791 QPDFWriter::setLinearizationPass1Filename(std::string const& filename)
742 792 {
743   - m->cfg.lin_pass1_filename_ = filename;
  793 + m->cfg.lin_pass1_filename(filename);
744 794 }
745 795  
746 796 void
747 797 QPDFWriter::setPCLm(bool val)
748 798 {
749   - m->cfg.pclm_ = val;
  799 + m->cfg.pclm(val);
  800 +}
  801 +
  802 +Config&
  803 +Config::pclm(bool val)
  804 +{
  805 + if (stream_decode_level_set_ || compress_streams_set_ || linearize_) {
  806 + usage(
  807 + "pclm cannot be set when stream_decode_level, compress_streams, linearize or qdf are "
  808 + "set");
  809 + return *this;
  810 + }
  811 + pclm_ = val;
750 812 if (val) {
751   - m->cfg.linearized_ = false;
  813 + stream_decode_level_ = qpdf_dl_none;
  814 + compress_streams_ = false;
  815 + linearize_ = false;
752 816 }
  817 +
  818 + return *this;
753 819 }
754 820  
755 821 void
... ... @@ -817,7 +883,7 @@ QPDFWriter::setR4EncryptionParametersInsecure(
817 883 bool use_aes)
818 884 {
819 885 m->encryption = std::make_unique<Encryption>(4, 4, 16, encrypt_metadata);
820   - m->cfg.encrypt_use_aes_ = use_aes;
  886 + m->cfg.encrypt_use_aes(use_aes);
821 887 m->interpretR3EncryptionParameters(
822 888 allow_accessibility,
823 889 allow_extract,
... ... @@ -844,7 +910,7 @@ QPDFWriter::setR5EncryptionParameters(
844 910 bool encrypt_metadata)
845 911 {
846 912 m->encryption = std::make_unique<Encryption>(5, 5, 32, encrypt_metadata);
847   - m->cfg.encrypt_use_aes_ = true;
  913 + m->cfg.encrypt_use_aes(true);
848 914 m->interpretR3EncryptionParameters(
849 915 allow_accessibility,
850 916 allow_extract,
... ... @@ -880,7 +946,7 @@ QPDFWriter::setR6EncryptionParameters(
880 946 allow_modify_other,
881 947 print,
882 948 qpdf_r3m_all);
883   - m->cfg.encrypt_use_aes_ = true;
  949 + m->cfg.encrypt_use_aes(true);
884 950 m->setEncryptionParameters(user_password, owner_password);
885 951 }
886 952  
... ... @@ -1001,7 +1067,7 @@ QPDFWriter::copyEncryptionParameters(QPDF&amp; qpdf)
1001 1067 void
1002 1068 impl::Writer::copyEncryptionParameters(QPDF& qpdf)
1003 1069 {
1004   - cfg.preserve_encryption_ = false;
  1070 + cfg.preserve_encryption(false);
1005 1071 QPDFObjectHandle trailer = qpdf.getTrailer();
1006 1072 if (trailer.hasKey("/Encrypt")) {
1007 1073 generateID(true);
... ... @@ -1021,10 +1087,10 @@ impl::Writer::copyEncryptionParameters(QPDF&amp; qpdf)
1021 1087 // Acrobat doesn't create files with V >= 4 that don't use AES, and the logic of
1022 1088 // figuring out whether AES is used or not is complicated with /StmF, /StrF, and /EFF
1023 1089 // all potentially having different values.
1024   - cfg.encrypt_use_aes_ = true;
  1090 + cfg.encrypt_use_aes(true);
1025 1091 }
1026 1092 QTC::TC("qpdf", "QPDFWriter copy encrypt metadata", encrypt_metadata ? 0 : 1);
1027   - QTC::TC("qpdf", "QPDFWriter copy use_aes", cfg.encrypt_use_aes_ ? 0 : 1);
  1093 + QTC::TC("qpdf", "QPDFWriter copy use_aes", cfg.encrypt_use_aes() ? 0 : 1);
1028 1094  
1029 1095 encryption = std::make_unique<Encryption>(
1030 1096 V,
... ... @@ -1065,7 +1131,7 @@ impl::Writer::disableIncompatibleEncryption(int major, int minor, int extension_
1065 1131 encryption = nullptr;
1066 1132 }
1067 1133 } else if (compareVersions(major, minor, 1, 6) < 0) {
1068   - if (cfg.encrypt_use_aes_) {
  1134 + if (cfg.encrypt_use_aes()) {
1069 1135 encryption = nullptr;
1070 1136 }
1071 1137 } else if (
... ... @@ -1122,7 +1188,7 @@ impl::Writer::setEncryptionMinimumVersion()
1122 1188 } else if (R == 5) {
1123 1189 setMinimumPDFVersion("1.7", 3);
1124 1190 } else if (R == 4) {
1125   - setMinimumPDFVersion(cfg.encrypt_use_aes_ ? "1.6" : "1.5");
  1191 + setMinimumPDFVersion(cfg.encrypt_use_aes() ? "1.6" : "1.5");
1126 1192 } else if (R == 3) {
1127 1193 setMinimumPDFVersion("1.4");
1128 1194 } else {
... ... @@ -1135,7 +1201,12 @@ impl::Writer::setDataKey(int objid)
1135 1201 {
1136 1202 if (encryption) {
1137 1203 cur_data_key = QPDF::compute_data_key(
1138   - encryption_key, objid, 0, cfg.encrypt_use_aes_, encryption->getV(), encryption->getR());
  1204 + encryption_key,
  1205 + objid,
  1206 + 0,
  1207 + cfg.encrypt_use_aes(),
  1208 + encryption->getV(),
  1209 + encryption->getR());
1139 1210 }
1140 1211 }
1141 1212  
... ... @@ -1203,7 +1274,7 @@ template &lt;typename... Args&gt;
1203 1274 impl::Writer&
1204 1275 impl::Writer::write_qdf(Args&&... args)
1205 1276 {
1206   - if (cfg.qdf_mode_) {
  1277 + if (cfg.qdf()) {
1207 1278 pipeline->write(std::forward<Args>(args)...);
1208 1279 }
1209 1280 return *this;
... ... @@ -1213,7 +1284,7 @@ template &lt;typename... Args&gt;
1213 1284 impl::Writer&
1214 1285 impl::Writer::write_no_qdf(Args&&... args)
1215 1286 {
1216   - if (!cfg.qdf_mode_) {
  1287 + if (!cfg.qdf()) {
1217 1288 pipeline->write(std::forward<Args>(args)...);
1218 1289 }
1219 1290 return *this;
... ... @@ -1222,7 +1293,7 @@ impl::Writer::write_no_qdf(Args&amp;&amp;... args)
1222 1293 void
1223 1294 impl::Writer::adjustAESStreamLength(size_t& length)
1224 1295 {
1225   - if (encryption && !cur_data_key.empty() && cfg.encrypt_use_aes_) {
  1296 + if (encryption && !cur_data_key.empty() && cfg.encrypt_use_aes()) {
1226 1297 // Stream length will be padded with 1 to 16 bytes to end up as a multiple of 16. It will
1227 1298 // also be prepended by 16 bits of random data.
1228 1299 length += 32 - (length & 0xf);
... ... @@ -1234,7 +1305,7 @@ impl::Writer::write_encrypted(std::string_view str)
1234 1305 {
1235 1306 if (!(encryption && !cur_data_key.empty())) {
1236 1307 write(str);
1237   - } else if (cfg.encrypt_use_aes_) {
  1308 + } else if (cfg.encrypt_use_aes()) {
1238 1309 write(pl::pipe<Pl_AES_PDF>(str, true, cur_data_key));
1239 1310 } else {
1240 1311 write(pl::pipe<Pl_RC4>(str, cur_data_key));
... ... @@ -1305,7 +1376,7 @@ impl::Writer::enqueue(QPDFObjectHandle const&amp; object)
1305 1376 "Use QPDF::copyForeignObject to add objects from another file." //
1306 1377 );
1307 1378  
1308   - if (cfg.qdf_mode_ && object.isStreamOfType("/XRef")) {
  1379 + if (cfg.qdf() && object.isStreamOfType("/XRef")) {
1309 1380 // As a special case, do not output any extraneous XRef streams in QDF mode. Doing so
1310 1381 // will confuse fix-qdf, which expects to see only one XRef stream at the end of the
1311 1382 // file. This case can occur when creating a QDF from a file with object streams when
... ... @@ -1331,10 +1402,10 @@ impl::Writer::enqueue(QPDFObjectHandle const&amp; object)
1331 1402 if (og.getGen() == 0 && object_stream_to_objects.contains(og.getObj())) {
1332 1403 // For linearized files, uncompressed objects go at end, and we take care of
1333 1404 // assigning numbers to them elsewhere.
1334   - if (!cfg.linearized_) {
  1405 + if (!cfg.linearize()) {
1335 1406 assignCompressedObjectNumbers(og);
1336 1407 }
1337   - } else if (!cfg.direct_stream_lengths_ && object.isStream()) {
  1408 + } else if (!cfg.direct_stream_lengths() && object.isStream()) {
1338 1409 // reserve next object ID for length
1339 1410 ++next_objid;
1340 1411 }
... ... @@ -1343,7 +1414,7 @@ impl::Writer::enqueue(QPDFObjectHandle const&amp; object)
1343 1414 return;
1344 1415 }
1345 1416  
1346   - if (cfg.linearized_) {
  1417 + if (cfg.linearize()) {
1347 1418 return;
1348 1419 }
1349 1420  
... ... @@ -1364,7 +1435,7 @@ impl::Writer::enqueue(QPDFObjectHandle const&amp; object)
1364 1435 void
1365 1436 impl::Writer::unparseChild(QPDFObjectHandle const& child, size_t level, int flags)
1366 1437 {
1367   - if (!cfg.linearized_) {
  1438 + if (!cfg.linearize()) {
1368 1439 enqueue(child);
1369 1440 }
1370 1441 if (child.indirect()) {
... ... @@ -1423,7 +1494,7 @@ impl::Writer::writeTrailer(
1423 1494 }
1424 1495 write("<00000000000000000000000000000000>");
1425 1496 } else {
1426   - if (linearization_pass == 0 && cfg.deterministic_id_) {
  1497 + if (linearization_pass == 0 && cfg.deterministic_id()) {
1427 1498 computeDeterministicIDData();
1428 1499 }
1429 1500 generateID(encryption.get());
... ... @@ -1454,19 +1525,19 @@ impl::Writer::will_filter_stream(QPDFObjectHandle stream, std::string* stream_da
1454 1525 {
1455 1526 const bool is_root_metadata = stream.isRootMetadata();
1456 1527 bool filter = false;
1457   - auto decode_level = cfg.stream_decode_level_;
  1528 + auto decode_level = cfg.stream_decode_level();
1458 1529 int encode_flags = 0;
1459 1530 Dictionary stream_dict = stream.getDict();
1460 1531  
1461 1532 if (stream.getFilterOnWrite()) {
1462   - filter = stream.isDataModified() || cfg.compress_streams_ || decode_level != qpdf_dl_none;
1463   - if (cfg.compress_streams_) {
  1533 + filter = stream.isDataModified() || cfg.compress_streams() || decode_level != qpdf_dl_none;
  1534 + if (cfg.compress_streams()) {
1464 1535 // Don't filter if the stream is already compressed with FlateDecode. This way we don't
1465 1536 // make it worse if the original file used a better Flate algorithm, and we don't spend
1466 1537 // time and CPU cycles uncompressing and recompressing stuff. This can be overridden
1467 1538 // with setRecompressFlate(true).
1468 1539 Name Filter = stream_dict["/Filter"];
1469   - if (Filter && !cfg.recompress_flate_ && !stream.isDataModified() &&
  1540 + if (Filter && !cfg.recompress_flate() && !stream.isDataModified() &&
1470 1541 (Filter == "/FlateDecode" || Filter == "/Fl")) {
1471 1542 filter = false;
1472 1543 }
... ... @@ -1474,10 +1545,10 @@ impl::Writer::will_filter_stream(QPDFObjectHandle stream, std::string* stream_da
1474 1545 if (is_root_metadata && (!encryption || !encryption->getEncryptMetadata())) {
1475 1546 filter = true;
1476 1547 decode_level = qpdf_dl_all;
1477   - } else if (cfg.normalize_content_ && normalized_streams.contains(stream)) {
  1548 + } else if (cfg.normalize_content() && normalized_streams.contains(stream)) {
1478 1549 encode_flags = qpdf_ef_normalize;
1479 1550 filter = true;
1480   - } else if (filter && cfg.compress_streams_) {
  1551 + } else if (filter && cfg.compress_streams()) {
1481 1552 encode_flags = qpdf_ef_compress;
1482 1553 }
1483 1554 }
... ... @@ -1531,11 +1602,11 @@ impl::Writer::unparseObject(
1531 1602 // For non-qdf, "indent" and "indent_large" are a single space between tokens. For qdf, they
1532 1603 // include the preceding newline.
1533 1604 std::string indent_large = " ";
1534   - if (cfg.qdf_mode_) {
  1605 + if (cfg.qdf()) {
1535 1606 indent_large.append(2 * (level + 1), ' ');
1536 1607 indent_large[0] = '\n';
1537 1608 }
1538   - std::string_view indent{indent_large.data(), cfg.qdf_mode_ ? indent_large.size() - 2 : 1};
  1609 + std::string_view indent{indent_large.data(), cfg.qdf() ? indent_large.size() - 2 : 1};
1539 1610  
1540 1611 if (auto const tc = object.getTypeCode(); tc == ::ot_array) {
1541 1612 // Note: PDF spec 1.4 implementation note 121 states that Acrobat requires a space after the
... ... @@ -1591,7 +1662,7 @@ impl::Writer::unparseObject(
1591 1662 if (need_extensions_adbe) {
1592 1663 if (!(have_extensions_other || have_extensions_adbe)) {
1593 1664 // We need Extensions and don't have it. Create it here.
1594   - QTC::TC("qpdf", "QPDFWriter create Extensions", cfg.qdf_mode_ ? 0 : 1);
  1665 + QTC::TC("qpdf", "QPDFWriter create Extensions", cfg.qdf() ? 0 : 1);
1595 1666 extensions = object.replaceKeyAndGetNew(
1596 1667 "/Extensions", QPDFObjectHandle::newDictionary());
1597 1668 }
... ... @@ -1696,7 +1767,7 @@ impl::Writer::unparseObject(
1696 1767 if (flags & f_stream) {
1697 1768 write(indent_large).write("/Length ");
1698 1769  
1699   - if (cfg.direct_stream_lengths_) {
  1770 + if (cfg.direct_stream_lengths()) {
1700 1771 write(stream_length);
1701 1772 } else {
1702 1773 write(cur_stream_length_id).write(" 0 R");
... ... @@ -1709,7 +1780,7 @@ impl::Writer::unparseObject(
1709 1780 write(indent).write(">>");
1710 1781 } else if (tc == ::ot_stream) {
1711 1782 // Write stream data to a buffer.
1712   - if (!cfg.direct_stream_lengths_) {
  1783 + if (!cfg.direct_stream_lengths()) {
1713 1784 cur_stream_length_id = obj[old_og].renumber + 1;
1714 1785 }
1715 1786  
... ... @@ -1730,14 +1801,14 @@ impl::Writer::unparseObject(
1730 1801 unparseObject(stream_dict, 0, flags, cur_stream_length, compress_stream);
1731 1802 char last_char = stream_data.empty() ? '\0' : stream_data.back();
1732 1803 write("\nstream\n").write_encrypted(stream_data);
1733   - added_newline = cfg.newline_before_endstream_ || (cfg.qdf_mode_ && last_char != '\n');
  1804 + added_newline = cfg.newline_before_endstream() || (cfg.qdf() && last_char != '\n');
1734 1805 write(added_newline ? "\nendstream" : "endstream");
1735 1806 } else if (tc == ::ot_string) {
1736 1807 std::string val;
1737 1808 if (encryption && !(flags & f_in_ostream) && !(flags & f_no_encryption) &&
1738 1809 !cur_data_key.empty()) {
1739 1810 val = object.getStringValue();
1740   - if (cfg.encrypt_use_aes_) {
  1811 + if (cfg.encrypt_use_aes()) {
1741 1812 Pl_Buffer bufpl("encrypted string");
1742 1813 Pl_AES_PDF pl("aes encrypt string", &bufpl, true, cur_data_key);
1743 1814 pl.writeString(val);
... ... @@ -1803,7 +1874,7 @@ impl::Writer::writeObjectStream(QPDFObjectHandle object)
1803 1874 std::string stream_buffer_pass1;
1804 1875 std::string stream_buffer_pass2;
1805 1876 int first_obj = -1;
1806   - const bool compressed = cfg.compress_streams_ && !cfg.qdf_mode_;
  1877 + const bool compressed = cfg.compress_streams() && !cfg.qdf();
1807 1878 {
1808 1879 // Pass 1
1809 1880 auto pp_ostream_pass1 = pipeline_stack.activate(stream_buffer_pass1);
... ... @@ -1815,9 +1886,9 @@ impl::Writer::writeObjectStream(QPDFObjectHandle object)
1815 1886 if (first_obj == -1) {
1816 1887 first_obj = new_o;
1817 1888 }
1818   - if (cfg.qdf_mode_) {
  1889 + if (cfg.qdf()) {
1819 1890 write("%% Object stream: object ").write(new_o).write(", index ").write(count);
1820   - if (!cfg.suppress_original_object_ids_) {
  1891 + if (!cfg.suppress_original_object_ids()) {
1821 1892 write("; original object ID: ").write(og.getObj());
1822 1893 // For compatibility, only write the generation if non-zero. While object
1823 1894 // streams only allow objects with generation 0, if we are generating object
... ... @@ -1893,11 +1964,10 @@ impl::Writer::writeObjectStream(QPDFObjectHandle object)
1893 1964 }
1894 1965 }
1895 1966 write_qdf("\n").write_no_qdf(" ").write(">>\nstream\n").write_encrypted(stream_buffer_pass2);
  1967 + write(cfg.newline_before_endstream() ? "\nendstream" : "endstream");
1896 1968 if (encryption) {
1897   - QTC::TC("qpdf", "QPDFWriter encrypt object stream");
  1969 + cur_data_key.clear();
1898 1970 }
1899   - write(cfg.newline_before_endstream_ ? "\nendstream" : "endstream");
1900   - cur_data_key.clear();
1901 1971 closeObject(new_stream_id);
1902 1972 }
1903 1973  
... ... @@ -1914,7 +1984,7 @@ impl::Writer::writeObject(QPDFObjectHandle object, int object_stream_index)
1914 1984  
1915 1985 indicateProgress(false, false);
1916 1986 auto new_id = obj[old_og].renumber;
1917   - if (cfg.qdf_mode_) {
  1987 + if (cfg.qdf()) {
1918 1988 if (page_object_to_seq.contains(old_og)) {
1919 1989 write("%% Page ").write(page_object_to_seq[old_og]).write("\n");
1920 1990 }
... ... @@ -1923,7 +1993,7 @@ impl::Writer::writeObject(QPDFObjectHandle object, int object_stream_index)
1923 1993 }
1924 1994 }
1925 1995 if (object_stream_index == -1) {
1926   - if (cfg.qdf_mode_ && !cfg.suppress_original_object_ids_) {
  1996 + if (cfg.qdf() && !cfg.suppress_original_object_ids()) {
1927 1997 write("%% Original object ID: ").write(object.getObjGen().unparse(' ')).write("\n");
1928 1998 }
1929 1999 openObject(new_id);
... ... @@ -1936,8 +2006,8 @@ impl::Writer::writeObject(QPDFObjectHandle object, int object_stream_index)
1936 2006 write("\n");
1937 2007 }
1938 2008  
1939   - if (!cfg.direct_stream_lengths_ && object.isStream()) {
1940   - if (cfg.qdf_mode_) {
  2009 + if (!cfg.direct_stream_lengths() && object.isStream()) {
  2010 + if (cfg.qdf()) {
1941 2011 if (added_newline) {
1942 2012 write("%QDF: ignore_newline\n");
1943 2013 }
... ... @@ -1973,7 +2043,7 @@ impl::Writer::generateID(bool encrypted)
1973 2043  
1974 2044 std::string result;
1975 2045  
1976   - if (cfg.static_id_) {
  2046 + if (cfg.static_id()) {
1977 2047 // For test suite use only...
1978 2048 static unsigned char tmp[] = {
1979 2049 0x31,
... ... @@ -2005,7 +2075,7 @@ impl::Writer::generateID(bool encrypted)
2005 2075 // that case, would have the same ID regardless of the output file's name.
2006 2076  
2007 2077 std::string seed;
2008   - if (cfg.deterministic_id_) {
  2078 + if (cfg.deterministic_id()) {
2009 2079 if (encrypted) {
2010 2080 throw std::runtime_error(
2011 2081 "QPDFWriter: unable to generated a deterministic ID because the file to be "
... ... @@ -2087,7 +2157,7 @@ impl::Writer::preserveObjectStreams()
2087 2157 // objects from being included.
2088 2158 auto end = xref.cend();
2089 2159 obj.streams_empty = true;
2090   - if (cfg.preserve_unreferenced_objects_) {
  2160 + if (cfg.preserve_unreferenced()) {
2091 2161 for (auto iter = xref.cbegin(); iter != end; ++iter) {
2092 2162 if (iter->second.getType() == 2) {
2093 2163 // Pdf contains object streams.
... ... @@ -2229,63 +2299,61 @@ impl::Writer::doWriteSetup()
2229 2299  
2230 2300 // Do preliminary setup
2231 2301  
2232   - if (cfg.linearized_) {
2233   - cfg.qdf_mode_ = false;
  2302 + if (cfg.linearize()) {
  2303 + cfg.qdf(false);
2234 2304 }
2235 2305  
2236   - if (cfg.pclm_) {
2237   - cfg.stream_decode_level_ = qpdf_dl_none;
2238   - cfg.compress_streams_ = false;
  2306 + if (cfg.pclm()) {
2239 2307 encryption = nullptr;
2240 2308 }
2241 2309  
2242   - if (cfg.qdf_mode_) {
  2310 + if (cfg.qdf()) {
2243 2311 if (!cfg.normalize_content_set_) {
2244   - cfg.normalize_content_ = true;
  2312 + cfg.normalize_content(true);
2245 2313 }
2246 2314 if (!cfg.compress_streams_set_) {
2247   - cfg.compress_streams_ = false;
  2315 + cfg.compress_streams(false);
2248 2316 }
2249 2317 if (!cfg.stream_decode_level_set_) {
2250   - cfg.stream_decode_level_ = qpdf_dl_generalized;
  2318 + cfg.stream_decode_level(qpdf_dl_generalized);
2251 2319 }
2252 2320 }
2253 2321  
2254 2322 if (encryption) {
2255 2323 // Encryption has been explicitly set
2256   - cfg.preserve_encryption_ = false;
2257   - } else if (cfg.normalize_content_ || cfg.pclm_ || cfg.qdf_mode_) {
  2324 + cfg.preserve_encryption(false);
  2325 + } else if (cfg.normalize_content() || cfg.pclm() || cfg.qdf()) {
2258 2326 // Encryption makes looking at contents pretty useless. If the user explicitly encrypted
2259 2327 // though, we still obey that.
2260   - cfg.preserve_encryption_ = false;
  2328 + cfg.preserve_encryption(false);
2261 2329 }
2262 2330  
2263   - if (cfg.preserve_encryption_) {
  2331 + if (cfg.preserve_encryption()) {
2264 2332 copyEncryptionParameters(qpdf);
2265 2333 }
2266 2334  
2267   - if (!cfg.forced_pdf_version_.empty()) {
  2335 + if (!cfg.forced_pdf_version().empty()) {
2268 2336 int major = 0;
2269 2337 int minor = 0;
2270   - parseVersion(cfg.forced_pdf_version_, major, minor);
2271   - disableIncompatibleEncryption(major, minor, cfg.forced_extension_level_);
  2338 + parseVersion(cfg.forced_pdf_version(), major, minor);
  2339 + disableIncompatibleEncryption(major, minor, cfg.forced_extension_level());
2272 2340 if (compareVersions(major, minor, 1, 5) < 0) {
2273   - cfg.object_stream_mode_ = qpdf_o_disable;
  2341 + cfg.object_streams(qpdf_o_disable);
2274 2342 }
2275 2343 }
2276 2344  
2277   - if (cfg.qdf_mode_ || cfg.normalize_content_) {
  2345 + if (cfg.qdf() || cfg.normalize_content()) {
2278 2346 initializeSpecialStreams();
2279 2347 }
2280 2348  
2281   - if (cfg.qdf_mode_) {
  2349 + if (cfg.qdf()) {
2282 2350 // Generate indirect stream lengths for qdf mode since fix-qdf uses them for storing
2283 2351 // recomputed stream length data. Certain streams such as object streams, xref streams, and
2284 2352 // hint streams always get direct stream lengths.
2285 2353 cfg.direct_stream_lengths_ = false;
2286 2354 }
2287 2355  
2288   - switch (cfg.object_stream_mode_) {
  2356 + switch (cfg.object_streams()) {
2289 2357 case qpdf_o_disable:
2290 2358 initializeTables();
2291 2359 obj.streams_empty = true;
... ... @@ -2299,12 +2367,10 @@ impl::Writer::doWriteSetup()
2299 2367 case qpdf_o_generate:
2300 2368 generateObjectStreams();
2301 2369 break;
2302   -
2303   - // no default so gcc will warn for missing case tag
2304 2370 }
2305 2371  
2306 2372 if (!obj.streams_empty) {
2307   - if (cfg.linearized_) {
  2373 + if (cfg.linearize()) {
2308 2374 // Page dictionaries are not allowed to be compressed objects.
2309 2375 for (auto& page: pages) {
2310 2376 if (obj[page].object_stream > 0) {
... ... @@ -2313,7 +2379,7 @@ impl::Writer::doWriteSetup()
2313 2379 }
2314 2380 }
2315 2381  
2316   - if (cfg.linearized_ || encryption) {
  2382 + if (cfg.linearize() || encryption) {
2317 2383 // The document catalog is not allowed to be compressed in cfg.linearized_ files either.
2318 2384 // It also appears that Adobe Reader 8.0.0 has a bug that prevents it from being able to
2319 2385 // handle encrypted files with compressed document catalogs, so we disable them in that
... ... @@ -2345,9 +2411,9 @@ impl::Writer::doWriteSetup()
2345 2411 setMinimumPDFVersion(qpdf.getPDFVersion(), qpdf.getExtensionLevel());
2346 2412 final_pdf_version = min_pdf_version;
2347 2413 final_extension_level = min_extension_level;
2348   - if (!cfg.forced_pdf_version_.empty()) {
2349   - final_pdf_version = cfg.forced_pdf_version_;
2350   - final_extension_level = cfg.forced_extension_level_;
  2414 + if (!cfg.forced_pdf_version().empty()) {
  2415 + final_pdf_version = cfg.forced_pdf_version();
  2416 + final_extension_level = cfg.forced_extension_level();
2351 2417 }
2352 2418 }
2353 2419  
... ... @@ -2364,11 +2430,11 @@ impl::Writer::write()
2364 2430  
2365 2431 // Set up progress reporting. For linearized files, we write two passes. events_expected is an
2366 2432 // approximation, but it's good enough for progress reporting, which is mostly a guess anyway.
2367   - events_expected = QIntC::to_int(qpdf.getObjectCount() * (cfg.linearized_ ? 2 : 1));
  2433 + events_expected = QIntC::to_int(qpdf.getObjectCount() * (cfg.linearize() ? 2 : 1));
2368 2434  
2369 2435 prepareFileForWrite();
2370 2436  
2371   - if (cfg.linearized_) {
  2437 + if (cfg.linearize()) {
2372 2438 writeLinearized();
2373 2439 } else {
2374 2440 writeStandard();
... ... @@ -2430,7 +2496,7 @@ impl::Writer::writeEncryptionDictionary()
2430 2496 write("<<");
2431 2497 if (V >= 4) {
2432 2498 write(" /CF << /StdCF << /AuthEvent /DocOpen /CFM ");
2433   - write(cfg.encrypt_use_aes_ ? (V < 5 ? "/AESV2" : "/AESV3") : "/V2");
  2499 + write(cfg.encrypt_use_aes() ? (V < 5 ? "/AESV2" : "/AESV3") : "/V2");
2434 2500 // The PDF spec says the /Length key is optional, but the PDF previewer on some versions of
2435 2501 // MacOS won't open encrypted files without it.
2436 2502 write(V < 5 ? " /Length 16 >> >>" : " /Length 32 >> >>");
... ... @@ -2471,7 +2537,7 @@ void
2471 2537 impl::Writer::writeHeader()
2472 2538 {
2473 2539 write("%PDF-").write(final_pdf_version);
2474   - if (cfg.pclm_) {
  2540 + if (cfg.pclm()) {
2475 2541 // PCLm version
2476 2542 write("\n%PCLm 1.0\n");
2477 2543 } else {
... ... @@ -2493,7 +2559,7 @@ impl::Writer::writeHintStream(int hint_id)
2493 2559 std::string hint_buffer;
2494 2560 int S = 0;
2495 2561 int O = 0;
2496   - bool compressed = cfg.compress_streams_;
  2562 + bool compressed = cfg.compress_streams();
2497 2563 lin.generateHintStream(new_obj, obj, hint_buffer, S, O, compressed);
2498 2564  
2499 2565 openObject(hint_id);
... ... @@ -2606,7 +2672,7 @@ impl::Writer::writeXRefStream(
2606 2672 new_obj[xref_id].xref = QPDFXRefEntry(pipeline->getCount());
2607 2673  
2608 2674 std::string xref_data;
2609   - const bool compressed = cfg.compress_streams_ && !cfg.qdf_mode_;
  2675 + const bool compressed = cfg.compress_streams() && !cfg.qdf();
2610 2676 {
2611 2677 auto pp_xref = pipeline_stack.activate(xref_data);
2612 2678  
... ... @@ -2809,15 +2875,15 @@ impl::Writer::writeLinearized()
2809 2875 auto pp_md5 = pipeline_stack.popper();
2810 2876 for (int pass: {1, 2}) {
2811 2877 if (pass == 1) {
2812   - if (!cfg.lin_pass1_filename_.empty()) {
2813   - lin_pass1_file = QUtil::safe_fopen(cfg.lin_pass1_filename_.data(), "wb");
  2878 + if (!cfg.lin_pass1_filename().empty()) {
  2879 + lin_pass1_file = QUtil::safe_fopen(cfg.lin_pass1_filename().data(), "wb");
2814 2880 pipeline_stack.activate(
2815 2881 pp_pass1,
2816 2882 std::make_unique<Pl_StdioFile>("linearization pass1", lin_pass1_file));
2817 2883 } else {
2818 2884 pipeline_stack.activate(pp_pass1, true);
2819 2885 }
2820   - if (cfg.deterministic_id_) {
  2886 + if (cfg.deterministic_id()) {
2821 2887 pipeline_stack.activate_md5(pp_md5);
2822 2888 }
2823 2889 }
... ... @@ -2852,7 +2918,7 @@ impl::Writer::writeLinearized()
2852 2918  
2853 2919 // If the user supplied any additional header text, write it here after the linearization
2854 2920 // parameter dictionary.
2855   - write(cfg.extra_header_text_);
  2921 + write(cfg.extra_header_text());
2856 2922  
2857 2923 // Part 3: first page cross reference table and trailer.
2858 2924  
... ... @@ -2987,7 +3053,7 @@ impl::Writer::writeLinearized()
2987 3053 write("startxref\n").write(first_xref_offset).write("\n%%EOF\n");
2988 3054  
2989 3055 if (pass == 1) {
2990   - if (cfg.deterministic_id_) {
  3056 + if (cfg.deterministic_id()) {
2991 3057 QTC::TC("qpdf", "QPDFWriter linearized deterministic ID", need_xref_stream ? 0 : 1);
2992 3058 computeDeterministicIDData();
2993 3059 pp_md5.pop();
... ... @@ -3032,7 +3098,7 @@ impl::Writer::writeLinearized()
3032 3098 void
3033 3099 impl::Writer::enqueueObjectsStandard()
3034 3100 {
3035   - if (cfg.preserve_unreferenced_objects_) {
  3101 + if (cfg.preserve_unreferenced()) {
3036 3102 for (auto const& oh: qpdf.getAllObjects()) {
3037 3103 enqueue(oh);
3038 3104 }
... ... @@ -3113,16 +3179,16 @@ void
3113 3179 impl::Writer::writeStandard()
3114 3180 {
3115 3181 auto pp_md5 = pipeline_stack.popper();
3116   - if (cfg.deterministic_id_) {
  3182 + if (cfg.deterministic_id()) {
3117 3183 pipeline_stack.activate_md5(pp_md5);
3118 3184 }
3119 3185  
3120 3186 // Start writing
3121 3187  
3122 3188 writeHeader();
3123   - write(cfg.extra_header_text_);
  3189 + write(cfg.extra_header_text());
3124 3190  
3125   - if (cfg.pclm_) {
  3191 + if (cfg.pclm()) {
3126 3192 enqueueObjectsPCLm();
3127 3193 } else {
3128 3194 enqueueObjectsStandard();
... ... @@ -3152,7 +3218,7 @@ impl::Writer::writeStandard()
3152 3218 }
3153 3219 write("startxref\n").write(xref_offset).write("\n%%EOF\n");
3154 3220  
3155   - if (cfg.deterministic_id_) {
  3221 + if (cfg.deterministic_id()) {
3156 3222 QTC::TC(
3157 3223 "qpdf",
3158 3224 "QPDFWriter standard deterministic ID",
... ...
libqpdf/qpdf/QPDFWriter_private.hh
... ... @@ -23,14 +23,252 @@ namespace qpdf
23 23 class Config
24 24 {
25 25 friend class impl::Writer;
26   - friend class ::QPDFWriter;
  26 +
  27 + public:
  28 + bool
  29 + linearize() const
  30 + {
  31 + return linearize_;
  32 + }
  33 +
  34 + Config& linearize(bool val);
  35 +
  36 + std::string const&
  37 + lin_pass1_filename() const
  38 + {
  39 + return lin_pass1_filename_;
  40 + }
  41 +
  42 + Config&
  43 + lin_pass1_filename(std::string const& val)
  44 + {
  45 + lin_pass1_filename_ = val;
  46 + return *this;
  47 + }
  48 +
  49 + bool
  50 + preserve_encryption() const
  51 + {
  52 + return preserve_encryption_;
  53 + }
  54 +
  55 + Config&
  56 + preserve_encryption(bool val)
  57 + {
  58 + preserve_encryption_ = val;
  59 + return *this;
  60 + }
  61 +
  62 + bool
  63 + encrypt_use_aes() const
  64 + {
  65 + return encrypt_use_aes_;
  66 + }
  67 +
  68 + Config&
  69 + encrypt_use_aes(bool val)
  70 + {
  71 + encrypt_use_aes_ = val;
  72 + return *this;
  73 + }
  74 +
  75 + qpdf_stream_decode_level_e
  76 + stream_decode_level() const
  77 + {
  78 + return stream_decode_level_;
  79 + }
  80 +
  81 + Config& stream_decode_level(qpdf_stream_decode_level_e val);
  82 +
  83 + qpdf_object_stream_e
  84 + object_streams() const
  85 + {
  86 + return object_streams_;
  87 + }
  88 +
  89 + Config&
  90 + object_streams(qpdf_object_stream_e val)
  91 + {
  92 + object_streams_ = val;
  93 + return *this;
  94 + }
  95 +
  96 + bool
  97 + compress_streams() const
  98 + {
  99 + return compress_streams_;
  100 + }
  101 +
  102 + Config& compress_streams(bool val);
  103 +
  104 + bool
  105 + direct_stream_lengths() const
  106 + {
  107 + return direct_stream_lengths_;
  108 + }
  109 +
  110 + bool
  111 + newline_before_endstream() const
  112 + {
  113 + return newline_before_endstream_;
  114 + }
  115 +
  116 + Config&
  117 + newline_before_endstream(bool val)
  118 + {
  119 + newline_before_endstream_ = val;
  120 + return *this;
  121 + }
  122 +
  123 + bool
  124 + recompress_flate() const
  125 + {
  126 + return recompress_flate_;
  127 + }
  128 +
  129 + Config&
  130 + recompress_flate(bool val)
  131 + {
  132 + recompress_flate_ = val;
  133 + return *this;
  134 + }
  135 +
  136 + Config& stream_data(qpdf_stream_data_e val);
  137 +
  138 + std::string const&
  139 + forced_pdf_version() const
  140 + {
  141 + return forced_pdf_version_;
  142 + }
  143 +
  144 + Config&
  145 + forced_pdf_version(std::string const& val)
  146 + {
  147 + forced_pdf_version_ = val;
  148 + return *this;
  149 + }
  150 +
  151 + Config&
  152 + forced_pdf_version(std::string const& val, int ext)
  153 + {
  154 + forced_pdf_version_ = val;
  155 + forced_extension_level_ = ext;
  156 + return *this;
  157 + }
  158 +
  159 + int
  160 + forced_extension_level() const
  161 + {
  162 + return forced_extension_level_;
  163 + }
  164 +
  165 + Config&
  166 + forced_extension_level(int val)
  167 + {
  168 + forced_extension_level_ = val;
  169 + return *this;
  170 + }
  171 +
  172 + std::string const&
  173 + extra_header_text()
  174 + {
  175 + return extra_header_text_;
  176 + }
  177 +
  178 + Config& extra_header_text(std::string const& val);
  179 +
  180 + bool
  181 + preserve_unreferenced() const
  182 + {
  183 + return preserve_unreferenced_;
  184 + }
  185 +
  186 + Config&
  187 + preserve_unreferenced(bool val)
  188 + {
  189 + preserve_unreferenced_ = val;
  190 + return *this;
  191 + }
  192 +
  193 + bool
  194 + suppress_original_object_ids() const
  195 + {
  196 + return suppress_original_object_ids_;
  197 + }
  198 +
  199 + Config&
  200 + suppress_original_object_ids(bool val)
  201 + {
  202 + suppress_original_object_ids_ = val;
  203 + return *this;
  204 + }
  205 +
  206 + bool
  207 + qdf() const
  208 + {
  209 + return qdf_;
  210 + }
  211 +
  212 + Config& qdf(bool val);
  213 +
  214 + bool
  215 + normalize_content() const
  216 + {
  217 + return normalize_content_;
  218 + }
  219 +
  220 + Config&
  221 + normalize_content(bool val)
  222 + {
  223 + normalize_content_ = val;
  224 + normalize_content_set_ = true;
  225 + return *this;
  226 + }
  227 +
  228 + bool
  229 + deterministic_id() const
  230 + {
  231 + return deterministic_id_;
  232 + }
  233 +
  234 + Config&
  235 + deterministic_id(bool val)
  236 + {
  237 + deterministic_id_ = val;
  238 + return *this;
  239 + }
  240 +
  241 + bool
  242 + static_id() const
  243 + {
  244 + return static_id_;
  245 + }
  246 +
  247 + Config&
  248 + static_id(bool val)
  249 + {
  250 + static_id_ = val;
  251 + return *this;
  252 + }
  253 +
  254 + bool
  255 + pclm() const
  256 + {
  257 + return pclm_;
  258 + }
  259 +
  260 + Config& pclm(bool val);
  261 +
  262 + private:
  263 + void usage(std::string_view msg) const {};
27 264  
28 265 std::string forced_pdf_version_;
29 266 std::string extra_header_text_;
30 267 // For linearization only
31 268 std::string lin_pass1_filename_;
32 269  
33   - qpdf_object_stream_e object_stream_mode_{qpdf_o_preserve};
  270 + qpdf_object_stream_e object_streams_{qpdf_o_preserve};
  271 + qpdf_stream_decode_level_e stream_decode_level_{qpdf_dl_generalized};
34 272  
35 273 int forced_extension_level_{0};
36 274  
... ... @@ -38,18 +276,17 @@ namespace qpdf
38 276 bool normalize_content_{false};
39 277 bool compress_streams_{true};
40 278 bool compress_streams_set_{false};
41   - qpdf_stream_decode_level_e stream_decode_level_{qpdf_dl_generalized};
42 279 bool stream_decode_level_set_{false};
43 280 bool recompress_flate_{false};
44   - bool qdf_mode_{false};
45   - bool preserve_unreferenced_objects_{false};
  281 + bool qdf_{false};
  282 + bool preserve_unreferenced_{false};
46 283 bool newline_before_endstream_{false};
47 284 bool deterministic_id_{false};
48 285 bool static_id_{false};
49 286 bool suppress_original_object_ids_{false};
50 287 bool direct_stream_lengths_{true};
51 288 bool preserve_encryption_{true};
52   - bool linearized_{false};
  289 + bool linearize_{false};
53 290 bool pclm_{false};
54 291 bool encrypt_use_aes_{false};
55 292 }; // class Writer::Config
... ...
qpdf/qpdf.testcov
... ... @@ -46,7 +46,6 @@ QPDFObjectHandle copy stream 1
46 46 QPDF ignoring XRefStm in trailer 0
47 47 SF_FlateLzwDecode PNG filter 0
48 48 QPDF xref /Index is array 1
49   -QPDFWriter encrypt object stream 0
50 49 QPDF exclude indirect length 0
51 50 QPDF exclude encryption dictionary 0
52 51 QPDF_Stream pipeStreamData with null pipeline 0
... ...