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 | 41 | #include <qpdf/QPDFObjectHandle.hh> |
| 42 | 42 | #include <qpdf/QPDFStreamFilter.hh> |
| 43 | 43 | #include <qpdf/QPDFTokenizer.hh> |
| 44 | +#include <qpdf/QPDFWriter.hh> | |
| 44 | 45 | #include <qpdf/QPDFXRefEntry.hh> |
| 45 | 46 | |
| 46 | 47 | class QPDF_Stream; |
| ... | ... | @@ -744,14 +745,13 @@ class QPDF |
| 744 | 745 | QPDF& qpdf, |
| 745 | 746 | std::map<int, QPDFXRefEntry> const& xref, |
| 746 | 747 | std::map<int, qpdf_offset_t> const& lengths, |
| 747 | - std::map<int, int> const& obj_renumber, | |
| 748 | + QPDFWriter::ObjTable const& obj, | |
| 748 | 749 | std::shared_ptr<Buffer>& hint_stream, |
| 749 | 750 | int& S, |
| 750 | 751 | int& O, |
| 751 | 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 | 757 | static void |
| ... | ... | @@ -1104,7 +1104,7 @@ class QPDF |
| 1104 | 1104 | void generateHintStream( |
| 1105 | 1105 | std::map<int, QPDFXRefEntry> const& xref, |
| 1106 | 1106 | std::map<int, qpdf_offset_t> const& lengths, |
| 1107 | - std::map<int, int> const& obj_renumber, | |
| 1107 | + QPDFWriter::ObjTable const& obj, | |
| 1108 | 1108 | std::shared_ptr<Buffer>& hint_stream, |
| 1109 | 1109 | int& S, |
| 1110 | 1110 | int& O, |
| ... | ... | @@ -1379,19 +1379,19 @@ class QPDF |
| 1379 | 1379 | int in_object, |
| 1380 | 1380 | int n, |
| 1381 | 1381 | std::map<int, qpdf_offset_t> const& lengths, |
| 1382 | - std::map<int, int> const& obj_renumber); | |
| 1382 | + QPDFWriter::ObjTable const& obj); | |
| 1383 | 1383 | void calculateHPageOffset( |
| 1384 | 1384 | std::map<int, QPDFXRefEntry> const& xref, |
| 1385 | 1385 | std::map<int, qpdf_offset_t> const& lengths, |
| 1386 | - std::map<int, int> const& obj_renumber); | |
| 1386 | + QPDFWriter::ObjTable const& obj); | |
| 1387 | 1387 | void calculateHSharedObject( |
| 1388 | 1388 | std::map<int, QPDFXRefEntry> const& xref, |
| 1389 | 1389 | std::map<int, qpdf_offset_t> const& lengths, |
| 1390 | - std::map<int, int> const& obj_renumber); | |
| 1390 | + QPDFWriter::ObjTable const& obj); | |
| 1391 | 1391 | void calculateHOutline( |
| 1392 | 1392 | std::map<int, QPDFXRefEntry> const& xref, |
| 1393 | 1393 | std::map<int, qpdf_offset_t> const& lengths, |
| 1394 | - std::map<int, int> const& obj_renumber); | |
| 1394 | + QPDFWriter::ObjTable const& obj); | |
| 1395 | 1395 | void writeHPageOffset(BitWriter&); |
| 1396 | 1396 | void writeHSharedObject(BitWriter&); |
| 1397 | 1397 | void writeHGeneric(BitWriter&, HGeneric&); | ... | ... |
include/qpdf/QPDFWriter.hh
libqpdf/QPDFWriter.cc
| ... | ... | @@ -2303,7 +2303,7 @@ QPDFWriter::writeHintStream(int hint_id) |
| 2303 | 2303 | int O = 0; |
| 2304 | 2304 | bool compressed = (m->compress_streams && !m->qdf_mode); |
| 2305 | 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 | 2308 | openObject(hint_id); |
| 2309 | 2309 | setDataKey(hint_id); |
| ... | ... | @@ -2546,26 +2546,6 @@ QPDFWriter::discardGeneration(std::map<QPDFObjGen, int> const& in, std::map<int, |
| 2546 | 2546 | } |
| 2547 | 2547 | |
| 2548 | 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 | 2549 | QPDFWriter::writeLinearized() |
| 2570 | 2550 | { |
| 2571 | 2551 | // Optimize file and enqueue objects in order |
| ... | ... | @@ -2887,8 +2867,6 @@ QPDFWriter::writeLinearized() |
| 2887 | 2867 | writeString(std::to_string(first_xref_offset)); |
| 2888 | 2868 | writeString("\n%%EOF\n"); |
| 2889 | 2869 | |
| 2890 | - discardGeneration(m->obj_renumber_no_gen); | |
| 2891 | - | |
| 2892 | 2870 | if (pass == 1) { |
| 2893 | 2871 | if (m->deterministic_id) { |
| 2894 | 2872 | QTC::TC("qpdf", "QPDFWriter linearized deterministic ID", need_xref_stream ? 0 : 1); | ... | ... |
libqpdf/QPDF_linearization.cc
| ... | ... | @@ -9,6 +9,7 @@ |
| 9 | 9 | #include <qpdf/Pl_Flate.hh> |
| 10 | 10 | #include <qpdf/QPDFExc.hh> |
| 11 | 11 | #include <qpdf/QPDFLogger.hh> |
| 12 | +#include <qpdf/QPDFWriter_private.hh> | |
| 12 | 13 | #include <qpdf/QTC.hh> |
| 13 | 14 | #include <qpdf/QUtil.hh> |
| 14 | 15 | |
| ... | ... | @@ -1459,15 +1460,15 @@ QPDF::outputLengthNextN( |
| 1459 | 1460 | int in_object, |
| 1460 | 1461 | int n, |
| 1461 | 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 | 1465 | // Figure out the length of a series of n consecutive objects in the output file starting with |
| 1465 | 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 | 1470 | stopOnError("found object that is not renumbered while writing linearization data"); |
| 1469 | 1471 | } |
| 1470 | - int first = (*(obj_renumber.find(in_object))).second; | |
| 1471 | 1472 | int length = 0; |
| 1472 | 1473 | for (int i = 0; i < n; ++i) { |
| 1473 | 1474 | if (lengths.count(first + i) == 0) { |
| ... | ... | @@ -1482,7 +1483,7 @@ void |
| 1482 | 1483 | QPDF::calculateHPageOffset( |
| 1483 | 1484 | std::map<int, QPDFXRefEntry> const& xref, |
| 1484 | 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 | 1488 | // Page Offset Hint Table |
| 1488 | 1489 | |
| ... | ... | @@ -1497,8 +1498,7 @@ QPDF::calculateHPageOffset( |
| 1497 | 1498 | |
| 1498 | 1499 | int min_nobjects = cphe.at(0).nobjects; |
| 1499 | 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 | 1502 | int max_length = min_length; |
| 1503 | 1503 | int max_shared = cphe.at(0).nshared_objects; |
| 1504 | 1504 | |
| ... | ... | @@ -1515,7 +1515,7 @@ QPDF::calculateHPageOffset( |
| 1515 | 1515 | // assignments. |
| 1516 | 1516 | |
| 1517 | 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 | 1519 | int nshared = cphe.at(i).nshared_objects; |
| 1520 | 1520 | |
| 1521 | 1521 | min_nobjects = std::min(min_nobjects, nobjects); |
| ... | ... | @@ -1530,8 +1530,7 @@ QPDF::calculateHPageOffset( |
| 1530 | 1530 | } |
| 1531 | 1531 | |
| 1532 | 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 | 1534 | ph.first_page_offset = (*(xref.find(out_page0_id))).second.getOffset(); |
| 1536 | 1535 | ph.nbits_delta_nobjects = nbits(max_nobjects - min_nobjects); |
| 1537 | 1536 | ph.min_page_length = min_length; |
| ... | ... | @@ -1569,7 +1568,7 @@ void |
| 1569 | 1568 | QPDF::calculateHSharedObject( |
| 1570 | 1569 | std::map<int, QPDFXRefEntry> const& xref, |
| 1571 | 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 | 1573 | CHSharedObject& cso = m->c_shared_object_data; |
| 1575 | 1574 | std::vector<CHSharedObjectEntry>& csoe = cso.entries; |
| ... | ... | @@ -1577,12 +1576,12 @@ QPDF::calculateHSharedObject( |
| 1577 | 1576 | std::vector<HSharedObjectEntry>& soe = so.entries; |
| 1578 | 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 | 1580 | int max_length = min_length; |
| 1582 | 1581 | |
| 1583 | 1582 | for (size_t i = 0; i < toS(cso.nshared_total); ++i) { |
| 1584 | 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 | 1585 | min_length = std::min(min_length, length); |
| 1587 | 1586 | max_length = std::max(max_length, length); |
| 1588 | 1587 | soe.emplace_back(); |
| ... | ... | @@ -1595,7 +1594,7 @@ QPDF::calculateHSharedObject( |
| 1595 | 1594 | so.nshared_total = cso.nshared_total; |
| 1596 | 1595 | so.nshared_first_page = cso.nshared_first_page; |
| 1597 | 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 | 1598 | so.first_shared_offset = (*(xref.find(so.first_shared_obj))).second.getOffset(); |
| 1600 | 1599 | } |
| 1601 | 1600 | so.min_group_length = min_length; |
| ... | ... | @@ -1614,7 +1613,7 @@ void |
| 1614 | 1613 | QPDF::calculateHOutline( |
| 1615 | 1614 | std::map<int, QPDFXRefEntry> const& xref, |
| 1616 | 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 | 1618 | HGeneric& cho = m->c_outline_data; |
| 1620 | 1619 | |
| ... | ... | @@ -1624,10 +1623,10 @@ QPDF::calculateHOutline( |
| 1624 | 1623 | |
| 1625 | 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 | 1627 | ho.first_object_offset = (*(xref.find(ho.first_object))).second.getOffset(); |
| 1629 | 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 | 1632 | template <class T, class int_type> |
| ... | ... | @@ -1758,16 +1757,16 @@ void |
| 1758 | 1757 | QPDF::generateHintStream( |
| 1759 | 1758 | std::map<int, QPDFXRefEntry> const& xref, |
| 1760 | 1759 | std::map<int, qpdf_offset_t> const& lengths, |
| 1761 | - std::map<int, int> const& obj_renumber, | |
| 1760 | + QPDFWriter::ObjTable const& obj, | |
| 1762 | 1761 | std::shared_ptr<Buffer>& hint_buffer, |
| 1763 | 1762 | int& S, |
| 1764 | 1763 | int& O, |
| 1765 | 1764 | bool compressed) |
| 1766 | 1765 | { |
| 1767 | 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 | 1771 | // Write the hint stream itself into a compressed memory buffer. Write through a counter so we |
| 1773 | 1772 | // can get offsets. | ... | ... |
libqpdf/qpdf/QPDFWriter_private.hh