diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh index 046c0103..2d9913ef 100644 --- a/include/qpdf/QPDF.hh +++ b/include/qpdf/QPDF.hh @@ -744,14 +744,13 @@ class QPDF generateHintStream( QPDF& qpdf, QPDFWriter::NewObjTable const& new_obj, - std::map const& lengths, QPDFWriter::ObjTable const& obj, std::shared_ptr& hint_stream, int& S, int& O, bool compressed) { - return qpdf.generateHintStream(new_obj, lengths, obj, hint_stream, S, O, compressed); + return qpdf.generateHintStream(new_obj, obj, hint_stream, S, O, compressed); } static void @@ -1103,7 +1102,6 @@ class QPDF void generateHintStream( QPDFWriter::NewObjTable const& new_obj, - std::map const& lengths, QPDFWriter::ObjTable const& obj, std::shared_ptr& hint_stream, int& S, @@ -1378,20 +1376,13 @@ class QPDF int outputLengthNextN( int in_object, int n, - std::map const& lengths, - QPDFWriter::ObjTable const& obj); - void calculateHPageOffset( QPDFWriter::NewObjTable const& new_obj, - std::map const& lengths, - QPDFWriter::ObjTable const& obj); - void calculateHSharedObject( - QPDFWriter::NewObjTable const& new_obj, - std::map const& lengths, - QPDFWriter::ObjTable const& obj); - void calculateHOutline( - QPDFWriter::NewObjTable const& new_obj, - std::map const& lengths, QPDFWriter::ObjTable const& obj); + void + calculateHPageOffset(QPDFWriter::NewObjTable const& new_obj, QPDFWriter::ObjTable const& obj); + void + calculateHSharedObject(QPDFWriter::NewObjTable const& new_obj, QPDFWriter::ObjTable const& obj); + void calculateHOutline(QPDFWriter::NewObjTable const& new_obj, QPDFWriter::ObjTable const& obj); void writeHPageOffset(BitWriter&); void writeHSharedObject(BitWriter&); void writeHGeneric(BitWriter&, HGeneric&); diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc index 51052cdb..8af3eda6 100644 --- a/libqpdf/QPDFWriter.cc +++ b/libqpdf/QPDFWriter.cc @@ -1050,7 +1050,8 @@ QPDFWriter::closeObject(int objid) // Write a newline before endobj as it makes the file easier to repair. writeString("\nendobj\n"); writeStringQDF("\n"); - m->lengths[objid] = m->pipeline->getCount() - m->new_obj[objid].xref.getOffset(); + auto& new_obj = m->new_obj[objid]; + new_obj.length = m->pipeline->getCount() - new_obj.xref.getOffset(); } void @@ -2309,8 +2310,7 @@ QPDFWriter::writeHintStream(int hint_id) int S = 0; int O = 0; bool compressed = (m->compress_streams && !m->qdf_mode); - QPDF::Writer::generateHintStream( - m->pdf, m->new_obj, m->lengths, m->obj, hint_buffer, S, O, compressed); + QPDF::Writer::generateHintStream(m->pdf, m->new_obj, m->obj, hint_buffer, S, O, compressed); openObject(hint_id); setDataKey(hint_id); diff --git a/libqpdf/QPDF_linearization.cc b/libqpdf/QPDF_linearization.cc index de32beb1..4489f616 100644 --- a/libqpdf/QPDF_linearization.cc +++ b/libqpdf/QPDF_linearization.cc @@ -1457,33 +1457,29 @@ nbits(int val) int QPDF::outputLengthNextN( - int in_object, - int n, - std::map const& lengths, - QPDFWriter::ObjTable const& obj) + int in_object, int n, QPDFWriter::NewObjTable const& new_obj, 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. int first = obj[in_object].renumber; + int last = first + n; if (first <= 0) { stopOnError("found object that is not renumbered while writing linearization data"); } - int length = 0; - for (int i = 0; i < n; ++i) { - if (lengths.count(first + i) == 0) { + qpdf_offset_t length = 0; + for (int i = first; i < last; ++i) { + auto l = new_obj[i].length; + if (l == 0) { stopOnError("found item with unknown length while writing linearization data"); } - length += toI((*(lengths.find(first + toI(i)))).second); + length += l; } - return length; + return toI(length); } void -QPDF::calculateHPageOffset( - QPDFWriter::NewObjTable const& new_obj, - std::map const& lengths, - QPDFWriter::ObjTable const& obj) +QPDF::calculateHPageOffset(QPDFWriter::NewObjTable const& new_obj, QPDFWriter::ObjTable const& obj) { // Page Offset Hint Table @@ -1498,7 +1494,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); + int min_length = outputLengthNextN(pages.at(0).getObjectID(), min_nobjects, new_obj, obj); int max_length = min_length; int max_shared = cphe.at(0).nshared_objects; @@ -1515,7 +1511,7 @@ QPDF::calculateHPageOffset( // assignments. int nobjects = cphe.at(i).nobjects; - int length = outputLengthNextN(pages.at(i).getObjectID(), nobjects, lengths, obj); + int length = outputLengthNextN(pages.at(i).getObjectID(), nobjects, new_obj, obj); int nshared = cphe.at(i).nshared_objects; min_nobjects = std::min(min_nobjects, nobjects); @@ -1565,9 +1561,7 @@ QPDF::calculateHPageOffset( void QPDF::calculateHSharedObject( - QPDFWriter::NewObjTable const& new_obj, - std::map const& lengths, - QPDFWriter::ObjTable const& obj) + QPDFWriter::NewObjTable const& new_obj, QPDFWriter::ObjTable const& obj) { CHSharedObject& cso = m->c_shared_object_data; std::vector& csoe = cso.entries; @@ -1575,12 +1569,12 @@ QPDF::calculateHSharedObject( std::vector& soe = so.entries; soe.clear(); - int min_length = outputLengthNextN(csoe.at(0).object, 1, lengths, obj); + int min_length = outputLengthNextN(csoe.at(0).object, 1, new_obj, 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); + int length = outputLengthNextN(csoe.at(i).object, 1, new_obj, obj); min_length = std::min(min_length, length); max_length = std::max(max_length, length); soe.emplace_back(); @@ -1610,10 +1604,7 @@ QPDF::calculateHSharedObject( } void -QPDF::calculateHOutline( - QPDFWriter::NewObjTable const& new_obj, - std::map const& lengths, - QPDFWriter::ObjTable const& obj) +QPDF::calculateHOutline(QPDFWriter::NewObjTable const& new_obj, QPDFWriter::ObjTable const& obj) { HGeneric& cho = m->c_outline_data; @@ -1626,7 +1617,7 @@ QPDF::calculateHOutline( ho.first_object = obj[cho.first_object].renumber; ho.first_object_offset = new_obj[ho.first_object].xref.getOffset(); ho.nobjects = cho.nobjects; - ho.group_length = outputLengthNextN(cho.first_object, ho.nobjects, lengths, obj); + ho.group_length = outputLengthNextN(cho.first_object, ho.nobjects, new_obj, obj); } template @@ -1756,7 +1747,6 @@ QPDF::writeHGeneric(BitWriter& w, HGeneric& t) void QPDF::generateHintStream( QPDFWriter::NewObjTable const& new_obj, - std::map const& lengths, QPDFWriter::ObjTable const& obj, std::shared_ptr& hint_buffer, int& S, @@ -1764,9 +1754,9 @@ QPDF::generateHintStream( bool compressed) { // Populate actual hint table values - calculateHPageOffset(new_obj, lengths, obj); - calculateHSharedObject(new_obj, lengths, obj); - calculateHOutline(new_obj, lengths, obj); + calculateHPageOffset(new_obj, obj); + calculateHSharedObject(new_obj, obj); + calculateHOutline(new_obj, 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 eeff3888..e7811d96 100644 --- a/libqpdf/qpdf/QPDFWriter_private.hh +++ b/libqpdf/qpdf/QPDFWriter_private.hh @@ -18,6 +18,7 @@ struct QPDFWriter::Object struct QPDFWriter::NewObject { QPDFXRefEntry xref; + qpdf_offset_t length{0}; }; class QPDFWriter::ObjTable: public ::ObjTable @@ -102,7 +103,6 @@ class QPDFWriter::Members size_t object_queue_front{0}; QPDFWriter::ObjTable obj; QPDFWriter::NewObjTable new_obj; - std::map lengths; int next_objid{1}; int cur_stream_length_id{0}; size_t cur_stream_length{0};