Commit cfa2eb97fb9b38d62fd2cd8d54ab59bac503967f

Authored by Jay Berkenbilt
1 parent d926d780

Add page rotation (fixes #132)

ChangeLog
1 1 2017-08-12 Jay Berkenbilt <ejb@ql.org>
2 2  
  3 + * Add QPDFObjectHandle::rotatePage to apply rotation to a page
  4 + object. Add --rotate option to qpdf to specify page rotation from
  5 + the command line.
  6 +
3 7 * Provide --verbose option that causes qpdf to print an indication
4 8 of what files it is writing.
5 9  
... ...
include/qpdf/QPDFObjectHandle.hh
... ... @@ -507,6 +507,13 @@ class QPDFObjectHandle
507 507 QPDF_DLL
508 508 void addPageContents(QPDFObjectHandle contents, bool first);
509 509  
  510 + // Rotate a page. If relative is false, set the rotation of the
  511 + // page to angle. Otherwise, add angle to the rotation of the
  512 + // page. Angle must be a multiple of 90. Adding 90 to the rotation
  513 + // rotates clockwise by 90 degrees.
  514 + QPDF_DLL
  515 + void rotatePage(int angle, bool relative);
  516 +
510 517 // Initializers for objects. This Factory class gives the QPDF
511 518 // class specific permission to call factory methods without
512 519 // making it a friend of the whole QPDFObjectHandle class.
... ...
libqpdf/QPDFObjectHandle.cc
... ... @@ -673,6 +673,62 @@ QPDFObjectHandle::addPageContents(QPDFObjectHandle new_contents, bool first)
673 673 this->replaceKey("/Contents", contents);
674 674 }
675 675  
  676 +void
  677 +QPDFObjectHandle::rotatePage(int angle, bool relative)
  678 +{
  679 + assertPageObject();
  680 + if ((angle % 90) != 0)
  681 + {
  682 + throw std::runtime_error(
  683 + "QPDF::rotatePage called with an"
  684 + " angle that is not a multiple of 90");
  685 + }
  686 + int new_angle = angle;
  687 + if (relative)
  688 + {
  689 + int old_angle = 0;
  690 + bool found_rotate = false;
  691 + QPDFObjectHandle cur_obj = *this;
  692 + bool searched_parent = false;
  693 + std::set<QPDFObjGen> visited;
  694 + while (! found_rotate)
  695 + {
  696 + if (visited.count(cur_obj.getObjGen()))
  697 + {
  698 + // Don't get stuck in an infinite loop
  699 + break;
  700 + }
  701 + if (! visited.empty())
  702 + {
  703 + searched_parent = true;
  704 + }
  705 + visited.insert(cur_obj.getObjGen());
  706 + if (cur_obj.getKey("/Rotate").isInteger())
  707 + {
  708 + found_rotate = true;
  709 + old_angle = cur_obj.getKey("/Rotate").getIntValue();
  710 + }
  711 + else if (cur_obj.getKey("/Parent").isDictionary())
  712 + {
  713 + cur_obj = cur_obj.getKey("/Parent");
  714 + }
  715 + else
  716 + {
  717 + break;
  718 + }
  719 + }
  720 + QTC::TC("qpdf", "QPDFObjectHandle found old angle",
  721 + searched_parent ? 0 : 1);
  722 + if ((old_angle % 90) != 0)
  723 + {
  724 + old_angle = 0;
  725 + }
  726 + new_angle += old_angle;
  727 + }
  728 + new_angle = (new_angle + 360) % 360;
  729 + replaceKey("/Rotate", QPDFObjectHandle::newInteger(new_angle));
  730 +}
  731 +
676 732 std::string
677 733 QPDFObjectHandle::unparse()
678 734 {
... ...
manual/qpdf-manual.xml
... ... @@ -349,6 +349,26 @@ make
349 349 </listitem>
350 350 </varlistentry>
351 351 <varlistentry>
  352 + <term><option>--rotate=[+|-]angle:page-range</option></term>
  353 + <listitem>
  354 + <para>
  355 + Apply rotation to specified pages. The
  356 + <option>page-range</option> portion of the option value has
  357 + the same format as page ranges in <xref
  358 + linkend="ref.page-selection"/>. The <option>angle</option>
  359 + portion of the parameter may be either 90, 180, or 270. If
  360 + preceded by <option>+</option> or <option>-</option>, the
  361 + angle is added to or subtracted from the specified pages'
  362 + original rotations. Otherwise the pages' rotations are set to
  363 + the exact value. For example, the command <command>qpdf in.pdf
  364 + out.pdf --rotate=+90:2,4,6 --rotate=180:7-8</command> would
  365 + rotate pages 2, 4, and 6 90 degrees clockwise from their
  366 + original rotation and force the rotation of pages 7 through 9
  367 + to 180 degrees regardless of their original rotation.
  368 + </para>
  369 + </listitem>
  370 + </varlistentry>
  371 + <varlistentry>
352 372 <term><option>--pages options --</option></term>
353 373 <listitem>
354 374 <para>
... ...
qpdf/qpdf.cc
... ... @@ -37,6 +37,18 @@ struct PageSpec
37 37 char const* range;
38 38 };
39 39  
  40 +struct RotationSpec
  41 +{
  42 + RotationSpec(int angle = 0, bool relative = false) :
  43 + angle(angle),
  44 + relative(relative)
  45 + {
  46 + }
  47 +
  48 + int angle;
  49 + bool relative;
  50 +};
  51 +
40 52 struct Options
41 53 {
42 54 Options() :
... ... @@ -151,6 +163,7 @@ struct Options
151 163 bool show_page_images;
152 164 bool check;
153 165 std::vector<PageSpec> page_specs;
  166 + std::map<std::string, RotationSpec> rotations;
154 167 bool require_outfile;
155 168 char const* infilename;
156 169 char const* outfilename;
... ... @@ -209,6 +222,8 @@ Basic Options\n\
209 222 --encrypt options -- generate an encrypted file\n\
210 223 --decrypt remove any encryption on the file\n\
211 224 --pages options -- select specific pages from one or more files\n\
  225 +--rotate=[+|-]angle:page-range\n\
  226 + rotate each specified page 90, 180, or 270 degrees\n\
212 227 --split-pages=[n] write each output page to a separate file\n\
213 228 \n\
214 229 If none of --copy-encryption, --encrypt or --decrypt are given, qpdf will\n\
... ... @@ -219,6 +234,13 @@ parameters will be copied, including both user and owner passwords, even\n\
219 234 if the user password is used to open the other file. This works even if\n\
220 235 the owner password is not known.\n\
221 236 \n\
  237 +The --rotate flag can be used to specify pages to rotate pages either\n\
  238 +90, 180, or 270 degrees. The page range is specified in the same\n\
  239 +format as with the --pages option, described below. Repeat the option\n\
  240 +to rotate multiple groups of pages. If the angle is preceded by + or -,\n\
  241 +it is added to or subtracted from the original rotation. Otherwise, the\n\
  242 +rotation angle is set explicitly to the given value.\n\
  243 +\n\
222 244 If --split-pages is specified, each page is written to a separate output\n\
223 245 file. File names are generated as follows:\n\
224 246 * If the string %d appears in the output file name, it is replaced with a\n\
... ... @@ -1148,6 +1170,62 @@ static void handle_help_verison(int argc, char* argv[])
1148 1170 }
1149 1171 }
1150 1172  
  1173 +static void parse_rotation_parameter(Options& o, std::string const& parameter)
  1174 +{
  1175 + std::string angle_str;
  1176 + std::string range;
  1177 + size_t colon = parameter.find(':');
  1178 + int relative = 0;
  1179 + if (colon != std::string::npos)
  1180 + {
  1181 + if (colon > 0)
  1182 + {
  1183 + angle_str = parameter.substr(0, colon);
  1184 + if (angle_str.length() > 0)
  1185 + {
  1186 + char first = angle_str.at(0);
  1187 + if ((first == '+') || (first == '-'))
  1188 + {
  1189 + relative = ((first == '+') ? 1 : -1);
  1190 + angle_str = angle_str.substr(1);
  1191 + }
  1192 + else if (! QUtil::is_digit(angle_str.at(0)))
  1193 + {
  1194 + angle_str = "";
  1195 + }
  1196 + }
  1197 + }
  1198 + if (colon + 1 < parameter.length())
  1199 + {
  1200 + range = parameter.substr(colon + 1);
  1201 + }
  1202 + }
  1203 + bool range_valid = false;
  1204 + try
  1205 + {
  1206 + parse_numrange(range.c_str(), 0, true);
  1207 + range_valid = true;
  1208 + }
  1209 + catch (std::runtime_error)
  1210 + {
  1211 + // ignore
  1212 + }
  1213 + if (range_valid &&
  1214 + ((angle_str == "90") || (angle_str == "180") || (angle_str == "270")))
  1215 + {
  1216 + int angle = atoi(angle_str.c_str());
  1217 + if (relative == -1)
  1218 + {
  1219 + angle = -angle;
  1220 + }
  1221 + o.rotations[range] = RotationSpec(angle, (relative != 0));
  1222 + }
  1223 + else
  1224 + {
  1225 + usage("invalid parameter to rotate: " + parameter);
  1226 + }
  1227 +}
  1228 +
1151 1229 static void parse_options(int argc, char* argv[], Options& o)
1152 1230 {
1153 1231 for (int i = 1; i < argc; ++i)
... ... @@ -1237,6 +1315,10 @@ static void parse_options(int argc, char* argv[], Options&amp; o)
1237 1315 usage("--pages: no page specifications given");
1238 1316 }
1239 1317 }
  1318 + else if (strcmp(arg, "rotate") == 0)
  1319 + {
  1320 + parse_rotation_parameter(o, parameter);
  1321 + }
1240 1322 else if (strcmp(arg, "stream-data") == 0)
1241 1323 {
1242 1324 if (parameter == 0)
... ... @@ -1829,6 +1911,29 @@ static void handle_page_specs(QPDF&amp; pdf, Options&amp; o,
1829 1911 }
1830 1912 }
1831 1913  
  1914 +static void handle_rotations(QPDF& pdf, Options& o)
  1915 +{
  1916 + std::vector<QPDFObjectHandle> pages = pdf.getAllPages();
  1917 + int npages = static_cast<int>(pages.size());
  1918 + for (std::map<std::string, RotationSpec>::iterator iter =
  1919 + o.rotations.begin();
  1920 + iter != o.rotations.end(); ++iter)
  1921 + {
  1922 + std::string const& range = (*iter).first;
  1923 + RotationSpec const& rspec = (*iter).second;
  1924 + std::vector<int> to_rotate = parse_numrange(range.c_str(), npages);
  1925 + for (std::vector<int>::iterator i2 = to_rotate.begin();
  1926 + i2 != to_rotate.end(); ++i2)
  1927 + {
  1928 + int pageno = *i2 - 1;
  1929 + if ((pageno >= 0) && (pageno < npages))
  1930 + {
  1931 + pages.at(pageno).rotatePage(rspec.angle, rspec.relative);
  1932 + }
  1933 + }
  1934 + }
  1935 +}
  1936 +
1832 1937 static void set_encryption_options(QPDF& pdf, Options& o, QPDFWriter& w)
1833 1938 {
1834 1939 int R = 0;
... ... @@ -2124,6 +2229,10 @@ int main(int argc, char* argv[])
2124 2229 {
2125 2230 handle_page_specs(pdf, o, page_heap);
2126 2231 }
  2232 + if (! o.rotations.empty())
  2233 + {
  2234 + handle_rotations(pdf, o);
  2235 + }
2127 2236  
2128 2237 if (o.outfilename == 0)
2129 2238 {
... ...
qpdf/qpdf.testcov
... ... @@ -295,3 +295,4 @@ QPDF ignore second extra space in xref entry 0
295 295 QPDF ignore length error xref entry 0
296 296 QPDF_encryption pad short parameter 0
297 297 QPDFWriter ignore self-referential object stream 0
  298 +QPDFObjectHandle found old angle 1
... ...
qpdf/qtest/qpdf.test
... ... @@ -780,6 +780,26 @@ foreach my $d (@sp_cases)
780 780  
781 781 show_ntests();
782 782 # ----------
  783 +$td->notify("--- Rotate Pages ---");
  784 +$n_tests += 2;
  785 +# XXX do absolute, positive, and negative on ranges that include
  786 +# inherited and non-inherited.
  787 +# Pages 11-15 inherit /Rotate 90
  788 +# Pages 1 and 2 have explicit /Rotate 270
  789 +# Pages 16 and 17 have explicit /Rotate 180
  790 +
  791 +$td->runtest("page rotation",
  792 + {$td->COMMAND => "qpdf --static-id to-rotate.pdf a.pdf" .
  793 + " --rotate=+90:1,4,11,16" .
  794 + " --rotate=180:2,5,12-13" .
  795 + " --rotate=-90:3,15,17,18"},
  796 + {$td->STRING => "", $td->EXIT_STATUS => 0});
  797 +$td->runtest("check output",
  798 + {$td->FILE => "a.pdf"},
  799 + {$td->FILE => "rotated.pdf"});
  800 +
  801 +show_ntests();
  802 +# ----------
783 803 $td->notify("--- Numeric range parsing tests ---");
784 804 my @nrange_tests = (
785 805 [",5",
... ...
qpdf/qtest/qpdf/rotated.pdf 0 โ†’ 100644
No preview for this file type
qpdf/qtest/qpdf/to-rotate.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 20
  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 + 17 0 R
  37 + 18 0 R
  38 + 19 0 R
  39 + ]
  40 + /Type /Pages
  41 +>>
  42 +endobj
  43 +
  44 +%% Page 1
  45 +4 0 obj
  46 +<<
  47 + /Contents 20 0 R
  48 + /MediaBox [
  49 + 0
  50 + 0
  51 + 612
  52 + 792
  53 + ]
  54 + /Parent 3 0 R
  55 + /Resources <<
  56 + /Font <<
  57 + /F1 22 0 R
  58 + >>
  59 + /ProcSet [
  60 + /PDF
  61 + /Text
  62 + ]
  63 + >>
  64 + /Rotate 270
  65 + /Type /Page
  66 +>>
  67 +endobj
  68 +
  69 +%% Page 2
  70 +5 0 obj
  71 +<<
  72 + /Contents 23 0 R
  73 + /MediaBox [
  74 + 0
  75 + 0
  76 + 612
  77 + 792
  78 + ]
  79 + /Parent 3 0 R
  80 + /Resources <<
  81 + /Font <<
  82 + /F1 22 0 R
  83 + >>
  84 + /ProcSet [
  85 + /PDF
  86 + /Text
  87 + ]
  88 + >>
  89 + /Rotate 270
  90 + /Type /Page
  91 +>>
  92 +endobj
  93 +
  94 +%% Page 3
  95 +6 0 obj
  96 +<<
  97 + /Contents 25 0 R
  98 + /MediaBox [
  99 + 0
  100 + 0
  101 + 612
  102 + 792
  103 + ]
  104 + /Parent 3 0 R
  105 + /Resources <<
  106 + /Font <<
  107 + /F1 22 0 R
  108 + >>
  109 + /ProcSet [
  110 + /PDF
  111 + /Text
  112 + ]
  113 + >>
  114 + /Type /Page
  115 +>>
  116 +endobj
  117 +
  118 +%% Page 4
  119 +7 0 obj
  120 +<<
  121 + /Contents 27 0 R
  122 + /MediaBox [
  123 + 0
  124 + 0
  125 + 612
  126 + 792
  127 + ]
  128 + /Parent 3 0 R
  129 + /Resources <<
  130 + /Font <<
  131 + /F1 22 0 R
  132 + >>
  133 + /ProcSet [
  134 + /PDF
  135 + /Text
  136 + ]
  137 + >>
  138 + /Type /Page
  139 +>>
  140 +endobj
  141 +
  142 +%% Page 5
  143 +8 0 obj
  144 +<<
  145 + /Contents 29 0 R
  146 + /MediaBox [
  147 + 0
  148 + 0
  149 + 612
  150 + 792
  151 + ]
  152 + /Parent 3 0 R
  153 + /Resources <<
  154 + /Font <<
  155 + /F1 22 0 R
  156 + >>
  157 + /ProcSet [
  158 + /PDF
  159 + /Text
  160 + ]
  161 + >>
  162 + /Type /Page
  163 +>>
  164 +endobj
  165 +
  166 +%% Page 6
  167 +9 0 obj
  168 +<<
  169 + /Contents 31 0 R
  170 + /MediaBox [
  171 + 0
  172 + 0
  173 + 612
  174 + 792
  175 + ]
  176 + /Parent 3 0 R
  177 + /Resources <<
  178 + /Font <<
  179 + /F1 22 0 R
  180 + >>
  181 + /ProcSet [
  182 + /PDF
  183 + /Text
  184 + ]
  185 + >>
  186 + /Type /Page
  187 +>>
  188 +endobj
  189 +
  190 +%% Page 7
  191 +10 0 obj
  192 +<<
  193 + /Contents 33 0 R
  194 + /MediaBox [
  195 + 0
  196 + 0
  197 + 612
  198 + 792
  199 + ]
  200 + /Parent 3 0 R
  201 + /Resources <<
  202 + /Font <<
  203 + /F1 22 0 R
  204 + >>
  205 + /ProcSet [
  206 + /PDF
  207 + /Text
  208 + ]
  209 + >>
  210 + /Type /Page
  211 +>>
  212 +endobj
  213 +
  214 +%% Page 8
  215 +11 0 obj
  216 +<<
  217 + /Contents 35 0 R
  218 + /MediaBox [
  219 + 0
  220 + 0
  221 + 612
  222 + 792
  223 + ]
  224 + /Parent 3 0 R
  225 + /Resources <<
  226 + /Font <<
  227 + /F1 22 0 R
  228 + >>
  229 + /ProcSet [
  230 + /PDF
  231 + /Text
  232 + ]
  233 + >>
  234 + /Type /Page
  235 +>>
  236 +endobj
  237 +
  238 +%% Page 9
  239 +12 0 obj
  240 +<<
  241 + /Contents 37 0 R
  242 + /MediaBox [
  243 + 0
  244 + 0
  245 + 612
  246 + 792
  247 + ]
  248 + /Parent 3 0 R
  249 + /Resources <<
  250 + /Font <<
  251 + /F1 22 0 R
  252 + >>
  253 + /ProcSet [
  254 + /PDF
  255 + /Text
  256 + ]
  257 + >>
  258 + /Type /Page
  259 +>>
  260 +endobj
  261 +
  262 +%% Page 10
  263 +13 0 obj
  264 +<<
  265 + /Contents 39 0 R
  266 + /MediaBox [
  267 + 0
  268 + 0
  269 + 612
  270 + 792
  271 + ]
  272 + /Parent 3 0 R
  273 + /Resources <<
  274 + /Font <<
  275 + /F1 22 0 R
  276 + >>
  277 + /ProcSet [
  278 + /PDF
  279 + /Text
  280 + ]
  281 + >>
  282 + /Type /Page
  283 +>>
  284 +endobj
  285 +
  286 +14 0 obj
  287 +<<
  288 + /Count 5
  289 + /Kids [
  290 + 41 0 R
  291 + 42 0 R
  292 + 43 0 R
  293 + 44 0 R
  294 + 45 0 R
  295 + ]
  296 + /Parent 3 0 R
  297 + /Rotate 90
  298 + /Type /Pages
  299 +>>
  300 +endobj
  301 +
  302 +%% Page 16
  303 +15 0 obj
  304 +<<
  305 + /Contents 46 0 R
  306 + /MediaBox [
  307 + 0
  308 + 0
  309 + 612
  310 + 792
  311 + ]
  312 + /Parent 3 0 R
  313 + /Resources <<
  314 + /Font <<
  315 + /F1 22 0 R
  316 + >>
  317 + /ProcSet [
  318 + /PDF
  319 + /Text
  320 + ]
  321 + >>
  322 + /Rotate 180
  323 + /Type /Page
  324 +>>
  325 +endobj
  326 +
  327 +%% Page 17
  328 +16 0 obj
  329 +<<
  330 + /Contents 48 0 R
  331 + /MediaBox [
  332 + 0
  333 + 0
  334 + 612
  335 + 792
  336 + ]
  337 + /Parent 3 0 R
  338 + /Resources <<
  339 + /Font <<
  340 + /F1 22 0 R
  341 + >>
  342 + /ProcSet [
  343 + /PDF
  344 + /Text
  345 + ]
  346 + >>
  347 + /Rotate 180
  348 + /Type /Page
  349 +>>
  350 +endobj
  351 +
  352 +%% Page 18
  353 +17 0 obj
  354 +<<
  355 + /Contents 50 0 R
  356 + /MediaBox [
  357 + 0
  358 + 0
  359 + 612
  360 + 792
  361 + ]
  362 + /Parent 3 0 R
  363 + /Resources <<
  364 + /Font <<
  365 + /F1 22 0 R
  366 + >>
  367 + /ProcSet [
  368 + /PDF
  369 + /Text
  370 + ]
  371 + >>
  372 + /Type /Page
  373 +>>
  374 +endobj
  375 +
  376 +%% Page 19
  377 +18 0 obj
  378 +<<
  379 + /Contents 52 0 R
  380 + /MediaBox [
  381 + 0
  382 + 0
  383 + 612
  384 + 792
  385 + ]
  386 + /Parent 3 0 R
  387 + /Resources <<
  388 + /Font <<
  389 + /F1 22 0 R
  390 + >>
  391 + /ProcSet [
  392 + /PDF
  393 + /Text
  394 + ]
  395 + >>
  396 + /Type /Page
  397 +>>
  398 +endobj
  399 +
  400 +%% Page 20
  401 +19 0 obj
  402 +<<
  403 + /Contents 54 0 R
  404 + /MediaBox [
  405 + 0
  406 + 0
  407 + 612
  408 + 792
  409 + ]
  410 + /Parent 3 0 R
  411 + /Resources <<
  412 + /Font <<
  413 + /F1 22 0 R
  414 + >>
  415 + /ProcSet [
  416 + /PDF
  417 + /Text
  418 + ]
  419 + >>
  420 + /Type /Page
  421 +>>
  422 +endobj
  423 +
  424 +%% Contents for page 1
  425 +20 0 obj
  426 +<<
  427 + /Length 21 0 R
  428 +>>
  429 +stream
  430 +BT /F1 15 Tf 72 720 Td (Original page 1) Tj ET
  431 +endstream
  432 +endobj
  433 +
  434 +21 0 obj
  435 +47
  436 +endobj
  437 +
  438 +22 0 obj
  439 +<<
  440 + /BaseFont /Times-Roman
  441 + /Encoding /WinAnsiEncoding
  442 + /Subtype /Type1
  443 + /Type /Font
  444 +>>
  445 +endobj
  446 +
  447 +%% Contents for page 2
  448 +23 0 obj
  449 +<<
  450 + /Length 24 0 R
  451 +>>
  452 +stream
  453 +BT /F1 15 Tf 72 720 Td (Original page 2) Tj ET
  454 +endstream
  455 +endobj
  456 +
  457 +24 0 obj
  458 +47
  459 +endobj
  460 +
  461 +%% Contents for page 3
  462 +25 0 obj
  463 +<<
  464 + /Length 26 0 R
  465 +>>
  466 +stream
  467 +BT /F1 15 Tf 72 720 Td (Original page 3) Tj ET
  468 +endstream
  469 +endobj
  470 +
  471 +26 0 obj
  472 +47
  473 +endobj
  474 +
  475 +%% Contents for page 4
  476 +27 0 obj
  477 +<<
  478 + /Length 28 0 R
  479 +>>
  480 +stream
  481 +BT /F1 15 Tf 72 720 Td (Original page 4) Tj ET
  482 +endstream
  483 +endobj
  484 +
  485 +28 0 obj
  486 +47
  487 +endobj
  488 +
  489 +%% Contents for page 5
  490 +29 0 obj
  491 +<<
  492 + /Length 30 0 R
  493 +>>
  494 +stream
  495 +BT /F1 15 Tf 72 720 Td (Original page 5) Tj ET
  496 +endstream
  497 +endobj
  498 +
  499 +30 0 obj
  500 +47
  501 +endobj
  502 +
  503 +%% Contents for page 6
  504 +31 0 obj
  505 +<<
  506 + /Length 32 0 R
  507 +>>
  508 +stream
  509 +BT /F1 15 Tf 72 720 Td (Original page 6) Tj ET
  510 +endstream
  511 +endobj
  512 +
  513 +32 0 obj
  514 +47
  515 +endobj
  516 +
  517 +%% Contents for page 7
  518 +33 0 obj
  519 +<<
  520 + /Length 34 0 R
  521 +>>
  522 +stream
  523 +BT /F1 15 Tf 72 720 Td (Original page 7) Tj ET
  524 +endstream
  525 +endobj
  526 +
  527 +34 0 obj
  528 +47
  529 +endobj
  530 +
  531 +%% Contents for page 8
  532 +35 0 obj
  533 +<<
  534 + /Length 36 0 R
  535 +>>
  536 +stream
  537 +BT /F1 15 Tf 72 720 Td (Original page 8) Tj ET
  538 +endstream
  539 +endobj
  540 +
  541 +36 0 obj
  542 +47
  543 +endobj
  544 +
  545 +%% Contents for page 9
  546 +37 0 obj
  547 +<<
  548 + /Length 38 0 R
  549 +>>
  550 +stream
  551 +BT /F1 15 Tf 72 720 Td (Original page 9) Tj ET
  552 +endstream
  553 +endobj
  554 +
  555 +38 0 obj
  556 +47
  557 +endobj
  558 +
  559 +%% Contents for page 10
  560 +39 0 obj
  561 +<<
  562 + /Length 40 0 R
  563 +>>
  564 +stream
  565 +BT /F1 15 Tf 72 720 Td (Original page 10) Tj ET
  566 +endstream
  567 +endobj
  568 +
  569 +40 0 obj
  570 +48
  571 +endobj
  572 +
  573 +%% Page 11
  574 +41 0 obj
  575 +<<
  576 + /Contents 56 0 R
  577 + /MediaBox [
  578 + 0
  579 + 0
  580 + 612
  581 + 792
  582 + ]
  583 + /Parent 14 0 R
  584 + /Resources <<
  585 + /Font <<
  586 + /F1 22 0 R
  587 + >>
  588 + /ProcSet [
  589 + /PDF
  590 + /Text
  591 + ]
  592 + >>
  593 + /Type /Page
  594 +>>
  595 +endobj
  596 +
  597 +%% Page 12
  598 +42 0 obj
  599 +<<
  600 + /Contents 58 0 R
  601 + /MediaBox [
  602 + 0
  603 + 0
  604 + 612
  605 + 792
  606 + ]
  607 + /Parent 14 0 R
  608 + /Resources <<
  609 + /Font <<
  610 + /F1 22 0 R
  611 + >>
  612 + /ProcSet [
  613 + /PDF
  614 + /Text
  615 + ]
  616 + >>
  617 + /Type /Page
  618 +>>
  619 +endobj
  620 +
  621 +%% Page 13
  622 +43 0 obj
  623 +<<
  624 + /Contents 60 0 R
  625 + /MediaBox [
  626 + 0
  627 + 0
  628 + 612
  629 + 792
  630 + ]
  631 + /Parent 14 0 R
  632 + /Resources <<
  633 + /Font <<
  634 + /F1 22 0 R
  635 + >>
  636 + /ProcSet [
  637 + /PDF
  638 + /Text
  639 + ]
  640 + >>
  641 + /Type /Page
  642 +>>
  643 +endobj
  644 +
  645 +%% Page 14
  646 +44 0 obj
  647 +<<
  648 + /Contents 62 0 R
  649 + /MediaBox [
  650 + 0
  651 + 0
  652 + 612
  653 + 792
  654 + ]
  655 + /Parent 14 0 R
  656 + /Resources <<
  657 + /Font <<
  658 + /F1 22 0 R
  659 + >>
  660 + /ProcSet [
  661 + /PDF
  662 + /Text
  663 + ]
  664 + >>
  665 + /Type /Page
  666 +>>
  667 +endobj
  668 +
  669 +%% Page 15
  670 +45 0 obj
  671 +<<
  672 + /Contents 64 0 R
  673 + /MediaBox [
  674 + 0
  675 + 0
  676 + 612
  677 + 792
  678 + ]
  679 + /Parent 14 0 R
  680 + /Resources <<
  681 + /Font <<
  682 + /F1 22 0 R
  683 + >>
  684 + /ProcSet [
  685 + /PDF
  686 + /Text
  687 + ]
  688 + >>
  689 + /Type /Page
  690 +>>
  691 +endobj
  692 +
  693 +%% Contents for page 16
  694 +46 0 obj
  695 +<<
  696 + /Length 47 0 R
  697 +>>
  698 +stream
  699 +BT /F1 15 Tf 72 720 Td (Original page 16) Tj ET
  700 +endstream
  701 +endobj
  702 +
  703 +47 0 obj
  704 +48
  705 +endobj
  706 +
  707 +%% Contents for page 17
  708 +48 0 obj
  709 +<<
  710 + /Length 49 0 R
  711 +>>
  712 +stream
  713 +BT /F1 15 Tf 72 720 Td (Original page 17) Tj ET
  714 +endstream
  715 +endobj
  716 +
  717 +49 0 obj
  718 +48
  719 +endobj
  720 +
  721 +%% Contents for page 18
  722 +50 0 obj
  723 +<<
  724 + /Length 51 0 R
  725 +>>
  726 +stream
  727 +BT /F1 15 Tf 72 720 Td (Original page 18) Tj ET
  728 +endstream
  729 +endobj
  730 +
  731 +51 0 obj
  732 +48
  733 +endobj
  734 +
  735 +%% Contents for page 19
  736 +52 0 obj
  737 +<<
  738 + /Length 53 0 R
  739 +>>
  740 +stream
  741 +BT /F1 15 Tf 72 720 Td (Original page 19) Tj ET
  742 +endstream
  743 +endobj
  744 +
  745 +53 0 obj
  746 +48
  747 +endobj
  748 +
  749 +%% Contents for page 20
  750 +54 0 obj
  751 +<<
  752 + /Length 55 0 R
  753 +>>
  754 +stream
  755 +BT /F1 15 Tf 72 720 Td (Original page 20) Tj ET
  756 +endstream
  757 +endobj
  758 +
  759 +55 0 obj
  760 +48
  761 +endobj
  762 +
  763 +%% Contents for page 11
  764 +56 0 obj
  765 +<<
  766 + /Length 57 0 R
  767 +>>
  768 +stream
  769 +BT /F1 15 Tf 72 720 Td (Original page 11) Tj ET
  770 +endstream
  771 +endobj
  772 +
  773 +57 0 obj
  774 +48
  775 +endobj
  776 +
  777 +%% Contents for page 12
  778 +58 0 obj
  779 +<<
  780 + /Length 59 0 R
  781 +>>
  782 +stream
  783 +BT /F1 15 Tf 72 720 Td (Original page 12) Tj ET
  784 +endstream
  785 +endobj
  786 +
  787 +59 0 obj
  788 +48
  789 +endobj
  790 +
  791 +%% Contents for page 13
  792 +60 0 obj
  793 +<<
  794 + /Length 61 0 R
  795 +>>
  796 +stream
  797 +BT /F1 15 Tf 72 720 Td (Original page 13) Tj ET
  798 +endstream
  799 +endobj
  800 +
  801 +61 0 obj
  802 +48
  803 +endobj
  804 +
  805 +%% Contents for page 14
  806 +62 0 obj
  807 +<<
  808 + /Length 63 0 R
  809 +>>
  810 +stream
  811 +BT /F1 15 Tf 72 720 Td (Original page 14) Tj ET
  812 +endstream
  813 +endobj
  814 +
  815 +63 0 obj
  816 +48
  817 +endobj
  818 +
  819 +%% Contents for page 15
  820 +64 0 obj
  821 +<<
  822 + /Length 65 0 R
  823 +>>
  824 +stream
  825 +BT /F1 15 Tf 72 720 Td (Original page 15) Tj ET
  826 +endstream
  827 +endobj
  828 +
  829 +65 0 obj
  830 +48
  831 +endobj
  832 +
  833 +xref
  834 +0 66
  835 +0000000000 65535 f
  836 +0000000025 00000 n
  837 +0000000079 00000 n
  838 +0000000165 00000 n
  839 +0000000408 00000 n
  840 +0000000651 00000 n
  841 +0000000894 00000 n
  842 +0000001123 00000 n
  843 +0000001352 00000 n
  844 +0000001581 00000 n
  845 +0000001810 00000 n
  846 +0000002040 00000 n
  847 +0000002270 00000 n
  848 +0000002501 00000 n
  849 +0000002721 00000 n
  850 +0000002879 00000 n
  851 +0000003124 00000 n
  852 +0000003369 00000 n
  853 +0000003600 00000 n
  854 +0000003831 00000 n
  855 +0000004074 00000 n
  856 +0000004178 00000 n
  857 +0000004198 00000 n
  858 +0000004330 00000 n
  859 +0000004434 00000 n
  860 +0000004477 00000 n
  861 +0000004581 00000 n
  862 +0000004624 00000 n
  863 +0000004728 00000 n
  864 +0000004771 00000 n
  865 +0000004875 00000 n
  866 +0000004918 00000 n
  867 +0000005022 00000 n
  868 +0000005065 00000 n
  869 +0000005169 00000 n
  870 +0000005212 00000 n
  871 +0000005316 00000 n
  872 +0000005359 00000 n
  873 +0000005463 00000 n
  874 +0000005507 00000 n
  875 +0000005612 00000 n
  876 +0000005643 00000 n
  877 +0000005875 00000 n
  878 +0000006107 00000 n
  879 +0000006339 00000 n
  880 +0000006571 00000 n
  881 +0000006816 00000 n
  882 +0000006921 00000 n
  883 +0000006965 00000 n
  884 +0000007070 00000 n
  885 +0000007114 00000 n
  886 +0000007219 00000 n
  887 +0000007263 00000 n
  888 +0000007368 00000 n
  889 +0000007412 00000 n
  890 +0000007517 00000 n
  891 +0000007561 00000 n
  892 +0000007666 00000 n
  893 +0000007710 00000 n
  894 +0000007815 00000 n
  895 +0000007859 00000 n
  896 +0000007964 00000 n
  897 +0000008008 00000 n
  898 +0000008113 00000 n
  899 +0000008157 00000 n
  900 +0000008262 00000 n
  901 +trailer <<
  902 + /Info 2 0 R
  903 + /Root 1 0 R
  904 + /Size 66
  905 + /ID [<e032a88c7a987db6ca3abee555506ccc><0c6f92bbd30230ec62bc832f23eddc35>]
  906 +>>
  907 +startxref
  908 +8282
  909 +%%EOF
... ...