Commit 9bb6f570ec73c6154748596d04a6f10c41c57721

Authored by Jay Berkenbilt
1 parent f072be03

C API: add functions for working with pages (fixes #594)

ChangeLog
  1 +2021-12-16 Jay Berkenbilt <ejb@ql.org>
  2 +
  3 + * Add several functions to the C API for working with pages. C
  4 + wrappers around sevearl of the "Legacy" page operations from
  5 + QPDFObjectHandle.hh have been added. See "PAGE FUNCTIONS" in
  6 + qpdf-c.h for details. Fixes #594.
  7 +
1 2021-12-12 Jay Berkenbilt <ejb@ql.org> 8 2021-12-12 Jay Berkenbilt <ejb@ql.org>
2 9
3 * Convert documentation from docbook to reStructuredText/Sphinx. 10 * Convert documentation from docbook to reStructuredText/Sphinx.
include/qpdf/qpdf-c.h
@@ -788,6 +788,67 @@ extern &quot;C&quot; { @@ -788,6 +788,67 @@ extern &quot;C&quot; {
788 char const* qpdf_oh_unparse_resolved(qpdf_data qpdf, qpdf_oh oh); 788 char const* qpdf_oh_unparse_resolved(qpdf_data qpdf, qpdf_oh oh);
789 QPDF_DLL 789 QPDF_DLL
790 char const* qpdf_oh_unparse_binary(qpdf_data qpdf, qpdf_oh oh); 790 char const* qpdf_oh_unparse_binary(qpdf_data qpdf, qpdf_oh oh);
  791 +
  792 + /* PAGE FUNCTIONS */
  793 +
  794 + /* The first time a page function is called, qpdf will traverse
  795 + * the /Pages tree. Subsequent calls to retrieve the number of
  796 + * pages or a specific page run in constant time as they are
  797 + * accessing the pages cache. If you manipulate the page tree
  798 + * outside of these functions, you should call
  799 + * qpdf_update_all_pages_cache. See comments for getAllPages() and
  800 + * updateAllPagesCache() in QPDF.hh.
  801 + */
  802 +
  803 + /* For each function, the corresponding method in QPDF.hh is
  804 + * referenced. Please see comments in QPDF.hh for details.
  805 + */
  806 +
  807 + /* calls getAllPages(). On error, returns -1 and sets error for
  808 + * qpdf_get_error. */
  809 + QPDF_DLL
  810 + int qpdf_get_num_pages(qpdf_data qpdf);
  811 + /* returns uninitialized object if out of range */
  812 + QPDF_DLL
  813 + qpdf_oh qpdf_get_page_n(qpdf_data qpdf, size_t zero_based_index);
  814 +
  815 + /* updateAllPagesCache() */
  816 + QPDF_DLL
  817 + QPDF_ERROR_CODE qpdf_update_all_pages_cache(qpdf_data qpdf);
  818 +
  819 + /* findPage() -- return zero-based index. If page is not found,
  820 + * return -1 and save the error to be retrieved with
  821 + * qpdf_get_error.
  822 + */
  823 + QPDF_DLL
  824 + int qpdf_find_page_by_id(qpdf_data qpdf, int objid, int generation);
  825 + QPDF_DLL
  826 + int qpdf_find_page_by_oh(qpdf_data qpdf, qpdf_oh oh);
  827 +
  828 + /* pushInheritedAttributesToPage() */
  829 + QPDF_DLL
  830 + QPDF_ERROR_CODE qpdf_push_inherited_attributes_to_page(qpdf_data qpdf);
  831 +
  832 + /* Functions that add pages may add pages from other files. If
  833 + * adding a page from the same file, newpage_qpdf and qpdf are the
  834 + * same.
  835 + /*/
  836 +
  837 + /* addPage() */
  838 + QPDF_DLL
  839 + QPDF_ERROR_CODE qpdf_add_page(
  840 + qpdf_data qpdf,
  841 + qpdf_data newpage_qpdf, qpdf_oh newpage,
  842 + QPDF_BOOL first);
  843 + /* addPageAt() */
  844 + QPDF_DLL
  845 + QPDF_ERROR_CODE qpdf_add_page_at(
  846 + qpdf_data qpdf,
  847 + qpdf_data newpage_qpdf, qpdf_oh newpage,
  848 + QPDF_BOOL before, qpdf_oh refpage);
  849 + /* removePage() */
  850 + QPDF_DLL
  851 + QPDF_ERROR_CODE qpdf_remove_page(qpdf_data qpdf, qpdf_oh page);
791 #ifdef __cplusplus 852 #ifdef __cplusplus
792 } 853 }
793 #endif 854 #endif
libqpdf/qpdf-c.cc
@@ -1579,3 +1579,102 @@ char const* qpdf_oh_unparse_binary(qpdf_data qpdf, qpdf_oh oh) @@ -1579,3 +1579,102 @@ char const* qpdf_oh_unparse_binary(qpdf_data qpdf, qpdf_oh oh)
1579 return qpdf->tmp_string.c_str(); 1579 return qpdf->tmp_string.c_str();
1580 }); 1580 });
1581 } 1581 }
  1582 +
  1583 +int qpdf_get_num_pages(qpdf_data qpdf)
  1584 +{
  1585 + QTC::TC("qpdf", "qpdf-c called qpdf_num_pages");
  1586 + int n = -1;
  1587 + QPDF_ERROR_CODE code = trap_errors(qpdf, [&n](qpdf_data q) {
  1588 + n = QIntC::to_int(q->qpdf->getAllPages().size());
  1589 + });
  1590 + if (code & QPDF_ERRORS)
  1591 + {
  1592 + return -1;
  1593 + }
  1594 + return n;
  1595 +}
  1596 +
  1597 +qpdf_oh qpdf_get_page_n(qpdf_data qpdf, size_t i)
  1598 +{
  1599 + QTC::TC("qpdf", "qpdf-c called qpdf_get_page_n");
  1600 + qpdf_oh result = 0;
  1601 + QPDF_ERROR_CODE code = trap_errors(qpdf, [&result, i](qpdf_data q) {
  1602 + result = new_object(q, q->qpdf->getAllPages().at(i));
  1603 + });
  1604 + if ((code & QPDF_ERRORS) || (result == 0))
  1605 + {
  1606 + return qpdf_oh_new_uninitialized(qpdf);
  1607 + }
  1608 + return result;
  1609 +}
  1610 +
  1611 +QPDF_ERROR_CODE qpdf_update_all_pages_cache(qpdf_data qpdf)
  1612 +{
  1613 + QTC::TC("qpdf", "qpdf-c called qpdf_update_all_pages_cache");
  1614 + return trap_errors(qpdf, [](qpdf_data q) {
  1615 + q->qpdf->updateAllPagesCache();
  1616 + });
  1617 +}
  1618 +
  1619 +int qpdf_find_page_by_id(qpdf_data qpdf, int objid, int generation)
  1620 +{
  1621 + QTC::TC("qpdf", "qpdf-c called qpdf_find_page_by_id");
  1622 + int n = -1;
  1623 + QPDFObjGen og(objid, generation);
  1624 + QPDF_ERROR_CODE code = trap_errors(qpdf, [&n, &og](qpdf_data q) {
  1625 + n = QIntC::to_int(q->qpdf->findPage(og));
  1626 + });
  1627 + if (code & QPDF_ERRORS)
  1628 + {
  1629 + return -1;
  1630 + }
  1631 + return n;
  1632 +}
  1633 +
  1634 +int qpdf_find_page_by_oh(qpdf_data qpdf, qpdf_oh oh)
  1635 +{
  1636 + QTC::TC("qpdf", "qpdf-c called qpdf_find_page_by_oh");
  1637 + return do_with_oh<int>(
  1638 + qpdf, oh, return_T<int>(-1), [qpdf](QPDFObjectHandle& o) {
  1639 + return qpdf->qpdf->findPage(o);
  1640 + });
  1641 +}
  1642 +
  1643 +QPDF_ERROR_CODE qpdf_push_inherited_attributes_to_page(qpdf_data qpdf)
  1644 +{
  1645 + QTC::TC("qpdf", "qpdf-c called qpdf_push_inherited_attributes_to_page");
  1646 + return trap_errors(qpdf, [](qpdf_data q) {
  1647 + q->qpdf->pushInheritedAttributesToPage();
  1648 + });
  1649 +}
  1650 +
  1651 +QPDF_ERROR_CODE qpdf_add_page(
  1652 + qpdf_data qpdf, qpdf_data newpage_qpdf, qpdf_oh newpage, QPDF_BOOL first)
  1653 +{
  1654 + QTC::TC("qpdf", "qpdf-c called qpdf_add_page");
  1655 + auto page = qpdf_oh_item_internal(newpage_qpdf, newpage);
  1656 + return trap_errors(qpdf, [&page, first](qpdf_data q) {
  1657 + q->qpdf->addPage(page, first);
  1658 + });
  1659 +}
  1660 +
  1661 +QPDF_ERROR_CODE qpdf_add_page_at(
  1662 + qpdf_data qpdf, qpdf_data newpage_qpdf, qpdf_oh newpage,
  1663 + QPDF_BOOL before, qpdf_oh refpage)
  1664 +{
  1665 + QTC::TC("qpdf", "qpdf-c called qpdf_add_page_at");
  1666 + auto page = qpdf_oh_item_internal(newpage_qpdf, newpage);
  1667 + auto ref = qpdf_oh_item_internal(qpdf, refpage);
  1668 + return trap_errors(qpdf, [&page, before, &ref](qpdf_data q) {
  1669 + q->qpdf->addPageAt(page, before, ref);
  1670 + });
  1671 +}
  1672 +
  1673 +QPDF_ERROR_CODE qpdf_remove_page(qpdf_data qpdf, qpdf_oh page)
  1674 +{
  1675 + QTC::TC("qpdf", "qpdf-c called qpdf_remove_page");
  1676 + auto p = qpdf_oh_item_internal(qpdf, page);
  1677 + return trap_errors(qpdf, [&p](qpdf_data q) {
  1678 + q->qpdf->removePage(p);
  1679 + });
  1680 +}
manual/index.rst
@@ -3626,7 +3626,9 @@ For a detailed list of changes, please see the file @@ -3626,7 +3626,9 @@ For a detailed list of changes, please see the file
3626 more detail what the behavior is. See :ref:`ref.object-accessors` for a more in-depth 3626 more detail what the behavior is. See :ref:`ref.object-accessors` for a more in-depth
3627 discussion. 3627 discussion.
3628 3628
3629 - - Overhaul error handling for the object handle functions in the 3629 + - C API Enhancements
  3630 +
  3631 + - Overhaul error handling for the object handle functions
3630 C API. See comments in the "Object handling" section of 3632 C API. See comments in the "Object handling" section of
3631 :file:`include/qpdf/qpdf-c.h` for details. 3633 :file:`include/qpdf/qpdf-c.h` for details.
3632 In particular, exceptions thrown by the underlying C++ code 3634 In particular, exceptions thrown by the underlying C++ code
@@ -3650,6 +3652,9 @@ For a detailed list of changes, please see the file @@ -3650,6 +3652,9 @@ For a detailed list of changes, please see the file
3650 and ``qpdf_replace_object``, exposing the corresponding methods 3652 and ``qpdf_replace_object``, exposing the corresponding methods
3651 in ``QPDF`` and ``QPDFObjectHandle``. 3653 in ``QPDF`` and ``QPDFObjectHandle``.
3652 3654
  3655 + - Add several functions for working with pages. See ``PAGE
  3656 + FUNCTIONS`` in ``include/qpdf/qpdf-c.h`` for details.
  3657 +
3653 - Documentation change 3658 - Documentation change
3654 3659
3655 - The documentation sources have been switched from docbook to 3660 - The documentation sources have been switched from docbook to
qpdf/qpdf-ctest.c
@@ -931,6 +931,138 @@ static void test33(char const* infile, @@ -931,6 +931,138 @@ static void test33(char const* infile,
931 report_errors(); 931 report_errors();
932 } 932 }
933 933
  934 +static void test34(char const* infile,
  935 + char const* password,
  936 + char const* outfile,
  937 + char const* xarg)
  938 +{
  939 + /* This test expects 11-pages.pdf as file1 and minimal.pdf as xarg. */
  940 +
  941 + /* Non-error cases for page API */
  942 +
  943 + qpdf_data qpdf2 = qpdf_init();
  944 + assert(qpdf_read(qpdf, infile, password) == 0);
  945 + assert(qpdf_read(qpdf2, xarg, "") == 0);
  946 + assert(qpdf_get_num_pages(qpdf) == 11);
  947 + assert(qpdf_get_num_pages(qpdf2) == 1);
  948 +
  949 + /* At this time, there is no C API for accessing stream data, so
  950 + * we hard-code object IDs from a known input file.
  951 + */
  952 + assert(qpdf_oh_get_object_id(qpdf, qpdf_get_page_n(qpdf, 0)) == 4);
  953 + assert(qpdf_oh_get_object_id(qpdf, qpdf_get_page_n(qpdf, 10)) == 14);
  954 + qpdf_oh page3 = qpdf_get_page_n(qpdf, 3);
  955 + assert(qpdf_find_page_by_oh(qpdf, page3) == 3);
  956 + assert(qpdf_find_page_by_id(
  957 + qpdf, qpdf_oh_get_object_id(qpdf, page3), 0) == 3);
  958 +
  959 + /* Add other page to the end */
  960 + qpdf_oh opage0 = qpdf_get_page_n(qpdf2, 0);
  961 + assert(qpdf_add_page(qpdf, qpdf2, opage0, QPDF_FALSE) == 0);
  962 + /* Add other page before page 3 */
  963 + assert(qpdf_add_page_at(qpdf, qpdf2, opage0, QPDF_TRUE, page3) == 0);
  964 + /* Remove page 3 */
  965 + assert(qpdf_remove_page(qpdf, page3) == 0);
  966 + /* At page 3 back at the beginning */
  967 + assert(qpdf_add_page(qpdf, qpdf, page3, QPDF_TRUE) == 0);
  968 +
  969 + qpdf_init_write(qpdf, outfile);
  970 + qpdf_set_static_ID(qpdf, QPDF_TRUE);
  971 + qpdf_set_qdf_mode(qpdf, QPDF_TRUE);
  972 + qpdf_set_suppress_original_object_IDs(qpdf, QPDF_TRUE);
  973 + qpdf_write(qpdf);
  974 + report_errors();
  975 + qpdf_cleanup(&qpdf2);
  976 +}
  977 +
  978 +static void test35(char const* infile,
  979 + char const* password,
  980 + char const* outfile,
  981 + char const* xarg)
  982 +{
  983 + /* This test uses 11-pages.pdf */
  984 +
  985 + assert(qpdf_get_num_pages(qpdf) == -1);
  986 + assert(qpdf_has_error(qpdf));
  987 + qpdf_error e = qpdf_get_error(qpdf);
  988 + assert(qpdf_get_error_code(qpdf, e) != QPDF_SUCCESS);
  989 + assert(! qpdf_has_error(qpdf));
  990 +
  991 + assert(qpdf_read(qpdf, infile, password) == 0);
  992 +
  993 + qpdf_oh range = qpdf_get_page_n(qpdf, 11);
  994 + assert(! qpdf_oh_is_initialized(qpdf, range));
  995 + assert(qpdf_has_error(qpdf));
  996 + e = qpdf_get_error(qpdf);
  997 + assert(qpdf_get_error_code(qpdf, e) != QPDF_SUCCESS);
  998 + assert(! qpdf_has_error(qpdf));
  999 +
  1000 + assert(qpdf_find_page_by_id(qpdf, 100, 0) == -1);
  1001 + assert(qpdf_has_error(qpdf));
  1002 + e = qpdf_get_error(qpdf);
  1003 + assert(qpdf_get_error_code(qpdf, e) != QPDF_SUCCESS);
  1004 + assert(! qpdf_has_error(qpdf));
  1005 +
  1006 + assert(qpdf_find_page_by_oh(qpdf, qpdf_get_root(qpdf)) == -1);
  1007 + assert(qpdf_more_warnings(qpdf));
  1008 + e = qpdf_next_warning(qpdf);
  1009 + assert(qpdf_get_error_code(qpdf, e) != QPDF_SUCCESS);
  1010 + assert(! qpdf_has_error(qpdf));
  1011 +
  1012 + assert(qpdf_find_page_by_id(qpdf, 100, 0) == -1);
  1013 + assert(qpdf_has_error(qpdf));
  1014 + e = qpdf_get_error(qpdf);
  1015 + assert(qpdf_get_error_code(qpdf, e) != QPDF_SUCCESS);
  1016 + assert(! qpdf_has_error(qpdf));
  1017 +
  1018 + assert(qpdf_add_page(qpdf, qpdf, 1000, QPDF_FALSE) != 0);
  1019 +
  1020 + report_errors();
  1021 +}
  1022 +
  1023 +static void test36(char const* infile,
  1024 + char const* password,
  1025 + char const* outfile,
  1026 + char const* xarg)
  1027 +{
  1028 + /* This test uses inherited-rotate.pdf */
  1029 +
  1030 + assert(qpdf_read(qpdf, infile, password) == 0);
  1031 +
  1032 + /* Non-trivially push inherited attributes */
  1033 + qpdf_oh page0 = qpdf_get_object_by_id(qpdf, 3, 0);
  1034 + assert(qpdf_oh_is_dictionary(qpdf, page0));
  1035 + qpdf_oh r = qpdf_oh_get_key(qpdf, page0, "/Rotate");
  1036 + assert(qpdf_oh_get_int_value(qpdf, r) == 90);
  1037 + qpdf_oh_remove_key(qpdf, page0, "/Rotate");
  1038 + assert(! qpdf_oh_has_key(qpdf, page0, "/Rotate"));
  1039 +
  1040 + assert(qpdf_push_inherited_attributes_to_page(qpdf) == 0);
  1041 + r = qpdf_oh_get_key(qpdf, page0, "/Rotate");
  1042 + assert(qpdf_oh_get_int_value(qpdf, r) == 270);
  1043 +
  1044 + assert(qpdf_add_page(qpdf, qpdf, page0, QPDF_TRUE) == 0);
  1045 +}
  1046 +
  1047 +static void test37(char const* infile,
  1048 + char const* password,
  1049 + char const* outfile,
  1050 + char const* xarg)
  1051 +{
  1052 + /* This test uses 11-pages.pdf */
  1053 +
  1054 + /* Manually manipulate pages tree */
  1055 + assert(qpdf_read(qpdf, infile, password) == 0);
  1056 + assert(qpdf_get_num_pages(qpdf) == 11);
  1057 + qpdf_oh pages = qpdf_get_object_by_id(qpdf, 3, 0);
  1058 + qpdf_oh kids = qpdf_oh_get_key(qpdf, pages, "/Kids");
  1059 + assert(qpdf_oh_get_array_n_items(qpdf, kids) == 11);
  1060 + qpdf_oh_erase_item(qpdf, kids, 0);
  1061 + assert(qpdf_get_num_pages(qpdf) == 11);
  1062 + assert(qpdf_update_all_pages_cache(qpdf) == 0);
  1063 + assert(qpdf_get_num_pages(qpdf) == 10);
  1064 +}
  1065 +
934 int main(int argc, char* argv[]) 1066 int main(int argc, char* argv[])
935 { 1067 {
936 char* p = 0; 1068 char* p = 0;
@@ -1004,6 +1136,10 @@ int main(int argc, char* argv[]) @@ -1004,6 +1136,10 @@ int main(int argc, char* argv[])
1004 (n == 31) ? test31 : 1136 (n == 31) ? test31 :
1005 (n == 32) ? test32 : 1137 (n == 32) ? test32 :
1006 (n == 33) ? test33 : 1138 (n == 33) ? test33 :
  1139 + (n == 34) ? test34 :
  1140 + (n == 35) ? test35 :
  1141 + (n == 36) ? test36 :
  1142 + (n == 37) ? test37 :
1007 0); 1143 0);
1008 1144
1009 if (fn == 0) 1145 if (fn == 0)
qpdf/qpdf.testcov
@@ -608,3 +608,12 @@ qpdf-c registered oh error handler 0 @@ -608,3 +608,12 @@ qpdf-c registered oh error handler 0
608 qpdf-c cleanup warned about unhandled error 0 608 qpdf-c cleanup warned about unhandled error 0
609 qpdf-c called qpdf_get_object_by_id 0 609 qpdf-c called qpdf_get_object_by_id 0
610 qpdf-c called qpdf_replace_object 0 610 qpdf-c called qpdf_replace_object 0
  611 +qpdf-c called qpdf_num_pages 0
  612 +qpdf-c called qpdf_get_page_n 0
  613 +qpdf-c called qpdf_update_all_pages_cache 0
  614 +qpdf-c called qpdf_find_page_by_id 0
  615 +qpdf-c called qpdf_find_page_by_oh 0
  616 +qpdf-c called qpdf_push_inherited_attributes_to_page 0
  617 +qpdf-c called qpdf_add_page 0
  618 +qpdf-c called qpdf_add_page_at 0
  619 +qpdf-c called qpdf_remove_page 0
qpdf/qtest/qpdf.test
@@ -4870,6 +4870,36 @@ $td-&gt;runtest(&quot;C get object by ID&quot;, @@ -4870,6 +4870,36 @@ $td-&gt;runtest(&quot;C get object by ID&quot;,
4870 4870
4871 show_ntests(); 4871 show_ntests();
4872 # ---------- 4872 # ----------
  4873 +$td->notify("--- C API Page Functions ---");
  4874 +$n_tests += 5;
  4875 +
  4876 +$td->runtest("C page normal",
  4877 + {$td->COMMAND =>
  4878 + "qpdf-ctest 34 11-pages.pdf '' a.pdf minimal.pdf"},
  4879 + {$td->STRING => "", $td->EXIT_STATUS => 0},
  4880 + $td->NORMALIZE_NEWLINES);
  4881 +$td->runtest("check output",
  4882 + {$td->FILE => 'a.pdf'},
  4883 + {$td->FILE => 'c-pages.pdf'});
  4884 +
  4885 +$td->runtest("C page errors",
  4886 + {$td->COMMAND =>
  4887 + "qpdf-ctest 35 11-pages.pdf '' ''"},
  4888 + {$td->FILE => "c-page-errors.out", $td->EXIT_STATUS => 0},
  4889 + $td->NORMALIZE_NEWLINES);
  4890 +$td->runtest("C inherited page resources",
  4891 + {$td->COMMAND =>
  4892 + "qpdf-ctest 36 inherited-rotate.pdf '' ''"},
  4893 + {$td->STRING => "", $td->EXIT_STATUS => 0},
  4894 + $td->NORMALIZE_NEWLINES);
  4895 +$td->runtest("C pages cache",
  4896 + {$td->COMMAND =>
  4897 + "qpdf-ctest 37 11-pages.pdf '' ''"},
  4898 + {$td->STRING => "", $td->EXIT_STATUS => 0},
  4899 + $td->NORMALIZE_NEWLINES);
  4900 +
  4901 +show_ntests();
  4902 +# ----------
4873 $td->notify("--- Content Preservation Tests ---"); 4903 $td->notify("--- Content Preservation Tests ---");
4874 # $n_tests incremented below 4904 # $n_tests incremented below
4875 4905
qpdf/qtest/qpdf/c-page-errors.out 0 โ†’ 100644
  1 +11-pages.pdf (page object: object 1 0): page object not referenced in /Pages tree
  2 +11-pages.pdf (C API object handle 1000): attempted access to unknown object handle
  3 +WARNING: object 27 0: operation for dictionary attempted on object of type null: ignoring key replacement request
  4 +warning: object 27 0: operation for dictionary attempted on object of type null: ignoring key replacement request
  5 + code: 7
  6 + file:
  7 + pos : 0
  8 + text: operation for dictionary attempted on object of type null: ignoring key replacement request
qpdf/qtest/qpdf/c-pages.pdf 0 โ†’ 100644
  1 +%PDF-1.4
  2 +%ยฟรทยขรพ
  3 +%QDF-1.0
  4 +
  5 +1 0 obj
  6 +<<
  7 + /Pages 3 0 R
  8 + /Type /Catalog
  9 +>>
  10 +endobj
  11 +
  12 +2 0 obj
  13 +<<
  14 + /CreationDate (D:20120721200217)
  15 + /Producer (Apex PDFWriter)
  16 +>>
  17 +endobj
  18 +
  19 +3 0 obj
  20 +<<
  21 + /Count 13
  22 + /Kids [
  23 + 4 0 R
  24 + 5 0 R
  25 + 6 0 R
  26 + 7 0 R
  27 + 8 0 R
  28 + 9 0 R
  29 + 10 0 R
  30 + 11 0 R
  31 + 12 0 R
  32 + 13 0 R
  33 + 14 0 R
  34 + 15 0 R
  35 + 16 0 R
  36 + ]
  37 + /Type /Pages
  38 +>>
  39 +endobj
  40 +
  41 +%% Page 1
  42 +4 0 obj
  43 +<<
  44 + /Contents 17 0 R
  45 + /MediaBox [
  46 + 0
  47 + 0
  48 + 612
  49 + 792
  50 + ]
  51 + /Parent 3 0 R
  52 + /Resources <<
  53 + /Font <<
  54 + /F1 19 0 R
  55 + >>
  56 + /ProcSet [
  57 + /PDF
  58 + /Text
  59 + ]
  60 + >>
  61 + /Type /Page
  62 +>>
  63 +endobj
  64 +
  65 +%% Page 2
  66 +5 0 obj
  67 +<<
  68 + /Contents 20 0 R
  69 + /MediaBox [
  70 + 0
  71 + 0
  72 + 612
  73 + 792
  74 + ]
  75 + /Parent 3 0 R
  76 + /Resources <<
  77 + /Font <<
  78 + /F1 19 0 R
  79 + >>
  80 + /ProcSet [
  81 + /PDF
  82 + /Text
  83 + ]
  84 + >>
  85 + /Type /Page
  86 +>>
  87 +endobj
  88 +
  89 +%% Page 3
  90 +6 0 obj
  91 +<<
  92 + /Contents 22 0 R
  93 + /MediaBox [
  94 + 0
  95 + 0
  96 + 612
  97 + 792
  98 + ]
  99 + /Parent 3 0 R
  100 + /Resources <<
  101 + /Font <<
  102 + /F1 19 0 R
  103 + >>
  104 + /ProcSet [
  105 + /PDF
  106 + /Text
  107 + ]
  108 + >>
  109 + /Type /Page
  110 +>>
  111 +endobj
  112 +
  113 +%% Page 4
  114 +7 0 obj
  115 +<<
  116 + /Contents 24 0 R
  117 + /MediaBox [
  118 + 0
  119 + 0
  120 + 612
  121 + 792
  122 + ]
  123 + /Parent 3 0 R
  124 + /Resources <<
  125 + /Font <<
  126 + /F1 19 0 R
  127 + >>
  128 + /ProcSet [
  129 + /PDF
  130 + /Text
  131 + ]
  132 + >>
  133 + /Type /Page
  134 +>>
  135 +endobj
  136 +
  137 +%% Page 5
  138 +8 0 obj
  139 +<<
  140 + /Contents 26 0 R
  141 + /MediaBox [
  142 + 0
  143 + 0
  144 + 612
  145 + 792
  146 + ]
  147 + /Parent 3 0 R
  148 + /Resources <<
  149 + /Font <<
  150 + /F1 28 0 R
  151 + >>
  152 + /ProcSet 29 0 R
  153 + >>
  154 + /Type /Page
  155 +>>
  156 +endobj
  157 +
  158 +%% Page 6
  159 +9 0 obj
  160 +<<
  161 + /Contents 30 0 R
  162 + /MediaBox [
  163 + 0
  164 + 0
  165 + 612
  166 + 792
  167 + ]
  168 + /Parent 3 0 R
  169 + /Resources <<
  170 + /Font <<
  171 + /F1 19 0 R
  172 + >>
  173 + /ProcSet [
  174 + /PDF
  175 + /Text
  176 + ]
  177 + >>
  178 + /Type /Page
  179 +>>
  180 +endobj
  181 +
  182 +%% Page 7
  183 +10 0 obj
  184 +<<
  185 + /Contents 32 0 R
  186 + /MediaBox [
  187 + 0
  188 + 0
  189 + 612
  190 + 792
  191 + ]
  192 + /Parent 3 0 R
  193 + /Resources <<
  194 + /Font <<
  195 + /F1 19 0 R
  196 + >>
  197 + /ProcSet [
  198 + /PDF
  199 + /Text
  200 + ]
  201 + >>
  202 + /Type /Page
  203 +>>
  204 +endobj
  205 +
  206 +%% Page 8
  207 +11 0 obj
  208 +<<
  209 + /Contents 34 0 R
  210 + /MediaBox [
  211 + 0
  212 + 0
  213 + 612
  214 + 792
  215 + ]
  216 + /Parent 3 0 R
  217 + /Resources <<
  218 + /Font <<
  219 + /F1 19 0 R
  220 + >>
  221 + /ProcSet [
  222 + /PDF
  223 + /Text
  224 + ]
  225 + >>
  226 + /Type /Page
  227 +>>
  228 +endobj
  229 +
  230 +%% Page 9
  231 +12 0 obj
  232 +<<
  233 + /Contents 36 0 R
  234 + /MediaBox [
  235 + 0
  236 + 0
  237 + 612
  238 + 792
  239 + ]
  240 + /Parent 3 0 R
  241 + /Resources <<
  242 + /Font <<
  243 + /F1 19 0 R
  244 + >>
  245 + /ProcSet [
  246 + /PDF
  247 + /Text
  248 + ]
  249 + >>
  250 + /Type /Page
  251 +>>
  252 +endobj
  253 +
  254 +%% Page 10
  255 +13 0 obj
  256 +<<
  257 + /Contents 38 0 R
  258 + /MediaBox [
  259 + 0
  260 + 0
  261 + 612
  262 + 792
  263 + ]
  264 + /Parent 3 0 R
  265 + /Resources <<
  266 + /Font <<
  267 + /F1 19 0 R
  268 + >>
  269 + /ProcSet [
  270 + /PDF
  271 + /Text
  272 + ]
  273 + >>
  274 + /Type /Page
  275 +>>
  276 +endobj
  277 +
  278 +%% Page 11
  279 +14 0 obj
  280 +<<
  281 + /Contents 40 0 R
  282 + /MediaBox [
  283 + 0
  284 + 0
  285 + 612
  286 + 792
  287 + ]
  288 + /Parent 3 0 R
  289 + /Resources <<
  290 + /Font <<
  291 + /F1 19 0 R
  292 + >>
  293 + /ProcSet [
  294 + /PDF
  295 + /Text
  296 + ]
  297 + >>
  298 + /Type /Page
  299 +>>
  300 +endobj
  301 +
  302 +%% Page 12
  303 +15 0 obj
  304 +<<
  305 + /Contents 42 0 R
  306 + /MediaBox [
  307 + 0
  308 + 0
  309 + 612
  310 + 792
  311 + ]
  312 + /Parent 3 0 R
  313 + /Resources <<
  314 + /Font <<
  315 + /F1 19 0 R
  316 + >>
  317 + /ProcSet [
  318 + /PDF
  319 + /Text
  320 + ]
  321 + >>
  322 + /Type /Page
  323 +>>
  324 +endobj
  325 +
  326 +%% Page 13
  327 +16 0 obj
  328 +<<
  329 + /Contents 26 0 R
  330 + /MediaBox [
  331 + 0
  332 + 0
  333 + 612
  334 + 792
  335 + ]
  336 + /Parent 3 0 R
  337 + /Resources <<
  338 + /Font <<
  339 + /F1 28 0 R
  340 + >>
  341 + /ProcSet 29 0 R
  342 + >>
  343 + /Type /Page
  344 +>>
  345 +endobj
  346 +
  347 +%% Contents for page 1
  348 +17 0 obj
  349 +<<
  350 + /Length 18 0 R
  351 +>>
  352 +stream
  353 +BT /F1 15 Tf 72 720 Td (Original page 4) Tj ET
  354 +endstream
  355 +endobj
  356 +
  357 +18 0 obj
  358 +47
  359 +endobj
  360 +
  361 +19 0 obj
  362 +<<
  363 + /BaseFont /Times-Roman
  364 + /Encoding /WinAnsiEncoding
  365 + /Subtype /Type1
  366 + /Type /Font
  367 +>>
  368 +endobj
  369 +
  370 +%% Contents for page 2
  371 +20 0 obj
  372 +<<
  373 + /Length 21 0 R
  374 +>>
  375 +stream
  376 +BT /F1 15 Tf 72 720 Td (Original page 1) Tj ET
  377 +endstream
  378 +endobj
  379 +
  380 +21 0 obj
  381 +47
  382 +endobj
  383 +
  384 +%% Contents for page 3
  385 +22 0 obj
  386 +<<
  387 + /Length 23 0 R
  388 +>>
  389 +stream
  390 +BT /F1 15 Tf 72 720 Td (Original page 2) Tj ET
  391 +endstream
  392 +endobj
  393 +
  394 +23 0 obj
  395 +47
  396 +endobj
  397 +
  398 +%% Contents for page 4
  399 +24 0 obj
  400 +<<
  401 + /Length 25 0 R
  402 +>>
  403 +stream
  404 +BT /F1 15 Tf 72 720 Td (Original page 3) Tj ET
  405 +endstream
  406 +endobj
  407 +
  408 +25 0 obj
  409 +47
  410 +endobj
  411 +
  412 +%% Contents for page 13
  413 +26 0 obj
  414 +<<
  415 + /Length 27 0 R
  416 +>>
  417 +stream
  418 +BT
  419 + /F1 24 Tf
  420 + 72 720 Td
  421 + (Potato) Tj
  422 +ET
  423 +endstream
  424 +endobj
  425 +
  426 +27 0 obj
  427 +44
  428 +endobj
  429 +
  430 +28 0 obj
  431 +<<
  432 + /BaseFont /Helvetica
  433 + /Encoding /WinAnsiEncoding
  434 + /Name /F1
  435 + /Subtype /Type1
  436 + /Type /Font
  437 +>>
  438 +endobj
  439 +
  440 +29 0 obj
  441 +[
  442 + /PDF
  443 + /Text
  444 +]
  445 +endobj
  446 +
  447 +%% Contents for page 6
  448 +30 0 obj
  449 +<<
  450 + /Length 31 0 R
  451 +>>
  452 +stream
  453 +BT /F1 15 Tf 72 720 Td (Original page 5) Tj ET
  454 +endstream
  455 +endobj
  456 +
  457 +31 0 obj
  458 +47
  459 +endobj
  460 +
  461 +%% Contents for page 7
  462 +32 0 obj
  463 +<<
  464 + /Length 33 0 R
  465 +>>
  466 +stream
  467 +BT /F1 15 Tf 72 720 Td (Original page 6) Tj ET
  468 +endstream
  469 +endobj
  470 +
  471 +33 0 obj
  472 +47
  473 +endobj
  474 +
  475 +%% Contents for page 8
  476 +34 0 obj
  477 +<<
  478 + /Length 35 0 R
  479 +>>
  480 +stream
  481 +BT /F1 15 Tf 72 720 Td (Original page 7) Tj ET
  482 +endstream
  483 +endobj
  484 +
  485 +35 0 obj
  486 +47
  487 +endobj
  488 +
  489 +%% Contents for page 9
  490 +36 0 obj
  491 +<<
  492 + /Length 37 0 R
  493 +>>
  494 +stream
  495 +BT /F1 15 Tf 72 720 Td (Original page 8) Tj ET
  496 +endstream
  497 +endobj
  498 +
  499 +37 0 obj
  500 +47
  501 +endobj
  502 +
  503 +%% Contents for page 10
  504 +38 0 obj
  505 +<<
  506 + /Length 39 0 R
  507 +>>
  508 +stream
  509 +BT /F1 15 Tf 72 720 Td (Original page 9) Tj ET
  510 +endstream
  511 +endobj
  512 +
  513 +39 0 obj
  514 +47
  515 +endobj
  516 +
  517 +%% Contents for page 11
  518 +40 0 obj
  519 +<<
  520 + /Length 41 0 R
  521 +>>
  522 +stream
  523 +BT /F1 15 Tf 72 720 Td (Original page 10) Tj ET
  524 +endstream
  525 +endobj
  526 +
  527 +41 0 obj
  528 +48
  529 +endobj
  530 +
  531 +%% Contents for page 12
  532 +42 0 obj
  533 +<<
  534 + /Length 43 0 R
  535 +>>
  536 +stream
  537 +BT /F1 15 Tf 72 720 Td (Original page 11) Tj ET
  538 +endstream
  539 +endobj
  540 +
  541 +43 0 obj
  542 +48
  543 +endobj
  544 +
  545 +xref
  546 +0 44
  547 +0000000000 65535 f
  548 +0000000025 00000 n
  549 +0000000079 00000 n
  550 +0000000165 00000 n
  551 +0000000375 00000 n
  552 +0000000604 00000 n
  553 +0000000833 00000 n
  554 +0000001062 00000 n
  555 +0000001291 00000 n
  556 +0000001496 00000 n
  557 +0000001725 00000 n
  558 +0000001955 00000 n
  559 +0000002185 00000 n
  560 +0000002416 00000 n
  561 +0000002647 00000 n
  562 +0000002878 00000 n
  563 +0000003109 00000 n
  564 +0000003328 00000 n
  565 +0000003432 00000 n
  566 +0000003452 00000 n
  567 +0000003584 00000 n
  568 +0000003688 00000 n
  569 +0000003731 00000 n
  570 +0000003835 00000 n
  571 +0000003878 00000 n
  572 +0000003982 00000 n
  573 +0000004026 00000 n
  574 +0000004127 00000 n
  575 +0000004147 00000 n
  576 +0000004266 00000 n
  577 +0000004325 00000 n
  578 +0000004429 00000 n
  579 +0000004472 00000 n
  580 +0000004576 00000 n
  581 +0000004619 00000 n
  582 +0000004723 00000 n
  583 +0000004766 00000 n
  584 +0000004870 00000 n
  585 +0000004914 00000 n
  586 +0000005018 00000 n
  587 +0000005062 00000 n
  588 +0000005167 00000 n
  589 +0000005211 00000 n
  590 +0000005316 00000 n
  591 +trailer <<
  592 + /Info 2 0 R
  593 + /Root 1 0 R
  594 + /Size 44
  595 + /ID [<e032a88c7a987db6ca3abee555506ccc><31415926535897932384626433832795>]
  596 +>>
  597 +startxref
  598 +5336
  599 +%%EOF