Commit 04c203ae060458ae39253263c7dd1c603b931bf0
1 parent
b4b8b28e
Eliminate flattenScalarReferences
Showing
18 changed files
with
260 additions
and
305 deletions
ChangeLog
| 1 | +2012-12-27 Jay Berkenbilt <ejb@ql.org> | |
| 2 | + | |
| 3 | + * Removed public method QPDF::flattenScalarReferences. Instead, | |
| 4 | + just flatten the scalar references we actually need to flatten. | |
| 5 | + Flattening scalar references was a wrong decision years ago and | |
| 6 | + has occasionally caused other problems, among which were that it | |
| 7 | + caused qpdf to visit otherwise unreferenced and possibly erroneous | |
| 8 | + objects in the file when it didn't have to. | |
| 9 | + | |
| 10 | + * Removed public method QPDF::decodeStreams which was previously | |
| 11 | + used by qpdf --check but is no longer used. The decodeStreams | |
| 12 | + method could generate false positives since it would attempt to | |
| 13 | + access all objects in the file including those that were not | |
| 14 | + referenced. | |
| 15 | + | |
| 16 | + * Removed public method QPDF::trimTrailerForWrite, which was only | |
| 17 | + intended for use by QPDFWriter and which is no longer used. | |
| 18 | + | |
| 1 | 19 | 2012-12-25 Jay Berkenbilt <ejb@ql.org> |
| 2 | 20 | |
| 3 | 21 | * Allow PDF header to appear anywhere in the first 1024 bytes of | ... | ... |
TODO
| ... | ... | @@ -41,38 +41,6 @@ General |
| 41 | 41 | outlines, page labels, thumbnails, zones. There are probably |
| 42 | 42 | others. |
| 43 | 43 | |
| 44 | - * See whether it's possible to remove the call to | |
| 45 | - flattenScalarReferences. I can't easily figure out why I do it, | |
| 46 | - but removing it causes strange test failures in linearization. I | |
| 47 | - would have to study the optimization and linearization code to | |
| 48 | - figure out why I added this to begin with and what in the code | |
| 49 | - assumes it's the case. For enqueueObject and unparseChild in | |
| 50 | - QPDFWriter, simply removing the checks for indirect scalars seems | |
| 51 | - sufficient. Looking back at the branch in the apex epub | |
| 52 | - repository, before flattening scalar references, there was special | |
| 53 | - case code in QPDFWriter to avoid writing out indirect nulls. It's | |
| 54 | - still not obvious to me why I did it though. | |
| 55 | - | |
| 56 | - To pursue this, remove the call to flattenScalarReferences in | |
| 57 | - QPDFWriter.cc and disable the logic_error exceptions for indirect | |
| 58 | - scalars. Just search for flattenScalarReferences in QPDFWriter.cc | |
| 59 | - since the logic errors have comments that mention | |
| 60 | - flattenScalarReferences. Then run the test suite. Several files | |
| 61 | - that explicitly test flattening of scalar references fail, but the | |
| 62 | - indirect scalars are properly preserved and written. But then | |
| 63 | - there are some linearized files that have a bunch of unreferenced | |
| 64 | - objects that contain scalars. Need to figure out what these are | |
| 65 | - and why they're there. Maybe they're objects that used to be | |
| 66 | - stream lengths. Probably we just need to make sure don't traverse | |
| 67 | - through a stream's /Length stream when enqueueing stream | |
| 68 | - dictionaries. This could potentially happen with any object that | |
| 69 | - QPDFWriter replaces when writing out files. Such objects would be | |
| 70 | - orphaned in the newly written file. This could be fixed, but it | |
| 71 | - may not be worth fixing. | |
| 72 | - | |
| 73 | - If flattenScalarReferences is removed, a new method will be needed | |
| 74 | - for checking PDF files. | |
| 75 | - | |
| 76 | 44 | * See if we can avoid preserving unreferenced objects in object |
| 77 | 45 | streams even when preserving the object streams. |
| 78 | 46 | ... | ... |
include/qpdf/QPDF.hh
| ... | ... | @@ -352,24 +352,8 @@ class QPDF |
| 352 | 352 | void optimize(std::map<int, int> const& object_stream_data, |
| 353 | 353 | bool allow_changes = true); |
| 354 | 354 | |
| 355 | - // Replace all references to indirect objects that are "scalars" | |
| 356 | - // (i.e., things that don't have children: not arrays, streams, or | |
| 357 | - // dictionaries) with direct objects. | |
| 358 | - QPDF_DLL | |
| 359 | - void flattenScalarReferences(); | |
| 360 | - | |
| 361 | - // Decode all streams, discarding the output. Used to check | |
| 362 | - // correctness of stream encoding. | |
| 363 | - QPDF_DLL | |
| 364 | - void decodeStreams(); | |
| 365 | - | |
| 366 | 355 | // For QPDFWriter: |
| 367 | 356 | |
| 368 | - // Remove /ID, /Encrypt, and /Prev keys from the trailer | |
| 369 | - // dictionary since these are regenerated during write. | |
| 370 | - QPDF_DLL | |
| 371 | - void trimTrailerForWrite(); | |
| 372 | - | |
| 373 | 357 | // Get lists of all objects in order according to the part of a |
| 374 | 358 | // linearized file that they belong to. |
| 375 | 359 | QPDF_DLL | ... | ... |
include/qpdf/QPDFWriter.hh
| ... | ... | @@ -299,6 +299,7 @@ class QPDFWriter |
| 299 | 299 | void setDataKey(int objid); |
| 300 | 300 | int openObject(int objid = 0); |
| 301 | 301 | void closeObject(int objid); |
| 302 | + void prepareFileForWrite(); | |
| 302 | 303 | void writeStandard(); |
| 303 | 304 | void writeLinearized(); |
| 304 | 305 | void enqueuePart(std::vector<QPDFObjectHandle>& part); | ... | ... |
ispell-words
| ... | ... | @@ -206,7 +206,6 @@ debian |
| 206 | 206 | declspec |
| 207 | 207 | DecodeParms |
| 208 | 208 | decodeRow |
| 209 | -decodeStreams | |
| 210 | 209 | decrypt |
| 211 | 210 | decrypted |
| 212 | 211 | decrypter |
| ... | ... | @@ -335,7 +334,6 @@ fl |
| 335 | 334 | flate |
| 336 | 335 | FlateDecode |
| 337 | 336 | flattenPagesTree |
| 338 | -flattenScalarReferences | |
| 339 | 337 | fn |
| 340 | 338 | fname |
| 341 | 339 | fo | ... | ... |
libqpdf/QPDF.cc
| ... | ... | @@ -1860,28 +1860,6 @@ QPDF::swapObjects(int objid1, int generation1, int objid2, int generation2) |
| 1860 | 1860 | this->obj_cache[og2] = t; |
| 1861 | 1861 | } |
| 1862 | 1862 | |
| 1863 | -void | |
| 1864 | -QPDF::trimTrailerForWrite() | |
| 1865 | -{ | |
| 1866 | - // Note that removing the encryption dictionary does not interfere | |
| 1867 | - // with reading encrypted files. QPDF loads all the information | |
| 1868 | - // it needs from the encryption dictionary at the beginning and | |
| 1869 | - // never looks at it again. | |
| 1870 | - this->trailer.removeKey("/ID"); | |
| 1871 | - this->trailer.removeKey("/Encrypt"); | |
| 1872 | - this->trailer.removeKey("/Prev"); | |
| 1873 | - | |
| 1874 | - // Remove all trailer keys that potentially come from a | |
| 1875 | - // cross-reference stream | |
| 1876 | - this->trailer.removeKey("/Index"); | |
| 1877 | - this->trailer.removeKey("/W"); | |
| 1878 | - this->trailer.removeKey("/Length"); | |
| 1879 | - this->trailer.removeKey("/Filter"); | |
| 1880 | - this->trailer.removeKey("/DecodeParms"); | |
| 1881 | - this->trailer.removeKey("/Type"); | |
| 1882 | - this->trailer.removeKey("/XRefStm"); | |
| 1883 | -} | |
| 1884 | - | |
| 1885 | 1863 | std::string |
| 1886 | 1864 | QPDF::getFilename() const |
| 1887 | 1865 | { |
| ... | ... | @@ -2067,20 +2045,3 @@ QPDF::pipeStreamData(int objid, int generation, |
| 2067 | 2045 | } |
| 2068 | 2046 | pipeline->finish(); |
| 2069 | 2047 | } |
| 2070 | - | |
| 2071 | -void | |
| 2072 | -QPDF::decodeStreams() | |
| 2073 | -{ | |
| 2074 | - for (std::map<ObjGen, QPDFXRefEntry>::iterator iter = | |
| 2075 | - this->xref_table.begin(); | |
| 2076 | - iter != this->xref_table.end(); ++iter) | |
| 2077 | - { | |
| 2078 | - ObjGen const& og = (*iter).first; | |
| 2079 | - QPDFObjectHandle obj = getObjectByID(og.obj, og.gen); | |
| 2080 | - if (obj.isStream()) | |
| 2081 | - { | |
| 2082 | - Pl_Discard pl; | |
| 2083 | - obj.pipeStreamData(&pl, true, false, false); | |
| 2084 | - } | |
| 2085 | - } | |
| 2086 | -} | ... | ... |
libqpdf/QPDFWriter.cc
| ... | ... | @@ -834,16 +834,6 @@ QPDFWriter::enqueueObject(QPDFObjectHandle object) |
| 834 | 834 | { |
| 835 | 835 | // This is a place-holder object for an object stream |
| 836 | 836 | } |
| 837 | - else if (object.isScalar()) | |
| 838 | - { | |
| 839 | - // flattenScalarReferences is supposed to have removed all | |
| 840 | - // indirect scalars. | |
| 841 | - throw std::logic_error( | |
| 842 | - "INTERNAL ERROR: QPDFWriter::enqueueObject: indirect scalar: " + | |
| 843 | - std::string(this->filename) + " " + | |
| 844 | - QUtil::int_to_string(object.getObjectID()) + " " + | |
| 845 | - QUtil::int_to_string(object.getGeneration())); | |
| 846 | - } | |
| 847 | 837 | int objid = object.getObjectID(); |
| 848 | 838 | |
| 849 | 839 | if (obj_renumber.count(objid) == 0) |
| ... | ... | @@ -916,15 +906,6 @@ QPDFWriter::unparseChild(QPDFObjectHandle child, int level, int flags) |
| 916 | 906 | } |
| 917 | 907 | if (child.isIndirect()) |
| 918 | 908 | { |
| 919 | - if (child.isScalar()) | |
| 920 | - { | |
| 921 | - // flattenScalarReferences is supposed to have removed all | |
| 922 | - // indirect scalars. | |
| 923 | - throw std::logic_error( | |
| 924 | - "INTERNAL ERROR: QPDFWriter::unparseChild: indirect scalar: " + | |
| 925 | - QUtil::int_to_string(child.getObjectID()) + " " + | |
| 926 | - QUtil::int_to_string(child.getGeneration())); | |
| 927 | - } | |
| 928 | 909 | int old_id = child.getObjectID(); |
| 929 | 910 | int new_id = obj_renumber[old_id]; |
| 930 | 911 | writeString(QUtil::int_to_string(new_id)); |
| ... | ... | @@ -1648,6 +1629,117 @@ QPDFWriter::generateObjectStreams() |
| 1648 | 1629 | } |
| 1649 | 1630 | |
| 1650 | 1631 | void |
| 1632 | +QPDFWriter::prepareFileForWrite() | |
| 1633 | +{ | |
| 1634 | + // Remove keys from the trailer that necessarily have to be | |
| 1635 | + // replaced when writing the file. | |
| 1636 | + | |
| 1637 | + QPDFObjectHandle trailer = pdf.getTrailer(); | |
| 1638 | + | |
| 1639 | + // Note that removing the encryption dictionary does not interfere | |
| 1640 | + // with reading encrypted files. QPDF loads all the information | |
| 1641 | + // it needs from the encryption dictionary at the beginning and | |
| 1642 | + // never looks at it again. | |
| 1643 | + trailer.removeKey("/ID"); | |
| 1644 | + trailer.removeKey("/Encrypt"); | |
| 1645 | + trailer.removeKey("/Prev"); | |
| 1646 | + | |
| 1647 | + // Remove all trailer keys that potentially come from a | |
| 1648 | + // cross-reference stream | |
| 1649 | + trailer.removeKey("/Index"); | |
| 1650 | + trailer.removeKey("/W"); | |
| 1651 | + trailer.removeKey("/Length"); | |
| 1652 | + trailer.removeKey("/Filter"); | |
| 1653 | + trailer.removeKey("/DecodeParms"); | |
| 1654 | + trailer.removeKey("/Type"); | |
| 1655 | + trailer.removeKey("/XRefStm"); | |
| 1656 | + | |
| 1657 | + // Do a traversal of the entire PDF file structure replacing all | |
| 1658 | + // indirect objects that QPDFWriter wants to be direct. This | |
| 1659 | + // includes stream lengths, stream filtering parameters, and | |
| 1660 | + // document extension level information. Also replace all | |
| 1661 | + // indirect null references with direct nulls. This way, the only | |
| 1662 | + // indirect nulls queued for output will be object stream place | |
| 1663 | + // holders. | |
| 1664 | + | |
| 1665 | + std::list<QPDFObjectHandle> queue; | |
| 1666 | + queue.push_back(pdf.getTrailer()); | |
| 1667 | + std::set<int> visited; | |
| 1668 | + | |
| 1669 | + while (! queue.empty()) | |
| 1670 | + { | |
| 1671 | + QPDFObjectHandle node = queue.front(); | |
| 1672 | + queue.pop_front(); | |
| 1673 | + if (node.isIndirect()) | |
| 1674 | + { | |
| 1675 | + if (visited.count(node.getObjectID()) > 0) | |
| 1676 | + { | |
| 1677 | + continue; | |
| 1678 | + } | |
| 1679 | + visited.insert(node.getObjectID()); | |
| 1680 | + } | |
| 1681 | + | |
| 1682 | + if (node.isArray()) | |
| 1683 | + { | |
| 1684 | + int nitems = node.getArrayNItems(); | |
| 1685 | + for (int i = 0; i < nitems; ++i) | |
| 1686 | + { | |
| 1687 | + QPDFObjectHandle oh = node.getArrayItem(i); | |
| 1688 | + if (oh.isIndirect() && oh.isNull()) | |
| 1689 | + { | |
| 1690 | + QTC::TC("qpdf", "QPDFWriter flatten array null"); | |
| 1691 | + oh.makeDirect(); | |
| 1692 | + node.setArrayItem(i, oh); | |
| 1693 | + } | |
| 1694 | + else if (! oh.isScalar()) | |
| 1695 | + { | |
| 1696 | + queue.push_back(oh); | |
| 1697 | + } | |
| 1698 | + } | |
| 1699 | + } | |
| 1700 | + else if (node.isDictionary() || node.isStream()) | |
| 1701 | + { | |
| 1702 | + bool is_stream = false; | |
| 1703 | + QPDFObjectHandle dict = node; | |
| 1704 | + if (node.isStream()) | |
| 1705 | + { | |
| 1706 | + is_stream = true; | |
| 1707 | + dict = node.getDict(); | |
| 1708 | + } | |
| 1709 | + | |
| 1710 | + std::set<std::string> keys = dict.getKeys(); | |
| 1711 | + for (std::set<std::string>::iterator iter = keys.begin(); | |
| 1712 | + iter != keys.end(); ++iter) | |
| 1713 | + { | |
| 1714 | + std::string const& key = *iter; | |
| 1715 | + QPDFObjectHandle oh = dict.getKey(key); | |
| 1716 | + bool add_to_queue = true; | |
| 1717 | + if (oh.isIndirect()) | |
| 1718 | + { | |
| 1719 | + if (is_stream) | |
| 1720 | + { | |
| 1721 | + if ((key == "/Length") || | |
| 1722 | + (key == "/Filter") || | |
| 1723 | + (key == "/DecodeParms")) | |
| 1724 | + { | |
| 1725 | + QTC::TC("qpdf", "QPDF make stream key direct"); | |
| 1726 | + add_to_queue = false; | |
| 1727 | + oh.makeDirect(); | |
| 1728 | + dict.replaceKey(key, oh); | |
| 1729 | + } | |
| 1730 | + } | |
| 1731 | + } | |
| 1732 | + | |
| 1733 | + if (add_to_queue) | |
| 1734 | + { | |
| 1735 | + queue.push_back(oh); | |
| 1736 | + } | |
| 1737 | + } | |
| 1738 | + } | |
| 1739 | + } | |
| 1740 | +} | |
| 1741 | + | |
| 1742 | +void | |
| 1651 | 1743 | QPDFWriter::write() |
| 1652 | 1744 | { |
| 1653 | 1745 | // Do preliminary setup |
| ... | ... | @@ -1785,8 +1877,7 @@ QPDFWriter::write() |
| 1785 | 1877 | |
| 1786 | 1878 | generateID(); |
| 1787 | 1879 | |
| 1788 | - pdf.trimTrailerForWrite(); | |
| 1789 | - pdf.flattenScalarReferences(); | |
| 1880 | + prepareFileForWrite(); | |
| 1790 | 1881 | |
| 1791 | 1882 | if (this->linearized) |
| 1792 | 1883 | { | ... | ... |
libqpdf/QPDF_optimization.cc
| ... | ... | @@ -59,103 +59,6 @@ QPDF::ObjUser::operator<(ObjUser const& rhs) const |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | 61 | void |
| 62 | -QPDF::flattenScalarReferences() | |
| 63 | -{ | |
| 64 | - // Do a traversal of the entire PDF file structure replacing all | |
| 65 | - // indirect objects that are not arrays, streams, or dictionaries | |
| 66 | - // with direct objects. | |
| 67 | - | |
| 68 | - std::list<QPDFObjectHandle> queue; | |
| 69 | - queue.push_back(this->trailer); | |
| 70 | - std::set<ObjGen> visited; | |
| 71 | - | |
| 72 | - // Add every object in the xref table to the queue. This ensures | |
| 73 | - // that we flatten scalar references in unreferenced objects. | |
| 74 | - // This becomes important if we are preserving object streams in a | |
| 75 | - // file that has unreferenced objects in its object streams. (See | |
| 76 | - // QPDF bug 2974522 at SourceForge.) | |
| 77 | - for (std::map<ObjGen, QPDFXRefEntry>::iterator iter = | |
| 78 | - this->xref_table.begin(); | |
| 79 | - iter != this->xref_table.end(); ++iter) | |
| 80 | - { | |
| 81 | - ObjGen const& og = (*iter).first; | |
| 82 | - queue.push_back(getObjectByID(og.obj, og.gen)); | |
| 83 | - } | |
| 84 | - | |
| 85 | - while (! queue.empty()) | |
| 86 | - { | |
| 87 | - QPDFObjectHandle node = queue.front(); | |
| 88 | - queue.pop_front(); | |
| 89 | - if (node.isIndirect()) | |
| 90 | - { | |
| 91 | - ObjGen og(node.getObjectID(), node.getGeneration()); | |
| 92 | - if (visited.count(og) > 0) | |
| 93 | - { | |
| 94 | - continue; | |
| 95 | - } | |
| 96 | - visited.insert(og); | |
| 97 | - } | |
| 98 | - | |
| 99 | - if (node.isArray()) | |
| 100 | - { | |
| 101 | - int nitems = node.getArrayNItems(); | |
| 102 | - for (int i = 0; i < nitems; ++i) | |
| 103 | - { | |
| 104 | - QPDFObjectHandle oh = node.getArrayItem(i); | |
| 105 | - if (oh.isScalar()) | |
| 106 | - { | |
| 107 | - if (oh.isIndirect()) | |
| 108 | - { | |
| 109 | - QTC::TC("qpdf", "QPDF opt flatten array scalar"); | |
| 110 | - oh.makeDirect(); | |
| 111 | - node.setArrayItem(i, oh); | |
| 112 | - } | |
| 113 | - } | |
| 114 | - else | |
| 115 | - { | |
| 116 | - queue.push_back(oh); | |
| 117 | - } | |
| 118 | - } | |
| 119 | - } | |
| 120 | - else if (node.isDictionary() || node.isStream()) | |
| 121 | - { | |
| 122 | - QPDFObjectHandle dict = node; | |
| 123 | - if (node.isStream()) | |
| 124 | - { | |
| 125 | - dict = node.getDict(); | |
| 126 | - } | |
| 127 | - std::set<std::string> keys = dict.getKeys(); | |
| 128 | - for (std::set<std::string>::iterator iter = keys.begin(); | |
| 129 | - iter != keys.end(); ++iter) | |
| 130 | - { | |
| 131 | - std::string const& key = *iter; | |
| 132 | - QPDFObjectHandle oh = dict.getKey(key); | |
| 133 | - if (oh.isNull()) | |
| 134 | - { | |
| 135 | - // QPDF_Dictionary.getKeys() never returns null | |
| 136 | - // keys. | |
| 137 | - throw std::logic_error( | |
| 138 | - "INTERNAL ERROR: dictionary with null key found"); | |
| 139 | - } | |
| 140 | - else if (oh.isScalar()) | |
| 141 | - { | |
| 142 | - if (oh.isIndirect()) | |
| 143 | - { | |
| 144 | - QTC::TC("qpdf", "QPDF opt flatten dict scalar"); | |
| 145 | - oh.makeDirect(); | |
| 146 | - dict.replaceKey(key, oh); | |
| 147 | - } | |
| 148 | - } | |
| 149 | - else | |
| 150 | - { | |
| 151 | - queue.push_back(oh); | |
| 152 | - } | |
| 153 | - } | |
| 154 | - } | |
| 155 | - } | |
| 156 | -} | |
| 157 | - | |
| 158 | -void | |
| 159 | 62 | QPDF::optimize(std::map<int, int> const& object_stream_data, |
| 160 | 63 | bool allow_changes) |
| 161 | 64 | { |
| ... | ... | @@ -304,9 +207,7 @@ QPDF::pushInheritedAttributesToPageInternal( |
| 304 | 207 | } |
| 305 | 208 | else |
| 306 | 209 | { |
| 307 | - // Don't defeat flattenScalarReferences which | |
| 308 | - // would have already been called by this | |
| 309 | - // time. | |
| 210 | + // It's okay to copy scalars. | |
| 310 | 211 | QTC::TC("qpdf", "QPDF opt inherited scalar"); |
| 311 | 212 | } |
| 312 | 213 | } | ... | ... |
qpdf/qpdf.cc
| ... | ... | @@ -8,6 +8,7 @@ |
| 8 | 8 | #include <qpdf/QUtil.hh> |
| 9 | 9 | #include <qpdf/QTC.hh> |
| 10 | 10 | #include <qpdf/Pl_StdioFile.hh> |
| 11 | +#include <qpdf/Pl_Discard.hh> | |
| 11 | 12 | #include <qpdf/PointerHolder.hh> |
| 12 | 13 | |
| 13 | 14 | #include <qpdf/QPDF.hh> |
| ... | ... | @@ -1381,12 +1382,14 @@ int main(int argc, char* argv[]) |
| 1381 | 1382 | else |
| 1382 | 1383 | { |
| 1383 | 1384 | std::cout << "File is not linearized\n"; |
| 1384 | - // calling flattenScalarReferences causes full | |
| 1385 | - // traversal of file, so any structural errors | |
| 1386 | - // would be exposed. | |
| 1387 | - pdf.flattenScalarReferences(); | |
| 1388 | - // Also explicitly decode all streams. | |
| 1389 | - pdf.decodeStreams(); | |
| 1385 | + // Write the file no nowhere, uncompressing | |
| 1386 | + // streams. This causes full file traversal | |
| 1387 | + // and decoding of all streams we can decode. | |
| 1388 | + QPDFWriter w(pdf); | |
| 1389 | + Pl_Discard discard; | |
| 1390 | + w.setOutputPipeline(&discard); | |
| 1391 | + w.setStreamDataMode(qpdf_s_uncompress); | |
| 1392 | + w.write(); | |
| 1390 | 1393 | okay = true; |
| 1391 | 1394 | } |
| 1392 | 1395 | } | ... | ... |
qpdf/qpdf.testcov
| ... | ... | @@ -29,8 +29,7 @@ QPDF lin outlines in part 1 |
| 29 | 29 | QPDF lin nshared_total > nshared_first_page 1 |
| 30 | 30 | QPDF lin part 8 empty 1 |
| 31 | 31 | QPDF lin check shared past first page 0 |
| 32 | -QPDF opt flatten array scalar 0 | |
| 33 | -QPDF opt flatten dict scalar 0 | |
| 32 | +QPDFWriter flatten array null 0 | |
| 34 | 33 | main QTest implicit 0 |
| 35 | 34 | main QTest indirect 1 |
| 36 | 35 | main QTest null 0 |
| ... | ... | @@ -244,3 +243,4 @@ QPDFWriter extra header text no newline 0 |
| 244 | 243 | QPDFWriter extra header text add newline 0 |
| 245 | 244 | QPDF bogus 0 offset 0 |
| 246 | 245 | QPDF global offset 0 |
| 246 | +QPDF make stream key direct 0 | ... | ... |
qpdf/qtest/qpdf/good13.qdf
| ... | ... | @@ -18,7 +18,7 @@ endobj |
| 18 | 18 | <01020300040560> |
| 19 | 19 | (AB) |
| 20 | 20 | ] |
| 21 | - /indirect (hello) | |
| 21 | + /indirect 4 0 R | |
| 22 | 22 | /nesting << |
| 23 | 23 | /a [ |
| 24 | 24 | 1 |
| ... | ... | @@ -58,17 +58,22 @@ endobj |
| 58 | 58 | << |
| 59 | 59 | /Count 1 |
| 60 | 60 | /Kids [ |
| 61 | - 4 0 R | |
| 61 | + 5 0 R | |
| 62 | 62 | ] |
| 63 | 63 | /Type /Pages |
| 64 | 64 | >> |
| 65 | 65 | endobj |
| 66 | 66 | |
| 67 | +%% Original object ID: 8 0 | |
| 68 | +4 0 obj | |
| 69 | +(hello) | |
| 70 | +endobj | |
| 71 | + | |
| 67 | 72 | %% Page 1 |
| 68 | 73 | %% Original object ID: 3 0 |
| 69 | -4 0 obj | |
| 74 | +5 0 obj | |
| 70 | 75 | << |
| 71 | - /Contents 5 0 R | |
| 76 | + /Contents 6 0 R | |
| 72 | 77 | /MediaBox [ |
| 73 | 78 | 0 |
| 74 | 79 | 0 |
| ... | ... | @@ -78,9 +83,9 @@ endobj |
| 78 | 83 | /Parent 3 0 R |
| 79 | 84 | /Resources << |
| 80 | 85 | /Font << |
| 81 | - /F1 7 0 R | |
| 86 | + /F1 8 0 R | |
| 82 | 87 | >> |
| 83 | - /ProcSet 8 0 R | |
| 88 | + /ProcSet 9 0 R | |
| 84 | 89 | >> |
| 85 | 90 | /Type /Page |
| 86 | 91 | >> |
| ... | ... | @@ -88,9 +93,9 @@ endobj |
| 88 | 93 | |
| 89 | 94 | %% Contents for page 1 |
| 90 | 95 | %% Original object ID: 4 0 |
| 91 | -5 0 obj | |
| 96 | +6 0 obj | |
| 92 | 97 | << |
| 93 | - /Length 6 0 R | |
| 98 | + /Length 7 0 R | |
| 94 | 99 | >> |
| 95 | 100 | stream |
| 96 | 101 | BT |
| ... | ... | @@ -101,12 +106,12 @@ ET |
| 101 | 106 | endstream |
| 102 | 107 | endobj |
| 103 | 108 | |
| 104 | -6 0 obj | |
| 109 | +7 0 obj | |
| 105 | 110 | 44 |
| 106 | 111 | endobj |
| 107 | 112 | |
| 108 | 113 | %% Original object ID: 6 0 |
| 109 | -7 0 obj | |
| 114 | +8 0 obj | |
| 110 | 115 | << |
| 111 | 116 | /BaseFont /Helvetica |
| 112 | 117 | /Encoding /WinAnsiEncoding |
| ... | ... | @@ -117,7 +122,7 @@ endobj |
| 117 | 122 | endobj |
| 118 | 123 | |
| 119 | 124 | %% Original object ID: 5 0 |
| 120 | -8 0 obj | |
| 125 | +9 0 obj | |
| 121 | 126 | [ |
| 122 | 127 | |
| 123 | 128 | /Text |
| ... | ... | @@ -125,22 +130,23 @@ endobj |
| 125 | 130 | endobj |
| 126 | 131 | |
| 127 | 132 | xref |
| 128 | -0 9 | |
| 133 | +0 10 | |
| 129 | 134 | 0000000000 65535 f |
| 130 | 135 | 0000000052 00000 n |
| 131 | 136 | 0000000133 00000 n |
| 132 | -0000000578 00000 n | |
| 133 | -0000000687 00000 n | |
| 134 | -0000000929 00000 n | |
| 135 | -0000001028 00000 n | |
| 136 | -0000001074 00000 n | |
| 137 | -0000001219 00000 n | |
| 137 | +0000000576 00000 n | |
| 138 | +0000000675 00000 n | |
| 139 | +0000000736 00000 n | |
| 140 | +0000000978 00000 n | |
| 141 | +0000001077 00000 n | |
| 142 | +0000001123 00000 n | |
| 143 | +0000001268 00000 n | |
| 138 | 144 | trailer << |
| 139 | 145 | /QTest 2 0 R |
| 140 | 146 | /Root 1 0 R |
| 141 | - /Size 9 | |
| 147 | + /Size 10 | |
| 142 | 148 | /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] |
| 143 | 149 | >> |
| 144 | 150 | startxref |
| 145 | -1254 | |
| 151 | +1303 | |
| 146 | 152 | %%EOF | ... | ... |
qpdf/qtest/qpdf/good5.qdf
| ... | ... | @@ -5,17 +5,22 @@ |
| 5 | 5 | %% Original object ID: 1 0 |
| 6 | 6 | 1 0 obj |
| 7 | 7 | << |
| 8 | - /Pages 2 0 R | |
| 8 | + /Pages 3 0 R | |
| 9 | 9 | /Type /Catalog |
| 10 | 10 | >> |
| 11 | 11 | endobj |
| 12 | 12 | |
| 13 | -%% Original object ID: 2 0 | |
| 13 | +%% Original object ID: 7 0 | |
| 14 | 14 | 2 0 obj |
| 15 | +true | |
| 16 | +endobj | |
| 17 | + | |
| 18 | +%% Original object ID: 2 0 | |
| 19 | +3 0 obj | |
| 15 | 20 | << |
| 16 | 21 | /Count 1 |
| 17 | 22 | /Kids [ |
| 18 | - 3 0 R | |
| 23 | + 4 0 R | |
| 19 | 24 | ] |
| 20 | 25 | /Type /Pages |
| 21 | 26 | >> |
| ... | ... | @@ -23,21 +28,21 @@ endobj |
| 23 | 28 | |
| 24 | 29 | %% Page 1 |
| 25 | 30 | %% Original object ID: 3 0 |
| 26 | -3 0 obj | |
| 31 | +4 0 obj | |
| 27 | 32 | << |
| 28 | - /Contents 4 0 R | |
| 33 | + /Contents 5 0 R | |
| 29 | 34 | /MediaBox [ |
| 30 | 35 | 0 |
| 31 | 36 | 0 |
| 32 | 37 | 612 |
| 33 | 38 | 792 |
| 34 | 39 | ] |
| 35 | - /Parent 2 0 R | |
| 40 | + /Parent 3 0 R | |
| 36 | 41 | /Resources << |
| 37 | 42 | /Font << |
| 38 | - /F1 6 0 R | |
| 43 | + /F1 7 0 R | |
| 39 | 44 | >> |
| 40 | - /ProcSet 7 0 R | |
| 45 | + /ProcSet 8 0 R | |
| 41 | 46 | >> |
| 42 | 47 | /Type /Page |
| 43 | 48 | >> |
| ... | ... | @@ -45,9 +50,9 @@ endobj |
| 45 | 50 | |
| 46 | 51 | %% Contents for page 1 |
| 47 | 52 | %% Original object ID: 4 0 |
| 48 | -4 0 obj | |
| 53 | +5 0 obj | |
| 49 | 54 | << |
| 50 | - /Length 5 0 R | |
| 55 | + /Length 6 0 R | |
| 51 | 56 | >> |
| 52 | 57 | stream |
| 53 | 58 | BT |
| ... | ... | @@ -58,12 +63,12 @@ ET |
| 58 | 63 | endstream |
| 59 | 64 | endobj |
| 60 | 65 | |
| 61 | -5 0 obj | |
| 66 | +6 0 obj | |
| 62 | 67 | 44 |
| 63 | 68 | endobj |
| 64 | 69 | |
| 65 | 70 | %% Original object ID: 6 0 |
| 66 | -6 0 obj | |
| 71 | +7 0 obj | |
| 67 | 72 | << |
| 68 | 73 | /BaseFont /Helvetica |
| 69 | 74 | /Encoding /WinAnsiEncoding |
| ... | ... | @@ -74,7 +79,7 @@ endobj |
| 74 | 79 | endobj |
| 75 | 80 | |
| 76 | 81 | %% Original object ID: 5 0 |
| 77 | -7 0 obj | |
| 82 | +8 0 obj | |
| 78 | 83 | [ |
| 79 | 84 | |
| 80 | 85 | /Text |
| ... | ... | @@ -82,21 +87,22 @@ endobj |
| 82 | 87 | endobj |
| 83 | 88 | |
| 84 | 89 | xref |
| 85 | -0 8 | |
| 90 | +0 9 | |
| 86 | 91 | 0000000000 65535 f |
| 87 | 92 | 0000000052 00000 n |
| 88 | 93 | 0000000133 00000 n |
| 89 | -0000000242 00000 n | |
| 90 | -0000000484 00000 n | |
| 91 | -0000000583 00000 n | |
| 92 | -0000000629 00000 n | |
| 93 | -0000000774 00000 n | |
| 94 | +0000000181 00000 n | |
| 95 | +0000000290 00000 n | |
| 96 | +0000000532 00000 n | |
| 97 | +0000000631 00000 n | |
| 98 | +0000000677 00000 n | |
| 99 | +0000000822 00000 n | |
| 94 | 100 | trailer << |
| 95 | - /QTest true | |
| 101 | + /QTest 2 0 R | |
| 96 | 102 | /Root 1 0 R |
| 97 | - /Size 8 | |
| 103 | + /Size 9 | |
| 98 | 104 | /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] |
| 99 | 105 | >> |
| 100 | 106 | startxref |
| 101 | -809 | |
| 107 | +857 | |
| 102 | 108 | %%EOF | ... | ... |
qpdf/qtest/qpdf/good8.qdf
| ... | ... | @@ -5,17 +5,22 @@ |
| 5 | 5 | %% Original object ID: 1 0 |
| 6 | 6 | 1 0 obj |
| 7 | 7 | << |
| 8 | - /Pages 2 0 R | |
| 8 | + /Pages 3 0 R | |
| 9 | 9 | /Type /Catalog |
| 10 | 10 | >> |
| 11 | 11 | endobj |
| 12 | 12 | |
| 13 | -%% Original object ID: 2 0 | |
| 13 | +%% Original object ID: 7 0 | |
| 14 | 14 | 2 0 obj |
| 15 | +3.14159 | |
| 16 | +endobj | |
| 17 | + | |
| 18 | +%% Original object ID: 2 0 | |
| 19 | +3 0 obj | |
| 15 | 20 | << |
| 16 | 21 | /Count 1 |
| 17 | 22 | /Kids [ |
| 18 | - 3 0 R | |
| 23 | + 4 0 R | |
| 19 | 24 | ] |
| 20 | 25 | /Type /Pages |
| 21 | 26 | >> |
| ... | ... | @@ -23,21 +28,21 @@ endobj |
| 23 | 28 | |
| 24 | 29 | %% Page 1 |
| 25 | 30 | %% Original object ID: 3 0 |
| 26 | -3 0 obj | |
| 31 | +4 0 obj | |
| 27 | 32 | << |
| 28 | - /Contents 4 0 R | |
| 33 | + /Contents 5 0 R | |
| 29 | 34 | /MediaBox [ |
| 30 | 35 | 0 |
| 31 | 36 | 0 |
| 32 | 37 | 612 |
| 33 | 38 | 792 |
| 34 | 39 | ] |
| 35 | - /Parent 2 0 R | |
| 40 | + /Parent 3 0 R | |
| 36 | 41 | /Resources << |
| 37 | 42 | /Font << |
| 38 | - /F1 6 0 R | |
| 43 | + /F1 7 0 R | |
| 39 | 44 | >> |
| 40 | - /ProcSet 7 0 R | |
| 45 | + /ProcSet 8 0 R | |
| 41 | 46 | >> |
| 42 | 47 | /Type /Page |
| 43 | 48 | >> |
| ... | ... | @@ -45,9 +50,9 @@ endobj |
| 45 | 50 | |
| 46 | 51 | %% Contents for page 1 |
| 47 | 52 | %% Original object ID: 4 0 |
| 48 | -4 0 obj | |
| 53 | +5 0 obj | |
| 49 | 54 | << |
| 50 | - /Length 5 0 R | |
| 55 | + /Length 6 0 R | |
| 51 | 56 | >> |
| 52 | 57 | stream |
| 53 | 58 | BT |
| ... | ... | @@ -58,12 +63,12 @@ ET |
| 58 | 63 | endstream |
| 59 | 64 | endobj |
| 60 | 65 | |
| 61 | -5 0 obj | |
| 66 | +6 0 obj | |
| 62 | 67 | 44 |
| 63 | 68 | endobj |
| 64 | 69 | |
| 65 | 70 | %% Original object ID: 6 0 |
| 66 | -6 0 obj | |
| 71 | +7 0 obj | |
| 67 | 72 | << |
| 68 | 73 | /BaseFont /Helvetica |
| 69 | 74 | /Encoding /WinAnsiEncoding |
| ... | ... | @@ -74,7 +79,7 @@ endobj |
| 74 | 79 | endobj |
| 75 | 80 | |
| 76 | 81 | %% Original object ID: 5 0 |
| 77 | -7 0 obj | |
| 82 | +8 0 obj | |
| 78 | 83 | [ |
| 79 | 84 | |
| 80 | 85 | /Text |
| ... | ... | @@ -82,21 +87,22 @@ endobj |
| 82 | 87 | endobj |
| 83 | 88 | |
| 84 | 89 | xref |
| 85 | -0 8 | |
| 90 | +0 9 | |
| 86 | 91 | 0000000000 65535 f |
| 87 | 92 | 0000000052 00000 n |
| 88 | 93 | 0000000133 00000 n |
| 89 | -0000000242 00000 n | |
| 90 | -0000000484 00000 n | |
| 91 | -0000000583 00000 n | |
| 92 | -0000000629 00000 n | |
| 93 | -0000000774 00000 n | |
| 94 | +0000000184 00000 n | |
| 95 | +0000000293 00000 n | |
| 96 | +0000000535 00000 n | |
| 97 | +0000000634 00000 n | |
| 98 | +0000000680 00000 n | |
| 99 | +0000000825 00000 n | |
| 94 | 100 | trailer << |
| 95 | - /QTest 3.14159 | |
| 101 | + /QTest 2 0 R | |
| 96 | 102 | /Root 1 0 R |
| 97 | - /Size 8 | |
| 103 | + /Size 9 | |
| 98 | 104 | /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] |
| 99 | 105 | >> |
| 100 | 106 | startxref |
| 101 | -809 | |
| 107 | +860 | |
| 102 | 108 | %%EOF | ... | ... |
qpdf/qtest/qpdf/lin-special.disable.exp
No preview for this file type
qpdf/qtest/qpdf/lin-special.generate.exp
No preview for this file type
qpdf/qtest/qpdf/lin-special.preserve.exp
No preview for this file type
qpdf/qtest/qpdf/test4-1.qdf
| ... | ... | @@ -39,8 +39,8 @@ endobj |
| 39 | 39 | << |
| 40 | 40 | /A 5 0 R |
| 41 | 41 | /B 6 0 R |
| 42 | - /Subject (Subject) | |
| 43 | - /Title (Some Title Is Here) | |
| 42 | + /Subject 7 0 R | |
| 43 | + /Title 8 0 R | |
| 44 | 44 | >> |
| 45 | 45 | endobj |
| 46 | 46 | |
| ... | ... | @@ -49,7 +49,7 @@ endobj |
| 49 | 49 | << |
| 50 | 50 | /Count 1 |
| 51 | 51 | /Kids [ |
| 52 | - 7 0 R | |
| 52 | + 9 0 R | |
| 53 | 53 | ] |
| 54 | 54 | /Type /Pages |
| 55 | 55 | >> |
| ... | ... | @@ -72,11 +72,21 @@ endobj |
| 72 | 72 | >> |
| 73 | 73 | endobj |
| 74 | 74 | |
| 75 | +%% Original object ID: 10 0 | |
| 76 | +7 0 obj | |
| 77 | +(Subject) | |
| 78 | +endobj | |
| 79 | + | |
| 80 | +%% Original object ID: 9 0 | |
| 81 | +8 0 obj | |
| 82 | +(Some Title Is Here) | |
| 83 | +endobj | |
| 84 | + | |
| 75 | 85 | %% Page 1 |
| 76 | 86 | %% Original object ID: 3 0 |
| 77 | -7 0 obj | |
| 87 | +9 0 obj | |
| 78 | 88 | << |
| 79 | - /Contents 8 0 R | |
| 89 | + /Contents 10 0 R | |
| 80 | 90 | /MediaBox [ |
| 81 | 91 | 0 |
| 82 | 92 | 0 |
| ... | ... | @@ -86,9 +96,9 @@ endobj |
| 86 | 96 | /Parent 4 0 R |
| 87 | 97 | /Resources << |
| 88 | 98 | /Font << |
| 89 | - /F1 10 0 R | |
| 99 | + /F1 12 0 R | |
| 90 | 100 | >> |
| 91 | - /ProcSet 11 0 R | |
| 101 | + /ProcSet 13 0 R | |
| 92 | 102 | >> |
| 93 | 103 | /Type /Page |
| 94 | 104 | >> |
| ... | ... | @@ -96,9 +106,9 @@ endobj |
| 96 | 106 | |
| 97 | 107 | %% Contents for page 1 |
| 98 | 108 | %% Original object ID: 4 0 |
| 99 | -8 0 obj | |
| 109 | +10 0 obj | |
| 100 | 110 | << |
| 101 | - /Length 9 0 R | |
| 111 | + /Length 11 0 R | |
| 102 | 112 | >> |
| 103 | 113 | stream |
| 104 | 114 | BT |
| ... | ... | @@ -109,12 +119,12 @@ ET |
| 109 | 119 | endstream |
| 110 | 120 | endobj |
| 111 | 121 | |
| 112 | -9 0 obj | |
| 122 | +11 0 obj | |
| 113 | 123 | 44 |
| 114 | 124 | endobj |
| 115 | 125 | |
| 116 | 126 | %% Original object ID: 6 0 |
| 117 | -10 0 obj | |
| 127 | +12 0 obj | |
| 118 | 128 | << |
| 119 | 129 | /BaseFont /Helvetica |
| 120 | 130 | /Encoding /WinAnsiEncoding |
| ... | ... | @@ -125,7 +135,7 @@ endobj |
| 125 | 135 | endobj |
| 126 | 136 | |
| 127 | 137 | %% Original object ID: 7 0 |
| 128 | -11 0 obj | |
| 138 | +13 0 obj | |
| 129 | 139 | [ |
| 130 | 140 | |
| 131 | 141 | /Text |
| ... | ... | @@ -133,26 +143,28 @@ endobj |
| 133 | 143 | endobj |
| 134 | 144 | |
| 135 | 145 | xref |
| 136 | -0 12 | |
| 146 | +0 14 | |
| 137 | 147 | 0000000000 65535 f |
| 138 | 148 | 0000000052 00000 n |
| 139 | 149 | 0000000134 00000 n |
| 140 | 150 | 0000000353 00000 n |
| 141 | -0000000475 00000 n | |
| 142 | -0000000575 00000 n | |
| 143 | -0000000635 00000 n | |
| 144 | -0000000714 00000 n | |
| 145 | -0000000958 00000 n | |
| 146 | -0000001057 00000 n | |
| 147 | -0000001103 00000 n | |
| 148 | -0000001249 00000 n | |
| 151 | +0000000456 00000 n | |
| 152 | +0000000556 00000 n | |
| 153 | +0000000616 00000 n | |
| 154 | +0000000686 00000 n | |
| 155 | +0000000739 00000 n | |
| 156 | +0000000813 00000 n | |
| 157 | +0000001058 00000 n | |
| 158 | +0000001159 00000 n | |
| 159 | +0000001206 00000 n | |
| 160 | +0000001352 00000 n | |
| 149 | 161 | trailer << |
| 150 | 162 | /Info 2 0 R |
| 151 | 163 | /QTest 3 0 R |
| 152 | 164 | /Root 1 0 R |
| 153 | - /Size 12 | |
| 165 | + /Size 14 | |
| 154 | 166 | /ID [<c61bd35bada064f61e0a56aa9588064e><31415926535897932384626433832795>] |
| 155 | 167 | >> |
| 156 | 168 | startxref |
| 157 | -1285 | |
| 169 | +1388 | |
| 158 | 170 | %%EOF | ... | ... |
qpdf/qtest/qpdf/unreferenced-indirect-scalar.out
No preview for this file type