From 97d78c75ff04e3db7801b6e609ee4f9d2e70c3fd Mon Sep 17 00:00:00 2001 From: m-holger Date: Mon, 4 Mar 2024 11:19:45 +0000 Subject: [PATCH] In QPDFWriter::writeLinearized use object table obj in call to optimize --- include/qpdf/QPDF.hh | 18 +++++++++++ libqpdf/QPDFWriter.cc | 2 +- libqpdf/QPDF_optimization.cc | 60 ++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh index b366b17b..685e3e65 100644 --- a/include/qpdf/QPDF.hh +++ b/include/qpdf/QPDF.hh @@ -727,6 +727,15 @@ class QPDF friend class QPDFWriter; private: + static void + optimize( + QPDF& qpdf, + QPDFWriter::ObjTable const& obj, + std::function skip_stream_parameters) + { + return qpdf.optimize(obj, skip_stream_parameters); + } + static void getLinearizedParts( QPDF& qpdf, @@ -1095,6 +1104,14 @@ class QPDF // For QPDFWriter: std::map const& getXRefTableInternal(); + template + void optimize_internal( + T const& object_stream_data, + bool allow_changes = true, + std::function skip_stream_parameters = nullptr); + void optimize( + QPDFWriter::ObjTable const& obj, + std::function skip_stream_parameters); size_t tableSize(); // Get lists of all objects in order according to the part of a linearized file that they belong @@ -1413,6 +1430,7 @@ class QPDF QPDFObjGen::set& visited, bool top); void filterCompressedObjects(std::map const& object_stream_data); + void filterCompressedObjects(QPDFWriter::ObjTable const& object_stream_data); // JSON import void importJSON(std::shared_ptr, bool must_be_complete); diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc index 2ad4d786..a3fd42f3 100644 --- a/libqpdf/QPDFWriter.cc +++ b/libqpdf/QPDFWriter.cc @@ -2576,7 +2576,7 @@ QPDFWriter::writeLinearized() } }; - m->pdf.optimize(m->object_to_object_stream_no_gen, true, skip_stream_parameters); + QPDF::Writer::optimize(m->pdf, m->obj, skip_stream_parameters); std::vector part4; std::vector part6; diff --git a/libqpdf/QPDF_optimization.cc b/libqpdf/QPDF_optimization.cc index 91da7564..9f423a3a 100644 --- a/libqpdf/QPDF_optimization.cc +++ b/libqpdf/QPDF_optimization.cc @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -58,6 +59,23 @@ QPDF::optimize( std::map const& object_stream_data, bool allow_changes, std::function skip_stream_parameters) +{ + optimize_internal(object_stream_data, allow_changes, skip_stream_parameters); +} + +void +QPDF::optimize( + QPDFWriter::ObjTable const& obj, std::function skip_stream_parameters) +{ + optimize_internal(obj, true, skip_stream_parameters); +} + +template +void +QPDF::optimize_internal( + T const& object_stream_data, + bool allow_changes, + std::function skip_stream_parameters) { if (!m->obj_user_to_objects.empty()) { // already optimized @@ -379,3 +397,45 @@ QPDF::filterCompressedObjects(std::map const& object_stream_data) m->obj_user_to_objects = t_obj_user_to_objects; m->object_to_obj_users = t_object_to_obj_users; } + +void +QPDF::filterCompressedObjects(QPDFWriter::ObjTable const& obj) +{ + if (obj.getStreamsEmpty()) { + return; + } + + // Transform object_to_obj_users and obj_user_to_objects so that they refer only to uncompressed + // objects. If something is a user of a compressed object, then it is really a user of the + // object stream that contains it. + + std::map> t_obj_user_to_objects; + std::map> t_object_to_obj_users; + + for (auto const& i1: m->obj_user_to_objects) { + ObjUser const& ou = i1.first; + // Loop over objects. + for (auto const& og: i1.second) { + if (auto const& i2 = obj[og].object_stream; i2 <= 0) { + t_obj_user_to_objects[ou].insert(og); + } else { + t_obj_user_to_objects[ou].insert(QPDFObjGen(i2, 0)); + } + } + } + + for (auto const& i1: m->object_to_obj_users) { + QPDFObjGen const& og = i1.first; + // Loop over obj_users. + for (auto const& ou: i1.second) { + if (auto i2 = obj[og].object_stream; i2 <= 0) { + t_object_to_obj_users[og].insert(ou); + } else { + t_object_to_obj_users[QPDFObjGen(i2, 0)].insert(ou); + } + } + } + + m->obj_user_to_objects = t_obj_user_to_objects; + m->object_to_obj_users = t_object_to_obj_users; +}