Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ This can also be enabled programmatically with `warnings.simplefilter('default',

## [2.8.6] - Not released yet
### Added
* support for interactive PDF form fields (AcroForms), including `text_field()` and `checkbox()` - _cf._ [issue #257](https://github.com/py-pdf/fpdf2/issues/257)
* support for SVG `<linearGradient>` and `<radialGradient>` elements - _cf._ [issue #1580](https://github.com/py-pdf/fpdf2/issues/1580) - thanks to @Ani07-05
### Fixed
* the `A5` value that could be specified as page `format` to the `FPDF` constructor was slightly incorrect, and the corresponding page dimensions have been fixed. This could lead to a minor change in your documents dimensions if you used this `A5` page format. - _cf._ [issue #1699](https://github.com/py-pdf/fpdf2/issues/1699)
Expand Down
87 changes: 87 additions & 0 deletions docs/Forms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Interactive Forms (AcroForms)

`fpdf2` supports creating interactive PDF forms that users can fill out directly in their PDF viewer. This is implemented using the AcroForm standard.

Currently supported field types:
* **Text Fields**: Single-line, multi-line, and password inputs.
* **Checkboxes**: Toggleable buttons.

## Basic Usage

To add form fields, use the `text_field()` and `checkbox()` methods.

```python
from fpdf import FPDF

pdf = FPDF()
pdf.add_page()
pdf.set_font("Helvetica", size=12)

# Add a label and a text field
pdf.text(10, 20, "First Name:")
pdf.text_field(name="first_name", x=40, y=15, w=50, h=10, value="John")

# Add a checkbox
pdf.checkbox(name="subscribe", x=10, y=30, size=5, checked=True)
pdf.text(17, 34, "Subscribe to newsletter")

pdf.output("form.pdf")
```

## Text Fields

The `text_field()` method supports several customization options:

| Parameter | Description |
| --- | --- |
| `name` | Unique identifier for the field. |
| `value` | Initial text content. |
| `multiline` | If `True`, the field allows multiple lines of text. |
| `password` | If `True`, characters are masked (e.g., with bullets). |
| `max_length` | Maximum number of characters allowed. |
| `font_size` | Size of the text in the field. |
| `font_color_gray` | Gray level (0-1) for the text. |
| `background_color` | RGB tuple (0-1) for the field background. |
| `border_color` | RGB tuple (0-1) for the field border. |

### Example: Multiline Text Area

```python
pdf.text_field(
name="comments",
x=10,
y=50,
w=100,
h=30,
multiline=True,
value="Enter your comments here..."
)
```

## Checkboxes

The `checkbox()` method creates a toggleable button.

| Parameter | Description |
| --- | --- |
| `name` | Unique identifier for the checkbox. |
| `checked` | Initial state of the checkbox. |
| `size` | Width and height of the checkbox. |
| `check_color_gray` | Gray level (0-1) for the checkmark. |

## Field Properties

Both field types support common properties:

* `read_only`: If `True`, the user cannot modify the field value.
* `required`: If `True`, the field must be filled before the form can be submitted.

## Compatibility

`fpdf2` generates **Appearance Streams** for all form fields. This ensures that the fields are visible and rendered correctly across almost all PDF readers, including:
* Adobe Acrobat Reader
* Chrome / Firefox / Edge built-in viewers
* Sumatra PDF
* Mobile PDF viewers

Note: Form fields require PDF version 1.4 or higher. `fpdf2` will automatically set the document version to 1.4 if any form fields are added.
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Go try it **now** online in a Jupyter notebook: [![Open In Colab](https://colab.
* Table of contents & [document outline](DocumentOutlineAndTableOfContents.md)
* [Document encryption](Encryption.md) & [document signing](Signing.md)
* [Annotations](Annotations.md), including text highlights, and [file attachments](FileAttachments.md)
* Interactive [Forms](Forms.md) (AcroForms), including text fields and checkboxes
* [Presentation mode](Presentations.md) with control over page display duration & transitions
* Optional basic Markdown-like styling: `**bold**, __italics__`
* It has very few dependencies: [Pillow](https://pillow.readthedocs.io/en/stable/), [defusedxml](https://pypi.org/project/defusedxml/), & [fonttools](https://pypi.org/project/fonttools/)
Expand Down
57 changes: 57 additions & 0 deletions fpdf/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,63 @@ class SignatureFlag(IntEnum):
"""


class FieldFlag(IntFlag):
"""
Flags for form field properties (/Ff entry in field dictionary).
These can be combined with bitwise OR (|) operator.
cf. PDF spec section 12.7.3.1 "Field flags common to all field types"
and sections 12.7.4.* for type-specific flags.
"""

# Common to all field types
READ_ONLY = 1
"The user may not change the value of the field."
REQUIRED = 2
"The field shall have a value before the form can be submitted."
NO_EXPORT = 4
"The field shall not be exported by a submit-form action."

# Text field specific flags (12.7.4.3)
MULTILINE = 4096
"The field may contain multiple lines of text."
PASSWORD = 8192
"The field is intended for entering a secure password."
FILE_SELECT = 1 << 20
"The field shall allow the user to select a file."
DO_NOT_SPELL_CHECK = 1 << 22
"Text entered shall not be spell-checked."
DO_NOT_SCROLL = 1 << 23
"The field shall not scroll to accommodate more text."
COMB = 1 << 24
"The field shall be divided into equally spaced positions (for character entry)."
RICH_TEXT = 1 << 25
"The value of this field shall be a rich text string."

# Button field specific flags (12.7.4.2)
NO_TOGGLE_TO_OFF = 1 << 14
"For radio buttons: exactly one button shall be selected at all times."
RADIO = 1 << 15
"The field is a set of radio buttons (vs checkboxes)."
PUSH_BUTTON = 1 << 16
"The field is a push button that does not retain a permanent value."
# Note: RADIOS_IN_UNISON intentionally shares bit 25 with RICH_TEXT per PDF spec.
# These flags apply to different field types (buttons vs text) so no conflict occurs.
RADIOS_IN_UNISON = 1 << 25
"Radio buttons with the same value are selected/deselected in unison."

# Choice field specific flags (12.7.4.4)
COMBO = 1 << 17
"The field is a combo box (vs list box)."
EDIT = 1 << 18
"The combo box includes an editable text box."
SORT = 1 << 19
"The field's option items shall be sorted alphabetically."
MULTI_SELECT = 1 << 21
"More than one of the field's option items may be selected."
COMMIT_ON_SEL_CHANGE = 1 << 26
"Value shall be committed as soon as a selection is made."


class CoerciveEnum(Enum):
"An enumeration that provides a helper to coerce strings into enumeration members."

Expand Down
Loading