mirror of
https://github.com/qpdf/qpdf.git
synced 2024-06-03 19:00:51 +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>
|
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
|
* Added new classes QPDFPageDocumentHelper and QPDFPageObjctHelper
|
||||||
for page-level API functions. These classes introduce a new API
|
for page-level API functions. These classes introduce a new API
|
||||||
pattern of document helpers and object helpers in qpdf. The helper
|
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__
|
#define __QPDFPAGEOBJECTHELPER_HH__
|
||||||
|
|
||||||
#include <qpdf/QPDFObjectHelper.hh>
|
#include <qpdf/QPDFObjectHelper.hh>
|
||||||
|
#include <qpdf/QPDFAnnotationObjectHelper.hh>
|
||||||
|
|
||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
|
|
||||||
|
@ -43,6 +44,13 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::map<std::string, QPDFObjectHandle> getPageImages();
|
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
|
// Returns a vector of stream objects representing the content
|
||||||
// streams for the given page. This routine allows the caller to
|
// streams for the given page. This routine allows the caller to
|
||||||
// not care whether there are one or more than one content streams
|
// 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();
|
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>
|
std::vector<QPDFObjectHandle>
|
||||||
QPDFPageObjectHelper::getPageContents()
|
QPDFPageObjectHelper::getPageContents()
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,7 +35,10 @@ SRCS_libqpdf = \
|
||||||
libqpdf/Pl_StdioFile.cc \
|
libqpdf/Pl_StdioFile.cc \
|
||||||
libqpdf/Pl_TIFFPredictor.cc \
|
libqpdf/Pl_TIFFPredictor.cc \
|
||||||
libqpdf/QPDF.cc \
|
libqpdf/QPDF.cc \
|
||||||
|
libqpdf/QPDFAcroFormDocumentHelper.cc \
|
||||||
|
libqpdf/QPDFAnnotationObjectHelper.cc \
|
||||||
libqpdf/QPDFExc.cc \
|
libqpdf/QPDFExc.cc \
|
||||||
|
libqpdf/QPDFFormFieldObjectHelper.cc \
|
||||||
libqpdf/QPDFObjGen.cc \
|
libqpdf/QPDFObjGen.cc \
|
||||||
libqpdf/QPDFObject.cc \
|
libqpdf/QPDFObject.cc \
|
||||||
libqpdf/QPDFObjectHandle.cc \
|
libqpdf/QPDFObjectHandle.cc \
|
||||||
|
|
|
@ -336,3 +336,23 @@ QPDFObjectHandle erase array bounds 0
|
||||||
qpdf-c called qpdf_check_pdf 0
|
qpdf-c called qpdf_check_pdf 0
|
||||||
QPDF xref loop 0
|
QPDF xref loop 0
|
||||||
QPDFObjectHandle too deep 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->FILE => "pdf-doc-to-utf8.out", $td->EXIT_STATUS => 0},
|
||||||
$td->NORMALIZE_NEWLINES);
|
$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();
|
show_ntests();
|
||||||
# ----------
|
# ----------
|
||||||
$td->notify("--- Stream Replacement Tests ---");
|
$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/QPDFPageDocumentHelper.hh>
|
||||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||||
|
#include <qpdf/QPDFAcroFormDocumentHelper.hh>
|
||||||
#include <qpdf/QUtil.hh>
|
#include <qpdf/QUtil.hh>
|
||||||
#include <qpdf/QTC.hh>
|
#include <qpdf/QTC.hh>
|
||||||
#include <qpdf/Pl_StdioFile.hh>
|
#include <qpdf/Pl_StdioFile.hh>
|
||||||
|
@ -153,6 +154,13 @@ static QPDFObjectHandle createPageContents(QPDF& pdf, std::string const& text)
|
||||||
return QPDFObjectHandle::newStream(&pdf, contents);
|
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)
|
void runtest(int n, char const* filename1, char const* arg2)
|
||||||
{
|
{
|
||||||
// Most tests here are crafted to work on specific files. Look at
|
// 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.urx > 5.59) && (r1.urx < 5.61) &&
|
||||||
(r1.ury > 7.79) && (r1.ury < 7.81));
|
(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
|
else
|
||||||
{
|
{
|
||||||
throw std::runtime_error(std::string("invalid test ") +
|
throw std::runtime_error(std::string("invalid test ") +
|
||||||
|
|
Loading…
Reference in New Issue
Block a user