diff --git a/tests/test_api.py b/tests/test_api.py
index bad869612..16def4b69 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -491,15 +491,12 @@ def test_partial_pdf_custom_metadata():
(b''
- , [b'/Ch', b'/Opt', b'/V (b)']),
- # The selected values will be (b) and (c) in the PDF.
+ b'', [b'/Ch', b'/Opt', b'/V (b)']),
(b''
- , [b'/Ch', b'/Opt', b'[(b) (c)]']),
+ b'', [b'/Ch', b'/Opt', b'[(b) (c)]']),
))
def test_pdf_inputs(html, fields):
stdout = _run('--pdf-forms --uncompressed-pdf - -', html)
diff --git a/weasyprint/pdf/anchors.py b/weasyprint/pdf/anchors.py
index ec2839e09..ac489957b 100644
--- a/weasyprint/pdf/anchors.py
+++ b/weasyprint/pdf/anchors.py
@@ -150,7 +150,7 @@ def add_inputs(inputs, matrix, pdf, page, resources, stream, font_map,
'Subtype': '/Widget',
'Rect': pydyf.Array(rectangle),
'FT': '/Btn',
- 'F': 2 ** (3 - 1), # Print flag
+ 'F': 1 << (3 - 1), # Print flag
'P': page.reference,
'T': pydyf.String(input_name),
'V': '/Yes' if checked else '/Off',
@@ -160,8 +160,8 @@ def add_inputs(inputs, matrix, pdf, page, resources, stream, font_map,
'AS': '/Yes' if checked else '/Off',
'DA': pydyf.String(b' '.join(field_stream.stream)),
})
- elif element.tag == "select":
- # Text, password, textarea, files, and unknown
+ elif element.tag == 'select':
+ # Select fields
font_description = get_font_description(style)
font = pango.pango_font_map_load_font(
font_map, context, font_description)
@@ -169,70 +169,34 @@ def add_inputs(inputs, matrix, pdf, page, resources, stream, font_map,
font.used_in_forms = True
field_stream.set_font_size(font.hash, font_size)
- multiple = element.attrib.get("multiple") is not None
options = []
selected_values = []
for option in element:
- options.append(
- pydyf.Array(
- [f'({option.attrib.get("value")})', f'({option.text})']
- )
- )
- if option.attrib.get("selected") is not None:
- selected_values.append(
- pydyf.String(option.attrib.get("value"))
- )
-
- if multiple:
- field = pydyf.Dictionary({
- 'DA': pydyf.String(b' '.join(field_stream.stream)),
- 'F': 2 ** (3 - 1), # Print flag
- 'FT': '/Ch',
- # To be a multiselect list we need to set the 21st bit to 1
- # outputing 2097152:
- # https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/PDF32000_2008.pdf # noqa: E501
- # This specification can be found on the link above on page
- # 445.
- 'Ff': (1 << 21),
- 'Opt': pydyf.Array(options),
- 'P': page.reference,
- 'Rect': pydyf.Array(rectangle),
- 'Subtype': '/Widget',
- 'T': pydyf.String(input_name),
- 'Type': '/Annot',
- # The select value is a list of selected values that come
- # from the options with the selected property. If there are
- # no selected values, then the value is an empty string.
- 'V': pydyf.Array(selected_values)
- if len(selected_values)
- else pydyf.String(''),
- })
+ value = pydyf.String(option.attrib.get('value', ''))
+ text = pydyf.String(option.text)
+ options.append(pydyf.Array([value, text]))
+ if 'selected' in option.attrib:
+ selected_values.append(value)
+
+ field = pydyf.Dictionary({
+ 'DA': pydyf.String(b' '.join(field_stream.stream)),
+ 'F': 1 << (3 - 1), # Print flag
+ 'FT': '/Ch',
+ 'Opt': pydyf.Array(options),
+ 'P': page.reference,
+ 'Rect': pydyf.Array(rectangle),
+ 'Subtype': '/Widget',
+ 'T': pydyf.String(input_name),
+ 'Type': '/Annot',
+ })
+ if 'multiple' in element.attrib:
+ field['Ff'] = 1 << (22 - 1)
+ field['V'] = pydyf.Array(selected_values)
else:
- field = pydyf.Dictionary({
- 'DA': pydyf.String(b' '.join(field_stream.stream)),
- 'F': 2 ** (3 - 1), # Print flag
- 'FT': '/Ch',
- # To be a combo box we need to set the 17th bit to 1
- # outputing 131072:
- # https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/PDF32000_2008.pdf # noqa: E501
- # This specification can be found on the link above on page
- # 444.
- 'Ff': (1 << 17),
- 'Opt': pydyf.Array(options),
- 'P': page.reference,
- 'Rect': pydyf.Array(rectangle),
- 'Subtype': '/Widget',
- 'T': pydyf.String(input_name),
- 'Type': '/Annot',
- # Get the last value in the list when there are multiple
- # selected values in a single select box (this is the same
- # approach used by browsers).
- # If there are no selected values, then the value is an
- # empty string.
- 'V': selected_values[-1]
- if len(selected_values)
- else pydyf.String(''),
- })
+ field['Ff'] = 1 << (18 - 1)
+ field['V'] = (
+ selected_values[-1] if selected_values
+ else pydyf.String(''))
else:
# Text, password, textarea, files, and unknown
font_description = get_font_description(style)
@@ -250,24 +214,18 @@ def add_inputs(inputs, matrix, pdf, page, resources, stream, font_map,
'Subtype': '/Widget',
'Rect': pydyf.Array(rectangle),
'FT': '/Tx',
- 'F': 2 ** (3 - 1), # Print flag
+ 'F': 1 << (3 - 1), # Print flag
'P': page.reference,
'T': pydyf.String(input_name),
- # Previously if the input had no value or the value was an
- # empty string, the V key was filled with a pydyf.String(None)
- # object. This caused the PDF input/textarea to be filled with
- # the string "None". Now if the input has no value or the
- # value is an empty string, the V key is filled with a
- # pydyf.String('') object.
'V': pydyf.String(value or ''),
'DA': pydyf.String(b' '.join(field_stream.stream)),
})
if element.tag == 'textarea':
- field['Ff'] = 2 ** (13 - 1)
+ field['Ff'] = 1 << (13 - 1)
elif input_type == 'password':
- field['Ff'] = 2 ** (14 - 1)
+ field['Ff'] = 1 << (14 - 1)
elif input_type == 'file':
- field['Ff'] = 2 ** (21 - 1)
+ field['Ff'] = 1 << (21 - 1)
pdf.add_object(field)
page['Annots'].append(field.reference)