Commit dd3de38974328a9345e1e3b6baab5fd123d2bd54

Authored by m-holger
1 parent 256f0633

Refactor `Lin` linearization hints: rename and encapsulate data structures.

include/qpdf/QPDF.hh
... ... @@ -787,16 +787,6 @@ class QPDF
787 787 bool is_root_metadata,
788 788 std::unique_ptr<Pipeline>& heap);
789 789  
790   - struct HPageOffsetEntry;
791   - struct HPageOffset;
792   - struct HSharedObjectEntry;
793   - struct HSharedObject;
794   - struct HGeneric;
795   - struct LinParameters;
796   - struct CHPageOffsetEntry;
797   - struct CHPageOffset;
798   - struct CHSharedObjectEntry;
799   - struct CHSharedObject;
800 790 class PatternFinder;
801 791  
802 792 // Methods to support pattern finding
... ...
libqpdf/QPDF_linearization.cc
... ... @@ -186,7 +186,7 @@ Lin::optimize_internal(
186 186 }
187 187  
188 188 ObjUser root_ou = ObjUser(ObjUser::ou_root);
189   - auto root_og =root.id_gen();
  189 + auto root_og = root.id_gen();
190 190 obj_user_to_objects_[root_ou].insert(root_og);
191 191 object_to_obj_users_[root_og].insert(root_ou);
192 192  
... ... @@ -427,8 +427,8 @@ Lin::linearized()
427 427 if (L != m->file->tell()) {
428 428 return false;
429 429 }
430   - m->linp.file_size = L;
431   - m->lindict = candidate;
  430 + linp_.file_size = L;
  431 + lindict_ = candidate;
432 432 return true;
433 433 }
434 434 }
... ... @@ -444,17 +444,17 @@ Lin::readLinearizationData()
444 444 // that prevent loading.
445 445  
446 446 // /L is read and stored in linp by isLinearized()
447   - Array H = m->lindict["/H"]; // hint table offset/length for primary and overflow hint tables
  447 + Array H = lindict_["/H"]; // hint table offset/length for primary and overflow hint tables
448 448 auto H_size = H.size();
449 449 Integer H_0 = H[0]; // hint table offset
450 450 Integer H_1 = H[1]; // hint table length
451 451 Integer H_2 = H[2]; // hint table offset for overflow hint table
452 452 Integer H_3 = H[3]; // hint table length for overflow hint table
453   - Integer O = m->lindict["/O"];
454   - Integer E = m->lindict["/E"];
455   - Integer N = m->lindict["/N"];
456   - Integer T = m->lindict["/T"];
457   - auto P_oh = m->lindict["/P"];
  453 + Integer O = lindict_["/O"];
  454 + Integer E = lindict_["/E"];
  455 + Integer N = lindict_["/N"];
  456 + Integer T = lindict_["/T"];
  457 + auto P_oh = lindict_["/P"];
458 458 Integer P = P_oh; // first page number
459 459 QTC::TC("qpdf", "QPDF P absent in lindict", P ? 0 : 1);
460 460  
... ... @@ -487,13 +487,13 @@ Lin::readLinearizationData()
487 487 );
488 488  
489 489 // file_size initialized by isLinearized()
490   - m->linp.first_page_object = O;
491   - m->linp.first_page_end = E;
492   - m->linp.npages = N;
493   - m->linp.xref_zero_offset = T;
494   - m->linp.first_page = P ? P : 0;
495   - m->linp.H_offset = H_0;
496   - m->linp.H_length = H_1;
  490 + linp_.first_page_object = O;
  491 + linp_.first_page_end = E;
  492 + linp_.npages = N;
  493 + linp_.xref_zero_offset = T;
  494 + linp_.first_page = P ? P : 0;
  495 + linp_.H_offset = H_0;
  496 + linp_.H_length = H_1;
497 497  
498 498 // Read hint streams
499 499  
... ... @@ -537,7 +537,7 @@ Lin::readLinearizationData()
537 537 "linearization dictionary" //
538 538 );
539 539 size_t HOi = HO;
540   - readHGeneric(BitStream(h_buf + HO, h_size - HOi), m->outline_hints);
  540 + readHGeneric(BitStream(h_buf + HO, h_size - HOi), outline_hints_);
541 541 }
542 542 }
543 543  
... ... @@ -581,7 +581,7 @@ Lin::readHPageOffset(BitStream h)
581 581 {
582 582 // All comments referring to the PDF spec refer to the spec for version 1.4.
583 583  
584   - HPageOffset& t = m->page_offset_hints;
  584 + HPageOffset& t = page_offset_hints_;
585 585  
586 586 t.min_nobjects = h.getBitsInt(32); // 1
587 587 t.first_page_offset = h.getBitsInt(32); // 2
... ... @@ -599,7 +599,7 @@ Lin::readHPageOffset(BitStream h)
599 599  
600 600 std::vector<HPageOffsetEntry>& entries = t.entries;
601 601 entries.clear();
602   - int nitems = toI(m->linp.npages);
  602 + int nitems = toI(linp_.npages);
603 603 load_vector_int(h, nitems, entries, t.nbits_delta_nobjects, &HPageOffsetEntry::delta_nobjects);
604 604 load_vector_int(
605 605 h, nitems, entries, t.nbits_delta_page_length, &HPageOffsetEntry::delta_page_length);
... ... @@ -628,7 +628,7 @@ Lin::readHPageOffset(BitStream h)
628 628 void
629 629 Lin::readHSharedObject(BitStream h)
630 630 {
631   - HSharedObject& t = m->shared_object_hints;
  631 + HSharedObject& t = shared_object_hints_;
632 632  
633 633 t.first_shared_obj = h.getBitsInt(32); // 1
634 634 t.first_shared_offset = h.getBitsInt(32); // 2
... ... @@ -677,7 +677,7 @@ Lin::checkLinearizationInternal()
677 677  
678 678 // Check all values in linearization parameter dictionary
679 679  
680   - LinParameters& p = m->linp;
  680 + LinParameters& p = linp_;
681 681  
682 682 // L: file size in bytes -- checked by isLinearized
683 683  
... ... @@ -873,7 +873,7 @@ Lin::checkHPageOffset(
873 873 // dictionary in with shared objects even when they are private.
874 874  
875 875 size_t npages = pages.size();
876   - qpdf_offset_t table_offset = adjusted_offset(m->page_offset_hints.first_page_offset);
  876 + qpdf_offset_t table_offset = adjusted_offset(page_offset_hints_.first_page_offset);
877 877 QPDFObjGen first_page_og(pages.at(0).getObjGen());
878 878 if (!m->xref_table.contains(first_page_og)) {
879 879 stopOnError("supposed first page object is not known");
... ... @@ -891,9 +891,9 @@ Lin::checkHPageOffset(
891 891 }
892 892 offset = getLinearizationOffset(page_og);
893 893  
894   - HPageOffsetEntry& he = m->page_offset_hints.entries.at(toS(pageno));
895   - CHPageOffsetEntry& ce = m->c_page_offset_data.entries.at(toS(pageno));
896   - int h_nobjects = he.delta_nobjects + m->page_offset_hints.min_nobjects;
  894 + HPageOffsetEntry& he = page_offset_hints_.entries.at(pageno);
  895 + CHPageOffsetEntry& ce = c_page_offset_data_.entries.at(pageno);
  896 + int h_nobjects = he.delta_nobjects + page_offset_hints_.min_nobjects;
897 897 if (h_nobjects != ce.nobjects) {
898 898 // This happens with pdlin when there are thumbnails.
899 899 linearizationWarning(
... ... @@ -904,7 +904,7 @@ Lin::checkHPageOffset(
904 904 // Use value for number of objects in hint table rather than computed value if there is a
905 905 // discrepancy.
906 906 int length = lengthNextN(first_object, h_nobjects);
907   - int h_length = toI(he.delta_page_length + m->page_offset_hints.min_page_length);
  907 + int h_length = toI(he.delta_page_length + page_offset_hints_.min_page_length);
908 908 if (length != h_length) {
909 909 // This condition almost certainly indicates a bad hint table or a bug in this code.
910 910 linearizationWarning(
... ... @@ -937,11 +937,11 @@ Lin::checkHPageOffset(
937 937 for (size_t i = 0; i < toS(ce.nshared_objects); ++i) {
938 938 int idx = ce.shared_identifiers.at(i);
939 939 no_ci_stop_if(
940   - idx >= m->c_shared_object_data.nshared_total,
  940 + idx >= c_shared_object_data_.nshared_total,
941 941 "index out of bounds for shared object hint table" //
942 942 );
943 943  
944   - int obj = m->c_shared_object_data.entries.at(toS(idx)).object;
  944 + int obj = c_shared_object_data_.entries.at(toS(idx)).object;
945 945 computed_shared.insert(obj);
946 946 }
947 947  
... ... @@ -983,7 +983,7 @@ Lin::checkHSharedObject(std::vector&lt;QPDFObjectHandle&gt; const&amp; pages, std::map&lt;int
983 983 // Empirically, Acrobat and pdlin generate incorrect values for these whenever there are no
984 984 // shared objects not referenced by the first page (i.e., nshared_total == nshared_first_page).
985 985  
986   - HSharedObject& so = m->shared_object_hints;
  986 + HSharedObject& so = shared_object_hints_;
987 987 if (so.nshared_total < so.nshared_first_page) {
988 988 linearizationWarning("shared object hint table: ntotal < nfirst_page");
989 989 } else {
... ... @@ -1044,12 +1044,12 @@ Lin::checkHOutlines()
1044 1044 // correct number of objects from the wrong starting place). pdlin appears to generate correct
1045 1045 // values in those cases.
1046 1046  
1047   - if (m->c_outline_data.nobjects == m->outline_hints.nobjects) {
1048   - if (m->c_outline_data.nobjects == 0) {
  1047 + if (c_outline_data_.nobjects == outline_hints_.nobjects) {
  1048 + if (c_outline_data_.nobjects == 0) {
1049 1049 return;
1050 1050 }
1051 1051  
1052   - if (m->c_outline_data.first_object == m->outline_hints.first_object) {
  1052 + if (c_outline_data_.first_object == outline_hints_.first_object) {
1053 1053 // Check length and offset. Acrobat gets these wrong.
1054 1054 QPDFObjectHandle outlines = qpdf.getRoot().getKey("/Outlines");
1055 1055 if (!outlines.isIndirect()) {
... ... @@ -1065,13 +1065,13 @@ Lin::checkHOutlines()
1065 1065 qpdf_offset_t offset = getLinearizationOffset(og);
1066 1066 ObjUser ou(ObjUser::ou_root_key, "/Outlines");
1067 1067 int length = toI(maxEnd(ou) - offset);
1068   - qpdf_offset_t table_offset = adjusted_offset(m->outline_hints.first_object_offset);
  1068 + qpdf_offset_t table_offset = adjusted_offset(outline_hints_.first_object_offset);
1069 1069 if (offset != table_offset) {
1070 1070 linearizationWarning(
1071 1071 "incorrect offset in outlines table: hint table = " +
1072 1072 std::to_string(table_offset) + "; computed = " + std::to_string(offset));
1073 1073 }
1074   - int table_length = m->outline_hints.group_length;
  1074 + int table_length = outline_hints_.group_length;
1075 1075 if (length != table_length) {
1076 1076 linearizationWarning(
1077 1077 "incorrect length in outlines table: hint table = " +
... ... @@ -1110,14 +1110,14 @@ Lin::dumpLinearizationDataInternal()
1110 1110  
1111 1111 info << m->file->getName() << ": linearization data:\n\n";
1112 1112  
1113   - info << "file_size: " << m->linp.file_size << "\n"
1114   - << "first_page_object: " << m->linp.first_page_object << "\n"
1115   - << "first_page_end: " << m->linp.first_page_end << "\n"
1116   - << "npages: " << m->linp.npages << "\n"
1117   - << "xref_zero_offset: " << m->linp.xref_zero_offset << "\n"
1118   - << "first_page: " << m->linp.first_page << "\n"
1119   - << "H_offset: " << m->linp.H_offset << "\n"
1120   - << "H_length: " << m->linp.H_length << "\n"
  1113 + info << "file_size: " << linp_.file_size << "\n"
  1114 + << "first_page_object: " << linp_.first_page_object << "\n"
  1115 + << "first_page_end: " << linp_.first_page_end << "\n"
  1116 + << "npages: " << linp_.npages << "\n"
  1117 + << "xref_zero_offset: " << linp_.xref_zero_offset << "\n"
  1118 + << "first_page: " << linp_.first_page << "\n"
  1119 + << "H_offset: " << linp_.H_offset << "\n"
  1120 + << "H_length: " << linp_.H_length << "\n"
1121 1121 << "\n";
1122 1122  
1123 1123 info << "Page Offsets Hint Table\n\n";
... ... @@ -1125,9 +1125,9 @@ Lin::dumpLinearizationDataInternal()
1125 1125 info << "\nShared Objects Hint Table\n\n";
1126 1126 dumpHSharedObject();
1127 1127  
1128   - if (m->outline_hints.nobjects > 0) {
  1128 + if (outline_hints_.nobjects > 0) {
1129 1129 info << "\nOutlines Hint Table\n\n";
1130   - dumpHGeneric(m->outline_hints);
  1130 + dumpHGeneric(outline_hints_);
1131 1131 }
1132 1132 }
1133 1133  
... ... @@ -1136,8 +1136,8 @@ Lin::adjusted_offset(qpdf_offset_t offset)
1136 1136 {
1137 1137 // All offsets >= H_offset have to be increased by H_length since all hint table location values
1138 1138 // disregard the hint table itself.
1139   - if (offset >= m->linp.H_offset) {
1140   - return offset + m->linp.H_length;
  1139 + if (offset >= linp_.H_offset) {
  1140 + return offset + linp_.H_length;
1141 1141 }
1142 1142 return offset;
1143 1143 }
... ... @@ -1146,7 +1146,7 @@ void
1146 1146 Lin::dumpHPageOffset()
1147 1147 {
1148 1148 auto& info = *cf.log()->getInfo();
1149   - HPageOffset& t = m->page_offset_hints;
  1149 + HPageOffset& t = page_offset_hints_;
1150 1150 info << "min_nobjects: " << t.min_nobjects << "\n"
1151 1151 << "first_page_offset: " << adjusted_offset(t.first_page_offset) << "\n"
1152 1152 << "nbits_delta_nobjects: " << t.nbits_delta_nobjects << "\n"
... ... @@ -1161,7 +1161,7 @@ Lin::dumpHPageOffset()
1161 1161 << "nbits_shared_numerator: " << t.nbits_shared_numerator << "\n"
1162 1162 << "shared_denominator: " << t.shared_denominator << "\n";
1163 1163  
1164   - for (size_t i1 = 0; i1 < m->linp.npages; ++i1) {
  1164 + for (size_t i1 = 0; i1 < linp_.npages; ++i1) {
1165 1165 HPageOffsetEntry& pe = t.entries.at(i1);
1166 1166 info << "Page " << i1 << ":\n"
1167 1167 << " nobjects: " << pe.delta_nobjects + t.min_nobjects << "\n"
... ... @@ -1182,7 +1182,7 @@ void
1182 1182 Lin::dumpHSharedObject()
1183 1183 {
1184 1184 auto& info = *cf.log()->getInfo();
1185   - HSharedObject& t = m->shared_object_hints;
  1185 + HSharedObject& t = shared_object_hints_;
1186 1186 info << "first_shared_obj: " << t.first_shared_obj << "\n"
1187 1187 << "first_shared_offset: " << adjusted_offset(t.first_shared_offset) << "\n"
1188 1188 << "nshared_first_page: " << t.nshared_first_page << "\n"
... ... @@ -1280,10 +1280,10 @@ Lin::calculateLinearizationData(T const&amp; object_stream_data)
1280 1280 m->part7.clear();
1281 1281 m->part8.clear();
1282 1282 m->part9.clear();
1283   - m->c_linp = LinParameters();
1284   - m->c_page_offset_data = CHPageOffset();
1285   - m->c_shared_object_data = CHSharedObject();
1286   - m->c_outline_data = HGeneric();
  1283 + c_linp_ = LinParameters();
  1284 + c_page_offset_data_ = CHPageOffset();
  1285 + c_shared_object_data_ = CHSharedObject();
  1286 + c_outline_data_ = HGeneric();
1287 1287  
1288 1288 QPDFObjectHandle root = qpdf.getRoot();
1289 1289 bool outlines_in_first_page = false;
... ... @@ -1417,8 +1417,8 @@ Lin::calculateLinearizationData(T const&amp; object_stream_data)
1417 1417  
1418 1418 // npages is the size of the existing pages vector, which has been created by traversing the
1419 1419 // pages tree, and as such is a reasonable size.
1420   - m->c_linp.npages = npages;
1421   - m->c_page_offset_data.entries = std::vector<CHPageOffsetEntry>(npages);
  1420 + c_linp_.npages = npages;
  1421 + c_page_offset_data_.entries = std::vector<CHPageOffsetEntry>(npages);
1422 1422  
1423 1423 // Part 4: open document objects. We don't care about the order.
1424 1424  
... ... @@ -1443,7 +1443,7 @@ Lin::calculateLinearizationData(T const&amp; object_stream_data)
1443 1443 no_ci_stop_if(
1444 1444 !lc_first_page_private.erase(first_page_og), "unable to linearize first page" //
1445 1445 );
1446   - m->c_linp.first_page_object = uc_pages.at(0).getObjectID();
  1446 + c_linp_.first_page_object = uc_pages.at(0).getObjectID();
1447 1447 m->part6.emplace_back(uc_pages.at(0));
1448 1448  
1449 1449 // The PDF spec "recommends" an order for the rest of the objects, but we are going to disregard
... ... @@ -1467,7 +1467,7 @@ Lin::calculateLinearizationData(T const&amp; object_stream_data)
1467 1467 // nshared_objects should be zero for the first page. pdlin does not appear to obey this, but
1468 1468 // it fills in garbage values for all the shared object identifiers on the first page.
1469 1469  
1470   - m->c_page_offset_data.entries.at(0).nobjects = toI(m->part6.size());
  1470 + c_page_offset_data_.entries.at(0).nobjects = toI(m->part6.size());
1471 1471  
1472 1472 // Part 7: other pages' private objects
1473 1473  
... ... @@ -1486,7 +1486,7 @@ Lin::calculateLinearizationData(T const&amp; object_stream_data)
1486 1486 // Place all non-shared objects referenced by this page, updating the page object count for
1487 1487 // the hint table.
1488 1488  
1489   - m->c_page_offset_data.entries.at(i).nobjects = 1;
  1489 + c_page_offset_data_.entries.at(i).nobjects = 1;
1490 1490  
1491 1491 ObjUser ou(ObjUser::ou_page, i);
1492 1492 no_ci_stop_if(
... ... @@ -1497,7 +1497,7 @@ Lin::calculateLinearizationData(T const&amp; object_stream_data)
1497 1497 for (auto const& og: obj_user_to_objects_[ou]) {
1498 1498 if (lc_other_page_private.erase(og)) {
1499 1499 m->part7.emplace_back(qpdf.getObject(og));
1500   - ++m->c_page_offset_data.entries.at(i).nobjects;
  1500 + ++c_page_offset_data_.entries.at(i).nobjects;
1501 1501 }
1502 1502 }
1503 1503 }
... ... @@ -1599,11 +1599,11 @@ Lin::calculateLinearizationData(T const&amp; object_stream_data)
1599 1599 // only without regards to generation.
1600 1600 std::map<int, int> obj_to_index;
1601 1601  
1602   - m->c_shared_object_data.nshared_first_page = toI(m->part6.size());
1603   - m->c_shared_object_data.nshared_total =
1604   - m->c_shared_object_data.nshared_first_page + toI(m->part8.size());
  1602 + c_shared_object_data_.nshared_first_page = toI(m->part6.size());
  1603 + c_shared_object_data_.nshared_total =
  1604 + c_shared_object_data_.nshared_first_page + toI(m->part8.size());
1605 1605  
1606   - std::vector<CHSharedObjectEntry>& shared = m->c_shared_object_data.entries;
  1606 + std::vector<CHSharedObjectEntry>& shared = c_shared_object_data_.entries;
1607 1607 for (auto& oh: m->part6) {
1608 1608 int obj = oh.getObjectID();
1609 1609 obj_to_index[obj] = toI(shared.size());
... ... @@ -1611,7 +1611,7 @@ Lin::calculateLinearizationData(T const&amp; object_stream_data)
1611 1611 }
1612 1612 QTC::TC("qpdf", "QPDF lin part 8 empty", m->part8.empty() ? 1 : 0);
1613 1613 if (!m->part8.empty()) {
1614   - m->c_shared_object_data.first_shared_obj = m->part8.at(0).getObjectID();
  1614 + c_shared_object_data_.first_shared_obj = m->part8.at(0).getObjectID();
1615 1615 for (auto& oh: m->part8) {
1616 1616 int obj = oh.getObjectID();
1617 1617 obj_to_index[obj] = toI(shared.size());
... ... @@ -1620,14 +1620,14 @@ Lin::calculateLinearizationData(T const&amp; object_stream_data)
1620 1620 }
1621 1621 no_ci_stop_if(
1622 1622 std::cmp_not_equal(
1623   - m->c_shared_object_data.nshared_total, m->c_shared_object_data.entries.size()),
  1623 + c_shared_object_data_.nshared_total, c_shared_object_data_.entries.size()),
1624 1624 "shared object hint table has wrong number of entries" //
1625 1625 );
1626 1626  
1627 1627 // Now compute the list of shared objects for each page after the first page.
1628 1628  
1629 1629 for (size_t i = 1; i < npages; ++i) {
1630   - CHPageOffsetEntry& pe = m->c_page_offset_data.entries.at(i);
  1630 + CHPageOffsetEntry& pe = c_page_offset_data_.entries.at(i);
1631 1631 ObjUser ou(ObjUser::ou_page, i);
1632 1632 no_ci_stop_if(
1633 1633 !obj_user_to_objects_.contains(ou),
... ... @@ -1668,15 +1668,15 @@ Lin::pushOutlinesToPart(
1668 1668 // Make sure outlines is in lc_outlines in case the file is damaged. in which case it may be
1669 1669 // included in an earlier part.
1670 1670 part.emplace_back(outlines);
1671   - m->c_outline_data.first_object = outlines_og.getObj();
1672   - m->c_outline_data.nobjects = 1;
  1671 + c_outline_data_.first_object = outlines_og.getObj();
  1672 + c_outline_data_.nobjects = 1;
1673 1673 }
1674 1674 for (auto const& og: lc_outlines) {
1675   - if (!m->c_outline_data.first_object) {
1676   - m->c_outline_data.first_object = og.getObj();
  1675 + if (!c_outline_data_.first_object) {
  1676 + c_outline_data_.first_object = og.getObj();
1677 1677 }
1678 1678 part.emplace_back(qpdf.getObject(og));
1679   - ++m->c_outline_data.nobjects;
  1679 + ++c_outline_data_.nobjects;
1680 1680 }
1681 1681 }
1682 1682  
... ... @@ -1734,7 +1734,7 @@ Lin::calculateHPageOffset(QPDFWriter::NewObjTable const&amp; new_obj, QPDFWriter::Ob
1734 1734  
1735 1735 auto const& all_pages = pages.all();
1736 1736 size_t npages = all_pages.size();
1737   - CHPageOffset& cph = m->c_page_offset_data;
  1737 + CHPageOffset& cph = c_page_offset_data_;
1738 1738 std::vector<CHPageOffsetEntry>& cphe = cph.entries;
1739 1739  
1740 1740 // Calculate minimum and maximum values for number of objects per page and page length.
... ... @@ -1745,7 +1745,7 @@ Lin::calculateHPageOffset(QPDFWriter::NewObjTable const&amp; new_obj, QPDFWriter::Ob
1745 1745 int max_length = 0;
1746 1746 int max_shared = 0;
1747 1747  
1748   - HPageOffset& ph = m->page_offset_hints;
  1748 + HPageOffset& ph = page_offset_hints_;
1749 1749 std::vector<HPageOffsetEntry>& phe = ph.entries;
1750 1750 // npages is the size of the existing pages array.
1751 1751 phe = std::vector<HPageOffsetEntry>(npages);
... ... @@ -1780,7 +1780,7 @@ Lin::calculateHPageOffset(QPDFWriter::NewObjTable const&amp; new_obj, QPDFWriter::Ob
1780 1780 ph.min_page_length = min_length;
1781 1781 ph.nbits_delta_page_length = nbits(max_length - min_length);
1782 1782 ph.nbits_nshared_objects = nbits(max_shared);
1783   - ph.nbits_shared_identifier = nbits(m->c_shared_object_data.nshared_total);
  1783 + ph.nbits_shared_identifier = nbits(c_shared_object_data_.nshared_total);
1784 1784 ph.shared_denominator = 4; // doesn't matter
1785 1785  
1786 1786 // It isn't clear how to compute content offset and content length. Since we are not
... ... @@ -1812,9 +1812,9 @@ Lin::calculateHPageOffset(QPDFWriter::NewObjTable const&amp; new_obj, QPDFWriter::Ob
1812 1812 void
1813 1813 Lin::calculateHSharedObject(QPDFWriter::NewObjTable const& new_obj, QPDFWriter::ObjTable const& obj)
1814 1814 {
1815   - CHSharedObject& cso = m->c_shared_object_data;
  1815 + CHSharedObject& cso = c_shared_object_data_;
1816 1816 std::vector<CHSharedObjectEntry>& csoe = cso.entries;
1817   - HSharedObject& so = m->shared_object_hints;
  1817 + HSharedObject& so = shared_object_hints_;
1818 1818 std::vector<HSharedObjectEntry>& soe = so.entries;
1819 1819 soe.clear();
1820 1820  
... ... @@ -1857,13 +1857,13 @@ Lin::calculateHSharedObject(QPDFWriter::NewObjTable const&amp; new_obj, QPDFWriter::
1857 1857 void
1858 1858 Lin::calculateHOutline(QPDFWriter::NewObjTable const& new_obj, QPDFWriter::ObjTable const& obj)
1859 1859 {
1860   - HGeneric& cho = m->c_outline_data;
  1860 + HGeneric& cho = c_outline_data_;
1861 1861  
1862 1862 if (cho.nobjects == 0) {
1863 1863 return;
1864 1864 }
1865 1865  
1866   - HGeneric& ho = m->outline_hints;
  1866 + HGeneric& ho = outline_hints_;
1867 1867  
1868 1868 ho.first_object = obj[cho.first_object].renumber;
1869 1869 ho.first_object_offset = new_obj[ho.first_object].xref.getOffset();
... ... @@ -1908,7 +1908,7 @@ write_vector_vector(
1908 1908 void
1909 1909 Lin::writeHPageOffset(BitWriter& w)
1910 1910 {
1911   - HPageOffset& t = m->page_offset_hints;
  1911 + HPageOffset& t = page_offset_hints_;
1912 1912  
1913 1913 w.writeBitsInt(t.min_nobjects, 32); // 1
1914 1914 w.writeBits(toULL(t.first_page_offset), 32); // 2
... ... @@ -1955,7 +1955,7 @@ Lin::writeHPageOffset(BitWriter&amp; w)
1955 1955 void
1956 1956 Lin::writeHSharedObject(BitWriter& w)
1957 1957 {
1958   - HSharedObject& t = m->shared_object_hints;
  1958 + HSharedObject& t = shared_object_hints_;
1959 1959  
1960 1960 w.writeBitsInt(t.first_shared_obj, 32); // 1
1961 1961 w.writeBits(toULL(t.first_shared_offset), 32); // 2
... ... @@ -2017,9 +2017,9 @@ Lin::generateHintStream(
2017 2017 S = toI(c.getCount());
2018 2018 writeHSharedObject(w);
2019 2019 O = 0;
2020   - if (m->outline_hints.nobjects > 0) {
  2020 + if (outline_hints_.nobjects > 0) {
2021 2021 O = toI(c.getCount());
2022   - writeHGeneric(w, m->outline_hints);
  2022 + writeHGeneric(w, outline_hints_);
2023 2023 }
2024 2024 if (compressed) {
2025 2025 hint_buffer = pl::pipe<Pl_Flate>(hint_buffer, Pl_Flate::a_deflate);
... ...
libqpdf/qpdf/QPDF_private.hh
... ... @@ -236,134 +236,8 @@ class QPDF::StringDecrypter final: public QPDFObjectHandle::StringDecrypter
236 236 QPDF* qpdf;
237 237 QPDFObjGen og;
238 238 };
239   -
240   -// PDF 1.4: Table F.4
241   -struct QPDF::HPageOffsetEntry
242   -{
243   - int delta_nobjects{0}; // 1
244   - qpdf_offset_t delta_page_length{0}; // 2
245   - // vectors' sizes = nshared_objects
246   - int nshared_objects{0}; // 3
247   - std::vector<int> shared_identifiers; // 4
248   - std::vector<int> shared_numerators; // 5
249   - qpdf_offset_t delta_content_offset{0}; // 6
250   - qpdf_offset_t delta_content_length{0}; // 7
251   -};
252   -
253   -// PDF 1.4: Table F.3
254   -struct QPDF::HPageOffset
255   -{
256   - int min_nobjects{0}; // 1
257   - qpdf_offset_t first_page_offset{0}; // 2
258   - int nbits_delta_nobjects{0}; // 3
259   - int min_page_length{0}; // 4
260   - int nbits_delta_page_length{0}; // 5
261   - int min_content_offset{0}; // 6
262   - int nbits_delta_content_offset{0}; // 7
263   - int min_content_length{0}; // 8
264   - int nbits_delta_content_length{0}; // 9
265   - int nbits_nshared_objects{0}; // 10
266   - int nbits_shared_identifier{0}; // 11
267   - int nbits_shared_numerator{0}; // 12
268   - int shared_denominator{0}; // 13
269   - // vector size is npages
270   - std::vector<HPageOffsetEntry> entries;
271   -};
272   -
273   -// PDF 1.4: Table F.6
274   -struct QPDF::HSharedObjectEntry
275   -{
276   - // Item 3 is a 128-bit signature (unsupported by Acrobat)
277   - int delta_group_length{0}; // 1
278   - int signature_present{0}; // 2 -- always 0
279   - int nobjects_minus_one{0}; // 4 -- always 0
280   -};
281   -
282   -// PDF 1.4: Table F.5
283   -struct QPDF::HSharedObject
284   -{
285   - int first_shared_obj{0}; // 1
286   - qpdf_offset_t first_shared_offset{0}; // 2
287   - int nshared_first_page{0}; // 3
288   - int nshared_total{0}; // 4
289   - int nbits_nobjects{0}; // 5
290   - int min_group_length{0}; // 6
291   - int nbits_delta_group_length{0}; // 7
292   - // vector size is nshared_total
293   - std::vector<HSharedObjectEntry> entries;
294   -};
295   -
296   -// PDF 1.4: Table F.9
297   -struct QPDF::HGeneric
298   -{
299   - int first_object{0}; // 1
300   - qpdf_offset_t first_object_offset{0}; // 2
301   - int nobjects{0}; // 3
302   - int group_length{0}; // 4
303   -};
304   -
305 239 // Other linearization data structures
306 240  
307   -// Initialized from Linearization Parameter dictionary
308   -struct QPDF::LinParameters
309   -{
310   - qpdf_offset_t file_size{0}; // /L
311   - int first_page_object{0}; // /O
312   - qpdf_offset_t first_page_end{0}; // /E
313   - size_t npages{0}; // /N
314   - qpdf_offset_t xref_zero_offset{0}; // /T
315   - int first_page{0}; // /P
316   - qpdf_offset_t H_offset{0}; // offset of primary hint stream
317   - qpdf_offset_t H_length{0}; // length of primary hint stream
318   -};
319   -
320   -// Computed hint table value data structures. These tables contain the computed values on which
321   -// the hint table values are based. They exclude things like number of bits and store actual
322   -// values instead of mins and deltas. File offsets are also absolute rather than being offset
323   -// by the size of the primary hint table. We populate the hint table structures from these
324   -// during writing and compare the hint table values with these during validation. We ignore
325   -// some values for various reasons described in the code. Those values are omitted from these
326   -// structures. Note also that object numbers are object numbers from the input file, not the
327   -// output file.
328   -
329   -// Naming convention: CHSomething is analogous to HSomething above. "CH" is computed hint.
330   -
331   -struct QPDF::CHPageOffsetEntry
332   -{
333   - int nobjects{0};
334   - int nshared_objects{0};
335   - // vectors' sizes = nshared_objects
336   - std::vector<int> shared_identifiers;
337   -};
338   -
339   -struct QPDF::CHPageOffset
340   -{
341   - // vector size is npages
342   - std::vector<CHPageOffsetEntry> entries;
343   -};
344   -
345   -struct QPDF::CHSharedObjectEntry
346   -{
347   - CHSharedObjectEntry(int object) :
348   - object(object)
349   - {
350   - }
351   -
352   - int object;
353   -};
354   -
355   -// PDF 1.4: Table F.5
356   -struct QPDF::CHSharedObject
357   -{
358   - int first_shared_obj{0};
359   - int nshared_first_page{0};
360   - int nshared_total{0};
361   - // vector size is nshared_total
362   - std::vector<CHSharedObjectEntry> entries;
363   -};
364   -
365   -// No need for CHGeneric -- HGeneric is fine as is.
366   -
367 241 class QPDF::PatternFinder final: public InputSource::Finder
368 242 {
369 243 public:
... ... @@ -736,13 +610,140 @@ class QPDF::Doc::Linearization: Common
736 610  
737 611 struct UpdateObjectMapsFrame
738 612 {
739   - UpdateObjectMapsFrame(ObjUser const& ou, QPDFObjectHandle oh, bool top) ;
  613 + UpdateObjectMapsFrame(ObjUser const& ou, QPDFObjectHandle oh, bool top);
740 614  
741 615 ObjUser const& ou;
742 616 QPDFObjectHandle oh;
743 617 bool top;
744 618 };
745 619  
  620 + // PDF 1.4: Table F.4
  621 + struct HPageOffsetEntry
  622 + {
  623 + int delta_nobjects{0}; // 1
  624 + qpdf_offset_t delta_page_length{0}; // 2
  625 + // vectors' sizes = nshared_objects
  626 + int nshared_objects{0}; // 3
  627 + std::vector<int> shared_identifiers; // 4
  628 + std::vector<int> shared_numerators; // 5
  629 + qpdf_offset_t delta_content_offset{0}; // 6
  630 + qpdf_offset_t delta_content_length{0}; // 7
  631 + };
  632 +
  633 + // PDF 1.4: Table F.3
  634 + struct HPageOffset
  635 + {
  636 + int min_nobjects{0}; // 1
  637 + qpdf_offset_t first_page_offset{0}; // 2
  638 + int nbits_delta_nobjects{0}; // 3
  639 + int min_page_length{0}; // 4
  640 + int nbits_delta_page_length{0}; // 5
  641 + int min_content_offset{0}; // 6
  642 + int nbits_delta_content_offset{0}; // 7
  643 + int min_content_length{0}; // 8
  644 + int nbits_delta_content_length{0}; // 9
  645 + int nbits_nshared_objects{0}; // 10
  646 + int nbits_shared_identifier{0}; // 11
  647 + int nbits_shared_numerator{0}; // 12
  648 + int shared_denominator{0}; // 13
  649 + // vector size is npages
  650 + std::vector<HPageOffsetEntry> entries;
  651 + };
  652 +
  653 + // PDF 1.4: Table F.6
  654 + struct HSharedObjectEntry
  655 + {
  656 + // Item 3 is a 128-bit signature (unsupported by Acrobat)
  657 + int delta_group_length{0}; // 1
  658 + int signature_present{0}; // 2 -- always 0
  659 + int nobjects_minus_one{0}; // 4 -- always 0
  660 + };
  661 +
  662 + // PDF 1.4: Table F.5
  663 + struct HSharedObject
  664 + {
  665 + int first_shared_obj{0}; // 1
  666 + qpdf_offset_t first_shared_offset{0}; // 2
  667 + int nshared_first_page{0}; // 3
  668 + int nshared_total{0}; // 4
  669 + int nbits_nobjects{0}; // 5
  670 + int min_group_length{0}; // 6
  671 + int nbits_delta_group_length{0}; // 7
  672 + // vector size is nshared_total
  673 + std::vector<HSharedObjectEntry> entries;
  674 + };
  675 +
  676 + // PDF 1.4: Table F.9
  677 + struct HGeneric
  678 + {
  679 + int first_object{0}; // 1
  680 + qpdf_offset_t first_object_offset{0}; // 2
  681 + int nobjects{0}; // 3
  682 + int group_length{0}; // 4
  683 + };
  684 +
  685 + // Other linearization data structures
  686 +
  687 + // Initialized from Linearization Parameter dictionary
  688 + struct LinParameters
  689 + {
  690 + qpdf_offset_t file_size{0}; // /L
  691 + int first_page_object{0}; // /O
  692 + qpdf_offset_t first_page_end{0}; // /E
  693 + size_t npages{0}; // /N
  694 + qpdf_offset_t xref_zero_offset{0}; // /T
  695 + int first_page{0}; // /P
  696 + qpdf_offset_t H_offset{0}; // offset of primary hint stream
  697 + qpdf_offset_t H_length{0}; // length of primary hint stream
  698 + };
  699 +
  700 + // Computed hint table value data structures. These tables contain the computed values on which
  701 + // the hint table values are based. They exclude things like number of bits and store actual
  702 + // values instead of mins and deltas. File offsets are also absolute rather than being offset
  703 + // by the size of the primary hint table. We populate the hint table structures from these
  704 + // during writing and compare the hint table values with these during validation. We ignore
  705 + // some values for various reasons described in the code. Those values are omitted from these
  706 + // structures. Note also that object numbers are object numbers from the input file, not the
  707 + // output file.
  708 +
  709 + // Naming convention: CHSomething is analogous to HSomething above. "CH" is computed hint.
  710 +
  711 + struct CHPageOffsetEntry
  712 + {
  713 + int nobjects{0};
  714 + int nshared_objects{0};
  715 + // vectors' sizes = nshared_objects
  716 + std::vector<int> shared_identifiers;
  717 + };
  718 +
  719 + struct CHPageOffset
  720 + {
  721 + // vector size is npages
  722 + std::vector<CHPageOffsetEntry> entries;
  723 + };
  724 +
  725 + struct CHSharedObjectEntry
  726 + {
  727 + CHSharedObjectEntry(int object) :
  728 + object(object)
  729 + {
  730 + }
  731 +
  732 + int object;
  733 + };
  734 +
  735 + // PDF 1.4: Table F.5
  736 + struct CHSharedObject
  737 + {
  738 + int first_shared_obj{0};
  739 + int nshared_first_page{0};
  740 + int nshared_total{0};
  741 + // vector size is nshared_total
  742 + std::vector<CHSharedObjectEntry> entries;
  743 + };
  744 +
  745 + // No need for CHGeneric -- HGeneric is fine as is.
  746 +
746 747 // methods to support linearization checking -- implemented in QPDF_linearization.cc
747 748  
748 749 void readLinearizationData();
... ... @@ -801,6 +802,23 @@ class QPDF::Doc::Linearization: Common
801 802 // Optimization data
802 803 std::map<ObjUser, std::set<QPDFObjGen>> obj_user_to_objects_;
803 804 std::map<QPDFObjGen, std::set<ObjUser>> object_to_obj_users_;
  805 +
  806 + // Linearization data
  807 +
  808 + // Linearization parameter dictionary and hint table data: may be read from file or computed
  809 + // prior to writing a linearized file
  810 + QPDFObjectHandle lindict_;
  811 + LinParameters linp_;
  812 + HPageOffset page_offset_hints_;
  813 + HSharedObject shared_object_hints_;
  814 + HGeneric outline_hints_;
  815 +
  816 + // Computed linearization data: used to populate above tables during writing and to compare
  817 + // with them during validation. c_ means computed.
  818 + LinParameters c_linp_;
  819 + CHPageOffset c_page_offset_data_;
  820 + CHSharedObject c_shared_object_data_;
  821 + HGeneric c_outline_data_;
804 822 };
805 823  
806 824 class QPDF::Doc::Objects: Common
... ... @@ -1151,21 +1169,6 @@ class QPDF::Members: Doc
1151 1169 bool uncompressed_after_compressed{false};
1152 1170 bool linearization_warnings{false}; // set by linearizationWarning, used by checkLinearization
1153 1171  
1154   - // Linearization parameter dictionary and hint table data: may be read from file or computed
1155   - // prior to writing a linearized file
1156   - QPDFObjectHandle lindict;
1157   - LinParameters linp;
1158   - HPageOffset page_offset_hints;
1159   - HSharedObject shared_object_hints;
1160   - HGeneric outline_hints;
1161   -
1162   - // Computed linearization data: used to populate above tables during writing and to compare
1163   - // with them during validation. c_ means computed.
1164   - LinParameters c_linp;
1165   - CHPageOffset c_page_offset_data;
1166   - CHSharedObject c_shared_object_data;
1167   - HGeneric c_outline_data;
1168   -
1169 1172 // Object ordering data for linearized files: initialized by calculateLinearizationData().
1170 1173 // Part numbers refer to the PDF 1.4 specification.
1171 1174 std::vector<QPDFObjectHandle> part4;
... ...