Skip to content

Commit 9ea3f06

Browse files
committed
MAINT: _writer: let _update_field_annotation return appearance stream
This patch lets the _update_field_annotation method return an appearance stream instead of None, so that this method can be separated out of _writer.py later on.
1 parent b6fff56 commit 9ea3f06

File tree

1 file changed

+23
-19
lines changed

1 file changed

+23
-19
lines changed

pypdf/_writer.py

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,6 @@ def _add_apstream_object(
862862
object_name: str,
863863
x_offset: float,
864864
y_offset: float,
865-
font_res: Optional[DictionaryObject] = None
866865
) -> None:
867866
"""
868867
Adds an appearance stream to the page content in the form of
@@ -874,17 +873,22 @@ def _add_apstream_object(
874873
object_name: The name of the appearance stream.
875874
x_offset: The horizontal offset for the appearance stream.
876875
y_offset: The vertical offset for the appearance stream.
877-
font_res: The appearance stream's font resource (if given).
878876
"""
879-
# Prepare XObject resource dictionary on the page
877+
# Prepare XObject resource dictionary on the page. This currently
878+
# only deals with font resources, but can easily be adapted to also
879+
# include other resources.
880880
pg_res = cast(DictionaryObject, page[PG.RESOURCES])
881-
if font_res is not None:
882-
font_name = font_res["/BaseFont"] # [/"Name"] often also exists, but is deprecated
883-
if "/Font" not in pg_res:
884-
pg_res[NameObject("/Font")] = DictionaryObject()
885-
pg_ft_res = cast(DictionaryObject, pg_res[NameObject("/Font")])
886-
if font_name not in pg_ft_res:
887-
pg_ft_res[NameObject(font_name)] = font_res
881+
if "/Resources" in appearance_stream_obj:
882+
ap_stream_res = cast(DictionaryObject, appearance_stream_obj["/Resources"])
883+
if "/Font" in ap_stream_res:
884+
ap_stream_font_dict = cast(DictionaryObject, ap_stream_res["/Font"])
885+
if "/Font" not in pg_res:
886+
pg_res[NameObject("/Font")] = DictionaryObject()
887+
pg_font_res = cast(DictionaryObject, pg_res["/Font"])
888+
# Merge fonts from the appearance stream into the page's font resources
889+
for font_name, font_ref in ap_stream_font_dict.items():
890+
if font_name not in pg_font_res:
891+
pg_font_res[font_name] = font_ref
888892
# Always add the resolved stream object to the writer to get a new IndirectObject.
889893
# This ensures we have a valid IndirectObject managed by *this* writer.
890894
xobject_ref = self._add_object(appearance_stream_obj)
@@ -910,8 +914,7 @@ def _update_field_annotation(
910914
annotation: DictionaryObject,
911915
font_name: str = "",
912916
font_size: float = -1,
913-
flatten: bool = False,
914-
) -> None:
917+
) -> StreamObject:
915918
# Calculate rectangle dimensions
916919
_rct = cast(RectangleObject, annotation[AA.Rect])
917920
rct = RectangleObject((0, 0, abs(_rct[2] - _rct[0]), abs(_rct[3] - _rct[1])))
@@ -1053,9 +1056,7 @@ def _update_field_annotation(
10531056
self._objects[n - 1] = dct
10541057
dct.indirect_reference = IndirectObject(n, 0, self)
10551058

1056-
if flatten:
1057-
field_name = self._get_qualified_field_name(annotation)
1058-
self._add_apstream_object(page, dct, field_name, _rct[0], _rct[1], font_res)
1059+
return dct
10591060

10601061
FFBITS_NUL = FA.FfBits(0)
10611062

@@ -1127,6 +1128,7 @@ def update_page_form_field_values(
11271128
).get_object()
11281129

11291130
for field, value in fields.items():
1131+
rct = cast(RectangleObject, annotation[AA.Rect])
11301132
if not (
11311133
self._get_qualified_field_name(parent_annotation) == field
11321134
or parent_annotation.get("/T", None) == field
@@ -1163,19 +1165,21 @@ def update_page_form_field_values(
11631165
if flatten and appearance_stream_obj is not None:
11641166
# We basically copy the entire appearance stream, which should be an XObject that
11651167
# is already registered. No need to add font resources.
1166-
rct = cast(RectangleObject, annotation[AA.Rect])
11671168
self._add_apstream_object(page, appearance_stream_obj, field, rct[0], rct[1])
11681169
elif (
11691170
parent_annotation.get(FA.FT) == "/Tx"
11701171
or parent_annotation.get(FA.FT) == "/Ch"
11711172
):
11721173
# textbox
11731174
if isinstance(value, tuple):
1174-
self._update_field_annotation(
1175-
page, parent_annotation, annotation, value[1], value[2], flatten=flatten
1175+
dct = self._update_field_annotation(
1176+
page, parent_annotation, annotation, value[1], value[2]
11761177
)
11771178
else:
1178-
self._update_field_annotation(page, parent_annotation, annotation, flatten=flatten)
1179+
dct = self._update_field_annotation(page, parent_annotation, annotation)
1180+
if flatten:
1181+
field_name = self._get_qualified_field_name(annotation)
1182+
self._add_apstream_object(page, dct, field_name, rct[0], rct[1])
11791183
elif (
11801184
annotation.get(FA.FT) == "/Sig"
11811185
): # deprecated # not implemented yet

0 commit comments

Comments
 (0)