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