Skip to content

Commit

Permalink
Merge pull request #428 from chinapandaman/PPF-427
Browse files Browse the repository at this point in the history
PPF-427: renaming element to widget
  • Loading branch information
chinapandaman authored Dec 24, 2023
2 parents 1e780b1 + 4766b69 commit db20750
Show file tree
Hide file tree
Showing 22 changed files with 411 additions and 390 deletions.
2 changes: 1 addition & 1 deletion PyPDFForm/core/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
ANNOTATION_RECTANGLE_KEY = "/Rect"
SUBTYPE_KEY = "/Subtype"
WIDGET_SUBTYPE_KEY = "/Widget"
ELEMENT_TYPE_KEY = "/FT"
WIDGET_TYPE_KEY = "/FT"
PARENT_KEY = "/Parent"
FIELD_FLAG_KEY = "/Ff"
TEXT_FIELD_IDENTIFIER = "/Tx"
Expand Down
130 changes: 65 additions & 65 deletions PyPDFForm/core/coordinate.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,118 +9,118 @@

from ..middleware.text import Text
from .constants import ANNOTATION_RECTANGLE_KEY
from .template import (get_char_rect_width, get_element_alignment,
from .template import (get_char_rect_width, get_widget_alignment,
is_text_multiline)


def get_draw_checkbox_radio_coordinates(
element: PdfDict,
element_middleware: Text,
widget: PdfDict,
widget_middleware: Text,
) -> Tuple[Union[float, int], Union[float, int]]:
"""Returns coordinates to draw at given a PDF form checkbox/radio element."""
"""Returns coordinates to draw at given a PDF form checkbox/radio widget."""

string_height = element_middleware.font_size * 96 / 72
string_height = widget_middleware.font_size * 96 / 72
width_mid_point = (
float(element[ANNOTATION_RECTANGLE_KEY][0])
+ float(element[ANNOTATION_RECTANGLE_KEY][2])
float(widget[ANNOTATION_RECTANGLE_KEY][0])
+ float(widget[ANNOTATION_RECTANGLE_KEY][2])
) / 2
height_mid_point = (
float(element[ANNOTATION_RECTANGLE_KEY][1])
+ float(element[ANNOTATION_RECTANGLE_KEY][3])
float(widget[ANNOTATION_RECTANGLE_KEY][1])
+ float(widget[ANNOTATION_RECTANGLE_KEY][3])
) / 2

return (
width_mid_point
- stringWidth(
element_middleware.value,
element_middleware.font,
element_middleware.font_size,
widget_middleware.value,
widget_middleware.font,
widget_middleware.font_size,
)
/ 2,
(height_mid_point - string_height / 2 + height_mid_point) / 2,
)


def get_draw_text_coordinates(
element: PdfDict, element_middleware: Text
widget: PdfDict, widget_middleware: Text
) -> Tuple[Union[float, int], Union[float, int]]:
"""Returns coordinates to draw text at given a PDF form text element."""
"""Returns coordinates to draw text at given a PDF form text widget."""

if element_middleware.preview:
if widget_middleware.preview:
return (
float(element[ANNOTATION_RECTANGLE_KEY][0]),
float(element[ANNOTATION_RECTANGLE_KEY][3]) + 5,
float(widget[ANNOTATION_RECTANGLE_KEY][0]),
float(widget[ANNOTATION_RECTANGLE_KEY][3]) + 5,
)

element_value = element_middleware.value or ""
text_value = widget_middleware.value or ""
length = (
min(len(element_value), element_middleware.max_length)
if element_middleware.max_length is not None
else len(element_value)
min(len(text_value), widget_middleware.max_length)
if widget_middleware.max_length is not None
else len(text_value)
)
element_value = element_value[:length]
text_value = text_value[:length]

if element_middleware.text_wrap_length is not None:
element_value = element_value[: element_middleware.text_wrap_length]
if widget_middleware.text_wrap_length is not None:
text_value = text_value[: widget_middleware.text_wrap_length]

character_paddings = (
element_middleware.character_paddings[:length]
if element_middleware.character_paddings is not None
else element_middleware.character_paddings
widget_middleware.character_paddings[:length]
if widget_middleware.character_paddings is not None
else widget_middleware.character_paddings
)

alignment = get_element_alignment(element) or 0
x = float(element[ANNOTATION_RECTANGLE_KEY][0])
alignment = get_widget_alignment(widget) or 0
x = float(widget[ANNOTATION_RECTANGLE_KEY][0])

if int(alignment) != 0:
width_mid_point = (
float(element[ANNOTATION_RECTANGLE_KEY][0])
+ float(element[ANNOTATION_RECTANGLE_KEY][2])
float(widget[ANNOTATION_RECTANGLE_KEY][0])
+ float(widget[ANNOTATION_RECTANGLE_KEY][2])
) / 2
string_width = stringWidth(
element_value,
element_middleware.font,
element_middleware.font_size,
text_value,
widget_middleware.font,
widget_middleware.font_size,
)
if element_middleware.comb is True and length:
if widget_middleware.comb is True and length:
string_width = character_paddings[-1] + stringWidth(
element_value[-1],
element_middleware.font,
element_middleware.font_size,
text_value[-1],
widget_middleware.font,
widget_middleware.font_size,
)

if int(alignment) == 1:
x = width_mid_point - string_width / 2
elif int(alignment) == 2:
x = float(element[ANNOTATION_RECTANGLE_KEY][2]) - string_width
if length > 0 and element_middleware.comb is True:
x = float(widget[ANNOTATION_RECTANGLE_KEY][2]) - string_width
if length > 0 and widget_middleware.comb is True:
x -= (
get_char_rect_width(element, element_middleware)
get_char_rect_width(widget, widget_middleware)
- stringWidth(
element_value[-1],
element_middleware.font,
element_middleware.font_size,
text_value[-1],
widget_middleware.font,
widget_middleware.font_size,
)
) / 2

string_height = element_middleware.font_size * 96 / 72
string_height = widget_middleware.font_size * 96 / 72
height_mid_point = (
float(element[ANNOTATION_RECTANGLE_KEY][1])
+ float(element[ANNOTATION_RECTANGLE_KEY][3])
float(widget[ANNOTATION_RECTANGLE_KEY][1])
+ float(widget[ANNOTATION_RECTANGLE_KEY][3])
) / 2
y = (height_mid_point - string_height / 2 + height_mid_point) / 2
if is_text_multiline(element):
y = float(element[ANNOTATION_RECTANGLE_KEY][3]) - string_height / 1.5
if is_text_multiline(widget):
y = float(widget[ANNOTATION_RECTANGLE_KEY][3]) - string_height / 1.5

if int(alignment) == 1 and element_middleware.comb is True and length != 0:
if int(alignment) == 1 and widget_middleware.comb is True and length != 0:
x -= character_paddings[0] / 2
if length % 2 == 0:
x -= (
character_paddings[0]
+ stringWidth(
element_value[:1],
element_middleware.font,
element_middleware.font_size,
text_value[:1],
widget_middleware.font,
widget_middleware.font_size,
)
/ 2
)
Expand All @@ -129,26 +129,26 @@ def get_draw_text_coordinates(


def get_text_line_x_coordinates(
element: PdfDict, element_middleware: Text
widget: PdfDict, widget_middleware: Text
) -> Union[List[float], None]:
"""
Returns the x coordinates to draw lines
of the text at given a PDF form paragraph element.
of the text at given a PDF form paragraph widget.
"""

if (
element_middleware.text_wrap_length is not None
and element_middleware.text_lines is not None
and len(element_middleware.text_lines)
and isinstance(element_middleware.value, str)
and len(element_middleware.value) > element_middleware.text_wrap_length
widget_middleware.text_wrap_length is not None
and widget_middleware.text_lines is not None
and len(widget_middleware.text_lines)
and isinstance(widget_middleware.value, str)
and len(widget_middleware.value) > widget_middleware.text_wrap_length
):
result = []
_ele = deepcopy(element_middleware)
for each in element_middleware.text_lines:
_ele.value = each
_ele.text_wrap_length = None
result.append(get_draw_text_coordinates(element, _ele)[0])
_widget = deepcopy(widget_middleware)
for each in widget_middleware.text_lines:
_widget.value = each
_widget.text_wrap_length = None
result.append(get_draw_text_coordinates(widget, _widget)[0])

return result

Expand Down
34 changes: 17 additions & 17 deletions PyPDFForm/core/filler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@
from pdfrw import PdfReader

from ..middleware.checkbox import Checkbox
from ..middleware.constants import ELEMENT_TYPES
from ..middleware.constants import WIDGET_TYPES
from ..middleware.radio import Radio
from .coordinate import (get_draw_checkbox_radio_coordinates,
get_draw_text_coordinates,
get_text_line_x_coordinates)
from .font import checkbox_radio_font_size
from .template import get_element_key, get_elements_by_page
from .template import get_widget_key, get_widgets_by_page
from .utils import checkbox_radio_to_draw, generate_stream
from .watermark import create_watermarks_and_draw, merge_watermarks_with_pdf


def fill(
template_stream: bytes,
elements: Dict[str, ELEMENT_TYPES],
widgets: Dict[str, WIDGET_TYPES],
) -> bytes:
"""Fills a PDF using watermarks."""

Expand All @@ -30,31 +30,31 @@ def fill(

radio_button_tracker = {}

for page, _elements in get_elements_by_page(template_pdf).items():
for page, _widgets in get_widgets_by_page(template_pdf).items():
texts_to_draw[page] = []
text_watermarks.append(b"")
for _element in _elements:
key = get_element_key(_element)
for _widget in _widgets:
key = get_widget_key(_widget)
needs_to_be_drawn = False

if isinstance(elements[key], (Checkbox, Radio)):
font_size = checkbox_radio_font_size(_element)
_to_draw = checkbox_radio_to_draw(elements[key], font_size)
x, y = get_draw_checkbox_radio_coordinates(_element, _to_draw)
if isinstance(elements[key], Checkbox) and elements[key].value:
if isinstance(widgets[key], (Checkbox, Radio)):
font_size = checkbox_radio_font_size(_widget)
_to_draw = checkbox_radio_to_draw(widgets[key], font_size)
x, y = get_draw_checkbox_radio_coordinates(_widget, _to_draw)
if isinstance(widgets[key], Checkbox) and widgets[key].value:
needs_to_be_drawn = True
elif isinstance(elements[key], Radio):
elif isinstance(widgets[key], Radio):
if key not in radio_button_tracker:
radio_button_tracker[key] = 0
radio_button_tracker[key] += 1
if elements[key].value == radio_button_tracker[key] - 1:
if widgets[key].value == radio_button_tracker[key] - 1:
needs_to_be_drawn = True
else:
elements[key].text_line_x_coordinates = get_text_line_x_coordinates(
_element, elements[key]
widgets[key].text_line_x_coordinates = get_text_line_x_coordinates(
_widget, widgets[key]
)
x, y = get_draw_text_coordinates(_element, elements[key])
_to_draw = elements[key]
x, y = get_draw_text_coordinates(_widget, widgets[key])
_to_draw = widgets[key]
needs_to_be_drawn = True

if needs_to_be_drawn:
Expand Down
Loading

0 comments on commit db20750

Please sign in to comment.