2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-05-31 17:30:54 +00:00

In QPDFWriter replace map obj_renumber_no_gen with ObjTable obj

This commit is contained in:
m-holger 2024-02-19 12:05:55 +00:00
parent 8791b5f8d0
commit 84e25919cb
5 changed files with 28 additions and 53 deletions

View File

@ -41,6 +41,7 @@
#include <qpdf/QPDFObjectHandle.hh> #include <qpdf/QPDFObjectHandle.hh>
#include <qpdf/QPDFStreamFilter.hh> #include <qpdf/QPDFStreamFilter.hh>
#include <qpdf/QPDFTokenizer.hh> #include <qpdf/QPDFTokenizer.hh>
#include <qpdf/QPDFWriter.hh>
#include <qpdf/QPDFXRefEntry.hh> #include <qpdf/QPDFXRefEntry.hh>
class QPDF_Stream; class QPDF_Stream;
@ -744,14 +745,13 @@ class QPDF
QPDF& qpdf, QPDF& qpdf,
std::map<int, QPDFXRefEntry> const& xref, std::map<int, QPDFXRefEntry> const& xref,
std::map<int, qpdf_offset_t> const& lengths, std::map<int, qpdf_offset_t> const& lengths,
std::map<int, int> const& obj_renumber, QPDFWriter::ObjTable const& obj,
std::shared_ptr<Buffer>& hint_stream, std::shared_ptr<Buffer>& hint_stream,
int& S, int& S,
int& O, int& O,
bool compressed) bool compressed)
{ {
return qpdf.generateHintStream( return qpdf.generateHintStream(xref, lengths, obj, hint_stream, S, O, compressed);
xref, lengths, obj_renumber, hint_stream, S, O, compressed);
} }
static void static void
@ -1104,7 +1104,7 @@ class QPDF
void generateHintStream( void generateHintStream(
std::map<int, QPDFXRefEntry> const& xref, std::map<int, QPDFXRefEntry> const& xref,
std::map<int, qpdf_offset_t> const& lengths, std::map<int, qpdf_offset_t> const& lengths,
std::map<int, int> const& obj_renumber, QPDFWriter::ObjTable const& obj,
std::shared_ptr<Buffer>& hint_stream, std::shared_ptr<Buffer>& hint_stream,
int& S, int& S,
int& O, int& O,
@ -1379,19 +1379,19 @@ class QPDF
int in_object, int in_object,
int n, int n,
std::map<int, qpdf_offset_t> const& lengths, std::map<int, qpdf_offset_t> const& lengths,
std::map<int, int> const& obj_renumber); QPDFWriter::ObjTable const& obj);
void calculateHPageOffset( void calculateHPageOffset(
std::map<int, QPDFXRefEntry> const& xref, std::map<int, QPDFXRefEntry> const& xref,
std::map<int, qpdf_offset_t> const& lengths, std::map<int, qpdf_offset_t> const& lengths,
std::map<int, int> const& obj_renumber); QPDFWriter::ObjTable const& obj);
void calculateHSharedObject( void calculateHSharedObject(
std::map<int, QPDFXRefEntry> const& xref, std::map<int, QPDFXRefEntry> const& xref,
std::map<int, qpdf_offset_t> const& lengths, std::map<int, qpdf_offset_t> const& lengths,
std::map<int, int> const& obj_renumber); QPDFWriter::ObjTable const& obj);
void calculateHOutline( void calculateHOutline(
std::map<int, QPDFXRefEntry> const& xref, std::map<int, QPDFXRefEntry> const& xref,
std::map<int, qpdf_offset_t> const& lengths, std::map<int, qpdf_offset_t> const& lengths,
std::map<int, int> const& obj_renumber); QPDFWriter::ObjTable const& obj);
void writeHPageOffset(BitWriter&); void writeHPageOffset(BitWriter&);
void writeHSharedObject(BitWriter&); void writeHSharedObject(BitWriter&);
void writeHGeneric(BitWriter&, HGeneric&); void writeHGeneric(BitWriter&, HGeneric&);

View File

@ -610,7 +610,6 @@ class QPDFWriter
void computeDeterministicIDData(); void computeDeterministicIDData();
void discardGeneration(std::map<QPDFObjGen, int> const& in, std::map<int, int>& out); void discardGeneration(std::map<QPDFObjGen, int> const& in, std::map<int, int>& out);
void discardGeneration(std::map<int, int>& out);
class Members; class Members;

View File

@ -2303,7 +2303,7 @@ QPDFWriter::writeHintStream(int hint_id)
int O = 0; int O = 0;
bool compressed = (m->compress_streams && !m->qdf_mode); bool compressed = (m->compress_streams && !m->qdf_mode);
QPDF::Writer::generateHintStream( 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); openObject(hint_id);
setDataKey(hint_id); setDataKey(hint_id);
@ -2545,26 +2545,6 @@ QPDFWriter::discardGeneration(std::map<QPDFObjGen, int> const& in, std::map<int,
} }
} }
void
QPDFWriter::discardGeneration(std::map<int, int>& 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 void
QPDFWriter::writeLinearized() QPDFWriter::writeLinearized()
{ {
@ -2887,8 +2867,6 @@ QPDFWriter::writeLinearized()
writeString(std::to_string(first_xref_offset)); writeString(std::to_string(first_xref_offset));
writeString("\n%%EOF\n"); writeString("\n%%EOF\n");
discardGeneration(m->obj_renumber_no_gen);
if (pass == 1) { if (pass == 1) {
if (m->deterministic_id) { if (m->deterministic_id) {
QTC::TC("qpdf", "QPDFWriter linearized deterministic ID", need_xref_stream ? 0 : 1); QTC::TC("qpdf", "QPDFWriter linearized deterministic ID", need_xref_stream ? 0 : 1);

View File

@ -9,6 +9,7 @@
#include <qpdf/Pl_Flate.hh> #include <qpdf/Pl_Flate.hh>
#include <qpdf/QPDFExc.hh> #include <qpdf/QPDFExc.hh>
#include <qpdf/QPDFLogger.hh> #include <qpdf/QPDFLogger.hh>
#include <qpdf/QPDFWriter_private.hh>
#include <qpdf/QTC.hh> #include <qpdf/QTC.hh>
#include <qpdf/QUtil.hh> #include <qpdf/QUtil.hh>
@ -1459,15 +1460,15 @@ QPDF::outputLengthNextN(
int in_object, int in_object,
int n, int n,
std::map<int, qpdf_offset_t> const& lengths, std::map<int, qpdf_offset_t> const& lengths,
std::map<int, int> const& obj_renumber) QPDFWriter::ObjTable const& obj)
{ {
// Figure out the length of a series of n consecutive objects in the output file starting with // 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. // 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"); stopOnError("found object that is not renumbered while writing linearization data");
} }
int first = (*(obj_renumber.find(in_object))).second;
int length = 0; int length = 0;
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
if (lengths.count(first + i) == 0) { if (lengths.count(first + i) == 0) {
@ -1482,7 +1483,7 @@ void
QPDF::calculateHPageOffset( QPDF::calculateHPageOffset(
std::map<int, QPDFXRefEntry> const& xref, std::map<int, QPDFXRefEntry> const& xref,
std::map<int, qpdf_offset_t> const& lengths, std::map<int, qpdf_offset_t> const& lengths,
std::map<int, int> const& obj_renumber) QPDFWriter::ObjTable const& obj)
{ {
// Page Offset Hint Table // Page Offset Hint Table
@ -1497,8 +1498,7 @@ QPDF::calculateHPageOffset(
int min_nobjects = cphe.at(0).nobjects; int min_nobjects = cphe.at(0).nobjects;
int max_nobjects = min_nobjects; int max_nobjects = min_nobjects;
int min_length = int min_length = outputLengthNextN(pages.at(0).getObjectID(), min_nobjects, lengths, obj);
outputLengthNextN(pages.at(0).getObjectID(), min_nobjects, lengths, obj_renumber);
int max_length = min_length; int max_length = min_length;
int max_shared = cphe.at(0).nshared_objects; int max_shared = cphe.at(0).nshared_objects;
@ -1515,7 +1515,7 @@ QPDF::calculateHPageOffset(
// assignments. // assignments.
int nobjects = cphe.at(i).nobjects; 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; int nshared = cphe.at(i).nshared_objects;
min_nobjects = std::min(min_nobjects, nobjects); min_nobjects = std::min(min_nobjects, nobjects);
@ -1530,8 +1530,7 @@ QPDF::calculateHPageOffset(
} }
ph.min_nobjects = min_nobjects; ph.min_nobjects = min_nobjects;
int in_page0_id = pages.at(0).getObjectID(); int out_page0_id = obj[pages.at(0)].renumber;
int out_page0_id = (*(obj_renumber.find(in_page0_id))).second;
ph.first_page_offset = (*(xref.find(out_page0_id))).second.getOffset(); ph.first_page_offset = (*(xref.find(out_page0_id))).second.getOffset();
ph.nbits_delta_nobjects = nbits(max_nobjects - min_nobjects); ph.nbits_delta_nobjects = nbits(max_nobjects - min_nobjects);
ph.min_page_length = min_length; ph.min_page_length = min_length;
@ -1569,7 +1568,7 @@ void
QPDF::calculateHSharedObject( QPDF::calculateHSharedObject(
std::map<int, QPDFXRefEntry> const& xref, std::map<int, QPDFXRefEntry> const& xref,
std::map<int, qpdf_offset_t> const& lengths, std::map<int, qpdf_offset_t> const& lengths,
std::map<int, int> const& obj_renumber) QPDFWriter::ObjTable const& obj)
{ {
CHSharedObject& cso = m->c_shared_object_data; CHSharedObject& cso = m->c_shared_object_data;
std::vector<CHSharedObjectEntry>& csoe = cso.entries; std::vector<CHSharedObjectEntry>& csoe = cso.entries;
@ -1577,12 +1576,12 @@ QPDF::calculateHSharedObject(
std::vector<HSharedObjectEntry>& soe = so.entries; std::vector<HSharedObjectEntry>& soe = so.entries;
soe.clear(); 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; int max_length = min_length;
for (size_t i = 0; i < toS(cso.nshared_total); ++i) { for (size_t i = 0; i < toS(cso.nshared_total); ++i) {
// Assign absolute numbers to deltas; adjust later // 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); min_length = std::min(min_length, length);
max_length = std::max(max_length, length); max_length = std::max(max_length, length);
soe.emplace_back(); soe.emplace_back();
@ -1595,7 +1594,7 @@ QPDF::calculateHSharedObject(
so.nshared_total = cso.nshared_total; so.nshared_total = cso.nshared_total;
so.nshared_first_page = cso.nshared_first_page; so.nshared_first_page = cso.nshared_first_page;
if (so.nshared_total > so.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.first_shared_offset = (*(xref.find(so.first_shared_obj))).second.getOffset();
} }
so.min_group_length = min_length; so.min_group_length = min_length;
@ -1614,7 +1613,7 @@ void
QPDF::calculateHOutline( QPDF::calculateHOutline(
std::map<int, QPDFXRefEntry> const& xref, std::map<int, QPDFXRefEntry> const& xref,
std::map<int, qpdf_offset_t> const& lengths, std::map<int, qpdf_offset_t> const& lengths,
std::map<int, int> const& obj_renumber) QPDFWriter::ObjTable const& obj)
{ {
HGeneric& cho = m->c_outline_data; HGeneric& cho = m->c_outline_data;
@ -1624,10 +1623,10 @@ QPDF::calculateHOutline(
HGeneric& ho = m->outline_hints; 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.first_object_offset = (*(xref.find(ho.first_object))).second.getOffset();
ho.nobjects = cho.nobjects; 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 <class T, class int_type> template <class T, class int_type>
@ -1758,16 +1757,16 @@ void
QPDF::generateHintStream( QPDF::generateHintStream(
std::map<int, QPDFXRefEntry> const& xref, std::map<int, QPDFXRefEntry> const& xref,
std::map<int, qpdf_offset_t> const& lengths, std::map<int, qpdf_offset_t> const& lengths,
std::map<int, int> const& obj_renumber, QPDFWriter::ObjTable const& obj,
std::shared_ptr<Buffer>& hint_buffer, std::shared_ptr<Buffer>& hint_buffer,
int& S, int& S,
int& O, int& O,
bool compressed) bool compressed)
{ {
// Populate actual hint table values // Populate actual hint table values
calculateHPageOffset(xref, lengths, obj_renumber); calculateHPageOffset(xref, lengths, obj);
calculateHSharedObject(xref, lengths, obj_renumber); calculateHSharedObject(xref, lengths, obj);
calculateHOutline(xref, lengths, obj_renumber); calculateHOutline(xref, lengths, obj);
// Write the hint stream itself into a compressed memory buffer. Write through a counter so we // Write the hint stream itself into a compressed memory buffer. Write through a counter so we
// can get offsets. // can get offsets.

View File

@ -99,7 +99,6 @@ class QPDFWriter::Members
// For linearization only // For linearization only
std::string lin_pass1_filename; std::string lin_pass1_filename;
std::map<int, int> obj_renumber_no_gen;
std::map<int, int> object_to_object_stream_no_gen; std::map<int, int> object_to_object_stream_no_gen;
// For progress reporting // For progress reporting