Commit 9ba5b27ce4ae8e42c836efedf44d08146e8eefa8

Authored by Jay Berkenbilt
1 parent 2dbc1006

add double-page-size example

git-svn-id: svn+q:///qpdf/trunk@996 71b93d88-0707-0410-a8cf-f5a4172ac649
ChangeLog
1 2010-08-05 Jay Berkenbilt <ejb@ql.org> 1 2010-08-05 Jay Berkenbilt <ejb@ql.org>
2 2
  3 + * Add QPDFObjectHandle::addPageContents, a convenience routine for
  4 + appending or prepending new streams to a page's content streams.
  5 + The "double-page-size" example illustrates its use.
  6 +
3 * Add new methods to QPDFObjectHandle: replaceStreamData and 7 * Add new methods to QPDFObjectHandle: replaceStreamData and
4 newStream. These methods allow users of the qpdf library to add 8 newStream. These methods allow users of the qpdf library to add
5 new streams and to replace data of existing streams. Examples are 9 new streams and to replace data of existing streams. Examples are
@@ -7,9 +7,9 @@ Next @@ -7,9 +7,9 @@ Next
7 in August, 2009. He seems to like to send encrypted mail (key 7 in August, 2009. He seems to like to send encrypted mail (key
8 01FCC336). Tell him about newStream and replaceStreamData. 8 01FCC336). Tell him about newStream and replaceStreamData.
9 9
10 - * Tell stronghorse@tom.com about QPDFObjectHandle::addPageContents.  
11 - See message from stronghorse@tom.com ("Suggestion for qpdf") from  
12 - 2010-06-09 and my response. 10 + * Tell stronghorse@tom.com about QPDFObjectHandle::addPageContents
  11 + and double-page-size example. See message from stronghorse@tom.com
  12 + ("Suggestion for qpdf") from 2010-06-09 and my response.
13 13
14 2.2 14 2.2
15 === 15 ===
@@ -18,8 +18,6 @@ Next @@ -18,8 +18,6 @@ Next
18 image. Use QPDF::getAllPages and QPDFObjectHandle::getPageImages 18 image. Use QPDF::getAllPages and QPDFObjectHandle::getPageImages
19 along with new stream data and dictionary manipulation. 19 along with new stream data and dictionary manipulation.
20 20
21 - * Add example program for addPageContents using suggestion from  
22 - stronghorse@tom.com's message above.  
23 21
24 General 22 General
25 ======= 23 =======
examples/build.mk
1 -BINS_examples = pdf-bookmarks pdf-mod-info pdf-npages 1 +BINS_examples = pdf-bookmarks pdf-mod-info pdf-npages double-page-size
2 CBINS_examples = pdf-linearize 2 CBINS_examples = pdf-linearize
3 3
4 TARGETS_examples = $(foreach B,$(BINS_examples) $(CBINS_examples),examples/$(OUTPUT_DIR)/$(call binname,$(B))) 4 TARGETS_examples = $(foreach B,$(BINS_examples) $(CBINS_examples),examples/$(OUTPUT_DIR)/$(call binname,$(B)))
examples/double-page-size.cc 0 → 100644
  1 +#include <iostream>
  2 +#include <string.h>
  3 +#include <stdlib.h>
  4 +#include <qpdf/QPDF.hh>
  5 +#include <qpdf/QUtil.hh>
  6 +#include <qpdf/Buffer.hh>
  7 +#include <qpdf/QPDFWriter.hh>
  8 +
  9 +static char const* whoami = 0;
  10 +
  11 +void usage()
  12 +{
  13 + std::cerr << "Usage: " << whoami << " infile.pdf outfile.pdf [in-password]"
  14 + << std::endl
  15 + << "Double size of all pages in infile.pdf;"
  16 + << " write output to outfile.pdf" << std::endl;
  17 + exit(2);
  18 +}
  19 +
  20 +static void doubleBoxSize(QPDFObjectHandle& page, char const* box_name)
  21 +{
  22 + QPDFObjectHandle box = page.getKey(box_name);
  23 + if (box.isNull())
  24 + {
  25 + return;
  26 + }
  27 + if (! (box.isArray() && (box.getArrayNItems() == 4)))
  28 + {
  29 + throw std::runtime_error(std::string("box ") + box_name +
  30 + " is not an array of four elements");
  31 + }
  32 + std::vector<QPDFObjectHandle> doubled;
  33 + for (unsigned int i = 0; i < 4; ++i)
  34 + {
  35 + doubled.push_back(
  36 + QPDFObjectHandle::newReal(
  37 + QUtil::double_to_string(
  38 + box.getArrayItem(i).getNumericValue() * 2.0, 2)));
  39 + }
  40 + page.replaceKey(box_name, QPDFObjectHandle::newArray(doubled));
  41 +}
  42 +
  43 +int main(int argc, char* argv[])
  44 +{
  45 + whoami = QUtil::getWhoami(argv[0]);
  46 +
  47 + // For libtool's sake....
  48 + if (strncmp(whoami, "lt-", 3) == 0)
  49 + {
  50 + whoami += 3;
  51 + }
  52 +
  53 + if (! ((argc == 3) || (argc == 4)))
  54 + {
  55 + usage();
  56 + }
  57 +
  58 + char const* infilename = argv[1];
  59 + char const* outfilename = argv[2];
  60 + char const* password = (argc == 4) ? argv[3] : "";
  61 +
  62 + // Text to prepend to each page's contents
  63 + char const* content = "2 0 0 2 0 0 cm\n";
  64 +
  65 + // Copy text into a buffer without the null terminator
  66 + PointerHolder<Buffer> b = new Buffer(strlen(content));
  67 + unsigned char* bp = b.getPointer()->getBuffer();
  68 + memcpy(bp, (unsigned char*)content, strlen(content));
  69 +
  70 + try
  71 + {
  72 + QPDF qpdf;
  73 + qpdf.processFile(infilename, password);
  74 +
  75 + std::vector<QPDFObjectHandle> pages = qpdf.getAllPages();
  76 + for (std::vector<QPDFObjectHandle>::iterator iter = pages.begin();
  77 + iter != pages.end(); ++iter)
  78 + {
  79 + QPDFObjectHandle& page = *iter;
  80 +
  81 + // Prepend the buffer to the page's contents
  82 + page.addPageContents(QPDFObjectHandle::newStream(&qpdf, b), true);
  83 +
  84 + // Double the size of each of the content boxes
  85 + doubleBoxSize(page, "/MediaBox");
  86 + doubleBoxSize(page, "/CropBox");
  87 + doubleBoxSize(page, "/BleedBox");
  88 + doubleBoxSize(page, "/TrimBox");
  89 + doubleBoxSize(page, "/ArtBox");
  90 + }
  91 +
  92 + // Write out a new file
  93 + QPDFWriter w(qpdf, outfilename);
  94 + if (QUtil::get_env("IN_TESTSUITE"))
  95 + {
  96 + // For the test suite, uncompress streams and use static
  97 + // IDs.
  98 + w.setStaticID(true);
  99 + w.setStreamDataMode(qpdf_s_uncompress);
  100 + }
  101 + w.write();
  102 + std::cout << whoami << ": new file written to " << outfilename
  103 + << std::endl;
  104 + }
  105 + catch (std::exception &e)
  106 + {
  107 + std::cerr << whoami << " processing file " << infilename << ": "
  108 + << e.what() << std::endl;
  109 + exit(2);
  110 + }
  111 +
  112 + return 0;
  113 +}
examples/qtest/double-page-size.test 0 → 100644
  1 +#!/usr/bin/env perl
  2 +require 5.008;
  3 +BEGIN { $^W = 1; }
  4 +use strict;
  5 +
  6 +chdir("double-page-size") or die "chdir testdir failed: $!\n";
  7 +
  8 +require TestDriver;
  9 +
  10 +my $td = new TestDriver('double-page-size');
  11 +
  12 +cleanup();
  13 +
  14 +$td->runtest("double page size",
  15 + {$td->COMMAND => "double-page-size in.pdf a.pdf"},
  16 + {$td->STRING => "double-page-size: new file written to a.pdf\n",
  17 + $td->EXIT_STATUS => 0},
  18 + $td->NORMALIZE_NEWLINES);
  19 +
  20 +$td->runtest("check output",
  21 + {$td->FILE => "a.pdf"},
  22 + {$td->FILE => "out.pdf"});
  23 +
  24 +cleanup();
  25 +
  26 +$td->report(2);
  27 +
  28 +sub cleanup
  29 +{
  30 + unlink 'a.pdf';
  31 +}
examples/qtest/double-page-size/in.pdf 0 → 100644
  1 +%PDF-1.3
  2 +%¿÷¢þ
  3 +1 0 obj
  4 +<< /Pages 2 0 R /Type /Catalog >>
  5 +endobj
  6 +2 0 obj
  7 +<< /Count 2 /Kids [ 3 0 R 4 0 R ] /Type /Pages >>
  8 +endobj
  9 +3 0 obj
  10 +<< /Contents 5 0 R /MediaBox [ 0 0 612 792 ] /Parent 2 0 R /Resources << /Font << /F1 6 0 R >> /ProcSet 7 0 R >> /Type /Page >>
  11 +endobj
  12 +4 0 obj
  13 +<< /Contents 8 0 R /MediaBox [ 0 0 612 792 ] /Parent 2 0 R /Resources << /Font << /F1 6 0 R >> /ProcSet 7 0 R >> /Type /Page >>
  14 +endobj
  15 +5 0 obj
  16 +<< /Length 44 >>
  17 +stream
  18 +BT
  19 + /F1 24 Tf
  20 + 72 720 Td
  21 + (Potato) Tj
  22 +ET
  23 +endstream
  24 +endobj
  25 +6 0 obj
  26 +<< /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >>
  27 +endobj
  28 +7 0 obj
  29 +[ /PDF /Text ]
  30 +endobj
  31 +8 0 obj
  32 +<< /Length 43 >>
  33 +stream
  34 +BT
  35 + /F1 24 Tf
  36 + 72 720 Td
  37 + (Salad) Tj
  38 +ET
  39 +endstream
  40 +endobj
  41 +xref
  42 +0 9
  43 +0000000000 65535 f
  44 +0000000015 00000 n
  45 +0000000064 00000 n
  46 +0000000129 00000 n
  47 +0000000272 00000 n
  48 +0000000415 00000 n
  49 +0000000508 00000 n
  50 +0000000615 00000 n
  51 +0000000645 00000 n
  52 +trailer << /Root 1 0 R /Size 9 /ID [<071a6499182be9cfc990b11d0c4e5bc0><90dbb2f2f000af76d1107187b0e00349>] >>
  53 +startxref
  54 +737
  55 +%%EOF
examples/qtest/double-page-size/out.pdf 0 → 100644
  1 +%PDF-1.3
  2 +%¿÷¢þ
  3 +1 0 obj
  4 +<< /Pages 2 0 R /Type /Catalog >>
  5 +endobj
  6 +2 0 obj
  7 +<< /Count 2 /Kids [ 3 0 R 4 0 R ] /Type /Pages >>
  8 +endobj
  9 +3 0 obj
  10 +<< /Contents [ 5 0 R 6 0 R ] /MediaBox [ 0.00 0.00 1224.00 1584.00 ] /Parent 2 0 R /Resources << /Font << /F1 7 0 R >> /ProcSet 8 0 R >> /Type /Page >>
  11 +endobj
  12 +4 0 obj
  13 +<< /Contents [ 9 0 R 10 0 R ] /MediaBox [ 0.00 0.00 1224.00 1584.00 ] /Parent 2 0 R /Resources << /Font << /F1 7 0 R >> /ProcSet 8 0 R >> /Type /Page >>
  14 +endobj
  15 +5 0 obj
  16 +<< /Length 15 >>
  17 +stream
  18 +2 0 0 2 0 0 cm
  19 +endstream
  20 +endobj
  21 +6 0 obj
  22 +<< /Length 44 >>
  23 +stream
  24 +BT
  25 + /F1 24 Tf
  26 + 72 720 Td
  27 + (Potato) Tj
  28 +ET
  29 +endstream
  30 +endobj
  31 +7 0 obj
  32 +<< /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >>
  33 +endobj
  34 +8 0 obj
  35 +[ /PDF /Text ]
  36 +endobj
  37 +9 0 obj
  38 +<< /Length 15 >>
  39 +stream
  40 +2 0 0 2 0 0 cm
  41 +endstream
  42 +endobj
  43 +10 0 obj
  44 +<< /Length 43 >>
  45 +stream
  46 +BT
  47 + /F1 24 Tf
  48 + 72 720 Td
  49 + (Salad) Tj
  50 +ET
  51 +endstream
  52 +endobj
  53 +xref
  54 +0 11
  55 +0000000000 65535 f
  56 +0000000015 00000 n
  57 +0000000064 00000 n
  58 +0000000129 00000 n
  59 +0000000296 00000 n
  60 +0000000464 00000 n
  61 +0000000528 00000 n
  62 +0000000621 00000 n
  63 +0000000728 00000 n
  64 +0000000758 00000 n
  65 +0000000822 00000 n
  66 +trailer << /Root 1 0 R /Size 11 /ID [<071a6499182be9cfc990b11d0c4e5bc0><31415926535897932384626433832795>] >>
  67 +startxref
  68 +915
  69 +%%EOF