Commit ae00ee6119dcaabcebeeea4f6ec50a076eff3ca1

Authored by m-holger
1 parent ef3a8025

Replace QPDF::Writer::getObjectStreamData with getXRefTable

include/qpdf/QPDF.hh
@@ -753,18 +753,18 @@ class QPDF @@ -753,18 +753,18 @@ class QPDF
753 return qpdf.generateHintStream(new_obj, obj, hint_stream, S, O, compressed); 753 return qpdf.generateHintStream(new_obj, obj, hint_stream, S, O, compressed);
754 } 754 }
755 755
756 - static void  
757 - getObjectStreamData(QPDF& qpdf, std::map<int, int>& omap)  
758 - {  
759 - qpdf.getObjectStreamData(omap);  
760 - }  
761 -  
762 static std::vector<QPDFObjGen> 756 static std::vector<QPDFObjGen>
763 getCompressibleObjGens(QPDF& qpdf) 757 getCompressibleObjGens(QPDF& qpdf)
764 { 758 {
765 return qpdf.getCompressibleObjGens(); 759 return qpdf.getCompressibleObjGens();
766 } 760 }
767 761
  762 + static std::map<QPDFObjGen, QPDFXRefEntry> const&
  763 + getXRefTable(QPDF& qpdf)
  764 + {
  765 + return qpdf.getXRefTableInternal();
  766 + }
  767 +
768 static size_t 768 static size_t
769 tableSize(QPDF& qpdf) 769 tableSize(QPDF& qpdf)
770 { 770 {
@@ -1088,6 +1088,7 @@ class QPDF @@ -1088,6 +1088,7 @@ class QPDF
1088 1088
1089 // For QPDFWriter: 1089 // For QPDFWriter:
1090 1090
  1091 + std::map<QPDFObjGen, QPDFXRefEntry> const& getXRefTableInternal();
1091 size_t tableSize(); 1092 size_t tableSize();
1092 1093
1093 // Get lists of all objects in order according to the part of a linearized file that they belong 1094 // Get lists of all objects in order according to the part of a linearized file that they belong
@@ -1108,9 +1109,6 @@ class QPDF @@ -1108,9 +1109,6 @@ class QPDF
1108 int& O, 1109 int& O,
1109 bool compressed); 1110 bool compressed);
1110 1111
1111 - // Map object to object stream that contains it  
1112 - void getObjectStreamData(std::map<int, int>&);  
1113 -  
1114 // Get a list of objects that would be permitted in an object stream. 1112 // Get a list of objects that would be permitted in an object stream.
1115 std::vector<QPDFObjGen> getCompressibleObjGens(); 1113 std::vector<QPDFObjGen> getCompressibleObjGens();
1116 1114
libqpdf/QPDF.cc
@@ -2370,6 +2370,12 @@ QPDF::getRoot() @@ -2370,6 +2370,12 @@ QPDF::getRoot()
2370 std::map<QPDFObjGen, QPDFXRefEntry> 2370 std::map<QPDFObjGen, QPDFXRefEntry>
2371 QPDF::getXRefTable() 2371 QPDF::getXRefTable()
2372 { 2372 {
  2373 + return getXRefTableInternal();
  2374 +}
  2375 +
  2376 +std::map<QPDFObjGen, QPDFXRefEntry> const&
  2377 +QPDF::getXRefTableInternal()
  2378 +{
2373 if (!m->parsed) { 2379 if (!m->parsed) {
2374 throw std::logic_error("QPDF::getXRefTable called before parsing."); 2380 throw std::logic_error("QPDF::getXRefTable called before parsing.");
2375 } 2381 }
@@ -2390,18 +2396,6 @@ QPDF::tableSize() @@ -2390,18 +2396,6 @@ QPDF::tableSize()
2390 return toS(++max_xref); 2396 return toS(++max_xref);
2391 } 2397 }
2392 2398
2393 -void  
2394 -QPDF::getObjectStreamData(std::map<int, int>& omap)  
2395 -{  
2396 - for (auto const& iter: m->xref_table) {  
2397 - QPDFObjGen const& og = iter.first;  
2398 - QPDFXRefEntry const& entry = iter.second;  
2399 - if (entry.getType() == 2) {  
2400 - omap[og.getObj()] = entry.getObjStreamNumber();  
2401 - }  
2402 - }  
2403 -}  
2404 -  
2405 std::vector<QPDFObjGen> 2399 std::vector<QPDFObjGen>
2406 QPDF::getCompressibleObjGens() 2400 QPDF::getCompressibleObjGens()
2407 { 2401 {
libqpdf/QPDFWriter.cc
@@ -1936,12 +1936,7 @@ QPDFWriter::initializeSpecialStreams() @@ -1936,12 +1936,7 @@ QPDFWriter::initializeSpecialStreams()
1936 void 1936 void
1937 QPDFWriter::preserveObjectStreams() 1937 QPDFWriter::preserveObjectStreams()
1938 { 1938 {
1939 - std::map<int, int> omap;  
1940 - QPDF::Writer::getObjectStreamData(m->pdf, omap);  
1941 - if (omap.empty()) {  
1942 - m->obj.streams_empty = true;  
1943 - return;  
1944 - } 1939 + auto const& xref = QPDF::Writer::getXRefTable(m->pdf);
1945 // Our object_to_object_stream map has to map ObjGen -> ObjGen since we may be generating object 1940 // Our object_to_object_stream map has to map ObjGen -> ObjGen since we may be generating object
1946 // streams out of old objects that have generation numbers greater than zero. However in an 1941 // streams out of old objects that have generation numbers greater than zero. However in an
1947 // existing PDF, all object stream objects and all objects in them must have generation 0 1942 // existing PDF, all object stream objects and all objects in them must have generation 0
@@ -1949,20 +1944,45 @@ QPDFWriter::preserveObjectStreams() @@ -1949,20 +1944,45 @@ QPDFWriter::preserveObjectStreams()
1949 // that are not allowed to be in object streams. In addition to removing objects that were 1944 // that are not allowed to be in object streams. In addition to removing objects that were
1950 // erroneously included in object streams in the source PDF, it also prevents unreferenced 1945 // erroneously included in object streams in the source PDF, it also prevents unreferenced
1951 // objects from being included. 1946 // objects from being included.
1952 - std::set<QPDFObjGen> eligible;  
1953 - if (!m->preserve_unreferenced_objects) {  
1954 - std::vector<QPDFObjGen> eligible_v = QPDF::Writer::getCompressibleObjGens(m->pdf);  
1955 - eligible = std::set<QPDFObjGen>(eligible_v.begin(), eligible_v.end());  
1956 - }  
1957 - QTC::TC("qpdf", "QPDFWriter preserve object streams", m->preserve_unreferenced_objects ? 0 : 1);  
1958 - for (auto iter: omap) {  
1959 - QPDFObjGen og(iter.first, 0);  
1960 - if (eligible.count(og) || m->preserve_unreferenced_objects) {  
1961 - m->obj[iter.first].object_stream = iter.second;  
1962 - } else {  
1963 - QTC::TC("qpdf", "QPDFWriter exclude from object stream"); 1947 + auto iter = xref.cbegin();
  1948 + auto end = xref.cend();
  1949 +
  1950 + // Start by scanning for first compressed object in case we don't have any object streams to
  1951 + // process.
  1952 + for (; iter != end; ++iter) {
  1953 + if (iter->second.getType() == 2) {
  1954 + // Pdf contains object streams.
  1955 + QTC::TC(
  1956 + "qpdf",
  1957 + "QPDFWriter preserve object streams",
  1958 + m->preserve_unreferenced_objects ? 0 : 1);
  1959 +
  1960 + if (m->preserve_unreferenced_objects) {
  1961 + for (; iter != end; ++iter) {
  1962 + if (iter->second.getType() == 2) {
  1963 + m->obj[iter->first].object_stream = iter->second.getObjStreamNumber();
  1964 + }
  1965 + }
  1966 + } else {
  1967 + std::set<QPDFObjGen> eligible;
  1968 + std::vector<QPDFObjGen> eligible_v = QPDF::Writer::getCompressibleObjGens(m->pdf);
  1969 + eligible = std::set<QPDFObjGen>(eligible_v.begin(), eligible_v.end());
  1970 + for (; iter != end; ++iter) {
  1971 + if (iter->second.getType() == 2) {
  1972 + QPDFObjGen og(iter->first.getObj(), 0);
  1973 + if (eligible.count(og)) {
  1974 + m->obj[iter->first].object_stream = iter->second.getObjStreamNumber();
  1975 + } else {
  1976 + QTC::TC("qpdf", "QPDFWriter exclude from object stream");
  1977 + }
  1978 + }
  1979 + }
  1980 + }
  1981 + return;
1964 } 1982 }
1965 } 1983 }
  1984 + // No compressed objects found.
  1985 + m->obj.streams_empty = true;
1966 } 1986 }
1967 1987
1968 void 1988 void