PyPDFForm 2.0.1__py3-none-any.whl → 2.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of PyPDFForm might be problematic. Click here for more details.
- PyPDFForm/__init__.py +6 -2
- PyPDFForm/adapter.py +37 -3
- PyPDFForm/constants.py +12 -1
- PyPDFForm/coordinate.py +218 -59
- PyPDFForm/filler.py +104 -9
- PyPDFForm/font.py +80 -16
- PyPDFForm/image.py +32 -3
- PyPDFForm/middleware/base.py +57 -8
- PyPDFForm/middleware/checkbox.py +49 -7
- PyPDFForm/middleware/dropdown.py +41 -5
- PyPDFForm/middleware/image.py +26 -2
- PyPDFForm/middleware/radio.py +41 -5
- PyPDFForm/middleware/signature.py +49 -6
- PyPDFForm/middleware/text.py +55 -7
- PyPDFForm/patterns.py +108 -10
- PyPDFForm/template.py +181 -29
- PyPDFForm/utils.py +108 -12
- PyPDFForm/watermark.py +151 -9
- PyPDFForm/widgets/base.py +65 -9
- PyPDFForm/widgets/checkbox.py +22 -2
- PyPDFForm/widgets/dropdown.py +31 -3
- PyPDFForm/widgets/radio.py +78 -0
- PyPDFForm/widgets/text.py +19 -2
- PyPDFForm/wrapper.py +338 -27
- {pypdfform-2.0.1.dist-info → pypdfform-2.1.0.dist-info}/METADATA +1 -1
- pypdfform-2.1.0.dist-info/RECORD +31 -0
- pypdfform-2.0.1.dist-info/RECORD +0 -30
- {pypdfform-2.0.1.dist-info → pypdfform-2.1.0.dist-info}/WHEEL +0 -0
- {pypdfform-2.0.1.dist-info → pypdfform-2.1.0.dist-info}/licenses/LICENSE +0 -0
- {pypdfform-2.0.1.dist-info → pypdfform-2.1.0.dist-info}/top_level.txt +0 -0
PyPDFForm/watermark.py
CHANGED
|
@@ -1,18 +1,41 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
"""
|
|
2
|
+
"""Provides watermark generation, annotation copying, and merging functionality for PDF forms.
|
|
3
|
+
|
|
4
|
+
This module handles:
|
|
5
|
+
- Drawing text, images, shapes, and lines onto PDF watermarks
|
|
6
|
+
- Managing watermark styles and properties
|
|
7
|
+
- Merging watermarks with PDF documents
|
|
8
|
+
- Copying annotation widgets (form fields) from watermark PDFs onto base PDFs
|
|
9
|
+
- Supporting various drawing operations needed for form filling
|
|
10
|
+
"""
|
|
3
11
|
|
|
4
12
|
from io import BytesIO
|
|
5
13
|
from typing import List
|
|
6
14
|
|
|
7
15
|
from pypdf import PdfReader, PdfWriter
|
|
16
|
+
from pypdf.generic import ArrayObject, NameObject
|
|
8
17
|
from reportlab.lib.utils import ImageReader
|
|
9
18
|
from reportlab.pdfgen.canvas import Canvas
|
|
10
19
|
|
|
20
|
+
from .constants import Annots
|
|
11
21
|
from .utils import stream_to_io
|
|
12
22
|
|
|
13
23
|
|
|
14
24
|
def draw_text(*args) -> None:
|
|
15
|
-
"""Draws a
|
|
25
|
+
"""Draws text onto a watermark canvas with proper formatting.
|
|
26
|
+
|
|
27
|
+
Handles:
|
|
28
|
+
- Comb fields (fixed character spacing)
|
|
29
|
+
- Multiline text with wrapping
|
|
30
|
+
- Font and color styling
|
|
31
|
+
- Text alignment
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
args[0]: Canvas object to draw on
|
|
35
|
+
args[1]: Text widget with content and properties
|
|
36
|
+
args[2]: X coordinate for drawing
|
|
37
|
+
args[3]: Y coordinate for drawing
|
|
38
|
+
"""
|
|
16
39
|
|
|
17
40
|
canvas = args[0]
|
|
18
41
|
widget = args[1]
|
|
@@ -73,7 +96,19 @@ def draw_text(*args) -> None:
|
|
|
73
96
|
|
|
74
97
|
|
|
75
98
|
def draw_rect(*args) -> None:
|
|
76
|
-
"""Draws a rectangle
|
|
99
|
+
"""Draws a rectangle onto a watermark canvas.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
args[0]: Canvas object to draw on
|
|
103
|
+
args[1]: X coordinate of bottom-left corner
|
|
104
|
+
args[2]: Y coordinate of bottom-left corner
|
|
105
|
+
args[3]: Width of rectangle
|
|
106
|
+
args[4]: Height of rectangle
|
|
107
|
+
args[5]: Border color
|
|
108
|
+
args[6]: Background color
|
|
109
|
+
args[7]: Border width
|
|
110
|
+
args[8]: Dash pattern for border
|
|
111
|
+
"""
|
|
77
112
|
|
|
78
113
|
canvas = args[0]
|
|
79
114
|
x = args[1]
|
|
@@ -88,7 +123,19 @@ def draw_rect(*args) -> None:
|
|
|
88
123
|
|
|
89
124
|
|
|
90
125
|
def draw_ellipse(*args) -> None:
|
|
91
|
-
"""Draws an ellipse
|
|
126
|
+
"""Draws an ellipse onto a watermark canvas.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
args[0]: Canvas object to draw on
|
|
130
|
+
args[1]: X coordinate of first bounding point
|
|
131
|
+
args[2]: Y coordinate of first bounding point
|
|
132
|
+
args[3]: X coordinate of second bounding point
|
|
133
|
+
args[4]: Y coordinate of second bounding point
|
|
134
|
+
args[5]: Border color
|
|
135
|
+
args[6]: Background color
|
|
136
|
+
args[7]: Border width
|
|
137
|
+
args[8]: Dash pattern for border
|
|
138
|
+
"""
|
|
92
139
|
|
|
93
140
|
canvas = args[0]
|
|
94
141
|
x1 = args[1]
|
|
@@ -103,7 +150,19 @@ def draw_ellipse(*args) -> None:
|
|
|
103
150
|
|
|
104
151
|
|
|
105
152
|
def draw_line(*args) -> None:
|
|
106
|
-
"""Draws a line
|
|
153
|
+
"""Draws a line onto a watermark canvas.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
args[0]: Canvas object to draw on
|
|
157
|
+
args[1]: X coordinate of start point
|
|
158
|
+
args[2]: Y coordinate of start point
|
|
159
|
+
args[3]: X coordinate of end point
|
|
160
|
+
args[4]: Y coordinate of end point
|
|
161
|
+
args[5]: Line color
|
|
162
|
+
args[6]: Unused (kept for consistency)
|
|
163
|
+
args[7]: Line width
|
|
164
|
+
args[8]: Dash pattern for line
|
|
165
|
+
"""
|
|
107
166
|
|
|
108
167
|
canvas = args[0]
|
|
109
168
|
src_x = args[1]
|
|
@@ -118,7 +177,18 @@ def draw_line(*args) -> None:
|
|
|
118
177
|
|
|
119
178
|
|
|
120
179
|
def set_border_and_background_styles(*args) -> tuple:
|
|
121
|
-
"""
|
|
180
|
+
"""Configures stroke and fill styles for drawing operations.
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
args[0]: Canvas object to configure
|
|
184
|
+
args[5]: Border color
|
|
185
|
+
args[6]: Background color
|
|
186
|
+
args[7]: Border width
|
|
187
|
+
args[8]: Dash pattern for border
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
tuple: (stroke_flag, fill_flag) indicating which styles were set
|
|
191
|
+
"""
|
|
122
192
|
|
|
123
193
|
canvas = args[0]
|
|
124
194
|
border_color = args[5]
|
|
@@ -143,7 +213,16 @@ def set_border_and_background_styles(*args) -> tuple:
|
|
|
143
213
|
|
|
144
214
|
|
|
145
215
|
def draw_image(*args) -> None:
|
|
146
|
-
"""Draws an image
|
|
216
|
+
"""Draws an image onto a watermark canvas.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
args[0]: Canvas object to draw on
|
|
220
|
+
args[1]: Image data as bytes
|
|
221
|
+
args[2]: X coordinate for drawing
|
|
222
|
+
args[3]: Y coordinate for drawing
|
|
223
|
+
args[4]: Width of drawn image
|
|
224
|
+
args[5]: Height of drawn image
|
|
225
|
+
"""
|
|
147
226
|
|
|
148
227
|
canvas = args[0]
|
|
149
228
|
image_stream = args[1]
|
|
@@ -174,7 +253,17 @@ def create_watermarks_and_draw(
|
|
|
174
253
|
action_type: str,
|
|
175
254
|
actions: List[list],
|
|
176
255
|
) -> List[bytes]:
|
|
177
|
-
"""Creates
|
|
256
|
+
"""Creates watermarks for each page with specified drawing operations.
|
|
257
|
+
|
|
258
|
+
Args:
|
|
259
|
+
pdf: PDF document as bytes
|
|
260
|
+
page_number: Page number to create watermark for (1-based)
|
|
261
|
+
action_type: Type of drawing operation ('text', 'image', 'line', etc.)
|
|
262
|
+
actions: List of drawing operations to perform
|
|
263
|
+
|
|
264
|
+
Returns:
|
|
265
|
+
List[bytes]: Watermark data for each page (empty for non-target pages)
|
|
266
|
+
"""
|
|
178
267
|
|
|
179
268
|
pdf_file = PdfReader(stream_to_io(pdf))
|
|
180
269
|
buff = BytesIO()
|
|
@@ -218,7 +307,15 @@ def merge_watermarks_with_pdf(
|
|
|
218
307
|
pdf: bytes,
|
|
219
308
|
watermarks: list,
|
|
220
309
|
) -> bytes:
|
|
221
|
-
"""
|
|
310
|
+
"""Combines watermarks with their corresponding PDF pages.
|
|
311
|
+
|
|
312
|
+
Args:
|
|
313
|
+
pdf: Original PDF document as bytes
|
|
314
|
+
watermarks: List of watermark data for each page
|
|
315
|
+
|
|
316
|
+
Returns:
|
|
317
|
+
bytes: Merged PDF document with watermarks applied
|
|
318
|
+
"""
|
|
222
319
|
|
|
223
320
|
result = BytesIO()
|
|
224
321
|
pdf_file = PdfReader(stream_to_io(pdf))
|
|
@@ -234,3 +331,48 @@ def merge_watermarks_with_pdf(
|
|
|
234
331
|
output.write(result)
|
|
235
332
|
result.seek(0)
|
|
236
333
|
return result.read()
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def copy_watermark_widgets(
|
|
337
|
+
pdf: bytes,
|
|
338
|
+
watermarks: list,
|
|
339
|
+
) -> bytes:
|
|
340
|
+
"""Copies annotation widgets from watermark PDFs onto the corresponding pages of a base PDF.
|
|
341
|
+
|
|
342
|
+
For each watermark in the provided list, any annotation widgets (such as form fields)
|
|
343
|
+
are cloned and appended to the annotations of the corresponding page in the base PDF.
|
|
344
|
+
|
|
345
|
+
Args:
|
|
346
|
+
pdf: The original PDF document as bytes.
|
|
347
|
+
watermarks: List of watermark PDF data (as bytes), one per page. Empty or None entries are skipped.
|
|
348
|
+
|
|
349
|
+
Returns:
|
|
350
|
+
bytes: The resulting PDF document with annotation widgets from watermarks copied onto their respective pages.
|
|
351
|
+
"""
|
|
352
|
+
|
|
353
|
+
pdf_file = PdfReader(stream_to_io(pdf))
|
|
354
|
+
out = PdfWriter()
|
|
355
|
+
out.append(pdf_file)
|
|
356
|
+
|
|
357
|
+
widgets_to_copy = {}
|
|
358
|
+
|
|
359
|
+
for i, watermark in enumerate(watermarks):
|
|
360
|
+
if not watermark:
|
|
361
|
+
continue
|
|
362
|
+
|
|
363
|
+
widgets_to_copy[i] = []
|
|
364
|
+
watermark_file = PdfReader(stream_to_io(watermark))
|
|
365
|
+
for page in watermark_file.pages:
|
|
366
|
+
for annot in page.get(Annots, []): # noqa
|
|
367
|
+
widgets_to_copy[i].append(annot.clone(out))
|
|
368
|
+
|
|
369
|
+
for i, page in enumerate(out.pages):
|
|
370
|
+
if i in widgets_to_copy:
|
|
371
|
+
page[NameObject(Annots)] = page[NameObject(Annots)] + ArrayObject(
|
|
372
|
+
widgets_to_copy[i]
|
|
373
|
+
) # noqa
|
|
374
|
+
|
|
375
|
+
with BytesIO() as f:
|
|
376
|
+
out.write(f)
|
|
377
|
+
f.seek(0)
|
|
378
|
+
return f.read()
|
PyPDFForm/widgets/base.py
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
"""
|
|
2
|
+
"""Provides base widget class and utilities for PDF form field creation.
|
|
3
|
+
|
|
4
|
+
This module contains:
|
|
5
|
+
- Widget base class with core form field creation functionality
|
|
6
|
+
- Watermark generation for form fields
|
|
7
|
+
- Parameter handling for both AcroForm and non-AcroForm fields
|
|
8
|
+
"""
|
|
3
9
|
|
|
4
10
|
from io import BytesIO
|
|
5
|
-
from typing import List, cast
|
|
11
|
+
from typing import List, Union, cast
|
|
6
12
|
|
|
7
13
|
from pypdf import PdfReader, PdfWriter
|
|
8
14
|
from pypdf.generic import DictionaryObject
|
|
@@ -15,7 +21,21 @@ from ..utils import extract_widget_property, stream_to_io
|
|
|
15
21
|
|
|
16
22
|
|
|
17
23
|
class Widget:
|
|
18
|
-
"""
|
|
24
|
+
"""Abstract base class for all PDF form widget creators.
|
|
25
|
+
|
|
26
|
+
Provides common functionality for:
|
|
27
|
+
- Managing widget parameters
|
|
28
|
+
- Generating watermarks for form fields
|
|
29
|
+
- Handling both AcroForm and non-AcroForm parameters
|
|
30
|
+
- PDF page integration
|
|
31
|
+
|
|
32
|
+
Attributes:
|
|
33
|
+
USER_PARAMS: List of (user_name, pdf_param) mappings
|
|
34
|
+
COLOR_PARAMS: List of color parameters to convert
|
|
35
|
+
ALLOWED_NON_ACRO_FORM_PARAMS: Supported non-AcroForm parameters
|
|
36
|
+
NONE_DEFAULTS: Parameters that should default to None
|
|
37
|
+
ACRO_FORM_FUNC: Name of AcroForm function for widget creation
|
|
38
|
+
"""
|
|
19
39
|
|
|
20
40
|
USER_PARAMS = []
|
|
21
41
|
COLOR_PARAMS = []
|
|
@@ -27,11 +47,19 @@ class Widget:
|
|
|
27
47
|
self,
|
|
28
48
|
name: str,
|
|
29
49
|
page_number: int,
|
|
30
|
-
x: float,
|
|
31
|
-
y: float,
|
|
50
|
+
x: Union[float, List[float]],
|
|
51
|
+
y: Union[float, List[float]],
|
|
32
52
|
**kwargs,
|
|
33
53
|
) -> None:
|
|
34
|
-
"""
|
|
54
|
+
"""Initializes a new widget with position and parameters.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
name: Field name/key for the widget
|
|
58
|
+
page_number: Page number to place widget on (1-based)
|
|
59
|
+
x: X coordinate(s) for widget position
|
|
60
|
+
y: Y coordinate(s) for widget position
|
|
61
|
+
**kwargs: Additional widget-specific parameters
|
|
62
|
+
"""
|
|
35
63
|
|
|
36
64
|
super().__init__()
|
|
37
65
|
self.page_number = page_number
|
|
@@ -63,8 +91,27 @@ class Widget:
|
|
|
63
91
|
((type(self).__name__, each), kwargs.get(each))
|
|
64
92
|
)
|
|
65
93
|
|
|
94
|
+
def canvas_operations(self, canvas: Canvas) -> None:
|
|
95
|
+
"""Draws the widget on the provided PDF canvas using AcroForm.
|
|
96
|
+
|
|
97
|
+
Calls the appropriate AcroForm function on the canvas to create the widget
|
|
98
|
+
with the parameters specified in self.acro_form_params.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
canvas: The ReportLab Canvas object to draw the widget on.
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
getattr(canvas.acroForm, self.ACRO_FORM_FUNC)(**self.acro_form_params)
|
|
105
|
+
|
|
66
106
|
def watermarks(self, stream: bytes) -> List[bytes]:
|
|
67
|
-
"""
|
|
107
|
+
"""Generates watermarks containing the widget for each page.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
stream: PDF document as bytes to add widget to
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
List[bytes]: Watermark data for each page (empty for non-target pages)
|
|
114
|
+
"""
|
|
68
115
|
|
|
69
116
|
pdf = PdfReader(stream_to_io(stream))
|
|
70
117
|
page_count = len(pdf.pages)
|
|
@@ -78,7 +125,7 @@ class Widget:
|
|
|
78
125
|
),
|
|
79
126
|
)
|
|
80
127
|
|
|
81
|
-
|
|
128
|
+
self.canvas_operations(canvas)
|
|
82
129
|
|
|
83
130
|
canvas.showPage()
|
|
84
131
|
canvas.save()
|
|
@@ -91,7 +138,16 @@ class Widget:
|
|
|
91
138
|
|
|
92
139
|
|
|
93
140
|
def handle_non_acro_form_params(pdf: bytes, key: str, params: list) -> bytes:
|
|
94
|
-
"""
|
|
141
|
+
"""Processes non-AcroForm parameters for a widget.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
pdf: PDF document as bytes to modify
|
|
145
|
+
key: Field name/key of the widget to update
|
|
146
|
+
params: List of (parameter_name, value) tuples to set
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
bytes: Modified PDF with updated parameters
|
|
150
|
+
"""
|
|
95
151
|
|
|
96
152
|
pdf_file = PdfReader(stream_to_io(pdf))
|
|
97
153
|
out = PdfWriter()
|
PyPDFForm/widgets/checkbox.py
CHANGED
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
"""
|
|
2
|
+
"""Provides checkbox widget creation functionality for PDF forms.
|
|
3
|
+
|
|
4
|
+
This module contains the CheckBoxWidget class which handles creation of:
|
|
5
|
+
- Interactive checkbox fields with three states (checked, unchecked, read-only)
|
|
6
|
+
- Custom button styles (check, cross, circle)
|
|
7
|
+
- Color styling for tick, background and border
|
|
8
|
+
- Size adjustments
|
|
9
|
+
- PDF form field integration
|
|
10
|
+
|
|
11
|
+
Supports all standard PDF checkbox properties and integrates with both
|
|
12
|
+
AcroForm and non-AcroForm PDF documents.
|
|
13
|
+
"""
|
|
3
14
|
|
|
4
15
|
from .base import Widget
|
|
5
16
|
|
|
6
17
|
|
|
7
18
|
class CheckBoxWidget(Widget):
|
|
8
|
-
"""
|
|
19
|
+
"""Creates and configures PDF checkbox widgets.
|
|
20
|
+
|
|
21
|
+
Supports all standard checkbox properties including:
|
|
22
|
+
- Button style customization (check, cross, circle)
|
|
23
|
+
- Tick, background and border colors
|
|
24
|
+
- Size adjustments
|
|
25
|
+
- PDF form field integration
|
|
26
|
+
|
|
27
|
+
Inherits from Widget base class adding checkbox-specific parameters.
|
|
28
|
+
"""
|
|
9
29
|
|
|
10
30
|
USER_PARAMS = [
|
|
11
31
|
("size", "size"),
|
PyPDFForm/widgets/dropdown.py
CHANGED
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
"""
|
|
2
|
+
"""Provides dropdown widget creation functionality for PDF forms.
|
|
3
|
+
|
|
4
|
+
This module contains the DropdownWidget class which handles creation of:
|
|
5
|
+
- Interactive dropdown/combobox fields
|
|
6
|
+
- Option list management
|
|
7
|
+
- Visual styling inheritance from text fields
|
|
8
|
+
- Form field integration
|
|
9
|
+
"""
|
|
3
10
|
|
|
4
11
|
from .text import TextWidget
|
|
5
12
|
|
|
6
13
|
|
|
7
14
|
class DropdownWidget(TextWidget):
|
|
8
|
-
"""
|
|
15
|
+
"""Creates and configures PDF dropdown widgets.
|
|
16
|
+
|
|
17
|
+
Extends TextWidget to support dropdown/combobox functionality including:
|
|
18
|
+
- Option list management
|
|
19
|
+
- Initial value selection
|
|
20
|
+
- All inherited text field styling options
|
|
21
|
+
|
|
22
|
+
Class Attributes:
|
|
23
|
+
NONE_DEFAULTS: Empty list - dropdowns require options
|
|
24
|
+
ACRO_FORM_FUNC: Uses underlying text field creation function
|
|
25
|
+
"""
|
|
9
26
|
|
|
10
27
|
NONE_DEFAULTS = []
|
|
11
28
|
ACRO_FORM_FUNC = "_textfield"
|
|
@@ -18,7 +35,18 @@ class DropdownWidget(TextWidget):
|
|
|
18
35
|
y: float,
|
|
19
36
|
**kwargs,
|
|
20
37
|
) -> None:
|
|
21
|
-
"""
|
|
38
|
+
"""Initializes a new dropdown widget with options.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
name: Field name/key for the dropdown
|
|
42
|
+
page_number: Page number to place widget on (1-based)
|
|
43
|
+
x: X coordinate for widget position
|
|
44
|
+
y: Y coordinate for widget position
|
|
45
|
+
**kwargs: Additional widget parameters including:
|
|
46
|
+
width/height: Field dimensions
|
|
47
|
+
font/font_size: Text styling
|
|
48
|
+
options: List of dropdown choices
|
|
49
|
+
"""
|
|
22
50
|
|
|
23
51
|
self.USER_PARAMS = super().USER_PARAMS[:-1] + [
|
|
24
52
|
("options", "options"),
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""Provides radio button widget creation functionality for PDF forms.
|
|
3
|
+
|
|
4
|
+
This module contains the RadioWidget class which handles creation of:
|
|
5
|
+
- Interactive radio button fields for mutually exclusive selections
|
|
6
|
+
- Custom button styles and color styling
|
|
7
|
+
- Size adjustments
|
|
8
|
+
- PDF form field integration
|
|
9
|
+
|
|
10
|
+
Supports all standard PDF radio button properties and integrates with both
|
|
11
|
+
AcroForm and non-AcroForm PDF documents.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from typing import List
|
|
15
|
+
|
|
16
|
+
from reportlab.pdfgen.canvas import Canvas
|
|
17
|
+
|
|
18
|
+
from .checkbox import CheckBoxWidget
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class RadioWidget(CheckBoxWidget):
|
|
22
|
+
"""Creates and configures PDF radio button widgets.
|
|
23
|
+
|
|
24
|
+
Supports all standard radio button properties including:
|
|
25
|
+
- Mutually exclusive selection handling
|
|
26
|
+
- Button style customization and color styling
|
|
27
|
+
- Size adjustments
|
|
28
|
+
- PDF form field integration
|
|
29
|
+
|
|
30
|
+
Inherits from CheckBoxWidget, adding radio-specific parameters and logic.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
ACRO_FORM_FUNC = "radio"
|
|
34
|
+
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
name: str,
|
|
38
|
+
page_number: int,
|
|
39
|
+
x: List[float],
|
|
40
|
+
y: List[float],
|
|
41
|
+
**kwargs,
|
|
42
|
+
) -> None:
|
|
43
|
+
"""Initializes a new radio button widget with options.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
name: Field name/key for the radio group.
|
|
47
|
+
page_number: Page number to place widget on (1-based).
|
|
48
|
+
x: List of X coordinates for each radio button.
|
|
49
|
+
y: List of Y coordinates for each radio button.
|
|
50
|
+
**kwargs: Additional widget parameters including:
|
|
51
|
+
width/height: Field dimensions.
|
|
52
|
+
font/font_size: Text styling.
|
|
53
|
+
options: List of radio button choices.
|
|
54
|
+
shape: Button style (e.g., circle, check, cross, etc.).
|
|
55
|
+
color: Button color and border styling.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
self.USER_PARAMS.append(("shape", "shape"))
|
|
59
|
+
super().__init__(name, page_number, x, y, **kwargs)
|
|
60
|
+
|
|
61
|
+
def canvas_operations(self, canvas: Canvas) -> None:
|
|
62
|
+
"""Draws all radio button options on the provided PDF canvas.
|
|
63
|
+
|
|
64
|
+
Iterates over each (x, y) coordinate pair for the radio button group,
|
|
65
|
+
sets the value for each option, and calls the AcroForm radio function
|
|
66
|
+
to render each button on the canvas.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
canvas: The ReportLab Canvas object to draw the radio buttons on.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
for i, x in enumerate(self.acro_form_params["x"]):
|
|
73
|
+
y = self.acro_form_params["y"][i]
|
|
74
|
+
new_acro_form_params = self.acro_form_params.copy()
|
|
75
|
+
new_acro_form_params["x"] = x
|
|
76
|
+
new_acro_form_params["y"] = y
|
|
77
|
+
new_acro_form_params["value"] = str(i)
|
|
78
|
+
getattr(canvas.acroForm, self.ACRO_FORM_FUNC)(**new_acro_form_params)
|
PyPDFForm/widgets/text.py
CHANGED
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
"""
|
|
2
|
+
"""Provides text field widget creation functionality for PDF forms.
|
|
3
|
+
|
|
4
|
+
This module contains the TextWidget class which handles creation of:
|
|
5
|
+
- Standard text input fields
|
|
6
|
+
- Multiline text fields
|
|
7
|
+
- Font and color styling
|
|
8
|
+
- Field size and length constraints
|
|
9
|
+
"""
|
|
3
10
|
|
|
4
11
|
from .base import Widget
|
|
5
12
|
|
|
6
13
|
|
|
7
14
|
class TextWidget(Widget):
|
|
8
|
-
"""
|
|
15
|
+
"""Creates and configures PDF text field widgets.
|
|
16
|
+
|
|
17
|
+
Supports all standard text field properties including:
|
|
18
|
+
- Font styling (family, size, color)
|
|
19
|
+
- Background and border colors
|
|
20
|
+
- Width/height dimensions
|
|
21
|
+
- Maximum length constraints
|
|
22
|
+
- Alignment and multiline options
|
|
23
|
+
|
|
24
|
+
Inherits from Widget base class adding text-specific parameters.
|
|
25
|
+
"""
|
|
9
26
|
|
|
10
27
|
USER_PARAMS = [
|
|
11
28
|
("width", "width"),
|