Commit 84e25919cb9e3303670d23320dcc4071759a9634
1 parent
8791b5f8
In QPDFWriter replace map obj_renumber_no_gen with ObjTable obj
Showing
5 changed files
with
28 additions
and
53 deletions
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<QPDFObjGen, int> const& in, std::map<int, | @@ -2546,26 +2546,6 @@ QPDFWriter::discardGeneration(std::map<QPDFObjGen, int> const& in, std::map<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 |