mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 10:58:58 +00:00
Add basic appearance stream generation
This commit is contained in:
parent
02281632cc
commit
158156d506
23
ChangeLog
23
ChangeLog
@ -1,5 +1,28 @@
|
||||
2019-01-03 Jay Berkenbilt <ejb@ql.org>
|
||||
|
||||
* Fix behavior of form field value setting to handle the following
|
||||
cases:
|
||||
- Strings are always written as UTF-16
|
||||
- Check boxes and radio buttons are handled properly with
|
||||
synchronization of values and appearance states
|
||||
|
||||
* Define constants in qpdf/Constants.h for interpretation of
|
||||
annotation and form field flags
|
||||
|
||||
* Add QPDFAnnotationObjectHelper::getFlags
|
||||
|
||||
* Add many new methods to QPDFFormFieldObjectHelper for querying
|
||||
flags and field types
|
||||
|
||||
* Add new methods for appearance stream generation. See comments
|
||||
in QPDFFormFieldObjectHelper.hh for generateAppearance() for a
|
||||
description of limitations.
|
||||
- QPDFAcroFormDocumentHelper::generateAppearancesIfNeeded
|
||||
- QPDFFormFieldObjectHelper::generateAppearance
|
||||
|
||||
* Bug fix: when writing form field values, always write string
|
||||
values encoded as UTF-16.
|
||||
|
||||
* Add method QUtil::utf8_to_ascii, which returns an ASCII string
|
||||
for a UTF-8 string, replacing out-of-range characters with a
|
||||
specified substitute.
|
||||
|
@ -157,6 +157,16 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper
|
||||
QPDF_DLL
|
||||
void setNeedAppearances(bool);
|
||||
|
||||
// If /NeedAppearances is false, do nothing. Otherwise generate
|
||||
// appearance streams for all widget annotations that need them.
|
||||
// See comments in QPDFFormFieldObjectHelper.hh for
|
||||
// generateAppearance for limitations. For checkbox and radio
|
||||
// button fields, this code ensures that appearance state is
|
||||
// consistent with the field's value and uses any pre-existing
|
||||
// appearance streams.
|
||||
QPDF_DLL
|
||||
void generateAppearancesIfNeeded();
|
||||
|
||||
private:
|
||||
void analyze();
|
||||
void traverseField(QPDFObjectHandle field,
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include <qpdf/DLL.h>
|
||||
#include <vector>
|
||||
|
||||
class QPDFAnnotationObjectHelper;
|
||||
|
||||
class QPDFFormFieldObjectHelper: public QPDFObjectHelper
|
||||
{
|
||||
public:
|
||||
@ -179,9 +181,21 @@ class QPDFFormFieldObjectHelper: public QPDFObjectHelper
|
||||
QPDF_DLL
|
||||
void setV(std::string const& utf8_value, bool need_appearances = true);
|
||||
|
||||
// Update the appearance stream for this field. Note that qpdf's
|
||||
// abilitiy to generate appearance streams is limited. We only
|
||||
// generate appearance streams for streams of type text or choice.
|
||||
// The appearance uses the default parameters provided in the
|
||||
// file, and it only supports ASCII characters. Quadding is
|
||||
// currently ignored. While this functionality is limited, it
|
||||
// should do a decent job on properly constructed PDF files when
|
||||
// field values are restricted to ASCII characters.
|
||||
QPDF_DLL
|
||||
void generateAppearance(QPDFAnnotationObjectHelper&);
|
||||
|
||||
private:
|
||||
void setRadioButtonValue(QPDFObjectHandle name);
|
||||
void setCheckBoxValue(bool value);
|
||||
void generateTextAppearance(QPDFAnnotationObjectHelper&);
|
||||
|
||||
class Members
|
||||
{
|
||||
|
@ -285,3 +285,48 @@ QPDFAcroFormDocumentHelper::setNeedAppearances(bool val)
|
||||
acroform.removeKey("/NeedAppearances");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QPDFAcroFormDocumentHelper::generateAppearancesIfNeeded()
|
||||
{
|
||||
if (! getNeedAppearances())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QPDFPageDocumentHelper pdh(this->qpdf);
|
||||
std::vector<QPDFPageObjectHelper> pages = pdh.getAllPages();
|
||||
for (std::vector<QPDFPageObjectHelper>::iterator page_iter =
|
||||
pages.begin();
|
||||
page_iter != pages.end(); ++page_iter)
|
||||
{
|
||||
std::vector<QPDFAnnotationObjectHelper> annotations =
|
||||
getWidgetAnnotationsForPage(*page_iter);
|
||||
for (std::vector<QPDFAnnotationObjectHelper>::iterator annot_iter =
|
||||
annotations.begin();
|
||||
annot_iter != annotations.end(); ++annot_iter)
|
||||
{
|
||||
QPDFAnnotationObjectHelper& aoh = *annot_iter;
|
||||
QPDFFormFieldObjectHelper ffh =
|
||||
getFieldForAnnotation(aoh);
|
||||
if (ffh.getFieldType() == "/Btn")
|
||||
{
|
||||
// Rather than generating appearances for button
|
||||
// fields, rely on what's already there. Just make
|
||||
// sure /AS is consistent with /V, which we can do by
|
||||
// resetting the value of the field back to itself.
|
||||
// This code is referenced in a comment in
|
||||
// QPDFFormFieldObjectHelper::generateAppearance.
|
||||
if (ffh.isRadioButton() || ffh.isCheckbox())
|
||||
{
|
||||
ffh.setV(ffh.getValue());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ffh.generateAppearance(aoh);
|
||||
}
|
||||
}
|
||||
}
|
||||
setNeedAppearances(false);
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
#include <qpdf/QPDFFormFieldObjectHelper.hh>
|
||||
#include <qpdf/QTC.hh>
|
||||
#include <qpdf/QPDFAcroFormDocumentHelper.hh>
|
||||
#include <qpdf/QPDFAnnotationObjectHelper.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
#include <qpdf/Pl_QPDFTokenizer.hh>
|
||||
#include <stdlib.h>
|
||||
|
||||
QPDFFormFieldObjectHelper::Members::~Members()
|
||||
{
|
||||
@ -313,7 +317,15 @@ QPDFFormFieldObjectHelper::setV(
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (value.isString())
|
||||
{
|
||||
setFieldAttribute(
|
||||
"/V", QPDFObjectHandle::newUnicodeString(value.getUTF8Value()));
|
||||
}
|
||||
else
|
||||
{
|
||||
setFieldAttribute("/V", value);
|
||||
}
|
||||
if (need_appearances)
|
||||
{
|
||||
QPDF* qpdf = this->oh.getOwningQPDF();
|
||||
@ -470,3 +482,290 @@ QPDFFormFieldObjectHelper::setCheckBoxValue(bool value)
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper set checkbox AS");
|
||||
annot.replaceKey("/AS", name);
|
||||
}
|
||||
|
||||
void
|
||||
QPDFFormFieldObjectHelper::generateAppearance(QPDFAnnotationObjectHelper& aoh)
|
||||
{
|
||||
std::string ft = getFieldType();
|
||||
// Ignore field types we don't know how to generate appearances
|
||||
// for. Button fields don't really need them -- see code in
|
||||
// QPDFAcroFormDocumentHelper::generateAppearancesIfNeeded.
|
||||
if ((ft == "/Tx") || (ft == "/Ch"))
|
||||
{
|
||||
generateTextAppearance(aoh);
|
||||
}
|
||||
}
|
||||
|
||||
class ValueSetter: public QPDFObjectHandle::TokenFilter
|
||||
{
|
||||
public:
|
||||
ValueSetter(std::string const& DA, std::string const& V,
|
||||
std::vector<std::string> const& opt, double tf,
|
||||
QPDFObjectHandle::Rectangle const& bbox);
|
||||
virtual ~ValueSetter()
|
||||
{
|
||||
}
|
||||
virtual void handleToken(QPDFTokenizer::Token const&);
|
||||
void writeAppearance();
|
||||
|
||||
private:
|
||||
std::string DA;
|
||||
std::string V;
|
||||
std::vector<std::string> opt;
|
||||
double tf;
|
||||
QPDFObjectHandle::Rectangle bbox;
|
||||
enum { st_top, st_bmc, st_emc, st_end } state;
|
||||
};
|
||||
|
||||
ValueSetter::ValueSetter(std::string const& DA, std::string const& V,
|
||||
std::vector<std::string> const& opt, double tf,
|
||||
QPDFObjectHandle::Rectangle const& bbox) :
|
||||
DA(DA),
|
||||
V(V),
|
||||
opt(opt),
|
||||
tf(tf),
|
||||
bbox(bbox),
|
||||
state(st_top)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ValueSetter::handleToken(QPDFTokenizer::Token const& token)
|
||||
{
|
||||
QPDFTokenizer::token_type_e ttype = token.getType();
|
||||
std::string value = token.getValue();
|
||||
bool do_replace = false;
|
||||
switch (state)
|
||||
{
|
||||
case st_top:
|
||||
writeToken(token);
|
||||
if ((ttype == QPDFTokenizer::tt_word) && (value == "BMC"))
|
||||
{
|
||||
state = st_bmc;
|
||||
}
|
||||
break;
|
||||
|
||||
case st_bmc:
|
||||
if ((ttype == QPDFTokenizer::tt_space) ||
|
||||
(ttype == QPDFTokenizer::tt_comment))
|
||||
{
|
||||
writeToken(token);
|
||||
}
|
||||
else
|
||||
{
|
||||
state = st_emc;
|
||||
}
|
||||
// fall through to emc
|
||||
|
||||
case st_emc:
|
||||
if ((ttype == QPDFTokenizer::tt_word) && (value == "EMC"))
|
||||
{
|
||||
do_replace = true;
|
||||
state = st_end;
|
||||
}
|
||||
break;
|
||||
|
||||
case st_end:
|
||||
writeToken(token);
|
||||
break;
|
||||
}
|
||||
if (do_replace)
|
||||
{
|
||||
writeAppearance();
|
||||
}
|
||||
}
|
||||
|
||||
void ValueSetter::writeAppearance()
|
||||
{
|
||||
// This code does not take quadding into consideration because
|
||||
// doing so requires font metric information, which we don't
|
||||
// have in many cases.
|
||||
|
||||
double tfh = 1.2 * tf;
|
||||
int dx = 1;
|
||||
|
||||
// Write one or more lines, centered vertically, possibly with
|
||||
// one row highlighted.
|
||||
|
||||
size_t max_rows = static_cast<size_t>((bbox.ury - bbox.lly) / tfh);
|
||||
bool highlight = false;
|
||||
size_t highlight_idx = 0;
|
||||
|
||||
std::vector<std::string> lines;
|
||||
if (opt.empty() || (max_rows < 2))
|
||||
{
|
||||
lines.push_back(V);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Figure out what rows to write
|
||||
size_t nopt = opt.size();
|
||||
size_t found_idx = 0;
|
||||
bool found = false;
|
||||
for (found_idx = 0; found_idx < nopt; ++found_idx)
|
||||
{
|
||||
if (opt.at(found_idx) == V)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
// Try to make the found item the second one, but
|
||||
// adjust for under/overflow.
|
||||
int wanted_first = found_idx - 1;
|
||||
int wanted_last = found_idx + max_rows - 2;
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper list found");
|
||||
while (wanted_first < 0)
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper list first too low");
|
||||
++wanted_first;
|
||||
++wanted_last;
|
||||
}
|
||||
while (wanted_last >= static_cast<int>(nopt))
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper list last too high");
|
||||
if (wanted_first > 0)
|
||||
{
|
||||
--wanted_first;
|
||||
}
|
||||
--wanted_last;
|
||||
}
|
||||
highlight = true;
|
||||
highlight_idx = found_idx - wanted_first;
|
||||
for (int i = wanted_first; i <= wanted_last; ++i)
|
||||
{
|
||||
lines.push_back(opt.at(i));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper list not found");
|
||||
// include our value and the first n-1 rows
|
||||
highlight_idx = 0;
|
||||
highlight = true;
|
||||
lines.push_back(V);
|
||||
for (size_t i = 0; ((i < nopt) && (i < (max_rows - 1))); ++i)
|
||||
{
|
||||
lines.push_back(opt.at(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write the lines centered vertically, highlighting if needed
|
||||
size_t nlines = lines.size();
|
||||
double dy = bbox.ury - ((bbox.ury - bbox.lly - (nlines * tfh)) / 2.0);
|
||||
write(DA + "\nq\n");
|
||||
if (highlight)
|
||||
{
|
||||
write("q\n0.85 0.85 0.85 rg\n" +
|
||||
QUtil::int_to_string(bbox.llx) + " " +
|
||||
QUtil::double_to_string(bbox.lly + dy -
|
||||
(tfh * (highlight_idx + 1))) + " " +
|
||||
QUtil::int_to_string(bbox.urx - bbox.llx) + " " +
|
||||
QUtil::double_to_string(tfh) +
|
||||
" re f\nQ\n");
|
||||
}
|
||||
dy += 0.2 * tf;
|
||||
for (size_t i = 0; i < nlines; ++i)
|
||||
{
|
||||
dy -= tfh;
|
||||
write("BT\n" +
|
||||
QUtil::int_to_string(bbox.llx + dx) + " " +
|
||||
QUtil::double_to_string(bbox.lly + dy) + " Td\n" +
|
||||
QPDFObjectHandle::newString(lines.at(i)).unparse() +
|
||||
" Tj\nET\n");
|
||||
}
|
||||
write("Q\nEMC");
|
||||
}
|
||||
|
||||
class TfFinder: public QPDFObjectHandle::TokenFilter
|
||||
{
|
||||
public:
|
||||
TfFinder();
|
||||
virtual ~TfFinder()
|
||||
{
|
||||
}
|
||||
virtual void handleToken(QPDFTokenizer::Token const&);
|
||||
double getTf();
|
||||
|
||||
private:
|
||||
double tf;
|
||||
double last_num;
|
||||
};
|
||||
|
||||
TfFinder::TfFinder() :
|
||||
tf(11.0),
|
||||
last_num(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TfFinder::handleToken(QPDFTokenizer::Token const& token)
|
||||
{
|
||||
QPDFTokenizer::token_type_e ttype = token.getType();
|
||||
std::string value = token.getValue();
|
||||
switch (ttype)
|
||||
{
|
||||
case QPDFTokenizer::tt_integer:
|
||||
case QPDFTokenizer::tt_real:
|
||||
last_num = strtod(value.c_str(), 0);
|
||||
break;
|
||||
|
||||
case QPDFTokenizer::tt_word:
|
||||
if ((value == "Tf") &&
|
||||
(last_num > 1.0) &&
|
||||
(last_num < 1000.0))
|
||||
{
|
||||
// These ranges are arbitrary but keep us from doing
|
||||
// insane things or suffering from over/underflow
|
||||
tf = last_num;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
double
|
||||
TfFinder::getTf()
|
||||
{
|
||||
return this->tf;
|
||||
}
|
||||
|
||||
void
|
||||
QPDFFormFieldObjectHelper::generateTextAppearance(
|
||||
QPDFAnnotationObjectHelper& aoh)
|
||||
{
|
||||
QPDFObjectHandle AS = aoh.getAppearanceStream("/N");
|
||||
if (! AS.isStream())
|
||||
{
|
||||
aoh.getObjectHandle().warnIfPossible(
|
||||
"unable to get normal appearance stream for update");
|
||||
return;
|
||||
}
|
||||
QPDFObjectHandle bbox_obj = AS.getDict().getKey("/BBox");
|
||||
if (! bbox_obj.isRectangle())
|
||||
{
|
||||
aoh.getObjectHandle().warnIfPossible(
|
||||
"unable to get appearance stream bounding box");
|
||||
return;
|
||||
}
|
||||
QPDFObjectHandle::Rectangle bbox = bbox_obj.getArrayAsRectangle();
|
||||
std::string DA = getDefaultAppearance();
|
||||
std::string V = QUtil::utf8_to_ascii(getValueAsString());
|
||||
|
||||
TfFinder tff;
|
||||
Pl_QPDFTokenizer tok("tf", &tff);
|
||||
tok.write(QUtil::unsigned_char_pointer(DA.c_str()), DA.length());
|
||||
tok.finish();
|
||||
double tf = tff.getTf();
|
||||
std::vector<std::string> opt;
|
||||
if (isChoice() && ((getFlags() & ff_ch_combo) == 0))
|
||||
{
|
||||
opt = getChoices();
|
||||
}
|
||||
AS.addTokenFilter(new ValueSetter(DA, V, opt, tf, bbox));
|
||||
}
|
||||
|
38
qpdf/qpdf.cc
38
qpdf/qpdf.cc
@ -106,6 +106,7 @@ struct Options
|
||||
flatten_annotations(false),
|
||||
flatten_annotations_required(0),
|
||||
flatten_annotations_forbidden(an_invisible | an_hidden),
|
||||
generate_appearances(false),
|
||||
show_npages(false),
|
||||
deterministic_id(false),
|
||||
static_id(false),
|
||||
@ -181,6 +182,7 @@ struct Options
|
||||
bool flatten_annotations;
|
||||
int flatten_annotations_required;
|
||||
int flatten_annotations_forbidden;
|
||||
bool generate_appearances;
|
||||
std::string min_version;
|
||||
std::string force_version;
|
||||
bool show_npages;
|
||||
@ -570,6 +572,7 @@ class ArgParser
|
||||
void argLinearizePass1(char* parameter);
|
||||
void argCoalesceContents();
|
||||
void argFlattenAnnotations(char* parameter);
|
||||
void argGenerateAppearances();
|
||||
void argMinVersion(char* parameter);
|
||||
void argForceVersion(char* parameter);
|
||||
void argSplitPages(char* parameter);
|
||||
@ -771,6 +774,8 @@ ArgParser::initOptionTable()
|
||||
char const* flatten_choices[] = {"all", "print", "screen", 0};
|
||||
(*t)["flatten-annotations"] = oe_requiredChoices(
|
||||
&ArgParser::argFlattenAnnotations, flatten_choices);
|
||||
(*t)["generate-appearances"] =
|
||||
oe_bare(&ArgParser::argGenerateAppearances);
|
||||
(*t)["min-version"] = oe_requiredParameter(
|
||||
&ArgParser::argMinVersion, "version");
|
||||
(*t)["force-version"] = oe_requiredParameter(
|
||||
@ -1233,6 +1238,12 @@ ArgParser::argFlattenAnnotations(char* parameter)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argGenerateAppearances()
|
||||
{
|
||||
o.generate_appearances = true;
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argMinVersion(char* parameter)
|
||||
{
|
||||
@ -1877,18 +1888,28 @@ familiar with the PDF file format or who are PDF developers.\n\
|
||||
--flatten-annotations=option\n\
|
||||
incorporate rendering of annotations into page\n\
|
||||
contents including those for interactive form\n\
|
||||
fields\n\
|
||||
fields; may also want --generate-appearances\n\
|
||||
--generate-appearances generate appearance streams for form fields\n\
|
||||
--qdf turns on \"QDF mode\" (below)\n\
|
||||
--linearize-pass1=file write intermediate pass of linearized file\n\
|
||||
for debugging\n\
|
||||
--min-version=version sets the minimum PDF version of the output file\n\
|
||||
--force-version=version forces this to be the PDF version of the output file\n\
|
||||
\n\
|
||||
Options for --flatten-annotations are all, print, or screen. If the\n\
|
||||
option is print, only annotations marked as print are included. If the\n\
|
||||
option is screen, options marked as \"no view\" are excluded.\n\
|
||||
Otherwise, annotations are flattened regardless of the presence of\n\
|
||||
print or NoView flags.\n\
|
||||
Options for --flatten-annotations are all, print, or screen. If the option\n\
|
||||
is print, only annotations marked as print are included. If the option is\n\
|
||||
screen, options marked as \"no view\" are excluded. Otherwise, annotations\n\
|
||||
are flattened regardless of the presence of print or NoView flags. It is\n\
|
||||
common for PDF files to have a flag set that appearance streams need to be\n\
|
||||
regenerated. This happens when someone changes a form value with software\n\
|
||||
that does not know how to render the new value. qpdf will not flatten form\n\
|
||||
fields in files like this. If you get this warning, you have two choices:\n\
|
||||
either use qpdf's --generate-appearances flag to tell qpdf to go ahead and\n\
|
||||
regenerate appearances, or use some other tool to generate the appearances.\n\
|
||||
qpdf does a pretty good job with most forms when only ASCII characters are\n\
|
||||
used in form field values, but if your form fields contain other\n\
|
||||
characters, rich text, or are other than left justified, you will get\n\
|
||||
better results first saving with other software.\n\
|
||||
\n\
|
||||
Version numbers may be expressed as major.minor.extension-level, so 1.7.3\n\
|
||||
means PDF version 1.7 at extension level 3.\n\
|
||||
@ -3356,6 +3377,11 @@ static void do_inspection(QPDF& pdf, Options& o)
|
||||
static void handle_transformations(QPDF& pdf, Options& o)
|
||||
{
|
||||
QPDFPageDocumentHelper dh(pdf);
|
||||
if (o.generate_appearances)
|
||||
{
|
||||
QPDFAcroFormDocumentHelper afdh(pdf);
|
||||
afdh.generateAppearancesIfNeeded();
|
||||
}
|
||||
if (o.flatten_annotations)
|
||||
{
|
||||
dh.flattenAnnotations(o.flatten_annotations_required,
|
||||
|
@ -398,3 +398,7 @@ QPDFFormFieldObjectHelper checkbox kid widget 0
|
||||
QPDFObjectHandle broken radio button 0
|
||||
QPDFFormFieldObjectHelper set checkbox AS 0
|
||||
QPDFObjectHandle broken checkbox 0
|
||||
QPDFFormFieldObjectHelper list not found 0
|
||||
QPDFFormFieldObjectHelper list found 0
|
||||
QPDFFormFieldObjectHelper list first too low 0
|
||||
QPDFFormFieldObjectHelper list last too high 0
|
||||
|
@ -232,6 +232,57 @@ $td->runtest("compare files",
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "button-set-broken-out.pdf"});
|
||||
|
||||
show_ntests();
|
||||
# ----------
|
||||
$td->notify("--- Appearance Streams ---");
|
||||
$n_tests += 4;
|
||||
|
||||
$td->runtest("generate appearances and flatten",
|
||||
{$td->COMMAND =>
|
||||
"qpdf --qdf --no-original-object-ids --static-id" .
|
||||
" --generate-appearances --flatten-annotations=all" .
|
||||
" need-appearances.pdf a.pdf"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("compare files",
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "appearances-a.pdf"});
|
||||
|
||||
$td->runtest("more choices",
|
||||
{$td->COMMAND =>
|
||||
"qpdf --qdf --no-original-object-ids --static-id" .
|
||||
" --generate-appearances" .
|
||||
" more-choices.pdf b.pdf"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
# b.pdf still has forms
|
||||
$td->runtest("compare files",
|
||||
{$td->FILE => "b.pdf"},
|
||||
{$td->FILE => "appearances-b.pdf"});
|
||||
|
||||
my @choice_values = qw(1 2 11 12 quack);
|
||||
$n_tests += 3 * scalar(@choice_values);
|
||||
foreach my $i (@choice_values)
|
||||
{
|
||||
# b.pdf was generated by qpdf and needs appearances
|
||||
# test_driver 52 writes a.pdf
|
||||
$td->runtest("set value to $i",
|
||||
{$td->COMMAND => "test_driver 52 b.pdf $i"},
|
||||
{$td->STRING => "setting list1 value\ntest 52 done\n",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("regenerate appearances",
|
||||
{$td->COMMAND =>
|
||||
"qpdf --qdf --no-original-object-ids --static-id" .
|
||||
" --generate-appearances" .
|
||||
" a.pdf b.pdf"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("compare files",
|
||||
{$td->FILE => "b.pdf"},
|
||||
{$td->FILE => "appearances-$i.pdf"});
|
||||
}
|
||||
|
||||
show_ntests();
|
||||
# ----------
|
||||
$td->notify("--- Stream Replacement Tests ---");
|
||||
|
3853
qpdf/qtest/qpdf/appearances-1.pdf
Normal file
3853
qpdf/qtest/qpdf/appearances-1.pdf
Normal file
File diff suppressed because it is too large
Load Diff
3853
qpdf/qtest/qpdf/appearances-11.pdf
Normal file
3853
qpdf/qtest/qpdf/appearances-11.pdf
Normal file
File diff suppressed because it is too large
Load Diff
3853
qpdf/qtest/qpdf/appearances-12.pdf
Normal file
3853
qpdf/qtest/qpdf/appearances-12.pdf
Normal file
File diff suppressed because it is too large
Load Diff
3853
qpdf/qtest/qpdf/appearances-2.pdf
Normal file
3853
qpdf/qtest/qpdf/appearances-2.pdf
Normal file
File diff suppressed because it is too large
Load Diff
3278
qpdf/qtest/qpdf/appearances-a.pdf
Normal file
3278
qpdf/qtest/qpdf/appearances-a.pdf
Normal file
File diff suppressed because it is too large
Load Diff
3853
qpdf/qtest/qpdf/appearances-b.pdf
Normal file
3853
qpdf/qtest/qpdf/appearances-b.pdf
Normal file
File diff suppressed because it is too large
Load Diff
3853
qpdf/qtest/qpdf/appearances-quack.pdf
Normal file
3853
qpdf/qtest/qpdf/appearances-quack.pdf
Normal file
File diff suppressed because it is too large
Load Diff
@ -321,7 +321,7 @@
|
||||
"parent": null,
|
||||
"partialname": "list1",
|
||||
"quadding": 0,
|
||||
"value": "five"
|
||||
"value": "six"
|
||||
},
|
||||
{
|
||||
"alternativename": "drop1",
|
||||
|
3788
qpdf/qtest/qpdf/more-choices.pdf
Normal file
3788
qpdf/qtest/qpdf/more-choices.pdf
Normal file
File diff suppressed because it is too large
Load Diff
@ -273,7 +273,7 @@ endobj
|
||||
/Subtype /Widget
|
||||
/T (list1)
|
||||
/Type /Annot
|
||||
/V <feff0066006900760065>
|
||||
/V <feff007300690078>
|
||||
>>
|
||||
endobj
|
||||
|
||||
@ -3617,199 +3617,199 @@ xref
|
||||
0000002295 00000 n
|
||||
0000002426 00000 n
|
||||
0000002780 00000 n
|
||||
0000003211 00000 n
|
||||
0000003687 00000 n
|
||||
0000004108 00000 n
|
||||
0000004579 00000 n
|
||||
0000005130 00000 n
|
||||
0000005204 00000 n
|
||||
0000005354 00000 n
|
||||
0000005444 00000 n
|
||||
0000005611 00000 n
|
||||
0000005631 00000 n
|
||||
0000005995 00000 n
|
||||
0000006361 00000 n
|
||||
0000006727 00000 n
|
||||
0000006895 00000 n
|
||||
0000006915 00000 n
|
||||
0000007153 00000 n
|
||||
0000007173 00000 n
|
||||
0000007254 00000 n
|
||||
0000007422 00000 n
|
||||
0000007442 00000 n
|
||||
0000007680 00000 n
|
||||
0000007700 00000 n
|
||||
0000007868 00000 n
|
||||
0000007888 00000 n
|
||||
0000008126 00000 n
|
||||
0000008146 00000 n
|
||||
0000008512 00000 n
|
||||
0000008876 00000 n
|
||||
0000009242 00000 n
|
||||
0000009411 00000 n
|
||||
0000009431 00000 n
|
||||
0000009632 00000 n
|
||||
0000009652 00000 n
|
||||
0000009853 00000 n
|
||||
0000009873 00000 n
|
||||
0000010076 00000 n
|
||||
0000010096 00000 n
|
||||
0000010295 00000 n
|
||||
0000010315 00000 n
|
||||
0000010479 00000 n
|
||||
0000010538 00000 n
|
||||
0000010580 00000 n
|
||||
0000015406 00000 n
|
||||
0000015451 00000 n
|
||||
0000015579 00000 n
|
||||
0000015599 00000 n
|
||||
0000016822 00000 n
|
||||
0000016843 00000 n
|
||||
0000017635 00000 n
|
||||
0000018037 00000 n
|
||||
0000018488 00000 n
|
||||
0000020405 00000 n
|
||||
0000020775 00000 n
|
||||
0000022689 00000 n
|
||||
0000023065 00000 n
|
||||
0000023086 00000 n
|
||||
0000023254 00000 n
|
||||
0000023274 00000 n
|
||||
0000023650 00000 n
|
||||
0000023671 00000 n
|
||||
0000023839 00000 n
|
||||
0000023859 00000 n
|
||||
0000024235 00000 n
|
||||
0000024256 00000 n
|
||||
0000024424 00000 n
|
||||
0000024444 00000 n
|
||||
0000024820 00000 n
|
||||
0000024841 00000 n
|
||||
0000025009 00000 n
|
||||
0000025029 00000 n
|
||||
0000025405 00000 n
|
||||
0000025426 00000 n
|
||||
0000025594 00000 n
|
||||
0000025614 00000 n
|
||||
0000025990 00000 n
|
||||
0000026011 00000 n
|
||||
0000026179 00000 n
|
||||
0000026199 00000 n
|
||||
0000026531 00000 n
|
||||
0000026644 00000 n
|
||||
0000026740 00000 n
|
||||
0000026853 00000 n
|
||||
0000026949 00000 n
|
||||
0000027062 00000 n
|
||||
0000027158 00000 n
|
||||
0000027254 00000 n
|
||||
0000027350 00000 n
|
||||
0000027446 00000 n
|
||||
0000027542 00000 n
|
||||
0000027639 00000 n
|
||||
0000027753 00000 n
|
||||
0000027850 00000 n
|
||||
0000027947 00000 n
|
||||
0000028044 00000 n
|
||||
0000028141 00000 n
|
||||
0000028238 00000 n
|
||||
0000028335 00000 n
|
||||
0000028432 00000 n
|
||||
0000028529 00000 n
|
||||
0000028626 00000 n
|
||||
0000028723 00000 n
|
||||
0000028837 00000 n
|
||||
0000028934 00000 n
|
||||
0000029031 00000 n
|
||||
0000029128 00000 n
|
||||
0000029225 00000 n
|
||||
0000029322 00000 n
|
||||
0000029419 00000 n
|
||||
0000029516 00000 n
|
||||
0000029613 00000 n
|
||||
0000029710 00000 n
|
||||
0000029807 00000 n
|
||||
0000029921 00000 n
|
||||
0000030018 00000 n
|
||||
0000030115 00000 n
|
||||
0000030212 00000 n
|
||||
0000030332 00000 n
|
||||
0000030429 00000 n
|
||||
0000030526 00000 n
|
||||
0000030623 00000 n
|
||||
0000030720 00000 n
|
||||
0000030817 00000 n
|
||||
0000030937 00000 n
|
||||
0000031035 00000 n
|
||||
0000031133 00000 n
|
||||
0000031231 00000 n
|
||||
0000031329 00000 n
|
||||
0000031427 00000 n
|
||||
0000031525 00000 n
|
||||
0000031623 00000 n
|
||||
0000031721 00000 n
|
||||
0000031819 00000 n
|
||||
0000031917 00000 n
|
||||
0000032015 00000 n
|
||||
0000032113 00000 n
|
||||
0000032211 00000 n
|
||||
0000032309 00000 n
|
||||
0000032407 00000 n
|
||||
0000032652 00000 n
|
||||
0000033413 00000 n
|
||||
0000033435 00000 n
|
||||
0000033651 00000 n
|
||||
0000033895 00000 n
|
||||
0000034536 00000 n
|
||||
0000034558 00000 n
|
||||
0000034773 00000 n
|
||||
0000034830 00000 n
|
||||
0000034887 00000 n
|
||||
0000034944 00000 n
|
||||
0000035001 00000 n
|
||||
0000035058 00000 n
|
||||
0000035115 00000 n
|
||||
0000035172 00000 n
|
||||
0000035229 00000 n
|
||||
0000035286 00000 n
|
||||
0000035343 00000 n
|
||||
0000035400 00000 n
|
||||
0000035457 00000 n
|
||||
0000035514 00000 n
|
||||
0000035571 00000 n
|
||||
0000035628 00000 n
|
||||
0000035685 00000 n
|
||||
0000035742 00000 n
|
||||
0000035799 00000 n
|
||||
0000035856 00000 n
|
||||
0000035913 00000 n
|
||||
0000035970 00000 n
|
||||
0000036027 00000 n
|
||||
0000036084 00000 n
|
||||
0000036141 00000 n
|
||||
0000036198 00000 n
|
||||
0000036255 00000 n
|
||||
0000036312 00000 n
|
||||
0000036369 00000 n
|
||||
0000036426 00000 n
|
||||
0000036483 00000 n
|
||||
0000036540 00000 n
|
||||
0000036597 00000 n
|
||||
0000036654 00000 n
|
||||
0000036711 00000 n
|
||||
0000036768 00000 n
|
||||
0000036825 00000 n
|
||||
0000036882 00000 n
|
||||
0000036939 00000 n
|
||||
0000036996 00000 n
|
||||
0000037053 00000 n
|
||||
0000037110 00000 n
|
||||
0000037167 00000 n
|
||||
0000037224 00000 n
|
||||
0000037281 00000 n
|
||||
0000053563 00000 n
|
||||
0000053587 00000 n
|
||||
0000064773 00000 n
|
||||
0000003207 00000 n
|
||||
0000003683 00000 n
|
||||
0000004104 00000 n
|
||||
0000004575 00000 n
|
||||
0000005126 00000 n
|
||||
0000005200 00000 n
|
||||
0000005350 00000 n
|
||||
0000005440 00000 n
|
||||
0000005607 00000 n
|
||||
0000005627 00000 n
|
||||
0000005991 00000 n
|
||||
0000006357 00000 n
|
||||
0000006723 00000 n
|
||||
0000006891 00000 n
|
||||
0000006911 00000 n
|
||||
0000007149 00000 n
|
||||
0000007169 00000 n
|
||||
0000007250 00000 n
|
||||
0000007418 00000 n
|
||||
0000007438 00000 n
|
||||
0000007676 00000 n
|
||||
0000007696 00000 n
|
||||
0000007864 00000 n
|
||||
0000007884 00000 n
|
||||
0000008122 00000 n
|
||||
0000008142 00000 n
|
||||
0000008508 00000 n
|
||||
0000008872 00000 n
|
||||
0000009238 00000 n
|
||||
0000009407 00000 n
|
||||
0000009427 00000 n
|
||||
0000009628 00000 n
|
||||
0000009648 00000 n
|
||||
0000009849 00000 n
|
||||
0000009869 00000 n
|
||||
0000010072 00000 n
|
||||
0000010092 00000 n
|
||||
0000010291 00000 n
|
||||
0000010311 00000 n
|
||||
0000010475 00000 n
|
||||
0000010534 00000 n
|
||||
0000010576 00000 n
|
||||
0000015402 00000 n
|
||||
0000015447 00000 n
|
||||
0000015575 00000 n
|
||||
0000015595 00000 n
|
||||
0000016818 00000 n
|
||||
0000016839 00000 n
|
||||
0000017631 00000 n
|
||||
0000018033 00000 n
|
||||
0000018484 00000 n
|
||||
0000020401 00000 n
|
||||
0000020771 00000 n
|
||||
0000022685 00000 n
|
||||
0000023061 00000 n
|
||||
0000023082 00000 n
|
||||
0000023250 00000 n
|
||||
0000023270 00000 n
|
||||
0000023646 00000 n
|
||||
0000023667 00000 n
|
||||
0000023835 00000 n
|
||||
0000023855 00000 n
|
||||
0000024231 00000 n
|
||||
0000024252 00000 n
|
||||
0000024420 00000 n
|
||||
0000024440 00000 n
|
||||
0000024816 00000 n
|
||||
0000024837 00000 n
|
||||
0000025005 00000 n
|
||||
0000025025 00000 n
|
||||
0000025401 00000 n
|
||||
0000025422 00000 n
|
||||
0000025590 00000 n
|
||||
0000025610 00000 n
|
||||
0000025986 00000 n
|
||||
0000026007 00000 n
|
||||
0000026175 00000 n
|
||||
0000026195 00000 n
|
||||
0000026527 00000 n
|
||||
0000026640 00000 n
|
||||
0000026736 00000 n
|
||||
0000026849 00000 n
|
||||
0000026945 00000 n
|
||||
0000027058 00000 n
|
||||
0000027154 00000 n
|
||||
0000027250 00000 n
|
||||
0000027346 00000 n
|
||||
0000027442 00000 n
|
||||
0000027538 00000 n
|
||||
0000027635 00000 n
|
||||
0000027749 00000 n
|
||||
0000027846 00000 n
|
||||
0000027943 00000 n
|
||||
0000028040 00000 n
|
||||
0000028137 00000 n
|
||||
0000028234 00000 n
|
||||
0000028331 00000 n
|
||||
0000028428 00000 n
|
||||
0000028525 00000 n
|
||||
0000028622 00000 n
|
||||
0000028719 00000 n
|
||||
0000028833 00000 n
|
||||
0000028930 00000 n
|
||||
0000029027 00000 n
|
||||
0000029124 00000 n
|
||||
0000029221 00000 n
|
||||
0000029318 00000 n
|
||||
0000029415 00000 n
|
||||
0000029512 00000 n
|
||||
0000029609 00000 n
|
||||
0000029706 00000 n
|
||||
0000029803 00000 n
|
||||
0000029917 00000 n
|
||||
0000030014 00000 n
|
||||
0000030111 00000 n
|
||||
0000030208 00000 n
|
||||
0000030328 00000 n
|
||||
0000030425 00000 n
|
||||
0000030522 00000 n
|
||||
0000030619 00000 n
|
||||
0000030716 00000 n
|
||||
0000030813 00000 n
|
||||
0000030933 00000 n
|
||||
0000031031 00000 n
|
||||
0000031129 00000 n
|
||||
0000031227 00000 n
|
||||
0000031325 00000 n
|
||||
0000031423 00000 n
|
||||
0000031521 00000 n
|
||||
0000031619 00000 n
|
||||
0000031717 00000 n
|
||||
0000031815 00000 n
|
||||
0000031913 00000 n
|
||||
0000032011 00000 n
|
||||
0000032109 00000 n
|
||||
0000032207 00000 n
|
||||
0000032305 00000 n
|
||||
0000032403 00000 n
|
||||
0000032648 00000 n
|
||||
0000033409 00000 n
|
||||
0000033431 00000 n
|
||||
0000033647 00000 n
|
||||
0000033891 00000 n
|
||||
0000034532 00000 n
|
||||
0000034554 00000 n
|
||||
0000034769 00000 n
|
||||
0000034826 00000 n
|
||||
0000034883 00000 n
|
||||
0000034940 00000 n
|
||||
0000034997 00000 n
|
||||
0000035054 00000 n
|
||||
0000035111 00000 n
|
||||
0000035168 00000 n
|
||||
0000035225 00000 n
|
||||
0000035282 00000 n
|
||||
0000035339 00000 n
|
||||
0000035396 00000 n
|
||||
0000035453 00000 n
|
||||
0000035510 00000 n
|
||||
0000035567 00000 n
|
||||
0000035624 00000 n
|
||||
0000035681 00000 n
|
||||
0000035738 00000 n
|
||||
0000035795 00000 n
|
||||
0000035852 00000 n
|
||||
0000035909 00000 n
|
||||
0000035966 00000 n
|
||||
0000036023 00000 n
|
||||
0000036080 00000 n
|
||||
0000036137 00000 n
|
||||
0000036194 00000 n
|
||||
0000036251 00000 n
|
||||
0000036308 00000 n
|
||||
0000036365 00000 n
|
||||
0000036422 00000 n
|
||||
0000036479 00000 n
|
||||
0000036536 00000 n
|
||||
0000036593 00000 n
|
||||
0000036650 00000 n
|
||||
0000036707 00000 n
|
||||
0000036764 00000 n
|
||||
0000036821 00000 n
|
||||
0000036878 00000 n
|
||||
0000036935 00000 n
|
||||
0000036992 00000 n
|
||||
0000037049 00000 n
|
||||
0000037106 00000 n
|
||||
0000037163 00000 n
|
||||
0000037220 00000 n
|
||||
0000037277 00000 n
|
||||
0000053559 00000 n
|
||||
0000053583 00000 n
|
||||
0000064769 00000 n
|
||||
trailer <<
|
||||
/DocChecksum /CC322E136FE95DECF8BC297B1A9B2C2E
|
||||
/Info 2 0 R
|
||||
@ -3818,5 +3818,5 @@ trailer <<
|
||||
/ID [<f8abc47bb1df544a0df9c15a75ef0046><31415926535897932384626433832795>]
|
||||
>>
|
||||
startxref
|
||||
64797
|
||||
64793
|
||||
%%EOF
|
||||
|
@ -273,7 +273,7 @@ endobj
|
||||
/Subtype /Widget
|
||||
/T (list1)
|
||||
/Type /Annot
|
||||
/V <feff0066006900760065>
|
||||
/V <feff007300690078>
|
||||
>>
|
||||
endobj
|
||||
|
||||
@ -3579,195 +3579,195 @@ xref
|
||||
0000002295 00000 n
|
||||
0000002426 00000 n
|
||||
0000002780 00000 n
|
||||
0000003211 00000 n
|
||||
0000003687 00000 n
|
||||
0000004108 00000 n
|
||||
0000004579 00000 n
|
||||
0000005006 00000 n
|
||||
0000005145 00000 n
|
||||
0000005295 00000 n
|
||||
0000005385 00000 n
|
||||
0000005552 00000 n
|
||||
0000005572 00000 n
|
||||
0000005936 00000 n
|
||||
0000006302 00000 n
|
||||
0000006668 00000 n
|
||||
0000006836 00000 n
|
||||
0000006856 00000 n
|
||||
0000007094 00000 n
|
||||
0000007114 00000 n
|
||||
0000007195 00000 n
|
||||
0000007363 00000 n
|
||||
0000007383 00000 n
|
||||
0000007621 00000 n
|
||||
0000007641 00000 n
|
||||
0000007809 00000 n
|
||||
0000007829 00000 n
|
||||
0000008067 00000 n
|
||||
0000008087 00000 n
|
||||
0000008453 00000 n
|
||||
0000008817 00000 n
|
||||
0000009183 00000 n
|
||||
0000009352 00000 n
|
||||
0000009372 00000 n
|
||||
0000009573 00000 n
|
||||
0000009593 00000 n
|
||||
0000009794 00000 n
|
||||
0000009814 00000 n
|
||||
0000010017 00000 n
|
||||
0000010037 00000 n
|
||||
0000010236 00000 n
|
||||
0000010279 00000 n
|
||||
0000015105 00000 n
|
||||
0000015127 00000 n
|
||||
0000015911 00000 n
|
||||
0000016312 00000 n
|
||||
0000016763 00000 n
|
||||
0000018680 00000 n
|
||||
0000019050 00000 n
|
||||
0000020964 00000 n
|
||||
0000021340 00000 n
|
||||
0000021361 00000 n
|
||||
0000021529 00000 n
|
||||
0000021549 00000 n
|
||||
0000021925 00000 n
|
||||
0000021946 00000 n
|
||||
0000022114 00000 n
|
||||
0000022134 00000 n
|
||||
0000022510 00000 n
|
||||
0000022531 00000 n
|
||||
0000022699 00000 n
|
||||
0000022719 00000 n
|
||||
0000023095 00000 n
|
||||
0000023116 00000 n
|
||||
0000023284 00000 n
|
||||
0000023304 00000 n
|
||||
0000023680 00000 n
|
||||
0000023701 00000 n
|
||||
0000023869 00000 n
|
||||
0000023889 00000 n
|
||||
0000024265 00000 n
|
||||
0000024286 00000 n
|
||||
0000024454 00000 n
|
||||
0000024474 00000 n
|
||||
0000024587 00000 n
|
||||
0000024683 00000 n
|
||||
0000024796 00000 n
|
||||
0000024892 00000 n
|
||||
0000025005 00000 n
|
||||
0000025101 00000 n
|
||||
0000025197 00000 n
|
||||
0000025293 00000 n
|
||||
0000025389 00000 n
|
||||
0000025485 00000 n
|
||||
0000025581 00000 n
|
||||
0000025694 00000 n
|
||||
0000025790 00000 n
|
||||
0000025886 00000 n
|
||||
0000025982 00000 n
|
||||
0000026078 00000 n
|
||||
0000026174 00000 n
|
||||
0000026270 00000 n
|
||||
0000026367 00000 n
|
||||
0000026464 00000 n
|
||||
0000026561 00000 n
|
||||
0000026658 00000 n
|
||||
0000026772 00000 n
|
||||
0000026869 00000 n
|
||||
0000026966 00000 n
|
||||
0000027063 00000 n
|
||||
0000027160 00000 n
|
||||
0000027257 00000 n
|
||||
0000027354 00000 n
|
||||
0000027451 00000 n
|
||||
0000027548 00000 n
|
||||
0000027645 00000 n
|
||||
0000027742 00000 n
|
||||
0000027856 00000 n
|
||||
0000027953 00000 n
|
||||
0000028050 00000 n
|
||||
0000028147 00000 n
|
||||
0000028267 00000 n
|
||||
0000028364 00000 n
|
||||
0000028461 00000 n
|
||||
0000028558 00000 n
|
||||
0000028655 00000 n
|
||||
0000028752 00000 n
|
||||
0000028872 00000 n
|
||||
0000028970 00000 n
|
||||
0000029068 00000 n
|
||||
0000029166 00000 n
|
||||
0000029264 00000 n
|
||||
0000029362 00000 n
|
||||
0000029460 00000 n
|
||||
0000029558 00000 n
|
||||
0000029656 00000 n
|
||||
0000029754 00000 n
|
||||
0000029852 00000 n
|
||||
0000029950 00000 n
|
||||
0000030048 00000 n
|
||||
0000030146 00000 n
|
||||
0000030244 00000 n
|
||||
0000030342 00000 n
|
||||
0000030587 00000 n
|
||||
0000031348 00000 n
|
||||
0000031370 00000 n
|
||||
0000031586 00000 n
|
||||
0000031830 00000 n
|
||||
0000032471 00000 n
|
||||
0000032493 00000 n
|
||||
0000032708 00000 n
|
||||
0000032765 00000 n
|
||||
0000032822 00000 n
|
||||
0000032879 00000 n
|
||||
0000032936 00000 n
|
||||
0000032993 00000 n
|
||||
0000033050 00000 n
|
||||
0000033107 00000 n
|
||||
0000033164 00000 n
|
||||
0000033221 00000 n
|
||||
0000033278 00000 n
|
||||
0000033335 00000 n
|
||||
0000033392 00000 n
|
||||
0000033449 00000 n
|
||||
0000033506 00000 n
|
||||
0000033563 00000 n
|
||||
0000033620 00000 n
|
||||
0000033677 00000 n
|
||||
0000033734 00000 n
|
||||
0000033791 00000 n
|
||||
0000033848 00000 n
|
||||
0000033905 00000 n
|
||||
0000033962 00000 n
|
||||
0000034019 00000 n
|
||||
0000034076 00000 n
|
||||
0000034133 00000 n
|
||||
0000034190 00000 n
|
||||
0000034247 00000 n
|
||||
0000034304 00000 n
|
||||
0000034361 00000 n
|
||||
0000034418 00000 n
|
||||
0000034475 00000 n
|
||||
0000034532 00000 n
|
||||
0000034589 00000 n
|
||||
0000034646 00000 n
|
||||
0000034703 00000 n
|
||||
0000034760 00000 n
|
||||
0000034817 00000 n
|
||||
0000034874 00000 n
|
||||
0000034931 00000 n
|
||||
0000034988 00000 n
|
||||
0000035045 00000 n
|
||||
0000035102 00000 n
|
||||
0000035159 00000 n
|
||||
0000035216 00000 n
|
||||
0000051498 00000 n
|
||||
0000051522 00000 n
|
||||
0000062708 00000 n
|
||||
0000062732 00000 n
|
||||
0000063067 00000 n
|
||||
0000063210 00000 n
|
||||
0000064435 00000 n
|
||||
0000003207 00000 n
|
||||
0000003683 00000 n
|
||||
0000004104 00000 n
|
||||
0000004575 00000 n
|
||||
0000005002 00000 n
|
||||
0000005141 00000 n
|
||||
0000005291 00000 n
|
||||
0000005381 00000 n
|
||||
0000005548 00000 n
|
||||
0000005568 00000 n
|
||||
0000005932 00000 n
|
||||
0000006298 00000 n
|
||||
0000006664 00000 n
|
||||
0000006832 00000 n
|
||||
0000006852 00000 n
|
||||
0000007090 00000 n
|
||||
0000007110 00000 n
|
||||
0000007191 00000 n
|
||||
0000007359 00000 n
|
||||
0000007379 00000 n
|
||||
0000007617 00000 n
|
||||
0000007637 00000 n
|
||||
0000007805 00000 n
|
||||
0000007825 00000 n
|
||||
0000008063 00000 n
|
||||
0000008083 00000 n
|
||||
0000008449 00000 n
|
||||
0000008813 00000 n
|
||||
0000009179 00000 n
|
||||
0000009348 00000 n
|
||||
0000009368 00000 n
|
||||
0000009569 00000 n
|
||||
0000009589 00000 n
|
||||
0000009790 00000 n
|
||||
0000009810 00000 n
|
||||
0000010013 00000 n
|
||||
0000010033 00000 n
|
||||
0000010232 00000 n
|
||||
0000010275 00000 n
|
||||
0000015101 00000 n
|
||||
0000015123 00000 n
|
||||
0000015907 00000 n
|
||||
0000016308 00000 n
|
||||
0000016759 00000 n
|
||||
0000018676 00000 n
|
||||
0000019046 00000 n
|
||||
0000020960 00000 n
|
||||
0000021336 00000 n
|
||||
0000021357 00000 n
|
||||
0000021525 00000 n
|
||||
0000021545 00000 n
|
||||
0000021921 00000 n
|
||||
0000021942 00000 n
|
||||
0000022110 00000 n
|
||||
0000022130 00000 n
|
||||
0000022506 00000 n
|
||||
0000022527 00000 n
|
||||
0000022695 00000 n
|
||||
0000022715 00000 n
|
||||
0000023091 00000 n
|
||||
0000023112 00000 n
|
||||
0000023280 00000 n
|
||||
0000023300 00000 n
|
||||
0000023676 00000 n
|
||||
0000023697 00000 n
|
||||
0000023865 00000 n
|
||||
0000023885 00000 n
|
||||
0000024261 00000 n
|
||||
0000024282 00000 n
|
||||
0000024450 00000 n
|
||||
0000024470 00000 n
|
||||
0000024583 00000 n
|
||||
0000024679 00000 n
|
||||
0000024792 00000 n
|
||||
0000024888 00000 n
|
||||
0000025001 00000 n
|
||||
0000025097 00000 n
|
||||
0000025193 00000 n
|
||||
0000025289 00000 n
|
||||
0000025385 00000 n
|
||||
0000025481 00000 n
|
||||
0000025577 00000 n
|
||||
0000025690 00000 n
|
||||
0000025786 00000 n
|
||||
0000025882 00000 n
|
||||
0000025978 00000 n
|
||||
0000026074 00000 n
|
||||
0000026170 00000 n
|
||||
0000026266 00000 n
|
||||
0000026363 00000 n
|
||||
0000026460 00000 n
|
||||
0000026557 00000 n
|
||||
0000026654 00000 n
|
||||
0000026768 00000 n
|
||||
0000026865 00000 n
|
||||
0000026962 00000 n
|
||||
0000027059 00000 n
|
||||
0000027156 00000 n
|
||||
0000027253 00000 n
|
||||
0000027350 00000 n
|
||||
0000027447 00000 n
|
||||
0000027544 00000 n
|
||||
0000027641 00000 n
|
||||
0000027738 00000 n
|
||||
0000027852 00000 n
|
||||
0000027949 00000 n
|
||||
0000028046 00000 n
|
||||
0000028143 00000 n
|
||||
0000028263 00000 n
|
||||
0000028360 00000 n
|
||||
0000028457 00000 n
|
||||
0000028554 00000 n
|
||||
0000028651 00000 n
|
||||
0000028748 00000 n
|
||||
0000028868 00000 n
|
||||
0000028966 00000 n
|
||||
0000029064 00000 n
|
||||
0000029162 00000 n
|
||||
0000029260 00000 n
|
||||
0000029358 00000 n
|
||||
0000029456 00000 n
|
||||
0000029554 00000 n
|
||||
0000029652 00000 n
|
||||
0000029750 00000 n
|
||||
0000029848 00000 n
|
||||
0000029946 00000 n
|
||||
0000030044 00000 n
|
||||
0000030142 00000 n
|
||||
0000030240 00000 n
|
||||
0000030338 00000 n
|
||||
0000030583 00000 n
|
||||
0000031344 00000 n
|
||||
0000031366 00000 n
|
||||
0000031582 00000 n
|
||||
0000031826 00000 n
|
||||
0000032467 00000 n
|
||||
0000032489 00000 n
|
||||
0000032704 00000 n
|
||||
0000032761 00000 n
|
||||
0000032818 00000 n
|
||||
0000032875 00000 n
|
||||
0000032932 00000 n
|
||||
0000032989 00000 n
|
||||
0000033046 00000 n
|
||||
0000033103 00000 n
|
||||
0000033160 00000 n
|
||||
0000033217 00000 n
|
||||
0000033274 00000 n
|
||||
0000033331 00000 n
|
||||
0000033388 00000 n
|
||||
0000033445 00000 n
|
||||
0000033502 00000 n
|
||||
0000033559 00000 n
|
||||
0000033616 00000 n
|
||||
0000033673 00000 n
|
||||
0000033730 00000 n
|
||||
0000033787 00000 n
|
||||
0000033844 00000 n
|
||||
0000033901 00000 n
|
||||
0000033958 00000 n
|
||||
0000034015 00000 n
|
||||
0000034072 00000 n
|
||||
0000034129 00000 n
|
||||
0000034186 00000 n
|
||||
0000034243 00000 n
|
||||
0000034300 00000 n
|
||||
0000034357 00000 n
|
||||
0000034414 00000 n
|
||||
0000034471 00000 n
|
||||
0000034528 00000 n
|
||||
0000034585 00000 n
|
||||
0000034642 00000 n
|
||||
0000034699 00000 n
|
||||
0000034756 00000 n
|
||||
0000034813 00000 n
|
||||
0000034870 00000 n
|
||||
0000034927 00000 n
|
||||
0000034984 00000 n
|
||||
0000035041 00000 n
|
||||
0000035098 00000 n
|
||||
0000035155 00000 n
|
||||
0000035212 00000 n
|
||||
0000051494 00000 n
|
||||
0000051518 00000 n
|
||||
0000062704 00000 n
|
||||
0000062728 00000 n
|
||||
0000063063 00000 n
|
||||
0000063206 00000 n
|
||||
0000064431 00000 n
|
||||
trailer <<
|
||||
/DocChecksum /CC322E136FE95DECF8BC297B1A9B2C2E
|
||||
/Info 2 0 R
|
||||
@ -3776,5 +3776,5 @@ trailer <<
|
||||
/ID [<f8abc47bb1df544a0df9c15a75ef0046><45201f7a345625a01ccb53b240a8ba8d>]
|
||||
>>
|
||||
startxref
|
||||
64457
|
||||
64453
|
||||
%%EOF
|
||||
|
@ -1820,6 +1820,32 @@ void runtest(int n, char const* filename1, char const* arg2)
|
||||
w.setStaticID(true);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 52)
|
||||
{
|
||||
// This test just sets a field value for appearance stream
|
||||
// generating testing.
|
||||
QPDFObjectHandle acroform = pdf.getRoot().getKey("/AcroForm");
|
||||
QPDFObjectHandle fields = acroform.getKey("/Fields");
|
||||
int n = fields.getArrayNItems();
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
QPDFObjectHandle field = fields.getArrayItem(i);
|
||||
QPDFObjectHandle T = field.getKey("/T");
|
||||
if (! T.isString())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
std::string Tval = T.getUTF8Value();
|
||||
if (Tval == "list1")
|
||||
{
|
||||
std::cout << "setting list1 value\n";
|
||||
QPDFFormFieldObjectHelper foh(field);
|
||||
foh.setV(QPDFObjectHandle::newString(arg2));
|
||||
}
|
||||
}
|
||||
QPDFWriter w(pdf, "a.pdf");
|
||||
w.write();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error(std::string("invalid test ") +
|
||||
|
Loading…
Reference in New Issue
Block a user