Commit ccad589f7d2e732f780d7160af0b23546888fa82
1 parent
47cf4e3a
In QPDFWriter replace map xref with new ObjTable new_obj
Showing
5 changed files
with
48 additions
and
39 deletions
include/qpdf/QPDF.hh
| ... | ... | @@ -743,7 +743,7 @@ class QPDF |
| 743 | 743 | static void |
| 744 | 744 | generateHintStream( |
| 745 | 745 | QPDF& qpdf, |
| 746 | - std::map<int, QPDFXRefEntry> const& xref, | |
| 746 | + QPDFWriter::NewObjTable const& new_obj, | |
| 747 | 747 | std::map<int, qpdf_offset_t> const& lengths, |
| 748 | 748 | QPDFWriter::ObjTable const& obj, |
| 749 | 749 | std::shared_ptr<Buffer>& hint_stream, |
| ... | ... | @@ -751,7 +751,7 @@ class QPDF |
| 751 | 751 | int& O, |
| 752 | 752 | bool compressed) |
| 753 | 753 | { |
| 754 | - return qpdf.generateHintStream(xref, lengths, obj, hint_stream, S, O, compressed); | |
| 754 | + return qpdf.generateHintStream(new_obj, lengths, obj, hint_stream, S, O, compressed); | |
| 755 | 755 | } |
| 756 | 756 | |
| 757 | 757 | static void |
| ... | ... | @@ -1102,7 +1102,7 @@ class QPDF |
| 1102 | 1102 | std::vector<QPDFObjectHandle>& part9); |
| 1103 | 1103 | |
| 1104 | 1104 | void generateHintStream( |
| 1105 | - std::map<int, QPDFXRefEntry> const& xref, | |
| 1105 | + QPDFWriter::NewObjTable const& new_obj, | |
| 1106 | 1106 | std::map<int, qpdf_offset_t> const& lengths, |
| 1107 | 1107 | QPDFWriter::ObjTable const& obj, |
| 1108 | 1108 | std::shared_ptr<Buffer>& hint_stream, |
| ... | ... | @@ -1381,15 +1381,15 @@ class QPDF |
| 1381 | 1381 | std::map<int, qpdf_offset_t> const& lengths, |
| 1382 | 1382 | QPDFWriter::ObjTable const& obj); |
| 1383 | 1383 | void calculateHPageOffset( |
| 1384 | - std::map<int, QPDFXRefEntry> const& xref, | |
| 1384 | + QPDFWriter::NewObjTable const& new_obj, | |
| 1385 | 1385 | std::map<int, qpdf_offset_t> const& lengths, |
| 1386 | 1386 | QPDFWriter::ObjTable const& obj); |
| 1387 | 1387 | void calculateHSharedObject( |
| 1388 | - std::map<int, QPDFXRefEntry> const& xref, | |
| 1388 | + QPDFWriter::NewObjTable const& new_obj, | |
| 1389 | 1389 | std::map<int, qpdf_offset_t> const& lengths, |
| 1390 | 1390 | QPDFWriter::ObjTable const& obj); |
| 1391 | 1391 | void calculateHOutline( |
| 1392 | - std::map<int, QPDFXRefEntry> const& xref, | |
| 1392 | + QPDFWriter::NewObjTable const& new_obj, | |
| 1393 | 1393 | std::map<int, qpdf_offset_t> const& lengths, |
| 1394 | 1394 | QPDFWriter::ObjTable const& obj); |
| 1395 | 1395 | void writeHPageOffset(BitWriter&); | ... | ... |
include/qpdf/QPDFWriter.hh
libqpdf/QPDFWriter.cc
| ... | ... | @@ -1038,7 +1038,7 @@ QPDFWriter::openObject(int objid) |
| 1038 | 1038 | if (objid == 0) { |
| 1039 | 1039 | objid = m->next_objid++; |
| 1040 | 1040 | } |
| 1041 | - m->xref[objid] = QPDFXRefEntry(m->pipeline->getCount()); | |
| 1041 | + m->new_obj[objid].xref = QPDFXRefEntry(m->pipeline->getCount()); | |
| 1042 | 1042 | writeString(std::to_string(objid)); |
| 1043 | 1043 | writeString(" 0 obj\n"); |
| 1044 | 1044 | return objid; |
| ... | ... | @@ -1050,7 +1050,7 @@ QPDFWriter::closeObject(int objid) |
| 1050 | 1050 | // Write a newline before endobj as it makes the file easier to repair. |
| 1051 | 1051 | writeString("\nendobj\n"); |
| 1052 | 1052 | writeStringQDF("\n"); |
| 1053 | - m->lengths[objid] = m->pipeline->getCount() - m->xref[objid].getOffset(); | |
| 1053 | + m->lengths[objid] = m->pipeline->getCount() - m->new_obj[objid].xref.getOffset(); | |
| 1054 | 1054 | } |
| 1055 | 1055 | |
| 1056 | 1056 | void |
| ... | ... | @@ -1703,7 +1703,7 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) |
| 1703 | 1703 | } |
| 1704 | 1704 | writeObject(obj_to_write, count); |
| 1705 | 1705 | |
| 1706 | - m->xref[new_obj] = QPDFXRefEntry(new_stream_id, count); | |
| 1706 | + m->new_obj[new_obj].xref = QPDFXRefEntry(new_stream_id, count); | |
| 1707 | 1707 | } |
| 1708 | 1708 | } |
| 1709 | 1709 | |
| ... | ... | @@ -1978,8 +1978,6 @@ QPDFWriter::generateObjectStreams() |
| 1978 | 1978 | std::vector<QPDFObjGen> eligible = QPDF::Writer::getCompressibleObjGens(m->pdf); |
| 1979 | 1979 | size_t n_object_streams = (eligible.size() + 99U) / 100U; |
| 1980 | 1980 | |
| 1981 | - // Initialize object table for all existing objects plus some headroom for objects created | |
| 1982 | - // during writing. | |
| 1983 | 1981 | initializeTables(2U * n_object_streams); |
| 1984 | 1982 | if (n_object_streams == 0) { |
| 1985 | 1983 | m->obj.streams_empty = true; |
| ... | ... | @@ -2065,6 +2063,7 @@ QPDFWriter::initializeTables(size_t extra) |
| 2065 | 2063 | { |
| 2066 | 2064 | auto size = QIntC::to_size(QPDF::Writer::tableSize(m->pdf) + 100) + extra; |
| 2067 | 2065 | m->obj.initialize(size); |
| 2066 | + m->new_obj.initialize(size); | |
| 2068 | 2067 | } |
| 2069 | 2068 | |
| 2070 | 2069 | void |
| ... | ... | @@ -2136,8 +2135,6 @@ QPDFWriter::doWriteSetup() |
| 2136 | 2135 | |
| 2137 | 2136 | switch (m->object_stream_mode) { |
| 2138 | 2137 | case qpdf_o_disable: |
| 2139 | - // Initialize object table for all existing objects plus some headroom for objects created | |
| 2140 | - // during writing. | |
| 2141 | 2138 | initializeTables(); |
| 2142 | 2139 | m->obj.streams_empty = true; |
| 2143 | 2140 | break; |
| ... | ... | @@ -2245,12 +2242,12 @@ QPDFWriter::getWrittenXRefTable() |
| 2245 | 2242 | { |
| 2246 | 2243 | std::map<QPDFObjGen, QPDFXRefEntry> result; |
| 2247 | 2244 | |
| 2248 | - for (auto const& iter: m->xref) { | |
| 2249 | - if (iter.first != 0 && iter.second.getType() != 0) { | |
| 2250 | - result[QPDFObjGen(iter.first, 0)] = iter.second; | |
| 2245 | + auto it = result.begin(); | |
| 2246 | + m->new_obj.forEach([&it, &result](auto id, auto const& item) -> void { | |
| 2247 | + if (item.xref.getType() != 0) { | |
| 2248 | + it = result.emplace_hint(it, QPDFObjGen(id, 0), item.xref); | |
| 2251 | 2249 | } |
| 2252 | - } | |
| 2253 | - | |
| 2250 | + }); | |
| 2254 | 2251 | return result; |
| 2255 | 2252 | } |
| 2256 | 2253 | |
| ... | ... | @@ -2313,7 +2310,7 @@ QPDFWriter::writeHintStream(int hint_id) |
| 2313 | 2310 | int O = 0; |
| 2314 | 2311 | bool compressed = (m->compress_streams && !m->qdf_mode); |
| 2315 | 2312 | QPDF::Writer::generateHintStream( |
| 2316 | - m->pdf, m->xref, m->lengths, m->obj, hint_buffer, S, O, compressed); | |
| 2313 | + m->pdf, m->new_obj, m->lengths, m->obj, hint_buffer, S, O, compressed); | |
| 2317 | 2314 | |
| 2318 | 2315 | openObject(hint_id); |
| 2319 | 2316 | setDataKey(hint_id); |
| ... | ... | @@ -2386,7 +2383,7 @@ QPDFWriter::writeXRefTable( |
| 2386 | 2383 | } else { |
| 2387 | 2384 | qpdf_offset_t offset = 0; |
| 2388 | 2385 | if (!suppress_offsets) { |
| 2389 | - offset = m->xref[i].getOffset(); | |
| 2386 | + offset = m->new_obj[i].xref.getOffset(); | |
| 2390 | 2387 | if ((hint_id != 0) && (i != hint_id) && (offset >= hint_offset)) { |
| 2391 | 2388 | offset += hint_length; |
| 2392 | 2389 | } |
| ... | ... | @@ -2439,7 +2436,7 @@ QPDFWriter::writeXRefStream( |
| 2439 | 2436 | |
| 2440 | 2437 | // Must store in xref table in advance of writing the actual data rather than waiting for |
| 2441 | 2438 | // openObject to do it. |
| 2442 | - m->xref[xref_id] = QPDFXRefEntry(m->pipeline->getCount()); | |
| 2439 | + m->new_obj[xref_id].xref = QPDFXRefEntry(m->pipeline->getCount()); | |
| 2443 | 2440 | |
| 2444 | 2441 | Pipeline* p = pushPipeline(new Pl_Buffer("xref stream")); |
| 2445 | 2442 | bool compressed = false; |
| ... | ... | @@ -2457,7 +2454,7 @@ QPDFWriter::writeXRefStream( |
| 2457 | 2454 | PipelinePopper pp_xref(this, &xref_data); |
| 2458 | 2455 | activatePipelineStack(pp_xref); |
| 2459 | 2456 | for (int i = first; i <= last; ++i) { |
| 2460 | - QPDFXRefEntry& e = m->xref[i]; | |
| 2457 | + QPDFXRefEntry& e = m->new_obj[i].xref; | |
| 2461 | 2458 | switch (e.getType()) { |
| 2462 | 2459 | case 0: |
| 2463 | 2460 | writeBinary(0, 1); |
| ... | ... | @@ -2712,7 +2709,7 @@ QPDFWriter::writeLinearized() |
| 2712 | 2709 | writeString(std::to_string(file_size + hint_length)); |
| 2713 | 2710 | // Implementation note 121 states that a space is mandatory after this open bracket. |
| 2714 | 2711 | writeString(" /H [ "); |
| 2715 | - writeString(std::to_string(m->xref[hint_id].getOffset())); | |
| 2712 | + writeString(std::to_string(m->new_obj[hint_id].xref.getOffset())); | |
| 2716 | 2713 | writeString(" "); |
| 2717 | 2714 | writeString(std::to_string(hint_length)); |
| 2718 | 2715 | writeString(" ] /O "); |
| ... | ... | @@ -2739,7 +2736,7 @@ QPDFWriter::writeLinearized() |
| 2739 | 2736 | qpdf_offset_t first_xref_offset = m->pipeline->getCount(); |
| 2740 | 2737 | qpdf_offset_t hint_offset = 0; |
| 2741 | 2738 | if (pass == 2) { |
| 2742 | - hint_offset = m->xref[hint_id].getOffset(); | |
| 2739 | + hint_offset = m->new_obj[hint_id].xref.getOffset(); | |
| 2743 | 2740 | } |
| 2744 | 2741 | if (need_xref_stream) { |
| 2745 | 2742 | // Must pad here too. |
| ... | ... | @@ -2810,7 +2807,7 @@ QPDFWriter::writeLinearized() |
| 2810 | 2807 | writeEncryptionDictionary(); |
| 2811 | 2808 | } |
| 2812 | 2809 | if (pass == 1) { |
| 2813 | - m->xref[hint_id] = QPDFXRefEntry(m->pipeline->getCount()); | |
| 2810 | + m->new_obj[hint_id].xref = QPDFXRefEntry(m->pipeline->getCount()); | |
| 2814 | 2811 | } else { |
| 2815 | 2812 | // Part 5: hint stream |
| 2816 | 2813 | writeBuffer(hint_buffer); |
| ... | ... | @@ -2883,7 +2880,7 @@ QPDFWriter::writeLinearized() |
| 2883 | 2880 | pp_pass1 = nullptr; |
| 2884 | 2881 | |
| 2885 | 2882 | // Save hint offset since it will be set to zero by calling openObject. |
| 2886 | - qpdf_offset_t hint_offset1 = m->xref[hint_id].getOffset(); | |
| 2883 | + qpdf_offset_t hint_offset1 = m->new_obj[hint_id].xref.getOffset(); | |
| 2887 | 2884 | |
| 2888 | 2885 | // Write hint stream to a buffer |
| 2889 | 2886 | { |
| ... | ... | @@ -2895,7 +2892,7 @@ QPDFWriter::writeLinearized() |
| 2895 | 2892 | hint_length = QIntC::to_offset(hint_buffer->getSize()); |
| 2896 | 2893 | |
| 2897 | 2894 | // Restore hint offset |
| 2898 | - m->xref[hint_id] = QPDFXRefEntry(hint_offset1); | |
| 2895 | + m->new_obj[hint_id].xref = QPDFXRefEntry(hint_offset1); | |
| 2899 | 2896 | if (lin_pass1_file) { |
| 2900 | 2897 | // Write some debugging information |
| 2901 | 2898 | fprintf( | ... | ... |
libqpdf/QPDF_linearization.cc
| ... | ... | @@ -1481,7 +1481,7 @@ QPDF::outputLengthNextN( |
| 1481 | 1481 | |
| 1482 | 1482 | void |
| 1483 | 1483 | QPDF::calculateHPageOffset( |
| 1484 | - std::map<int, QPDFXRefEntry> const& xref, | |
| 1484 | + QPDFWriter::NewObjTable const& new_obj, | |
| 1485 | 1485 | std::map<int, qpdf_offset_t> const& lengths, |
| 1486 | 1486 | QPDFWriter::ObjTable const& obj) |
| 1487 | 1487 | { |
| ... | ... | @@ -1530,8 +1530,7 @@ QPDF::calculateHPageOffset( |
| 1530 | 1530 | } |
| 1531 | 1531 | |
| 1532 | 1532 | ph.min_nobjects = min_nobjects; |
| 1533 | - int out_page0_id = obj[pages.at(0)].renumber; | |
| 1534 | - ph.first_page_offset = (*(xref.find(out_page0_id))).second.getOffset(); | |
| 1533 | + ph.first_page_offset = new_obj[obj[pages.at(0)].renumber].xref.getOffset(); | |
| 1535 | 1534 | ph.nbits_delta_nobjects = nbits(max_nobjects - min_nobjects); |
| 1536 | 1535 | ph.min_page_length = min_length; |
| 1537 | 1536 | ph.nbits_delta_page_length = nbits(max_length - min_length); |
| ... | ... | @@ -1566,7 +1565,7 @@ QPDF::calculateHPageOffset( |
| 1566 | 1565 | |
| 1567 | 1566 | void |
| 1568 | 1567 | QPDF::calculateHSharedObject( |
| 1569 | - std::map<int, QPDFXRefEntry> const& xref, | |
| 1568 | + QPDFWriter::NewObjTable const& new_obj, | |
| 1570 | 1569 | std::map<int, qpdf_offset_t> const& lengths, |
| 1571 | 1570 | QPDFWriter::ObjTable const& obj) |
| 1572 | 1571 | { |
| ... | ... | @@ -1595,7 +1594,8 @@ QPDF::calculateHSharedObject( |
| 1595 | 1594 | so.nshared_first_page = cso.nshared_first_page; |
| 1596 | 1595 | if (so.nshared_total > so.nshared_first_page) { |
| 1597 | 1596 | so.first_shared_obj = obj[cso.first_shared_obj].renumber; |
| 1598 | - so.first_shared_offset = (*(xref.find(so.first_shared_obj))).second.getOffset(); | |
| 1597 | + so.min_group_length = min_length; | |
| 1598 | + so.first_shared_offset = new_obj[so.first_shared_obj].xref.getOffset(); | |
| 1599 | 1599 | } |
| 1600 | 1600 | so.min_group_length = min_length; |
| 1601 | 1601 | so.nbits_delta_group_length = nbits(max_length - min_length); |
| ... | ... | @@ -1611,7 +1611,7 @@ QPDF::calculateHSharedObject( |
| 1611 | 1611 | |
| 1612 | 1612 | void |
| 1613 | 1613 | QPDF::calculateHOutline( |
| 1614 | - std::map<int, QPDFXRefEntry> const& xref, | |
| 1614 | + QPDFWriter::NewObjTable const& new_obj, | |
| 1615 | 1615 | std::map<int, qpdf_offset_t> const& lengths, |
| 1616 | 1616 | QPDFWriter::ObjTable const& obj) |
| 1617 | 1617 | { |
| ... | ... | @@ -1624,7 +1624,7 @@ QPDF::calculateHOutline( |
| 1624 | 1624 | HGeneric& ho = m->outline_hints; |
| 1625 | 1625 | |
| 1626 | 1626 | ho.first_object = obj[cho.first_object].renumber; |
| 1627 | - ho.first_object_offset = (*(xref.find(ho.first_object))).second.getOffset(); | |
| 1627 | + ho.first_object_offset = new_obj[ho.first_object].xref.getOffset(); | |
| 1628 | 1628 | ho.nobjects = cho.nobjects; |
| 1629 | 1629 | ho.group_length = outputLengthNextN(cho.first_object, ho.nobjects, lengths, obj); |
| 1630 | 1630 | } |
| ... | ... | @@ -1755,7 +1755,7 @@ QPDF::writeHGeneric(BitWriter& w, HGeneric& t) |
| 1755 | 1755 | |
| 1756 | 1756 | void |
| 1757 | 1757 | QPDF::generateHintStream( |
| 1758 | - std::map<int, QPDFXRefEntry> const& xref, | |
| 1758 | + QPDFWriter::NewObjTable const& new_obj, | |
| 1759 | 1759 | std::map<int, qpdf_offset_t> const& lengths, |
| 1760 | 1760 | QPDFWriter::ObjTable const& obj, |
| 1761 | 1761 | std::shared_ptr<Buffer>& hint_buffer, |
| ... | ... | @@ -1764,9 +1764,9 @@ QPDF::generateHintStream( |
| 1764 | 1764 | bool compressed) |
| 1765 | 1765 | { |
| 1766 | 1766 | // Populate actual hint table values |
| 1767 | - calculateHPageOffset(xref, lengths, obj); | |
| 1768 | - calculateHSharedObject(xref, lengths, obj); | |
| 1769 | - calculateHOutline(xref, lengths, obj); | |
| 1767 | + calculateHPageOffset(new_obj, lengths, obj); | |
| 1768 | + calculateHSharedObject(new_obj, lengths, obj); | |
| 1769 | + calculateHOutline(new_obj, lengths, obj); | |
| 1770 | 1770 | |
| 1771 | 1771 | // Write the hint stream itself into a compressed memory buffer. Write through a counter so we |
| 1772 | 1772 | // can get offsets. | ... | ... |
libqpdf/qpdf/QPDFWriter_private.hh
| ... | ... | @@ -15,6 +15,11 @@ struct QPDFWriter::Object |
| 15 | 15 | int object_stream{0}; |
| 16 | 16 | }; |
| 17 | 17 | |
| 18 | +struct QPDFWriter::NewObject | |
| 19 | +{ | |
| 20 | + QPDFXRefEntry xref; | |
| 21 | +}; | |
| 22 | + | |
| 18 | 23 | class QPDFWriter::ObjTable: public ::ObjTable<QPDFWriter::Object> |
| 19 | 24 | { |
| 20 | 25 | friend class QPDFWriter; |
| ... | ... | @@ -31,6 +36,11 @@ class QPDFWriter::ObjTable: public ::ObjTable<QPDFWriter::Object> |
| 31 | 36 | bool streams_empty{false}; |
| 32 | 37 | }; |
| 33 | 38 | |
| 39 | +class QPDFWriter::NewObjTable: public ::ObjTable<QPDFWriter::NewObject> | |
| 40 | +{ | |
| 41 | + friend class QPDFWriter; | |
| 42 | +}; | |
| 43 | + | |
| 34 | 44 | class QPDFWriter::Members |
| 35 | 45 | { |
| 36 | 46 | friend class QPDFWriter; |
| ... | ... | @@ -91,7 +101,7 @@ class QPDFWriter::Members |
| 91 | 101 | std::vector<QPDFObjectHandle> object_queue; |
| 92 | 102 | size_t object_queue_front{0}; |
| 93 | 103 | QPDFWriter::ObjTable obj; |
| 94 | - std::map<int, QPDFXRefEntry> xref; | |
| 104 | + QPDFWriter::NewObjTable new_obj; | |
| 95 | 105 | std::map<int, qpdf_offset_t> lengths; |
| 96 | 106 | int next_objid{1}; |
| 97 | 107 | int cur_stream_length_id{0}; | ... | ... |