mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 10:58:58 +00:00
In QPDFWriter replace map xref with new ObjTable new_obj
This commit is contained in:
parent
47cf4e3a50
commit
ccad589f7d
@ -743,7 +743,7 @@ class QPDF
|
||||
static void
|
||||
generateHintStream(
|
||||
QPDF& qpdf,
|
||||
std::map<int, QPDFXRefEntry> const& xref,
|
||||
QPDFWriter::NewObjTable const& new_obj,
|
||||
std::map<int, qpdf_offset_t> const& lengths,
|
||||
QPDFWriter::ObjTable const& obj,
|
||||
std::shared_ptr<Buffer>& hint_stream,
|
||||
@ -751,7 +751,7 @@ class QPDF
|
||||
int& O,
|
||||
bool compressed)
|
||||
{
|
||||
return qpdf.generateHintStream(xref, lengths, obj, hint_stream, S, O, compressed);
|
||||
return qpdf.generateHintStream(new_obj, lengths, obj, hint_stream, S, O, compressed);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1102,7 +1102,7 @@ class QPDF
|
||||
std::vector<QPDFObjectHandle>& part9);
|
||||
|
||||
void generateHintStream(
|
||||
std::map<int, QPDFXRefEntry> const& xref,
|
||||
QPDFWriter::NewObjTable const& new_obj,
|
||||
std::map<int, qpdf_offset_t> const& lengths,
|
||||
QPDFWriter::ObjTable const& obj,
|
||||
std::shared_ptr<Buffer>& hint_stream,
|
||||
@ -1381,15 +1381,15 @@ class QPDF
|
||||
std::map<int, qpdf_offset_t> const& lengths,
|
||||
QPDFWriter::ObjTable const& obj);
|
||||
void calculateHPageOffset(
|
||||
std::map<int, QPDFXRefEntry> const& xref,
|
||||
QPDFWriter::NewObjTable const& new_obj,
|
||||
std::map<int, qpdf_offset_t> const& lengths,
|
||||
QPDFWriter::ObjTable const& obj);
|
||||
void calculateHSharedObject(
|
||||
std::map<int, QPDFXRefEntry> const& xref,
|
||||
QPDFWriter::NewObjTable const& new_obj,
|
||||
std::map<int, qpdf_offset_t> const& lengths,
|
||||
QPDFWriter::ObjTable const& obj);
|
||||
void calculateHOutline(
|
||||
std::map<int, QPDFXRefEntry> const& xref,
|
||||
QPDFWriter::NewObjTable const& new_obj,
|
||||
std::map<int, qpdf_offset_t> const& lengths,
|
||||
QPDFWriter::ObjTable const& obj);
|
||||
void writeHPageOffset(BitWriter&);
|
||||
|
@ -439,7 +439,9 @@ class QPDFWriter
|
||||
|
||||
// The following structs / classes are not part of the public API.
|
||||
struct Object;
|
||||
struct NewObject;
|
||||
class ObjTable;
|
||||
class NewObjTable;
|
||||
|
||||
private:
|
||||
// flags used by unparseObject
|
||||
|
@ -1038,7 +1038,7 @@ QPDFWriter::openObject(int objid)
|
||||
if (objid == 0) {
|
||||
objid = m->next_objid++;
|
||||
}
|
||||
m->xref[objid] = QPDFXRefEntry(m->pipeline->getCount());
|
||||
m->new_obj[objid].xref = QPDFXRefEntry(m->pipeline->getCount());
|
||||
writeString(std::to_string(objid));
|
||||
writeString(" 0 obj\n");
|
||||
return objid;
|
||||
@ -1050,7 +1050,7 @@ 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->xref[objid].getOffset();
|
||||
m->lengths[objid] = m->pipeline->getCount() - m->new_obj[objid].xref.getOffset();
|
||||
}
|
||||
|
||||
void
|
||||
@ -1703,7 +1703,7 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object)
|
||||
}
|
||||
writeObject(obj_to_write, count);
|
||||
|
||||
m->xref[new_obj] = QPDFXRefEntry(new_stream_id, count);
|
||||
m->new_obj[new_obj].xref = QPDFXRefEntry(new_stream_id, count);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1978,8 +1978,6 @@ QPDFWriter::generateObjectStreams()
|
||||
std::vector<QPDFObjGen> eligible = QPDF::Writer::getCompressibleObjGens(m->pdf);
|
||||
size_t n_object_streams = (eligible.size() + 99U) / 100U;
|
||||
|
||||
// Initialize object table for all existing objects plus some headroom for objects created
|
||||
// during writing.
|
||||
initializeTables(2U * n_object_streams);
|
||||
if (n_object_streams == 0) {
|
||||
m->obj.streams_empty = true;
|
||||
@ -2065,6 +2063,7 @@ QPDFWriter::initializeTables(size_t extra)
|
||||
{
|
||||
auto size = QIntC::to_size(QPDF::Writer::tableSize(m->pdf) + 100) + extra;
|
||||
m->obj.initialize(size);
|
||||
m->new_obj.initialize(size);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2136,8 +2135,6 @@ QPDFWriter::doWriteSetup()
|
||||
|
||||
switch (m->object_stream_mode) {
|
||||
case qpdf_o_disable:
|
||||
// Initialize object table for all existing objects plus some headroom for objects created
|
||||
// during writing.
|
||||
initializeTables();
|
||||
m->obj.streams_empty = true;
|
||||
break;
|
||||
@ -2245,12 +2242,12 @@ QPDFWriter::getWrittenXRefTable()
|
||||
{
|
||||
std::map<QPDFObjGen, QPDFXRefEntry> result;
|
||||
|
||||
for (auto const& iter: m->xref) {
|
||||
if (iter.first != 0 && iter.second.getType() != 0) {
|
||||
result[QPDFObjGen(iter.first, 0)] = iter.second;
|
||||
auto it = result.begin();
|
||||
m->new_obj.forEach([&it, &result](auto id, auto const& item) -> void {
|
||||
if (item.xref.getType() != 0) {
|
||||
it = result.emplace_hint(it, QPDFObjGen(id, 0), item.xref);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -2313,7 +2310,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, hint_buffer, S, O, compressed);
|
||||
m->pdf, m->new_obj, m->lengths, m->obj, hint_buffer, S, O, compressed);
|
||||
|
||||
openObject(hint_id);
|
||||
setDataKey(hint_id);
|
||||
@ -2386,7 +2383,7 @@ QPDFWriter::writeXRefTable(
|
||||
} else {
|
||||
qpdf_offset_t offset = 0;
|
||||
if (!suppress_offsets) {
|
||||
offset = m->xref[i].getOffset();
|
||||
offset = m->new_obj[i].xref.getOffset();
|
||||
if ((hint_id != 0) && (i != hint_id) && (offset >= hint_offset)) {
|
||||
offset += hint_length;
|
||||
}
|
||||
@ -2439,7 +2436,7 @@ QPDFWriter::writeXRefStream(
|
||||
|
||||
// Must store in xref table in advance of writing the actual data rather than waiting for
|
||||
// openObject to do it.
|
||||
m->xref[xref_id] = QPDFXRefEntry(m->pipeline->getCount());
|
||||
m->new_obj[xref_id].xref = QPDFXRefEntry(m->pipeline->getCount());
|
||||
|
||||
Pipeline* p = pushPipeline(new Pl_Buffer("xref stream"));
|
||||
bool compressed = false;
|
||||
@ -2457,7 +2454,7 @@ QPDFWriter::writeXRefStream(
|
||||
PipelinePopper pp_xref(this, &xref_data);
|
||||
activatePipelineStack(pp_xref);
|
||||
for (int i = first; i <= last; ++i) {
|
||||
QPDFXRefEntry& e = m->xref[i];
|
||||
QPDFXRefEntry& e = m->new_obj[i].xref;
|
||||
switch (e.getType()) {
|
||||
case 0:
|
||||
writeBinary(0, 1);
|
||||
@ -2712,7 +2709,7 @@ QPDFWriter::writeLinearized()
|
||||
writeString(std::to_string(file_size + hint_length));
|
||||
// Implementation note 121 states that a space is mandatory after this open bracket.
|
||||
writeString(" /H [ ");
|
||||
writeString(std::to_string(m->xref[hint_id].getOffset()));
|
||||
writeString(std::to_string(m->new_obj[hint_id].xref.getOffset()));
|
||||
writeString(" ");
|
||||
writeString(std::to_string(hint_length));
|
||||
writeString(" ] /O ");
|
||||
@ -2739,7 +2736,7 @@ QPDFWriter::writeLinearized()
|
||||
qpdf_offset_t first_xref_offset = m->pipeline->getCount();
|
||||
qpdf_offset_t hint_offset = 0;
|
||||
if (pass == 2) {
|
||||
hint_offset = m->xref[hint_id].getOffset();
|
||||
hint_offset = m->new_obj[hint_id].xref.getOffset();
|
||||
}
|
||||
if (need_xref_stream) {
|
||||
// Must pad here too.
|
||||
@ -2810,7 +2807,7 @@ QPDFWriter::writeLinearized()
|
||||
writeEncryptionDictionary();
|
||||
}
|
||||
if (pass == 1) {
|
||||
m->xref[hint_id] = QPDFXRefEntry(m->pipeline->getCount());
|
||||
m->new_obj[hint_id].xref = QPDFXRefEntry(m->pipeline->getCount());
|
||||
} else {
|
||||
// Part 5: hint stream
|
||||
writeBuffer(hint_buffer);
|
||||
@ -2883,7 +2880,7 @@ QPDFWriter::writeLinearized()
|
||||
pp_pass1 = nullptr;
|
||||
|
||||
// Save hint offset since it will be set to zero by calling openObject.
|
||||
qpdf_offset_t hint_offset1 = m->xref[hint_id].getOffset();
|
||||
qpdf_offset_t hint_offset1 = m->new_obj[hint_id].xref.getOffset();
|
||||
|
||||
// Write hint stream to a buffer
|
||||
{
|
||||
@ -2895,7 +2892,7 @@ QPDFWriter::writeLinearized()
|
||||
hint_length = QIntC::to_offset(hint_buffer->getSize());
|
||||
|
||||
// Restore hint offset
|
||||
m->xref[hint_id] = QPDFXRefEntry(hint_offset1);
|
||||
m->new_obj[hint_id].xref = QPDFXRefEntry(hint_offset1);
|
||||
if (lin_pass1_file) {
|
||||
// Write some debugging information
|
||||
fprintf(
|
||||
|
@ -1481,7 +1481,7 @@ QPDF::outputLengthNextN(
|
||||
|
||||
void
|
||||
QPDF::calculateHPageOffset(
|
||||
std::map<int, QPDFXRefEntry> const& xref,
|
||||
QPDFWriter::NewObjTable const& new_obj,
|
||||
std::map<int, qpdf_offset_t> const& lengths,
|
||||
QPDFWriter::ObjTable const& obj)
|
||||
{
|
||||
@ -1530,8 +1530,7 @@ QPDF::calculateHPageOffset(
|
||||
}
|
||||
|
||||
ph.min_nobjects = min_nobjects;
|
||||
int out_page0_id = obj[pages.at(0)].renumber;
|
||||
ph.first_page_offset = (*(xref.find(out_page0_id))).second.getOffset();
|
||||
ph.first_page_offset = new_obj[obj[pages.at(0)].renumber].xref.getOffset();
|
||||
ph.nbits_delta_nobjects = nbits(max_nobjects - min_nobjects);
|
||||
ph.min_page_length = min_length;
|
||||
ph.nbits_delta_page_length = nbits(max_length - min_length);
|
||||
@ -1566,7 +1565,7 @@ QPDF::calculateHPageOffset(
|
||||
|
||||
void
|
||||
QPDF::calculateHSharedObject(
|
||||
std::map<int, QPDFXRefEntry> const& xref,
|
||||
QPDFWriter::NewObjTable const& new_obj,
|
||||
std::map<int, qpdf_offset_t> const& lengths,
|
||||
QPDFWriter::ObjTable const& obj)
|
||||
{
|
||||
@ -1595,7 +1594,8 @@ QPDF::calculateHSharedObject(
|
||||
so.nshared_first_page = cso.nshared_first_page;
|
||||
if (so.nshared_total > so.nshared_first_page) {
|
||||
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;
|
||||
so.first_shared_offset = new_obj[so.first_shared_obj].xref.getOffset();
|
||||
}
|
||||
so.min_group_length = min_length;
|
||||
so.nbits_delta_group_length = nbits(max_length - min_length);
|
||||
@ -1611,7 +1611,7 @@ QPDF::calculateHSharedObject(
|
||||
|
||||
void
|
||||
QPDF::calculateHOutline(
|
||||
std::map<int, QPDFXRefEntry> const& xref,
|
||||
QPDFWriter::NewObjTable const& new_obj,
|
||||
std::map<int, qpdf_offset_t> const& lengths,
|
||||
QPDFWriter::ObjTable const& obj)
|
||||
{
|
||||
@ -1624,7 +1624,7 @@ QPDF::calculateHOutline(
|
||||
HGeneric& ho = m->outline_hints;
|
||||
|
||||
ho.first_object = obj[cho.first_object].renumber;
|
||||
ho.first_object_offset = (*(xref.find(ho.first_object))).second.getOffset();
|
||||
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);
|
||||
}
|
||||
@ -1755,7 +1755,7 @@ QPDF::writeHGeneric(BitWriter& w, HGeneric& t)
|
||||
|
||||
void
|
||||
QPDF::generateHintStream(
|
||||
std::map<int, QPDFXRefEntry> const& xref,
|
||||
QPDFWriter::NewObjTable const& new_obj,
|
||||
std::map<int, qpdf_offset_t> const& lengths,
|
||||
QPDFWriter::ObjTable const& obj,
|
||||
std::shared_ptr<Buffer>& hint_buffer,
|
||||
@ -1764,9 +1764,9 @@ QPDF::generateHintStream(
|
||||
bool compressed)
|
||||
{
|
||||
// Populate actual hint table values
|
||||
calculateHPageOffset(xref, lengths, obj);
|
||||
calculateHSharedObject(xref, lengths, obj);
|
||||
calculateHOutline(xref, lengths, obj);
|
||||
calculateHPageOffset(new_obj, lengths, obj);
|
||||
calculateHSharedObject(new_obj, lengths, obj);
|
||||
calculateHOutline(new_obj, lengths, obj);
|
||||
|
||||
// Write the hint stream itself into a compressed memory buffer. Write through a counter so we
|
||||
// can get offsets.
|
||||
|
@ -15,6 +15,11 @@ struct QPDFWriter::Object
|
||||
int object_stream{0};
|
||||
};
|
||||
|
||||
struct QPDFWriter::NewObject
|
||||
{
|
||||
QPDFXRefEntry xref;
|
||||
};
|
||||
|
||||
class QPDFWriter::ObjTable: public ::ObjTable<QPDFWriter::Object>
|
||||
{
|
||||
friend class QPDFWriter;
|
||||
@ -31,6 +36,11 @@ class QPDFWriter::ObjTable: public ::ObjTable<QPDFWriter::Object>
|
||||
bool streams_empty{false};
|
||||
};
|
||||
|
||||
class QPDFWriter::NewObjTable: public ::ObjTable<QPDFWriter::NewObject>
|
||||
{
|
||||
friend class QPDFWriter;
|
||||
};
|
||||
|
||||
class QPDFWriter::Members
|
||||
{
|
||||
friend class QPDFWriter;
|
||||
@ -91,7 +101,7 @@ class QPDFWriter::Members
|
||||
std::vector<QPDFObjectHandle> object_queue;
|
||||
size_t object_queue_front{0};
|
||||
QPDFWriter::ObjTable obj;
|
||||
std::map<int, QPDFXRefEntry> xref;
|
||||
QPDFWriter::NewObjTable new_obj;
|
||||
std::map<int, qpdf_offset_t> lengths;
|
||||
int next_objid{1};
|
||||
int cur_stream_length_id{0};
|
||||
|
Loading…
Reference in New Issue
Block a user