Convert pages to form XObjects

Support conversion of pages to form XObjects and placement of form
XObjects on pages.
This commit is contained in:
Jay Berkenbilt 2019-01-26 16:48:48 -05:00
parent 68ccd87c9e
commit 623f5b664e
14 changed files with 14164 additions and 0 deletions

View File

@ -1,3 +1,10 @@
2019-01-26 Jay Berkenbilt <ejb@ql.org>
* Add new methods QPDFPageObjectHelper::getFormXObjectForPage,
which creates a form XObject equivalent to a page, and
QPDFObjectHandle::placeFormXObject, which generates content stream
code to placing a form XObject on a page.
2019-01-25 Jay Berkenbilt <ejb@ql.org>
* Add new method QPDFObjectHandle::getUniqueResourceName() to

View File

@ -51,6 +51,21 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
QPDFObjectHandle
getAttribute(std::string const& name, bool copy_if_shared);
// Return the TrimBox. If not defined, fall back to CropBox
QPDF_DLL
QPDFObjectHandle
getTrimBox(bool copy_if_shared = false);
// Return the CropBox. If not defined, fall back to MediaBox
QPDF_DLL
QPDFObjectHandle
getCropBox(bool copy_if_shared = false);
// Return the MediaBox
QPDF_DLL
QPDFObjectHandle
getMediaBox(bool copy_if_shared = false);
// Returns an empty map if there are no images or no resources.
// Prior to qpdf 8.4.0, this function did not support inherited
// resources, but it does now. Return value is a map from XObject
@ -162,6 +177,54 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
QPDF_DLL
QPDFPageObjectHelper shallowCopyPage();
// Return a transformation matrix whose effect is the same as the
// page's /Rotate and /UserUnit parameters. If invert is true,
// return a matrix whose effect is the opposite. The regular
// matrix is suitable for taking something from this page to put
// elsewhere, and the second one is suitable for putting something
// else onto this page. The page's TrimBox is used as the bounding
// box for purposes of computing the matrix.
QPDF_DLL
QPDFObjectHandle::Matrix getMatrixForTransformations(bool invert = false);
// Return a form XObject that draws this page. This is useful for
// n-up operations, underlay, overlay, thumbnail generation, or
// any other case in which it is useful to replicate the contents
// of a page in some other context. The dictionaries are shallow
// copies of the original page dictionary, and the contents are
// coalesced from the page's contents. The resulting object handle
// is not referenced anywhere. If handle_transformations is true,
// the resulting form XObject's /Matrix will be set to replicate
// rotation (/Rotate) and scaling (/UserUnit) in the page's
// dictionary. In this way, the page's transformations will be
// preserved when placing this object on another page.
QPDF_DLL
QPDFObjectHandle getFormXObjectForPage(bool handle_transformations = true);
// Return content stream text that will place the given form
// XObject (fo) using the resource name "name" on this page
// centered within the given rectangle and shrunk to fit if
// necessary. If invert_transformations is true, the effect of any
// rotation (/Rotate) and scaling (/UserUnit) applied to the
// current page will be inverted in the form XObject placement.
// This will cause the form XObject's absolute orientation to be
// preserved. You could overlay one page on another by calling
// getFormXObjectForPage on the original page,
// QPDFObjectHandle::getUniqueResourceName on the destination
// page's Resources dictionary to generate a name for the
// resulting object, and calling placeFormXObject on the
// destination page. Then insert the new fo (or, if it comes from
// a different file, the result of calling copyForeignObject on
// it) into the resources dictionary using name, and append or
// prepend the content to the page's content streams. See the
// overlay/underlay code in qpdf.cc or
// examples/pdf-overlay-page.cc for an example.
QPDF_DLL
std::string placeFormXObject(
QPDFObjectHandle fo, std::string name,
QPDFObjectHandle::Rectangle rect,
bool invert_transformations = true);
private:
class Members
{

View File

@ -1,6 +1,40 @@
#include <qpdf/QPDFPageObjectHelper.hh>
#include <qpdf/QTC.hh>
#include <qpdf/QPDF.hh>
#include <qpdf/Pl_Concatenate.hh>
#include <qpdf/QUtil.hh>
#include <qpdf/QPDFExc.hh>
#include <qpdf/QPDFMatrix.hh>
class ContentProvider: public QPDFObjectHandle::StreamDataProvider
{
public:
ContentProvider(QPDFObjectHandle from_page) :
from_page(from_page)
{
}
virtual ~ContentProvider()
{
}
virtual void provideStreamData(int objid, int generation,
Pipeline* pipeline);
private:
QPDFObjectHandle from_page;
};
void
ContentProvider::provideStreamData(int, int, Pipeline* p)
{
Pl_Concatenate concat("concatenate", p);
std::string description = "contents from page object " +
QUtil::int_to_string(from_page.getObjectID()) + " " +
QUtil::int_to_string(from_page.getGeneration());
std::string all_description;
from_page.getKey("/Contents").pipeContentStreams(
&concat, description, all_description);
concat.manualFinish();
}
QPDFPageObjectHelper::Members::~Members()
{
@ -50,6 +84,34 @@ QPDFPageObjectHelper::getAttribute(std::string const& name,
return result;
}
QPDFObjectHandle
QPDFPageObjectHelper::getTrimBox(bool copy_if_shared)
{
QPDFObjectHandle result = getAttribute("/TrimBox", copy_if_shared);
if (result.isNull())
{
result = getCropBox(copy_if_shared);
}
return result;
}
QPDFObjectHandle
QPDFPageObjectHelper::getCropBox(bool copy_if_shared)
{
QPDFObjectHandle result = getAttribute("/CropBox", copy_if_shared);
if (result.isNull())
{
result = getMediaBox();
}
return result;
}
QPDFObjectHandle
QPDFPageObjectHelper::getMediaBox(bool copy_if_shared)
{
return getAttribute("/MediaBox", copy_if_shared);
}
std::map<std::string, QPDFObjectHandle>
QPDFPageObjectHelper::getPageImages()
@ -231,3 +293,211 @@ QPDFPageObjectHelper::shallowCopyPage()
QPDFObjectHandle new_page = this->oh.shallowCopy();
return QPDFPageObjectHelper(qpdf->makeIndirectObject(new_page));
}
QPDFObjectHandle::Matrix
QPDFPageObjectHelper::getMatrixForTransformations(bool invert)
{
QPDFObjectHandle::Matrix matrix(1, 0, 0, 1, 0, 0);
QPDFObjectHandle bbox = getTrimBox(false);
if (! bbox.isRectangle())
{
return matrix;
}
QPDFObjectHandle rotate_obj = getAttribute("/Rotate", false);
QPDFObjectHandle scale_obj = getAttribute("/UserUnit", false);
if (! (rotate_obj.isNull() && scale_obj.isNull()))
{
QPDFObjectHandle::Rectangle rect = bbox.getArrayAsRectangle();
double width = rect.urx - rect.llx;
double height = rect.ury - rect.lly;
double scale = (scale_obj.isNumber()
? scale_obj.getNumericValue()
: 1.0);
int rotate = (rotate_obj.isInteger()
? rotate_obj.getIntValue()
: 0);
if (invert)
{
if (scale == 0.0)
{
return matrix;
}
scale = 1.0 / scale;
rotate = 360 - rotate;
}
// Ignore invalid rotation angle
switch (rotate)
{
case 90:
matrix = QPDFObjectHandle::Matrix(
0, -scale, scale, 0, 0, width * scale);
break;
case 180:
matrix = QPDFObjectHandle::Matrix(
-scale, 0, 0, -scale, width * scale, height * scale);
break;
case 270:
matrix = QPDFObjectHandle::Matrix(
0, scale, -scale, 0, height * scale, 0);
break;
default:
matrix = QPDFObjectHandle::Matrix(
scale, 0, 0, scale, 0, 0);
break;
}
}
return matrix;
}
QPDFObjectHandle
QPDFPageObjectHelper::getFormXObjectForPage(bool handle_transformations)
{
QPDF* qpdf = this->oh.getOwningQPDF();
if (! qpdf)
{
throw std::runtime_error(
"QPDFPageObjectHelper::getFormXObjectForPage"
" called with a direct objet");
}
QPDFObjectHandle result = QPDFObjectHandle::newStream(qpdf);
QPDFObjectHandle newdict = result.getDict();
newdict.replaceKey("/Type", QPDFObjectHandle::newName("/XObject"));
newdict.replaceKey("/Subtype", QPDFObjectHandle::newName("/Form"));
newdict.replaceKey("/Resources",
getAttribute("/Resources", false).shallowCopy());
newdict.replaceKey("/Group",
getAttribute("/Group", false).shallowCopy());
QPDFObjectHandle bbox = getTrimBox(false).shallowCopy();
if (! bbox.isRectangle())
{
this->oh.warnIfPossible(
"bounding box is invalid; form"
" XObject created from page will not work");
}
newdict.replaceKey("/BBox", bbox);
PointerHolder<QPDFObjectHandle::StreamDataProvider> provider =
new ContentProvider(this->oh);
result.replaceStreamData(
provider, QPDFObjectHandle::newNull(), QPDFObjectHandle::newNull());
QPDFObjectHandle rotate_obj = getAttribute("/Rotate", false);
QPDFObjectHandle scale_obj = getAttribute("/UserUnit", false);
if (handle_transformations &&
(! (rotate_obj.isNull() && scale_obj.isNull())))
{
newdict.replaceKey("/Matrix",
QPDFObjectHandle::newArray(
getMatrixForTransformations()));
}
return result;
}
std::string
QPDFPageObjectHelper::placeFormXObject(
QPDFObjectHandle fo, std::string name,
QPDFObjectHandle::Rectangle rect,
bool invert_transformations)
{
// Calculate the transformation matrix that will place the given
// form XObject fully inside the given rectangle, shrinking and
// centering if needed.
// When rendering a form XObject, the transformation in the
// graphics state (cm) is applied first (of course -- when it is
// applied, the PDF interpreter doesn't even know we're going to
// be drawing a form XObject yet), and then the object's matrix
// (M) is applied. The resulting matrix, when applied to the form
// XObject's bounding box, will generate a new rectangle. We want
// to create a transformation matrix that make the form XObject's
// bounding box land in exactly the right spot.
QPDFObjectHandle fdict = fo.getDict();
QPDFObjectHandle bbox_obj = fdict.getKey("/BBox");
if (! bbox_obj.isRectangle())
{
return "";
}
QPDFMatrix wmatrix; // work matrix
QPDFMatrix tmatrix; // "to" matrix
QPDFMatrix fmatrix; // "from" matrix
if (invert_transformations)
{
// tmatrix inverts scaling and rotation of the destination
// page. Applying this matrix allows the overlayed form
// XObject's to be absolute rather than relative to properties
// of the destination page. tmatrix is part of the computed
// transformation matrix.
tmatrix = QPDFMatrix(getMatrixForTransformations(true));
wmatrix.concat(tmatrix);
}
if (fdict.getKey("/Matrix").isMatrix())
{
// fmatrix is the transformation matrix that is applied to the
// form XObject itself. We need this for calculations, but we
// don't explicitly use it in the final result because the PDF
// rendering system automatically applies this last before
// drawing the form XObject.
fmatrix = QPDFMatrix(fdict.getKey("/Matrix").getArrayAsMatrix());
wmatrix.concat(fmatrix);
}
// The current wmatrix handles transformation from the form
// xobject and, if requested, the destination page. Next, we have
// to adjust this for scale and position.
// Step 1: figure out what scale factor we need to make the form
// XObject's bnounding box fit within the destination rectangle.
// Transform bounding box
QPDFObjectHandle::Rectangle bbox = bbox_obj.getArrayAsRectangle();
QPDFObjectHandle::Rectangle T = wmatrix.transformRectangle(bbox);
// Calculate a scale factor, if needed. If the transformed
// rectangle is too big, shrink it. Never expand it.
if ((T.urx == T.llx) || (T.ury == T.lly))
{
// avoid division by zero
return "";
}
double rect_w = rect.urx - rect.llx;
double rect_h = rect.ury - rect.lly;
double t_w = T.urx - T.llx;
double t_h = T.ury - T.lly;
double xscale = rect_w / t_w;
double yscale = rect_h / t_h;
double scale = (xscale < yscale ? xscale : yscale);
if (scale > 1.0)
{
scale = 1.0;
}
// Step 2: figure out what translation is required to get the
// rectangle to the right spot: centered within the destination.
wmatrix = QPDFMatrix();
wmatrix.scale(scale, scale);
wmatrix.concat(tmatrix);
wmatrix.concat(fmatrix);
T = wmatrix.transformRectangle(bbox);
double t_cx = (T.llx + T.urx) / 2.0;
double t_cy = (T.lly + T.ury) / 2.0;
double r_cx = (rect.llx + rect.urx) / 2.0;
double r_cy = (rect.lly + rect.ury) / 2.0;
double tx = r_cx - t_cx;
double ty = r_cy - t_cy;
// Now we can calculate the final matrix. The final matrix does
// not include fmatrix because that is applied automatically by
// the PDF interpreter.
QPDFMatrix cm;
cm.translate(tx, ty);
cm.scale(scale, scale);
cm.concat(tmatrix);
return (
"q\n" +
cm.unparse() + " cm\n" +
name + " Do\n" +
"Q\n");
}

View File

@ -0,0 +1,15 @@
#!/usr/bin/env perl
require 5.008;
use warnings;
use strict;
require TestDriver;
my $td = new TestDriver('matrix');
$td->runtest("matrix",
{$td->COMMAND => "matrix"},
{$td->STRING => "matrix tests done\n", $td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES);
$td->report(1);

View File

@ -320,6 +320,32 @@ foreach my $i (@choice_values)
{$td->FILE => "appearances-$i.pdf"});
}
show_ntests();
# ----------
$td->notify("--- Form XObject, underlay, overlay ---");
$n_tests += 10;
$td->runtest("form xobject creation",
{$td->COMMAND => "test_driver 55 fxo-red.pdf"},
{$td->STRING => "test 55 done\n", $td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES);
$td->runtest("compare files",
{$td->FILE => "a.pdf"},
{$td->FILE => "form-xobjects-out.pdf"});
foreach (my $i = 56; $i <= 59; ++$i)
{
# See comments in test_driver.cc for a verbal description of what
# the resulting files should look like.
$td->runtest("overlay transformations",
{$td->COMMAND => "test_driver $i fxo-red.pdf fxo-blue.pdf"},
{$td->STRING => "test $i done\n", $td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES);
$td->runtest("compare files",
{$td->FILE => "a.pdf"},
{$td->FILE => "fx-overlay-$i.pdf"});
}
show_ntests();
# ----------
$td->notify("--- Stream Replacement Tests ---");

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,854 @@
%PDF-1.3
%¿÷¢þ
%QDF-1.0
1 0 obj
<<
/Pages 2 0 R
/Type /Catalog
>>
endobj
2 0 obj
<<
/Count 16
/Kids [
3 0 R
4 0 R
5 0 R
6 0 R
7 0 R
8 0 R
9 0 R
10 0 R
11 0 R
12 0 R
13 0 R
14 0 R
15 0 R
16 0 R
17 0 R
18 0 R
]
/Type /Pages
>>
endobj
%% Page 1
3 0 obj
<<
/Contents 19 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Type /Page
>>
endobj
%% Page 2
4 0 obj
<<
/Contents 23 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 90
/Type /Page
>>
endobj
%% Page 3
5 0 obj
<<
/Contents 25 0 R
/CropBox [
10
10
602
782
]
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 180
/Type /Page
>>
endobj
%% Page 4
6 0 obj
<<
/Contents 27 0 R
/CropBox [
10
10
602
782
]
/TrimBox [
20
20
592
772
]
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 270
/Type /Page
>>
endobj
%% Page 5
7 0 obj
<<
/Contents 29 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Type /Page
>>
endobj
%% Page 6
8 0 obj
<<
/Contents 31 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 90
/Type /Page
>>
endobj
%% Page 7
9 0 obj
<<
/Contents 33 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 180
/Type /Page
>>
endobj
%% Page 8
10 0 obj
<<
/Contents 35 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 270
/Type /Page
>>
endobj
%% Page 9
11 0 obj
<<
/Contents 37 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Type /Page
>>
endobj
%% Page 10
12 0 obj
<<
/Contents 39 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 90
/Type /Page
>>
endobj
%% Page 11
13 0 obj
<<
/Contents 41 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 180
/Type /Page
>>
endobj
%% Page 12
14 0 obj
<<
/Contents 43 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 270
/Type /Page
>>
endobj
%% Page 13
15 0 obj
<<
/Contents 45 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Type /Page
>>
endobj
%% Page 14
16 0 obj
<<
/Contents 47 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 90
/Type /Page
/UserUnit 1.5
>>
endobj
%% Page 15
17 0 obj
<<
/Contents 49 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 180
/Type /Page
>>
endobj
%% Page 16
18 0 obj
<<
/Contents 51 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 270
/Type /Page
>>
endobj
%% Contents for page 1
19 0 obj
<<
/Length 20 0 R
>>
stream
0 0 1 RG
0 0 1 rg
BT
/F1 24 Tf
72 690 Td
(Page 1 - blue) Tj
ET
5 w
0 0 612 792 re s
291 391 60 60 re f
endstream
endobj
20 0 obj
109
endobj
21 0 obj
<<
/BaseFont /Helvetica
/Encoding /WinAnsiEncoding
/Name /F1
/Subtype /Type1
/Type /Font
>>
endobj
22 0 obj
[
/PDF
/Text
]
endobj
%% Contents for page 2
23 0 obj
<<
/Length 24 0 R
>>
stream
0 0 1 RG
0 0 1 rg
BT
/F1 24 Tf
72 690 Td
(Page 2 - blue, 90) Tj
ET
5 w
0 0 612 792 re s
291 391 60 60 re f
endstream
endobj
24 0 obj
113
endobj
%% Contents for page 3
25 0 obj
<<
/Length 26 0 R
>>
stream
0 0 1 RG
0 0 1 rg
BT
/F1 24 Tf
72 690 Td
(Page 3 - blue, 180) Tj
ET
5 w
0 0 612 792 re s
10 10 592 772 re s
291 391 60 60 re f
endstream
endobj
26 0 obj
133
endobj
%% Contents for page 4
27 0 obj
<<
/Length 28 0 R
>>
stream
0 0 1 RG
0 0 1 rg
BT
/F1 24 Tf
72 690 Td
(Page 4 - blue, 270) Tj
ET
5 w
0 0 612 792 re s
10 10 592 772 re s
20 20 572 752 re s
291 391 60 60 re f
endstream
endobj
28 0 obj
152
endobj
%% Contents for page 5
29 0 obj
<<
/Length 30 0 R
>>
stream
0 0 1 RG
0 0 1 rg
BT
/F1 24 Tf
72 690 Td
(Page 5 - blue) Tj
ET
5 w
0 0 612 792 re s
291 391 60 60 re f
endstream
endobj
30 0 obj
109
endobj
%% Contents for page 6
31 0 obj
<<
/Length 32 0 R
>>
stream
0 0 1 RG
0 0 1 rg
BT
/F1 24 Tf
72 690 Td
(Page 6 - blue, 90) Tj
ET
5 w
0 0 612 792 re s
291 391 60 60 re f
endstream
endobj
32 0 obj
113
endobj
%% Contents for page 7
33 0 obj
<<
/Length 34 0 R
>>
stream
0 0 1 RG
0 0 1 rg
BT
/F1 24 Tf
72 690 Td
(Page 7 - blue, 180) Tj
ET
5 w
0 0 612 792 re s
291 391 60 60 re f
endstream
endobj
34 0 obj
114
endobj
%% Contents for page 8
35 0 obj
<<
/Length 36 0 R
>>
stream
0 0 1 RG
0 0 1 rg
BT
/F1 24 Tf
72 690 Td
(Page 8 - blue, 270) Tj
ET
5 w
0 0 612 792 re s
291 391 60 60 re f
endstream
endobj
36 0 obj
114
endobj
%% Contents for page 9
37 0 obj
<<
/Length 38 0 R
>>
stream
0 0 1 RG
0 0 1 rg
BT
/F1 24 Tf
72 690 Td
(Page 9 - blue) Tj
ET
5 w
0 0 612 792 re s
291 391 60 60 re f
endstream
endobj
38 0 obj
109
endobj
%% Contents for page 10
39 0 obj
<<
/Length 40 0 R
>>
stream
0 0 1 RG
0 0 1 rg
BT
/F1 24 Tf
72 690 Td
(Page 10 - blue, 90) Tj
ET
5 w
0 0 612 792 re s
291 391 60 60 re f
endstream
endobj
40 0 obj
114
endobj
%% Contents for page 11
41 0 obj
<<
/Length 42 0 R
>>
stream
0 0 1 RG
0 0 1 rg
BT
/F1 24 Tf
72 690 Td
(Page 11 - blue, 180) Tj
ET
5 w
0 0 612 792 re s
291 391 60 60 re f
endstream
endobj
42 0 obj
115
endobj
%% Contents for page 12
43 0 obj
<<
/Length 44 0 R
>>
stream
0 0 1 RG
0 0 1 rg
BT
/F1 24 Tf
72 690 Td
(Page 12 - blue, 270) Tj
ET
5 w
0 0 612 792 re s
291 391 60 60 re f
endstream
endobj
44 0 obj
115
endobj
%% Contents for page 13
45 0 obj
<<
/Length 46 0 R
>>
stream
0 0 1 RG
0 0 1 rg
BT
/F1 24 Tf
72 690 Td
(Page 13 - blue) Tj
ET
5 w
0 0 612 792 re s
291 391 60 60 re f
endstream
endobj
46 0 obj
110
endobj
%% Contents for page 14
47 0 obj
<<
/Length 48 0 R
>>
stream
0 0 1 RG
0 0 1 rg
BT
/F1 24 Tf
72 690 Td
(Page 14 - blue, 90, scale 1.5) Tj
ET
5 w
0 0 612 792 re s
291 391 60 60 re f
endstream
endobj
48 0 obj
125
endobj
%% Contents for page 15
49 0 obj
<<
/Length 50 0 R
>>
stream
0 0 1 RG
0 0 1 rg
BT
/F1 24 Tf
72 690 Td
(Page 15 - blue, 180) Tj
ET
5 w
0 0 612 792 re s
291 391 60 60 re f
endstream
endobj
50 0 obj
115
endobj
%% Contents for page 16
51 0 obj
<<
/Length 52 0 R
>>
stream
0 0 1 RG
0 0 1 rg
BT
/F1 24 Tf
72 690 Td
(Page 16 - blue, 270) Tj
ET
5 w
0 0 612 792 re s
291 391 60 60 re f
endstream
endobj
52 0 obj
115
endobj
xref
0 53
0000000000 65535 f
0000000025 00000 n
0000000079 00000 n
0000000321 00000 n
0000000526 00000 n
0000000744 00000 n
0000001010 00000 n
0000001323 00000 n
0000001528 00000 n
0000001746 00000 n
0000001965 00000 n
0000002185 00000 n
0000002392 00000 n
0000002612 00000 n
0000002833 00000 n
0000003054 00000 n
0000003261 00000 n
0000003497 00000 n
0000003718 00000 n
0000003951 00000 n
0000004117 00000 n
0000004138 00000 n
0000004257 00000 n
0000004316 00000 n
0000004486 00000 n
0000004530 00000 n
0000004720 00000 n
0000004764 00000 n
0000004973 00000 n
0000005017 00000 n
0000005183 00000 n
0000005227 00000 n
0000005397 00000 n
0000005441 00000 n
0000005612 00000 n
0000005656 00000 n
0000005827 00000 n
0000005871 00000 n
0000006037 00000 n
0000006082 00000 n
0000006253 00000 n
0000006298 00000 n
0000006470 00000 n
0000006515 00000 n
0000006687 00000 n
0000006732 00000 n
0000006899 00000 n
0000006944 00000 n
0000007126 00000 n
0000007171 00000 n
0000007343 00000 n
0000007388 00000 n
0000007560 00000 n
trailer <<
/Root 1 0 R
/Size 53
/ID [<4866f3ccc81fb28dc4a27f0f976ce937><ac1c8b0fc0fc7cde25973f6a4877193a>]
>>
startxref
7581
%%EOF

View File

@ -0,0 +1,442 @@
%PDF-1.3
%¿÷¢þ
%QDF-1.0
1 0 obj
<<
/Pages 2 0 R
/Type /Catalog
>>
endobj
2 0 obj
<<
/Count 8
/Kids [
3 0 R
4 0 R
5 0 R
6 0 R
7 0 R
8 0 R
9 0 R
10 0 R
]
/Type /Pages
>>
endobj
%% Page 1
3 0 obj
<<
/Contents 11 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 13 0 R
>>
/ProcSet 14 0 R
>>
/Type /Page
>>
endobj
%% Page 2
4 0 obj
<<
/Contents 15 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 13 0 R
>>
/ProcSet 14 0 R
>>
/Type /Page
>>
endobj
%% Page 3
5 0 obj
<<
/Contents 17 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 13 0 R
>>
/ProcSet 14 0 R
>>
/Rotate 90
/Type /Page
>>
endobj
%% Page 4
6 0 obj
<<
/Contents 19 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 13 0 R
>>
/ProcSet 14 0 R
>>
/Rotate 90
/Type /Page
>>
endobj
%% Page 5
7 0 obj
<<
/Contents 21 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 13 0 R
>>
/ProcSet 14 0 R
>>
/Rotate 180
/Type /Page
>>
endobj
%% Page 6
8 0 obj
<<
/Contents 23 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 13 0 R
>>
/ProcSet 14 0 R
>>
/Rotate 180
/Type /Page
>>
endobj
%% Page 7
9 0 obj
<<
/Contents 25 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 13 0 R
>>
/ProcSet 14 0 R
>>
/Rotate 270
/Type /Page
>>
endobj
%% Page 8
10 0 obj
<<
/Contents 27 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 13 0 R
>>
/ProcSet 14 0 R
>>
/Rotate 270
/Type /Page
>>
endobj
%% Contents for page 1
11 0 obj
<<
/Length 12 0 R
>>
stream
0 1 0 RG
0 1 0 rg
BT
/F1 24 Tf
72 660 Td
(Page 1 - green) Tj
ET
5 w
0 0 612 792 re s
281 381 60 60 re f
endstream
endobj
12 0 obj
110
endobj
13 0 obj
<<
/BaseFont /Helvetica
/Encoding /WinAnsiEncoding
/Name /F1
/Subtype /Type1
/Type /Font
>>
endobj
14 0 obj
[
/PDF
/Text
]
endobj
%% Contents for page 2
15 0 obj
<<
/Length 16 0 R
>>
stream
0 1 0 RG
0 1 0 rg
BT
/F1 24 Tf
72 660 Td
(Page 2 - green) Tj
ET
5 w
0 0 612 792 re s
281 381 60 60 re f
endstream
endobj
16 0 obj
110
endobj
%% Contents for page 3
17 0 obj
<<
/Length 18 0 R
>>
stream
0 1 0 RG
0 1 0 rg
BT
/F1 24 Tf
72 660 Td
(Page 3 - green, 90) Tj
ET
5 w
0 0 612 792 re s
281 381 60 60 re f
endstream
endobj
18 0 obj
114
endobj
%% Contents for page 4
19 0 obj
<<
/Length 20 0 R
>>
stream
0 1 0 RG
0 1 0 rg
BT
/F1 24 Tf
72 660 Td
(Page 4 - green, 90) Tj
ET
5 w
0 0 612 792 re s
281 381 60 60 re f
endstream
endobj
20 0 obj
114
endobj
%% Contents for page 5
21 0 obj
<<
/Length 22 0 R
>>
stream
0 1 0 RG
0 1 0 rg
BT
/F1 24 Tf
72 660 Td
(Page 5 - green, 180) Tj
ET
5 w
0 0 612 792 re s
281 381 60 60 re f
endstream
endobj
22 0 obj
115
endobj
%% Contents for page 6
23 0 obj
<<
/Length 24 0 R
>>
stream
0 1 0 RG
0 1 0 rg
BT
/F1 24 Tf
72 660 Td
(Page 6 - green, 180) Tj
ET
5 w
0 0 612 792 re s
281 381 60 60 re f
endstream
endobj
24 0 obj
115
endobj
%% Contents for page 7
25 0 obj
<<
/Length 26 0 R
>>
stream
0 1 0 RG
0 1 0 rg
BT
/F1 24 Tf
72 660 Td
(Page 7 - green, 270) Tj
ET
5 w
0 0 612 792 re s
281 381 60 60 re f
endstream
endobj
26 0 obj
115
endobj
%% Contents for page 8
27 0 obj
<<
/Length 28 0 R
>>
stream
0 1 0 RG
0 1 0 rg
BT
/F1 24 Tf
72 660 Td
(Page 8 - green, 270) Tj
ET
5 w
0 0 612 792 re s
281 381 60 60 re f
endstream
endobj
28 0 obj
115
endobj
xref
0 29
0000000000 65535 f
0000000025 00000 n
0000000079 00000 n
0000000232 00000 n
0000000437 00000 n
0000000642 00000 n
0000000860 00000 n
0000001078 00000 n
0000001297 00000 n
0000001516 00000 n
0000001735 00000 n
0000001968 00000 n
0000002135 00000 n
0000002156 00000 n
0000002275 00000 n
0000002334 00000 n
0000002501 00000 n
0000002545 00000 n
0000002716 00000 n
0000002760 00000 n
0000002931 00000 n
0000002975 00000 n
0000003147 00000 n
0000003191 00000 n
0000003363 00000 n
0000003407 00000 n
0000003579 00000 n
0000003623 00000 n
0000003795 00000 n
trailer <<
/Root 1 0 R
/Size 29
/ID [<4866f3ccc81fb28dc4a27f0f976ce937><403c6a48695b03d989d7bf77eca90ce8>]
>>
startxref
3816
%%EOF

854
qpdf/qtest/qpdf/fxo-red.pdf Normal file
View File

@ -0,0 +1,854 @@
%PDF-1.3
%¿÷¢þ
%QDF-1.0
1 0 obj
<<
/Pages 2 0 R
/Type /Catalog
>>
endobj
2 0 obj
<<
/Count 16
/Kids [
3 0 R
4 0 R
5 0 R
6 0 R
7 0 R
8 0 R
9 0 R
10 0 R
11 0 R
12 0 R
13 0 R
14 0 R
15 0 R
16 0 R
17 0 R
18 0 R
]
/Type /Pages
>>
endobj
%% Page 1
3 0 obj
<<
/Contents 19 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Type /Page
>>
endobj
%% Page 2
4 0 obj
<<
/Contents 23 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Type /Page
/UserUnit 2
>>
endobj
%% Page 3
5 0 obj
<<
/Contents [
25 0 R
27 0 R
]
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Type /Page
>>
endobj
%% Page 4
6 0 obj
<<
/Contents 29 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Type /Page
>>
endobj
%% Page 5
7 0 obj
<<
/Contents 31 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 90
/Type /Page
>>
endobj
%% Page 6
8 0 obj
<<
/Contents 33 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 90
/Type /Page
/UserUnit 1.5
>>
endobj
%% Page 7
9 0 obj
<<
/Contents 35 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 90
/Type /Page
>>
endobj
%% Page 8
10 0 obj
<<
/Contents 37 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 90
/Type /Page
>>
endobj
%% Page 9
11 0 obj
<<
/Contents 39 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 180
/Type /Page
>>
endobj
%% Page 10
12 0 obj
<<
/Contents 41 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 180
/Type /Page
/UserUnit 0.75
>>
endobj
%% Page 11
13 0 obj
<<
/Contents 43 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 180
/Type /Page
>>
endobj
%% Page 12
14 0 obj
<<
/Contents 45 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 180
/Type /Page
>>
endobj
%% Page 13
15 0 obj
<<
/Contents 47 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 270
/Type /Page
>>
endobj
%% Page 14
16 0 obj
<<
/Contents 49 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 270
/Type /Page
/UserUnit 1.25
>>
endobj
%% Page 15
17 0 obj
<<
/Contents 51 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 270
/Type /Page
>>
endobj
%% Page 16
18 0 obj
<<
/Contents 53 0 R
/MediaBox [
0
0
612
792
]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 21 0 R
>>
/ProcSet 22 0 R
>>
/Rotate 270
/Type /Page
>>
endobj
%% Contents for page 1
19 0 obj
<<
/Length 20 0 R
>>
stream
1 0 0 RG
1 0 0 rg
BT
/F1 24 Tf
72 720 Td
(Page 1 - red) Tj
ET
5 w
0 0 612 792 re s
271 371 60 60 re f
endstream
endobj
20 0 obj
108
endobj
21 0 obj
<<
/BaseFont /Helvetica
/Encoding /WinAnsiEncoding
/Name /F1
/Subtype /Type1
/Type /Font
>>
endobj
22 0 obj
[
/PDF
/Text
]
endobj
%% Contents for page 2
23 0 obj
<<
/Length 24 0 R
>>
stream
1 0 0 RG
1 0 0 rg
BT
/F1 24 Tf
72 720 Td
(Page 2 - red, scale 2) Tj
ET
5 w
0 0 612 792 re s
271 371 60 60 re f
endstream
endobj
24 0 obj
117
endobj
%% Contents for page 3
25 0 obj
<<
/Length 26 0 R
>>
stream
1 0 0 RG
1 0 0 rg
BT
/F1 24 Tf
72 720 Td
endstream
endobj
26 0 obj
45
endobj
%% Contents for page 3
27 0 obj
<<
/Length 28 0 R
>>
stream
(Page 3 - red) Tj
ET
5 w
0 0 612 792 re s
271 371 60 60 re f
endstream
endobj
28 0 obj
63
endobj
%% Contents for page 4
29 0 obj
<<
/Length 30 0 R
>>
stream
1 0 0 RG
1 0 0 rg
BT
/F1 24 Tf
72 720 Td
(Page 4 - red) Tj
ET
5 w
0 0 612 792 re s
271 371 60 60 re f
endstream
endobj
30 0 obj
108
endobj
%% Contents for page 5
31 0 obj
<<
/Length 32 0 R
>>
stream
1 0 0 RG
1 0 0 rg
BT
/F1 24 Tf
72 720 Td
(Page 5 - red, 90) Tj
ET
5 w
0 0 612 792 re s
271 371 60 60 re f
endstream
endobj
32 0 obj
112
endobj
%% Contents for page 6
33 0 obj
<<
/Length 34 0 R
>>
stream
1 0 0 RG
1 0 0 rg
BT
/F1 24 Tf
72 720 Td
(Page 6 - red, 90, scale 1.5) Tj
ET
5 w
0 0 612 792 re s
271 371 60 60 re f
endstream
endobj
34 0 obj
123
endobj
%% Contents for page 7
35 0 obj
<<
/Length 36 0 R
>>
stream
1 0 0 RG
1 0 0 rg
BT
/F1 24 Tf
72 720 Td
(Page 7 - red, 90) Tj
ET
5 w
0 0 612 792 re s
271 371 60 60 re f
endstream
endobj
36 0 obj
112
endobj
%% Contents for page 8
37 0 obj
<<
/Length 38 0 R
>>
stream
1 0 0 RG
1 0 0 rg
BT
/F1 24 Tf
72 720 Td
(Page 8 - red, 90) Tj
ET
5 w
0 0 612 792 re s
271 371 60 60 re f
endstream
endobj
38 0 obj
112
endobj
%% Contents for page 9
39 0 obj
<<
/Length 40 0 R
>>
stream
1 0 0 RG
1 0 0 rg
BT
/F1 24 Tf
72 720 Td
(Page 9 - red, 180) Tj
ET
5 w
0 0 612 792 re s
271 371 60 60 re f
endstream
endobj
40 0 obj
113
endobj
%% Contents for page 10
41 0 obj
<<
/Length 42 0 R
>>
stream
1 0 0 RG
1 0 0 rg
BT
/F1 24 Tf
72 720 Td
(Page 10 - red, 180, scale 0.75) Tj
ET
5 w
0 0 612 792 re s
271 371 60 60 re f
endstream
endobj
42 0 obj
126
endobj
%% Contents for page 11
43 0 obj
<<
/Length 44 0 R
>>
stream
1 0 0 RG
1 0 0 rg
BT
/F1 24 Tf
72 720 Td
(Page 11 - red, 180) Tj
ET
5 w
0 0 612 792 re s
271 371 60 60 re f
endstream
endobj
44 0 obj
114
endobj
%% Contents for page 12
45 0 obj
<<
/Length 46 0 R
>>
stream
1 0 0 RG
1 0 0 rg
BT
/F1 24 Tf
72 720 Td
(Page 12 - red, 180) Tj
ET
5 w
0 0 612 792 re s
271 371 60 60 re f
endstream
endobj
46 0 obj
114
endobj
%% Contents for page 13
47 0 obj
<<
/Length 48 0 R
>>
stream
1 0 0 RG
1 0 0 rg
BT
/F1 24 Tf
72 720 Td
(Page 13 - red, 270) Tj
ET
5 w
0 0 612 792 re s
271 371 60 60 re f
endstream
endobj
48 0 obj
114
endobj
%% Contents for page 14
49 0 obj
<<
/Length 50 0 R
>>
stream
1 0 0 RG
1 0 0 rg
BT
/F1 24 Tf
72 720 Td
(Page 14 - red, 270, scale 1.25) Tj
ET
5 w
0 0 612 792 re s
271 371 60 60 re f
endstream
endobj
50 0 obj
126
endobj
%% Contents for page 15
51 0 obj
<<
/Length 52 0 R
>>
stream
1 0 0 RG
1 0 0 rg
BT
/F1 24 Tf
72 720 Td
(Page 15 - red, 270) Tj
ET
5 w
0 0 612 792 re s
271 371 60 60 re f
endstream
endobj
52 0 obj
114
endobj
%% Contents for page 16
53 0 obj
<<
/Length 54 0 R
>>
stream
1 0 0 RG
1 0 0 rg
BT
/F1 24 Tf
72 720 Td
(Page 16 - red, 270) Tj
ET
5 w
0 0 612 792 re s
271 371 60 60 re f
endstream
endobj
54 0 obj
114
endobj
xref
0 55
0000000000 65535 f
0000000025 00000 n
0000000079 00000 n
0000000321 00000 n
0000000526 00000 n
0000000745 00000 n
0000000971 00000 n
0000001176 00000 n
0000001394 00000 n
0000001628 00000 n
0000001846 00000 n
0000002065 00000 n
0000002286 00000 n
0000002524 00000 n
0000002745 00000 n
0000002966 00000 n
0000003187 00000 n
0000003425 00000 n
0000003646 00000 n
0000003879 00000 n
0000004044 00000 n
0000004065 00000 n
0000004184 00000 n
0000004243 00000 n
0000004417 00000 n
0000004461 00000 n
0000004563 00000 n
0000004606 00000 n
0000004726 00000 n
0000004769 00000 n
0000004934 00000 n
0000004978 00000 n
0000005147 00000 n
0000005191 00000 n
0000005371 00000 n
0000005415 00000 n
0000005584 00000 n
0000005628 00000 n
0000005797 00000 n
0000005841 00000 n
0000006011 00000 n
0000006056 00000 n
0000006239 00000 n
0000006284 00000 n
0000006455 00000 n
0000006500 00000 n
0000006671 00000 n
0000006716 00000 n
0000006887 00000 n
0000006932 00000 n
0000007115 00000 n
0000007160 00000 n
0000007331 00000 n
0000007376 00000 n
0000007547 00000 n
trailer <<
/Root 1 0 R
/Size 55
/ID [<4866f3ccc81fb28dc4a27f0f976ce937><3284da213b50483218e61c3cf23f99f3>]
>>
startxref
7568
%%EOF

View File

@ -1944,6 +1944,78 @@ void runtest(int n, char const* filename1, char const* arg2)
std::cout << "oops: " << w.getFinalVersion() << std::endl;
}
}
else if (n == 55)
{
// Form XObjects
std::vector<QPDFPageObjectHelper> pages =
QPDFPageDocumentHelper(pdf).getAllPages();
QPDFObjectHandle qtest = QPDFObjectHandle::newArray();
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
iter != pages.end(); ++iter)
{
QPDFPageObjectHelper& ph(*iter);
qtest.appendItem(ph.getFormXObjectForPage());
qtest.appendItem(ph.getFormXObjectForPage(false));
}
pdf.getTrailer().replaceKey("/QTest", qtest);
QPDFWriter w(pdf, "a.pdf");
w.setQDFMode(true);
w.setStaticID(true);
w.write();
}
else if ((n >= 56) && (n <= 59))
{
// Placing form XObjects
assert(arg2);
QPDF pdf2;
pdf2.processFile(arg2);
// red pages are from pdf, blue pages are from pdf2
// red pages always have stated rotation absolutely
// 56: blue pages are overlayed exactly on top of red pages
// 57: blue pages have stated rotation relative to red pages
// 58: blue pages have no rotation (absolutely upgright)
// 59: blue pages have stated rotation absolutely
bool handle_from_transformation = ((n == 57) || (n == 59));
bool invert_to_transformation = ((n == 58) || (n == 59));
std::vector<QPDFPageObjectHelper> pages1 =
QPDFPageDocumentHelper(pdf).getAllPages();
std::vector<QPDFPageObjectHelper> pages2 =
QPDFPageDocumentHelper(pdf2).getAllPages();
size_t npages = (pages1.size() < pages2.size()
? pages1.size() : pages2.size());
for (size_t i = 0; i < npages; ++i)
{
QPDFPageObjectHelper& ph1 = pages1.at(i);
QPDFPageObjectHelper& ph2 = pages2.at(i);
QPDFObjectHandle fo = pdf.copyForeignObject(
ph2.getFormXObjectForPage(handle_from_transformation));
int min_suffix = 1;
QPDFObjectHandle resources = ph1.getAttribute("/Resources", true);
std::string name = resources.getUniqueResourceName(
"/Fx", min_suffix);
std::string content =
ph1.placeFormXObject(
fo, name, ph1.getTrimBox().getArrayAsRectangle(),
invert_to_transformation);
if (! content.empty())
{
resources.mergeResources(
QPDFObjectHandle::parse("<< /XObject << >> >>"));
resources.getKey("/XObject").replaceKey(name, fo);
ph1.addPageContents(
QPDFObjectHandle::newStream(&pdf, "q\n"), true);
ph1.addPageContents(
QPDFObjectHandle::newStream(&pdf, "\nQ\n" + content),
false);
}
}
QPDFWriter w(pdf, "a.pdf");
w.setQDFMode(true);
w.setStaticID(true);
w.write();
}
else
{
throw std::runtime_error(std::string("invalid test ") +