Commit 98c14e7740cb879be05ce95a22a3c1f2c403bea0
1 parent
7775aec3
Refactor QPDF::checkLinearizationInternal
Showing
3 changed files
with
64 additions
and
12 deletions
include/qpdf/QPDF.hh
| @@ -836,6 +836,7 @@ class QPDF | @@ -836,6 +836,7 @@ class QPDF | ||
| 836 | void optimize( | 836 | void optimize( |
| 837 | QPDFWriter::ObjTable const& obj, | 837 | QPDFWriter::ObjTable const& obj, |
| 838 | std::function<int(QPDFObjectHandle&)> skip_stream_parameters); | 838 | std::function<int(QPDFObjectHandle&)> skip_stream_parameters); |
| 839 | + void optimize(Xref_table const& obj); | ||
| 839 | size_t tableSize(); | 840 | size_t tableSize(); |
| 840 | 841 | ||
| 841 | // Get lists of all objects in order according to the part of a linearized file that they belong | 842 | // Get lists of all objects in order according to the part of a linearized file that they belong |
| @@ -935,6 +936,7 @@ class QPDF | @@ -935,6 +936,7 @@ class QPDF | ||
| 935 | QPDFObjectHandle | 936 | QPDFObjectHandle |
| 936 | getUncompressedObject(QPDFObjectHandle&, std::map<int, int> const& object_stream_data); | 937 | getUncompressedObject(QPDFObjectHandle&, std::map<int, int> const& object_stream_data); |
| 937 | QPDFObjectHandle getUncompressedObject(QPDFObjectHandle&, QPDFWriter::ObjTable const& obj); | 938 | QPDFObjectHandle getUncompressedObject(QPDFObjectHandle&, QPDFWriter::ObjTable const& obj); |
| 939 | + QPDFObjectHandle getUncompressedObject(QPDFObjectHandle&, Xref_table const& obj); | ||
| 938 | int lengthNextN(int first_object, int n); | 940 | int lengthNextN(int first_object, int n); |
| 939 | void | 941 | void |
| 940 | checkHPageOffset(std::vector<QPDFObjectHandle> const& pages, std::map<int, int>& idx_to_obj); | 942 | checkHPageOffset(std::vector<QPDFObjectHandle> const& pages, std::map<int, int>& idx_to_obj); |
| @@ -980,6 +982,7 @@ class QPDF | @@ -980,6 +982,7 @@ class QPDF | ||
| 980 | std::function<int(QPDFObjectHandle&)> skip_stream_parameters); | 982 | std::function<int(QPDFObjectHandle&)> skip_stream_parameters); |
| 981 | void filterCompressedObjects(std::map<int, int> const& object_stream_data); | 983 | void filterCompressedObjects(std::map<int, int> const& object_stream_data); |
| 982 | void filterCompressedObjects(QPDFWriter::ObjTable const& object_stream_data); | 984 | void filterCompressedObjects(QPDFWriter::ObjTable const& object_stream_data); |
| 985 | + void filterCompressedObjects(Xref_table const& object_stream_data); | ||
| 983 | 986 | ||
| 984 | // JSON import | 987 | // JSON import |
| 985 | void importJSON(std::shared_ptr<InputSource>, bool must_be_complete); | 988 | void importJSON(std::shared_ptr<InputSource>, bool must_be_complete); |
libqpdf/QPDF_linearization.cc
| @@ -484,18 +484,9 @@ QPDF::checkLinearizationInternal() | @@ -484,18 +484,9 @@ QPDF::checkLinearizationInternal() | ||
| 484 | // Further checking requires optimization and order calculation. Don't allow optimization to | 484 | // Further checking requires optimization and order calculation. Don't allow optimization to |
| 485 | // make changes. If it has to, then the file is not properly linearized. We use the xref table | 485 | // make changes. If it has to, then the file is not properly linearized. We use the xref table |
| 486 | // to figure out which objects are compressed and which are uncompressed. | 486 | // to figure out which objects are compressed and which are uncompressed. |
| 487 | - { // local scope | ||
| 488 | - std::map<int, int> object_stream_data; | ||
| 489 | - for (auto const& iter: m->xref_table.as_map()) { | ||
| 490 | - QPDFObjGen const& og = iter.first; | ||
| 491 | - QPDFXRefEntry const& entry = iter.second; | ||
| 492 | - if (entry.getType() == 2) { | ||
| 493 | - object_stream_data[og.getObj()] = entry.getObjStreamNumber(); | ||
| 494 | - } | ||
| 495 | - } | ||
| 496 | - optimize(object_stream_data, false); | ||
| 497 | - calculateLinearizationData(object_stream_data); | ||
| 498 | - } | 487 | + |
| 488 | + optimize(m->xref_table); | ||
| 489 | + calculateLinearizationData(m->xref_table); | ||
| 499 | 490 | ||
| 500 | // E: offset of end of first page -- Implementation note 123 says Acrobat includes on extra | 491 | // E: offset of end of first page -- Implementation note 123 says Acrobat includes on extra |
| 501 | // object here by mistake. pdlin fails to place thumbnail images in section 9, so when | 492 | // object here by mistake. pdlin fails to place thumbnail images in section 9, so when |
| @@ -582,6 +573,16 @@ QPDF::getUncompressedObject(QPDFObjectHandle& obj, std::map<int, int> const& obj | @@ -582,6 +573,16 @@ QPDF::getUncompressedObject(QPDFObjectHandle& obj, std::map<int, int> const& obj | ||
| 582 | } | 573 | } |
| 583 | 574 | ||
| 584 | QPDFObjectHandle | 575 | QPDFObjectHandle |
| 576 | +QPDF::getUncompressedObject(QPDFObjectHandle& obj, Xref_table const& xref) | ||
| 577 | +{ | ||
| 578 | + auto og = obj.getObjGen(); | ||
| 579 | + if (obj.isNull() || xref.type(og) != 2) { | ||
| 580 | + return obj; | ||
| 581 | + } | ||
| 582 | + return getObject(xref.stream_number(og.getObj()), 0); | ||
| 583 | +} | ||
| 584 | + | ||
| 585 | +QPDFObjectHandle | ||
| 585 | QPDF::getUncompressedObject(QPDFObjectHandle& oh, QPDFWriter::ObjTable const& obj) | 586 | QPDF::getUncompressedObject(QPDFObjectHandle& oh, QPDFWriter::ObjTable const& obj) |
| 586 | { | 587 | { |
| 587 | if (obj.contains(oh)) { | 588 | if (obj.contains(oh)) { |
libqpdf/QPDF_optimization.cc
| @@ -78,6 +78,12 @@ QPDF::optimize( | @@ -78,6 +78,12 @@ QPDF::optimize( | ||
| 78 | optimize_internal(obj, true, skip_stream_parameters); | 78 | optimize_internal(obj, true, skip_stream_parameters); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | +void | ||
| 82 | +QPDF::optimize(QPDF::Xref_table const& xref) | ||
| 83 | +{ | ||
| 84 | + optimize_internal(xref, false, nullptr); | ||
| 85 | +} | ||
| 86 | + | ||
| 81 | template <typename T> | 87 | template <typename T> |
| 82 | void | 88 | void |
| 83 | QPDF::optimize_internal( | 89 | QPDF::optimize_internal( |
| @@ -442,3 +448,45 @@ QPDF::filterCompressedObjects(QPDFWriter::ObjTable const& obj) | @@ -442,3 +448,45 @@ QPDF::filterCompressedObjects(QPDFWriter::ObjTable const& obj) | ||
| 442 | m->obj_user_to_objects = t_obj_user_to_objects; | 448 | m->obj_user_to_objects = t_obj_user_to_objects; |
| 443 | m->object_to_obj_users = t_object_to_obj_users; | 449 | m->object_to_obj_users = t_object_to_obj_users; |
| 444 | } | 450 | } |
| 451 | + | ||
| 452 | +void | ||
| 453 | +QPDF::filterCompressedObjects(QPDF::Xref_table const& xref) | ||
| 454 | +{ | ||
| 455 | + if (!xref.object_streams()) { | ||
| 456 | + return; | ||
| 457 | + } | ||
| 458 | + | ||
| 459 | + // Transform object_to_obj_users and obj_user_to_objects so that they refer only to uncompressed | ||
| 460 | + // objects. If something is a user of a compressed object, then it is really a user of the | ||
| 461 | + // object stream that contains it. | ||
| 462 | + | ||
| 463 | + std::map<ObjUser, std::set<QPDFObjGen>> t_obj_user_to_objects; | ||
| 464 | + std::map<QPDFObjGen, std::set<ObjUser>> t_object_to_obj_users; | ||
| 465 | + | ||
| 466 | + for (auto const& i1: m->obj_user_to_objects) { | ||
| 467 | + ObjUser const& ou = i1.first; | ||
| 468 | + // Loop over objects. | ||
| 469 | + for (auto const& og: i1.second) { | ||
| 470 | + if (auto stream = xref.stream_number(og.getObj())) { | ||
| 471 | + t_obj_user_to_objects[ou].insert(QPDFObjGen(stream, 0)); | ||
| 472 | + } else { | ||
| 473 | + t_obj_user_to_objects[ou].insert(og); | ||
| 474 | + } | ||
| 475 | + } | ||
| 476 | + } | ||
| 477 | + | ||
| 478 | + for (auto const& i1: m->object_to_obj_users) { | ||
| 479 | + QPDFObjGen const& og = i1.first; | ||
| 480 | + // Loop over obj_users. | ||
| 481 | + for (auto const& ou: i1.second) { | ||
| 482 | + if (auto stream = xref.stream_number(og.getObj())) { | ||
| 483 | + t_object_to_obj_users[QPDFObjGen(stream, 0)].insert(ou); | ||
| 484 | + } else { | ||
| 485 | + t_object_to_obj_users[og].insert(ou); | ||
| 486 | + } | ||
| 487 | + } | ||
| 488 | + } | ||
| 489 | + | ||
| 490 | + m->obj_user_to_objects = t_obj_user_to_objects; | ||
| 491 | + m->object_to_obj_users = t_object_to_obj_users; | ||
| 492 | +} |