Commit 7b6ab900dced033465172976abeb3497454a1a7a

Authored by Jay Berkenbilt
1 parent 16fd6e64

Support page collation with --collate (fixes #259)

ChangeLog
1 2019-01-04 Jay Berkenbilt <ejb@ql.org> 1 2019-01-04 Jay Berkenbilt <ejb@ql.org>
2 2
  3 + * Add new option --collate. When specified, the semantics of
  4 + --pages change from concatenation to collation. See the manual for
  5 + a more detailed discussion. Fixes #259.
  6 +
3 * Add new method QPDFWriter::getFinalVersion, which returns the 7 * Add new method QPDFWriter::getFinalVersion, which returns the
4 PDF version that will ultimately be written to the final file. See 8 PDF version that will ultimately be written to the final file. See
5 comments in QPDFWriter.hh for some restrictions on its use. Fixes 9 comments in QPDFWriter.hh for some restrictions on its use. Fixes
qpdf/qpdf.cc
@@ -124,6 +124,7 @@ struct Options @@ -124,6 +124,7 @@ struct Options
124 show_filtered_stream_data(false), 124 show_filtered_stream_data(false),
125 show_pages(false), 125 show_pages(false),
126 show_page_images(false), 126 show_page_images(false),
  127 + collate(false),
127 json(false), 128 json(false),
128 check(false), 129 check(false),
129 require_outfile(true), 130 require_outfile(true),
@@ -202,6 +203,7 @@ struct Options @@ -202,6 +203,7 @@ struct Options
202 bool show_filtered_stream_data; 203 bool show_filtered_stream_data;
203 bool show_pages; 204 bool show_pages;
204 bool show_page_images; 205 bool show_page_images;
  206 + bool collate;
205 bool json; 207 bool json;
206 std::set<std::string> json_keys; 208 std::set<std::string> json_keys;
207 std::set<std::string> json_objects; 209 std::set<std::string> json_objects;
@@ -216,6 +218,7 @@ struct Options @@ -216,6 +218,7 @@ struct Options
216 struct QPDFPageData 218 struct QPDFPageData
217 { 219 {
218 QPDFPageData(std::string const& filename, QPDF* qpdf, char const* range); 220 QPDFPageData(std::string const& filename, QPDF* qpdf, char const* range);
  221 + QPDFPageData(QPDFPageData const& other, int page);
219 222
220 std::string filename; 223 std::string filename;
221 QPDF* qpdf; 224 QPDF* qpdf;
@@ -557,6 +560,7 @@ class ArgParser @@ -557,6 +560,7 @@ class ArgParser
557 void argEncryptionFilePassword(char* parameter); 560 void argEncryptionFilePassword(char* parameter);
558 void argPages(); 561 void argPages();
559 void argRotate(char* parameter); 562 void argRotate(char* parameter);
  563 + void argCollate();
560 void argStreamData(char* parameter); 564 void argStreamData(char* parameter);
561 void argCompressStreams(char* parameter); 565 void argCompressStreams(char* parameter);
562 void argDecodeLevel(char* parameter); 566 void argDecodeLevel(char* parameter);
@@ -743,6 +747,7 @@ ArgParser::initOptionTable() @@ -743,6 +747,7 @@ ArgParser::initOptionTable()
743 &ArgParser::argRotate, "[+|-]angle:page-range"); 747 &ArgParser::argRotate, "[+|-]angle:page-range");
744 char const* stream_data_choices[] = 748 char const* stream_data_choices[] =
745 {"compress", "preserve", "uncompress", 0}; 749 {"compress", "preserve", "uncompress", 0};
  750 + (*t)["collate"] = oe_bare(&ArgParser::argCollate);
746 (*t)["stream-data"] = oe_requiredChoices( 751 (*t)["stream-data"] = oe_requiredChoices(
747 &ArgParser::argStreamData, stream_data_choices); 752 &ArgParser::argStreamData, stream_data_choices);
748 (*t)["compress-streams"] = oe_requiredChoices( 753 (*t)["compress-streams"] = oe_requiredChoices(
@@ -1063,6 +1068,12 @@ ArgParser::argEncryptionFilePassword(char* parameter) @@ -1063,6 +1068,12 @@ ArgParser::argEncryptionFilePassword(char* parameter)
1063 } 1068 }
1064 1069
1065 void 1070 void
  1071 +ArgParser::argCollate()
  1072 +{
  1073 + o.collate = true;
  1074 +}
  1075 +
  1076 +void
1066 ArgParser::argPages() 1077 ArgParser::argPages()
1067 { 1078 {
1068 ++cur_arg; 1079 ++cur_arg;
@@ -1711,6 +1722,8 @@ Basic Options\n\ @@ -1711,6 +1722,8 @@ Basic Options\n\
1711 --decrypt remove any encryption on the file\n\ 1722 --decrypt remove any encryption on the file\n\
1712 --password-is-hex-key treat primary password option as a hex-encoded key\n\ 1723 --password-is-hex-key treat primary password option as a hex-encoded key\n\
1713 --pages options -- select specific pages from one or more files\n\ 1724 --pages options -- select specific pages from one or more files\n\
  1725 +--collate causes files specified in --pages to be collated\n\
  1726 + rather than concatenated\n\
1714 --rotate=[+|-]angle[:page-range]\n\ 1727 --rotate=[+|-]angle[:page-range]\n\
1715 rotate each specified page 90, 180, or 270 degrees;\n\ 1728 rotate each specified page 90, 180, or 270 degrees;\n\
1716 rotate all pages if no page range is given\n\ 1729 rotate all pages if no page range is given\n\
@@ -1854,6 +1867,14 @@ If the page range is omitted, the range of 1-z is assumed. qpdf decides\n\ @@ -1854,6 +1867,14 @@ If the page range is omitted, the range of 1-z is assumed. qpdf decides\n\
1854 that the page range is omitted if the range argument is either -- or a\n\ 1867 that the page range is omitted if the range argument is either -- or a\n\
1855 valid file name and not a valid range.\n\ 1868 valid file name and not a valid range.\n\
1856 \n\ 1869 \n\
  1870 +The usual behavior of --pages is to add all pages from the first file,\n\
  1871 +then all pages from the second file, and so on. If the --collate option\n\
  1872 +is specified, then pages are collated instead. In other words, qpdf takes\n\
  1873 +the first page from the first file, the first page from the second file,\n\
  1874 +and so on until it runs out of files; then it takes the second page from\n\
  1875 +each file, etc. When a file runs out of pages, it is skipped until all\n\
  1876 +specified pages are taken from all files.\n\
  1877 +\n\
1857 See the manual for examples and a discussion of additional subtleties.\n\ 1878 See the manual for examples and a discussion of additional subtleties.\n\
1858 \n\ 1879 \n\
1859 \n\ 1880 \n\
@@ -2225,6 +2246,14 @@ QPDFPageData::QPDFPageData(std::string const&amp; filename, @@ -2225,6 +2246,14 @@ QPDFPageData::QPDFPageData(std::string const&amp; filename,
2225 } 2246 }
2226 } 2247 }
2227 2248
  2249 +QPDFPageData::QPDFPageData(QPDFPageData const& other, int page) :
  2250 + filename(other.filename),
  2251 + qpdf(other.qpdf),
  2252 + orig_pages(other.orig_pages)
  2253 +{
  2254 + this->selected_pages.push_back(page);
  2255 +}
  2256 +
2228 static void parse_version(std::string const& full_version_string, 2257 static void parse_version(std::string const& full_version_string,
2229 std::string& version, int& extension_level) 2258 std::string& version, int& extension_level)
2230 { 2259 {
@@ -3553,6 +3582,35 @@ static void handle_page_specs(QPDF&amp; pdf, Options&amp; o, @@ -3553,6 +3582,35 @@ static void handle_page_specs(QPDF&amp; pdf, Options&amp; o,
3553 dh.removePage(*iter); 3582 dh.removePage(*iter);
3554 } 3583 }
3555 3584
  3585 + if (o.collate && (parsed_specs.size() > 1))
  3586 + {
  3587 + // Collate the pages by selecting one page from each spec in
  3588 + // order. When a spec runs out of pages, stop selecting from
  3589 + // it.
  3590 + std::vector<QPDFPageData> new_parsed_specs;
  3591 + size_t nspecs = parsed_specs.size();
  3592 + size_t cur_page = 0;
  3593 + bool got_pages = true;
  3594 + while (got_pages)
  3595 + {
  3596 + got_pages = false;
  3597 + for (size_t i = 0; i < nspecs; ++i)
  3598 + {
  3599 + QPDFPageData& page_data = parsed_specs.at(i);
  3600 + if (cur_page < page_data.selected_pages.size())
  3601 + {
  3602 + got_pages = true;
  3603 + new_parsed_specs.push_back(
  3604 + QPDFPageData(
  3605 + page_data,
  3606 + page_data.selected_pages.at(cur_page)));
  3607 + }
  3608 + }
  3609 + ++cur_page;
  3610 + }
  3611 + parsed_specs = new_parsed_specs;
  3612 + }
  3613 +
3556 // Add all the pages from all the files in the order specified. 3614 // Add all the pages from all the files in the order specified.
3557 // Keep track of any pages from the original file that we are 3615 // Keep track of any pages from the original file that we are
3558 // selecting. 3616 // selecting.
qpdf/qtest/qpdf.test
@@ -1739,6 +1739,28 @@ $td-&gt;runtest(&quot;check output&quot;, @@ -1739,6 +1739,28 @@ $td-&gt;runtest(&quot;check output&quot;,
1739 1739
1740 show_ntests(); 1740 show_ntests();
1741 # ---------- 1741 # ----------
  1742 +$td->notify("--- Collating ---");
  1743 +my @collate = (
  1744 + ["three-files", "collate-odd",
  1745 + "collate-odd.pdf 1-5 minimal.pdf collate-even.pdf 7-1"],
  1746 + );
  1747 +$n_tests += 2 * scalar(@collate);
  1748 +
  1749 +foreach my $d (@collate)
  1750 +{
  1751 + my ($description, $first, $args) = @$d;
  1752 + $td->runtest("collate pages: $description",
  1753 + {$td->COMMAND =>
  1754 + "qpdf --qdf --static-id --collate $first.pdf" .
  1755 + " --pages $args -- a.pdf"},
  1756 + {$td->STRING => "", $td->EXIT_STATUS => 0});
  1757 + $td->runtest("check output",
  1758 + {$td->FILE => "a.pdf"},
  1759 + {$td->FILE => "$description-collate-out.pdf"});
  1760 +}
  1761 +
  1762 +show_ntests();
  1763 +# ----------
1742 $td->notify("--- PDF From Scratch ---"); 1764 $td->notify("--- PDF From Scratch ---");
1743 $n_tests += 2; 1765 $n_tests += 2;
1744 1766
qpdf/qtest/qpdf/collate-even.pdf 0 โ†’ 100644
No preview for this file type
qpdf/qtest/qpdf/collate-odd.pdf 0 โ†’ 100644
No preview for this file type
qpdf/qtest/qpdf/three-files-collate-out.pdf 0 โ†’ 100644
  1 +%PDF-1.3
  2 +%ยฟรทยขรพ
  3 +%QDF-1.0
  4 +
  5 +%% Original object ID: 1 0
  6 +1 0 obj
  7 +<<
  8 + /Outlines 2 0 R
  9 + /PageLabels <<
  10 + /Nums [
  11 + 0
  12 + <<
  13 + /P ()
  14 + /St 1
  15 + >>
  16 + 1
  17 + <<
  18 + /St 2
  19 + >>
  20 + 2
  21 + <<
  22 + /S /D
  23 + /St 3
  24 + >>
  25 + 3
  26 + <<
  27 + /S /r
  28 + /St 1
  29 + >>
  30 + 4
  31 + <<
  32 + /P ()
  33 + /St 1
  34 + >>
  35 + 5
  36 + <<
  37 + /S /r
  38 + /St 3
  39 + >>
  40 + 6
  41 + <<
  42 + /S /r
  43 + /St 6
  44 + >>
  45 + 7
  46 + <<
  47 + /S /r
  48 + /St 5
  49 + >>
  50 + 8
  51 + <<
  52 + /P ()
  53 + /St 1
  54 + >>
  55 + 10
  56 + <<
  57 + /S /r
  58 + /St 4
  59 + >>
  60 + 11
  61 + <<
  62 + /S /r
  63 + /St 2
  64 + >>
  65 + 12
  66 + <<
  67 + /P ()
  68 + /St 2
  69 + >>
  70 + ]
  71 + >>
  72 + /PageMode /UseOutlines
  73 + /Pages 3 0 R
  74 + /Type /Catalog
  75 +>>
  76 +endobj
  77 +
  78 +%% Original object ID: 2 0
  79 +2 0 obj
  80 +<<
  81 + /Count 6
  82 + /First 4 0 R
  83 + /Last 5 0 R
  84 + /Type /Outlines
  85 +>>
  86 +endobj
  87 +
  88 +%% Original object ID: 3 0
  89 +3 0 obj
  90 +<<
  91 + /Count 13
  92 + /Kids [
  93 + 6 0 R
  94 + 7 0 R
  95 + 8 0 R
  96 + 9 0 R
  97 + 10 0 R
  98 + 11 0 R
  99 + 12 0 R
  100 + 13 0 R
  101 + 14 0 R
  102 + 15 0 R
  103 + 16 0 R
  104 + 17 0 R
  105 + 18 0 R
  106 + ]
  107 + /Type /Pages
  108 +>>
  109 +endobj
  110 +
  111 +%% Original object ID: 4 0
  112 +4 0 obj
  113 +<<
  114 + /Count 4
  115 + /Dest [
  116 + null
  117 + /XYZ
  118 + null
  119 + null
  120 + null
  121 + ]
  122 + /First 19 0 R
  123 + /Last 20 0 R
  124 + /Next 5 0 R
  125 + /Parent 2 0 R
  126 + /Title (Isรญs 1 -> 5: /XYZ null null null)
  127 + /Type /Outline
  128 +>>
  129 +endobj
  130 +
  131 +%% Original object ID: 5 0
  132 +5 0 obj
  133 +<<
  134 + /Dest [
  135 + null
  136 + /XYZ
  137 + 66
  138 + 756
  139 + 3
  140 + ]
  141 + /Parent 2 0 R
  142 + /Prev 4 0 R
  143 + /Title (Trepak 2 -> 15: /XYZ 66 756 3)
  144 + /Type /Outline
  145 +>>
  146 +endobj
  147 +
  148 +%% Page 1
  149 +%% Original object ID: 6 0
  150 +6 0 obj
  151 +<<
  152 + /Contents 21 0 R
  153 + /MediaBox [
  154 + 0
  155 + 0
  156 + 612
  157 + 792
  158 + ]
  159 + /Parent 3 0 R
  160 + /Resources <<
  161 + /Font <<
  162 + /F1 23 0 R
  163 + >>
  164 + /ProcSet 24 0 R
  165 + >>
  166 + /Type /Page
  167 +>>
  168 +endobj
  169 +
  170 +%% Page 2
  171 +%% Original object ID: 47 0
  172 +7 0 obj
  173 +<<
  174 + /Contents 25 0 R
  175 + /MediaBox [
  176 + 0
  177 + 0
  178 + 612
  179 + 792
  180 + ]
  181 + /Parent 3 0 R
  182 + /Resources <<
  183 + /Font <<
  184 + /F1 27 0 R
  185 + >>
  186 + /ProcSet 28 0 R
  187 + >>
  188 + /Type /Page
  189 +>>
  190 +endobj
  191 +
  192 +%% Page 3
  193 +%% Original object ID: 51 0
  194 +8 0 obj
  195 +<<
  196 + /Contents 29 0 R
  197 + /MediaBox [
  198 + 0
  199 + 0
  200 + 612
  201 + 792
  202 + ]
  203 + /Parent 3 0 R
  204 + /Resources <<
  205 + /Font <<
  206 + /F1 31 0 R
  207 + >>
  208 + /ProcSet 32 0 R
  209 + >>
  210 + /Type /Page
  211 +>>
  212 +endobj
  213 +
  214 +%% Page 4
  215 +%% Original object ID: 7 0
  216 +9 0 obj
  217 +<<
  218 + /Contents 33 0 R
  219 + /MediaBox [
  220 + 0
  221 + 0
  222 + 612
  223 + 792
  224 + ]
  225 + /Parent 3 0 R
  226 + /Resources <<
  227 + /Font <<
  228 + /F1 23 0 R
  229 + >>
  230 + /ProcSet 24 0 R
  231 + >>
  232 + /Type /Page
  233 +>>
  234 +endobj
  235 +
  236 +%% Page 5
  237 +%% Original object ID: 55 0
  238 +10 0 obj
  239 +<<
  240 + /Contents 35 0 R
  241 + /MediaBox [
  242 + 0
  243 + 0
  244 + 612
  245 + 792
  246 + ]
  247 + /Parent 3 0 R
  248 + /Resources <<
  249 + /Font <<
  250 + /F1 31 0 R
  251 + >>
  252 + /ProcSet 32 0 R
  253 + >>
  254 + /Type /Page
  255 +>>
  256 +endobj
  257 +
  258 +%% Page 6
  259 +%% Original object ID: 8 0
  260 +11 0 obj
  261 +<<
  262 + /Contents 37 0 R
  263 + /MediaBox [
  264 + 0
  265 + 0
  266 + 612
  267 + 792
  268 + ]
  269 + /Parent 3 0 R
  270 + /Resources <<
  271 + /Font <<
  272 + /F1 23 0 R
  273 + >>
  274 + /ProcSet 24 0 R
  275 + >>
  276 + /Type /Page
  277 +>>
  278 +endobj
  279 +
  280 +%% Page 7
  281 +%% Original object ID: 57 0
  282 +12 0 obj
  283 +<<
  284 + /Contents 39 0 R
  285 + /MediaBox [
  286 + 0
  287 + 0
  288 + 612
  289 + 792
  290 + ]
  291 + /Parent 3 0 R
  292 + /Resources <<
  293 + /Font <<
  294 + /F1 31 0 R
  295 + >>
  296 + /ProcSet 32 0 R
  297 + >>
  298 + /Type /Page
  299 +>>
  300 +endobj
  301 +
  302 +%% Page 8
  303 +%% Original object ID: 9 0
  304 +13 0 obj
  305 +<<
  306 + /Contents 41 0 R
  307 + /MediaBox [
  308 + 0
  309 + 0
  310 + 612
  311 + 792
  312 + ]
  313 + /Parent 3 0 R
  314 + /Resources <<
  315 + /Font <<
  316 + /F1 23 0 R
  317 + >>
  318 + /ProcSet 24 0 R
  319 + >>
  320 + /Type /Page
  321 +>>
  322 +endobj
  323 +
  324 +%% Page 9
  325 +%% Original object ID: 59 0
  326 +14 0 obj
  327 +<<
  328 + /Contents 43 0 R
  329 + /MediaBox [
  330 + 0
  331 + 0
  332 + 612
  333 + 792
  334 + ]
  335 + /Parent 3 0 R
  336 + /Resources <<
  337 + /Font <<
  338 + /F1 31 0 R
  339 + >>
  340 + /ProcSet 32 0 R
  341 + >>
  342 + /Type /Page
  343 +>>
  344 +endobj
  345 +
  346 +%% Page 10
  347 +%% Original object ID: 10 0
  348 +15 0 obj
  349 +<<
  350 + /Contents 45 0 R
  351 + /MediaBox [
  352 + 0
  353 + 0
  354 + 612
  355 + 792
  356 + ]
  357 + /Parent 3 0 R
  358 + /Resources <<
  359 + /Font <<
  360 + /F1 23 0 R
  361 + >>
  362 + /ProcSet 24 0 R
  363 + >>
  364 + /Type /Page
  365 +>>
  366 +endobj
  367 +
  368 +%% Page 11
  369 +%% Original object ID: 61 0
  370 +16 0 obj
  371 +<<
  372 + /Contents 47 0 R
  373 + /MediaBox [
  374 + 0
  375 + 0
  376 + 612
  377 + 792
  378 + ]
  379 + /Parent 3 0 R
  380 + /Resources <<
  381 + /Font <<
  382 + /F1 31 0 R
  383 + >>
  384 + /ProcSet 32 0 R
  385 + >>
  386 + /Type /Page
  387 +>>
  388 +endobj
  389 +
  390 +%% Page 12
  391 +%% Original object ID: 63 0
  392 +17 0 obj
  393 +<<
  394 + /Contents 49 0 R
  395 + /MediaBox [
  396 + 0
  397 + 0
  398 + 612
  399 + 792
  400 + ]
  401 + /Parent 3 0 R
  402 + /Resources <<
  403 + /Font <<
  404 + /F1 31 0 R
  405 + >>
  406 + /ProcSet 32 0 R
  407 + >>
  408 + /Type /Page
  409 +>>
  410 +endobj
  411 +
  412 +%% Page 13
  413 +%% Original object ID: 65 0
  414 +18 0 obj
  415 +<<
  416 + /Contents 51 0 R
  417 + /MediaBox [
  418 + 0
  419 + 0
  420 + 612
  421 + 792
  422 + ]
  423 + /Parent 3 0 R
  424 + /Resources <<
  425 + /Font <<
  426 + /F1 31 0 R
  427 + >>
  428 + /ProcSet 32 0 R
  429 + >>
  430 + /Type /Page
  431 +>>
  432 +endobj
  433 +
  434 +%% Original object ID: 21 0
  435 +19 0 obj
  436 +<<
  437 + /Count -3
  438 + /Dest [
  439 + null
  440 + /Fit
  441 + ]
  442 + /First 53 0 R
  443 + /Last 54 0 R
  444 + /Next 20 0 R
  445 + /Parent 4 0 R
  446 + /Title (Amanda 1.1 -> 11: /Fit)
  447 + /Type /Outline
  448 +>>
  449 +endobj
  450 +
  451 +%% Original object ID: 22 0
  452 +20 0 obj
  453 +<<
  454 + /Count 2
  455 + /Dest [
  456 + null
  457 + /FitH
  458 + 792
  459 + ]
  460 + /First 55 0 R
  461 + /Last 56 0 R
  462 + /Parent 4 0 R
  463 + /Prev 19 0 R
  464 + /Title <feff00530061006e00640079002000f703a303b103bd03b403b900f700200031002e00320020002d003e002000310033003a0020002f00460069007400480020003700390032>
  465 + /Type /Outline
  466 +>>
  467 +endobj
  468 +
  469 +%% Contents for page 1
  470 +%% Original object ID: 23 0
  471 +21 0 obj
  472 +<<
  473 + /Length 22 0 R
  474 +>>
  475 +stream
  476 +BT
  477 + /F1 24 Tf
  478 + 72 720 Td
  479 + (Potato 0) Tj
  480 +ET
  481 +endstream
  482 +endobj
  483 +
  484 +22 0 obj
  485 +46
  486 +endobj
  487 +
  488 +%% Original object ID: 24 0
  489 +23 0 obj
  490 +<<
  491 + /BaseFont /Helvetica
  492 + /Encoding /WinAnsiEncoding
  493 + /Name /F1
  494 + /Subtype /Type1
  495 + /Type /Font
  496 +>>
  497 +endobj
  498 +
  499 +%% Original object ID: 25 0
  500 +24 0 obj
  501 +[
  502 + /PDF
  503 + /Text
  504 +]
  505 +endobj
  506 +
  507 +%% Contents for page 2
  508 +%% Original object ID: 48 0
  509 +25 0 obj
  510 +<<
  511 + /Length 26 0 R
  512 +>>
  513 +stream
  514 +BT
  515 + /F1 24 Tf
  516 + 72 720 Td
  517 + (Potato) Tj
  518 +ET
  519 +endstream
  520 +endobj
  521 +
  522 +26 0 obj
  523 +44
  524 +endobj
  525 +
  526 +%% Original object ID: 49 0
  527 +27 0 obj
  528 +<<
  529 + /BaseFont /Helvetica
  530 + /Encoding /WinAnsiEncoding
  531 + /Name /F1
  532 + /Subtype /Type1
  533 + /Type /Font
  534 +>>
  535 +endobj
  536 +
  537 +%% Original object ID: 50 0
  538 +28 0 obj
  539 +[
  540 + /PDF
  541 + /Text
  542 +]
  543 +endobj
  544 +
  545 +%% Contents for page 3
  546 +%% Original object ID: 52 0
  547 +29 0 obj
  548 +<<
  549 + /Length 30 0 R
  550 +>>
  551 +stream
  552 +BT
  553 + /F1 24 Tf
  554 + 72 720 Td
  555 + (Potato 13) Tj
  556 +ET
  557 +endstream
  558 +endobj
  559 +
  560 +30 0 obj
  561 +47
  562 +endobj
  563 +
  564 +%% Original object ID: 53 0
  565 +31 0 obj
  566 +<<
  567 + /BaseFont /Helvetica
  568 + /Encoding /WinAnsiEncoding
  569 + /Name /F1
  570 + /Subtype /Type1
  571 + /Type /Font
  572 +>>
  573 +endobj
  574 +
  575 +%% Original object ID: 54 0
  576 +32 0 obj
  577 +[
  578 + /PDF
  579 + /Text
  580 +]
  581 +endobj
  582 +
  583 +%% Contents for page 4
  584 +%% Original object ID: 26 0
  585 +33 0 obj
  586 +<<
  587 + /Length 34 0 R
  588 +>>
  589 +stream
  590 +BT
  591 + /F1 24 Tf
  592 + 72 720 Td
  593 + (Potato 2) Tj
  594 +ET
  595 +endstream
  596 +endobj
  597 +
  598 +34 0 obj
  599 +46
  600 +endobj
  601 +
  602 +%% Contents for page 5
  603 +%% Original object ID: 56 0
  604 +35 0 obj
  605 +<<
  606 + /Length 36 0 R
  607 +>>
  608 +stream
  609 +BT
  610 + /F1 24 Tf
  611 + 72 720 Td
  612 + (Potato 11) Tj
  613 +ET
  614 +endstream
  615 +endobj
  616 +
  617 +36 0 obj
  618 +47
  619 +endobj
  620 +
  621 +%% Contents for page 6
  622 +%% Original object ID: 27 0
  623 +37 0 obj
  624 +<<
  625 + /Length 38 0 R
  626 +>>
  627 +stream
  628 +BT
  629 + /F1 24 Tf
  630 + 72 720 Td
  631 + (Potato 4) Tj
  632 +ET
  633 +endstream
  634 +endobj
  635 +
  636 +38 0 obj
  637 +46
  638 +endobj
  639 +
  640 +%% Contents for page 7
  641 +%% Original object ID: 58 0
  642 +39 0 obj
  643 +<<
  644 + /Length 40 0 R
  645 +>>
  646 +stream
  647 +BT
  648 + /F1 24 Tf
  649 + 72 720 Td
  650 + (Potato 9) Tj
  651 +ET
  652 +endstream
  653 +endobj
  654 +
  655 +40 0 obj
  656 +46
  657 +endobj
  658 +
  659 +%% Contents for page 8
  660 +%% Original object ID: 28 0
  661 +41 0 obj
  662 +<<
  663 + /Length 42 0 R
  664 +>>
  665 +stream
  666 +BT
  667 + /F1 24 Tf
  668 + 72 720 Td
  669 + (Potato 6) Tj
  670 +ET
  671 +endstream
  672 +endobj
  673 +
  674 +42 0 obj
  675 +46
  676 +endobj
  677 +
  678 +%% Contents for page 9
  679 +%% Original object ID: 60 0
  680 +43 0 obj
  681 +<<
  682 + /Length 44 0 R
  683 +>>
  684 +stream
  685 +BT
  686 + /F1 24 Tf
  687 + 72 720 Td
  688 + (Potato 7) Tj
  689 +ET
  690 +endstream
  691 +endobj
  692 +
  693 +44 0 obj
  694 +46
  695 +endobj
  696 +
  697 +%% Contents for page 10
  698 +%% Original object ID: 29 0
  699 +45 0 obj
  700 +<<
  701 + /Length 46 0 R
  702 +>>
  703 +stream
  704 +BT
  705 + /F1 24 Tf
  706 + 72 720 Td
  707 + (Potato 8) Tj
  708 +ET
  709 +endstream
  710 +endobj
  711 +
  712 +46 0 obj
  713 +46
  714 +endobj
  715 +
  716 +%% Contents for page 11
  717 +%% Original object ID: 62 0
  718 +47 0 obj
  719 +<<
  720 + /Length 48 0 R
  721 +>>
  722 +stream
  723 +BT
  724 + /F1 24 Tf
  725 + 72 720 Td
  726 + (Potato 5) Tj
  727 +ET
  728 +endstream
  729 +endobj
  730 +
  731 +48 0 obj
  732 +46
  733 +endobj
  734 +
  735 +%% Contents for page 12
  736 +%% Original object ID: 64 0
  737 +49 0 obj
  738 +<<
  739 + /Length 50 0 R
  740 +>>
  741 +stream
  742 +BT
  743 + /F1 24 Tf
  744 + 72 720 Td
  745 + (Potato 3) Tj
  746 +ET
  747 +endstream
  748 +endobj
  749 +
  750 +50 0 obj
  751 +46
  752 +endobj
  753 +
  754 +%% Contents for page 13
  755 +%% Original object ID: 66 0
  756 +51 0 obj
  757 +<<
  758 + /Length 52 0 R
  759 +>>
  760 +stream
  761 +BT
  762 + /F1 24 Tf
  763 + 72 720 Td
  764 + (Potato 1) Tj
  765 +ET
  766 +endstream
  767 +endobj
  768 +
  769 +52 0 obj
  770 +46
  771 +endobj
  772 +
  773 +%% Original object ID: 40 0
  774 +53 0 obj
  775 +<<
  776 + /Count -2
  777 + /Dest [
  778 + null
  779 + /FitV
  780 + 100
  781 + ]
  782 + /First 57 0 R
  783 + /Last 58 0 R
  784 + /Next 54 0 R
  785 + /Parent 19 0 R
  786 + /Title (Isosicle 1.1.1 -> 12: /FitV 100)
  787 + /Type /Outline
  788 +>>
  789 +endobj
  790 +
  791 +%% Original object ID: 41 0
  792 +54 0 obj
  793 +<<
  794 + /Count 1
  795 + /Dest [
  796 + null
  797 + /XYZ
  798 + null
  799 + null
  800 + null
  801 + ]
  802 + /First 59 0 R
  803 + /Last 59 0 R
  804 + /Parent 19 0 R
  805 + /Prev 53 0 R
  806 + /Title (Isosicle 1.1.2 -> 12: /XYZ null null null)
  807 + /Type /Outline
  808 +>>
  809 +endobj
  810 +
  811 +%% Original object ID: 42 0
  812 +55 0 obj
  813 +<<
  814 + /Dest [
  815 + null
  816 + /FitR
  817 + 66
  818 + 714
  819 + 180
  820 + 770
  821 + ]
  822 + /Next 56 0 R
  823 + /Parent 20 0 R
  824 + /Title (Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770)
  825 + /Type /Outline
  826 +>>
  827 +endobj
  828 +
  829 +%% Original object ID: 43 0
  830 +56 0 obj
  831 +<<
  832 + /Dest [
  833 + 6 0 R
  834 + /XYZ
  835 + null
  836 + null
  837 + null
  838 + ]
  839 + /Parent 20 0 R
  840 + /Prev 55 0 R
  841 + /Title (Trepsicle 1.2.2 -> 0: /XYZ null null null)
  842 + /Type /Outline
  843 +>>
  844 +endobj
  845 +
  846 +%% Original object ID: 44 0
  847 +57 0 obj
  848 +<<
  849 + /Dest [
  850 + null
  851 + /XYZ
  852 + null
  853 + null
  854 + null
  855 + ]
  856 + /Next 58 0 R
  857 + /Parent 53 0 R
  858 + /Title (Isosicle 1.1.1.1 -> 18: /XYZ null null null)
  859 + /Type /Outline
  860 +>>
  861 +endobj
  862 +
  863 +%% Original object ID: 45 0
  864 +58 0 obj
  865 +<<
  866 + /Dest [
  867 + null
  868 + /XYZ
  869 + null
  870 + null
  871 + null
  872 + ]
  873 + /Parent 53 0 R
  874 + /Prev 57 0 R
  875 + /Title (Isosicle 1.1.1.2 -> 19: /XYZ null null null)
  876 + /Type /Outline
  877 +>>
  878 +endobj
  879 +
  880 +%% Original object ID: 46 0
  881 +59 0 obj
  882 +<<
  883 + /Dest [
  884 + null
  885 + /XYZ
  886 + null
  887 + null
  888 + null
  889 + ]
  890 + /Parent 54 0 R
  891 + /Title (Isosicle 1.1.2.1 -> 22: /XYZ null null null)
  892 + /Type /Outline
  893 +>>
  894 +endobj
  895 +
  896 +xref
  897 +0 60
  898 +0000000000 65535 f
  899 +0000000052 00000 n
  900 +0000000853 00000 n
  901 +0000000960 00000 n
  902 +0000001189 00000 n
  903 +0000001430 00000 n
  904 +0000001630 00000 n
  905 +0000001863 00000 n
  906 +0000002096 00000 n
  907 +0000002328 00000 n
  908 +0000002561 00000 n
  909 +0000002794 00000 n
  910 +0000003028 00000 n
  911 +0000003261 00000 n
  912 +0000003495 00000 n
  913 +0000003730 00000 n
  914 +0000003965 00000 n
  915 +0000004200 00000 n
  916 +0000004435 00000 n
  917 +0000004659 00000 n
  918 +0000004867 00000 n
  919 +0000005224 00000 n
  920 +0000005327 00000 n
  921 +0000005375 00000 n
  922 +0000005522 00000 n
  923 +0000005609 00000 n
  924 +0000005710 00000 n
  925 +0000005758 00000 n
  926 +0000005905 00000 n
  927 +0000005992 00000 n
  928 +0000006096 00000 n
  929 +0000006144 00000 n
  930 +0000006291 00000 n
  931 +0000006378 00000 n
  932 +0000006481 00000 n
  933 +0000006552 00000 n
  934 +0000006656 00000 n
  935 +0000006727 00000 n
  936 +0000006830 00000 n
  937 +0000006901 00000 n
  938 +0000007004 00000 n
  939 +0000007075 00000 n
  940 +0000007178 00000 n
  941 +0000007249 00000 n
  942 +0000007352 00000 n
  943 +0000007424 00000 n
  944 +0000007527 00000 n
  945 +0000007599 00000 n
  946 +0000007702 00000 n
  947 +0000007774 00000 n
  948 +0000007877 00000 n
  949 +0000007949 00000 n
  950 +0000008052 00000 n
  951 +0000008100 00000 n
  952 +0000008327 00000 n
  953 +0000008581 00000 n
  954 +0000008801 00000 n
  955 +0000009014 00000 n
  956 +0000009228 00000 n
  957 +0000009442 00000 n
  958 +trailer <<
  959 + /Root 1 0 R
  960 + /Size 60
  961 + /ID [<d3fab8d0603e683dc94e42ac31141868><31415926535897932384626433832795>]
  962 +>>
  963 +startxref
  964 +9613
  965 +%%EOF