Commit 9ba5b27ce4ae8e42c836efedf44d08146e8eefa8
1 parent
2dbc1006
add double-page-size example
git-svn-id: svn+q:///qpdf/trunk@996 71b93d88-0707-0410-a8cf-f5a4172ac649
Showing
7 changed files
with
276 additions
and
6 deletions
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 |
TODO
| @@ -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 |