mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-31 14:01:59 +00:00
Add methods for copying form fields
This commit is contained in:
parent
f02aa74bf5
commit
1f35ec9988
@ -1,5 +1,11 @@
|
|||||||
2021-02-22 Jay Berkenbilt <ejb@ql.org>
|
2021-02-22 Jay Berkenbilt <ejb@ql.org>
|
||||||
|
|
||||||
|
* Add QPDFAcroFormDocumentHelper::copyFieldsFromForeignPage to
|
||||||
|
copy form fields from a foreign page into the current file.
|
||||||
|
|
||||||
|
* Add QPDFFormFieldObjectHelper::getTopLevelField to get the
|
||||||
|
top-level field for a given form field.
|
||||||
|
|
||||||
* Update pdf-overlay-page example to include copying of
|
* Update pdf-overlay-page example to include copying of
|
||||||
annotations.
|
annotations.
|
||||||
|
|
||||||
|
@ -140,6 +140,11 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper
|
|||||||
std::vector<QPDFAnnotationObjectHelper>
|
std::vector<QPDFAnnotationObjectHelper>
|
||||||
getWidgetAnnotationsForPage(QPDFPageObjectHelper);
|
getWidgetAnnotationsForPage(QPDFPageObjectHelper);
|
||||||
|
|
||||||
|
// Return form fields for a page.
|
||||||
|
QPDF_DLL
|
||||||
|
std::vector<QPDFFormFieldObjectHelper>
|
||||||
|
getFormFieldsForPage(QPDFPageObjectHelper);
|
||||||
|
|
||||||
// Return the terminal field that is associated with this
|
// Return the terminal field that is associated with this
|
||||||
// annotation. If the annotation dictionary is merged with the
|
// annotation. If the annotation dictionary is merged with the
|
||||||
// field dictionary, the underlying object will be the same, but
|
// field dictionary, the underlying object will be the same, but
|
||||||
@ -204,6 +209,13 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper
|
|||||||
QPDF* from_qpdf = nullptr,
|
QPDF* from_qpdf = nullptr,
|
||||||
QPDFAcroFormDocumentHelper* from_afdh = nullptr);
|
QPDFAcroFormDocumentHelper* from_afdh = nullptr);
|
||||||
|
|
||||||
|
// Copy form fields from a page in a different QPDF object to this
|
||||||
|
// QPDF.
|
||||||
|
QPDF_DLL
|
||||||
|
void copyFieldsFromForeignPage(
|
||||||
|
QPDFPageObjectHelper foreign_page,
|
||||||
|
QPDFAcroFormDocumentHelper& foreign_afdh);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void analyze();
|
void analyze();
|
||||||
void traverseField(QPDFObjectHandle field,
|
void traverseField(QPDFObjectHandle field,
|
||||||
|
@ -54,6 +54,13 @@ class QPDFFormFieldObjectHelper: public QPDFObjectHelper
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFFormFieldObjectHelper getParent();
|
QPDFFormFieldObjectHelper getParent();
|
||||||
|
|
||||||
|
// Return the top-level field for this field. Typically this will
|
||||||
|
// be the field itself or its parent. If is_different is provided,
|
||||||
|
// it is set to true if the top-level field is different from the
|
||||||
|
// field itself; otherwise it is set to false.
|
||||||
|
QPDF_DLL
|
||||||
|
QPDFFormFieldObjectHelper getTopLevelField(bool* is_different = nullptr);
|
||||||
|
|
||||||
// Get a field value, possibly inheriting the value from an
|
// Get a field value, possibly inheriting the value from an
|
||||||
// ancestor node.
|
// ancestor node.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
|
@ -132,6 +132,23 @@ QPDFAcroFormDocumentHelper::getWidgetAnnotationsForPage(QPDFPageObjectHelper h)
|
|||||||
return h.getAnnotations("/Widget");
|
return h.getAnnotations("/Widget");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<QPDFFormFieldObjectHelper>
|
||||||
|
QPDFAcroFormDocumentHelper::getFormFieldsForPage(QPDFPageObjectHelper ph)
|
||||||
|
{
|
||||||
|
std::vector<QPDFFormFieldObjectHelper> result;
|
||||||
|
auto widget_annotations = getWidgetAnnotationsForPage(ph);
|
||||||
|
for (auto annot: widget_annotations)
|
||||||
|
{
|
||||||
|
auto field = getFieldForAnnotation(annot);
|
||||||
|
field = field.getTopLevelField();
|
||||||
|
if (field.getObjectHandle().isDictionary())
|
||||||
|
{
|
||||||
|
result.push_back(field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QPDFFormFieldObjectHelper
|
QPDFFormFieldObjectHelper
|
||||||
QPDFAcroFormDocumentHelper::getFieldForAnnotation(QPDFAnnotationObjectHelper h)
|
QPDFAcroFormDocumentHelper::getFieldForAnnotation(QPDFAnnotationObjectHelper h)
|
||||||
{
|
{
|
||||||
@ -501,19 +518,8 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
|
|||||||
// annotation and field separately in this case.
|
// annotation and field separately in this case.
|
||||||
have_field = true;
|
have_field = true;
|
||||||
// Find the top-level field. It may be the field itself.
|
// Find the top-level field. It may be the field itself.
|
||||||
top_field = ffield_oh;
|
top_field = ffield.getTopLevelField(
|
||||||
std::set<QPDFObjGen> seen;
|
&have_parent).getObjectHandle();
|
||||||
while (! top_field.getKey("/Parent").isNull())
|
|
||||||
{
|
|
||||||
top_field = top_field.getKey("/Parent");
|
|
||||||
have_parent = true;
|
|
||||||
auto og = top_field.getObjGen();
|
|
||||||
if (seen.count(og))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
seen.insert(og);
|
|
||||||
}
|
|
||||||
if (foreign)
|
if (foreign)
|
||||||
{
|
{
|
||||||
// copyForeignObject returns the same value if called
|
// copyForeignObject returns the same value if called
|
||||||
@ -537,7 +543,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
|
|||||||
{
|
{
|
||||||
queue.push_back(top_field);
|
queue.push_back(top_field);
|
||||||
}
|
}
|
||||||
seen.clear();
|
std::set<QPDFObjGen> seen;
|
||||||
while (! queue.empty())
|
while (! queue.empty())
|
||||||
{
|
{
|
||||||
QPDFObjectHandle obj = queue.front();
|
QPDFObjectHandle obj = queue.front();
|
||||||
@ -664,3 +670,16 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
|
|||||||
"/Rect", QPDFObjectHandle::newFromRectangle(rect));
|
"/Rect", QPDFObjectHandle::newFromRectangle(rect));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFAcroFormDocumentHelper::copyFieldsFromForeignPage(
|
||||||
|
QPDFPageObjectHelper foreign_page,
|
||||||
|
QPDFAcroFormDocumentHelper& foreign_afdh)
|
||||||
|
{
|
||||||
|
for (auto field: foreign_afdh.getFormFieldsForPage(foreign_page))
|
||||||
|
{
|
||||||
|
auto new_field = this->qpdf.copyForeignObject(
|
||||||
|
field.getObjectHandle());
|
||||||
|
addFormField(new_field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -39,6 +39,29 @@ QPDFFormFieldObjectHelper::getParent()
|
|||||||
return this->oh.getKey("/Parent"); // may be null
|
return this->oh.getKey("/Parent"); // may be null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPDFFormFieldObjectHelper
|
||||||
|
QPDFFormFieldObjectHelper::getTopLevelField(bool* is_different)
|
||||||
|
{
|
||||||
|
auto top_field = this->oh;
|
||||||
|
std::set<QPDFObjGen> seen;
|
||||||
|
while (top_field.isDictionary() &&
|
||||||
|
(! top_field.getKey("/Parent").isNull()))
|
||||||
|
{
|
||||||
|
top_field = top_field.getKey("/Parent");
|
||||||
|
if (is_different)
|
||||||
|
{
|
||||||
|
*is_different = true;
|
||||||
|
}
|
||||||
|
auto og = top_field.getObjGen();
|
||||||
|
if (seen.count(og))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
seen.insert(og);
|
||||||
|
}
|
||||||
|
return QPDFFormFieldObjectHelper(top_field);
|
||||||
|
}
|
||||||
|
|
||||||
QPDFObjectHandle
|
QPDFObjectHandle
|
||||||
QPDFFormFieldObjectHelper::getInheritableFieldValue(std::string const& name)
|
QPDFFormFieldObjectHelper::getInheritableFieldValue(std::string const& name)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user