Commit feafcc4e88798626c80840797822efbf55722716

Authored by Jay Berkenbilt
1 parent a0dbb71a

C API: add several stream functions (fixes #596)

ChangeLog
1 1 2021-12-17 Jay Berkenbilt <ejb@ql.org>
2 2  
  3 + * C API: add functions for working with stream data. Search for
  4 + "STREAM FUNCTIONS" in qpdf-c.h. Fixes #596.
  5 +
3 6 * QPDFObjectHandle object types have been moved from
4 7 QPDFObject::object_type_e to qpdf_object_type_e (defined in
5 8 Constants.h). Old values are available for backward compatibility.
... ...
include/qpdf/qpdf-c.h
... ... @@ -129,7 +129,9 @@ extern &quot;C&quot; {
129 129 qpdf_data qpdf_init();
130 130  
131 131 /* Pass a pointer to the qpdf_data pointer created by qpdf_init to
132   - * clean up resources.
  132 + * clean up resources. This does not include buffers initialized
  133 + * by functions that return stream data but it otherwise includes
  134 + * all data associated with the QPDF object or any object handles.
133 135 */
134 136 QPDF_DLL
135 137 void qpdf_cleanup(qpdf_data* qpdf);
... ... @@ -752,6 +754,15 @@ extern &quot;C&quot; {
752 754 QPDF_DLL
753 755 qpdf_oh qpdf_oh_new_dictionary(qpdf_data qpdf);
754 756  
  757 + /* Create a new stream. Use qpdf_oh_get_dict to get (and
  758 + * subsequently modify) the stream dictionary if needed. See
  759 + * comments in QPDFObjectHandle.hh for newStream() for additional
  760 + * notes. You must call qpdf_oh_replace_stream_data to provide
  761 + * data for the stream. See STREAM FUNCTIONS below.
  762 + */
  763 + QPDF_DLL
  764 + qpdf_oh qpdf_oh_new_stream(qpdf_data qpdf);
  765 +
755 766 QPDF_DLL
756 767 void qpdf_oh_make_direct(qpdf_data qpdf, qpdf_oh oh);
757 768  
... ... @@ -789,6 +800,67 @@ extern &quot;C&quot; {
789 800 QPDF_DLL
790 801 char const* qpdf_oh_unparse_binary(qpdf_data qpdf, qpdf_oh oh);
791 802  
  803 + /* Note about foreign objects: the C API does not have enough
  804 + * information in the value of a qpdf_oh to know what QPDF object
  805 + * it belongs to. To uniquely specify a qpdf object handle from a
  806 + * specific qpdf_data instance, you always pair the qpdf_oh with
  807 + * the correct qpdf_data. Otherwise, you are likely to get
  808 + * completely the wrong object if you are not lucky enough to get
  809 + * an error about the object being invalid.
  810 + */
  811 +
  812 + /* Copy foreign object: the qpdf_oh returned belongs to `qpdf`,
  813 + * while `foreign_oh` belongs to `other_qpdf`.
  814 + */
  815 + QPDF_DLL
  816 + qpdf_oh qpdf_oh_copy_foreign_object(
  817 + qpdf_data qpdf, qpdf_data other_qpdf, qpdf_oh foreign_oh);
  818 +
  819 + /* STREAM FUNCTIONS */
  820 +
  821 + /* These functions provide basic access to streams and stream
  822 + * data. They are not as comprehensive as what is in
  823 + * QPDFObjectHandle, but they do allow for working with streams
  824 + * and stream data as caller-managed memory.
  825 + */
  826 +
  827 + /* Get stream data as a buffer. The buffer is allocated with
  828 + * malloc and must be freed by the caller. The size of the buffer
  829 + * is stored in *len. The arguments are similar to those in
  830 + * QPDFObjectHandle::pipeStreamData. To get raw stream data, pass
  831 + * qpdf_dl_none as decode_level. Otherwise, filtering is attempted
  832 + * and *filtered is set to indicate whether it was successful. If
  833 + * *filtered is QPDF_FALSE, then raw, unfiltered stream data was
  834 + * returned. You may pass a null pointer as filtered if you don't
  835 + * care about the result. If you pass a null pointer as bufp (and
  836 + * len), the value of filtered will be set to whether the stream
  837 + * can be filterable.
  838 + */
  839 + QPDF_DLL
  840 + QPDF_ERROR_CODE qpdf_oh_get_stream_data(
  841 + qpdf_data qpdf, qpdf_oh stream_oh,
  842 + enum qpdf_stream_decode_level_e decode_level, QPDF_BOOL* filtered,
  843 + unsigned char** bufp, size_t* len);
  844 +
  845 + /* This function returns the concatenation of all of a page's
  846 + * content streams as a single, dynamically allocated buffer. As
  847 + * with qpdf_oh_get_stream_data, the buffer is allocated with
  848 + * malloc and must be freed by the caller.
  849 + */
  850 + QPDF_DLL
  851 + QPDF_ERROR_CODE qpdf_oh_get_page_content_data(
  852 + qpdf_data qpdf, qpdf_oh page_oh,
  853 + unsigned char** bufp, size_t* len);
  854 +
  855 + /* The data pointed to by bufp will be copied by the library. It
  856 + * does not need to remain valid after the call returns.
  857 + */
  858 + QPDF_DLL
  859 + void qpdf_oh_replace_stream_data(
  860 + qpdf_data qpdf, qpdf_oh stream_oh,
  861 + unsigned char const* buf, size_t len,
  862 + qpdf_oh filter, qpdf_oh decode_parms);
  863 +
792 864 /* PAGE FUNCTIONS */
793 865  
794 866 /* The first time a page function is called, qpdf will traverse
... ...
libqpdf/qpdf-c.cc
... ... @@ -5,6 +5,7 @@
5 5 #include <qpdf/QTC.hh>
6 6 #include <qpdf/QPDFExc.hh>
7 7 #include <qpdf/Pl_Discard.hh>
  8 +#include <qpdf/Pl_Buffer.hh>
8 9 #include <qpdf/QIntC.hh>
9 10 #include <qpdf/QUtil.hh>
10 11  
... ... @@ -1427,6 +1428,13 @@ qpdf_oh qpdf_oh_new_dictionary(qpdf_data qpdf)
1427 1428 return new_object(qpdf, QPDFObjectHandle::newDictionary());
1428 1429 }
1429 1430  
  1431 +qpdf_oh qpdf_oh_new_stream(qpdf_data qpdf)
  1432 +{
  1433 + QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_stream");
  1434 + return new_object(
  1435 + qpdf, QPDFObjectHandle::newStream(qpdf->qpdf.getPointer()));
  1436 +}
  1437 +
1430 1438 void qpdf_oh_make_direct(qpdf_data qpdf, qpdf_oh oh)
1431 1439 {
1432 1440 do_with_oh_void(
... ... @@ -1580,6 +1588,88 @@ char const* qpdf_oh_unparse_binary(qpdf_data qpdf, qpdf_oh oh)
1580 1588 });
1581 1589 }
1582 1590  
  1591 +qpdf_oh qpdf_oh_copy_foreign_object(
  1592 + qpdf_data qpdf, qpdf_data other_qpdf, qpdf_oh foreign_oh)
  1593 +{
  1594 + return do_with_oh<qpdf_oh>(
  1595 + other_qpdf, foreign_oh,
  1596 + return_uninitialized(qpdf),
  1597 + [qpdf](QPDFObjectHandle& o) {
  1598 + QTC::TC("qpdf", "qpdf-c called qpdf_oh_copy_foreign_object");
  1599 + return new_object(qpdf, qpdf->qpdf->copyForeignObject(o));
  1600 + });
  1601 +}
  1602 +
  1603 +QPDF_ERROR_CODE qpdf_oh_get_stream_data(
  1604 + qpdf_data qpdf, qpdf_oh stream_oh,
  1605 + qpdf_stream_decode_level_e decode_level, QPDF_BOOL* filtered,
  1606 + unsigned char** bufp, size_t* len)
  1607 +{
  1608 + return trap_errors(qpdf, [stream_oh, decode_level,
  1609 + filtered, bufp, len] (qpdf_data q) {
  1610 + auto stream = qpdf_oh_item_internal(q, stream_oh);
  1611 + Pipeline* p = nullptr;
  1612 + Pl_Buffer buf("stream data");
  1613 + if (bufp)
  1614 + {
  1615 + p = &buf;
  1616 + }
  1617 + bool was_filtered = false;
  1618 + if (stream.pipeStreamData(
  1619 + p, &was_filtered, 0, decode_level, false, false))
  1620 + {
  1621 + QTC::TC("qpdf", "qpdf-c stream data buf set",
  1622 + bufp ? 0 : 1);
  1623 + if (p && bufp && len)
  1624 + {
  1625 + buf.getMallocBuffer(bufp, len);
  1626 + }
  1627 + QTC::TC("qpdf", "qpdf-c stream data filtered set",
  1628 + filtered ? 0 : 1);
  1629 + if (filtered)
  1630 + {
  1631 + *filtered = was_filtered ? QPDF_TRUE : QPDF_FALSE;
  1632 + }
  1633 + }
  1634 + else
  1635 + {
  1636 + throw std::runtime_error(
  1637 + "unable to access stream data for stream " + stream.unparse());
  1638 + }
  1639 + });
  1640 +}
  1641 +
  1642 +QPDF_ERROR_CODE qpdf_oh_get_page_content_data(
  1643 + qpdf_data qpdf, qpdf_oh page_oh,
  1644 + unsigned char** bufp, size_t* len)
  1645 +{
  1646 + return trap_errors(qpdf, [page_oh, bufp, len] (qpdf_data q) {
  1647 + QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_page_content_data");
  1648 + auto o = qpdf_oh_item_internal(q, page_oh);
  1649 + Pl_Buffer buf("page contents");
  1650 + o.pipePageContents(&buf);
  1651 + buf.getMallocBuffer(bufp, len);
  1652 + });
  1653 +}
  1654 +
  1655 +void qpdf_oh_replace_stream_data(
  1656 + qpdf_data qpdf, qpdf_oh stream_oh,
  1657 + unsigned char const* buf, size_t len,
  1658 + qpdf_oh filter_oh, qpdf_oh decode_parms_oh)
  1659 +{
  1660 + do_with_oh_void(qpdf, stream_oh, [
  1661 + qpdf, buf, len, filter_oh,
  1662 + decode_parms_oh](QPDFObjectHandle& o) {
  1663 + QTC::TC("qpdf", "qpdf-c called qpdf_oh_replace_stream_data");
  1664 + auto filter = qpdf_oh_item_internal(qpdf, filter_oh);
  1665 + auto decode_parms = qpdf_oh_item_internal(qpdf, decode_parms_oh);
  1666 + // XXX test with binary data with null
  1667 + o.replaceStreamData(
  1668 + std::string(reinterpret_cast<char const*>(buf), len),
  1669 + filter, decode_parms);
  1670 + });
  1671 +}
  1672 +
1583 1673 int qpdf_get_num_pages(qpdf_data qpdf)
1584 1674 {
1585 1675 QTC::TC("qpdf", "qpdf-c called qpdf_num_pages");
... ...
manual/index.rst
... ... @@ -3659,6 +3659,9 @@ For a detailed list of changes, please see the file
3659 3659 - Add several functions for working with pages. See ``PAGE
3660 3660 FUNCTIONS`` in ``include/qpdf/qpdf-c.h`` for details.
3661 3661  
  3662 + - Add several functions for working with streams. See ``STREAM
  3663 + FUNCTIONS`` in ``include/qpdf/qpdf-c.h`` for details.
  3664 +
3662 3665 - Documentation change
3663 3666  
3664 3667 - The documentation sources have been switched from docbook to
... ...
qpdf/qpdf-ctest.c
... ... @@ -1063,6 +1063,118 @@ static void test37(char const* infile,
1063 1063 assert(qpdf_get_num_pages(qpdf) == 10);
1064 1064 }
1065 1065  
  1066 +static void test38(char const* infile,
  1067 + char const* password,
  1068 + char const* outfile,
  1069 + char const* xarg)
  1070 +{
  1071 + /* This test expects 11-pages.pdf. */
  1072 +
  1073 + /* Read stream data */
  1074 +
  1075 + assert(qpdf_read(qpdf, infile, password) == 0);
  1076 + qpdf_oh stream = qpdf_get_object_by_id(qpdf, 17, 0);
  1077 + qpdf_oh dict = qpdf_oh_get_dict(qpdf, stream);
  1078 + assert(qpdf_oh_get_int_value_as_int(
  1079 + qpdf, qpdf_oh_get_key(qpdf, dict, "/Length")) == 53);
  1080 + /* Get raw data */
  1081 + unsigned char *buf = 0;
  1082 + size_t len = 0;
  1083 + assert(qpdf_oh_get_stream_data(
  1084 + qpdf, stream, qpdf_dl_none, 0, &buf, &len) == 0);
  1085 + assert(len == 53);
  1086 + assert(((int)buf[0] == 'x') && ((int)buf[1] == 0234));
  1087 + free(buf);
  1088 +
  1089 + /* Test whether filterable */
  1090 + QPDF_BOOL filtered = QPDF_FALSE;
  1091 + assert(qpdf_oh_get_stream_data(
  1092 + qpdf, stream, qpdf_dl_all, &filtered, 0, 0) == 0);
  1093 + assert(filtered == QPDF_TRUE);
  1094 +
  1095 + /* Get filtered data */
  1096 + assert(qpdf_oh_get_stream_data(
  1097 + qpdf, stream, qpdf_dl_all, 0, &buf, &len) == 0);
  1098 + assert(len == 47);
  1099 + assert(memcmp((char const*)buf,
  1100 + "BT /F1 15 Tf 72 720 Td (Original page 2) Tj ET\n",
  1101 + len) == 0);
  1102 +
  1103 + /* Get page data */
  1104 + qpdf_oh page2 = qpdf_get_page_n(qpdf, 1); /* 0-based index */
  1105 + unsigned char* buf2 = 0;
  1106 + assert(qpdf_oh_get_page_content_data(qpdf, page2, &buf2, &len) == 0);
  1107 + assert(len == 47);
  1108 + assert(memcmp(buf, buf2, len) == 0);
  1109 + free(buf);
  1110 + free(buf2);
  1111 +
  1112 + /* errors */
  1113 + printf("page content on broken page\n");
  1114 + qpdf_oh_replace_key(qpdf, page2, "/Contents", qpdf_oh_new_integer(qpdf, 3));
  1115 + buf = 0;
  1116 + qpdf_oh_get_page_content_data(qpdf, page2, &buf, &len);
  1117 + assert(buf == 0);
  1118 + report_errors();
  1119 + printf("stream data for non stream\n");
  1120 + qpdf_oh root = qpdf_get_root(qpdf);
  1121 + assert(qpdf_oh_get_stream_data(qpdf, root, qpdf_dl_all, 0, 0, 0) != 0);
  1122 + report_errors();
  1123 +}
  1124 +
  1125 +static void test39(char const* infile,
  1126 + char const* password,
  1127 + char const* outfile,
  1128 + char const* xarg)
  1129 +{
  1130 + /* This test expects 11-pages.pdf as file1 and minimal.pdf as xarg. */
  1131 +
  1132 + /* Foreign object */
  1133 +
  1134 + qpdf_data qpdf2 = qpdf_init();
  1135 + assert(qpdf_read(qpdf, infile, password) == 0);
  1136 + assert(qpdf_read(qpdf2, xarg, "") == 0);
  1137 +
  1138 + qpdf_oh resources = qpdf_get_object_by_id(qpdf2, 3, 0);
  1139 + qpdf_oh copy = qpdf_oh_copy_foreign_object(qpdf, qpdf2, resources);
  1140 + qpdf_oh root = qpdf_get_root(qpdf);
  1141 + qpdf_oh_replace_key(qpdf, root, "/Copy", copy);
  1142 +
  1143 + qpdf_init_write(qpdf, outfile);
  1144 + qpdf_set_static_ID(qpdf, QPDF_TRUE);
  1145 + qpdf_set_qdf_mode(qpdf, QPDF_TRUE);
  1146 + qpdf_set_suppress_original_object_IDs(qpdf, QPDF_TRUE);
  1147 + qpdf_write(qpdf);
  1148 + report_errors();
  1149 + qpdf_cleanup(&qpdf2);
  1150 +}
  1151 +
  1152 +static void test40(char const* infile,
  1153 + char const* password,
  1154 + char const* outfile,
  1155 + char const* xarg)
  1156 +{
  1157 + /* This test expects minimal.pdf. */
  1158 +
  1159 + /* New stream */
  1160 +
  1161 + assert(qpdf_read(qpdf, infile, password) == 0);
  1162 + qpdf_oh stream = qpdf_oh_new_stream(qpdf);
  1163 + qpdf_oh_replace_stream_data(
  1164 + qpdf, stream,
  1165 + (unsigned char*)"12345\000abcde", 11, /* embedded null */
  1166 + qpdf_oh_new_null(qpdf), qpdf_oh_new_null(qpdf));
  1167 + qpdf_oh root = qpdf_get_root(qpdf);
  1168 + qpdf_oh_replace_key(qpdf, root, "/Potato", stream);
  1169 +
  1170 + qpdf_init_write(qpdf, outfile);
  1171 + qpdf_set_static_ID(qpdf, QPDF_TRUE);
  1172 + qpdf_set_qdf_mode(qpdf, QPDF_TRUE);
  1173 + qpdf_set_suppress_original_object_IDs(qpdf, QPDF_TRUE);
  1174 + qpdf_write(qpdf);
  1175 + report_errors();
  1176 +}
  1177 +
1066 1178 int main(int argc, char* argv[])
1067 1179 {
1068 1180 char* p = 0;
... ... @@ -1140,6 +1252,9 @@ int main(int argc, char* argv[])
1140 1252 (n == 35) ? test35 :
1141 1253 (n == 36) ? test36 :
1142 1254 (n == 37) ? test37 :
  1255 + (n == 38) ? test38 :
  1256 + (n == 39) ? test39 :
  1257 + (n == 40) ? test40 :
1143 1258 0);
1144 1259  
1145 1260 if (fn == 0)
... ...
qpdf/qpdf.testcov
... ... @@ -617,3 +617,9 @@ qpdf-c called qpdf_push_inherited_attributes_to_page 0
617 617 qpdf-c called qpdf_add_page 0
618 618 qpdf-c called qpdf_add_page_at 0
619 619 qpdf-c called qpdf_remove_page 0
  620 +qpdf-c called qpdf_oh_new_stream 0
  621 +qpdf-c called qpdf_oh_copy_foreign_object 0
  622 +qpdf-c stream data filtered set 1
  623 +qpdf-c stream data buf set 1
  624 +qpdf-c called qpdf_oh_get_page_content_data 0
  625 +qpdf-c called qpdf_oh_replace_stream_data 0
... ...
qpdf/qtest/qpdf.test
... ... @@ -4904,6 +4904,34 @@ $td-&gt;runtest(&quot;C pages cache&quot;,
4904 4904  
4905 4905 show_ntests();
4906 4906 # ----------
  4907 +$td->notify("--- C API Stream Functions ---");
  4908 +$n_tests += 5;
  4909 +
  4910 +$td->runtest("C read streams",
  4911 + {$td->COMMAND =>
  4912 + "qpdf-ctest 38 11-pages.pdf '' ''"},
  4913 + {$td->FILE => "c-get-stream.out", $td->EXIT_STATUS => 0},
  4914 + $td->NORMALIZE_NEWLINES);
  4915 +
  4916 +$td->runtest("C foreign object",
  4917 + {$td->COMMAND =>
  4918 + "qpdf-ctest 39 11-pages.pdf '' a.pdf minimal.pdf"},
  4919 + {$td->STRING => "C test 39 done\n", $td->EXIT_STATUS => 0},
  4920 + $td->NORMALIZE_NEWLINES);
  4921 +$td->runtest("check output",
  4922 + {$td->FILE => 'a.pdf'},
  4923 + {$td->FILE => 'c-foreign.pdf'});
  4924 +
  4925 +$td->runtest("C new stream",
  4926 + {$td->COMMAND =>
  4927 + "qpdf-ctest 40 minimal.pdf '' a.pdf"},
  4928 + {$td->STRING => "C test 40 done\n", $td->EXIT_STATUS => 0},
  4929 + $td->NORMALIZE_NEWLINES);
  4930 +$td->runtest("check output",
  4931 + {$td->FILE => 'a.pdf'},
  4932 + {$td->FILE => 'c-new-stream.pdf'});
  4933 +show_ntests();
  4934 +# ----------
4907 4935 $td->notify("--- Content Preservation Tests ---");
4908 4936 # $n_tests incremented below
4909 4937  
... ...
qpdf/qtest/qpdf/c-foreign.pdf 0 → 100644
  1 +%PDF-1.4
  2 +%¿÷¢þ
  3 +%QDF-1.0
  4 +
  5 +1 0 obj
  6 +<<
  7 + /Copy 3 0 R
  8 + /Pages 4 0 R
  9 + /Type /Catalog
  10 +>>
  11 +endobj
  12 +
  13 +2 0 obj
  14 +<<
  15 + /CreationDate (D:20120721200217)
  16 + /Producer (Apex PDFWriter)
  17 +>>
  18 +endobj
  19 +
  20 +3 0 obj
  21 +<<
  22 + /Contents 5 0 R
  23 + /MediaBox [
  24 + 0
  25 + 0
  26 + 612
  27 + 792
  28 + ]
  29 + /Resources <<
  30 + /Font <<
  31 + /F1 7 0 R
  32 + >>
  33 + /ProcSet 8 0 R
  34 + >>
  35 + /Type /Page
  36 +>>
  37 +endobj
  38 +
  39 +4 0 obj
  40 +<<
  41 + /Count 11
  42 + /Kids [
  43 + 9 0 R
  44 + 10 0 R
  45 + 11 0 R
  46 + 12 0 R
  47 + 13 0 R
  48 + 14 0 R
  49 + 15 0 R
  50 + 16 0 R
  51 + 17 0 R
  52 + 18 0 R
  53 + 19 0 R
  54 + ]
  55 + /Type /Pages
  56 +>>
  57 +endobj
  58 +
  59 +5 0 obj
  60 +<<
  61 + /Length 6 0 R
  62 +>>
  63 +stream
  64 +BT
  65 + /F1 24 Tf
  66 + 72 720 Td
  67 + (Potato) Tj
  68 +ET
  69 +endstream
  70 +endobj
  71 +
  72 +6 0 obj
  73 +44
  74 +endobj
  75 +
  76 +7 0 obj
  77 +<<
  78 + /BaseFont /Helvetica
  79 + /Encoding /WinAnsiEncoding
  80 + /Name /F1
  81 + /Subtype /Type1
  82 + /Type /Font
  83 +>>
  84 +endobj
  85 +
  86 +8 0 obj
  87 +[
  88 + /PDF
  89 + /Text
  90 +]
  91 +endobj
  92 +
  93 +%% Page 1
  94 +9 0 obj
  95 +<<
  96 + /Contents 20 0 R
  97 + /MediaBox [
  98 + 0
  99 + 0
  100 + 612
  101 + 792
  102 + ]
  103 + /Parent 4 0 R
  104 + /Resources <<
  105 + /Font <<
  106 + /F1 22 0 R
  107 + >>
  108 + /ProcSet [
  109 + /PDF
  110 + /Text
  111 + ]
  112 + >>
  113 + /Type /Page
  114 +>>
  115 +endobj
  116 +
  117 +%% Page 2
  118 +10 0 obj
  119 +<<
  120 + /Contents 23 0 R
  121 + /MediaBox [
  122 + 0
  123 + 0
  124 + 612
  125 + 792
  126 + ]
  127 + /Parent 4 0 R
  128 + /Resources <<
  129 + /Font <<
  130 + /F1 22 0 R
  131 + >>
  132 + /ProcSet [
  133 + /PDF
  134 + /Text
  135 + ]
  136 + >>
  137 + /Type /Page
  138 +>>
  139 +endobj
  140 +
  141 +%% Page 3
  142 +11 0 obj
  143 +<<
  144 + /Contents 25 0 R
  145 + /MediaBox [
  146 + 0
  147 + 0
  148 + 612
  149 + 792
  150 + ]
  151 + /Parent 4 0 R
  152 + /Resources <<
  153 + /Font <<
  154 + /F1 22 0 R
  155 + >>
  156 + /ProcSet [
  157 + /PDF
  158 + /Text
  159 + ]
  160 + >>
  161 + /Type /Page
  162 +>>
  163 +endobj
  164 +
  165 +%% Page 4
  166 +12 0 obj
  167 +<<
  168 + /Contents 27 0 R
  169 + /MediaBox [
  170 + 0
  171 + 0
  172 + 612
  173 + 792
  174 + ]
  175 + /Parent 4 0 R
  176 + /Resources <<
  177 + /Font <<
  178 + /F1 22 0 R
  179 + >>
  180 + /ProcSet [
  181 + /PDF
  182 + /Text
  183 + ]
  184 + >>
  185 + /Type /Page
  186 +>>
  187 +endobj
  188 +
  189 +%% Page 5
  190 +13 0 obj
  191 +<<
  192 + /Contents 29 0 R
  193 + /MediaBox [
  194 + 0
  195 + 0
  196 + 612
  197 + 792
  198 + ]
  199 + /Parent 4 0 R
  200 + /Resources <<
  201 + /Font <<
  202 + /F1 22 0 R
  203 + >>
  204 + /ProcSet [
  205 + /PDF
  206 + /Text
  207 + ]
  208 + >>
  209 + /Type /Page
  210 +>>
  211 +endobj
  212 +
  213 +%% Page 6
  214 +14 0 obj
  215 +<<
  216 + /Contents 31 0 R
  217 + /MediaBox [
  218 + 0
  219 + 0
  220 + 612
  221 + 792
  222 + ]
  223 + /Parent 4 0 R
  224 + /Resources <<
  225 + /Font <<
  226 + /F1 22 0 R
  227 + >>
  228 + /ProcSet [
  229 + /PDF
  230 + /Text
  231 + ]
  232 + >>
  233 + /Type /Page
  234 +>>
  235 +endobj
  236 +
  237 +%% Page 7
  238 +15 0 obj
  239 +<<
  240 + /Contents 33 0 R
  241 + /MediaBox [
  242 + 0
  243 + 0
  244 + 612
  245 + 792
  246 + ]
  247 + /Parent 4 0 R
  248 + /Resources <<
  249 + /Font <<
  250 + /F1 22 0 R
  251 + >>
  252 + /ProcSet [
  253 + /PDF
  254 + /Text
  255 + ]
  256 + >>
  257 + /Type /Page
  258 +>>
  259 +endobj
  260 +
  261 +%% Page 8
  262 +16 0 obj
  263 +<<
  264 + /Contents 35 0 R
  265 + /MediaBox [
  266 + 0
  267 + 0
  268 + 612
  269 + 792
  270 + ]
  271 + /Parent 4 0 R
  272 + /Resources <<
  273 + /Font <<
  274 + /F1 22 0 R
  275 + >>
  276 + /ProcSet [
  277 + /PDF
  278 + /Text
  279 + ]
  280 + >>
  281 + /Type /Page
  282 +>>
  283 +endobj
  284 +
  285 +%% Page 9
  286 +17 0 obj
  287 +<<
  288 + /Contents 37 0 R
  289 + /MediaBox [
  290 + 0
  291 + 0
  292 + 612
  293 + 792
  294 + ]
  295 + /Parent 4 0 R
  296 + /Resources <<
  297 + /Font <<
  298 + /F1 22 0 R
  299 + >>
  300 + /ProcSet [
  301 + /PDF
  302 + /Text
  303 + ]
  304 + >>
  305 + /Type /Page
  306 +>>
  307 +endobj
  308 +
  309 +%% Page 10
  310 +18 0 obj
  311 +<<
  312 + /Contents 39 0 R
  313 + /MediaBox [
  314 + 0
  315 + 0
  316 + 612
  317 + 792
  318 + ]
  319 + /Parent 4 0 R
  320 + /Resources <<
  321 + /Font <<
  322 + /F1 22 0 R
  323 + >>
  324 + /ProcSet [
  325 + /PDF
  326 + /Text
  327 + ]
  328 + >>
  329 + /Type /Page
  330 +>>
  331 +endobj
  332 +
  333 +%% Page 11
  334 +19 0 obj
  335 +<<
  336 + /Contents 41 0 R
  337 + /MediaBox [
  338 + 0
  339 + 0
  340 + 612
  341 + 792
  342 + ]
  343 + /Parent 4 0 R
  344 + /Resources <<
  345 + /Font <<
  346 + /F1 22 0 R
  347 + >>
  348 + /ProcSet [
  349 + /PDF
  350 + /Text
  351 + ]
  352 + >>
  353 + /Type /Page
  354 +>>
  355 +endobj
  356 +
  357 +%% Contents for page 1
  358 +20 0 obj
  359 +<<
  360 + /Length 21 0 R
  361 +>>
  362 +stream
  363 +BT /F1 15 Tf 72 720 Td (Original page 1) Tj ET
  364 +endstream
  365 +endobj
  366 +
  367 +21 0 obj
  368 +47
  369 +endobj
  370 +
  371 +22 0 obj
  372 +<<
  373 + /BaseFont /Times-Roman
  374 + /Encoding /WinAnsiEncoding
  375 + /Subtype /Type1
  376 + /Type /Font
  377 +>>
  378 +endobj
  379 +
  380 +%% Contents for page 2
  381 +23 0 obj
  382 +<<
  383 + /Length 24 0 R
  384 +>>
  385 +stream
  386 +BT /F1 15 Tf 72 720 Td (Original page 2) Tj ET
  387 +endstream
  388 +endobj
  389 +
  390 +24 0 obj
  391 +47
  392 +endobj
  393 +
  394 +%% Contents for page 3
  395 +25 0 obj
  396 +<<
  397 + /Length 26 0 R
  398 +>>
  399 +stream
  400 +BT /F1 15 Tf 72 720 Td (Original page 3) Tj ET
  401 +endstream
  402 +endobj
  403 +
  404 +26 0 obj
  405 +47
  406 +endobj
  407 +
  408 +%% Contents for page 4
  409 +27 0 obj
  410 +<<
  411 + /Length 28 0 R
  412 +>>
  413 +stream
  414 +BT /F1 15 Tf 72 720 Td (Original page 4) Tj ET
  415 +endstream
  416 +endobj
  417 +
  418 +28 0 obj
  419 +47
  420 +endobj
  421 +
  422 +%% Contents for page 5
  423 +29 0 obj
  424 +<<
  425 + /Length 30 0 R
  426 +>>
  427 +stream
  428 +BT /F1 15 Tf 72 720 Td (Original page 5) Tj ET
  429 +endstream
  430 +endobj
  431 +
  432 +30 0 obj
  433 +47
  434 +endobj
  435 +
  436 +%% Contents for page 6
  437 +31 0 obj
  438 +<<
  439 + /Length 32 0 R
  440 +>>
  441 +stream
  442 +BT /F1 15 Tf 72 720 Td (Original page 6) Tj ET
  443 +endstream
  444 +endobj
  445 +
  446 +32 0 obj
  447 +47
  448 +endobj
  449 +
  450 +%% Contents for page 7
  451 +33 0 obj
  452 +<<
  453 + /Length 34 0 R
  454 +>>
  455 +stream
  456 +BT /F1 15 Tf 72 720 Td (Original page 7) Tj ET
  457 +endstream
  458 +endobj
  459 +
  460 +34 0 obj
  461 +47
  462 +endobj
  463 +
  464 +%% Contents for page 8
  465 +35 0 obj
  466 +<<
  467 + /Length 36 0 R
  468 +>>
  469 +stream
  470 +BT /F1 15 Tf 72 720 Td (Original page 8) Tj ET
  471 +endstream
  472 +endobj
  473 +
  474 +36 0 obj
  475 +47
  476 +endobj
  477 +
  478 +%% Contents for page 9
  479 +37 0 obj
  480 +<<
  481 + /Length 38 0 R
  482 +>>
  483 +stream
  484 +BT /F1 15 Tf 72 720 Td (Original page 9) Tj ET
  485 +endstream
  486 +endobj
  487 +
  488 +38 0 obj
  489 +47
  490 +endobj
  491 +
  492 +%% Contents for page 10
  493 +39 0 obj
  494 +<<
  495 + /Length 40 0 R
  496 +>>
  497 +stream
  498 +BT /F1 15 Tf 72 720 Td (Original page 10) Tj ET
  499 +endstream
  500 +endobj
  501 +
  502 +40 0 obj
  503 +48
  504 +endobj
  505 +
  506 +%% Contents for page 11
  507 +41 0 obj
  508 +<<
  509 + /Length 42 0 R
  510 +>>
  511 +stream
  512 +BT /F1 15 Tf 72 720 Td (Original page 11) Tj ET
  513 +endstream
  514 +endobj
  515 +
  516 +42 0 obj
  517 +48
  518 +endobj
  519 +
  520 +xref
  521 +0 43
  522 +0000000000 65535 f
  523 +0000000025 00000 n
  524 +0000000093 00000 n
  525 +0000000179 00000 n
  526 +0000000355 00000 n
  527 +0000000538 00000 n
  528 +0000000637 00000 n
  529 +0000000656 00000 n
  530 +0000000774 00000 n
  531 +0000000819 00000 n
  532 +0000001048 00000 n
  533 +0000001278 00000 n
  534 +0000001508 00000 n
  535 +0000001738 00000 n
  536 +0000001968 00000 n
  537 +0000002198 00000 n
  538 +0000002428 00000 n
  539 +0000002658 00000 n
  540 +0000002889 00000 n
  541 +0000003120 00000 n
  542 +0000003363 00000 n
  543 +0000003467 00000 n
  544 +0000003487 00000 n
  545 +0000003619 00000 n
  546 +0000003723 00000 n
  547 +0000003766 00000 n
  548 +0000003870 00000 n
  549 +0000003913 00000 n
  550 +0000004017 00000 n
  551 +0000004060 00000 n
  552 +0000004164 00000 n
  553 +0000004207 00000 n
  554 +0000004311 00000 n
  555 +0000004354 00000 n
  556 +0000004458 00000 n
  557 +0000004501 00000 n
  558 +0000004605 00000 n
  559 +0000004648 00000 n
  560 +0000004752 00000 n
  561 +0000004796 00000 n
  562 +0000004901 00000 n
  563 +0000004945 00000 n
  564 +0000005050 00000 n
  565 +trailer <<
  566 + /Info 2 0 R
  567 + /Root 1 0 R
  568 + /Size 43
  569 + /ID [<e032a88c7a987db6ca3abee555506ccc><31415926535897932384626433832795>]
  570 +>>
  571 +startxref
  572 +5070
  573 +%%EOF
... ...
qpdf/qtest/qpdf/c-get-stream.out 0 → 100644
  1 +page content on broken page
  2 +error: page object 5 0: object is supposed to be a stream or an array of streams but is neither
  3 + code: 5
  4 + file:
  5 + pos : 0
  6 + text: object is supposed to be a stream or an array of streams but is neither
  7 +stream data for non stream
  8 +error: operation for stream attempted on object of type dictionary
  9 + code: 2
  10 + file:
  11 + pos : 0
  12 + text: operation for stream attempted on object of type dictionary
  13 +C test 38 done
... ...
qpdf/qtest/qpdf/c-new-stream.pdf 0 → 100644
No preview for this file type