aboutsummaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorm-holger <m-holger@kubitscheck.org>2023-05-27 19:19:52 +0200
committerm-holger <m-holger@kubitscheck.org>2023-06-02 17:00:40 +0200
commit3c5700c255f4603b5df9c6d183d13dd71a083cc3 (patch)
tree0f01c62c54b56d009b341922fa3441907a2e560b /examples
parent6e6a73d28f5f61f038209a61a3e85995dc71aa32 (diff)
downloadqpdf-3c5700c255f4603b5df9c6d183d13dd71a083cc3.tar.zst
Code tidy - reflow comments and strings
Diffstat (limited to 'examples')
-rw-r--r--examples/pdf-attach-file.cc22
-rw-r--r--examples/pdf-bookmarks.cc15
-rw-r--r--examples/pdf-c-objects.c11
-rw-r--r--examples/pdf-count-strings.cc20
-rw-r--r--examples/pdf-create.cc59
-rw-r--r--examples/pdf-custom-filter.cc327
-rw-r--r--examples/pdf-double-page-size.cc10
-rw-r--r--examples/pdf-filter-tokens.cc74
-rw-r--r--examples/pdf-invert-images.cc65
-rw-r--r--examples/pdf-linearize.c3
-rw-r--r--examples/pdf-name-number-tree.cc53
-rw-r--r--examples/pdf-overlay-page.cc22
-rw-r--r--examples/pdf-parse-content.cc4
-rw-r--r--examples/pdf-set-form-values.cc40
-rw-r--r--examples/pdf-split-pages.cc8
-rw-r--r--examples/qpdf-job.cc10
-rw-r--r--examples/qpdfjob-c-save-attachment.c12
-rw-r--r--examples/qpdfjob-c.c17
-rw-r--r--examples/qpdfjob-remove-annotations.cc7
-rw-r--r--examples/qpdfjob-save-attachment.cc7
20 files changed, 323 insertions, 463 deletions
diff --git a/examples/pdf-attach-file.cc b/examples/pdf-attach-file.cc
index b5a1c64a..9ae3b247 100644
--- a/examples/pdf-attach-file.cc
+++ b/examples/pdf-attach-file.cc
@@ -8,11 +8,10 @@
#include <iostream>
//
-// This example attaches a file to an input file, adds a page to the
-// beginning of the file that includes a file attachment annotation,
-// and writes the result to an output file. It also illustrates a
-// number of new API calls that were added in qpdf 10.2 as well as
-// the use of the qpdf literal syntax introduced in qpdf 10.6.
+// This example attaches a file to an input file, adds a page to the beginning of the file that
+// includes a file attachment annotation, and writes the result to an output file. It also
+// illustrates a number of new API calls that were added in qpdf 10.2 as well as the use of the qpdf
+// literal syntax introduced in qpdf 10.6.
//
static char const* whoami = nullptr;
@@ -43,8 +42,8 @@ process(
QPDF q;
q.processFile(infilename, password);
- // Create an indirect object for the built-in Helvetica font. This
- // uses the qpdf literal syntax introduced in qpdf 10.6.
+ // Create an indirect object for the built-in Helvetica font. This uses the qpdf literal syntax
+ // introduced in qpdf 10.6.
auto f1 = q.makeIndirectObject(
// force line-break
"<<"
@@ -55,9 +54,8 @@ process(
" /Encoding /WinAnsiEncoding"
">>"_qpdf);
- // Create a resources dictionary with fonts. This uses the new
- // parse introduced in qpdf 10.2 that takes a QPDF* and allows
- // indirect object references.
+ // Create a resources dictionary with fonts. This uses the new parse introduced in qpdf 10.2
+ // that takes a QPDF* and allows indirect object references.
auto resources = q.makeIndirectObject(
// line-break
QPDFObjectHandle::parse(
@@ -97,8 +95,8 @@ process(
"S\n");
auto apdict = ap.getDict();
- // The following four lines demonstrate the use of the qpdf literal syntax
- // introduced in qpdf 10.6. They could have been written as:
+ // The following four lines demonstrate the use of the qpdf literal syntax introduced in
+ // qpdf 10.6. They could have been written as:
// apdict.replaceKey("/Resources", QPDFObjectHandle::newDictionary());
// apdict.replaceKey("/Type", QPDFObjectHandle::newName("/XObject"));
// apdict.replaceKey("/Subtype", QPDFObjectHandle::newName("/Form"));
diff --git a/examples/pdf-bookmarks.cc b/examples/pdf-bookmarks.cc
index d40ded6a..9581a135 100644
--- a/examples/pdf-bookmarks.cc
+++ b/examples/pdf-bookmarks.cc
@@ -8,9 +8,9 @@
#include <cstring>
#include <iostream>
-// 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.
+// 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.
//
// Ignore calls to QTC::TC - they are for qpdf CI testing only.
@@ -118,11 +118,10 @@ show_bookmark_details(QPDFOutlineObjectHelper outline, std::vector<int> numbers)
void
extract_bookmarks(std::vector<QPDFOutlineObjectHelper> outlines, std::vector<int>& numbers)
{
- // For style == st_numbers, numbers.at(n) contains the numerical
- // label for the outline, so we count up from 1.
- // For style == st_lines, numbers.at(n) == 0 indicates the last
- // outline at level n, and we don't otherwise care what the value
- // is, so we count up to zero.
+ // For style == st_numbers, numbers.at(n) contains the numerical label for the outline, so we
+ // count up from 1.
+ // For style == st_lines, numbers.at(n) == 0 indicates the last outline at level n, and we don't
+ // otherwise care what the value is, so we count up to zero.
numbers.push_back((style == st_lines) ? -QIntC::to_int(outlines.size()) : 0);
for (auto& outline: outlines) {
++(numbers.back());
diff --git a/examples/pdf-c-objects.c b/examples/pdf-c-objects.c
index f4b872a7..171a9b66 100644
--- a/examples/pdf-c-objects.c
+++ b/examples/pdf-c-objects.c
@@ -1,7 +1,4 @@
-/*
- * This is an example program to demonstrate use of object handle
- * functions in the C API.
- */
+/* This is an example program to demonstrate use of object handle functions in the C API. */
#include <qpdf/qpdf-c.h>
#include <stdio.h>
@@ -20,8 +17,7 @@ usage()
QPDF_BOOL
modify_file(qpdf_data qpdf)
{
- /* This small example performs the following operation on the
- * document catalog (a.k.a. root):
+ /* This small example performs the following operation on the document catalog (a.k.a. root):
* - Remove PageLayout
* - Remove OpenAction
* - If there are outlines, set PageMode to UseOutlines; otherwise,
@@ -72,8 +68,7 @@ main(int argc, char* argv[])
if (((qpdf_read(qpdf, infile, password) & QPDF_ERRORS) == 0) && modify_file(qpdf) &&
((qpdf_init_write(qpdf, outfile) & QPDF_ERRORS) == 0)) {
- /* Use static ID for testing only. For production, a
- * non-static ID is used. See also
+ /* Use static ID for testing only. For production, a non-static ID is used. See also
* qpdf_set_deterministic_ID. */
qpdf_set_static_ID(qpdf, QPDF_TRUE); /* for testing only */
qpdf_write(qpdf);
diff --git a/examples/pdf-count-strings.cc b/examples/pdf-count-strings.cc
index c70e183e..2061a499 100644
--- a/examples/pdf-count-strings.cc
+++ b/examples/pdf-count-strings.cc
@@ -1,7 +1,7 @@
//
-// This example illustrates the use of QPDFObjectHandle::TokenFilter
-// with filterContents. See also pdf-filter-tokens.cc for an example
-// that uses QPDFObjectHandle::TokenFilter with addContentTokenFilter.
+// This example illustrates the use of QPDFObjectHandle::TokenFilter with filterContents. See also
+// pdf-filter-tokens.cc for an example that uses QPDFObjectHandle::TokenFilter with
+// addContentTokenFilter.
//
#include <cstdlib>
@@ -46,16 +46,15 @@ StringCounter::handleToken(QPDFTokenizer::Token const& token)
if (token.getType() == QPDFTokenizer::tt_string) {
++this->count;
}
- // Preserve input verbatim by passing each token to any specified
- // downstream filter.
+ // Preserve input verbatim by passing each token to any specified downstream filter.
writeToken(token);
}
void
StringCounter::handleEOF()
{
- // Write a comment at the end of the stream just to show how we
- // can enhance the output if we want.
+ // Write a comment at the end of the stream just to show how we can enhance the output if we
+ // want.
write("\n% strings found: ");
write(std::to_string(this->count));
}
@@ -82,10 +81,9 @@ main(int argc, char* argv[])
int pageno = 0;
for (auto& page: QPDFPageDocumentHelper(pdf).getAllPages()) {
++pageno;
- // Pass the contents of a page through our string counter.
- // If it's an even page, capture the output. This
- // illustrates that you may capture any output generated
- // by the filter, or you may ignore it.
+ // Pass the contents of a page through our string counter. If it's an even page, capture
+ // the output. This illustrates that you may capture any output generated by the filter,
+ // or you may ignore it.
StringCounter counter;
if (pageno % 2) {
// Ignore output for odd pages.
diff --git a/examples/pdf-create.cc b/examples/pdf-create.cc
index e0fa93b1..c793b5f8 100644
--- a/examples/pdf-create.cc
+++ b/examples/pdf-create.cc
@@ -1,7 +1,6 @@
//
-// This is an example of creating a PDF file from scratch. It
-// illustrates use of several QPDF operations for creating objects and
-// streams. It also serves as an illustration of how to use
+// This is an example of creating a PDF file from scratch. It illustrates use of several QPDF
+// operations for creating objects and streams. It also serves as an illustration of how to use
// StreamDataProvider with different types of filters.
//
@@ -20,8 +19,8 @@
static char const* whoami = nullptr;
-// This is a simple StreamDataProvider that writes image data for an
-// orange square of the given width and height.
+// This is a simple StreamDataProvider that writes image data for an orange square of the given
+// width and height.
class ImageProvider: public QPDFObjectHandle::StreamDataProvider
{
public:
@@ -130,8 +129,7 @@ usage()
static QPDFObjectHandle
createPageContents(QPDF& pdf, std::string const& text)
{
- // Create a stream that displays our image and the given text in
- // our font.
+ // Create a stream that displays our image and the given text in our font.
std::string contents = "BT /F1 24 Tf 72 320 Td (" + text +
") Tj ET\n"
"q 244 0 0 144 184 100 cm /Im1 Do Q\n";
@@ -159,11 +157,9 @@ add_page(
{
QPDF& pdf(dh.getQPDF());
- // Create a stream to encode our image. QPDFWriter will fill in
- // the length and will respect our filters based on stream data
- // mode. Since we are not specifying, QPDFWriter will compress
- // with /FlateDecode if we don't provide any other form of
- // compression.
+ // Create a stream to encode our image. QPDFWriter will fill in the length and will respect our
+ // filters based on stream data mode. Since we are not specifying, QPDFWriter will compress with
+ // /FlateDecode if we don't provide any other form of compression.
auto* p = new ImageProvider(color_space, filter);
std::shared_ptr<QPDFObjectHandle::StreamDataProvider> provider(p);
size_t width = p->getWidth();
@@ -219,20 +215,17 @@ check(
std::vector<std::string> const& color_spaces,
std::vector<std::string> const& filters)
{
- // Each stream is compressed the way it is supposed to be. We will
- // add additional tests in qpdf.test to exercise QPDFWriter more
- // fully. In this case, we want to make sure that we actually have
- // RunLengthDecode and DCTDecode where we are supposed to and
- // FlateDecode where we provided no filters.
+ // Each stream is compressed the way it is supposed to be. We will add additional tests in
+ // qpdf.test to exercise QPDFWriter more fully. In this case, we want to make sure that we
+ // actually have RunLengthDecode and DCTDecode where we are supposed to and FlateDecode where we
+ // provided no filters.
- // Each image is correct. For non-lossy image compression, the
- // uncompressed image data should exactly match what ImageProvider
- // provided. For the DCTDecode data, allow for some fuzz to handle
- // jpeg compression as well as its variance on different systems.
+ // Each image is correct. For non-lossy image compression, the uncompressed image data should
+ // exactly match what ImageProvider provided. For the DCTDecode data, allow for some fuzz to
+ // handle jpeg compression as well as its variance on different systems.
- // These tests should use QPDFObjectHandle's stream data retrieval
- // methods, but don't try to fully exercise them here. That is
- // done elsewhere.
+ // These tests should use QPDFObjectHandle's stream data retrieval methods, but don't try to
+ // fully exercise them here. That is done elsewhere.
size_t n_color_spaces = color_spaces.size();
size_t n_filters = filters.size();
@@ -254,8 +247,8 @@ check(
// Check filter and color space.
std::string desired_color_space = color_spaces[(pageno - 1) / n_color_spaces];
std::string desired_filter = filters[(pageno - 1) % n_filters];
- // In the default mode, QPDFWriter will compress with
- // /FlateDecode if no filters are provided.
+ // In the default mode, QPDFWriter will compress with /FlateDecode if no filters are
+ // provided.
if (desired_filter == "null") {
desired_filter = "/FlateDecode";
}
@@ -288,11 +281,9 @@ check(
std::cout << "page " << pageno << ": image data length mismatch" << std::endl;
this_errors = errors = true;
} else {
- // Compare bytes. For JPEG, allow a certain number of
- // the bytes to be off desired by more than a given
- // tolerance. Any of the samples may be a little off
- // because of lossy compression, and around sharp
- // edges, things can be quite off. For non-lossy
+ // Compare bytes. For JPEG, allow a certain number of the bytes to be off desired by
+ // more than a given tolerance. Any of the samples may be a little off because of
+ // lossy compression, and around sharp edges, things can be quite off. For non-lossy
// compression, do not allow any tolerance.
unsigned char const* actual_bytes = actual_data->getBuffer();
unsigned char const* desired_bytes = desired_data->getBuffer();
@@ -332,8 +323,7 @@ create_pdf(char const* filename)
// Start with an empty PDF that has no pages or non-required objects.
pdf.emptyPDF();
- // Add an indirect object to contain a font descriptor for the
- // built-in Helvetica font.
+ // Add an indirect object to contain a font descriptor for the built-in Helvetica font.
QPDFObjectHandle font = pdf.makeIndirectObject(
// line-break
"<<"
@@ -362,8 +352,7 @@ create_pdf(char const* filename)
QPDFWriter w(pdf, filename);
w.write();
- // For test suite, verify that everything is the way it is
- // supposed to be.
+ // For test suite, verify that everything is the way it is supposed to be.
check(filename, color_spaces, filters);
}
diff --git a/examples/pdf-custom-filter.cc b/examples/pdf-custom-filter.cc
index 57eedf74..e3cdf164 100644
--- a/examples/pdf-custom-filter.cc
+++ b/examples/pdf-custom-filter.cc
@@ -8,43 +8,35 @@
#include <iostream>
#include <memory>
-// This example shows you everything you need to know to implement a
-// custom stream filter for encoding and decoding as well as a stream
-// data provider that modifies the stream's dictionary. This example
-// uses the pattern of having the stream data provider class use a
-// second QPDF instance with copies of streams from the original QPDF
-// so that the stream data provider can access the original stream
-// data. This is implemented very efficiently inside the qpdf library as
-// the second QPDF instance knows how to read the stream data from the
-// original input file, so no extra copies of the original stream data
-// are made.
-
-// This example creates an imaginary filter called /XORDecode. There
-// is no such filter in PDF, so the streams created by the example
-// would not be usable by any PDF reader. However, the techniques here
-// would work if you were going to implement support for a filter that
-// qpdf does not support natively. For example, using the techniques
-// shown here, it would be possible to create an application that
-// downsampled or re-encoded images or that re-compressed streams
-// using a more efficient "deflate" implementation than zlib.
-
-// Comments appear throughout the code describing each piece of code
-// and its purpose. You can read the file top to bottom, or you can
-// start with main() and follow the flow.
-
-// Please also see the test suite, qtest/custom-filter.test, which
-// contains additional comments describing how to observe the results
-// of running this example on test files that are specifically crafted
-// for it.
+// This example shows you everything you need to know to implement a custom stream filter for
+// encoding and decoding as well as a stream data provider that modifies the stream's dictionary.
+// This example uses the pattern of having the stream data provider class use a second QPDF instance
+// with copies of streams from the original QPDF so that the stream data provider can access the
+// original stream data. This is implemented very efficiently inside the qpdf library as the second
+// QPDF instance knows how to read the stream data from the original input file, so no extra copies
+// of the original stream data are made.
+
+// This example creates an imaginary filter called /XORDecode. There is no such filter in PDF, so
+// the streams created by the example would not be usable by any PDF reader. However, the techniques
+// here would work if you were going to implement support for a filter that qpdf does not support
+// natively. For example, using the techniques shown here, it would be possible to create an
+// application that downsampled or re-encoded images or that re-compressed streams using a more
+// efficient "deflate" implementation than zlib.
+
+// Comments appear throughout the code describing each piece of code and its purpose. You can read
+// the file top to bottom, or you can start with main() and follow the flow.
+
+// Please also see the test suite, qtest/custom-filter.test, which contains additional comments
+// describing how to observe the results of running this example on test files that are specifically
+// crafted for it.
static char const* whoami = nullptr;
class Pl_XOR: public Pipeline
{
- // This class implements a Pipeline for the made-up XOR decoder.
- // It is initialized with a single-byte "key" and just XORs each
- // byte with that key. This makes it reversible, so there is no
- // distinction between encoding and decoding.
+ // This class implements a Pipeline for the made-up XOR decoder. It is initialized with a
+ // single-byte "key" and just XORs each byte with that key. This makes it reversible, so there
+ // is no distinction between encoding and decoding.
public:
Pl_XOR(char const* identifier, Pipeline* next, unsigned char key);
@@ -79,17 +71,14 @@ Pl_XOR::finish()
class SF_XORDecode: public QPDFStreamFilter
{
- // This class implements a QPDFStreamFilter that knows how to
- // validate and interpret decode parameters (/DecodeParms) for the
- // made-up /XORDecode stream filter. Since this is not a real
- // stream filter, no actual PDF reader would know how to interpret
- // it. This is just to illustrate how to create a stream filter.
- // In main(), we call QPDF::registerStreamFilter to tell the
- // library about the filter. See comments in QPDFStreamFilter.hh
- // for details on how to implement the methods. For purposes of
- // example, we are calling this a "specialized" compression
- // filter, which just means QPDF assumes that it should not
- // "uncompress" the stream by default.
+ // This class implements a QPDFStreamFilter that knows how to validate and interpret decode
+ // parameters (/DecodeParms) for the made-up /XORDecode stream filter. Since this is not a real
+ // stream filter, no actual PDF reader would know how to interpret it. This is just to
+ // illustrate how to create a stream filter. In main(), we call QPDF::registerStreamFilter to
+ // tell the library about the filter. See comments in QPDFStreamFilter.hh for details on how to
+ // implement the methods. For purposes of example, we are calling this a "specialized"
+ // compression filter, which just means QPDF assumes that it should not "uncompress" the stream
+ // by default.
public:
~SF_XORDecode() override = default;
bool setDecodeParms(QPDFObjectHandle decode_parms) override;
@@ -98,33 +87,28 @@ class SF_XORDecode: public QPDFStreamFilter
private:
unsigned char key;
- // It is the responsibility of the QPDFStreamFilter implementation
- // to ensure that the pipeline returned by getDecodePipeline() is
- // deleted when the class is deleted. The easiest way to do this
- // is to stash the pipeline in a std::shared_ptr, which enables us
- // to use the default destructor implementation.
+ // It is the responsibility of the QPDFStreamFilter implementation to ensure that the pipeline
+ // returned by getDecodePipeline() is deleted when the class is deleted. The easiest way to do
+ // this is to stash the pipeline in a std::shared_ptr, which enables us to use the default
+ // destructor implementation.
std::shared_ptr<Pl_XOR> pipeline;
};
bool
SF_XORDecode::setDecodeParms(QPDFObjectHandle decode_parms)
{
- // For purposes of example, we store the key in a separate stream.
- // We could just as well store the key directly in /DecodeParms,
- // but this example uses a stream to illustrate how one might do
- // that. For example, if implementing /JBIG2Decode, one would need
- // to handle the /JBIG2Globals key, which points to a stream. See
- // comments in SF_XORDecode::registerStream for additional notes
- // on this.
+ // For purposes of example, we store the key in a separate stream. We could just as well store
+ // the key directly in /DecodeParms, but this example uses a stream to illustrate how one might
+ // do that. For example, if implementing /JBIG2Decode, one would need to handle the
+ // /JBIG2Globals key, which points to a stream. See comments in SF_XORDecode::registerStream for
+ // additional notes on this.
try {
- // Expect /DecodeParms to be a dictionary with a /KeyStream
- // key that points to a one-byte stream whose single byte is
- // the key. If we are successful at retrieving the key, return
- // true, indicating that we are able to process with the given
- // decode parameters. Under any other circumstances, return
- // false. For other examples of QPDFStreamFilter
- // implementations, look at the classes whose names start with
- // SF_ in the qpdf library implementation.
+ // Expect /DecodeParms to be a dictionary with a /KeyStream key that points to a one-byte
+ // stream whose single byte is the key. If we are successful at retrieving the key, return
+ // true, indicating that we are able to process with the given decode parameters. Under any
+ // other circumstances, return false. For other examples of QPDFStreamFilter
+ // implementations, look at the classes whose names start with SF_ in the qpdf library
+ // implementation.
auto buf = decode_parms.getKey("/KeyStream").getStreamData();
if (buf->getSize() != 1) {
return false;
@@ -140,14 +124,12 @@ SF_XORDecode::setDecodeParms(QPDFObjectHandle decode_parms)
Pipeline*
SF_XORDecode::getDecodePipeline(Pipeline* next)
{
- // Return a pipeline that the qpdf library should pass the stream
- // data through. The pipeline should receive encoded data and pass
- // decoded data to "next". getDecodePipeline() can always count on
- // setDecodeParms() having been called first. The setDecodeParms()
- // method should store any parameters needed by the pipeline. To
- // ensure that the pipeline we return disappears when the class
- // disappears, stash it in a std::shared_ptr<Pl_XOR> and retrieve
- // the raw pointer from there.
+ // Return a pipeline that the qpdf library should pass the stream data through. The pipeline
+ // should receive encoded data and pass decoded data to "next". getDecodePipeline() can always
+ // count on setDecodeParms() having been called first. The setDecodeParms() method should store
+ // any parameters needed by the pipeline. To ensure that the pipeline we return disappears when
+ // the class disappears, stash it in a std::shared_ptr<Pl_XOR> and retrieve the raw pointer from
+ // there.
this->pipeline = std::make_shared<Pl_XOR>("xor", next, this->key);
return this->pipeline.get();
}
@@ -155,46 +137,37 @@ SF_XORDecode::getDecodePipeline(Pipeline* next)
bool
SF_XORDecode::isSpecializedCompression()
{
- // The default implementation of QPDFStreamFilter would return
- // false, so if you want a specialized or lossy compression
- // filter, override one of the methods as described in
+ // The default implementation of QPDFStreamFilter would return false, so if you want a
+ // specialized or lossy compression filter, override one of the methods as described in
// QPDFStreamFilter.hh.
return true;
}
class StreamReplacer: public QPDFObjectHandle::StreamDataProvider
{
- // This class implements a StreamDataProvider that, under specific
- // conditions, replaces the stream data with data encoded with the
- // made-up /XORDecode filter.
+ // This class implements a StreamDataProvider that, under specific conditions, replaces the
+ // stream data with data encoded with the made-up /XORDecode filter.
// The flow for this class is as follows:
//
- // * The main application iterates through streams that should be
- // replaced and calls registerStream. registerStream in turn
- // calls maybeReplace passing nullptr to pipeline and the
- // address of a valid QPDFObjectHandle to dict_updates. The
- // stream passed in for this call is the stream for the original
- // QPDF object. It has not yet been altered, so we have access
- // to its original dictionary and data. As described in the
- // method, the method when called in this way makes a
- // determination as to whether the stream should be replaced. If
- // so, registerStream makes whatever changes are required. We
- // have to do this now because we can't modify the stream during
- // the writing process.
+ // * The main application iterates through streams that should be replaced and calls
+ // registerStream. registerStream in turn calls maybeReplace passing nullptr to pipeline and
+ // the address of a valid QPDFObjectHandle to dict_updates. The stream passed in for this call
+ // is the stream for the original QPDF object. It has not yet been altered, so we have access
+ // to its original dictionary and data. As described in the method, the method when called in
+ // this way makes a determination as to whether the stream should be replaced. If so,
+ // registerStream makes whatever changes are required. We have to do this now because we can't
+ // modify the stream during the writing process.
//
- // * provideStreamData(), which is called by QPDFWriter during the
- // write process, actually writes the modified stream data. It
- // calls maybeReplace again, but this time it passes a valid
- // pipeline and passes nullptr to dict_updates. In this mode,
- // the stream dictionary has already been altered, and the
- // original stream data is no longer directly accessible. Trying
- // to retrieve the stream data would cause an infinite loop because
- // it would just end up calling provideStreamData again. This is
- // why maybeReplace uses a stashed copy of the original stream.
-
- // Additional explanation can be found in the method
- // implementations.
+ // * provideStreamData(), which is called by QPDFWriter during the write process, actually
+ // writes the modified stream data. It calls maybeReplace again, but this time it passes a
+ // valid pipeline and passes nullptr to dict_updates. In this mode, the stream dictionary has
+ // already been altered, and the original stream data is no longer directly accessible. Trying
+ // to retrieve the stream data would cause an infinite loop because it would just end up
+ // calling provideStreamData again. This is why maybeReplace uses a stashed copy of the
+ // original stream.
+
+ // Additional explanation can be found in the method implementations.
public:
StreamReplacer(QPDF* pdf);
@@ -211,17 +184,16 @@ class StreamReplacer: public QPDFObjectHandle::StreamDataProvider
Pipeline* pipeline,
QPDFObjectHandle* dict_updates);
- // Hang onto a reference to the QPDF object containing the streams
- // we are replacing. We need this to create a new stream.
+ // Hang onto a reference to the QPDF object containing the streams we are replacing. We need
+ // this to create a new stream.
QPDF* pdf;
- // Map the object/generation in original file to the copied stream
- // in "other". We use this to retrieve the original data.
+ // Map the object/generation in original file to the copied stream in "other". We use this to
+ // retrieve the original data.
std::map<QPDFObjGen, QPDFObjectHandle> copied_streams;
- // Each stream gets is own "key" for the XOR filter. We use a
- // single instance of StreamReplacer for all streams, so stash all
- // the keys here.
+ // Each stream gets is own "key" for the XOR filter. We use a single instance of StreamReplacer
+ // for all streams, so stash all the keys here.
std::map<QPDFObjGen, unsigned char> keys;
};
@@ -237,49 +209,38 @@ StreamReplacer::maybeReplace(
Pipeline* pipeline,
QPDFObjectHandle* dict_updates)
{
- // As described in the class comments, this method is called
- // twice. Before writing has started pipeline is nullptr, and
- // dict_updates is provided. In this mode, we figure out whether
- // we should replace the stream and, if so, take care of the
- // necessary setup. When we are actually ready to supply the data,
- // this method is called again with pipeline populated and
- // dict_updates as a nullptr. In this mode, we are not allowed to
- // change anything, since writing is already in progress. We
- // must simply provide the stream data.
-
- // The return value indicates whether or not we should replace the
- // stream. If the first call returns false, there will be no
- // second call. If the second call returns false, something went
- // wrong since the method should always make the same decision for
- // a given stream.
-
- // For this example, all the determination logic could have
- // appeared inside the if (dict_updates) block rather than being
- // duplicated, but in some cases, there may be a reason to
- // duplicate things. For example, if you wanted to write code that
- // re-encoded an image if the new encoding was more efficient,
- // you'd have to actually try it out. Then you would either have
- // to cache the result somewhere or just repeat the calculations,
- // depending on space/time constraints, etc.
-
- // In our contrived example, we are replacing the data for all
- // streams that have /DoXOR = true in the stream dictionary. If
- // this were a more realistic application, our criteria would be
- // more sensible. For example, an image downsampler might choose
- // to replace a stream that represented an image with a high pixel
- // density.
+ // As described in the class comments, this method is called twice. Before writing has started
+ // pipeline is nullptr, and dict_updates is provided. In this mode, we figure out whether we
+ // should replace the stream and, if so, take care of the necessary setup. When we are actually
+ // ready to supply the data, this method is called again with pipeline populated and
+ // dict_updates as a nullptr. In this mode, we are not allowed to change anything, since writing
+ // is already in progress. We must simply provide the stream data.
+
+ // The return value indicates whether or not we should replace the stream. If the first call
+ // returns false, there will be no second call. If the second call returns false, something went
+ // wrong since the method should always make the same decision for a given stream.
+
+ // For this example, all the determination logic could have appeared inside the if
+ // (dict_updates) block rather than being duplicated, but in some cases, there may be a reason
+ // to duplicate things. For example, if you wanted to write code that re-encoded an image if the
+ // new encoding was more efficient, you'd have to actually try it out. Then you would either
+ // have to cache the result somewhere or just repeat the calculations, depending on space/time
+ // constraints, etc.
+
+ // In our contrived example, we are replacing the data for all streams that have /DoXOR = true
+ // in the stream dictionary. If this were a more realistic application, our criteria would be
+ // more sensible. For example, an image downsampler might choose to replace a stream that
+ // represented an image with a high pixel density.
auto dict = stream.getDict();
auto mark = dict.getKey("/DoXOR");
if (!(mark.isBool() && mark.getBoolValue())) {
return false;
}
- // We can't replace the stream data if we can't get the original
- // stream data for any reason. A more realistic application may
- // actually look at the data here as well, or it may be able to
- // make all its decisions from the stream dictionary. However,
- // it's a good idea to make sure we can retrieve the filtered data
- // if we are going to need it later.
+ // We can't replace the stream data if we can't get the original stream data for any reason. A
+ // more realistic application may actually look at the data here as well, or it may be able to
+ // make all its decisions from the stream dictionary. However, it's a good idea to make sure we
+ // can retrieve the filtered data if we are going to need it later.
std::shared_ptr<Buffer> out;
try {
out = stream.getStreamData();
@@ -288,19 +249,15 @@ StreamReplacer::maybeReplace(
}
if (dict_updates) {
- // It's not safe to make any modifications to any objects
- // during the writing process since the updated objects may
- // have already been written. In this mode, when dict_updates
- // is provided, we have not started writing. Store the
- // modifications we intend to make to the stream dictionary
- // here. We're just storing /OrigLength for purposes of
- // example. Again, a realistic application would make other
- // changes. For example, an image resampler might change the
- // dimensions or other properties of the image.
+ // It's not safe to make any modifications to any objects during the writing process since
+ // the updated objects may have already been written. In this mode, when dict_updates is
+ // provided, we have not started writing. Store the modifications we intend to make to the
+ // stream dictionary here. We're just storing /OrigLength for purposes of example. Again, a
+ // realistic application would make other changes. For example, an image resampler might
+ // change the dimensions or other properties of the image.
dict_updates->replaceKey(
"/OrigLength", QPDFObjectHandle::newInteger(QIntC::to_longlong(out->getSize())));
- // We are also storing the "key" that we will access when
- // writing the data.
+ // We are also storing the "key" that we will access when writing the data.
this->keys[og] = QIntC::to_uchar((og.getObj() * QIntC::to_int(out->getSize())) & 0xff);
}
@@ -319,21 +276,18 @@ StreamReplacer::registerStream(
{
QPDFObjGen og(stream.getObjGen());
- // We don't need to process a stream more than once. In this
- // example, we are just iterating through objects, but if we were
- // doing something like iterating through images on pages, we
+ // We don't need to process a stream more than once. In this example, we are just iterating
+ // through objects, but if we were doing something like iterating through images on pages, we
// might realistically encounter the same stream more than once.
if (this->copied_streams.count(og) > 0) {
return;
}
- // Store something in copied_streams so that we don't
- // double-process even in the negative case. This gets replaced
- // later if needed.
+ // Store something in copied_streams so that we don't double-process even in the negative case.
+ // This gets replaced later if needed.
this->copied_streams[og] = QPDFObjectHandle::newNull();
- // Call maybeReplace with dict_updates. In this mode, it
- // determines whether we should replace the stream data and, if
- // so, supplies dictionary updates we should make.
+ // Call maybeReplace with dict_updates. In this mode, it determines whether we should replace
+ // the stream data and, if so, supplies dictionary updates we should make.
bool should_replace = false;
QPDFObjectHandle dict_updates = QPDFObjectHandle::newDictionary();
try {
@@ -343,9 +297,8 @@ StreamReplacer::registerStream(
}
if (should_replace) {
- // Copy the stream so we can get to the original data from the
- // stream data provider. This doesn't actually copy any data,
- // but the copy retains the original stream data after the
+ // Copy the stream so we can get to the original data from the stream data provider. This
+ // doesn't actually copy any data, but the copy retains the original stream data after the
// original one is modified.
this->copied_streams[og] = stream.copyStream();
// Update the stream dictionary with any changes.
@@ -353,20 +306,17 @@ StreamReplacer::registerStream(
for (auto const& k: dict_updates.getKeys()) {
dict.replaceKey(k, dict_updates.getKey(k));
}
- // Create the key stream that will be referenced from
- // /DecodeParms. We have to do this now since you can't modify
- // or create objects during write.
+ // Create the key stream that will be referenced from /DecodeParms. We have to do this now
+ // since you can't modify or create objects during write.
char p[1] = {static_cast<char>(this->keys[og])};
std::string p_str(p, 1);
QPDFObjectHandle dp_stream = this->pdf->newStream(p_str);
- // Create /DecodeParms as expected by our fictitious
- // /XORDecode filter.
+ // Create /DecodeParms as expected by our fictitious /XORDecode filter.
QPDFObjectHandle decode_parms =
QPDFObjectHandle::newDictionary({{"/KeyStream", dp_stream}});
stream.replaceStreamData(self, QPDFObjectHandle::newName("/XORDecode"), decode_parms);
- // Further, if /ProtectXOR = true, we disable filtering on write
- // so that QPDFWriter will not decode the stream even though we
- // have registered a stream filter for /XORDecode.
+ // Further, if /ProtectXOR = true, we disable filtering on write so that QPDFWriter will not
+ // decode the stream even though we have registered a stream filter for /XORDecode.
auto protect = dict.getKey("/ProtectXOR");
if (protect.isBool() && protect.getBoolValue()) {
stream.setFilterOnWrite(false);
@@ -378,14 +328,12 @@ void
StreamReplacer::provideStreamData(QPDFObjGen const& og, Pipeline* pipeline)
{
QPDFObjectHandle orig = this->copied_streams[og];
- // call maybeReplace again, this time with the pipeline and no
- // dict_updates. In this mode, maybeReplace doesn't make any
- // changes. We have to hand it the original stream data, which we
+ // call maybeReplace again, this time with the pipeline and no dict_updates. In this mode,
+ // maybeReplace doesn't make any changes. We have to hand it the original stream data, which we
// get from copied_streams.
if (!maybeReplace(og, orig, pipeline, nullptr)) {
- // Since this only gets called for streams we already
- // determined we are replacing, a false return would indicate
- // a logic error.
+ // Since this only gets called for streams we already determined we are replacing, a false
+ // return would indicate a logic error.
throw std::logic_error("should_replace return false in provideStreamData");
}
}
@@ -396,17 +344,15 @@ process(char const* infilename, char const* outfilename, bool decode_specialized
QPDF qpdf;
qpdf.processFile(infilename);
- // Create a single StreamReplacer instance. The interface requires
- // a std::shared_ptr in various places, so allocate a StreamReplacer
- // and stash it in a std::shared_ptr.
+ // Create a single StreamReplacer instance. The interface requires a std::shared_ptr in various
+ // places, so allocate a StreamReplacer and stash it in a std::shared_ptr.
auto* replacer = new StreamReplacer(&qpdf);
std::shared_ptr<QPDFObjectHandle::StreamDataProvider> p(replacer);
for (auto& o: qpdf.getAllObjects()) {
if (o.isStream()) {
- // Call registerStream for every stream. Only ones that
- // registerStream decides to replace will actually be
- // replaced.
+ // Call registerStream for every stream. Only ones that registerStream decides to
+ // replace will actually be replaced.
replacer->registerStream(o, p);
}
}
@@ -454,9 +400,8 @@ main(int argc, char* argv[])
}
try {
- // Register our fictitious filter. This enables QPDFWriter to
- // decode our streams. This is not a real filter, so no real
- // PDF reading application would be able to interpret it. This
+ // Register our fictitious filter. This enables QPDFWriter to decode our streams. This is
+ // not a real filter, so no real PDF reading application would be able to interpret it. This
// is just for illustrative purposes.
QPDF::registerStreamFilter("/XORDecode", [] { return std::make_shared<SF_XORDecode>(); });
// Do the actual processing.
diff --git a/examples/pdf-double-page-size.cc b/examples/pdf-double-page-size.cc
index 6e1b4f8b..289c4d17 100644
--- a/examples/pdf-double-page-size.cc
+++ b/examples/pdf-double-page-size.cc
@@ -14,18 +14,16 @@ void
usage()
{
std::cerr << "Usage: " << whoami << " infile.pdf outfile.pdf [in-password]" << std::endl
- << "Double size of all pages in infile.pdf;"
- << " write output to outfile.pdf" << std::endl;
+ << "Double size of all pages in infile.pdf; write output to outfile.pdf" << std::endl;
exit(2);
}
-// If there is a box of name box_name, replace it with a new box whose
-// elements are double the values of the original box.
+// If there is a box of name box_name, replace it with a new box whose elements are double the
+// values of the original box.
static void
doubleBoxSize(QPDFPageObjectHelper& page, char const* box_name)
{
- // We need to use getAttribute rather than getKey as some boxes could
- // be inherited.
+ // We need to use getAttribute rather than getKey as some boxes could be inherited.
auto box = page.getAttribute(box_name, true);
if (box.isNull()) {
return;
diff --git a/examples/pdf-filter-tokens.cc b/examples/pdf-filter-tokens.cc
index 68d6e149..4a06bcd2 100644
--- a/examples/pdf-filter-tokens.cc
+++ b/examples/pdf-filter-tokens.cc
@@ -1,7 +1,6 @@
//
-// This example illustrates the use of QPDFObjectHandle::TokenFilter
-// with addContentTokenFilter. Please see comments inline for details.
-// See also pdf-count-strings.cc for a use of
+// This example illustrates the use of QPDFObjectHandle::TokenFilter with addContentTokenFilter.
+// Please see comments inline for details. See also pdf-count-strings.cc for a use of
// QPDFObjectHandle::TokenFilter with filterContents.
//
@@ -26,9 +25,8 @@ usage()
exit(2);
}
-// The StringReverser class is a trivial example of using a token
-// filter. This class only overrides the pure virtual handleToken
-// function and preserves the default handleEOF function.
+// The StringReverser class is a trivial example of using a token filter. This class only overrides
+// the pure virtual handleToken function and preserves the default handleEOF function.
class StringReverser: public QPDFObjectHandle::TokenFilter
{
public:
@@ -39,15 +37,12 @@ class StringReverser: public QPDFObjectHandle::TokenFilter
void
StringReverser::handleToken(QPDFTokenizer::Token const& token)
{
- // For string tokens, reverse the characters. For other tokens,
- // just pass them through. Notice that we construct a new string
- // token and write that, thus allowing the library to handle any
- // subtleties about properly encoding unprintable characters. This
- // function doesn't handle multibyte characters at all. It's not
- // intended to be an example of the correct way to reverse
- // strings. It's just intended to give a simple example of a
- // pretty minimal filter and to show an example of writing a
- // constructed token.
+ // For string tokens, reverse the characters. For other tokens, just pass them through. Notice
+ // that we construct a new string token and write that, thus allowing the library to handle any
+ // subtleties about properly encoding unprintable characters. This function doesn't handle
+ // multibyte characters at all. It's not intended to be an example of the correct way to reverse
+ // strings. It's just intended to give a simple example of a pretty minimal filter and to show
+ // an example of writing a constructed token.
if (token.getType() == QPDFTokenizer::tt_string) {
std::string value = token.getValue();
std::reverse(value.begin(), value.end());
@@ -57,9 +52,8 @@ StringReverser::handleToken(QPDFTokenizer::Token const& token)
}
}
-// The ColorToGray filter finds all "rg" operators in the content
-// stream and replaces them with "g" operators, thus mapping color to
-// grayscale. Note that it only applies to content streams, not
+// The ColorToGray filter finds all "rg" operators in the content stream and replaces them with "g"
+// operators, thus mapping color to grayscale. Note that it only applies to content streams, not
// images, so this will not replace color images with grayscale
// images.
class ColorToGray: public QPDFObjectHandle::TokenFilter
@@ -99,29 +93,23 @@ ColorToGray::numericValue(QPDFTokenizer::Token const& token)
void
ColorToGray::handleToken(QPDFTokenizer::Token const& token)
{
- // Track the number of non-ignorable tokens we've seen. If we see
- // an "rg" following three numbers, convert it to a grayscale
- // value. Keep writing tokens to the output as we can.
-
- // There are several things to notice here. We keep two stacks:
- // one of "meaningful" tokens, and one of all tokens. This way we
- // can preserve whitespace or comments that we encounter in the
- // stream and there preserve layout. As we receive tokens, we keep
- // the last four meaningful tokens. If we see three numbers
- // followed by rg, we use the three numbers to calculate a gray
- // value that is perceptually similar to the color value and then
- // write the "g" operator to the output, discarding any spaces or
- // comments encountered embedded in the "rg" operator.
-
- // The stack and all_stack members are updated in such a way that
- // they always contain exactly the same non-ignorable tokens. The
- // stack member contains the tokens that would be left if you
+ // Track the number of non-ignorable tokens we've seen. If we see an "rg" following three
+ // numbers, convert it to a grayscale value. Keep writing tokens to the output as we can.
+
+ // There are several things to notice here. We keep two stacks: one of "meaningful" tokens, and
+ // one of all tokens. This way we can preserve whitespace or comments that we encounter in the
+ // stream and there preserve layout. As we receive tokens, we keep the last four meaningful
+ // tokens. If we see three numbers followed by rg, we use the three numbers to calculate a gray
+ // value that is perceptually similar to the color value and then write the "g" operator to the
+ // output, discarding any spaces or comments encountered embedded in the "rg" operator.
+
+ // The stack and all_stack members are updated in such a way that they always contain exactly
+ // the same non-ignorable tokens. The stack member contains the tokens that would be left if you
// removed all space and comment tokens from all_stack.
- // On each new token, flush out any space or comment tokens. Store
- // the incoming token. If we just got an rg preceded by the right
- // kinds of operands, replace the command. Flush any additional
- // accumulated tokens to keep the stack only four tokens deep.
+ // On each new token, flush out any space or comment tokens. Store the incoming token. If we
+ // just got an rg preceded by the right kinds of operands, replace the command. Flush any
+ // additional accumulated tokens to keep the stack only four tokens deep.
while ((!this->all_stack.empty()) && isIgnorable(this->all_stack.at(0).getType())) {
writeToken(this->all_stack.at(0));
@@ -182,11 +170,9 @@ main(int argc, char* argv[])
QPDF pdf;
pdf.processFile(infilename);
for (auto& page: QPDFPageDocumentHelper(pdf).getAllPages()) {
- // Attach two token filters to each page of this file.
- // When the file is written, or when the pages' contents
- // are retrieved in any other way, the filters will be
- // applied. See comments on the filters for additional
- // details.
+ // Attach two token filters to each page of this file. When the file is written, or when
+ // the pages' contents are retrieved in any other way, the filters will be applied. See
+ // comments on the filters for additional details.
page.addContentTokenFilter(
std::shared_ptr<QPDFObjectHandle::TokenFilter>(new StringReverser));
page.addContentTokenFilter(
diff --git a/examples/pdf-invert-images.cc b/examples/pdf-invert-images.cc
index 5692e7b2..0ef2169e 100644
--- a/examples/pdf-invert-images.cc
+++ b/examples/pdf-invert-images.cc
@@ -20,15 +20,12 @@ usage()
exit(2);
}
-// Derive a class from StreamDataProvider to provide updated stream
-// data. The main purpose of using this object is to avoid having to
-// allocate memory up front for the objects. We want to replace the
-// stream data with a function of the original stream data. In order
-// to do this without actually holding all the images in memory, we
-// create copies of the streams. Copying the streams doesn't actually
-// copy the data. Internally, the qpdf library is holding onto the
-// location of the original stream data, which makes it possible for
-// the StreamDataProvider to access it when it needs it.
+// Derive a class from StreamDataProvider to provide updated stream data. The main purpose of using
+// this object is to avoid having to allocate memory up front for the objects. We want to replace
+// the stream data with a function of the original stream data. In order to do this without actually
+// holding all the images in memory, we create copies of the streams. Copying the streams doesn't
+// actually copy the data. Internally, the qpdf library is holding onto the location of the original
+// stream data, which makes it possible for the StreamDataProvider to access it when it needs it.
class ImageInverter: public QPDFObjectHandle::StreamDataProvider
{
public:
@@ -46,42 +43,35 @@ void
ImageInverter::registerImage(
QPDFObjectHandle image, std::shared_ptr<QPDFObjectHandle::StreamDataProvider> self)
{
- // replaceStreamData requires a pointer holder to the stream data
- // provider, but there's no way for us to generate one ourselves,
- // so we have to have it handed to us. Don't be tempted to have
- // the class contain a std::shared_ptr to itself as a member. Doing
- // this will prevent the class from ever being deleted since the
- // reference count will never drop to zero (and std::shared_ptr
- // doesn't have weak references).
+ // replaceStreamData requires a pointer holder to the stream data provider, but there's no way
+ // for us to generate one ourselves, so we have to have it handed to us. Don't be tempted to
+ // have the class contain a std::shared_ptr to itself as a member. Doing this will prevent the
+ // class from ever being deleted since the reference count will never drop to zero (and
+ // std::shared_ptr doesn't have weak references).
QPDFObjGen og(image.getObjGen());
- // Store information about the images based on the object and
- // generation number. Recall that a single image object may be
- // used more than once, so no need to update the same stream
- // multiple times.
+ // Store information about the images based on the object and generation number. Recall that a
+ // single image object may be used more than once, so no need to update the same stream multiple
+ // times.
if (this->copied_images.count(og) > 0) {
return;
}
this->copied_images[og] = image.copyStream();
- // Register our stream data provider for this stream. Future calls
- // to getStreamData or pipeStreamData will use the new
- // information. Provide null for both filter and decode
- // parameters. Note that this does not mean the image data will be
- // uncompressed when we write the file. By default, QPDFWriter
- // will use /FlateDecode for anything that is uncompressed or
- // filterable in the input QPDF object, so we don't have to deal
- // with it explicitly here. We could explicitly use /DCTDecode and
- // write through a DCT filter if we wanted.
+ // Register our stream data provider for this stream. Future calls to getStreamData or
+ // pipeStreamData will use the new information. Provide null for both filter and decode
+ // parameters. Note that this does not mean the image data will be uncompressed when we write
+ // the file. By default, QPDFWriter will use /FlateDecode for anything that is uncompressed or
+ // filterable in the input QPDF object, so we don't have to deal with it explicitly here. We
+ // could explicitly use /DCTDecode and write through a DCT filter if we wanted.
image.replaceStreamData(self, QPDFObjectHandle::newNull(), QPDFObjectHandle::newNull());
}
void
ImageInverter::provideStreamData(QPDFObjGen const& og, Pipeline* pipeline)
{
- // Use the object and generation number supplied to look up the
- // image data. Then invert the image data and write the inverted
- // data to the pipeline.
+ // Use the object and generation number supplied to look up the image data. Then invert the
+ // image data and write the inverted data to the pipeline.
std::shared_ptr<Buffer> data = this->copied_images[og].getStreamData(qpdf_dl_all);
size_t size = data->getSize();
unsigned char* buf = data->getBuffer();
@@ -130,11 +120,9 @@ main(int argc, char* argv[])
QPDFObjectHandle color_space = image_dict.getKey("/ColorSpace");
QPDFObjectHandle bits_per_component = image_dict.getKey("/BitsPerComponent");
- // For our example, we can only work with images 8-bit
- // grayscale images that we can fully decode. Use
- // pipeStreamData with a null pipeline to determine
- // whether the image is filterable. Directly inspect
- // keys to determine the image type.
+ // For our example, we can only work with images 8-bit grayscale images that we can
+ // fully decode. Use pipeStreamData with a null pipeline to determine whether the
+ // image is filterable. Directly inspect keys to determine the image type.
if (image.pipeStreamData(nullptr, qpdf_ef_compress, qpdf_dl_all) &&
color_space.isNameAndEquals("/DeviceGray") && bits_per_component.isInteger() &&
(bits_per_component.getIntValue() == 8)) {
@@ -146,8 +134,7 @@ main(int argc, char* argv[])
// Write out a new file
QPDFWriter w(qpdf, outfilename);
if (static_id) {
- // For the test suite, uncompress streams and use static
- // IDs.
+ // For the test suite, uncompress streams and use static IDs.
w.setStaticID(true); // for testing only
}
w.write();
diff --git a/examples/pdf-linearize.c b/examples/pdf-linearize.c
index 3a7a335d..20461593 100644
--- a/examples/pdf-linearize.c
+++ b/examples/pdf-linearize.c
@@ -51,8 +51,7 @@ main(int argc, char* argv[])
if (((qpdf_read(qpdf, infile, password) & QPDF_ERRORS) == 0) &&
((qpdf_init_write(qpdf, outfile) & QPDF_ERRORS) == 0)) {
- /* Use static ID for testing only. For production, a
- * non-static ID is used. See also
+ /* Use static ID for testing only. For production, a non-static ID is used. See also
* qpdf_set_deterministic_ID. */
qpdf_set_static_ID(qpdf, QPDF_TRUE); /* for testing only */
qpdf_set_linearization(qpdf, QPDF_TRUE);
diff --git a/examples/pdf-name-number-tree.cc b/examples/pdf-name-number-tree.cc
index a14ad126..31eaf932 100644
--- a/examples/pdf-name-number-tree.cc
+++ b/examples/pdf-name-number-tree.cc
@@ -29,24 +29,19 @@ main(int argc, char* argv[])
QPDF qpdf;
qpdf.emptyPDF();
- // This example doesn't do anything particularly useful other than
- // just illustrate how to use the APIs for name and number trees.
- // It also demonstrates use of the iterators for dictionaries and
- // arrays introduced at the same time with qpdf 10.2.
-
- // To use this example, compile it and run it. Study the output
- // and compare it to what you expect. When done, look at the
- // generated output file in a text editor to inspect the structure
- // of the trees as left in the file.
-
- // We're just going to create some name and number trees, hang
- // them off the document catalog (root), and write an empty PDF to
- // a file. The PDF will have no pages and won't be viewable, but
- // you can look at it in a text editor to see the resulting
- // structure of the PDF.
-
- // Create a dictionary off the root where we will hang our name
- // and number tree.
+ // This example doesn't do anything particularly useful other than just illustrate how to use
+ // the APIs for name and number trees. It also demonstrates use of the iterators for
+ // dictionaries and arrays introduced at the same time with qpdf 10.2.
+
+ // To use this example, compile it and run it. Study the output and compare it to what you
+ // expect. When done, look at the generated output file in a text editor to inspect the
+ // structure of the trees as left in the file.
+
+ // We're just going to create some name and number trees, hang them off the document catalog
+ // (root), and write an empty PDF to a file. The PDF will have no pages and won't be viewable,
+ // but you can look at it in a text editor to see the resulting structure of the PDF.
+
+ // Create a dictionary off the root where we will hang our name and number tree.
auto root = qpdf.getRoot();
auto example = QPDFObjectHandle::newDictionary();
root.replaceKey("/Example", example);
@@ -75,8 +70,8 @@ main(int argc, char* argv[])
std::cout << " " << i.first << " -> " << i.second.unparse() << std::endl;
}
- // This is a small tree, so everything will be at the root. We can
- // look at it using dictionary and array iterators.
+ // This is a small tree, so everything will be at the root. We can look at it using dictionary
+ // and array iterators.
std::cout << "Keys in name tree object:" << std::endl;
QPDFObjectHandle names;
for (auto const& i: name_tree_oh.ditems()) {
@@ -121,15 +116,12 @@ main(int argc, char* argv[])
<< std::endl;
std::cout << "Has K?: " << name_tree.hasName("K") << std::endl;
- // Illustrate some more advanced usage using number trees. These
- // calls work for name trees too.
+ // Illustrate some more advanced usage using number trees. These calls work for name trees too.
- // The safe way to populate a tree is to call insert repeatedly as
- // above, but if you know you are definitely inserting items in
- // order, it is more efficient to insert them using insertAfter,
- // which avoids doing a binary search through the tree for each
- // insertion. Note that if you don't insert items in order using
- // this method, you will create an invalid tree.
+ // The safe way to populate a tree is to call insert repeatedly as above, but if you know you
+ // are definitely inserting items in order, it is more efficient to insert them using
+ // insertAfter, which avoids doing a binary search through the tree for each insertion. Note
+ // that if you don't insert items in order using this method, you will create an invalid tree.
auto number_tree = QPDFNumberTreeObjectHelper::newEmpty(qpdf);
auto number_tree_oh = number_tree.getObjectHandle();
example.replaceKey("/NumberTree", number_tree_oh);
@@ -149,9 +141,8 @@ main(int argc, char* argv[])
++n;
}
- // When you remove an item with an iterator, the iterator
- // advances. This makes it possible to filter while iterating.
- // Remove all items that are multiples of 5.
+ // When you remove an item with an iterator, the iterator advances. This makes it possible to
+ // filter while iterating. Remove all items that are multiples of 5.
iter2 = number_tree.begin();
while (iter2 != number_tree.end()) {
if (iter2->first % 5 == 0) {
diff --git a/examples/pdf-overlay-page.cc b/examples/pdf-overlay-page.cc
index 6d1cd0b0..75577094 100644
--- a/examples/pdf-overlay-page.cc
+++ b/examples/pdf-overlay-page.cc
@@ -6,10 +6,9 @@
#include <cstdlib>
#include <iostream>
-// 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.
+// 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 = nullptr;
@@ -44,24 +43,21 @@ stamp_page(char const* infile, char const* stampfile, char const* outfile)
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.
+ // Generate content to place the form XObject centered within destination page's trim box.
QPDFMatrix m;
std::string content =
ph.placeFormXObject(stamp_fo, name, ph.getTrimBox().getArrayAsRectangle(), m);
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.
+ // 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("<< /XObject << >> >>"_qpdf);
resources.getKey("/XObject").replaceKey(name, stamp_fo);
ph.addPageContents(inpdf.newStream("q\n"), true);
ph.addPageContents(inpdf.newStream("\nQ\n" + content), false);
}
- // Copy the annotations and form fields from the original page
- // to the new page. For more efficiency when copying multiple
- // pages, we can create a QPDFAcroFormDocumentHelper and pass
- // it in. See comments in QPDFPageObjectHelper.hh for details.
+ // Copy the annotations and form fields from the original page to the new page. For more
+ // efficiency when copying multiple pages, we can create a QPDFAcroFormDocumentHelper and
+ // pass it in. See comments in QPDFPageObjectHelper.hh for details.
ph.copyAnnotations(stamp_page_1, m);
}
diff --git a/examples/pdf-parse-content.cc b/examples/pdf-parse-content.cc
index 743986a1..b60693f0 100644
--- a/examples/pdf-parse-content.cc
+++ b/examples/pdf-parse-content.cc
@@ -13,8 +13,8 @@ void
usage()
{
std::cerr << "Usage: " << whoami << " filename page-number" << std::endl
- << "Prints a dump of the objects in the content streams"
- << " of the given page." << std::endl
+ << "Prints a dump of the objects in the content streams of the given page."
+ << std::endl
<< "Pages are numbered from 1." << std::endl;
exit(2);
}
diff --git a/examples/pdf-set-form-values.cc b/examples/pdf-set-form-values.cc
index c2793142..a1a19db1 100644
--- a/examples/pdf-set-form-values.cc
+++ b/examples/pdf-set-form-values.cc
@@ -29,41 +29,33 @@ main(int argc, char* argv[])
char const* outfilename = argv[2];
char const* value = argv[3];
- // This is a contrived example that just goes through a file page
- // by page and sets the value of any text fields it finds to a
- // fixed value as given on the command line. The purpose here is
- // to illustrate use of the helper classes around interactive
- // forms.
+ // This is a contrived example that just goes through a file page by page and sets the value of
+ // any text fields it finds to a fixed value as given on the command line. The purpose here is
+ // to illustrate use of the helper classes around interactive forms.
try {
QPDF qpdf;
qpdf.processFile(infilename);
- // We will iterate through form fields by starting at the page
- // level and looking at each field for each page. We could
- // also called QPDFAcroFormDocumentHelper::getFormFields to
- // iterate at the field level, but doing it as below
- // illustrates how we can map from annotations to fields.
+ // We will iterate through form fields by starting at the page level and looking at each
+ // field for each page. We could also called QPDFAcroFormDocumentHelper::getFormFields to
+ // iterate at the field level, but doing it as below illustrates how we can map from
+ // annotations to fields.
QPDFAcroFormDocumentHelper afdh(qpdf);
for (auto const& page: QPDFPageDocumentHelper(qpdf).getAllPages()) {
- // Get all widget annotations for each page. Widget
- // annotations are the ones that contain the details of
- // what's in a form field.
+ // Get all widget annotations for each page. Widget annotations are the ones that
+ // contain the details of what's in a form field.
for (auto& annot: afdh.getWidgetAnnotationsForPage(page)) {
- // For each annotation, find its associated field. If
- // it's a text field, set its value.
+ // For each annotation, find its associated field. If it's a text field, set its
+ // value.
QPDFFormFieldObjectHelper ffh = afdh.getFieldForAnnotation(annot);
if (ffh.getFieldType() == "/Tx") {
- // Set the value. Passing false as the second
- // value prevents qpdf from setting
- // /NeedAppearances to true (but will not turn it
- // off if it's already on), so we call
- // generateAppearance after setting the value. You
- // may or may not want to do this depending on
- // whether the appearance streams generated by
- // qpdf are good enough for your purposes. For
- // additional details, please see comments in
+ // Set the value. Passing false as the second value prevents qpdf from setting
+ // /NeedAppearances to true (but will not turn it off if it's already on), so we
+ // call generateAppearance after setting the value. You may or may not want to
+ // do this depending on whether the appearance streams generated by qpdf are
+ // good enough for your purposes. For additional details, please see comments in
// QPDFFormFieldObjectHelper.hh for this method.
ffh.setV(value, false);
ffh.generateAppearance(annot);
diff --git a/examples/pdf-split-pages.cc b/examples/pdf-split-pages.cc
index 9890ccf4..fde4bc1b 100644
--- a/examples/pdf-split-pages.cc
+++ b/examples/pdf-split-pages.cc
@@ -1,7 +1,6 @@
//
-// This is a stand-alone example of splitting a PDF into individual
-// pages. It does essentially the same thing that qpdf --split-pages
-// does.
+// This is a stand-alone example of splitting a PDF into individual pages. It does essentially the
+// same thing that qpdf --split-pages does.
//
#include <qpdf/QIntC.hh>
@@ -32,8 +31,7 @@ process(char const* whoami, char const* infile, std::string outprefix)
QPDFPageDocumentHelper(outpdf).addPage(page, false);
QPDFWriter outpdfw(outpdf, outfile.c_str());
if (static_id) {
- // For the test suite, uncompress streams and use static
- // IDs.
+ // For the test suite, uncompress streams and use static IDs.
outpdfw.setStaticID(true); // for testing only
outpdfw.setStreamDataMode(qpdf_s_uncompress);
}
diff --git a/examples/qpdf-job.cc b/examples/qpdf-job.cc
index c7131f77..be868a17 100644
--- a/examples/qpdf-job.cc
+++ b/examples/qpdf-job.cc
@@ -3,8 +3,7 @@
#include <iostream>
-// This program is a simple demonstration of different ways to use the
-// QPDFJob API.
+// This program is a simple demonstration of different ways to use the QPDFJob API.
static char const* whoami = nullptr;
@@ -28,10 +27,9 @@ main(int argc, char* argv[])
usage();
}
- // The examples below all catch std::exception. Note that
- // QPDFUsage can be caught separately to report on errors in using
- // the API itself. For CLI, this is command-line usage. For JSON
- // or the API, it would be errors from the equivalent invocation.
+ // The examples below all catch std::exception. Note that QPDFUsage can be caught separately to
+ // report on errors in using the API itself. For CLI, this is command-line usage. For JSON or
+ // the API, it would be errors from the equivalent invocation.
// Note that staticId is used for testing only.
diff --git a/examples/qpdfjob-c-save-attachment.c b/examples/qpdfjob-c-save-attachment.c
index c461f974..30e48127 100644
--- a/examples/qpdfjob-c-save-attachment.c
+++ b/examples/qpdfjob-c-save-attachment.c
@@ -6,10 +6,9 @@
#include <stdlib.h>
#include <string.h>
-// This example demonstrates how we can redirect where saved output
-// goes by calling the default logger's setSave method before running
-// something with QPDFJob. See qpdfjob-c-save-attachment.c for an
-// implementation that uses the C API.
+// This example demonstrates how we can redirect where saved output goes by calling the default
+// logger's setSave method before running something with QPDFJob. See qpdfjob-c-save-attachment.c
+// for an implementation that uses the C API.
static int
save_to_file(char const* data, size_t len, void* udata)
@@ -79,9 +78,8 @@ main(int argc, char* argv[])
};
outfile = do_fopen(outfilename);
- /* Use qpdflogger_set_save with a callback function to redirect
- * saved data. You can use other qpdf logger functions to capture
- * informational output, warnings, and errors.
+ /* Use qpdflogger_set_save with a callback function to redirect saved data. You can use other
+ * qpdf logger functions to capture informational output, warnings, and errors.
*/
qpdflogger_set_save(l, qpdf_log_dest_custom, save_to_file, (void*)outfile, 0);
qpdflogger_cleanup(&l);
diff --git a/examples/qpdfjob-c.c b/examples/qpdfjob-c.c
index 452e689b..62528392 100644
--- a/examples/qpdfjob-c.c
+++ b/examples/qpdfjob-c.c
@@ -1,7 +1,4 @@
-/*
- * This is an example program to linearize a PDF file using the C
- * QPDFJob API.
- */
+/* This is an example program to linearize a PDF file using the C QPDFJob API. */
#include <qpdf/qpdfjob-c.h>
#include <stdio.h>
@@ -48,14 +45,12 @@ main(int argc, char* argv[])
new_argv[4] = "--static-id"; /* for testing only */
new_argv[5] = NULL;
- /* See qpdf-job.cc for a C++ example of using the json interface.
- * To use that from C just like the argv one, call
- * qpdfjob_run_from_json instead and pass the json string as a
- * single char const* argument.
+ /* See qpdf-job.cc for a C++ example of using the json interface. To use that from C just like
+ * the argv one, call qpdfjob_run_from_json instead and pass the json string as a single char
+ * const* argument.
*
- * See qpdfjob-c-save-attachment.c for an example of using the
- * full form of the qpdfjob interface with init and cleanup
- * functions.
+ * See qpdfjob-c-save-attachment.c for an example of using the full form of the qpdfjob
+ * interface with init and cleanup functions.
*/
r = qpdfjob_run_from_argv(new_argv);
return r;
diff --git a/examples/qpdfjob-remove-annotations.cc b/examples/qpdfjob-remove-annotations.cc
index b0afa2da..bc043d33 100644
--- a/examples/qpdfjob-remove-annotations.cc
+++ b/examples/qpdfjob-remove-annotations.cc
@@ -6,10 +6,9 @@
#include <cstdlib>
#include <iostream>
-// This example demonstrates how we can use the QPDFJob createQPDF and writeQPDF
-// methods to add custom transformations to the output produced by QPDFJob runs.
-// The example is a full copy of the qpdf program modified to allways remove all
-// annotations from the final output.
+// This example demonstrates how we can use the QPDFJob createQPDF and writeQPDF methods to add
+// custom transformations to the output produced by QPDFJob runs. The example is a full copy of the
+// qpdf program modified to allways remove all annotations from the final output.
static char const* whoami = nullptr;
diff --git a/examples/qpdfjob-save-attachment.cc b/examples/qpdfjob-save-attachment.cc
index 045e38bf..790d808f 100644
--- a/examples/qpdfjob-save-attachment.cc
+++ b/examples/qpdfjob-save-attachment.cc
@@ -3,10 +3,9 @@
#include <qpdf/QPDFLogger.hh>
#include <qpdf/QUtil.hh>
-// This example demonstrates how we can redirect where saved output
-// goes by calling the default logger's setSave method before running
-// something with QPDFJob. See qpdfjob-c-save-attachment.c for an
-// implementation that uses the C API.
+// This example demonstrates how we can redirect where saved output goes by calling the default
+// logger's setSave method before running something with QPDFJob. See qpdfjob-c-save-attachment.c
+// for an implementation that uses the C API.
int
main(int argc, char* argv[])