Commit aa2e0d23f0a09b2f1c37bd09d31147b6fb08fada

Authored by m-holger
1 parent 97d78c75

In QPDFWriter::writeLinearized use object table obj in call to getLinearizedParts

include/qpdf/QPDF.hh
@@ -739,14 +739,14 @@ class QPDF @@ -739,14 +739,14 @@ class QPDF
739 static void 739 static void
740 getLinearizedParts( 740 getLinearizedParts(
741 QPDF& qpdf, 741 QPDF& qpdf,
742 - std::map<int, int> const& object_stream_data, 742 + QPDFWriter::ObjTable const& obj,
743 std::vector<QPDFObjectHandle>& part4, 743 std::vector<QPDFObjectHandle>& part4,
744 std::vector<QPDFObjectHandle>& part6, 744 std::vector<QPDFObjectHandle>& part6,
745 std::vector<QPDFObjectHandle>& part7, 745 std::vector<QPDFObjectHandle>& part7,
746 std::vector<QPDFObjectHandle>& part8, 746 std::vector<QPDFObjectHandle>& part8,
747 std::vector<QPDFObjectHandle>& part9) 747 std::vector<QPDFObjectHandle>& part9)
748 { 748 {
749 - qpdf.getLinearizedParts(object_stream_data, part4, part6, part7, part8, part9); 749 + qpdf.getLinearizedParts(obj, part4, part6, part7, part8, part9);
750 } 750 }
751 751
752 static void 752 static void
@@ -1117,7 +1117,7 @@ class QPDF @@ -1117,7 +1117,7 @@ class QPDF
1117 // Get lists of all objects in order according to the part of a linearized file that they belong 1117 // Get lists of all objects in order according to the part of a linearized file that they belong
1118 // to. 1118 // to.
1119 void getLinearizedParts( 1119 void getLinearizedParts(
1120 - std::map<int, int> const& object_stream_data, 1120 + QPDFWriter::ObjTable const& obj,
1121 std::vector<QPDFObjectHandle>& part4, 1121 std::vector<QPDFObjectHandle>& part4,
1122 std::vector<QPDFObjectHandle>& part6, 1122 std::vector<QPDFObjectHandle>& part6,
1123 std::vector<QPDFObjectHandle>& part7, 1123 std::vector<QPDFObjectHandle>& part7,
@@ -1382,6 +1382,7 @@ class QPDF @@ -1382,6 +1382,7 @@ class QPDF
1382 qpdf_offset_t getLinearizationOffset(QPDFObjGen const&); 1382 qpdf_offset_t getLinearizationOffset(QPDFObjGen const&);
1383 QPDFObjectHandle 1383 QPDFObjectHandle
1384 getUncompressedObject(QPDFObjectHandle&, std::map<int, int> const& object_stream_data); 1384 getUncompressedObject(QPDFObjectHandle&, std::map<int, int> const& object_stream_data);
  1385 + QPDFObjectHandle getUncompressedObject(QPDFObjectHandle&, QPDFWriter::ObjTable const& obj);
1385 int lengthNextN(int first_object, int n); 1386 int lengthNextN(int first_object, int n);
1386 void 1387 void
1387 checkHPageOffset(std::vector<QPDFObjectHandle> const& pages, std::map<int, int>& idx_to_obj); 1388 checkHPageOffset(std::vector<QPDFObjectHandle> const& pages, std::map<int, int>& idx_to_obj);
@@ -1392,11 +1393,13 @@ class QPDF @@ -1392,11 +1393,13 @@ class QPDF
1392 void dumpHSharedObject(); 1393 void dumpHSharedObject();
1393 void dumpHGeneric(HGeneric&); 1394 void dumpHGeneric(HGeneric&);
1394 qpdf_offset_t adjusted_offset(qpdf_offset_t offset); 1395 qpdf_offset_t adjusted_offset(qpdf_offset_t offset);
1395 - void calculateLinearizationData(std::map<int, int> const& object_stream_data); 1396 + template <typename T>
  1397 + void calculateLinearizationData(T const& object_stream_data);
  1398 + template <typename T>
1396 void pushOutlinesToPart( 1399 void pushOutlinesToPart(
1397 std::vector<QPDFObjectHandle>& part, 1400 std::vector<QPDFObjectHandle>& part,
1398 std::set<QPDFObjGen>& lc_outlines, 1401 std::set<QPDFObjGen>& lc_outlines,
1399 - std::map<int, int> const& object_stream_data); 1402 + T const& object_stream_data);
1400 int outputLengthNextN( 1403 int outputLengthNextN(
1401 int in_object, 1404 int in_object,
1402 int n, 1405 int n,
include/qpdf/QPDFWriter.hh
@@ -611,8 +611,6 @@ class QPDFWriter @@ -611,8 +611,6 @@ class QPDFWriter
611 void pushMD5Pipeline(PipelinePopper&); 611 void pushMD5Pipeline(PipelinePopper&);
612 void computeDeterministicIDData(); 612 void computeDeterministicIDData();
613 613
614 - void discardGeneration(std::map<int, int>& out);  
615 -  
616 class Members; 614 class Members;
617 615
618 // Keep all member variables inside the Members object, which we dynamically allocate. This 616 // Keep all member variables inside the Members object, which we dynamically allocate. This
libqpdf/QPDFWriter.cc
@@ -2540,32 +2540,10 @@ QPDFWriter::calculateXrefStreamPadding(qpdf_offset_t xref_bytes) @@ -2540,32 +2540,10 @@ QPDFWriter::calculateXrefStreamPadding(qpdf_offset_t xref_bytes)
2540 } 2540 }
2541 2541
2542 void 2542 void
2543 -QPDFWriter::discardGeneration(std::map<int, int>& out)  
2544 -{  
2545 - // There are deep assumptions in the linearization code in QPDF that there is only one object  
2546 - // with each object number; i.e., you can't have two objects with the same object number and  
2547 - // different generations. This is a pretty safe assumption because Adobe Reader and Acrobat  
2548 - // can't actually handle this case. There is not much if any code in QPDF outside linearization  
2549 - // that assumes this, but the linearization code as currently implemented would do weird things  
2550 - // if we found such a case. In order to avoid breaking ABI changes in QPDF, we will first  
2551 - // assert that this condition holds. Then we can create new maps for QPDF that throw away  
2552 - // generation numbers.  
2553 -  
2554 - out.clear();  
2555 - m->obj.forEach([&out](auto id, auto const& item) -> void {  
2556 - if (item.object_stream > 0) {  
2557 - out[id] = item.object_stream;  
2558 - }  
2559 - });  
2560 -}  
2561 -  
2562 -void  
2563 QPDFWriter::writeLinearized() 2543 QPDFWriter::writeLinearized()
2564 { 2544 {
2565 // Optimize file and enqueue objects in order 2545 // Optimize file and enqueue objects in order
2566 2546
2567 - discardGeneration(m->object_to_object_stream_no_gen);  
2568 -  
2569 auto skip_stream_parameters = [this](QPDFObjectHandle& stream) { 2547 auto skip_stream_parameters = [this](QPDFObjectHandle& stream) {
2570 bool compress_stream; 2548 bool compress_stream;
2571 bool is_metadata; 2549 bool is_metadata;
@@ -2583,8 +2561,7 @@ QPDFWriter::writeLinearized() @@ -2583,8 +2561,7 @@ QPDFWriter::writeLinearized()
2583 std::vector<QPDFObjectHandle> part7; 2561 std::vector<QPDFObjectHandle> part7;
2584 std::vector<QPDFObjectHandle> part8; 2562 std::vector<QPDFObjectHandle> part8;
2585 std::vector<QPDFObjectHandle> part9; 2563 std::vector<QPDFObjectHandle> part9;
2586 - QPDF::Writer::getLinearizedParts(  
2587 - m->pdf, m->object_to_object_stream_no_gen, part4, part6, part7, part8, part9); 2564 + QPDF::Writer::getLinearizedParts(m->pdf, m->obj, part4, part6, part7, part8, part9);
2588 2565
2589 // Object number sequence: 2566 // Object number sequence:
2590 // 2567 //
libqpdf/QPDF_linearization.cc
@@ -586,6 +586,17 @@ QPDF::getUncompressedObject(QPDFObjectHandle&amp; obj, std::map&lt;int, int&gt; const&amp; obj @@ -586,6 +586,17 @@ QPDF::getUncompressedObject(QPDFObjectHandle&amp; obj, std::map&lt;int, int&gt; const&amp; obj
586 } 586 }
587 } 587 }
588 588
  589 +QPDFObjectHandle
  590 +QPDF::getUncompressedObject(QPDFObjectHandle& oh, QPDFWriter::ObjTable const& obj)
  591 +{
  592 + if (obj.contains(oh)) {
  593 + if (auto id = obj[oh].object_stream; id > 0) {
  594 + return oh.isNull() ? oh : getObject(id, 0);
  595 + }
  596 + }
  597 + return oh;
  598 +}
  599 +
589 int 600 int
590 QPDF::lengthNextN(int first_object, int n) 601 QPDF::lengthNextN(int first_object, int n)
591 { 602 {
@@ -960,8 +971,9 @@ QPDF::dumpHGeneric(HGeneric&amp; t) @@ -960,8 +971,9 @@ QPDF::dumpHGeneric(HGeneric&amp; t)
960 << "group_length: " << t.group_length << "\n"; 971 << "group_length: " << t.group_length << "\n";
961 } 972 }
962 973
  974 +template <typename T>
963 void 975 void
964 -QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data) 976 +QPDF::calculateLinearizationData(T const& object_stream_data)
965 { 977 {
966 // This function calculates the ordering of objects, divides them into the appropriate parts, 978 // This function calculates the ordering of objects, divides them into the appropriate parts,
967 // and computes some values for the linearization parameter dictionary and hint tables. The 979 // and computes some values for the linearization parameter dictionary and hint tables. The
@@ -1403,11 +1415,12 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data) @@ -1403,11 +1415,12 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1403 } 1415 }
1404 } 1416 }
1405 1417
  1418 +template <typename T>
1406 void 1419 void
1407 QPDF::pushOutlinesToPart( 1420 QPDF::pushOutlinesToPart(
1408 std::vector<QPDFObjectHandle>& part, 1421 std::vector<QPDFObjectHandle>& part,
1409 std::set<QPDFObjGen>& lc_outlines, 1422 std::set<QPDFObjGen>& lc_outlines,
1410 - std::map<int, int> const& object_stream_data) 1423 + T const& object_stream_data)
1411 { 1424 {
1412 QPDFObjectHandle root = getRoot(); 1425 QPDFObjectHandle root = getRoot();
1413 QPDFObjectHandle outlines = root.getKey("/Outlines"); 1426 QPDFObjectHandle outlines = root.getKey("/Outlines");
@@ -1434,14 +1447,14 @@ QPDF::pushOutlinesToPart( @@ -1434,14 +1447,14 @@ QPDF::pushOutlinesToPart(
1434 1447
1435 void 1448 void
1436 QPDF::getLinearizedParts( 1449 QPDF::getLinearizedParts(
1437 - std::map<int, int> const& object_stream_data, 1450 + QPDFWriter::ObjTable const& obj,
1438 std::vector<QPDFObjectHandle>& part4, 1451 std::vector<QPDFObjectHandle>& part4,
1439 std::vector<QPDFObjectHandle>& part6, 1452 std::vector<QPDFObjectHandle>& part6,
1440 std::vector<QPDFObjectHandle>& part7, 1453 std::vector<QPDFObjectHandle>& part7,
1441 std::vector<QPDFObjectHandle>& part8, 1454 std::vector<QPDFObjectHandle>& part8,
1442 std::vector<QPDFObjectHandle>& part9) 1455 std::vector<QPDFObjectHandle>& part9)
1443 { 1456 {
1444 - calculateLinearizationData(object_stream_data); 1457 + calculateLinearizationData(obj);
1445 part4 = m->part4; 1458 part4 = m->part4;
1446 part6 = m->part6; 1459 part6 = m->part6;
1447 part7 = m->part7; 1460 part7 = m->part7;
libqpdf/qpdf/QPDFWriter_private.hh
@@ -121,7 +121,6 @@ class QPDFWriter::Members @@ -121,7 +121,6 @@ class QPDFWriter::Members
121 121
122 // For linearization only 122 // For linearization only
123 std::string lin_pass1_filename; 123 std::string lin_pass1_filename;
124 - std::map<int, int> object_to_object_stream_no_gen;  
125 124
126 // For progress reporting 125 // For progress reporting
127 std::shared_ptr<QPDFWriter::ProgressReporter> progress_reporter; 126 std::shared_ptr<QPDFWriter::ProgressReporter> progress_reporter;