aboutsummaryrefslogtreecommitdiffstats
path: root/include/qpdf/QPDFAcroFormDocumentHelper.hh
diff options
context:
space:
mode:
Diffstat (limited to 'include/qpdf/QPDFAcroFormDocumentHelper.hh')
-rw-r--r--include/qpdf/QPDFAcroFormDocumentHelper.hh234
1 files changed, 96 insertions, 138 deletions
diff --git a/include/qpdf/QPDFAcroFormDocumentHelper.hh b/include/qpdf/QPDFAcroFormDocumentHelper.hh
index 1ae593af..a86563fa 100644
--- a/include/qpdf/QPDFAcroFormDocumentHelper.hh
+++ b/include/qpdf/QPDFAcroFormDocumentHelper.hh
@@ -2,69 +2,55 @@
//
// 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
+// 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.
+// 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.
+// 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:
+// 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.
+// * 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.
+// * 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:
+// * 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.
+// - 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.
+// - 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
+// - 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>
@@ -87,34 +73,28 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper
QPDF_DLL
virtual ~QPDFAcroFormDocumentHelper() = default;
- // 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.
+ // 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();
- // Add a form field, initializing the document's AcroForm
- // dictionary if needed, updating the cache if necessary. Note
- // that you are adding fields that are copies of other fields,
- // this method may result in multiple fields existing with the
- // same qualified name, which can have unexpected side effects. In
- // that case, you should use addAndRenameFormFields() instead.
+ // Add a form field, initializing the document's AcroForm dictionary if needed, updating the
+ // cache if necessary. Note that you are adding fields that are copies of other fields, this
+ // method may result in multiple fields existing with the same qualified name, which can have
+ // unexpected side effects. In that case, you should use addAndRenameFormFields() instead.
QPDF_DLL
void addFormField(QPDFFormFieldObjectHelper);
- // Add a collection of form fields making sure that their fully
- // qualified names don't conflict with already present form
- // fields. Fields within the collection of new fields that have
- // the same name as each other will continue to do so.
+ // Add a collection of form fields making sure that their fully qualified names don't conflict
+ // with already present form fields. Fields within the collection of new fields that have the
+ // same name as each other will continue to do so.
QPDF_DLL
void addAndRenameFormFields(std::vector<QPDFObjectHandle> fields);
@@ -122,31 +102,27 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper
QPDF_DLL
void removeFormFields(std::set<QPDFObjGen> const&);
- // Set the name of a field, updating internal records of field
- // names. Name should be UTF-8 encoded.
+ // Set the name of a field, updating internal records of field names. Name should be UTF-8
+ // encoded.
QPDF_DLL
void setFormFieldName(QPDFFormFieldObjectHelper, std::string const& name);
- // 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.
+ // 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 all the form fields that have the given fully-qualified
- // name and also have an explicit "/T" attribute. For this
- // information to be accurate, any changes to field names must be
- // done through setFormFieldName() above.
+ // Return all the form fields that have the given fully-qualified name and also have an explicit
+ // "/T" attribute. For this information to be accurate, any changes to field names must be done
+ // through setFormFieldName() above.
QPDF_DLL
std::set<QPDFObjGen> getFieldsWithQualifiedName(std::string const& name);
- // 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.
+ // 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);
@@ -158,63 +134,49 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper
QPDF_DLL
std::vector<QPDFFormFieldObjectHelper> getFormFieldsForPage(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 return a
+ // 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 return a
// helper associated with a null object (isNull() == true).
QPDF_DLL
QPDFFormFieldObjectHelper getFieldForAnnotation(QPDFAnnotationObjectHelper);
- // Return the current value of /NeedAppearances. If
- // /NeedAppearances is missing, return false as that is how PDF
- // viewers are supposed to interpret it.
+ // Return the current value of /NeedAppearances. If /NeedAppearances is missing, return false as
+ // that is how PDF viewers are supposed to interpret it.
QPDF_DLL
bool getNeedAppearances();
- // Indicate whether appearance streams must be regenerated. If you
- // modify a field value, you should call setNeedAppearances(true)
- // unless you also generate an appearance stream for the
- // corresponding annotation at the same time. If you generate
- // appearance streams for all fields, you can call
- // setNeedAppearances(false). If you use
- // QPDFFormFieldObjectHelper::setV, it will automatically call
- // this method unless you tell it not to.
+ // Indicate whether appearance streams must be regenerated. If you modify a field value, you
+ // should call setNeedAppearances(true) unless you also generate an appearance stream for the
+ // corresponding annotation at the same time. If you generate appearance streams for all fields,
+ // you can call setNeedAppearances(false). If you use QPDFFormFieldObjectHelper::setV, it will
+ // automatically call this method unless you tell it not to.
QPDF_DLL
void setNeedAppearances(bool);
- // If /NeedAppearances is false, do nothing. Otherwise generate
- // appearance streams for all widget annotations that need them.
- // See comments in QPDFFormFieldObjectHelper.hh for
- // generateAppearance for limitations. For checkbox and radio
- // button fields, this code ensures that appearance state is
- // consistent with the field's value and uses any pre-existing
+ // If /NeedAppearances is false, do nothing. Otherwise generate appearance streams for all
+ // widget annotations that need them. See comments in QPDFFormFieldObjectHelper.hh for
+ // generateAppearance for limitations. For checkbox and radio button fields, this code ensures
+ // that appearance state is consistent with the field's value and uses any pre-existing
// appearance streams.
QPDF_DLL
void generateAppearancesIfNeeded();
- // Note: this method works on all annotations, not just ones with
- // associated fields. For each annotation in old_annots, apply the
- // given transformation matrix to create a new annotation. New
- // annotations are appended to new_annots. If the annotation is
- // associated with a form field, a new form field is created that
- // points to the new annotation and is appended to new_fields, and
- // the old field is added to old_fields.
+ // Note: this method works on all annotations, not just ones with associated fields. For each
+ // annotation in old_annots, apply the given transformation matrix to create a new annotation.
+ // New annotations are appended to new_annots. If the annotation is associated with a form
+ // field, a new form field is created that points to the new annotation and is appended to
+ // new_fields, and the old field is added to old_fields.
//
- // old_annots may belong to a different QPDF object. In that case,
- // you should pass in from_qpdf, and copyForeignObject will be
- // called automatically. If this is the case, for efficiency, you
- // may pass in a QPDFAcroFormDocumentHelper for the other file to
- // avoid the expensive process of creating one for each call to
- // transformAnnotations. New fields and annotations are not added
- // to the document or pages. You have to do that yourself after
- // calling transformAnnotations. If this operation will leave
- // orphaned fields behind, such as if you are replacing the old
- // annotations with the new ones on the same page and the fields
- // and annotations are not shared, you will also need to remove
- // the old fields to prevent them from hanging round unreferenced.
+ // old_annots may belong to a different QPDF object. In that case, you should pass in from_qpdf,
+ // and copyForeignObject will be called automatically. If this is the case, for efficiency, you
+ // may pass in a QPDFAcroFormDocumentHelper for the other file to avoid the expensive process of
+ // creating one for each call to transformAnnotations. New fields and annotations are not added
+ // to the document or pages. You have to do that yourself after calling transformAnnotations. If
+ // this operation will leave orphaned fields behind, such as if you are replacing the old
+ // annotations with the new ones on the same page and the fields and annotations are not shared,
+ // you will also need to remove the old fields to prevent them from hanging round unreferenced.
QPDF_DLL
void transformAnnotations(
QPDFObjectHandle old_annots,
@@ -225,18 +187,14 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper
QPDF* from_qpdf = nullptr,
QPDFAcroFormDocumentHelper* from_afdh = nullptr);
- // Copy form fields and annotations from one page to another,
- // allowing the from page to be in a different QPDF or in the same
- // QPDF. This would typically be called after calling addPage to
- // add field/annotation awareness. When just copying the page by
- // itself, annotations end up being shared, and fields end up
- // being omitted because there is no reference to the field from
- // the page. This method ensures that each separate copy of a page
- // has private annotations and that fields and annotations are
- // properly updated to resolve conflicts that may occur from
- // common resource and field names across documents. It is
- // basically a wrapper around transformAnnotations that handles
- // updating the receiving page. If new_fields is non-null, any
+ // Copy form fields and annotations from one page to another, allowing the from page to be in a
+ // different QPDF or in the same QPDF. This would typically be called after calling addPage to
+ // add field/annotation awareness. When just copying the page by itself, annotations end up
+ // being shared, and fields end up being omitted because there is no reference to the field from
+ // the page. This method ensures that each separate copy of a page has private annotations and
+ // that fields and annotations are properly updated to resolve conflicts that may occur from
+ // common resource and field names across documents. It is basically a wrapper around
+ // transformAnnotations that handles updating the receiving page. If new_fields is non-null, any
// newly created fields are added to it.
QPDF_DLL
void fixCopiedAnnotations(