PyPDFForm 1.3.5__tar.gz → 1.4.0__tar.gz

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.

Files changed (39) hide show
  1. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PKG-INFO +20 -4
  2. PyPDFForm-1.4.0/PyPDFForm/__init__.py +6 -0
  3. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm/core/constants.py +1 -1
  4. PyPDFForm-1.4.0/PyPDFForm/core/coordinate.py +155 -0
  5. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm/core/filler.py +17 -17
  6. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm/core/font.py +38 -44
  7. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm/core/patterns.py +15 -14
  8. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm/core/template.py +64 -65
  9. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm/core/utils.py +35 -35
  10. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm/core/watermark.py +30 -32
  11. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm/middleware/checkbox.py +6 -6
  12. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm/middleware/constants.py +3 -1
  13. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm/middleware/dropdown.py +6 -6
  14. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm/middleware/radio.py +6 -6
  15. PyPDFForm-1.4.0/PyPDFForm/middleware/template.py +76 -0
  16. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm/middleware/text.py +6 -6
  17. PyPDFForm-1.3.5/PyPDFForm/middleware/element.py → PyPDFForm-1.4.0/PyPDFForm/middleware/widget.py +10 -10
  18. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm/wrapper.py +82 -34
  19. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm.egg-info/PKG-INFO +20 -4
  20. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm.egg-info/SOURCES.txt +1 -1
  21. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/README.md +19 -3
  22. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/tests/test_dropdown.py +10 -10
  23. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/tests/test_fill_max_length_text_field.py +9 -9
  24. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/tests/test_functional.py +77 -54
  25. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/tests/test_paragraph.py +11 -11
  26. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/tests/test_preview.py +6 -6
  27. PyPDFForm-1.3.5/PyPDFForm/__init__.py +0 -8
  28. PyPDFForm-1.3.5/PyPDFForm/core/coordinate.py +0 -155
  29. PyPDFForm-1.3.5/PyPDFForm/middleware/template.py +0 -78
  30. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/LICENSE +0 -0
  31. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm/core/__init__.py +0 -0
  32. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm/core/image.py +0 -0
  33. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm/middleware/__init__.py +0 -0
  34. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm/middleware/adapter.py +0 -0
  35. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm.egg-info/dependency_links.txt +0 -0
  36. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm.egg-info/requires.txt +0 -0
  37. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/PyPDFForm.egg-info/top_level.txt +0 -0
  38. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/setup.cfg +0 -0
  39. {PyPDFForm-1.3.5 → PyPDFForm-1.4.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyPDFForm
3
- Version: 1.3.5
3
+ Version: 1.4.0
4
4
  Summary: The Python library for PDF forms.
5
5
  Home-page: https://github.com/chinapandaman/PyPDFForm
6
6
  Author: Jinge Li
@@ -24,12 +24,28 @@ Requires-Dist: reportlab
24
24
  <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-orange.svg"></a>
25
25
  </p>
26
26
 
27
+ ## Important API Changes
28
+
29
+ Happy new year fellow developers! We start the year 2024 with a new release of v1.4.0 and
30
+ there are some important changes I'm making to the APIs of the library.
31
+
32
+ * The PDF object that gets instantiated is now `PyPDFForm.PdfWrapper`, changed from `PyPDFForm.PyPDFForm`.
33
+ * Form widgets are now accessed via the `PdfWrapper.widgets` attribute, changed from `PdfWrapper.elements`.
34
+ * The JSON schema of the form data is now accessed via a new attribute called `PdfWrapper.schema`,
35
+ changed from the old method of `PdfWrapper.generate_schema()`.
36
+
37
+ All the old APIs will be persisted for half a year and then fully deprecated. Each of them
38
+ will emit a `DeprecationWarning` when invoked, so it is advised that you make the switch before they are
39
+ removed and start breaking your code.
40
+
41
+ Happy hacking!
42
+
27
43
  ## Introduction
28
44
 
29
45
  PyPDFForm is a pure Python library for PDF form processing.
30
46
  It allows filling a PDF form programmatically by creating
31
47
  a Python dictionary with keys matching its annotated names
32
- for elements like text fields and checkboxes. It also supports other functionalities such as
48
+ for widgets like text fields and checkboxes. It also supports other functionalities such as
33
49
  drawing image and merging multiple PDFs together.
34
50
 
35
51
  ## Installing
@@ -48,7 +64,7 @@ A sample PDF form can be found [here](https://github.com/chinapandaman/PyPDFForm
48
64
  ```python
49
65
  import os
50
66
 
51
- from PyPDFForm import PyPDFForm
67
+ from PyPDFForm import PdfWrapper
52
68
 
53
69
  PATH_TO_DOWNLOADED_SAMPLE_PDF_FORM = os.path.join(
54
70
  os.path.expanduser("~/Downloads"), "sample_template.pdf"
@@ -60,7 +76,7 @@ PATH_TO_FILLED_PDF_FORM = os.path.join(
60
76
 
61
77
  with open(PATH_TO_FILLED_PDF_FORM, "wb+") as output:
62
78
  output.write(
63
- PyPDFForm(PATH_TO_DOWNLOADED_SAMPLE_PDF_FORM)
79
+ PdfWrapper(PATH_TO_DOWNLOADED_SAMPLE_PDF_FORM)
64
80
  .fill(
65
81
  {
66
82
  "test": "test_1",
@@ -0,0 +1,6 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Contains any object users might need."""
3
+
4
+ __version__ = "1.4.0"
5
+
6
+ from .wrapper import PdfWrapper, PyPDFForm
@@ -6,7 +6,7 @@ ANNOTATION_FIELD_KEY = "/T"
6
6
  ANNOTATION_RECTANGLE_KEY = "/Rect"
7
7
  SUBTYPE_KEY = "/Subtype"
8
8
  WIDGET_SUBTYPE_KEY = "/Widget"
9
- ELEMENT_TYPE_KEY = "/FT"
9
+ WIDGET_TYPE_KEY = "/FT"
10
10
  PARENT_KEY = "/Parent"
11
11
  FIELD_FLAG_KEY = "/Ff"
12
12
  TEXT_FIELD_IDENTIFIER = "/Tx"
@@ -0,0 +1,155 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Contains helpers for coordinates calculations."""
3
+
4
+ from copy import deepcopy
5
+ from typing import List, Tuple, Union
6
+
7
+ from pdfrw import PdfDict
8
+ from reportlab.pdfbase.pdfmetrics import stringWidth
9
+
10
+ from ..middleware.text import Text
11
+ from .constants import ANNOTATION_RECTANGLE_KEY
12
+ from .template import (get_char_rect_width, get_widget_alignment,
13
+ is_text_multiline)
14
+
15
+
16
+ def get_draw_checkbox_radio_coordinates(
17
+ widget: PdfDict,
18
+ widget_middleware: Text,
19
+ ) -> Tuple[Union[float, int], Union[float, int]]:
20
+ """Returns coordinates to draw at given a PDF form checkbox/radio widget."""
21
+
22
+ string_height = widget_middleware.font_size * 96 / 72
23
+ width_mid_point = (
24
+ float(widget[ANNOTATION_RECTANGLE_KEY][0])
25
+ + float(widget[ANNOTATION_RECTANGLE_KEY][2])
26
+ ) / 2
27
+ height_mid_point = (
28
+ float(widget[ANNOTATION_RECTANGLE_KEY][1])
29
+ + float(widget[ANNOTATION_RECTANGLE_KEY][3])
30
+ ) / 2
31
+
32
+ return (
33
+ width_mid_point
34
+ - stringWidth(
35
+ widget_middleware.value,
36
+ widget_middleware.font,
37
+ widget_middleware.font_size,
38
+ )
39
+ / 2,
40
+ (height_mid_point - string_height / 2 + height_mid_point) / 2,
41
+ )
42
+
43
+
44
+ def get_draw_text_coordinates(
45
+ widget: PdfDict, widget_middleware: Text
46
+ ) -> Tuple[Union[float, int], Union[float, int]]:
47
+ """Returns coordinates to draw text at given a PDF form text widget."""
48
+
49
+ if widget_middleware.preview:
50
+ return (
51
+ float(widget[ANNOTATION_RECTANGLE_KEY][0]),
52
+ float(widget[ANNOTATION_RECTANGLE_KEY][3]) + 5,
53
+ )
54
+
55
+ text_value = widget_middleware.value or ""
56
+ length = (
57
+ min(len(text_value), widget_middleware.max_length)
58
+ if widget_middleware.max_length is not None
59
+ else len(text_value)
60
+ )
61
+ text_value = text_value[:length]
62
+
63
+ if widget_middleware.text_wrap_length is not None:
64
+ text_value = text_value[: widget_middleware.text_wrap_length]
65
+
66
+ character_paddings = (
67
+ widget_middleware.character_paddings[:length]
68
+ if widget_middleware.character_paddings is not None
69
+ else widget_middleware.character_paddings
70
+ )
71
+
72
+ alignment = get_widget_alignment(widget) or 0
73
+ x = float(widget[ANNOTATION_RECTANGLE_KEY][0])
74
+
75
+ if int(alignment) != 0:
76
+ width_mid_point = (
77
+ float(widget[ANNOTATION_RECTANGLE_KEY][0])
78
+ + float(widget[ANNOTATION_RECTANGLE_KEY][2])
79
+ ) / 2
80
+ string_width = stringWidth(
81
+ text_value,
82
+ widget_middleware.font,
83
+ widget_middleware.font_size,
84
+ )
85
+ if widget_middleware.comb is True and length:
86
+ string_width = character_paddings[-1] + stringWidth(
87
+ text_value[-1],
88
+ widget_middleware.font,
89
+ widget_middleware.font_size,
90
+ )
91
+
92
+ if int(alignment) == 1:
93
+ x = width_mid_point - string_width / 2
94
+ elif int(alignment) == 2:
95
+ x = float(widget[ANNOTATION_RECTANGLE_KEY][2]) - string_width
96
+ if length > 0 and widget_middleware.comb is True:
97
+ x -= (
98
+ get_char_rect_width(widget, widget_middleware)
99
+ - stringWidth(
100
+ text_value[-1],
101
+ widget_middleware.font,
102
+ widget_middleware.font_size,
103
+ )
104
+ ) / 2
105
+
106
+ string_height = widget_middleware.font_size * 96 / 72
107
+ height_mid_point = (
108
+ float(widget[ANNOTATION_RECTANGLE_KEY][1])
109
+ + float(widget[ANNOTATION_RECTANGLE_KEY][3])
110
+ ) / 2
111
+ y = (height_mid_point - string_height / 2 + height_mid_point) / 2
112
+ if is_text_multiline(widget):
113
+ y = float(widget[ANNOTATION_RECTANGLE_KEY][3]) - string_height / 1.5
114
+
115
+ if int(alignment) == 1 and widget_middleware.comb is True and length != 0:
116
+ x -= character_paddings[0] / 2
117
+ if length % 2 == 0:
118
+ x -= (
119
+ character_paddings[0]
120
+ + stringWidth(
121
+ text_value[:1],
122
+ widget_middleware.font,
123
+ widget_middleware.font_size,
124
+ )
125
+ / 2
126
+ )
127
+
128
+ return x, y
129
+
130
+
131
+ def get_text_line_x_coordinates(
132
+ widget: PdfDict, widget_middleware: Text
133
+ ) -> Union[List[float], None]:
134
+ """
135
+ Returns the x coordinates to draw lines
136
+ of the text at given a PDF form paragraph widget.
137
+ """
138
+
139
+ if (
140
+ widget_middleware.text_wrap_length is not None
141
+ and widget_middleware.text_lines is not None
142
+ and len(widget_middleware.text_lines)
143
+ and isinstance(widget_middleware.value, str)
144
+ and len(widget_middleware.value) > widget_middleware.text_wrap_length
145
+ ):
146
+ result = []
147
+ _widget = deepcopy(widget_middleware)
148
+ for each in widget_middleware.text_lines:
149
+ _widget.value = each
150
+ _widget.text_wrap_length = None
151
+ result.append(get_draw_text_coordinates(widget, _widget)[0])
152
+
153
+ return result
154
+
155
+ return None
@@ -6,20 +6,20 @@ from typing import Dict
6
6
  from pdfrw import PdfReader
7
7
 
8
8
  from ..middleware.checkbox import Checkbox
9
- from ..middleware.constants import ELEMENT_TYPES
9
+ from ..middleware.constants import WIDGET_TYPES
10
10
  from ..middleware.radio import Radio
11
11
  from .coordinate import (get_draw_checkbox_radio_coordinates,
12
12
  get_draw_text_coordinates,
13
13
  get_text_line_x_coordinates)
14
14
  from .font import checkbox_radio_font_size
15
- from .template import get_element_key, get_elements_by_page
15
+ from .template import get_widget_key, get_widgets_by_page
16
16
  from .utils import checkbox_radio_to_draw, generate_stream
17
17
  from .watermark import create_watermarks_and_draw, merge_watermarks_with_pdf
18
18
 
19
19
 
20
20
  def fill(
21
21
  template_stream: bytes,
22
- elements: Dict[str, ELEMENT_TYPES],
22
+ widgets: Dict[str, WIDGET_TYPES],
23
23
  ) -> bytes:
24
24
  """Fills a PDF using watermarks."""
25
25
 
@@ -30,31 +30,31 @@ def fill(
30
30
 
31
31
  radio_button_tracker = {}
32
32
 
33
- for page, _elements in get_elements_by_page(template_pdf).items():
33
+ for page, _widgets in get_widgets_by_page(template_pdf).items():
34
34
  texts_to_draw[page] = []
35
35
  text_watermarks.append(b"")
36
- for _element in _elements:
37
- key = get_element_key(_element)
36
+ for _widget in _widgets:
37
+ key = get_widget_key(_widget)
38
38
  needs_to_be_drawn = False
39
39
 
40
- if isinstance(elements[key], (Checkbox, Radio)):
41
- font_size = checkbox_radio_font_size(_element)
42
- _to_draw = checkbox_radio_to_draw(elements[key], font_size)
43
- x, y = get_draw_checkbox_radio_coordinates(_element, _to_draw)
44
- if isinstance(elements[key], Checkbox) and elements[key].value:
40
+ if isinstance(widgets[key], (Checkbox, Radio)):
41
+ font_size = checkbox_radio_font_size(_widget)
42
+ _to_draw = checkbox_radio_to_draw(widgets[key], font_size)
43
+ x, y = get_draw_checkbox_radio_coordinates(_widget, _to_draw)
44
+ if isinstance(widgets[key], Checkbox) and widgets[key].value:
45
45
  needs_to_be_drawn = True
46
- elif isinstance(elements[key], Radio):
46
+ elif isinstance(widgets[key], Radio):
47
47
  if key not in radio_button_tracker:
48
48
  radio_button_tracker[key] = 0
49
49
  radio_button_tracker[key] += 1
50
- if elements[key].value == radio_button_tracker[key] - 1:
50
+ if widgets[key].value == radio_button_tracker[key] - 1:
51
51
  needs_to_be_drawn = True
52
52
  else:
53
- elements[key].text_line_x_coordinates = get_text_line_x_coordinates(
54
- _element, elements[key]
53
+ widgets[key].text_line_x_coordinates = get_text_line_x_coordinates(
54
+ _widget, widgets[key]
55
55
  )
56
- x, y = get_draw_text_coordinates(_element, elements[key])
57
- _to_draw = elements[key]
56
+ x, y = get_draw_text_coordinates(_widget, widgets[key])
57
+ _to_draw = widgets[key]
58
58
  needs_to_be_drawn = True
59
59
 
60
60
  if needs_to_be_drawn:
@@ -10,15 +10,14 @@ from pdfrw import PdfDict, PdfReader
10
10
  from reportlab.pdfbase.pdfmetrics import registerFont, standardFonts
11
11
  from reportlab.pdfbase.ttfonts import TTFError, TTFont
12
12
 
13
- from ..middleware.constants import ELEMENT_TYPES
13
+ from ..middleware.constants import WIDGET_TYPES
14
14
  from ..middleware.text import Text
15
15
  from .constants import (ANNOTATION_RECTANGLE_KEY, DEFAULT_FONT,
16
16
  DEFAULT_FONT_SIZE, FONT_COLOR_IDENTIFIER,
17
17
  FONT_SIZE_IDENTIFIER)
18
18
  from .patterns import TEXT_FIELD_APPEARANCE_PATTERNS
19
- from .template import (get_element_key, get_elements_by_page,
20
- get_paragraph_auto_wrap_length, get_paragraph_lines,
21
- is_text_multiline)
19
+ from .template import (get_paragraph_auto_wrap_length, get_paragraph_lines,
20
+ get_widget_key, get_widgets_by_page, is_text_multiline)
22
21
  from .utils import traverse_pattern
23
22
 
24
23
 
@@ -39,14 +38,14 @@ def register_font(font_name: str, ttf_stream: bytes) -> bool:
39
38
  return result
40
39
 
41
40
 
42
- def auto_detect_font(element: PdfDict) -> str:
41
+ def auto_detect_font(widget: PdfDict) -> str:
43
42
  """Returns the font of the text field if it is one of the standard fonts."""
44
43
 
45
44
  result = DEFAULT_FONT
46
45
 
47
46
  text_appearance = None
48
47
  for pattern in TEXT_FIELD_APPEARANCE_PATTERNS:
49
- text_appearance = traverse_pattern(pattern, element)
48
+ text_appearance = traverse_pattern(pattern, widget)
50
49
 
51
50
  if text_appearance:
52
51
  break
@@ -76,46 +75,46 @@ def auto_detect_font(element: PdfDict) -> str:
76
75
  return result
77
76
 
78
77
 
79
- def text_field_font_size(element: PdfDict) -> Union[float, int]:
78
+ def text_field_font_size(widget: PdfDict) -> Union[float, int]:
80
79
  """
81
80
  Calculates the font size it should be drawn with
82
- given a text field element.
81
+ given a text field widget.
83
82
  """
84
83
 
85
- if is_text_multiline(element):
84
+ if is_text_multiline(widget):
86
85
  return DEFAULT_FONT_SIZE
87
86
 
88
87
  height = abs(
89
- float(element[ANNOTATION_RECTANGLE_KEY][1])
90
- - float(element[ANNOTATION_RECTANGLE_KEY][3])
88
+ float(widget[ANNOTATION_RECTANGLE_KEY][1])
89
+ - float(widget[ANNOTATION_RECTANGLE_KEY][3])
91
90
  )
92
91
 
93
92
  return height * 2 / 3
94
93
 
95
94
 
96
- def checkbox_radio_font_size(element: PdfDict) -> Union[float, int]:
95
+ def checkbox_radio_font_size(widget: PdfDict) -> Union[float, int]:
97
96
  """
98
97
  Calculates the font size it should be drawn with
99
- given a checkbox/radio button element.
98
+ given a checkbox/radio button widget.
100
99
  """
101
100
 
102
101
  area = abs(
103
- float(element[ANNOTATION_RECTANGLE_KEY][0])
104
- - float(element[ANNOTATION_RECTANGLE_KEY][2])
102
+ float(widget[ANNOTATION_RECTANGLE_KEY][0])
103
+ - float(widget[ANNOTATION_RECTANGLE_KEY][2])
105
104
  ) * abs(
106
- float(element[ANNOTATION_RECTANGLE_KEY][1])
107
- - float(element[ANNOTATION_RECTANGLE_KEY][3])
105
+ float(widget[ANNOTATION_RECTANGLE_KEY][1])
106
+ - float(widget[ANNOTATION_RECTANGLE_KEY][3])
108
107
  )
109
108
 
110
109
  return sqrt(area) * 72 / 96
111
110
 
112
111
 
113
- def get_text_field_font_size(element: PdfDict) -> Union[float, int]:
112
+ def get_text_field_font_size(widget: PdfDict) -> Union[float, int]:
114
113
  """Returns the font size of the text field if presented or zero."""
115
114
 
116
115
  result = 0
117
116
  for pattern in TEXT_FIELD_APPEARANCE_PATTERNS:
118
- text_appearance = traverse_pattern(pattern, element)
117
+ text_appearance = traverse_pattern(pattern, widget)
119
118
  if text_appearance:
120
119
  text_appearance = text_appearance.replace("(", "").replace(")", "")
121
120
  properties = text_appearance.split(" ")
@@ -127,13 +126,13 @@ def get_text_field_font_size(element: PdfDict) -> Union[float, int]:
127
126
 
128
127
 
129
128
  def get_text_field_font_color(
130
- element: PdfDict,
129
+ widget: PdfDict,
131
130
  ) -> Union[Tuple[float, float, float], None]:
132
131
  """Returns the font color tuple of the text field if presented or black."""
133
132
 
134
133
  result = (0, 0, 0)
135
134
  for pattern in TEXT_FIELD_APPEARANCE_PATTERNS:
136
- text_appearance = traverse_pattern(pattern, element)
135
+ text_appearance = traverse_pattern(pattern, widget)
137
136
  if text_appearance:
138
137
  if FONT_COLOR_IDENTIFIER not in text_appearance:
139
138
  return result
@@ -155,32 +154,27 @@ def get_text_field_font_color(
155
154
 
156
155
  def update_text_field_attributes(
157
156
  template_stream: bytes,
158
- elements: Dict[str, ELEMENT_TYPES],
157
+ widgets: Dict[str, WIDGET_TYPES],
159
158
  ) -> None:
160
159
  """Auto updates text fields' attributes."""
161
160
 
162
161
  template_pdf = PdfReader(fdata=template_stream)
163
162
 
164
- for _, _elements in get_elements_by_page(template_pdf).items():
165
- for _element in _elements:
166
- key = get_element_key(_element)
167
-
168
- if isinstance(elements[key], Text):
169
- if elements[key].font is None:
170
- elements[key].font = auto_detect_font(_element)
171
- if elements[key].font_size is None:
172
- elements[key].font_size = get_text_field_font_size(
173
- _element
174
- ) or text_field_font_size(_element)
175
- if elements[key].font_color is None:
176
- elements[key].font_color = get_text_field_font_color(_element)
177
- if (
178
- is_text_multiline(_element)
179
- and elements[key].text_wrap_length is None
180
- ):
181
- elements[key].text_wrap_length = get_paragraph_auto_wrap_length(
182
- _element, elements[key]
183
- )
184
- elements[key].text_lines = get_paragraph_lines(
185
- _element, elements[key]
163
+ for _, _widgets in get_widgets_by_page(template_pdf).items():
164
+ for _widget in _widgets:
165
+ key = get_widget_key(_widget)
166
+
167
+ if isinstance(widgets[key], Text):
168
+ if widgets[key].font is None:
169
+ widgets[key].font = auto_detect_font(_widget)
170
+ if widgets[key].font_size is None:
171
+ widgets[key].font_size = get_text_field_font_size(
172
+ _widget
173
+ ) or text_field_font_size(_widget)
174
+ if widgets[key].font_color is None:
175
+ widgets[key].font_color = get_text_field_font_color(_widget)
176
+ if is_text_multiline(_widget) and widgets[key].text_wrap_length is None:
177
+ widgets[key].text_wrap_length = get_paragraph_auto_wrap_length(
178
+ _widget, widgets[key]
186
179
  )
180
+ widgets[key].text_lines = get_paragraph_lines(_widget, widgets[key])
@@ -1,52 +1,53 @@
1
1
  # -*- coding: utf-8 -*-
2
- """Contains patterns used for identifying properties of elements."""
2
+ """Contains patterns used for identifying properties of widgets."""
3
3
 
4
4
  from ..middleware.checkbox import Checkbox
5
5
  from ..middleware.dropdown import Dropdown
6
6
  from ..middleware.radio import Radio
7
7
  from ..middleware.text import Text
8
8
  from .constants import (ANNOTATION_FIELD_KEY, CHOICE_FIELD_IDENTIFIER,
9
- CHOICES_IDENTIFIER, ELEMENT_TYPE_KEY, FIELD_FLAG_KEY,
10
- PARENT_KEY, SELECTABLE_IDENTIFIER, SUBTYPE_KEY,
9
+ CHOICES_IDENTIFIER, FIELD_FLAG_KEY, PARENT_KEY,
10
+ SELECTABLE_IDENTIFIER, SUBTYPE_KEY,
11
11
  TEXT_FIELD_ALIGNMENT_IDENTIFIER,
12
12
  TEXT_FIELD_APPEARANCE_IDENTIFIER,
13
- TEXT_FIELD_IDENTIFIER, WIDGET_SUBTYPE_KEY)
13
+ TEXT_FIELD_IDENTIFIER, WIDGET_SUBTYPE_KEY,
14
+ WIDGET_TYPE_KEY)
14
15
 
15
- ELEMENT_TYPE_PATTERNS = [
16
+ WIDGET_TYPE_PATTERNS = [
16
17
  (
17
- ({ELEMENT_TYPE_KEY: TEXT_FIELD_IDENTIFIER},),
18
+ ({WIDGET_TYPE_KEY: TEXT_FIELD_IDENTIFIER},),
18
19
  Text,
19
20
  ),
20
21
  (
21
- ({ELEMENT_TYPE_KEY: SELECTABLE_IDENTIFIER},),
22
+ ({WIDGET_TYPE_KEY: SELECTABLE_IDENTIFIER},),
22
23
  Checkbox,
23
24
  ),
24
25
  (
25
- ({ELEMENT_TYPE_KEY: CHOICE_FIELD_IDENTIFIER},),
26
+ ({WIDGET_TYPE_KEY: CHOICE_FIELD_IDENTIFIER},),
26
27
  Dropdown,
27
28
  ),
28
29
  (
29
- ({PARENT_KEY: {ELEMENT_TYPE_KEY: CHOICE_FIELD_IDENTIFIER}},),
30
+ ({PARENT_KEY: {WIDGET_TYPE_KEY: CHOICE_FIELD_IDENTIFIER}},),
30
31
  Dropdown,
31
32
  ),
32
33
  (
33
- ({PARENT_KEY: {ELEMENT_TYPE_KEY: TEXT_FIELD_IDENTIFIER}},),
34
+ ({PARENT_KEY: {WIDGET_TYPE_KEY: TEXT_FIELD_IDENTIFIER}},),
34
35
  Text,
35
36
  ),
36
37
  (
37
38
  (
38
- {PARENT_KEY: {ELEMENT_TYPE_KEY: SELECTABLE_IDENTIFIER}},
39
+ {PARENT_KEY: {WIDGET_TYPE_KEY: SELECTABLE_IDENTIFIER}},
39
40
  {PARENT_KEY: {SUBTYPE_KEY: WIDGET_SUBTYPE_KEY}},
40
41
  ),
41
42
  Checkbox,
42
43
  ),
43
44
  (
44
- ({PARENT_KEY: {ELEMENT_TYPE_KEY: SELECTABLE_IDENTIFIER}},),
45
+ ({PARENT_KEY: {WIDGET_TYPE_KEY: SELECTABLE_IDENTIFIER}},),
45
46
  Radio,
46
47
  ),
47
48
  ]
48
49
 
49
- ELEMENT_KEY_PATTERNS = [
50
+ WIDGET_KEY_PATTERNS = [
50
51
  {ANNOTATION_FIELD_KEY: True},
51
52
  {PARENT_KEY: {ANNOTATION_FIELD_KEY: True}},
52
53
  ]
@@ -56,7 +57,7 @@ DROPDOWN_CHOICE_PATTERNS = [
56
57
  {PARENT_KEY: {CHOICES_IDENTIFIER: True}},
57
58
  ]
58
59
 
59
- ELEMENT_ALIGNMENT_PATTERNS = [
60
+ WIDGET_ALIGNMENT_PATTERNS = [
60
61
  {TEXT_FIELD_ALIGNMENT_IDENTIFIER: True},
61
62
  {PARENT_KEY: {TEXT_FIELD_ALIGNMENT_IDENTIFIER: True}},
62
63
  ]