Commit 84e25919cb9e3303670d23320dcc4071759a9634

Authored by m-holger
1 parent 8791b5f8

In QPDFWriter replace map obj_renumber_no_gen with ObjTable obj

include/qpdf/QPDF.hh
@@ -41,6 +41,7 @@ @@ -41,6 +41,7 @@
41 #include <qpdf/QPDFObjectHandle.hh> 41 #include <qpdf/QPDFObjectHandle.hh>
42 #include <qpdf/QPDFStreamFilter.hh> 42 #include <qpdf/QPDFStreamFilter.hh>
43 #include <qpdf/QPDFTokenizer.hh> 43 #include <qpdf/QPDFTokenizer.hh>
  44 +#include <qpdf/QPDFWriter.hh>
44 #include <qpdf/QPDFXRefEntry.hh> 45 #include <qpdf/QPDFXRefEntry.hh>
45 46
46 class QPDF_Stream; 47 class QPDF_Stream;
@@ -744,14 +745,13 @@ class QPDF @@ -744,14 +745,13 @@ class QPDF
744 QPDF& qpdf, 745 QPDF& qpdf,
745 std::map<int, QPDFXRefEntry> const& xref, 746 std::map<int, QPDFXRefEntry> const& xref,
746 std::map<int, qpdf_offset_t> const& lengths, 747 std::map<int, qpdf_offset_t> const& lengths,
747 - std::map<int, int> const& obj_renumber, 748 + QPDFWriter::ObjTable const& obj,
748 std::shared_ptr<Buffer>& hint_stream, 749 std::shared_ptr<Buffer>& hint_stream,
749 int& S, 750 int& S,
750 int& O, 751 int& O,
751 bool compressed) 752 bool compressed)
752 { 753 {
753 - return qpdf.generateHintStream(  
754 - xref, lengths, obj_renumber, hint_stream, S, O, compressed); 754 + return qpdf.generateHintStream(xref, lengths, obj, hint_stream, S, O, compressed);
755 } 755 }
756 756
757 static void 757 static void
@@ -1104,7 +1104,7 @@ class QPDF @@ -1104,7 +1104,7 @@ class QPDF
1104 void generateHintStream( 1104 void generateHintStream(
1105 std::map<int, QPDFXRefEntry> const& xref, 1105 std::map<int, QPDFXRefEntry> const& xref,
1106 std::map<int, qpdf_offset_t> const& lengths, 1106 std::map<int, qpdf_offset_t> const& lengths,
1107 - std::map<int, int> const& obj_renumber, 1107 + QPDFWriter::ObjTable const& obj,
1108 std::shared_ptr<Buffer>& hint_stream, 1108 std::shared_ptr<Buffer>& hint_stream,
1109 int& S, 1109 int& S,
1110 int& O, 1110 int& O,
@@ -1379,19 +1379,19 @@ class QPDF @@ -1379,19 +1379,19 @@ class QPDF
1379 int in_object, 1379 int in_object,
1380 int n, 1380 int n,
1381 std::map<int, qpdf_offset_t> const& lengths, 1381 std::map<int, qpdf_offset_t> const& lengths,
1382 - std::map<int, int> const& obj_renumber); 1382 + QPDFWriter::ObjTable const& obj);
1383 void calculateHPageOffset( 1383 void calculateHPageOffset(
1384 std::map<int, QPDFXRefEntry> const& xref, 1384 std::map<int, QPDFXRefEntry> const& xref,
1385 std::map<int, qpdf_offset_t> const& lengths, 1385 std::map<int, qpdf_offset_t> const& lengths,
1386 - std::map<int, int> const& obj_renumber); 1386 + QPDFWriter::ObjTable const& obj);
1387 void calculateHSharedObject( 1387 void calculateHSharedObject(
1388 std::map<int, QPDFXRefEntry> const& xref, 1388 std::map<int, QPDFXRefEntry> const& xref,
1389 std::map<int, qpdf_offset_t> const& lengths, 1389 std::map<int, qpdf_offset_t> const& lengths,
1390 - std::map<int, int> const& obj_renumber); 1390 + QPDFWriter::ObjTable const& obj);
1391 void calculateHOutline( 1391 void calculateHOutline(
1392 std::map<int, QPDFXRefEntry> const& xref, 1392 std::map<int, QPDFXRefEntry> const& xref,
1393 std::map<int, qpdf_offset_t> const& lengths, 1393 std::map<int, qpdf_offset_t> const& lengths,
1394 - std::map<int, int> const& obj_renumber); 1394 + QPDFWriter::ObjTable const& obj);
1395 void writeHPageOffset(BitWriter&); 1395 void writeHPageOffset(BitWriter&);
1396 void writeHSharedObject(BitWriter&); 1396 void writeHSharedObject(BitWriter&);
1397 void writeHGeneric(BitWriter&, HGeneric&); 1397 void writeHGeneric(BitWriter&, HGeneric&);
include/qpdf/QPDFWriter.hh
@@ -610,7 +610,6 @@ class QPDFWriter @@ -610,7 +610,6 @@ class QPDFWriter
610 void computeDeterministicIDData(); 610 void computeDeterministicIDData();
611 611
612 void discardGeneration(std::map<QPDFObjGen, int> const& in, std::map<int, int>& out); 612 void discardGeneration(std::map<QPDFObjGen, int> const& in, std::map<int, int>& out);
613 - void discardGeneration(std::map<int, int>& out);  
614 613
615 class Members; 614 class Members;
616 615
libqpdf/QPDFWriter.cc
@@ -2303,7 +2303,7 @@ QPDFWriter::writeHintStream(int hint_id) @@ -2303,7 +2303,7 @@ QPDFWriter::writeHintStream(int hint_id)
2303 int O = 0; 2303 int O = 0;
2304 bool compressed = (m->compress_streams && !m->qdf_mode); 2304 bool compressed = (m->compress_streams && !m->qdf_mode);
2305 QPDF::Writer::generateHintStream( 2305 QPDF::Writer::generateHintStream(
2306 - m->pdf, m->xref, m->lengths, m->obj_renumber_no_gen, hint_buffer, S, O, compressed); 2306 + m->pdf, m->xref, m->lengths, m->obj, hint_buffer, S, O, compressed);
2307 2307
2308 openObject(hint_id); 2308 openObject(hint_id);
2309 setDataKey(hint_id); 2309 setDataKey(hint_id);
@@ -2546,26 +2546,6 @@ QPDFWriter::discardGeneration(std::map&lt;QPDFObjGen, int&gt; const&amp; in, std::map&lt;int, @@ -2546,26 +2546,6 @@ QPDFWriter::discardGeneration(std::map&lt;QPDFObjGen, int&gt; const&amp; in, std::map&lt;int,
2546 } 2546 }
2547 2547
2548 void 2548 void
2549 -QPDFWriter::discardGeneration(std::map<int, int>& out)  
2550 -{  
2551 - // There are deep assumptions in the linearization code in QPDF that there is only one object  
2552 - // with each object number; i.e., you can't have two objects with the same object number and  
2553 - // different generations. This is a pretty safe assumption because Adobe Reader and Acrobat  
2554 - // can't actually handle this case. There is not much if any code in QPDF outside linearization  
2555 - // that assumes this, but the linearization code as currently implemented would do weird things  
2556 - // if we found such a case. In order to avoid breaking ABI changes in QPDF, we will first  
2557 - // assert that this condition holds. Then we can create new maps for QPDF that throw away  
2558 - // generation numbers.  
2559 -  
2560 - out.clear();  
2561 - m->obj.forEach([&out](auto id, auto const& item) -> void {  
2562 - if (item.renumber > 0) {  
2563 - out[id] = item.renumber;  
2564 - }  
2565 - });  
2566 -}  
2567 -  
2568 -void  
2569 QPDFWriter::writeLinearized() 2549 QPDFWriter::writeLinearized()
2570 { 2550 {
2571 // Optimize file and enqueue objects in order 2551 // Optimize file and enqueue objects in order
@@ -2887,8 +2867,6 @@ QPDFWriter::writeLinearized() @@ -2887,8 +2867,6 @@ QPDFWriter::writeLinearized()
2887 writeString(std::to_string(first_xref_offset)); 2867 writeString(std::to_string(first_xref_offset));
2888 writeString("\n%%EOF\n"); 2868 writeString("\n%%EOF\n");
2889 2869
2890 - discardGeneration(m->obj_renumber_no_gen);  
2891 -  
2892 if (pass == 1) { 2870 if (pass == 1) {
2893 if (m->deterministic_id) { 2871 if (m->deterministic_id) {
2894 QTC::TC("qpdf", "QPDFWriter linearized deterministic ID", need_xref_stream ? 0 : 1); 2872 QTC::TC("qpdf", "QPDFWriter linearized deterministic ID", need_xref_stream ? 0 : 1);
libqpdf/QPDF_linearization.cc
@@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
9 #include <qpdf/Pl_Flate.hh> 9 #include <qpdf/Pl_Flate.hh>
10 #include <qpdf/QPDFExc.hh> 10 #include <qpdf/QPDFExc.hh>
11 #include <qpdf/QPDFLogger.hh> 11 #include <qpdf/QPDFLogger.hh>
  12 +#include <qpdf/QPDFWriter_private.hh>
12 #include <qpdf/QTC.hh> 13 #include <qpdf/QTC.hh>
13 #include <qpdf/QUtil.hh> 14 #include <qpdf/QUtil.hh>
14 15
@@ -1459,15 +1460,15 @@ QPDF::outputLengthNextN( @@ -1459,15 +1460,15 @@ QPDF::outputLengthNextN(
1459 int in_object, 1460 int in_object,
1460 int n, 1461 int n,
1461 std::map<int, qpdf_offset_t> const& lengths, 1462 std::map<int, qpdf_offset_t> const& lengths,
1462 - std::map<int, int> const& obj_renumber) 1463 + QPDFWriter::ObjTable const& obj)
1463 { 1464 {
1464 // Figure out the length of a series of n consecutive objects in the output file starting with 1465 // Figure out the length of a series of n consecutive objects in the output file starting with
1465 // whatever object in_object from the input file mapped to. 1466 // whatever object in_object from the input file mapped to.
1466 1467
1467 - if (obj_renumber.count(in_object) == 0) { 1468 + int first = obj[in_object].renumber;
  1469 + if (first <= 0) {
1468 stopOnError("found object that is not renumbered while writing linearization data"); 1470 stopOnError("found object that is not renumbered while writing linearization data");
1469 } 1471 }
1470 - int first = (*(obj_renumber.find(in_object))).second;  
1471 int length = 0; 1472 int length = 0;
1472 for (int i = 0; i < n; ++i) { 1473 for (int i = 0; i < n; ++i) {
1473 if (lengths.count(first + i) == 0) { 1474 if (lengths.count(first + i) == 0) {
@@ -1482,7 +1483,7 @@ void @@ -1482,7 +1483,7 @@ void
1482 QPDF::calculateHPageOffset( 1483 QPDF::calculateHPageOffset(
1483 std::map<int, QPDFXRefEntry> const& xref, 1484 std::map<int, QPDFXRefEntry> const& xref,
1484 std::map<int, qpdf_offset_t> const& lengths, 1485 std::map<int, qpdf_offset_t> const& lengths,
1485 - std::map<int, int> const& obj_renumber) 1486 + QPDFWriter::ObjTable const& obj)
1486 { 1487 {
1487 // Page Offset Hint Table 1488 // Page Offset Hint Table
1488 1489
@@ -1497,8 +1498,7 @@ QPDF::calculateHPageOffset( @@ -1497,8 +1498,7 @@ QPDF::calculateHPageOffset(
1497 1498
1498 int min_nobjects = cphe.at(0).nobjects; 1499 int min_nobjects = cphe.at(0).nobjects;
1499 int max_nobjects = min_nobjects; 1500 int max_nobjects = min_nobjects;
1500 - int min_length =  
1501 - outputLengthNextN(pages.at(0).getObjectID(), min_nobjects, lengths, obj_renumber); 1501 + int min_length = outputLengthNextN(pages.at(0).getObjectID(), min_nobjects, lengths, obj);
1502 int max_length = min_length; 1502 int max_length = min_length;
1503 int max_shared = cphe.at(0).nshared_objects; 1503 int max_shared = cphe.at(0).nshared_objects;
1504 1504
@@ -1515,7 +1515,7 @@ QPDF::calculateHPageOffset( @@ -1515,7 +1515,7 @@ QPDF::calculateHPageOffset(
1515 // assignments. 1515 // assignments.
1516 1516
1517 int nobjects = cphe.at(i).nobjects; 1517 int nobjects = cphe.at(i).nobjects;
1518 - int length = outputLengthNextN(pages.at(i).getObjectID(), nobjects, lengths, obj_renumber); 1518 + int length = outputLengthNextN(pages.at(i).getObjectID(), nobjects, lengths, obj);
1519 int nshared = cphe.at(i).nshared_objects; 1519 int nshared = cphe.at(i).nshared_objects;
1520 1520
1521 min_nobjects = std::min(min_nobjects, nobjects); 1521 min_nobjects = std::min(min_nobjects, nobjects);
@@ -1530,8 +1530,7 @@ QPDF::calculateHPageOffset( @@ -1530,8 +1530,7 @@ QPDF::calculateHPageOffset(
1530 } 1530 }
1531 1531
1532 ph.min_nobjects = min_nobjects; 1532 ph.min_nobjects = min_nobjects;
1533 - int in_page0_id = pages.at(0).getObjectID();  
1534 - int out_page0_id = (*(obj_renumber.find(in_page0_id))).second; 1533 + int out_page0_id = obj[pages.at(0)].renumber;
1535 ph.first_page_offset = (*(xref.find(out_page0_id))).second.getOffset(); 1534 ph.first_page_offset = (*(xref.find(out_page0_id))).second.getOffset();
1536 ph.nbits_delta_nobjects = nbits(max_nobjects - min_nobjects); 1535 ph.nbits_delta_nobjects = nbits(max_nobjects - min_nobjects);
1537 ph.min_page_length = min_length; 1536 ph.min_page_length = min_length;
@@ -1569,7 +1568,7 @@ void @@ -1569,7 +1568,7 @@ void
1569 QPDF::calculateHSharedObject( 1568 QPDF::calculateHSharedObject(
1570 std::map<int, QPDFXRefEntry> const& xref, 1569 std::map<int, QPDFXRefEntry> const& xref,
1571 std::map<int, qpdf_offset_t> const& lengths, 1570 std::map<int, qpdf_offset_t> const& lengths,
1572 - std::map<int, int> const& obj_renumber) 1571 + QPDFWriter::ObjTable const& obj)
1573 { 1572 {
1574 CHSharedObject& cso = m->c_shared_object_data; 1573 CHSharedObject& cso = m->c_shared_object_data;
1575 std::vector<CHSharedObjectEntry>& csoe = cso.entries; 1574 std::vector<CHSharedObjectEntry>& csoe = cso.entries;
@@ -1577,12 +1576,12 @@ QPDF::calculateHSharedObject( @@ -1577,12 +1576,12 @@ QPDF::calculateHSharedObject(
1577 std::vector<HSharedObjectEntry>& soe = so.entries; 1576 std::vector<HSharedObjectEntry>& soe = so.entries;
1578 soe.clear(); 1577 soe.clear();
1579 1578
1580 - int min_length = outputLengthNextN(csoe.at(0).object, 1, lengths, obj_renumber); 1579 + int min_length = outputLengthNextN(csoe.at(0).object, 1, lengths, obj);
1581 int max_length = min_length; 1580 int max_length = min_length;
1582 1581
1583 for (size_t i = 0; i < toS(cso.nshared_total); ++i) { 1582 for (size_t i = 0; i < toS(cso.nshared_total); ++i) {
1584 // Assign absolute numbers to deltas; adjust later 1583 // Assign absolute numbers to deltas; adjust later
1585 - int length = outputLengthNextN(csoe.at(i).object, 1, lengths, obj_renumber); 1584 + int length = outputLengthNextN(csoe.at(i).object, 1, lengths, obj);
1586 min_length = std::min(min_length, length); 1585 min_length = std::min(min_length, length);
1587 max_length = std::max(max_length, length); 1586 max_length = std::max(max_length, length);
1588 soe.emplace_back(); 1587 soe.emplace_back();
@@ -1595,7 +1594,7 @@ QPDF::calculateHSharedObject( @@ -1595,7 +1594,7 @@ QPDF::calculateHSharedObject(
1595 so.nshared_total = cso.nshared_total; 1594 so.nshared_total = cso.nshared_total;
1596 so.nshared_first_page = cso.nshared_first_page; 1595 so.nshared_first_page = cso.nshared_first_page;
1597 if (so.nshared_total > so.nshared_first_page) { 1596 if (so.nshared_total > so.nshared_first_page) {
1598 - so.first_shared_obj = (*(obj_renumber.find(cso.first_shared_obj))).second; 1597 + so.first_shared_obj = obj[cso.first_shared_obj].renumber;
1599 so.first_shared_offset = (*(xref.find(so.first_shared_obj))).second.getOffset(); 1598 so.first_shared_offset = (*(xref.find(so.first_shared_obj))).second.getOffset();
1600 } 1599 }
1601 so.min_group_length = min_length; 1600 so.min_group_length = min_length;
@@ -1614,7 +1613,7 @@ void @@ -1614,7 +1613,7 @@ void
1614 QPDF::calculateHOutline( 1613 QPDF::calculateHOutline(
1615 std::map<int, QPDFXRefEntry> const& xref, 1614 std::map<int, QPDFXRefEntry> const& xref,
1616 std::map<int, qpdf_offset_t> const& lengths, 1615 std::map<int, qpdf_offset_t> const& lengths,
1617 - std::map<int, int> const& obj_renumber) 1616 + QPDFWriter::ObjTable const& obj)
1618 { 1617 {
1619 HGeneric& cho = m->c_outline_data; 1618 HGeneric& cho = m->c_outline_data;
1620 1619
@@ -1624,10 +1623,10 @@ QPDF::calculateHOutline( @@ -1624,10 +1623,10 @@ QPDF::calculateHOutline(
1624 1623
1625 HGeneric& ho = m->outline_hints; 1624 HGeneric& ho = m->outline_hints;
1626 1625
1627 - ho.first_object = (*(obj_renumber.find(cho.first_object))).second; 1626 + ho.first_object = obj[cho.first_object].renumber;
1628 ho.first_object_offset = (*(xref.find(ho.first_object))).second.getOffset(); 1627 ho.first_object_offset = (*(xref.find(ho.first_object))).second.getOffset();
1629 ho.nobjects = cho.nobjects; 1628 ho.nobjects = cho.nobjects;
1630 - ho.group_length = outputLengthNextN(cho.first_object, ho.nobjects, lengths, obj_renumber); 1629 + ho.group_length = outputLengthNextN(cho.first_object, ho.nobjects, lengths, obj);
1631 } 1630 }
1632 1631
1633 template <class T, class int_type> 1632 template <class T, class int_type>
@@ -1758,16 +1757,16 @@ void @@ -1758,16 +1757,16 @@ void
1758 QPDF::generateHintStream( 1757 QPDF::generateHintStream(
1759 std::map<int, QPDFXRefEntry> const& xref, 1758 std::map<int, QPDFXRefEntry> const& xref,
1760 std::map<int, qpdf_offset_t> const& lengths, 1759 std::map<int, qpdf_offset_t> const& lengths,
1761 - std::map<int, int> const& obj_renumber, 1760 + QPDFWriter::ObjTable const& obj,
1762 std::shared_ptr<Buffer>& hint_buffer, 1761 std::shared_ptr<Buffer>& hint_buffer,
1763 int& S, 1762 int& S,
1764 int& O, 1763 int& O,
1765 bool compressed) 1764 bool compressed)
1766 { 1765 {
1767 // Populate actual hint table values 1766 // Populate actual hint table values
1768 - calculateHPageOffset(xref, lengths, obj_renumber);  
1769 - calculateHSharedObject(xref, lengths, obj_renumber);  
1770 - calculateHOutline(xref, lengths, obj_renumber); 1767 + calculateHPageOffset(xref, lengths, obj);
  1768 + calculateHSharedObject(xref, lengths, obj);
  1769 + calculateHOutline(xref, lengths, obj);
1771 1770
1772 // Write the hint stream itself into a compressed memory buffer. Write through a counter so we 1771 // Write the hint stream itself into a compressed memory buffer. Write through a counter so we
1773 // can get offsets. 1772 // can get offsets.
libqpdf/qpdf/QPDFWriter_private.hh
@@ -99,7 +99,6 @@ class QPDFWriter::Members @@ -99,7 +99,6 @@ class QPDFWriter::Members
99 99
100 // For linearization only 100 // For linearization only
101 std::string lin_pass1_filename; 101 std::string lin_pass1_filename;
102 - std::map<int, int> obj_renumber_no_gen;  
103 std::map<int, int> object_to_object_stream_no_gen; 102 std::map<int, int> object_to_object_stream_no_gen;
104 103
105 // For progress reporting 104 // For progress reporting