Commit c290a82fcc236a739465b8387d91ae009e8fafcb

Authored by m-holger
Committed by GitHub
2 parents 9a6cfda2 3f43b187

Merge pull request #1584 from m-holger/ffoh

Remove implementation detail from QPDFFormFieldObjectHelper.hh
include/qpdf/QPDFFormFieldObjectHelper.hh
@@ -187,23 +187,7 @@ class QPDFFormFieldObjectHelper: public QPDFObjectHelper @@ -187,23 +187,7 @@ class QPDFFormFieldObjectHelper: public QPDFObjectHelper
187 void generateAppearance(QPDFAnnotationObjectHelper&); 187 void generateAppearance(QPDFAnnotationObjectHelper&);
188 188
189 private: 189 private:
190 - QPDFObjectHandle getFieldFromAcroForm(std::string const& name);  
191 - void setRadioButtonValue(QPDFObjectHandle name);  
192 - void setCheckBoxValue(bool value);  
193 - void generateTextAppearance(QPDFAnnotationObjectHelper&);  
194 - QPDFObjectHandle getFontFromResource(QPDFObjectHandle resources, std::string const& font_name);  
195 -  
196 - class Members  
197 - {  
198 - friend class QPDFFormFieldObjectHelper;  
199 -  
200 - public:  
201 - ~Members() = default;  
202 -  
203 - private:  
204 - Members() = default;  
205 - Members(Members const&) = delete;  
206 - }; 190 + class Members;
207 191
208 std::shared_ptr<Members> m; 192 std::shared_ptr<Members> m;
209 }; 193 };
libqpdf/QPDFFormFieldObjectHelper.cc
1 #include <qpdf/QPDFFormFieldObjectHelper.hh> 1 #include <qpdf/QPDFFormFieldObjectHelper.hh>
2 2
  3 +#include <qpdf/FormField.hh>
  4 +
3 #include <qpdf/Pl_QPDFTokenizer.hh> 5 #include <qpdf/Pl_QPDFTokenizer.hh>
4 #include <qpdf/QIntC.hh> 6 #include <qpdf/QIntC.hh>
5 #include <qpdf/QPDFAcroFormDocumentHelper.hh> 7 #include <qpdf/QPDFAcroFormDocumentHelper.hh>
@@ -10,35 +12,63 @@ @@ -10,35 +12,63 @@
10 #include <qpdf/QUtil.hh> 12 #include <qpdf/QUtil.hh>
11 #include <cstdlib> 13 #include <cstdlib>
12 14
  15 +#include <memory>
  16 +
13 using namespace qpdf; 17 using namespace qpdf;
14 18
15 -QPDFFormFieldObjectHelper::QPDFFormFieldObjectHelper(QPDFObjectHandle oh) :  
16 - QPDFObjectHelper(oh),  
17 - m(new Members()) 19 +using FormField = qpdf::impl::FormField;
  20 +
  21 +class QPDFFormFieldObjectHelper::Members: public FormField
  22 +{
  23 + public:
  24 + Members(QPDFObjectHandle const& oh) :
  25 + FormField(oh)
  26 + {
  27 + }
  28 +};
  29 +
  30 +QPDFFormFieldObjectHelper::QPDFFormFieldObjectHelper(QPDFObjectHandle o) :
  31 + QPDFObjectHelper(o),
  32 + m(std::make_shared<Members>(oh()))
18 { 33 {
19 } 34 }
20 35
21 QPDFFormFieldObjectHelper::QPDFFormFieldObjectHelper() : 36 QPDFFormFieldObjectHelper::QPDFFormFieldObjectHelper() :
22 - QPDFObjectHelper(QPDFObjectHandle::newNull()),  
23 - m(new Members()) 37 + QPDFObjectHelper(Null::temp()),
  38 + m(std::make_shared<Members>(QPDFObjectHandle()))
24 { 39 {
25 } 40 }
26 41
27 bool 42 bool
28 QPDFFormFieldObjectHelper::isNull() 43 QPDFFormFieldObjectHelper::isNull()
29 { 44 {
30 - return oh().null(); 45 + return m->null();
31 } 46 }
32 47
33 QPDFFormFieldObjectHelper 48 QPDFFormFieldObjectHelper
34 QPDFFormFieldObjectHelper::getParent() 49 QPDFFormFieldObjectHelper::getParent()
35 { 50 {
36 - return oh().getKey("/Parent"); // may be null 51 + return {Null::if_null(m->getParent().oh())};
  52 +}
  53 +
  54 +FormField
  55 +FormField::getParent()
  56 +{
  57 + return {oh()["/Parent"]}; // maybe null
37 } 58 }
38 59
39 QPDFFormFieldObjectHelper 60 QPDFFormFieldObjectHelper
40 QPDFFormFieldObjectHelper::getTopLevelField(bool* is_different) 61 QPDFFormFieldObjectHelper::getTopLevelField(bool* is_different)
41 { 62 {
  63 + return Null::if_null(m->getTopLevelField(is_different).oh());
  64 +}
  65 +
  66 +FormField
  67 +FormField::getTopLevelField(bool* is_different)
  68 +{
  69 + if (!obj) {
  70 + return {};
  71 + }
42 auto top_field = oh(); 72 auto top_field = oh();
43 QPDFObjGen::set seen; 73 QPDFObjGen::set seen;
44 while (seen.add(top_field) && !top_field.getKeyIfDict("/Parent").null()) { 74 while (seen.add(top_field) && !top_field.getKeyIfDict("/Parent").null()) {
@@ -51,7 +81,7 @@ QPDFFormFieldObjectHelper::getTopLevelField(bool* is_different) @@ -51,7 +81,7 @@ QPDFFormFieldObjectHelper::getTopLevelField(bool* is_different)
51 } 81 }
52 82
53 QPDFObjectHandle 83 QPDFObjectHandle
54 -QPDFFormFieldObjectHelper::getFieldFromAcroForm(std::string const& name) 84 +FormField::getFieldFromAcroForm(std::string const& name)
55 { 85 {
56 QPDFObjectHandle result = QPDFObjectHandle::newNull(); 86 QPDFObjectHandle result = QPDFObjectHandle::newNull();
57 // Fields are supposed to be indirect, so this should work. 87 // Fields are supposed to be indirect, so this should work.
@@ -69,6 +99,12 @@ QPDFFormFieldObjectHelper::getFieldFromAcroForm(std::string const&amp; name) @@ -69,6 +99,12 @@ QPDFFormFieldObjectHelper::getFieldFromAcroForm(std::string const&amp; name)
69 QPDFObjectHandle 99 QPDFObjectHandle
70 QPDFFormFieldObjectHelper::getInheritableFieldValue(std::string const& name) 100 QPDFFormFieldObjectHelper::getInheritableFieldValue(std::string const& name)
71 { 101 {
  102 + return m->getInheritableFieldValue(name);
  103 +}
  104 +
  105 +QPDFObjectHandle
  106 +FormField::getInheritableFieldValue(std::string const& name)
  107 +{
72 QPDFObjectHandle node = oh(); 108 QPDFObjectHandle node = oh();
73 if (!node.isDictionary()) { 109 if (!node.isDictionary()) {
74 return QPDFObjectHandle::newNull(); 110 return QPDFObjectHandle::newNull();
@@ -90,6 +126,12 @@ QPDFFormFieldObjectHelper::getInheritableFieldValue(std::string const&amp; name) @@ -90,6 +126,12 @@ QPDFFormFieldObjectHelper::getInheritableFieldValue(std::string const&amp; name)
90 std::string 126 std::string
91 QPDFFormFieldObjectHelper::getInheritableFieldValueAsString(std::string const& name) 127 QPDFFormFieldObjectHelper::getInheritableFieldValueAsString(std::string const& name)
92 { 128 {
  129 + return m->getInheritableFieldValueAsString(name);
  130 +}
  131 +
  132 +std::string
  133 +FormField::getInheritableFieldValueAsString(std::string const& name)
  134 +{
93 auto fv = getInheritableFieldValue(name); 135 auto fv = getInheritableFieldValue(name);
94 if (fv.isString()) { 136 if (fv.isString()) {
95 return fv.getUTF8Value(); 137 return fv.getUTF8Value();
@@ -100,6 +142,12 @@ QPDFFormFieldObjectHelper::getInheritableFieldValueAsString(std::string const&amp; n @@ -100,6 +142,12 @@ QPDFFormFieldObjectHelper::getInheritableFieldValueAsString(std::string const&amp; n
100 std::string 142 std::string
101 QPDFFormFieldObjectHelper::getInheritableFieldValueAsName(std::string const& name) 143 QPDFFormFieldObjectHelper::getInheritableFieldValueAsName(std::string const& name)
102 { 144 {
  145 + return m->getInheritableFieldValueAsName(name);
  146 +}
  147 +
  148 +std::string
  149 +FormField::getInheritableFieldValueAsName(std::string const& name)
  150 +{
103 if (Name fv = getInheritableFieldValue(name)) { 151 if (Name fv = getInheritableFieldValue(name)) {
104 return fv; 152 return fv;
105 } 153 }
@@ -109,12 +157,24 @@ QPDFFormFieldObjectHelper::getInheritableFieldValueAsName(std::string const&amp; nam @@ -109,12 +157,24 @@ QPDFFormFieldObjectHelper::getInheritableFieldValueAsName(std::string const&amp; nam
109 std::string 157 std::string
110 QPDFFormFieldObjectHelper::getFieldType() 158 QPDFFormFieldObjectHelper::getFieldType()
111 { 159 {
  160 + return m->getFieldType();
  161 +}
  162 +
  163 +std::string
  164 +FormField::getFieldType()
  165 +{
112 return getInheritableFieldValueAsName("/FT"); 166 return getInheritableFieldValueAsName("/FT");
113 } 167 }
114 168
115 std::string 169 std::string
116 QPDFFormFieldObjectHelper::getFullyQualifiedName() 170 QPDFFormFieldObjectHelper::getFullyQualifiedName()
117 { 171 {
  172 + return m->getFullyQualifiedName();
  173 +}
  174 +
  175 +std::string
  176 +FormField::getFullyQualifiedName()
  177 +{
118 std::string result; 178 std::string result;
119 QPDFObjectHandle node = oh(); 179 QPDFObjectHandle node = oh();
120 QPDFObjGen::set seen; 180 QPDFObjGen::set seen;
@@ -133,6 +193,12 @@ QPDFFormFieldObjectHelper::getFullyQualifiedName() @@ -133,6 +193,12 @@ QPDFFormFieldObjectHelper::getFullyQualifiedName()
133 std::string 193 std::string
134 QPDFFormFieldObjectHelper::getPartialName() 194 QPDFFormFieldObjectHelper::getPartialName()
135 { 195 {
  196 + return m->getPartialName();
  197 +}
  198 +
  199 +std::string
  200 +FormField::getPartialName()
  201 +{
136 std::string result; 202 std::string result;
137 if (oh().getKey("/T").isString()) { 203 if (oh().getKey("/T").isString()) {
138 result = oh().getKey("/T").getUTF8Value(); 204 result = oh().getKey("/T").getUTF8Value();
@@ -143,6 +209,12 @@ QPDFFormFieldObjectHelper::getPartialName() @@ -143,6 +209,12 @@ QPDFFormFieldObjectHelper::getPartialName()
143 std::string 209 std::string
144 QPDFFormFieldObjectHelper::getAlternativeName() 210 QPDFFormFieldObjectHelper::getAlternativeName()
145 { 211 {
  212 + return m->getAlternativeName();
  213 +}
  214 +
  215 +std::string
  216 +FormField::getAlternativeName()
  217 +{
146 if (oh().getKey("/TU").isString()) { 218 if (oh().getKey("/TU").isString()) {
147 QTC::TC("qpdf", "QPDFFormFieldObjectHelper TU present"); 219 QTC::TC("qpdf", "QPDFFormFieldObjectHelper TU present");
148 return oh().getKey("/TU").getUTF8Value(); 220 return oh().getKey("/TU").getUTF8Value();
@@ -154,6 +226,12 @@ QPDFFormFieldObjectHelper::getAlternativeName() @@ -154,6 +226,12 @@ QPDFFormFieldObjectHelper::getAlternativeName()
154 std::string 226 std::string
155 QPDFFormFieldObjectHelper::getMappingName() 227 QPDFFormFieldObjectHelper::getMappingName()
156 { 228 {
  229 + return m->getMappingName();
  230 +}
  231 +
  232 +std::string
  233 +FormField::getMappingName()
  234 +{
157 if (oh().getKey("/TM").isString()) { 235 if (oh().getKey("/TM").isString()) {
158 QTC::TC("qpdf", "QPDFFormFieldObjectHelper TM present"); 236 QTC::TC("qpdf", "QPDFFormFieldObjectHelper TM present");
159 return oh().getKey("/TM").getUTF8Value(); 237 return oh().getKey("/TM").getUTF8Value();
@@ -165,6 +243,12 @@ QPDFFormFieldObjectHelper::getMappingName() @@ -165,6 +243,12 @@ QPDFFormFieldObjectHelper::getMappingName()
165 QPDFObjectHandle 243 QPDFObjectHandle
166 QPDFFormFieldObjectHelper::getValue() 244 QPDFFormFieldObjectHelper::getValue()
167 { 245 {
  246 + return m->getValue();
  247 +}
  248 +
  249 +QPDFObjectHandle
  250 +FormField::getValue()
  251 +{
168 return getInheritableFieldValue("/V"); 252 return getInheritableFieldValue("/V");
169 } 253 }
170 254
@@ -174,27 +258,57 @@ QPDFFormFieldObjectHelper::getValueAsString() @@ -174,27 +258,57 @@ QPDFFormFieldObjectHelper::getValueAsString()
174 return getInheritableFieldValueAsString("/V"); 258 return getInheritableFieldValueAsString("/V");
175 } 259 }
176 260
  261 +std::string
  262 +FormField::getValueAsString()
  263 +{
  264 + return getInheritableFieldValueAsString("/V");
  265 +}
  266 +
177 QPDFObjectHandle 267 QPDFObjectHandle
178 QPDFFormFieldObjectHelper::getDefaultValue() 268 QPDFFormFieldObjectHelper::getDefaultValue()
179 { 269 {
  270 + return m->getDefaultValue();
  271 +}
  272 +
  273 +QPDFObjectHandle
  274 +FormField::getDefaultValue()
  275 +{
180 return getInheritableFieldValue("/DV"); 276 return getInheritableFieldValue("/DV");
181 } 277 }
182 278
183 std::string 279 std::string
184 QPDFFormFieldObjectHelper::getDefaultValueAsString() 280 QPDFFormFieldObjectHelper::getDefaultValueAsString()
185 { 281 {
  282 + return m->getDefaultValueAsString();
  283 +}
  284 +
  285 +std::string
  286 +FormField::getDefaultValueAsString()
  287 +{
186 return getInheritableFieldValueAsString("/DV"); 288 return getInheritableFieldValueAsString("/DV");
187 } 289 }
188 290
189 QPDFObjectHandle 291 QPDFObjectHandle
190 QPDFFormFieldObjectHelper::getDefaultResources() 292 QPDFFormFieldObjectHelper::getDefaultResources()
191 { 293 {
  294 + return m->getDefaultResources();
  295 +}
  296 +
  297 +QPDFObjectHandle
  298 +FormField::getDefaultResources()
  299 +{
192 return getFieldFromAcroForm("/DR"); 300 return getFieldFromAcroForm("/DR");
193 } 301 }
194 302
195 std::string 303 std::string
196 QPDFFormFieldObjectHelper::getDefaultAppearance() 304 QPDFFormFieldObjectHelper::getDefaultAppearance()
197 { 305 {
  306 + return m->getDefaultAppearance();
  307 +}
  308 +
  309 +std::string
  310 +FormField::getDefaultAppearance()
  311 +{
198 auto value = getInheritableFieldValue("/DA"); 312 auto value = getInheritableFieldValue("/DA");
199 bool looked_in_acroform = false; 313 bool looked_in_acroform = false;
200 if (!value.isString()) { 314 if (!value.isString()) {
@@ -211,6 +325,12 @@ QPDFFormFieldObjectHelper::getDefaultAppearance() @@ -211,6 +325,12 @@ QPDFFormFieldObjectHelper::getDefaultAppearance()
211 int 325 int
212 QPDFFormFieldObjectHelper::getQuadding() 326 QPDFFormFieldObjectHelper::getQuadding()
213 { 327 {
  328 + return m->getQuadding();
  329 +}
  330 +
  331 +int
  332 +FormField::getQuadding()
  333 +{
214 QPDFObjectHandle fv = getInheritableFieldValue("/Q"); 334 QPDFObjectHandle fv = getInheritableFieldValue("/Q");
215 bool looked_in_acroform = false; 335 bool looked_in_acroform = false;
216 if (!fv.isInteger()) { 336 if (!fv.isInteger()) {
@@ -227,6 +347,12 @@ QPDFFormFieldObjectHelper::getQuadding() @@ -227,6 +347,12 @@ QPDFFormFieldObjectHelper::getQuadding()
227 int 347 int
228 QPDFFormFieldObjectHelper::getFlags() 348 QPDFFormFieldObjectHelper::getFlags()
229 { 349 {
  350 + return m->getFlags();
  351 +}
  352 +
  353 +int
  354 +FormField::getFlags()
  355 +{
230 QPDFObjectHandle f = getInheritableFieldValue("/Ff"); 356 QPDFObjectHandle f = getInheritableFieldValue("/Ff");
231 return f.isInteger() ? f.getIntValueAsInt() : 0; 357 return f.isInteger() ? f.getIntValueAsInt() : 0;
232 } 358 }
@@ -234,42 +360,84 @@ QPDFFormFieldObjectHelper::getFlags() @@ -234,42 +360,84 @@ QPDFFormFieldObjectHelper::getFlags()
234 bool 360 bool
235 QPDFFormFieldObjectHelper::isText() 361 QPDFFormFieldObjectHelper::isText()
236 { 362 {
  363 + return m->isText();
  364 +}
  365 +
  366 +bool
  367 +FormField::isText()
  368 +{
237 return getFieldType() == "/Tx"; 369 return getFieldType() == "/Tx";
238 } 370 }
239 371
240 bool 372 bool
241 QPDFFormFieldObjectHelper::isCheckbox() 373 QPDFFormFieldObjectHelper::isCheckbox()
242 { 374 {
  375 + return m->isCheckbox();
  376 +}
  377 +
  378 +bool
  379 +FormField::isCheckbox()
  380 +{
243 return getFieldType() == "/Btn" && (getFlags() & (ff_btn_radio | ff_btn_pushbutton)) == 0; 381 return getFieldType() == "/Btn" && (getFlags() & (ff_btn_radio | ff_btn_pushbutton)) == 0;
244 } 382 }
245 383
246 bool 384 bool
247 QPDFFormFieldObjectHelper::isChecked() 385 QPDFFormFieldObjectHelper::isChecked()
248 { 386 {
  387 + return m->isChecked();
  388 +}
  389 +
  390 +bool
  391 +FormField::isChecked()
  392 +{
249 return isCheckbox() && Name(getValue()) != "/Off"; 393 return isCheckbox() && Name(getValue()) != "/Off";
250 } 394 }
251 395
252 bool 396 bool
253 QPDFFormFieldObjectHelper::isRadioButton() 397 QPDFFormFieldObjectHelper::isRadioButton()
254 { 398 {
  399 + return m->isRadioButton();
  400 +}
  401 +
  402 +bool
  403 +FormField::isRadioButton()
  404 +{
255 return getFieldType() == "/Btn" && (getFlags() & ff_btn_radio) == ff_btn_radio; 405 return getFieldType() == "/Btn" && (getFlags() & ff_btn_radio) == ff_btn_radio;
256 } 406 }
257 407
258 bool 408 bool
259 QPDFFormFieldObjectHelper::isPushbutton() 409 QPDFFormFieldObjectHelper::isPushbutton()
260 { 410 {
  411 + return m->isPushbutton();
  412 +}
  413 +
  414 +bool
  415 +FormField::isPushbutton()
  416 +{
261 return getFieldType() == "/Btn" && (getFlags() & ff_btn_pushbutton) == ff_btn_pushbutton; 417 return getFieldType() == "/Btn" && (getFlags() & ff_btn_pushbutton) == ff_btn_pushbutton;
262 } 418 }
263 419
264 bool 420 bool
265 QPDFFormFieldObjectHelper::isChoice() 421 QPDFFormFieldObjectHelper::isChoice()
266 { 422 {
  423 + return m->isChoice();
  424 +}
  425 +
  426 +bool
  427 +FormField::isChoice()
  428 +{
267 return getFieldType() == "/Ch"; 429 return getFieldType() == "/Ch";
268 } 430 }
269 431
270 std::vector<std::string> 432 std::vector<std::string>
271 QPDFFormFieldObjectHelper::getChoices() 433 QPDFFormFieldObjectHelper::getChoices()
272 { 434 {
  435 + return m->getChoices();
  436 +}
  437 +
  438 +std::vector<std::string>
  439 +FormField::getChoices()
  440 +{
273 if (!isChoice()) { 441 if (!isChoice()) {
274 return {}; 442 return {};
275 } 443 }
@@ -290,18 +458,36 @@ QPDFFormFieldObjectHelper::getChoices() @@ -290,18 +458,36 @@ QPDFFormFieldObjectHelper::getChoices()
290 void 458 void
291 QPDFFormFieldObjectHelper::setFieldAttribute(std::string const& key, QPDFObjectHandle value) 459 QPDFFormFieldObjectHelper::setFieldAttribute(std::string const& key, QPDFObjectHandle value)
292 { 460 {
  461 + m->setFieldAttribute(key, value);
  462 +}
  463 +
  464 +void
  465 +FormField::setFieldAttribute(std::string const& key, QPDFObjectHandle value)
  466 +{
293 oh().replaceKey(key, value); 467 oh().replaceKey(key, value);
294 } 468 }
295 469
296 void 470 void
297 QPDFFormFieldObjectHelper::setFieldAttribute(std::string const& key, std::string const& utf8_value) 471 QPDFFormFieldObjectHelper::setFieldAttribute(std::string const& key, std::string const& utf8_value)
298 { 472 {
  473 + m->setFieldAttribute(key, utf8_value);
  474 +}
  475 +
  476 +void
  477 +FormField::setFieldAttribute(std::string const& key, std::string const& utf8_value)
  478 +{
299 oh().replaceKey(key, QPDFObjectHandle::newUnicodeString(utf8_value)); 479 oh().replaceKey(key, QPDFObjectHandle::newUnicodeString(utf8_value));
300 } 480 }
301 481
302 void 482 void
303 QPDFFormFieldObjectHelper::setV(QPDFObjectHandle value, bool need_appearances) 483 QPDFFormFieldObjectHelper::setV(QPDFObjectHandle value, bool need_appearances)
304 { 484 {
  485 + m->setV(value, need_appearances);
  486 +}
  487 +
  488 +void
  489 +FormField::setV(QPDFObjectHandle value, bool need_appearances)
  490 +{
305 Name name = value; 491 Name name = value;
306 if (getFieldType() == "/Btn") { 492 if (getFieldType() == "/Btn") {
307 if (isCheckbox()) { 493 if (isCheckbox()) {
@@ -344,11 +530,17 @@ QPDFFormFieldObjectHelper::setV(QPDFObjectHandle value, bool need_appearances) @@ -344,11 +530,17 @@ QPDFFormFieldObjectHelper::setV(QPDFObjectHandle value, bool need_appearances)
344 void 530 void
345 QPDFFormFieldObjectHelper::setV(std::string const& utf8_value, bool need_appearances) 531 QPDFFormFieldObjectHelper::setV(std::string const& utf8_value, bool need_appearances)
346 { 532 {
  533 + m->setV(utf8_value, need_appearances);
  534 +}
  535 +
  536 +void
  537 +FormField::setV(std::string const& utf8_value, bool need_appearances)
  538 +{
347 setV(QPDFObjectHandle::newUnicodeString(utf8_value), need_appearances); 539 setV(QPDFObjectHandle::newUnicodeString(utf8_value), need_appearances);
348 } 540 }
349 541
350 void 542 void
351 -QPDFFormFieldObjectHelper::setRadioButtonValue(QPDFObjectHandle name) 543 +FormField::setRadioButtonValue(QPDFObjectHandle name)
352 { 544 {
353 // Set the value of a radio button field. This has the following specific behavior: 545 // Set the value of a radio button field. This has the following specific behavior:
354 // * If this is a radio button field that has a parent that is also a radio button field and has 546 // * If this is a radio button field that has a parent that is also a radio button field and has
@@ -360,7 +552,7 @@ QPDFFormFieldObjectHelper::setRadioButtonValue(QPDFObjectHandle name) @@ -360,7 +552,7 @@ QPDFFormFieldObjectHelper::setRadioButtonValue(QPDFObjectHandle name)
360 // Note that we never turn on /NeedAppearances when setting a radio button field. 552 // Note that we never turn on /NeedAppearances when setting a radio button field.
361 QPDFObjectHandle parent = oh().getKey("/Parent"); 553 QPDFObjectHandle parent = oh().getKey("/Parent");
362 if (parent.isDictionary() && parent.getKey("/Parent").null()) { 554 if (parent.isDictionary() && parent.getKey("/Parent").null()) {
363 - QPDFFormFieldObjectHelper ph(parent); 555 + FormField ph(parent);
364 if (ph.isRadioButton()) { 556 if (ph.isRadioButton()) {
365 // This is most likely one of the individual buttons. Try calling on the parent. 557 // This is most likely one of the individual buttons. Try calling on the parent.
366 ph.setRadioButtonValue(name); 558 ph.setRadioButtonValue(name);
@@ -403,7 +595,7 @@ QPDFFormFieldObjectHelper::setRadioButtonValue(QPDFObjectHandle name) @@ -403,7 +595,7 @@ QPDFFormFieldObjectHelper::setRadioButtonValue(QPDFObjectHandle name)
403 } 595 }
404 596
405 void 597 void
406 -QPDFFormFieldObjectHelper::setCheckBoxValue(bool value) 598 +FormField::setCheckBoxValue(bool value)
407 { 599 {
408 QPDFObjectHandle AP = oh().getKey("/AP"); 600 QPDFObjectHandle AP = oh().getKey("/AP");
409 QPDFObjectHandle annot; 601 QPDFObjectHandle annot;
@@ -454,6 +646,12 @@ QPDFFormFieldObjectHelper::setCheckBoxValue(bool value) @@ -454,6 +646,12 @@ QPDFFormFieldObjectHelper::setCheckBoxValue(bool value)
454 void 646 void
455 QPDFFormFieldObjectHelper::generateAppearance(QPDFAnnotationObjectHelper& aoh) 647 QPDFFormFieldObjectHelper::generateAppearance(QPDFAnnotationObjectHelper& aoh)
456 { 648 {
  649 + m->generateAppearance(aoh);
  650 +}
  651 +
  652 +void
  653 +FormField::generateAppearance(QPDFAnnotationObjectHelper& aoh)
  654 +{
457 std::string ft = getFieldType(); 655 std::string ft = getFieldType();
458 // Ignore field types we don't know how to generate appearances for. Button fields don't really 656 // Ignore field types we don't know how to generate appearances for. Button fields don't really
459 // need them -- see code in QPDFAcroFormDocumentHelper::generateAppearancesIfNeeded. 657 // need them -- see code in QPDFAcroFormDocumentHelper::generateAppearancesIfNeeded.
@@ -729,7 +927,7 @@ namespace @@ -729,7 +927,7 @@ namespace
729 } // namespace 927 } // namespace
730 928
731 QPDFObjectHandle 929 QPDFObjectHandle
732 -QPDFFormFieldObjectHelper::getFontFromResource(QPDFObjectHandle resources, std::string const& name) 930 +FormField::getFontFromResource(QPDFObjectHandle resources, std::string const& name)
733 { 931 {
734 QPDFObjectHandle result; 932 QPDFObjectHandle result;
735 if (resources.isDictionary() && resources.getKey("/Font").isDictionary() && 933 if (resources.isDictionary() && resources.getKey("/Font").isDictionary() &&
@@ -740,7 +938,7 @@ QPDFFormFieldObjectHelper::getFontFromResource(QPDFObjectHandle resources, std:: @@ -740,7 +938,7 @@ QPDFFormFieldObjectHelper::getFontFromResource(QPDFObjectHandle resources, std::
740 } 938 }
741 939
742 void 940 void
743 -QPDFFormFieldObjectHelper::generateTextAppearance(QPDFAnnotationObjectHelper& aoh) 941 +FormField::generateTextAppearance(QPDFAnnotationObjectHelper& aoh)
744 { 942 {
745 QPDFObjectHandle AS = aoh.getAppearanceStream("/N"); 943 QPDFObjectHandle AS = aoh.getAppearanceStream("/N");
746 if (AS.null()) { 944 if (AS.null()) {
libqpdf/qpdf/FormField.hh 0 โ†’ 100644
  1 +#ifndef FORMFIELD_HH
  2 +#define FORMFIELD_HH
  3 +
  4 +#include <qpdf/QPDFObjectHandle_private.hh>
  5 +#include <qpdf/QPDFObjectHelper.hh>
  6 +
  7 +#include <vector>
  8 +
  9 +class QPDFAnnotationObjectHelper;
  10 +
  11 +namespace qpdf::impl
  12 +{
  13 + // This object helper helps with form fields for interactive forms. Please see comments in
  14 + // QPDFAcroFormDocumentHelper.hh for additional details.
  15 + class FormField: public qpdf::BaseDictionary
  16 + {
  17 + public:
  18 + FormField() = default;
  19 + FormField(FormField const&) = default;
  20 + FormField& operator=(FormField const&) = default;
  21 + FormField(FormField&&) = default;
  22 + FormField& operator=(FormField&&) = default;
  23 + ~FormField() = default;
  24 +
  25 + FormField(QPDFObjectHandle const& oh) :
  26 + BaseDictionary(oh)
  27 + {
  28 + }
  29 +
  30 + FormField(QPDFObjectHandle&& oh) :
  31 + BaseDictionary(std::move(oh))
  32 + {
  33 + }
  34 +
  35 + // Return the field's parent. A form field object helper whose underlying object is null is
  36 + // returned if there is no parent. This condition may be tested by calling isNull().
  37 + FormField getParent();
  38 +
  39 + // Return the top-level field for this field. Typically this will be the field itself or its
  40 + // parent. If is_different is provided, it is set to true if the top-level field is
  41 + // different from the field itself; otherwise it is set to false.
  42 + FormField getTopLevelField(bool* is_different = nullptr);
  43 +
  44 + // Get a field value, possibly inheriting the value from an ancestor node.
  45 + QPDFObjectHandle getInheritableFieldValue(std::string const& name);
  46 +
  47 + // Get an inherited field value as a string. If it is not a string, silently return the
  48 + // empty string.
  49 + std::string getInheritableFieldValueAsString(std::string const& name);
  50 +
  51 + // Get an inherited field value of type name as a string representing the name. If it is not
  52 + // a name, silently return the empty string.
  53 + std::string getInheritableFieldValueAsName(std::string const& name);
  54 +
  55 + // Returns the value of /FT if present, otherwise returns the empty string.
  56 + std::string getFieldType();
  57 +
  58 + std::string getFullyQualifiedName();
  59 +
  60 + std::string getPartialName();
  61 +
  62 + // Return the alternative field name (/TU), which is the field name intended to be presented
  63 + // to users. If not present, fall back to the fully qualified name.
  64 + std::string getAlternativeName();
  65 +
  66 + // Return the mapping field name (/TM). If not present, fall back to the alternative name,
  67 + // then to the partial name.
  68 + std::string getMappingName();
  69 +
  70 + QPDFObjectHandle getValue();
  71 +
  72 + // Return the field's value as a string. If this is called with a field whose value is not a
  73 + std::string getValueAsString();
  74 +
  75 + QPDFObjectHandle getDefaultValue();
  76 +
  77 + // Return the field's default value as a string. If this is called with a field whose value
  78 + // is not a string, the empty string will be silently returned.
  79 + std::string getDefaultValueAsString();
  80 +
  81 + // Return the default appearance string, taking inheritance from the field tree into
  82 + // account. Returns the empty string if the default appearance string is not available
  83 + // (because it's erroneously absent or because this is not a variable text field). If not
  84 + // found in the field hierarchy, look in /AcroForm.
  85 + std::string getDefaultAppearance();
  86 +
  87 + // Return the default resource dictionary for the field. This comes not from the field but
  88 + // from the document-level /AcroForm dictionary. While several PDF generates put a /DR key
  89 + // in the form field's dictionary, experimentation suggests that many popular readers,
  90 + // including Adobe Acrobat and Acrobat Reader, ignore any /DR item on the field.
  91 + QPDFObjectHandle getDefaultResources();
  92 +
  93 + // Return the quadding value, taking inheritance from the field tree into account. Returns 0
  94 + // if quadding is not specified. Look in /AcroForm if not found in the field hierarchy.
  95 + int getQuadding();
  96 +
  97 + // Return field flags from /Ff. The value is a logical or of pdf_form_field_flag_e as
  98 + // defined in qpdf/Constants.h//
  99 + int getFlags();
  100 +
  101 + // Methods for testing for particular types of form fields
  102 +
  103 + // Returns true if field is of type /Tx
  104 + bool isText();
  105 + // Returns true if field is of type /Btn and flags do not indicate some other type of
  106 + // button.
  107 + bool isCheckbox();
  108 +
  109 + // Returns true if field is a checkbox and is checked.
  110 + bool isChecked();
  111 +
  112 + // Returns true if field is of type /Btn and flags indicate that it is a radio button
  113 + bool isRadioButton();
  114 +
  115 + // Returns true if field is of type /Btn and flags indicate that it is a pushbutton
  116 + bool isPushbutton();
  117 +
  118 + // Returns true if fields if of type /Ch
  119 + bool isChoice();
  120 +
  121 + // Returns choices display values as UTF-8 strings
  122 + std::vector<std::string> getChoices();
  123 +
  124 + // Set an attribute to the given value. If you have a QPDFAcroFormDocumentHelper and you
  125 + // want to set the name of a field, use QPDFAcroFormDocumentHelper::setFormFieldName
  126 + // instead.
  127 + void setFieldAttribute(std::string const& key, QPDFObjectHandle value);
  128 +
  129 + // Set an attribute to the given value as a Unicode string (UTF-16 BE encoded). The input
  130 + // string should be UTF-8 encoded. If you have a QPDFAcroFormDocumentHelper and you want to
  131 + // set the name of a field, use QPDFAcroFormDocumentHelper::setFormFieldName instead.
  132 + void setFieldAttribute(std::string const& key, std::string const& utf8_value);
  133 +
  134 + // Set /V (field value) to the given value. If need_appearances is true and the field type
  135 + // is either /Tx (text) or /Ch (choice), set /NeedAppearances to true. You can explicitly
  136 + // tell this method not to set /NeedAppearances if you are going to generate an appearance
  137 + // stream yourself. Starting with qpdf 8.3.0, this method handles fields of type /Btn
  138 + // (checkboxes, radio buttons, pushbuttons) specially. When setting a checkbox value, any
  139 + // value other than /Off will be treated as on, and the actual value set will be based on
  140 + // the appearance stream's /N dictionary, so the value that ends up in /V may not exactly
  141 + // match the value you pass in.
  142 + void setV(QPDFObjectHandle value, bool need_appearances = true);
  143 +
  144 + // Set /V (field value) to the given string value encoded as a Unicode string. The input
  145 + // value should be UTF-8 encoded. See comments above about /NeedAppearances.
  146 + void setV(std::string const& utf8_value, bool need_appearances = true);
  147 +
  148 + // Update the appearance stream for this field. Note that qpdf's ability to generate
  149 + // appearance streams is limited. We only generate appearance streams for streams of type
  150 + // text or choice. The appearance uses the default parameters provided in the file, and it
  151 + // only supports ASCII characters. Quadding is currently ignored. While this functionality
  152 + // is limited, it should do a decent job on properly constructed PDF files when field values
  153 + // are restricted to ASCII characters.
  154 + void generateAppearance(QPDFAnnotationObjectHelper&);
  155 +
  156 + private:
  157 + QPDFObjectHandle getFieldFromAcroForm(std::string const& name);
  158 + void setRadioButtonValue(QPDFObjectHandle name);
  159 + void setCheckBoxValue(bool value);
  160 + void generateTextAppearance(QPDFAnnotationObjectHelper&);
  161 + QPDFObjectHandle
  162 + getFontFromResource(QPDFObjectHandle resources, std::string const& font_name);
  163 + };
  164 +} // namespace qpdf::impl
  165 +
  166 +#endif // FORMFIELD_HH