aboutsummaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/build.mk3
-rw-r--r--examples/pdf-bookmarks.cc193
-rw-r--r--examples/pdf-overlay-page.cc110
-rw-r--r--examples/pdf-split-pages.cc2
-rw-r--r--examples/qtest/create.test1
-rw-r--r--examples/qtest/overlay-page.test28
-rw-r--r--examples/qtest/overlay-page/in.pdfbin0 -> 1840 bytes
-rw-r--r--examples/qtest/overlay-page/out.pdfbin0 -> 3361 bytes
-rw-r--r--examples/qtest/overlay-page/stamp.pdfbin0 -> 799 bytes
9 files changed, 235 insertions, 102 deletions
diff --git a/examples/build.mk b/examples/build.mk
index 031601ff..8033d7d2 100644
--- a/examples/build.mk
+++ b/examples/build.mk
@@ -9,7 +9,8 @@ BINS_examples = \
pdf-split-pages \
pdf-filter-tokens \
pdf-count-strings \
- pdf-set-form-values
+ pdf-set-form-values \
+ pdf-overlay-page
CBINS_examples = pdf-linearize
TARGETS_examples = $(foreach B,$(BINS_examples) $(CBINS_examples),examples/$(OUTPUT_DIR)/$(call binname,$(B)))
diff --git a/examples/pdf-bookmarks.cc b/examples/pdf-bookmarks.cc
index ed5b8029..807fc02f 100644
--- a/examples/pdf-bookmarks.cc
+++ b/examples/pdf-bookmarks.cc
@@ -3,9 +3,14 @@
#include <stdlib.h>
#include <qpdf/QPDF.hh>
#include <qpdf/QPDFPageDocumentHelper.hh>
+#include <qpdf/QPDFOutlineDocumentHelper.hh>
#include <qpdf/QUtil.hh>
#include <qpdf/QTC.hh>
+// This program demonstrates extraction of bookmarks using the qpdf
+// outlines API. Note that all the information shown by this program
+// can also be obtained from a PDF file using qpdf's --json option.
+
static char const* whoami = 0;
static enum { st_none, st_numbers, st_lines } style = st_none;
static bool show_open = false;
@@ -56,111 +61,99 @@ void generate_page_map(QPDF& qpdf)
}
}
-void extract_bookmarks(QPDFObjectHandle outlines, std::vector<int>& numbers)
+void show_bookmark_details(QPDFOutlineObjectHelper outline,
+ std::vector<int> numbers)
{
- if (outlines.hasKey("/Title"))
+ // No default so gcc will warn on missing tag
+ switch (style)
{
- // No default so gcc will warn on missing tag
- switch (style)
- {
- case st_none:
- QTC::TC("examples", "pdf-bookmarks none");
- break;
-
- case st_numbers:
- QTC::TC("examples", "pdf-bookmarks numbers");
- for (std::vector<int>::iterator iter = numbers.begin();
- iter != numbers.end(); ++iter)
- {
- std::cout << *iter << ".";
- }
- std::cout << " ";
- break;
-
- case st_lines:
- QTC::TC("examples", "pdf-bookmarks lines");
- print_lines(numbers);
- std::cout << "|" << std::endl;
- print_lines(numbers);
- std::cout << "+-+ ";
- break;
- }
-
- if (show_open)
- {
- if (outlines.hasKey("/Count"))
- {
- QTC::TC("examples", "pdf-bookmarks has count");
- int count = outlines.getKey("/Count").getIntValue();
- if (count > 0)
- {
- // hierarchy is open at this point
- QTC::TC("examples", "pdf-bookmarks open");
- std::cout << "(v) ";
- }
- else
- {
- QTC::TC("examples", "pdf-bookmarks closed");
- std::cout << "(>) ";
- }
- }
- else
- {
- QTC::TC("examples", "pdf-bookmarks no count");
- std::cout << "( ) ";
- }
- }
-
- if (show_targets)
- {
- QTC::TC("examples", "pdf-bookmarks targets");
- std::string target = "unknown";
- // Only explicit destinations supported for now
- if (outlines.hasKey("/Dest"))
- {
- QTC::TC("examples", "pdf-bookmarks dest");
- QPDFObjectHandle dest = outlines.getKey("/Dest");
- if ((dest.isArray()) && (dest.getArrayNItems() > 0))
- {
- QPDFObjectHandle first = dest.getArrayItem(0);
- QPDFObjGen og = first.getObjGen();
- if (page_map.count(og))
- {
- target = QUtil::int_to_string(page_map[og]);
- }
- }
+ case st_none:
+ QTC::TC("examples", "pdf-bookmarks none");
+ break;
+
+ case st_numbers:
+ QTC::TC("examples", "pdf-bookmarks numbers");
+ for (std::vector<int>::iterator iter = numbers.begin();
+ iter != numbers.end(); ++iter)
+ {
+ std::cout << *iter << ".";
+ }
+ std::cout << " ";
+ break;
+
+ case st_lines:
+ QTC::TC("examples", "pdf-bookmarks lines");
+ print_lines(numbers);
+ std::cout << "|" << std::endl;
+ print_lines(numbers);
+ std::cout << "+-+ ";
+ break;
+ }
- std::cout << "[ -> " << target << " ] ";
- }
- }
+ if (show_open)
+ {
+ int count = outline.getCount();
+ if (count)
+ {
+ QTC::TC("examples", "pdf-bookmarks has count");
+ if (count > 0)
+ {
+ // hierarchy is open at this point
+ QTC::TC("examples", "pdf-bookmarks open");
+ std::cout << "(v) ";
+ }
+ else
+ {
+ QTC::TC("examples", "pdf-bookmarks closed");
+ std::cout << "(>) ";
+ }
+ }
+ else
+ {
+ QTC::TC("examples", "pdf-bookmarks no count");
+ std::cout << "( ) ";
+ }
+ }
- std::cout << outlines.getKey("/Title").getUTF8Value() << std::endl;
+ if (show_targets)
+ {
+ QTC::TC("examples", "pdf-bookmarks targets");
+ std::string target = "unknown";
+ QPDFObjectHandle dest_page = outline.getDestPage();
+ if (! dest_page.isNull())
+ {
+ QTC::TC("examples", "pdf-bookmarks dest");
+ QPDFObjGen og = dest_page.getObjGen();
+ if (page_map.count(og))
+ {
+ target = QUtil::int_to_string(page_map[og]);
+ }
+ }
+ std::cout << "[ -> " << target << " ] ";
}
- if (outlines.hasKey("/First"))
+ std::cout << outline.getTitle() << std::endl;
+}
+
+void extract_bookmarks(std::list<QPDFOutlineObjectHelper> outlines,
+ std::vector<int>& numbers)
+{
+ numbers.push_back(0);
+ for (std::list<QPDFOutlineObjectHelper>::iterator iter = outlines.begin();
+ iter != outlines.end(); ++iter)
{
- numbers.push_back(0);
- QPDFObjectHandle child = outlines.getKey("/First");
- while (1)
- {
- ++(numbers.back());
- bool has_next = child.hasKey("/Next");
- if ((style == st_lines) && (! has_next))
- {
- numbers.back() = 0;
- }
- extract_bookmarks(child, numbers);
- if (has_next)
- {
- child = child.getKey("/Next");
- }
- else
- {
- break;
- }
- }
- numbers.pop_back();
+ ++(numbers.back());
+ show_bookmark_details(*iter, numbers);
+ std::list<QPDFOutlineObjectHelper>::iterator next = iter;
+ ++next;
+ bool has_next = (next != outlines.end());
+ if ((style == st_lines) && (! has_next))
+ {
+ numbers.back() = 0;
+ }
+ extract_bookmarks((*iter).getKids(), numbers);
}
+ numbers.pop_back();
}
int main(int argc, char* argv[])
@@ -233,15 +226,15 @@ int main(int argc, char* argv[])
QPDF qpdf;
qpdf.processFile(filename, password);
- QPDFObjectHandle root = qpdf.getRoot();
- if (root.hasKey("/Outlines"))
+ QPDFOutlineDocumentHelper odh(qpdf);
+ if (odh.hasOutlines())
{
std::vector<int> numbers;
if (show_targets)
{
generate_page_map(qpdf);
}
- extract_bookmarks(root.getKey("/Outlines"), numbers);
+ extract_bookmarks(odh.getTopLevelOutlines(), numbers);
}
else
{
diff --git a/examples/pdf-overlay-page.cc b/examples/pdf-overlay-page.cc
new file mode 100644
index 00000000..88722352
--- /dev/null
+++ b/examples/pdf-overlay-page.cc
@@ -0,0 +1,110 @@
+#include <iostream>
+#include <string.h>
+#include <stdlib.h>
+#include <qpdf/QPDF.hh>
+#include <qpdf/QPDFPageDocumentHelper.hh>
+#include <qpdf/QPDFPageObjectHelper.hh>
+#include <qpdf/QPDFWriter.hh>
+#include <qpdf/QUtil.hh>
+
+// This program demonstrates use of form XObjects to overlay a page
+// from one file onto all pages of another file. The qpdf program's
+// --overlay and --underlay options provide a more general version of
+// this capability.
+
+static char const* whoami = 0;
+
+void usage()
+{
+ std::cerr << "Usage: " << whoami << " infile pagefile outfile"
+ << std::endl
+ << "Stamp page 1 of pagefile on every page of infile,"
+ << " writing to outfile"
+ << std::endl;
+ exit(2);
+}
+
+static void stamp_page(char const* infile,
+ char const* stampfile,
+ char const* outfile)
+{
+ QPDF inpdf;
+ inpdf.processFile(infile);
+ QPDF stamppdf;
+ stamppdf.processFile(stampfile);
+
+ // Get first page from other file
+ QPDFPageObjectHelper stamp_page_1 =
+ QPDFPageDocumentHelper(stamppdf).getAllPages().at(0);
+ // Convert page to a form XObject
+ QPDFObjectHandle foreign_fo = stamp_page_1.getFormXObjectForPage();
+ // Copy form XObject to the input file
+ QPDFObjectHandle stamp_fo = inpdf.copyForeignObject(foreign_fo);
+
+ // For each page...
+ std::vector<QPDFPageObjectHelper> pages =
+ QPDFPageDocumentHelper(inpdf).getAllPages();
+ for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
+ iter != pages.end(); ++iter)
+ {
+ QPDFPageObjectHelper& ph = *iter;
+
+ // Find a unique resource name for the new form XObject
+ QPDFObjectHandle resources = ph.getAttribute("/Resources", true);
+ int min_suffix = 1;
+ std::string name = resources.getUniqueResourceName("/Fx", min_suffix);
+
+ // Generate content to place the form XObject centered within
+ // destination page's trim box.
+ std::string content =
+ ph.placeFormXObject(
+ stamp_fo, name, ph.getTrimBox().getArrayAsRectangle());
+ if (! content.empty())
+ {
+ // Append the content to the page's content. Surround the
+ // original content with q...Q to the new content from the
+ // page's original content.
+ resources.mergeResources(
+ QPDFObjectHandle::parse("<< /XObject << >> >>"));
+ resources.getKey("/XObject").replaceKey(name, stamp_fo);
+ ph.addPageContents(
+ QPDFObjectHandle::newStream(&inpdf, "q\n"), true);
+ ph.addPageContents(
+ QPDFObjectHandle::newStream(&inpdf, "\nQ\n" + content), false);
+ }
+ }
+
+ QPDFWriter w(inpdf, outfile);
+ w.setStaticID(true); // for testing only
+ w.write();
+}
+
+int main(int argc, char* argv[])
+{
+ whoami = QUtil::getWhoami(argv[0]);
+
+ // For libtool's sake....
+ if (strncmp(whoami, "lt-", 3) == 0)
+ {
+ whoami += 3;
+ }
+
+ if (argc != 4)
+ {
+ usage();
+ }
+ char const* infile = argv[1];
+ char const* stampfile = argv[2];
+ char const* outfile = argv[3];
+
+ try
+ {
+ stamp_page(infile, stampfile, outfile);
+ }
+ catch (std::exception &e)
+ {
+ std::cerr << whoami << ": " << e.what() << std::endl;
+ exit(2);
+ }
+ return 0;
+}
diff --git a/examples/pdf-split-pages.cc b/examples/pdf-split-pages.cc
index b65f96ee..aa089e5a 100644
--- a/examples/pdf-split-pages.cc
+++ b/examples/pdf-split-pages.cc
@@ -77,7 +77,7 @@ int main(int argc, char* argv[])
{
process(whoami, argv[1], argv[2]);
}
- catch (std::exception e)
+ catch (std::exception const& e)
{
std::cerr << whoami << ": exception: " << e.what() << std::endl;
return 2;
diff --git a/examples/qtest/create.test b/examples/qtest/create.test
index f83509e2..f18c5fd6 100644
--- a/examples/qtest/create.test
+++ b/examples/qtest/create.test
@@ -23,4 +23,5 @@ $td->report(1);
sub cleanup
{
unlink "a.pdf";
+ unlink "tmp.out";
}
diff --git a/examples/qtest/overlay-page.test b/examples/qtest/overlay-page.test
new file mode 100644
index 00000000..68e695d3
--- /dev/null
+++ b/examples/qtest/overlay-page.test
@@ -0,0 +1,28 @@
+#!/usr/bin/env perl
+require 5.008;
+use warnings;
+use strict;
+
+chdir("overlay-page");
+
+require TestDriver;
+
+my $td = new TestDriver('overlay-page');
+
+cleanup();
+
+$td->runtest("overlay-page",
+ {$td->COMMAND => "pdf-overlay-page in.pdf stamp.pdf a.pdf"},
+ {$td->STRING => "", $td->EXIT_STATUS => 0});
+$td->runtest("compare files",
+ {$td->FILE => "a.pdf"},
+ {$td->FILE => "out.pdf"});
+
+cleanup();
+
+$td->report(2);
+
+sub cleanup
+{
+ unlink("a.pdf");
+}
diff --git a/examples/qtest/overlay-page/in.pdf b/examples/qtest/overlay-page/in.pdf
new file mode 100644
index 00000000..f94c739a
--- /dev/null
+++ b/examples/qtest/overlay-page/in.pdf
Binary files differ
diff --git a/examples/qtest/overlay-page/out.pdf b/examples/qtest/overlay-page/out.pdf
new file mode 100644
index 00000000..b589d2c4
--- /dev/null
+++ b/examples/qtest/overlay-page/out.pdf
Binary files differ
diff --git a/examples/qtest/overlay-page/stamp.pdf b/examples/qtest/overlay-page/stamp.pdf
new file mode 100644
index 00000000..a86f4344
--- /dev/null
+++ b/examples/qtest/overlay-page/stamp.pdf
Binary files differ