mirror of https://github.com/qpdf/qpdf.git
Implement helper class for interactive forms
This commit is contained in:
parent
0dadf17ab7
commit
0b05111db8
17
ChangeLog
17
ChangeLog
|
@ -1,5 +1,22 @@
|
|||
2018-06-20 Jay Berkenbilt <ejb@ql.org>
|
||||
|
||||
* Added new classes QPDFAcroFormDocumentHelper,
|
||||
QPDFFormFieldObjectHelper, and QPDFAnnotationObjectHelper to
|
||||
assist with working with interactive forms in PDF files. At
|
||||
present, API methods for reading forms, form fields, and widget
|
||||
annotations have been added. It is likely that some additional
|
||||
methods for modifying forms will be added in the future. Note that
|
||||
qpdf remains a library whose function is primarily focused around
|
||||
document structure and metadata rather than content. As such, it
|
||||
is not expected that qpdf will have higher level APIs for
|
||||
generating form contents, but qpdf will hopefully gain the
|
||||
capability to deal with the bookkeeping aspects of wiring up all
|
||||
the objects, which could make it a useful library for other
|
||||
software that works with PDF interactive forms. PDF forms are
|
||||
complex, and the terminology around them is confusing. Please see
|
||||
comments at the top of QPDFAcroFormDocumentHelper.hh for
|
||||
additional discussion.
|
||||
|
||||
* Added new classes QPDFPageDocumentHelper and QPDFPageObjctHelper
|
||||
for page-level API functions. These classes introduce a new API
|
||||
pattern of document helpers and object helpers in qpdf. The helper
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
// Copyright (c) 2005-2018 Jay Berkenbilt
|
||||
//
|
||||
// This file is part of qpdf.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Versions of qpdf prior to version 7 were released under the terms
|
||||
// of version 2.0 of the Artistic License. At your option, you may
|
||||
// continue to consider qpdf to be licensed under those terms. Please
|
||||
// see the manual for additional information.
|
||||
|
||||
#ifndef __QPDFACROFORMDOCUMENTHELPER_HH__
|
||||
#define __QPDFACROFORMDOCUMENTHELPER_HH__
|
||||
|
||||
// This document helper is intended to help with operations on
|
||||
// interactive forms. Here are the key things to know:
|
||||
|
||||
// * The PDF specification talks about interactive forms and also
|
||||
// about form XObjects. While form XObjects appear in parts of
|
||||
// interactive forms, this class is concerned about interactive
|
||||
// forms, not form XObjects.
|
||||
//
|
||||
// * Interactive forms are discussed in the PDF Specification (ISO PDF
|
||||
// 32000-1:2008) section 12.7. Also relevant is the section about
|
||||
// Widget annotations. Annotations are discussed in section 12.5
|
||||
// with annotation dictionaries discussed in 12.5.1. Widget
|
||||
// annotations are discussed specifically in section 12.5.6.19.
|
||||
//
|
||||
// * What you need to know about the structure of interactive forms in
|
||||
// PDF files:
|
||||
//
|
||||
// - The document catalog contains the key "/AcroForm" which
|
||||
// contains a list of fields. Fields are represented as a tree
|
||||
// structure much like pages. Nodes in the fields tree may contain
|
||||
// other fields. Fields may inherit values of many of their
|
||||
// attributes from ancestors in the tree.
|
||||
//
|
||||
// - Fields may also have children that are widget annotations. As a
|
||||
// special case, and a cause of considerable confusion, if a field
|
||||
// has a single annotation as a child, the annotation dictionary
|
||||
// may be merged with the field dictionary. In that case, the
|
||||
// field and the annotation are in the same object. Note that,
|
||||
// while field dictionary attributes are inherited, annotation
|
||||
// dictionary attributes are not.
|
||||
//
|
||||
// - A page dictionary contains a key called "/Annots" which
|
||||
// contains a simple list of annotations. For any given annotation
|
||||
// of subtype "/Widget", you should encounter that annotation in
|
||||
// the "/Annots" dictionary of a page, and you should also be able
|
||||
// to reach it by traversing through the "/AcroForm" dictionary
|
||||
// from the document catalog. In the simplest case (and also a
|
||||
// very common case), a form field's widget annotation will be
|
||||
// merged with the field object, and the object will appear
|
||||
// directly both under "/Annots" in the page dictionary and under
|
||||
// "/Fields" in the "/AcroForm" dictionary. In a more complex
|
||||
// case, you may have to trace through various "/Kids" elements in
|
||||
// the "/AcroForm" field entry until you find the annotation
|
||||
// dictionary.
|
||||
|
||||
|
||||
#include <qpdf/QPDFDocumentHelper.hh>
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
#include <qpdf/QPDFAnnotationObjectHelper.hh>
|
||||
#include <qpdf/QPDFFormFieldObjectHelper.hh>
|
||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper
|
||||
{
|
||||
public:
|
||||
QPDFAcroFormDocumentHelper(QPDF&);
|
||||
|
||||
// This class lazily creates an internal cache of the mapping
|
||||
// among form fields, annotations, and pages. Methods within this
|
||||
// class preserve the validity of this cache. However, if you
|
||||
// modify pages' annotation dictionaries, the document's /AcroForm
|
||||
// dictionary, or any form fields manually in a way that alters
|
||||
// the association between forms, fields, annotations, and pages,
|
||||
// it may cause this cache to become invalid. This method marks
|
||||
// the cache invalid and forces it to be regenerated the next time
|
||||
// it is needed.
|
||||
QPDF_DLL
|
||||
void invalidateCache();
|
||||
|
||||
QPDF_DLL
|
||||
bool
|
||||
hasAcroForm();
|
||||
|
||||
// Return a vector of all terminal fields in a document. Terminal
|
||||
// fields are fields that have no children that are also fields.
|
||||
// Terminal fields may still have children that are annotations.
|
||||
// Intermediate nodes in the fields tree are not included in this
|
||||
// list, but you can still reach them through the getParent method
|
||||
// of the field object helper.
|
||||
QPDF_DLL
|
||||
std::vector<QPDFFormFieldObjectHelper>
|
||||
getFormFields();
|
||||
|
||||
// Return the annotations associated with a terminal field. Note
|
||||
// that in the case of a field having a single annotation, the
|
||||
// underlying object will typically be the same as the underlying
|
||||
// object for the field.
|
||||
QPDF_DLL
|
||||
std::vector<QPDFAnnotationObjectHelper>
|
||||
getAnnotationsForField(QPDFFormFieldObjectHelper);
|
||||
|
||||
// Return annotations of subtype /Widget for a page.
|
||||
QPDF_DLL
|
||||
std::vector<QPDFAnnotationObjectHelper>
|
||||
getWidgetAnnotationsForPage(QPDFPageObjectHelper);
|
||||
|
||||
// Return the terminal field that is associated with this
|
||||
// annotation. If the annotation dictionary is merged with the
|
||||
// field dictionary, the underlying object will be the same, but
|
||||
// this is not always the case. Note that if you call this method
|
||||
// with an annotation that is not a widget annotation, there will
|
||||
// not be an associated field, and this method will raise an
|
||||
// exception.
|
||||
QPDF_DLL
|
||||
QPDFFormFieldObjectHelper
|
||||
getFieldForAnnotation(QPDFAnnotationObjectHelper);
|
||||
|
||||
private:
|
||||
void analyze();
|
||||
void traverseField(QPDFObjectHandle field,
|
||||
QPDFObjectHandle parent,
|
||||
int depth, std::set<QPDFObjGen>& visited);
|
||||
|
||||
class Members
|
||||
{
|
||||
friend class QPDFAcroFormDocumentHelper;
|
||||
|
||||
public:
|
||||
~Members();
|
||||
|
||||
private:
|
||||
Members();
|
||||
Members(Members const&);
|
||||
|
||||
bool cache_valid;
|
||||
std::map<QPDFObjGen,
|
||||
std::vector<QPDFAnnotationObjectHelper>
|
||||
> field_to_annotations;
|
||||
std::map<QPDFObjGen, QPDFFormFieldObjectHelper> annotation_to_field;
|
||||
};
|
||||
|
||||
PointerHolder<Members> m;
|
||||
};
|
||||
|
||||
#endif // __QPDFACROFORMDOCUMENTHELPER_HH__
|
|
@ -0,0 +1,86 @@
|
|||
// Copyright (c) 2005-2018 Jay Berkenbilt
|
||||
//
|
||||
// This file is part of qpdf.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Versions of qpdf prior to version 7 were released under the terms
|
||||
// of version 2.0 of the Artistic License. At your option, you may
|
||||
// continue to consider qpdf to be licensed under those terms. Please
|
||||
// see the manual for additional information.
|
||||
|
||||
#ifndef __QPDFANNOTATIONOBJECTHELPER_HH__
|
||||
#define __QPDFANNOTATIONOBJECTHELPER_HH__
|
||||
|
||||
#include <qpdf/QPDFObjectHelper.hh>
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
class QPDFAnnotationObjectHelper: public QPDFObjectHelper
|
||||
{
|
||||
public:
|
||||
QPDFAnnotationObjectHelper(QPDFObjectHandle);
|
||||
|
||||
// This class provides helper methods for certain types of
|
||||
// annotations. At its introduction, it only supports Widget
|
||||
// annotations, but other types of annotations may be supported in
|
||||
// the future. For additional information about interactive forms,
|
||||
// please see the comments at the top of
|
||||
// QPDFAcroFormDocumentHelper.hh.
|
||||
|
||||
// Return the subtype of the annotation as a string (e.g.
|
||||
// "/Widget"). Returns the empty string if the subtype (which is
|
||||
// required by the spec) is missing.
|
||||
QPDF_DLL
|
||||
std::string getSubtype();
|
||||
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle::Rectangle getRect();
|
||||
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getAppearanceDictionary();
|
||||
|
||||
// Return the appearance state as given in "/AS", or the empty
|
||||
// string if none is given.
|
||||
QPDF_DLL
|
||||
std::string getAppearanceState();
|
||||
|
||||
// Return a specific stream. "which" may be one of "/N", "/R", or
|
||||
// "/D" to indicate the normal, rollover, or down appearance
|
||||
// stream. (Any value may be passed to "which"; if an appearance
|
||||
// stream of that name exists, it will be returned.) If the value
|
||||
// associated with "which" in the appearance dictionary is a
|
||||
// subdictionary, an appearance state may be specified to select
|
||||
// which appearance stream is desired. If not specified, the
|
||||
// appearance state in "/AS" will used.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getAppearanceStream(std::string const& which,
|
||||
std::string const& state = "");
|
||||
|
||||
private:
|
||||
class Members
|
||||
{
|
||||
friend class QPDFPageObjectHelper;
|
||||
|
||||
public:
|
||||
~Members();
|
||||
|
||||
private:
|
||||
Members();
|
||||
Members(Members const&);
|
||||
};
|
||||
|
||||
PointerHolder<Members> m;
|
||||
};
|
||||
|
||||
#endif // __QPDFANNOTATIONOBJECTHELPER_HH__
|
|
@ -0,0 +1,133 @@
|
|||
// Copyright (c) 2005-2018 Jay Berkenbilt
|
||||
//
|
||||
// This file is part of qpdf.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Versions of qpdf prior to version 7 were released under the terms
|
||||
// of version 2.0 of the Artistic License. At your option, you may
|
||||
// continue to consider qpdf to be licensed under those terms. Please
|
||||
// see the manual for additional information.
|
||||
|
||||
#ifndef __QPDFFORMFIELDOBJECTHELPER_HH__
|
||||
#define __QPDFFORMFIELDOBJECTHELPER_HH__
|
||||
|
||||
// This object helper helps with form fields for interactive forms.
|
||||
// Please see comments in QPDFAcroFormDocumentHelper.hh for additional
|
||||
// details.
|
||||
|
||||
#include <qpdf/QPDFObjectHelper.hh>
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
class QPDFFormFieldObjectHelper: public QPDFObjectHelper
|
||||
{
|
||||
public:
|
||||
QPDFFormFieldObjectHelper();
|
||||
QPDFFormFieldObjectHelper(QPDFObjectHandle);
|
||||
|
||||
QPDF_DLL
|
||||
bool isNull();
|
||||
|
||||
// Return the field's parent. A form field object helper whose
|
||||
// underlying object is null is returned if there is no parent.
|
||||
// This condition may be tested by calling isNull().
|
||||
QPDF_DLL
|
||||
QPDFFormFieldObjectHelper getParent();
|
||||
|
||||
// Get a field value, possibly inheriting the value from an
|
||||
// ancestor node.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getInheritableFieldValue(std::string const& name);
|
||||
|
||||
// Get an inherited field value as a string. If it is not a
|
||||
// string, silently return the empty string.
|
||||
QPDF_DLL
|
||||
std::string getInheritableFieldValueAsString(std::string const& name);
|
||||
|
||||
// Get an inherited field value of type name as a string
|
||||
// representing the name. If it is not a name, silently return
|
||||
// the empty string.
|
||||
QPDF_DLL
|
||||
std::string getInheritableFieldValueAsName(std::string const& name);
|
||||
|
||||
// Returns the value of /FT if present, otherwise returns the
|
||||
// empty string.
|
||||
QPDF_DLL
|
||||
std::string getFieldType();
|
||||
|
||||
QPDF_DLL
|
||||
std::string getFullyQualifiedName();
|
||||
|
||||
QPDF_DLL
|
||||
std::string getPartialName();
|
||||
|
||||
// Return the alternative field name (/TU), which is the field
|
||||
// name intended to be presented to users. If not present, fall
|
||||
// back to the fully qualified name.
|
||||
QPDF_DLL
|
||||
std::string getAlternativeName();
|
||||
|
||||
// Return the mapping field name (/TM). If not present, fall back
|
||||
// to the alternative name, then to the partial name.
|
||||
QPDF_DLL
|
||||
std::string getMappingName();
|
||||
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getValue();
|
||||
|
||||
// Return the field's value as a string. If this is called with a
|
||||
// field whose value is not a string, the empty string will be
|
||||
// silently returned.
|
||||
QPDF_DLL
|
||||
std::string getValueAsString();
|
||||
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getDefaultValue();
|
||||
|
||||
// Return the field's default value as a string. If this is called
|
||||
// with a field whose value is not a string, the empty string will
|
||||
// be silently returned.
|
||||
QPDF_DLL
|
||||
std::string getDefaultValueAsString();
|
||||
|
||||
// Return the default appearance string, taking inheritance from
|
||||
// the field tree into account. Returns the empty string if the
|
||||
// default appearance string is not available (because it's
|
||||
// erroneously absent or because this is not a variable text
|
||||
// field).
|
||||
QPDF_DLL
|
||||
std::string getDefaultAppearance();
|
||||
|
||||
// Return the quadding value, taking inheritance from the field
|
||||
// tree into account. Returns 0 if quadding is not specified.
|
||||
QPDF_DLL
|
||||
int getQuadding();
|
||||
|
||||
private:
|
||||
class Members
|
||||
{
|
||||
friend class QPDFFormFieldObjectHelper;
|
||||
|
||||
public:
|
||||
~Members();
|
||||
|
||||
private:
|
||||
Members();
|
||||
Members(Members const&);
|
||||
};
|
||||
|
||||
PointerHolder<Members> m;
|
||||
};
|
||||
|
||||
#endif // __QPDFFORMFIELDOBJECTHELPER_HH__
|
|
@ -23,6 +23,7 @@
|
|||
#define __QPDFPAGEOBJECTHELPER_HH__
|
||||
|
||||
#include <qpdf/QPDFObjectHelper.hh>
|
||||
#include <qpdf/QPDFAnnotationObjectHelper.hh>
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
|
@ -43,6 +44,13 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
|
|||
QPDF_DLL
|
||||
std::map<std::string, QPDFObjectHandle> getPageImages();
|
||||
|
||||
// Return the annotations in the page's "/Annots" list, if any. If
|
||||
// only_subtype is non-empty, only include annotations of the
|
||||
// given subtype.
|
||||
QPDF_DLL
|
||||
std::vector<QPDFAnnotationObjectHelper> getAnnotations(
|
||||
std::string const& only_subtype = "");
|
||||
|
||||
// Returns a vector of stream objects representing the content
|
||||
// streams for the given page. This routine allows the caller to
|
||||
// not care whether there are one or more than one content streams
|
||||
|
|
|
@ -0,0 +1,252 @@
|
|||
#include <qpdf/QPDFAcroFormDocumentHelper.hh>
|
||||
|
||||
#include <qpdf/QTC.hh>
|
||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||
|
||||
QPDFAcroFormDocumentHelper::Members::~Members()
|
||||
{
|
||||
}
|
||||
|
||||
QPDFAcroFormDocumentHelper::Members::Members() :
|
||||
cache_valid(false)
|
||||
{
|
||||
}
|
||||
|
||||
QPDFAcroFormDocumentHelper::QPDFAcroFormDocumentHelper(QPDF& qpdf) :
|
||||
QPDFDocumentHelper(qpdf),
|
||||
m(new Members())
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
QPDFAcroFormDocumentHelper::invalidateCache()
|
||||
{
|
||||
this->m->cache_valid = false;
|
||||
this->m->field_to_annotations.clear();
|
||||
this->m->annotation_to_field.clear();
|
||||
}
|
||||
|
||||
bool
|
||||
QPDFAcroFormDocumentHelper::hasAcroForm()
|
||||
{
|
||||
return this->qpdf.getRoot().hasKey("/AcroForm");
|
||||
}
|
||||
|
||||
std::vector<QPDFFormFieldObjectHelper>
|
||||
QPDFAcroFormDocumentHelper::getFormFields()
|
||||
{
|
||||
analyze();
|
||||
std::vector<QPDFFormFieldObjectHelper> result;
|
||||
for (std::map<QPDFObjGen,
|
||||
std::vector<QPDFAnnotationObjectHelper> >::iterator iter =
|
||||
this->m->field_to_annotations.begin();
|
||||
iter != this->m->field_to_annotations.end(); ++iter)
|
||||
{
|
||||
result.push_back(this->qpdf.getObjectByObjGen((*iter).first));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<QPDFAnnotationObjectHelper>
|
||||
QPDFAcroFormDocumentHelper::getAnnotationsForField(QPDFFormFieldObjectHelper h)
|
||||
{
|
||||
analyze();
|
||||
std::vector<QPDFAnnotationObjectHelper> result;
|
||||
QPDFObjGen og(h.getObjectHandle().getObjGen());
|
||||
if (this->m->field_to_annotations.count(og))
|
||||
{
|
||||
result = this->m->field_to_annotations[og];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<QPDFAnnotationObjectHelper>
|
||||
QPDFAcroFormDocumentHelper::getWidgetAnnotationsForPage(QPDFPageObjectHelper h)
|
||||
{
|
||||
return h.getAnnotations("/Widget");
|
||||
}
|
||||
|
||||
QPDFFormFieldObjectHelper
|
||||
QPDFAcroFormDocumentHelper::getFieldForAnnotation(QPDFAnnotationObjectHelper h)
|
||||
{
|
||||
QPDFObjectHandle oh = h.getObjectHandle();
|
||||
if (! (oh.isDictionary() &&
|
||||
oh.getKey("/Subtype").isName() &&
|
||||
(oh.getKey("/Subtype").getName() == "/Widget")))
|
||||
{
|
||||
throw std::logic_error(
|
||||
"QPDFAnnotationObjectHelper::getFieldForAnnotation called for"
|
||||
" non-/Widget annotation");
|
||||
}
|
||||
analyze();
|
||||
QPDFFormFieldObjectHelper result(QPDFObjectHandle::newNull());
|
||||
QPDFObjGen og(oh.getObjGen());
|
||||
if (this->m->annotation_to_field.count(og))
|
||||
{
|
||||
result = this->m->annotation_to_field[og];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
QPDFAcroFormDocumentHelper::analyze()
|
||||
{
|
||||
if (this->m->cache_valid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this->m->cache_valid = true;
|
||||
QPDFObjectHandle acroform = this->qpdf.getRoot().getKey("/AcroForm");
|
||||
if (! (acroform.isDictionary() && acroform.hasKey("/Fields")))
|
||||
{
|
||||
return;
|
||||
}
|
||||
QPDFObjectHandle fields = acroform.getKey("/Fields");
|
||||
if (! fields.isArray())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFAcroFormDocumentHelper fields not array");
|
||||
acroform.warnIfPossible(
|
||||
"/Fields key of /AcroForm dictionary is not an array; ignoring");
|
||||
fields = QPDFObjectHandle::newArray();
|
||||
}
|
||||
|
||||
// Traverse /AcroForm to find annotations and map them
|
||||
// bidirectionally to fields.
|
||||
|
||||
std::set<QPDFObjGen> visited;
|
||||
size_t nfields = fields.getArrayNItems();
|
||||
QPDFObjectHandle null(QPDFObjectHandle::newNull());
|
||||
for (size_t i = 0; i < nfields; ++i)
|
||||
{
|
||||
traverseField(fields.getArrayItem(i), null, 0, visited);
|
||||
}
|
||||
|
||||
// All Widget annotations should have been encountered by
|
||||
// traversing /AcroForm, but in case any weren't, find them by
|
||||
// walking through pages, and treat any widget annotation that is
|
||||
// not associated with a field as its own field. This just ensures
|
||||
// that requesting the field for any annotation we find through a
|
||||
// page's /Annots list will have some associated field. Note that
|
||||
// a file that contains this kind of error will probably not
|
||||
// actually work with most viewers.
|
||||
|
||||
QPDFPageDocumentHelper dh(this->qpdf);
|
||||
std::vector<QPDFPageObjectHelper> pages = dh.getAllPages();
|
||||
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
||||
iter != pages.end(); ++iter)
|
||||
{
|
||||
QPDFPageObjectHelper ph(*iter);
|
||||
std::vector<QPDFAnnotationObjectHelper> annots =
|
||||
getWidgetAnnotationsForPage(ph);
|
||||
for (std::vector<QPDFAnnotationObjectHelper>::iterator i2 =
|
||||
annots.begin();
|
||||
i2 != annots.end(); ++i2)
|
||||
{
|
||||
QPDFObjectHandle annot((*i2).getObjectHandle());
|
||||
QPDFObjGen og(annot.getObjGen());
|
||||
if (this->m->annotation_to_field.count(og) == 0)
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFAcroFormDocumentHelper orphaned widget");
|
||||
// This is not supposed to happen, but it's easy
|
||||
// enough for us to handle this case. Treat the
|
||||
// annotation as its own field. This could allow qpdf
|
||||
// to sensibly handle a case such as a PDF creator
|
||||
// adding a self-contained annotation (merged with the
|
||||
// field dictionary) to the page's /Annots array and
|
||||
// forgetting to also put it in /AcroForm.
|
||||
annot.warnIfPossible(
|
||||
"this widget annotation is not"
|
||||
" reachable from /AcroForm in the document catalog");
|
||||
this->m->annotation_to_field[og] =
|
||||
QPDFFormFieldObjectHelper(annot);
|
||||
this->m->field_to_annotations[og].push_back(
|
||||
QPDFAnnotationObjectHelper(annot));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QPDFAcroFormDocumentHelper::traverseField(
|
||||
QPDFObjectHandle field, QPDFObjectHandle parent, int depth,
|
||||
std::set<QPDFObjGen>& visited)
|
||||
{
|
||||
if (depth > 100)
|
||||
{
|
||||
// Arbitrarily cut off recursion at a fixed depth to avoid
|
||||
// specially crafted files that could cause stack overflow.
|
||||
return;
|
||||
}
|
||||
if (! field.isIndirect())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFAcroFormDocumentHelper direct field");
|
||||
field.warnIfPossible(
|
||||
"encountered a direct object as a field or annotation while"
|
||||
" traversing /AcroForm; ignoring field or annotation");
|
||||
return;
|
||||
}
|
||||
if (! field.isDictionary())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFAcroFormDocumentHelper non-dictionary field");
|
||||
field.warnIfPossible(
|
||||
"encountered a non-dictionary as a field or annotation while"
|
||||
" traversing /AcroForm; ignoring field or annotation");
|
||||
return;
|
||||
}
|
||||
QPDFObjGen og(field.getObjGen());
|
||||
if (visited.count(og) != 0)
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFAcroFormDocumentHelper loop");
|
||||
field.warnIfPossible("loop detected while traversing /AcroForm");
|
||||
return;
|
||||
}
|
||||
visited.insert(og);
|
||||
|
||||
// A dictionary encountered while traversing the /AcroForm field
|
||||
// may be a form field, an annotation, or the merger of the two. A
|
||||
// field that has no fields below it is a terminal. If a terminal
|
||||
// field looks like an annotation, it is an annotation because
|
||||
// annotation dictionary fields can be merged with terminal field
|
||||
// dictionaries. Otherwise, the annotation fields might be there
|
||||
// to be inherited by annotations below it.
|
||||
|
||||
bool is_annotation = false;
|
||||
bool is_field = (0 == depth);
|
||||
QPDFObjectHandle kids = field.getKey("/Kids");
|
||||
if (kids.isArray())
|
||||
{
|
||||
is_field = true;
|
||||
size_t nkids = kids.getArrayNItems();
|
||||
for (size_t k = 0; k < nkids; ++k)
|
||||
{
|
||||
traverseField(kids.getArrayItem(k), field, 1 + depth, visited);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (field.hasKey("/Parent"))
|
||||
{
|
||||
is_field = true;
|
||||
}
|
||||
if (field.hasKey("/Subtype") ||
|
||||
field.hasKey("/Rect") ||
|
||||
field.hasKey("/AP"))
|
||||
{
|
||||
is_annotation = true;
|
||||
}
|
||||
}
|
||||
|
||||
QTC::TC("qpdf", "QPDFAcroFormDocumentHelper field found",
|
||||
(depth == 0) ? 0 : 1);
|
||||
QTC::TC("qpdf", "QPDFAcroFormDocumentHelper annotation found",
|
||||
(is_field ? 0 : 1));
|
||||
|
||||
if (is_annotation)
|
||||
{
|
||||
QPDFObjectHandle our_field = (is_field ? field : parent);
|
||||
this->m->field_to_annotations[our_field.getObjGen()].push_back(
|
||||
QPDFAnnotationObjectHelper(field));
|
||||
this->m->annotation_to_field[og] =
|
||||
QPDFFormFieldObjectHelper(our_field);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
#include <qpdf/QPDFAnnotationObjectHelper.hh>
|
||||
#include <qpdf/QTC.hh>
|
||||
|
||||
QPDFAnnotationObjectHelper::Members::~Members()
|
||||
{
|
||||
}
|
||||
|
||||
QPDFAnnotationObjectHelper::Members::Members()
|
||||
{
|
||||
}
|
||||
|
||||
QPDFAnnotationObjectHelper::QPDFAnnotationObjectHelper(QPDFObjectHandle oh) :
|
||||
QPDFObjectHelper(oh)
|
||||
{
|
||||
}
|
||||
|
||||
std::string
|
||||
QPDFAnnotationObjectHelper::getSubtype()
|
||||
{
|
||||
return this->oh.getKey("/Subtype").getName();
|
||||
}
|
||||
|
||||
QPDFObjectHandle::Rectangle
|
||||
QPDFAnnotationObjectHelper::getRect()
|
||||
{
|
||||
return this->oh.getKey("/Rect").getArrayAsRectangle();
|
||||
}
|
||||
|
||||
QPDFObjectHandle
|
||||
QPDFAnnotationObjectHelper::getAppearanceDictionary()
|
||||
{
|
||||
return this->oh.getKey("/AP");
|
||||
}
|
||||
|
||||
std::string
|
||||
QPDFAnnotationObjectHelper::getAppearanceState()
|
||||
{
|
||||
if (this->oh.getKey("/AS").isName())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFAnnotationObjectHelper AS present");
|
||||
return this->oh.getKey("/AS").getName();
|
||||
}
|
||||
QTC::TC("qpdf", "QPDFAnnotationObjectHelper AS absent");
|
||||
return "";
|
||||
}
|
||||
|
||||
QPDFObjectHandle
|
||||
QPDFAnnotationObjectHelper::getAppearanceStream(
|
||||
std::string const& which,
|
||||
std::string const& state)
|
||||
{
|
||||
QPDFObjectHandle ap = getAppearanceDictionary();
|
||||
std::string desired_state = state.empty() ? getAppearanceState() : state;
|
||||
if (ap.isDictionary())
|
||||
{
|
||||
QPDFObjectHandle ap_sub = ap.getKey(which);
|
||||
if (ap_sub.isStream() && desired_state.empty())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFAnnotationObjectHelper AP stream");
|
||||
return ap_sub;
|
||||
}
|
||||
if (ap_sub.isDictionary() && (! desired_state.empty()))
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFAnnotationObjectHelper AP dictionary");
|
||||
QPDFObjectHandle ap_sub_val = ap_sub.getKey(desired_state);
|
||||
if (ap_sub_val.isStream())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFAnnotationObjectHelper AN sub stream");
|
||||
return ap_sub_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
QTC::TC("qpdf", "QPDFAnnotationObjectHelper AN null");
|
||||
return QPDFObjectHandle::newNull();
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
#include <qpdf/QPDFFormFieldObjectHelper.hh>
|
||||
#include <qpdf/QTC.hh>
|
||||
|
||||
QPDFFormFieldObjectHelper::Members::~Members()
|
||||
{
|
||||
}
|
||||
|
||||
QPDFFormFieldObjectHelper::Members::Members()
|
||||
{
|
||||
}
|
||||
|
||||
QPDFFormFieldObjectHelper::QPDFFormFieldObjectHelper(QPDFObjectHandle oh) :
|
||||
QPDFObjectHelper(oh),
|
||||
m(new Members())
|
||||
{
|
||||
}
|
||||
|
||||
QPDFFormFieldObjectHelper::QPDFFormFieldObjectHelper() :
|
||||
QPDFObjectHelper(QPDFObjectHandle::newNull()),
|
||||
m(new Members())
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
QPDFFormFieldObjectHelper::isNull()
|
||||
{
|
||||
return this->oh.isNull();
|
||||
}
|
||||
|
||||
QPDFFormFieldObjectHelper
|
||||
QPDFFormFieldObjectHelper::getParent()
|
||||
{
|
||||
return this->oh.getKey("/Parent"); // may be null
|
||||
}
|
||||
|
||||
QPDFObjectHandle
|
||||
QPDFFormFieldObjectHelper::getInheritableFieldValue(std::string const& name)
|
||||
{
|
||||
QPDFObjectHandle node = this->oh;
|
||||
QPDFObjectHandle result(node.getKey(name));
|
||||
std::set<QPDFObjGen> seen;
|
||||
while (result.isNull() && node.hasKey("/Parent"))
|
||||
{
|
||||
seen.insert(node.getObjGen());
|
||||
node = node.getKey("/Parent");
|
||||
if (seen.count(node.getObjGen()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
result = node.getKey(name);
|
||||
if (! result.isNull())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper non-trivial inheritance");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string
|
||||
QPDFFormFieldObjectHelper::getInheritableFieldValueAsString(
|
||||
std::string const& name)
|
||||
{
|
||||
QPDFObjectHandle fv = getInheritableFieldValue(name);
|
||||
std::string result;
|
||||
if (fv.isString())
|
||||
{
|
||||
result = fv.getUTF8Value();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string
|
||||
QPDFFormFieldObjectHelper::getInheritableFieldValueAsName(
|
||||
std::string const& name)
|
||||
{
|
||||
QPDFObjectHandle fv = getInheritableFieldValue(name);
|
||||
std::string result;
|
||||
if (fv.isName())
|
||||
{
|
||||
result = fv.getName();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string
|
||||
QPDFFormFieldObjectHelper::getFieldType()
|
||||
{
|
||||
return getInheritableFieldValueAsName("/FT");
|
||||
}
|
||||
|
||||
std::string
|
||||
QPDFFormFieldObjectHelper::getFullyQualifiedName()
|
||||
{
|
||||
std::string result;
|
||||
QPDFObjectHandle node = this->oh;
|
||||
std::set<QPDFObjGen> seen;
|
||||
while ((! node.isNull()) && (seen.count(node.getObjGen()) == 0))
|
||||
{
|
||||
if (node.getKey("/T").isString())
|
||||
{
|
||||
if (! result.empty())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper non-trivial qualified name");
|
||||
result = "." + result;
|
||||
}
|
||||
result = node.getKey("/T").getUTF8Value() + result;
|
||||
}
|
||||
seen.insert(node.getObjGen());
|
||||
node = node.getKey("/Parent");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string
|
||||
QPDFFormFieldObjectHelper::getPartialName()
|
||||
{
|
||||
std::string result;
|
||||
if (this->oh.getKey("/T").isString())
|
||||
{
|
||||
result = this->oh.getKey("/T").getUTF8Value();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string
|
||||
QPDFFormFieldObjectHelper::getAlternativeName()
|
||||
{
|
||||
if (this->oh.getKey("/TU").isString())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper TU present");
|
||||
return this->oh.getKey("/TU").getUTF8Value();
|
||||
}
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper TU absent");
|
||||
return getFullyQualifiedName();
|
||||
}
|
||||
|
||||
std::string
|
||||
QPDFFormFieldObjectHelper::getMappingName()
|
||||
{
|
||||
if (this->oh.getKey("/TM").isString())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper TM present");
|
||||
return this->oh.getKey("/TM").getUTF8Value();
|
||||
}
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper TM absent");
|
||||
return getAlternativeName();
|
||||
}
|
||||
|
||||
QPDFObjectHandle
|
||||
QPDFFormFieldObjectHelper::getValue()
|
||||
{
|
||||
return getInheritableFieldValue("/V");
|
||||
}
|
||||
|
||||
std::string
|
||||
QPDFFormFieldObjectHelper::getValueAsString()
|
||||
{
|
||||
return getInheritableFieldValueAsString("/V");
|
||||
}
|
||||
|
||||
QPDFObjectHandle
|
||||
QPDFFormFieldObjectHelper::getDefaultValue()
|
||||
{
|
||||
return getInheritableFieldValue("/DV");
|
||||
}
|
||||
|
||||
std::string
|
||||
QPDFFormFieldObjectHelper::getDefaultValueAsString()
|
||||
{
|
||||
return getInheritableFieldValueAsString("/DV");
|
||||
}
|
||||
|
||||
std::string
|
||||
QPDFFormFieldObjectHelper::getDefaultAppearance()
|
||||
{
|
||||
return getInheritableFieldValueAsString("/DA");
|
||||
}
|
||||
|
||||
int
|
||||
QPDFFormFieldObjectHelper::getQuadding()
|
||||
{
|
||||
int result = 0;
|
||||
QPDFObjectHandle fv = getInheritableFieldValue("/Q");
|
||||
if (fv.isInteger())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper Q present");
|
||||
result = static_cast<int>(fv.getIntValue());
|
||||
}
|
||||
return result;
|
||||
}
|
|
@ -19,6 +19,29 @@ QPDFPageObjectHelper::getPageImages()
|
|||
return this->oh.getPageImages();
|
||||
}
|
||||
|
||||
std::vector<QPDFAnnotationObjectHelper>
|
||||
QPDFPageObjectHelper::getAnnotations(std::string const& only_subtype)
|
||||
{
|
||||
std::vector<QPDFAnnotationObjectHelper> result;
|
||||
QPDFObjectHandle annots = this->oh.getKey("/Annots");
|
||||
if (annots.isArray())
|
||||
{
|
||||
size_t nannots = annots.getArrayNItems();
|
||||
for (size_t i = 0; i < nannots; ++i)
|
||||
{
|
||||
QPDFObjectHandle annot = annots.getArrayItem(i);
|
||||
if (only_subtype.empty() ||
|
||||
(annot.isDictionary() &&
|
||||
annot.getKey("/Subtype").isName() &&
|
||||
(only_subtype == annot.getKey("/Subtype").getName())))
|
||||
{
|
||||
result.push_back(QPDFAnnotationObjectHelper(annot));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<QPDFObjectHandle>
|
||||
QPDFPageObjectHelper::getPageContents()
|
||||
{
|
||||
|
|
|
@ -35,7 +35,10 @@ SRCS_libqpdf = \
|
|||
libqpdf/Pl_StdioFile.cc \
|
||||
libqpdf/Pl_TIFFPredictor.cc \
|
||||
libqpdf/QPDF.cc \
|
||||
libqpdf/QPDFAcroFormDocumentHelper.cc \
|
||||
libqpdf/QPDFAnnotationObjectHelper.cc \
|
||||
libqpdf/QPDFExc.cc \
|
||||
libqpdf/QPDFFormFieldObjectHelper.cc \
|
||||
libqpdf/QPDFObjGen.cc \
|
||||
libqpdf/QPDFObject.cc \
|
||||
libqpdf/QPDFObjectHandle.cc \
|
||||
|
|
|
@ -336,3 +336,23 @@ QPDFObjectHandle erase array bounds 0
|
|||
qpdf-c called qpdf_check_pdf 0
|
||||
QPDF xref loop 0
|
||||
QPDFObjectHandle too deep 0
|
||||
QPDFFormFieldObjectHelper non-trivial inheritance 0
|
||||
QPDFFormFieldObjectHelper non-trivial qualified name 0
|
||||
QPDFFormFieldObjectHelper TU present 0
|
||||
QPDFFormFieldObjectHelper TM present 0
|
||||
QPDFFormFieldObjectHelper TU absent 0
|
||||
QPDFFormFieldObjectHelper TM absent 0
|
||||
QPDFFormFieldObjectHelper Q present 0
|
||||
QPDFAnnotationObjectHelper AS present 0
|
||||
QPDFAnnotationObjectHelper AS absent 0
|
||||
QPDFAnnotationObjectHelper AP stream 0
|
||||
QPDFAnnotationObjectHelper AP dictionary 0
|
||||
QPDFAnnotationObjectHelper AN sub stream 0
|
||||
QPDFAnnotationObjectHelper AN null 0
|
||||
QPDFAcroFormDocumentHelper fields not array 0
|
||||
QPDFAcroFormDocumentHelper orphaned widget 0
|
||||
QPDFAcroFormDocumentHelper direct field 0
|
||||
QPDFAcroFormDocumentHelper non-dictionary field 0
|
||||
QPDFAcroFormDocumentHelper loop 0
|
||||
QPDFAcroFormDocumentHelper field found 1
|
||||
QPDFAcroFormDocumentHelper annotation found 1
|
||||
|
|
|
@ -92,6 +92,38 @@ $td->runtest("PDF doc encoding to Unicode",
|
|||
{$td->FILE => "pdf-doc-to-utf8.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
show_ntests();
|
||||
# ----------
|
||||
$td->notify("--- Form Tests ---");
|
||||
|
||||
my @form_tests = (
|
||||
'minimal',
|
||||
'form-empty-from-odt',
|
||||
'form-mod1',
|
||||
# Atril (MATE Document Viewer) 1.20.1 dumps appearance streams
|
||||
# when modifying form fields, leaving /NeedAppearances true.
|
||||
'form-filled-with-atril',
|
||||
'form-bad-fields-array',
|
||||
'form-errors',
|
||||
);
|
||||
|
||||
$n_tests += scalar(@form_tests);
|
||||
|
||||
# Many of the form*.pdf files were created by converting the
|
||||
# LibreOffice document storage/form.odt to PDF and then manually
|
||||
# modifying the resulting PDF in various ways. That file would be good
|
||||
# starting point for generation of more complex forms should that be
|
||||
# required in the future. The file storage/form.pdf is a direct export
|
||||
# from LibreOffice with no modifications.
|
||||
|
||||
foreach my $f (@form_tests)
|
||||
{
|
||||
$td->runtest("form test: $f",
|
||||
{$td->COMMAND => "test_driver 43 $f.pdf"},
|
||||
{$td->FILE => "form-$f.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
}
|
||||
|
||||
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
|
@ -0,0 +1,253 @@
|
|||
iterating over form fields
|
||||
WARNING: form-bad-fields-array.pdf, object 1 0 at offset 50: /Fields key of /AcroForm dictionary is not an array; ignoring
|
||||
WARNING: form-bad-fields-array.pdf, object 4 0 at offset 615: this widget annotation is not reachable from /AcroForm in the document catalog
|
||||
WARNING: form-bad-fields-array.pdf, object 16 0 at offset 3419: this widget annotation is not reachable from /AcroForm in the document catalog
|
||||
WARNING: form-bad-fields-array.pdf, object 17 0 at offset 3775: this widget annotation is not reachable from /AcroForm in the document catalog
|
||||
WARNING: form-bad-fields-array.pdf, object 18 0 at offset 4131: this widget annotation is not reachable from /AcroForm in the document catalog
|
||||
WARNING: form-bad-fields-array.pdf, object 6 0 at offset 1032: this widget annotation is not reachable from /AcroForm in the document catalog
|
||||
WARNING: form-bad-fields-array.pdf, object 7 0 at offset 1413: this widget annotation is not reachable from /AcroForm in the document catalog
|
||||
WARNING: form-bad-fields-array.pdf, object 8 0 at offset 1796: this widget annotation is not reachable from /AcroForm in the document catalog
|
||||
WARNING: form-bad-fields-array.pdf, object 32 0 at offset 5893: this widget annotation is not reachable from /AcroForm in the document catalog
|
||||
WARNING: form-bad-fields-array.pdf, object 33 0 at offset 6251: this widget annotation is not reachable from /AcroForm in the document catalog
|
||||
WARNING: form-bad-fields-array.pdf, object 34 0 at offset 6607: this widget annotation is not reachable from /AcroForm in the document catalog
|
||||
WARNING: form-bad-fields-array.pdf, object 10 0 at offset 2311: this widget annotation is not reachable from /AcroForm in the document catalog
|
||||
Field: 4 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Text Box 1
|
||||
Partial name: Text Box 1
|
||||
Alternative name: Text Box 1
|
||||
Mapping name: Text Box 1
|
||||
Field type: /Tx
|
||||
Value: <feff>
|
||||
Value as string:
|
||||
Default value: <feff>
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /F2 12 Tf
|
||||
Quadding: 0
|
||||
Annotation: 4 0 R
|
||||
Field: 6 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Check Box 1
|
||||
Partial name: Check Box 1
|
||||
Alternative name: Check Box 1
|
||||
Mapping name: Check Box 1
|
||||
Field type: /Btn
|
||||
Value: /Off
|
||||
Value as string:
|
||||
Default value: /Off
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 6 0 R
|
||||
Field: 7 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Check Box 2
|
||||
Partial name: Check Box 2
|
||||
Alternative name: Check Box 2
|
||||
Mapping name: Check Box 2
|
||||
Field type: /Btn
|
||||
Value: /Yes
|
||||
Value as string:
|
||||
Default value: /Yes
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 7 0 R
|
||||
Field: 8 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Check Box 3
|
||||
Partial name: Check Box 3
|
||||
Alternative name: Check Box 3
|
||||
Mapping name: Check Box 3
|
||||
Field type: /Btn
|
||||
Value: /Off
|
||||
Value as string:
|
||||
Default value: /Off
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 8 0 R
|
||||
Field: 10 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Text Box 2
|
||||
Partial name: Text Box 2
|
||||
Alternative name: Text Box 2
|
||||
Mapping name: Text Box 2
|
||||
Field type: /Tx
|
||||
Value: <feff00730061006c00610064002003c002ac>
|
||||
Value as string: salad πʬ
|
||||
Default value: <feff00730061006c00610064002003c002ac>
|
||||
Default value as string: salad πʬ
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /F2 12 Tf
|
||||
Quadding: 0
|
||||
Annotation: 10 0 R
|
||||
Field: 16 0 R
|
||||
Parent: 5 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r1
|
||||
Partial name:
|
||||
Alternative name: r1
|
||||
Mapping name: r1
|
||||
Field type: /Btn
|
||||
Value: /1
|
||||
Value as string:
|
||||
Default value: /1
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 16 0 R
|
||||
Field: 17 0 R
|
||||
Parent: 5 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r1
|
||||
Partial name:
|
||||
Alternative name: r1
|
||||
Mapping name: r1
|
||||
Field type: /Btn
|
||||
Value: /1
|
||||
Value as string:
|
||||
Default value: /1
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 17 0 R
|
||||
Field: 18 0 R
|
||||
Parent: 5 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r1
|
||||
Partial name:
|
||||
Alternative name: r1
|
||||
Mapping name: r1
|
||||
Field type: /Btn
|
||||
Value: /1
|
||||
Value as string:
|
||||
Default value: /1
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 18 0 R
|
||||
Field: 32 0 R
|
||||
Parent: 9 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r2
|
||||
Partial name:
|
||||
Alternative name: r2
|
||||
Mapping name: r2
|
||||
Field type: /Btn
|
||||
Value: /2
|
||||
Value as string:
|
||||
Default value: /2
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 32 0 R
|
||||
Field: 33 0 R
|
||||
Parent: 9 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r2
|
||||
Partial name:
|
||||
Alternative name: r2
|
||||
Mapping name: r2
|
||||
Field type: /Btn
|
||||
Value: /2
|
||||
Value as string:
|
||||
Default value: /2
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 33 0 R
|
||||
Field: 34 0 R
|
||||
Parent: 9 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r2
|
||||
Partial name:
|
||||
Alternative name: r2
|
||||
Mapping name: r2
|
||||
Field type: /Btn
|
||||
Value: /2
|
||||
Value as string:
|
||||
Default value: /2
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 34 0 R
|
||||
iterating over annotations per page
|
||||
Page: 11 0 R
|
||||
Annotation: 4 0 R
|
||||
Field: 4 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [123.4, 692.1, 260.9, 706.7]
|
||||
Appearance stream (/N): 14 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 16 0 R
|
||||
Field: 16 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [149.3, 648.5, 161.6, 660.4]
|
||||
Appearance state: /1
|
||||
Appearance stream (/N): 44 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 17 0 R
|
||||
Field: 17 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [152.7, 627.3, 165, 639.2]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 50 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 18 0 R
|
||||
Field: 18 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [151.3, 601.7, 163.6, 613.6]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 54 0 R
|
||||
Appearance stream (/N, /3): 52 0 R
|
||||
Annotation: 6 0 R
|
||||
Field: 6 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [121.9, 559.1, 134.2, 571]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 19 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 7 0 R
|
||||
Field: 7 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [118.6, 527.7, 130.9, 539.6]
|
||||
Appearance state: /Yes
|
||||
Appearance stream (/N): 26 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 8 0 R
|
||||
Field: 8 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [118.6, 500.5, 130.9, 512.4]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 28 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Page: 40 0 R
|
||||
Page: 35 0 R
|
||||
Annotation: 32 0 R
|
||||
Field: 32 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [118.6, 555.7, 130.9, 567.6]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 58 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 33 0 R
|
||||
Field: 33 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [119.3, 514.8, 131.6, 526.7]
|
||||
Appearance state: /2
|
||||
Appearance stream (/N): 60 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 34 0 R
|
||||
Field: 34 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [121.3, 472.5, 133.6, 484.4]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 66 0 R
|
||||
Appearance stream (/N, /3): 64 0 R
|
||||
Annotation: 10 0 R
|
||||
Field: 10 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [113.6, 378.5, 351.3, 396.3]
|
||||
Appearance stream (/N): 36 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
test 43 done
|
|
@ -0,0 +1,241 @@
|
|||
iterating over form fields
|
||||
Field: 4 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Text Box 1
|
||||
Partial name: Text Box 1
|
||||
Alternative name: Text Box 1
|
||||
Mapping name: Text Box 1
|
||||
Field type: /Tx
|
||||
Value: <feff>
|
||||
Value as string:
|
||||
Default value: <feff>
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /F2 12 Tf
|
||||
Quadding: 0
|
||||
Annotation: 4 0 R
|
||||
Field: 6 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Check Box 1
|
||||
Partial name: Check Box 1
|
||||
Alternative name: Check Box 1
|
||||
Mapping name: Check Box 1
|
||||
Field type: /Btn
|
||||
Value: /Off
|
||||
Value as string:
|
||||
Default value: /Off
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 6 0 R
|
||||
Field: 7 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Check Box 2
|
||||
Partial name: Check Box 2
|
||||
Alternative name: Check Box 2
|
||||
Mapping name: Check Box 2
|
||||
Field type: /Btn
|
||||
Value: /Yes
|
||||
Value as string:
|
||||
Default value: /Yes
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 7 0 R
|
||||
Field: 8 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Check Box 3
|
||||
Partial name: Check Box 3
|
||||
Alternative name: Check Box 3
|
||||
Mapping name: Check Box 3
|
||||
Field type: /Btn
|
||||
Value: /Off
|
||||
Value as string:
|
||||
Default value: /Off
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 8 0 R
|
||||
Field: 10 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Text Box 2
|
||||
Partial name: Text Box 2
|
||||
Alternative name: Text Box 2
|
||||
Mapping name: Text Box 2
|
||||
Field type: /Tx
|
||||
Value: <feff00730061006c00610064002003c002ac>
|
||||
Value as string: salad πʬ
|
||||
Default value: <feff00730061006c00610064002003c002ac>
|
||||
Default value as string: salad πʬ
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /F2 12 Tf
|
||||
Quadding: 0
|
||||
Annotation: 10 0 R
|
||||
Field: 16 0 R
|
||||
Parent: 5 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r1
|
||||
Partial name:
|
||||
Alternative name: r1
|
||||
Mapping name: r1
|
||||
Field type: /Btn
|
||||
Value: /1
|
||||
Value as string:
|
||||
Default value: /1
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 16 0 R
|
||||
Field: 17 0 R
|
||||
Parent: 5 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r1
|
||||
Partial name:
|
||||
Alternative name: r1
|
||||
Mapping name: r1
|
||||
Field type: /Btn
|
||||
Value: /1
|
||||
Value as string:
|
||||
Default value: /1
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 17 0 R
|
||||
Field: 18 0 R
|
||||
Parent: 5 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r1
|
||||
Partial name:
|
||||
Alternative name: r1
|
||||
Mapping name: r1
|
||||
Field type: /Btn
|
||||
Value: /1
|
||||
Value as string:
|
||||
Default value: /1
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 18 0 R
|
||||
Field: 32 0 R
|
||||
Parent: 9 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r2
|
||||
Partial name:
|
||||
Alternative name: r2
|
||||
Mapping name: r2
|
||||
Field type: /Btn
|
||||
Value: /2
|
||||
Value as string:
|
||||
Default value: /2
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 32 0 R
|
||||
Field: 33 0 R
|
||||
Parent: 9 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r2
|
||||
Partial name:
|
||||
Alternative name: r2
|
||||
Mapping name: r2
|
||||
Field type: /Btn
|
||||
Value: /2
|
||||
Value as string:
|
||||
Default value: /2
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 33 0 R
|
||||
Field: 34 0 R
|
||||
Parent: 9 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r2
|
||||
Partial name:
|
||||
Alternative name: r2
|
||||
Mapping name: r2
|
||||
Field type: /Btn
|
||||
Value: /2
|
||||
Value as string:
|
||||
Default value: /2
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 34 0 R
|
||||
iterating over annotations per page
|
||||
Page: 11 0 R
|
||||
Annotation: 4 0 R
|
||||
Field: 4 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [123.4, 692.1, 260.9, 706.7]
|
||||
Appearance stream (/N): 14 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 16 0 R
|
||||
Field: 16 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [149.3, 648.5, 161.6, 660.4]
|
||||
Appearance state: /1
|
||||
Appearance stream (/N): 44 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 17 0 R
|
||||
Field: 17 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [152.7, 627.3, 165, 639.2]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 50 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 18 0 R
|
||||
Field: 18 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [151.3, 601.7, 163.6, 613.6]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 54 0 R
|
||||
Appearance stream (/N, /3): 52 0 R
|
||||
Annotation: 6 0 R
|
||||
Field: 6 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [121.9, 559.1, 134.2, 571]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 19 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 7 0 R
|
||||
Field: 7 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [118.6, 527.7, 130.9, 539.6]
|
||||
Appearance state: /Yes
|
||||
Appearance stream (/N): 26 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 8 0 R
|
||||
Field: 8 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [118.6, 500.5, 130.9, 512.4]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 28 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Page: 40 0 R
|
||||
Page: 35 0 R
|
||||
Annotation: 32 0 R
|
||||
Field: 32 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [118.6, 555.7, 130.9, 567.6]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 58 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 33 0 R
|
||||
Field: 33 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [119.3, 514.8, 131.6, 526.7]
|
||||
Appearance state: /2
|
||||
Appearance stream (/N): 60 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 34 0 R
|
||||
Field: 34 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [121.3, 472.5, 133.6, 484.4]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 66 0 R
|
||||
Appearance stream (/N, /3): 64 0 R
|
||||
Annotation: 10 0 R
|
||||
Field: 10 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [113.6, 378.5, 351.3, 396.3]
|
||||
Appearance stream (/N): 36 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
test 43 done
|
|
@ -0,0 +1,246 @@
|
|||
iterating over form fields
|
||||
WARNING: form-errors.pdf, object 4 0 at offset 625: loop detected while traversing /AcroForm
|
||||
WARNING: form-errors.pdf, object 5 0 at offset 993: encountered a direct object as a field or annotation while traversing /AcroForm; ignoring field or annotation
|
||||
WARNING: form-errors.pdf, object 15 0 at offset 3452: encountered a non-dictionary as a field or annotation while traversing /AcroForm; ignoring field or annotation
|
||||
WARNING: form-errors.pdf, object 16 0 at offset 3475: this widget annotation is not reachable from /AcroForm in the document catalog
|
||||
WARNING: form-errors.pdf, object 32 0 at offset 5974: this widget annotation is not reachable from /AcroForm in the document catalog
|
||||
Field: 4 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Text Box 1
|
||||
Partial name: Text Box 1
|
||||
Alternative name: Text Box 1
|
||||
Mapping name: Text Box 1
|
||||
Field type: /Tx
|
||||
Value: <feff>
|
||||
Value as string:
|
||||
Default value: <feff>
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /F2 12 Tf
|
||||
Quadding: 0
|
||||
Annotation: 4 0 R
|
||||
Field: 6 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Check Box 1
|
||||
Partial name: Check Box 1
|
||||
Alternative name: Check Box 1
|
||||
Mapping name: Check Box 1
|
||||
Field type: /Btn
|
||||
Value: /Off
|
||||
Value as string:
|
||||
Default value: /Off
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 6 0 R
|
||||
Field: 7 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Check Box 2
|
||||
Partial name: Check Box 2
|
||||
Alternative name: Check Box 2
|
||||
Mapping name: Check Box 2
|
||||
Field type: /Btn
|
||||
Value: /Yes
|
||||
Value as string:
|
||||
Default value: /Yes
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 7 0 R
|
||||
Field: 8 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Check Box 3
|
||||
Partial name: Check Box 3
|
||||
Alternative name: Check Box 3
|
||||
Mapping name: Check Box 3
|
||||
Field type: /Btn
|
||||
Value: /Off
|
||||
Value as string:
|
||||
Default value: /Off
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 8 0 R
|
||||
Field: 10 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Text Box 2
|
||||
Partial name: Text Box 2
|
||||
Alternative name: Text Box 2
|
||||
Mapping name: Text Box 2
|
||||
Field type: /Tx
|
||||
Value: <feff00730061006c00610064002003c002ac>
|
||||
Value as string: salad πʬ
|
||||
Default value: <feff00730061006c00610064002003c002ac>
|
||||
Default value as string: salad πʬ
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /F2 12 Tf
|
||||
Quadding: 0
|
||||
Annotation: 10 0 R
|
||||
Field: 16 0 R
|
||||
Parent: 5 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r1
|
||||
Partial name:
|
||||
Alternative name: r1
|
||||
Mapping name: r1
|
||||
Field type: /Btn
|
||||
Value: /1
|
||||
Value as string:
|
||||
Default value: /1
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 16 0 R
|
||||
Field: 17 0 R
|
||||
Parent: 5 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r1
|
||||
Partial name:
|
||||
Alternative name: r1
|
||||
Mapping name: r1
|
||||
Field type: /Btn
|
||||
Value: /1
|
||||
Value as string:
|
||||
Default value: /1
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 17 0 R
|
||||
Field: 18 0 R
|
||||
Parent: 5 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r1
|
||||
Partial name:
|
||||
Alternative name: r1
|
||||
Mapping name: r1
|
||||
Field type: /Btn
|
||||
Value: /1
|
||||
Value as string:
|
||||
Default value: /1
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 18 0 R
|
||||
Field: 32 0 R
|
||||
Parent: 9 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r2
|
||||
Partial name:
|
||||
Alternative name: r2
|
||||
Mapping name: r2
|
||||
Field type: /Btn
|
||||
Value: /2
|
||||
Value as string:
|
||||
Default value: /2
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 32 0 R
|
||||
Field: 33 0 R
|
||||
Parent: 9 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r2
|
||||
Partial name:
|
||||
Alternative name: r2
|
||||
Mapping name: r2
|
||||
Field type: /Btn
|
||||
Value: /2
|
||||
Value as string:
|
||||
Default value: /2
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 33 0 R
|
||||
Field: 34 0 R
|
||||
Parent: 9 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r2
|
||||
Partial name:
|
||||
Alternative name: r2
|
||||
Mapping name: r2
|
||||
Field type: /Btn
|
||||
Value: /2
|
||||
Value as string:
|
||||
Default value: /2
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 34 0 R
|
||||
iterating over annotations per page
|
||||
Page: 11 0 R
|
||||
Annotation: 4 0 R
|
||||
Field: 4 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [123.4, 692.1, 260.9, 706.7]
|
||||
Appearance stream (/N): 14 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 16 0 R
|
||||
Field: 16 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [149.3, 648.5, 161.6, 660.4]
|
||||
Appearance state: /1
|
||||
Appearance stream (/N): 44 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 17 0 R
|
||||
Field: 17 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [152.7, 627.3, 165, 639.2]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 50 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 18 0 R
|
||||
Field: 18 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [151.3, 601.7, 163.6, 613.6]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 54 0 R
|
||||
Appearance stream (/N, /3): 52 0 R
|
||||
Annotation: 6 0 R
|
||||
Field: 6 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [121.9, 559.1, 134.2, 571]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 19 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 7 0 R
|
||||
Field: 7 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [118.6, 527.7, 130.9, 539.6]
|
||||
Appearance state: /Yes
|
||||
Appearance stream (/N): 26 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 8 0 R
|
||||
Field: 8 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [118.6, 500.5, 130.9, 512.4]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 28 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Page: 40 0 R
|
||||
Page: 35 0 R
|
||||
Annotation: 32 0 R
|
||||
Field: 32 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [118.6, 555.7, 130.9, 567.6]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 58 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 33 0 R
|
||||
Field: 33 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [119.3, 514.8, 131.6, 526.7]
|
||||
Appearance state: /2
|
||||
Appearance stream (/N): 60 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 34 0 R
|
||||
Field: 34 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [121.3, 472.5, 133.6, 484.4]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 66 0 R
|
||||
Appearance stream (/N, /3): 64 0 R
|
||||
Annotation: 10 0 R
|
||||
Field: 10 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [113.6, 378.5, 351.3, 396.3]
|
||||
Appearance stream (/N): 36 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
test 43 done
|
|
@ -0,0 +1,241 @@
|
|||
iterating over form fields
|
||||
Field: 4 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Text Box 1
|
||||
Partial name: Text Box 1
|
||||
Alternative name: Text Box 1
|
||||
Mapping name: Text Box 1
|
||||
Field type: /Tx
|
||||
Value: <feff004800610067006f006f00670061006d00610067006f006f0067006c0065>
|
||||
Value as string: Hagoogamagoogle
|
||||
Default value: <feff>
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /F2 12 Tf
|
||||
Quadding: 0
|
||||
Annotation: 4 0 R
|
||||
Field: 6 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Check Box 1
|
||||
Partial name: Check Box 1
|
||||
Alternative name: Check Box 1
|
||||
Mapping name: Check Box 1
|
||||
Field type: /Btn
|
||||
Value: /Yes
|
||||
Value as string:
|
||||
Default value: /Off
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 6 0 R
|
||||
Field: 7 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Check Box 2
|
||||
Partial name: Check Box 2
|
||||
Alternative name: Check Box 2
|
||||
Mapping name: Check Box 2
|
||||
Field type: /Btn
|
||||
Value: /Yes
|
||||
Value as string:
|
||||
Default value: /Yes
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 7 0 R
|
||||
Field: 8 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Check Box 3
|
||||
Partial name: Check Box 3
|
||||
Alternative name: Check Box 3
|
||||
Mapping name: Check Box 3
|
||||
Field type: /Btn
|
||||
Value: /Off
|
||||
Value as string:
|
||||
Default value: /Off
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 8 0 R
|
||||
Field: 10 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Text Box 2
|
||||
Partial name: Text Box 2
|
||||
Alternative name: Text Box 2
|
||||
Mapping name: Text Box 2
|
||||
Field type: /Tx
|
||||
Value: <feff00730061006c00610064002003c002ac00200021>
|
||||
Value as string: salad πʬ !
|
||||
Default value: <feff00730061006c00610064002003c002ac>
|
||||
Default value as string: salad πʬ
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /F2 12 Tf
|
||||
Quadding: 0
|
||||
Annotation: 10 0 R
|
||||
Field: 16 0 R
|
||||
Parent: 5 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r1
|
||||
Partial name:
|
||||
Alternative name: r1
|
||||
Mapping name: r1
|
||||
Field type: /Btn
|
||||
Value: /3
|
||||
Value as string:
|
||||
Default value: /1
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 16 0 R
|
||||
Field: 17 0 R
|
||||
Parent: 5 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r1
|
||||
Partial name:
|
||||
Alternative name: r1
|
||||
Mapping name: r1
|
||||
Field type: /Btn
|
||||
Value: /3
|
||||
Value as string:
|
||||
Default value: /1
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 17 0 R
|
||||
Field: 18 0 R
|
||||
Parent: 5 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r1
|
||||
Partial name:
|
||||
Alternative name: r1
|
||||
Mapping name: r1
|
||||
Field type: /Btn
|
||||
Value: /3
|
||||
Value as string:
|
||||
Default value: /1
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 18 0 R
|
||||
Field: 32 0 R
|
||||
Parent: 9 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r2
|
||||
Partial name:
|
||||
Alternative name: r2
|
||||
Mapping name: r2
|
||||
Field type: /Btn
|
||||
Value: /2
|
||||
Value as string:
|
||||
Default value: /2
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 32 0 R
|
||||
Field: 33 0 R
|
||||
Parent: 9 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r2
|
||||
Partial name:
|
||||
Alternative name: r2
|
||||
Mapping name: r2
|
||||
Field type: /Btn
|
||||
Value: /2
|
||||
Value as string:
|
||||
Default value: /2
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 33 0 R
|
||||
Field: 34 0 R
|
||||
Parent: 9 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r2
|
||||
Partial name:
|
||||
Alternative name: r2
|
||||
Mapping name: r2
|
||||
Field type: /Btn
|
||||
Value: /2
|
||||
Value as string:
|
||||
Default value: /2
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 34 0 R
|
||||
iterating over annotations per page
|
||||
Page: 11 0 R
|
||||
Annotation: 4 0 R
|
||||
Field: 4 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [123.4, 692.1, 260.9, 706.7]
|
||||
Appearance stream (/N): null
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 16 0 R
|
||||
Field: 16 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [149.3, 648.5, 161.6, 660.4]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 46 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 17 0 R
|
||||
Field: 17 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [152.7, 627.3, 165, 639.2]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 50 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 18 0 R
|
||||
Field: 18 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [151.3, 601.7, 163.6, 613.6]
|
||||
Appearance state: /3
|
||||
Appearance stream (/N): 52 0 R
|
||||
Appearance stream (/N, /3): 52 0 R
|
||||
Annotation: 6 0 R
|
||||
Field: 6 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [121.9, 559.1, 134.2, 571]
|
||||
Appearance state: /Yes
|
||||
Appearance stream (/N): 21 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 7 0 R
|
||||
Field: 7 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [118.6, 527.7, 130.9, 539.6]
|
||||
Appearance state: /Yes
|
||||
Appearance stream (/N): 26 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 8 0 R
|
||||
Field: 8 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [118.6, 500.5, 130.9, 512.4]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 28 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Page: 40 0 R
|
||||
Page: 35 0 R
|
||||
Annotation: 32 0 R
|
||||
Field: 32 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [118.6, 555.7, 130.9, 567.6]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 58 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 33 0 R
|
||||
Field: 33 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [119.3, 514.8, 131.6, 526.7]
|
||||
Appearance state: /2
|
||||
Appearance stream (/N): 60 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 34 0 R
|
||||
Field: 34 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [121.3, 472.5, 133.6, 484.4]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 66 0 R
|
||||
Appearance stream (/N, /3): 64 0 R
|
||||
Annotation: 10 0 R
|
||||
Field: 10 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [113.6, 378.5, 351.3, 396.3]
|
||||
Appearance stream (/N): null
|
||||
Appearance stream (/N, /3): null
|
||||
test 43 done
|
|
@ -0,0 +1,241 @@
|
|||
iterating over form fields
|
||||
Field: 4 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Text Box 1
|
||||
Partial name: Text Box 1
|
||||
Alternative name: Text Box 1
|
||||
Mapping name: Text Box 1
|
||||
Field type: /Tx
|
||||
Value: <feff>
|
||||
Value as string:
|
||||
Default value: <feff>
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /F2 12 Tf
|
||||
Quadding: 0
|
||||
Annotation: 83 0 R
|
||||
Field: 6 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Check Box 1
|
||||
Partial name: Check Box 1
|
||||
Alternative name: Check Box 1
|
||||
Mapping name: Check Box 1
|
||||
Field type: /Btn
|
||||
Value: /Off
|
||||
Value as string:
|
||||
Default value: /Off
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 6 0 R
|
||||
Field: 7 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Check Box 2
|
||||
Partial name: Check Box 2
|
||||
Alternative name: Check Box 2
|
||||
Mapping name: Check Box 2
|
||||
Field type: /Btn
|
||||
Value: /Yes
|
||||
Value as string:
|
||||
Default value: /Yes
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 7 0 R
|
||||
Field: 8 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Check Box 3
|
||||
Partial name: Check Box 3
|
||||
Alternative name: Check Box 3
|
||||
Mapping name: Check Box 3
|
||||
Field type: /Btn
|
||||
Value: /Off
|
||||
Value as string:
|
||||
Default value: /Off
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 8 0 R
|
||||
Field: 10 0 R
|
||||
Parent: none
|
||||
Fully qualified name: Text Box 2
|
||||
Partial name: Text Box 2
|
||||
Alternative name: Text Box 2
|
||||
Mapping name: Text Box 2
|
||||
Field type: /Tx
|
||||
Value: <feff00730061006c00610064002003c002ac>
|
||||
Value as string: salad πʬ
|
||||
Default value: <feff00730061006c00610064002003c002ac>
|
||||
Default value as string: salad πʬ
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /F2 12 Tf
|
||||
Quadding: 1
|
||||
Annotation: 10 0 R
|
||||
Field: 16 0 R
|
||||
Parent: 5 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r1.choice1
|
||||
Partial name: choice1
|
||||
Alternative name: chice 1
|
||||
Mapping name: choice 1 TM
|
||||
Field type: /Btn
|
||||
Value: /1
|
||||
Value as string:
|
||||
Default value: /1
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 16 0 R
|
||||
Field: 17 0 R
|
||||
Parent: 5 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r1
|
||||
Partial name:
|
||||
Alternative name: r1
|
||||
Mapping name: r1
|
||||
Field type: /Btn
|
||||
Value: /1
|
||||
Value as string:
|
||||
Default value: /1
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 17 0 R
|
||||
Field: 18 0 R
|
||||
Parent: 5 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r1
|
||||
Partial name:
|
||||
Alternative name: r1
|
||||
Mapping name: r1
|
||||
Field type: /Btn
|
||||
Value: /1
|
||||
Value as string:
|
||||
Default value: /1
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 18 0 R
|
||||
Field: 32 0 R
|
||||
Parent: 9 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r2
|
||||
Partial name:
|
||||
Alternative name: r2
|
||||
Mapping name: r2
|
||||
Field type: /Btn
|
||||
Value: /2
|
||||
Value as string:
|
||||
Default value: /2
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 32 0 R
|
||||
Field: 33 0 R
|
||||
Parent: 9 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r2
|
||||
Partial name:
|
||||
Alternative name: r2
|
||||
Mapping name: r2
|
||||
Field type: /Btn
|
||||
Value: /2
|
||||
Value as string:
|
||||
Default value: /2
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 33 0 R
|
||||
Field: 34 0 R
|
||||
Parent: 9 0 R
|
||||
Parent: none
|
||||
Fully qualified name: r2
|
||||
Partial name:
|
||||
Alternative name: r2
|
||||
Mapping name: r2
|
||||
Field type: /Btn
|
||||
Value: /2
|
||||
Value as string:
|
||||
Default value: /2
|
||||
Default value as string:
|
||||
Default appearance: 0.18039 0.20392 0.21176 rg /ZaDi 0 Tf
|
||||
Quadding: 0
|
||||
Annotation: 34 0 R
|
||||
iterating over annotations per page
|
||||
Page: 11 0 R
|
||||
Annotation: 83 0 R
|
||||
Field: 4 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [123.4, 692.1, 260.9, 706.7]
|
||||
Appearance stream (/N): 14 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 16 0 R
|
||||
Field: 16 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [149.3, 648.5, 161.6, 660.4]
|
||||
Appearance state: /1
|
||||
Appearance stream (/N): 44 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 17 0 R
|
||||
Field: 17 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [152.7, 627.3, 165, 639.2]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 50 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 18 0 R
|
||||
Field: 18 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [151.3, 601.7, 163.6, 613.6]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 54 0 R
|
||||
Appearance stream (/N, /3): 52 0 R
|
||||
Annotation: 6 0 R
|
||||
Field: 6 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [121.9, 559.1, 134.2, 571]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 19 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 7 0 R
|
||||
Field: 7 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [118.6, 527.7, 130.9, 539.6]
|
||||
Appearance state: /Yes
|
||||
Appearance stream (/N): 26 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 8 0 R
|
||||
Field: 8 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [118.6, 500.5, 130.9, 512.4]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 28 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Page: 40 0 R
|
||||
Page: 35 0 R
|
||||
Annotation: 32 0 R
|
||||
Field: 32 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [118.6, 555.7, 130.9, 567.6]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 58 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 33 0 R
|
||||
Field: 33 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [119.3, 514.8, 131.6, 526.7]
|
||||
Appearance state: /2
|
||||
Appearance stream (/N): 60 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
Annotation: 34 0 R
|
||||
Field: 34 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [121.3, 472.5, 133.6, 484.4]
|
||||
Appearance state: /Off
|
||||
Appearance stream (/N): 66 0 R
|
||||
Appearance stream (/N, /3): 64 0 R
|
||||
Annotation: 10 0 R
|
||||
Field: 10 0 R
|
||||
Subtype: /Widget
|
||||
Rect: [113.6, 378.5, 351.3, 396.3]
|
||||
Appearance stream (/N): 36 0 R
|
||||
Appearance stream (/N, /3): null
|
||||
test 43 done
|
|
@ -0,0 +1 @@
|
|||
no forms
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,4 @@
|
|||
This directory contains files that I want to keep around because I
|
||||
hand-created them or otherwise went to some trouble and used them in
|
||||
some fashion in the test suite. Any file in this directory should be
|
||||
referenced in a comment in the test code.
|
Binary file not shown.
Binary file not shown.
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||
#include <qpdf/QPDFAcroFormDocumentHelper.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
#include <qpdf/QTC.hh>
|
||||
#include <qpdf/Pl_StdioFile.hh>
|
||||
|
@ -153,6 +154,13 @@ static QPDFObjectHandle createPageContents(QPDF& pdf, std::string const& text)
|
|||
return QPDFObjectHandle::newStream(&pdf, contents);
|
||||
}
|
||||
|
||||
static void print_rect(std::ostream& out,
|
||||
QPDFObjectHandle::Rectangle const& r)
|
||||
{
|
||||
out << "[" << r.llx << ", " << r.lly << ", "
|
||||
<< r.urx << ", " << r.ury << "]";
|
||||
}
|
||||
|
||||
void runtest(int n, char const* filename1, char const* arg2)
|
||||
{
|
||||
// Most tests here are crafted to work on specific files. Look at
|
||||
|
@ -1474,6 +1482,108 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
(r1.urx > 5.59) && (r1.urx < 5.61) &&
|
||||
(r1.ury > 7.79) && (r1.ury < 7.81));
|
||||
}
|
||||
else if (n == 43)
|
||||
{
|
||||
// Forms
|
||||
QPDFAcroFormDocumentHelper afdh(pdf);
|
||||
if (! afdh.hasAcroForm())
|
||||
{
|
||||
std::cout << "no forms\n";
|
||||
return;
|
||||
}
|
||||
std::cout << "iterating over form fields\n";
|
||||
std::vector<QPDFFormFieldObjectHelper> form_fields =
|
||||
afdh.getFormFields();
|
||||
for (std::vector<QPDFFormFieldObjectHelper>::iterator iter =
|
||||
form_fields.begin();
|
||||
iter != form_fields.end(); ++iter)
|
||||
{
|
||||
QPDFFormFieldObjectHelper ffh(*iter);
|
||||
std::cout << "Field: " << ffh.getObjectHandle().unparse()
|
||||
<< std::endl;
|
||||
QPDFFormFieldObjectHelper node = ffh;
|
||||
while (! node.isNull())
|
||||
{
|
||||
QPDFFormFieldObjectHelper parent(node.getParent());
|
||||
std::cout << " Parent: "
|
||||
<< (parent.isNull()
|
||||
? "none"
|
||||
: parent.getObjectHandle().unparse())
|
||||
<< std::endl;
|
||||
node = parent;
|
||||
}
|
||||
std::cout << " Fully qualified name: "
|
||||
<< ffh.getFullyQualifiedName() << std::endl;
|
||||
std::cout << " Partial name: "
|
||||
<< ffh.getPartialName() << std::endl;
|
||||
std::cout << " Alternative name: "
|
||||
<< ffh.getAlternativeName() << std::endl;
|
||||
std::cout << " Mapping name: "
|
||||
<< ffh.getMappingName() << std::endl;
|
||||
std::cout << " Field type: "
|
||||
<< ffh.getFieldType() << std::endl;
|
||||
std::cout << " Value: "
|
||||
<< ffh.getValue().unparse() << std::endl;
|
||||
std::cout << " Value as string: "
|
||||
<< ffh.getValueAsString() << std::endl;
|
||||
std::cout << " Default value: "
|
||||
<< ffh.getDefaultValue().unparse() << std::endl;
|
||||
std::cout << " Default value as string: "
|
||||
<< ffh.getDefaultValueAsString() << std::endl;
|
||||
std::cout << " Default appearance: "
|
||||
<< ffh.getDefaultAppearance() << std::endl;
|
||||
std::cout << " Quadding: "
|
||||
<< ffh.getQuadding() << std::endl;
|
||||
std::vector<QPDFAnnotationObjectHelper> annotations =
|
||||
afdh.getAnnotationsForField(ffh);
|
||||
for (std::vector<QPDFAnnotationObjectHelper>::iterator i2 =
|
||||
annotations.begin();
|
||||
i2 != annotations.end(); ++i2)
|
||||
{
|
||||
std::cout << " Annotation: "
|
||||
<< (*i2).getObjectHandle().unparse() << std::endl;
|
||||
}
|
||||
}
|
||||
std::cout << "iterating over annotations per page\n";
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
QPDFPageDocumentHelper(pdf).getAllPages();
|
||||
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
||||
iter != pages.end(); ++iter)
|
||||
{
|
||||
std::cout << "Page: " << (*iter).getObjectHandle().unparse()
|
||||
<< std::endl;
|
||||
std::vector<QPDFAnnotationObjectHelper> annotations =
|
||||
afdh.getWidgetAnnotationsForPage(*iter);
|
||||
for (std::vector<QPDFAnnotationObjectHelper>::iterator i2 =
|
||||
annotations.begin();
|
||||
i2 != annotations.end(); ++i2)
|
||||
{
|
||||
QPDFAnnotationObjectHelper ah(*i2);
|
||||
std::cout << " Annotation: " << ah.getObjectHandle().unparse()
|
||||
<< std::endl;
|
||||
std::cout << " Field: "
|
||||
<< (afdh.getFieldForAnnotation(ah).
|
||||
getObjectHandle().unparse())
|
||||
<< std::endl;
|
||||
std::cout << " Subtype: " << ah.getSubtype() << std::endl;
|
||||
std::cout << " Rect: ";
|
||||
print_rect(std::cout, ah.getRect());
|
||||
std::cout << std::endl;
|
||||
std::string state = ah.getAppearanceState();
|
||||
if (! state.empty())
|
||||
{
|
||||
std::cout << " Appearance state: " << state
|
||||
<< std::endl;
|
||||
}
|
||||
std::cout << " Appearance stream (/N): "
|
||||
<< ah.getAppearanceStream("/N").unparse()
|
||||
<< std::endl;
|
||||
std::cout << " Appearance stream (/N, /3): "
|
||||
<< ah.getAppearanceStream("/N", "/3").unparse()
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error(std::string("invalid test ") +
|
||||
|
|
Loading…
Reference in New Issue