diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh index 922a6ad7..331a5f1f 100644 --- a/include/qpdf/QPDF.hh +++ b/include/qpdf/QPDF.hh @@ -41,6 +41,7 @@ #include #include #include +#include #include class QPDF_Stream; @@ -744,14 +745,13 @@ class QPDF QPDF& qpdf, std::map const& xref, std::map const& lengths, - std::map const& obj_renumber, + QPDFWriter::ObjTable const& obj, std::shared_ptr& hint_stream, int& S, int& O, bool compressed) { - return qpdf.generateHintStream( - xref, lengths, obj_renumber, hint_stream, S, O, compressed); + return qpdf.generateHintStream(xref, lengths, obj, hint_stream, S, O, compressed); } static void @@ -1104,7 +1104,7 @@ class QPDF void generateHintStream( std::map const& xref, std::map const& lengths, - std::map const& obj_renumber, + QPDFWriter::ObjTable const& obj, std::shared_ptr& hint_stream, int& S, int& O, @@ -1379,19 +1379,19 @@ class QPDF int in_object, int n, std::map const& lengths, - std::map const& obj_renumber); + QPDFWriter::ObjTable const& obj); void calculateHPageOffset( std::map const& xref, std::map const& lengths, - std::map const& obj_renumber); + QPDFWriter::ObjTable const& obj); void calculateHSharedObject( std::map const& xref, std::map const& lengths, - std::map const& obj_renumber); + QPDFWriter::ObjTable const& obj); void calculateHOutline( std::map const& xref, std::map const& lengths, - std::map const& obj_renumber); + QPDFWriter::ObjTable const& obj); void writeHPageOffset(BitWriter&); void writeHSharedObject(BitWriter&); void writeHGeneric(BitWriter&, HGeneric&); diff --git a/include/qpdf/QPDFWriter.hh b/include/qpdf/QPDFWriter.hh index f6f18f77..f987bfe3 100644 --- a/include/qpdf/QPDFWriter.hh +++ b/include/qpdf/QPDFWriter.hh @@ -610,7 +610,6 @@ class QPDFWriter void computeDeterministicIDData(); void discardGeneration(std::map const& in, std::map& out); - void discardGeneration(std::map& out); class Members; diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc index de0aa951..327e9ab2 100644 --- a/libqpdf/QPDFWriter.cc +++ b/libqpdf/QPDFWriter.cc @@ -2303,7 +2303,7 @@ QPDFWriter::writeHintStream(int hint_id) int O = 0; bool compressed = (m->compress_streams && !m->qdf_mode); QPDF::Writer::generateHintStream( - m->pdf, m->xref, m->lengths, m->obj_renumber_no_gen, hint_buffer, S, O, compressed); + m->pdf, m->xref, m->lengths, m->obj, hint_buffer, S, O, compressed); openObject(hint_id); setDataKey(hint_id); @@ -2545,26 +2545,6 @@ QPDFWriter::discardGeneration(std::map const& in, std::map& out) -{ - // There are deep assumptions in the linearization code in QPDF that there is only one object - // with each object number; i.e., you can't have two objects with the same object number and - // different generations. This is a pretty safe assumption because Adobe Reader and Acrobat - // can't actually handle this case. There is not much if any code in QPDF outside linearization - // that assumes this, but the linearization code as currently implemented would do weird things - // if we found such a case. In order to avoid breaking ABI changes in QPDF, we will first - // assert that this condition holds. Then we can create new maps for QPDF that throw away - // generation numbers. - - out.clear(); - m->obj.forEach([&out](auto id, auto const& item) -> void { - if (item.renumber > 0) { - out[id] = item.renumber; - } - }); -} - void QPDFWriter::writeLinearized() { @@ -2887,8 +2867,6 @@ QPDFWriter::writeLinearized() writeString(std::to_string(first_xref_offset)); writeString("\n%%EOF\n"); - discardGeneration(m->obj_renumber_no_gen); - if (pass == 1) { if (m->deterministic_id) { QTC::TC("qpdf", "QPDFWriter linearized deterministic ID", need_xref_stream ? 0 : 1); diff --git a/libqpdf/QPDF_linearization.cc b/libqpdf/QPDF_linearization.cc index 1657d54a..4891900b 100644 --- a/libqpdf/QPDF_linearization.cc +++ b/libqpdf/QPDF_linearization.cc @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -1459,15 +1460,15 @@ QPDF::outputLengthNextN( int in_object, int n, std::map const& lengths, - std::map const& obj_renumber) + QPDFWriter::ObjTable const& obj) { // Figure out the length of a series of n consecutive objects in the output file starting with // whatever object in_object from the input file mapped to. - if (obj_renumber.count(in_object) == 0) { + int first = obj[in_object].renumber; + if (first <= 0) { stopOnError("found object that is not renumbered while writing linearization data"); } - int first = (*(obj_renumber.find(in_object))).second; int length = 0; for (int i = 0; i < n; ++i) { if (lengths.count(first + i) == 0) { @@ -1482,7 +1483,7 @@ void QPDF::calculateHPageOffset( std::map const& xref, std::map const& lengths, - std::map const& obj_renumber) + QPDFWriter::ObjTable const& obj) { // Page Offset Hint Table @@ -1497,8 +1498,7 @@ QPDF::calculateHPageOffset( int min_nobjects = cphe.at(0).nobjects; int max_nobjects = min_nobjects; - int min_length = - outputLengthNextN(pages.at(0).getObjectID(), min_nobjects, lengths, obj_renumber); + int min_length = outputLengthNextN(pages.at(0).getObjectID(), min_nobjects, lengths, obj); int max_length = min_length; int max_shared = cphe.at(0).nshared_objects; @@ -1515,7 +1515,7 @@ QPDF::calculateHPageOffset( // assignments. int nobjects = cphe.at(i).nobjects; - int length = outputLengthNextN(pages.at(i).getObjectID(), nobjects, lengths, obj_renumber); + int length = outputLengthNextN(pages.at(i).getObjectID(), nobjects, lengths, obj); int nshared = cphe.at(i).nshared_objects; min_nobjects = std::min(min_nobjects, nobjects); @@ -1530,8 +1530,7 @@ QPDF::calculateHPageOffset( } ph.min_nobjects = min_nobjects; - int in_page0_id = pages.at(0).getObjectID(); - int out_page0_id = (*(obj_renumber.find(in_page0_id))).second; + int out_page0_id = obj[pages.at(0)].renumber; ph.first_page_offset = (*(xref.find(out_page0_id))).second.getOffset(); ph.nbits_delta_nobjects = nbits(max_nobjects - min_nobjects); ph.min_page_length = min_length; @@ -1569,7 +1568,7 @@ void QPDF::calculateHSharedObject( std::map const& xref, std::map const& lengths, - std::map const& obj_renumber) + QPDFWriter::ObjTable const& obj) { CHSharedObject& cso = m->c_shared_object_data; std::vector& csoe = cso.entries; @@ -1577,12 +1576,12 @@ QPDF::calculateHSharedObject( std::vector& soe = so.entries; soe.clear(); - int min_length = outputLengthNextN(csoe.at(0).object, 1, lengths, obj_renumber); + int min_length = outputLengthNextN(csoe.at(0).object, 1, lengths, obj); int max_length = min_length; for (size_t i = 0; i < toS(cso.nshared_total); ++i) { // Assign absolute numbers to deltas; adjust later - int length = outputLengthNextN(csoe.at(i).object, 1, lengths, obj_renumber); + int length = outputLengthNextN(csoe.at(i).object, 1, lengths, obj); min_length = std::min(min_length, length); max_length = std::max(max_length, length); soe.emplace_back(); @@ -1595,7 +1594,7 @@ QPDF::calculateHSharedObject( so.nshared_total = cso.nshared_total; so.nshared_first_page = cso.nshared_first_page; if (so.nshared_total > so.nshared_first_page) { - so.first_shared_obj = (*(obj_renumber.find(cso.first_shared_obj))).second; + so.first_shared_obj = obj[cso.first_shared_obj].renumber; so.first_shared_offset = (*(xref.find(so.first_shared_obj))).second.getOffset(); } so.min_group_length = min_length; @@ -1614,7 +1613,7 @@ void QPDF::calculateHOutline( std::map const& xref, std::map const& lengths, - std::map const& obj_renumber) + QPDFWriter::ObjTable const& obj) { HGeneric& cho = m->c_outline_data; @@ -1624,10 +1623,10 @@ QPDF::calculateHOutline( HGeneric& ho = m->outline_hints; - ho.first_object = (*(obj_renumber.find(cho.first_object))).second; + ho.first_object = obj[cho.first_object].renumber; ho.first_object_offset = (*(xref.find(ho.first_object))).second.getOffset(); ho.nobjects = cho.nobjects; - ho.group_length = outputLengthNextN(cho.first_object, ho.nobjects, lengths, obj_renumber); + ho.group_length = outputLengthNextN(cho.first_object, ho.nobjects, lengths, obj); } template @@ -1758,16 +1757,16 @@ void QPDF::generateHintStream( std::map const& xref, std::map const& lengths, - std::map const& obj_renumber, + QPDFWriter::ObjTable const& obj, std::shared_ptr& hint_buffer, int& S, int& O, bool compressed) { // Populate actual hint table values - calculateHPageOffset(xref, lengths, obj_renumber); - calculateHSharedObject(xref, lengths, obj_renumber); - calculateHOutline(xref, lengths, obj_renumber); + calculateHPageOffset(xref, lengths, obj); + calculateHSharedObject(xref, lengths, obj); + calculateHOutline(xref, lengths, obj); // Write the hint stream itself into a compressed memory buffer. Write through a counter so we // can get offsets. diff --git a/libqpdf/qpdf/QPDFWriter_private.hh b/libqpdf/qpdf/QPDFWriter_private.hh index 3ec15f09..8af950e0 100644 --- a/libqpdf/qpdf/QPDFWriter_private.hh +++ b/libqpdf/qpdf/QPDFWriter_private.hh @@ -99,7 +99,6 @@ class QPDFWriter::Members // For linearization only std::string lin_pass1_filename; - std::map obj_renumber_no_gen; std::map object_to_object_stream_no_gen; // For progress reporting