Commit ccad589f7d2e732f780d7160af0b23546888fa82

Authored by m-holger
1 parent 47cf4e3a

In QPDFWriter replace map xref with new ObjTable new_obj

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
... ... @@ -439,7 +439,9 @@ class QPDFWriter
439 439  
440 440 // The following structs / classes are not part of the public API.
441 441 struct Object;
  442 + struct NewObject;
442 443 class ObjTable;
  444 + class NewObjTable;
443 445  
444 446 private:
445 447 // flags used by unparseObject
... ...
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&amp; w, HGeneric&amp; 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&lt;QPDFWriter::Object&gt;
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};
... ...