Skip to content

Commit 57d1d63

Browse files
committed
Allow arbitrary ON values for CheckBoxes
We previously insisted that the ON-values for CheckBoxes are defined as "Yes" in the PDF (the published recommended value). This fix introduces lifts this restriction and supports arbitrary values as ON for check boxes. So a check box turns to OFF if setting its field value to `False` or "Off". It is set to ON if the field value is set to any of 'True`, "Yes" or the respective value coded in the PDF. When checking a check box's value, the return values invariably are either "Off" or the ON-value in the PDF. Which value this is, can be checked via method `on_state()`.
1 parent 63a3a08 commit 57d1d63

File tree

3 files changed

+61
-8
lines changed

3 files changed

+61
-8
lines changed

src/__init__.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7269,8 +7269,6 @@ def on_state(self):
72697269
"""
72707270
if self.field_type not in (2, 5):
72717271
return None # no checkbox or radio button
7272-
if self.field_type == 2:
7273-
return "Yes"
72747272
bstate = self.button_states()
72757273
if bstate is None:
72767274
bstate = dict()
@@ -17681,13 +17679,13 @@ def GETATTR(name):
1768117679
mupdf.pdf_dict_put_name(annot_obj, PDF_NAME('AS'), on)
1768217680
elif text:
1768317681
mupdf.pdf_dict_put_name(annot_obj, PDF_NAME('AS'), text)
17684-
elif field_type == mupdf.PDF_WIDGET_TYPE_CHECKBOX: # will always be "Yes" or "Off"
17685-
if value is True or text == 'Yes':
17686-
onstate = mupdf.pdf_button_field_on_state(annot_obj)
17687-
on = mupdf.pdf_to_name(onstate)
17682+
elif field_type == mupdf.PDF_WIDGET_TYPE_CHECKBOX:
17683+
onstate = mupdf.pdf_button_field_on_state(annot_obj)
17684+
on = onstate.pdf_to_name()
17685+
if value in (True, on) or text == 'Yes':
1768817686
mupdf.pdf_set_field_value(pdf, annot_obj, on, 1)
17689-
mupdf.pdf_dict_put_name(annot_obj, PDF_NAME('AS'), 'Yes')
17690-
mupdf.pdf_dict_put_name(annot_obj, PDF_NAME('V'), 'Yes')
17687+
mupdf.pdf_dict_put_name(annot_obj, PDF_NAME('AS'), on)
17688+
mupdf.pdf_dict_put_name(annot_obj, PDF_NAME('V'), on)
1769117689
else:
1769217690
mupdf.pdf_dict_put_name( annot_obj, PDF_NAME('AS'), 'Off')
1769317691
mupdf.pdf_dict_put_name( annot_obj, PDF_NAME('V'), 'Off')

tests/resources/test-4055.pdf

69.6 KB
Binary file not shown.

tests/test_widgets.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
scriptdir = os.path.abspath(os.path.dirname(__file__))
99
filename = os.path.join(scriptdir, "resources", "widgettest.pdf")
1010
file_2333 = os.path.join(scriptdir, "resources", "test-2333.pdf")
11+
file_4055 = os.path.join(scriptdir, "resources", "test-4055.pdf")
1112

1213

1314
doc = pymupdf.open()
@@ -379,3 +380,57 @@ def get_widgets_by_name(doc):
379380
assert str(e) == 'Annot is not bound to a page'
380381

381382
doc.close()
383+
384+
385+
def test_4055():
386+
"""Check correct setting of CheckBox "Yes" values.
387+
388+
Test scope:
389+
* setting on with any of 'True' / 'Yes' / built-in values works
390+
* setting off with any of 'False' or 'Off' works
391+
"""
392+
393+
# this PDF has digits as "Yes" values.
394+
doc = pymupdf.open(file_4055)
395+
page = doc[0]
396+
397+
# Round 1: confirm all check boxes are off
398+
for w in page.widgets(types=[2]):
399+
# check that this file doesn't use the "Yes" standard
400+
assert w.on_state() != "Yes"
401+
assert w.field_value == "Off" # all check boxes are off
402+
w.field_value = w.on_state()
403+
w.update()
404+
405+
page = doc.reload_page(page) # reload page to make sure we start fresh
406+
407+
# Round 2: confirm that fields contain the PDF's own on values
408+
for w in page.widgets(types=[2]):
409+
# confirm each value coincides with the "Yes" value
410+
assert w.field_value == w.on_state()
411+
w.field_value = False # switch to "Off" using False
412+
w.update()
413+
414+
page = doc.reload_page(page)
415+
416+
# Round 3: confirm that 'False' achieved "Off" values
417+
for w in page.widgets(types=[2]):
418+
assert w.field_value == "Off"
419+
w.field_value = True # use True for the next round
420+
w.update()
421+
422+
page = doc.reload_page(page)
423+
424+
# Round 4: confirm that setting to True also worked
425+
for w in page.widgets(types=[2]):
426+
assert w.field_value == w.on_state()
427+
w.field_value = "Off" # set off again
428+
w.update()
429+
w.field_value = "Yes"
430+
w.update()
431+
432+
page = doc.reload_page(page)
433+
434+
# Round 5: final check: setting to "Yes" also does work
435+
for w in page.widgets(types=[2]):
436+
assert w.field_value == w.on_state()

0 commit comments

Comments
 (0)