mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 02:49:00 +00:00
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
|
||||
|
165
include/qpdf/QPDFAcroFormDocumentHelper.hh
Normal file
165
include/qpdf/QPDFAcroFormDocumentHelper.hh
Normal file
@ -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__
|
86
include/qpdf/QPDFAnnotationObjectHelper.hh
Normal file
86
include/qpdf/QPDFAnnotationObjectHelper.hh
Normal file
@ -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__
|
133
include/qpdf/QPDFFormFieldObjectHelper.hh
Normal file
133
include/qpdf/QPDFFormFieldObjectHelper.hh
Normal file
@ -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
|
||||
|
252
libqpdf/QPDFAcroFormDocumentHelper.cc
Normal file
252
libqpdf/QPDFAcroFormDocumentHelper.cc
Normal file
@ -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);
|
||||
}
|
||||
}
|
75
libqpdf/QPDFAnnotationObjectHelper.cc
Normal file
75
libqpdf/QPDFAnnotationObjectHelper.cc
Normal file
@ -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();
|
||||
}
|
190
libqpdf/QPDFFormFieldObjectHelper.cc
Normal file
190
libqpdf/QPDFFormFieldObjectHelper.cc
Normal file
@ -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 ---");
|
||||
|
2429
qpdf/qtest/qpdf/form-bad-fields-array.pdf
Normal file
2429
qpdf/qtest/qpdf/form-bad-fields-array.pdf
Normal file
File diff suppressed because it is too large
Load Diff
2428
qpdf/qtest/qpdf/form-empty-from-odt.pdf
Normal file
2428
qpdf/qtest/qpdf/form-empty-from-odt.pdf
Normal file
File diff suppressed because it is too large
Load Diff
2431
qpdf/qtest/qpdf/form-errors.pdf
Normal file
2431
qpdf/qtest/qpdf/form-errors.pdf
Normal file
File diff suppressed because it is too large
Load Diff
2456
qpdf/qtest/qpdf/form-filled-with-atril.pdf
Normal file
2456
qpdf/qtest/qpdf/form-filled-with-atril.pdf
Normal file
File diff suppressed because it is too large
Load Diff
253
qpdf/qtest/qpdf/form-form-bad-fields-array.out
Normal file
253
qpdf/qtest/qpdf/form-form-bad-fields-array.out
Normal file
@ -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
|
241
qpdf/qtest/qpdf/form-form-empty-from-odt.out
Normal file
241
qpdf/qtest/qpdf/form-form-empty-from-odt.out
Normal file
@ -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
|
246
qpdf/qtest/qpdf/form-form-errors.out
Normal file
246
qpdf/qtest/qpdf/form-form-errors.out
Normal file
@ -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
|
241
qpdf/qtest/qpdf/form-form-filled-with-atril.out
Normal file
241
qpdf/qtest/qpdf/form-form-filled-with-atril.out
Normal file
@ -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
|
241
qpdf/qtest/qpdf/form-form-mod1.out
Normal file
241
qpdf/qtest/qpdf/form-form-mod1.out
Normal file
@ -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
|
1
qpdf/qtest/qpdf/form-minimal.out
Normal file
1
qpdf/qtest/qpdf/form-minimal.out
Normal file
@ -0,0 +1 @@
|
||||
no forms
|
2439
qpdf/qtest/qpdf/form-mod1.pdf
Normal file
2439
qpdf/qtest/qpdf/form-mod1.pdf
Normal file
File diff suppressed because it is too large
Load Diff
4
qpdf/qtest/storage/README
Normal file
4
qpdf/qtest/storage/README
Normal file
@ -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.
|
BIN
qpdf/qtest/storage/form.odt
Normal file
BIN
qpdf/qtest/storage/form.odt
Normal file
Binary file not shown.
BIN
qpdf/qtest/storage/form.pdf
Normal file
BIN
qpdf/qtest/storage/form.pdf
Normal file
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
Block a user