8787from .constants import PageAttributes as PG
8888from .constants import PagesAttributes as PA
8989from .constants import TrailerKeys as TK
90+ from .errors import PyPdfError
9091from .generic import (
9192 PAGE_FIT ,
9293 AnnotationBuilder ,
@@ -836,11 +837,14 @@ def _update_text_field(self, field: DictionaryObject) -> None:
836837 rct = RectangleObject ((0 , 0 , _rct [2 ] - _rct [0 ], _rct [3 ] - _rct [1 ]))
837838
838839 # Extract font information
839- font_properties : Any = (
840- cast (str , field [AA .DA ]).replace ("\n " , " " ).replace ("\r " , " " ).split (" " )
841- )
840+ da = cast (str , field [AA .DA ])
841+ font_properties = da .replace ("\n " , " " ).replace ("\r " , " " ).split (" " )
842842 font_name = font_properties [font_properties .index ("Tf" ) - 2 ]
843843 font_height = float (font_properties [font_properties .index ("Tf" ) - 1 ])
844+ if font_height == 0 :
845+ font_height = rct .height - 2
846+ font_properties [font_properties .index ("Tf" ) - 1 ] = str (font_height )
847+ da = " " .join (font_properties )
844848 y_offset = rct .height - 1 - font_height
845849
846850 # Retrieve field text and selected values
@@ -855,7 +859,7 @@ def _update_text_field(self, field: DictionaryObject) -> None:
855859 sel = []
856860
857861 # Generate appearance stream
858- ap_stream = f"q\n /Tx BMC \n q\n 1 1 { rct .width - 1 } { rct .height - 1 } re\n W\n BT\n { field [ AA . DA ] } \n " .encode ()
862+ ap_stream = f"q\n /Tx BMC \n q\n 1 1 { rct .width - 1 } { rct .height - 1 } re\n W\n BT\n { da } \n " .encode ()
859863 for line_number , line in enumerate (txt .replace ("\n " , "\r " ).split ("\r " )):
860864 if line in sel :
861865 # may be improved but can not find how get fill working => replaced with lined box
@@ -938,12 +942,21 @@ def update_page_form_field_values(
938942 auto_regenerate: set/unset the need_appearances flag ;
939943 the flag is unchanged if auto_regenerate is None
940944 """
945+ if CatalogDictionary .ACRO_FORM not in self ._root_object :
946+ raise PyPdfError ("No /AcroForm dictionary in PdfWriter Object" )
947+ af = cast (DictionaryObject , self ._root_object [CatalogDictionary .ACRO_FORM ])
948+ if InteractiveFormDictEntries .Fields not in af :
949+ raise PyPdfError ("No /Fields dictionary in Pdf in PdfWriter Object" )
941950 if isinstance (auto_regenerate , bool ):
942951 self .set_need_appearances_writer (auto_regenerate )
943952 # Iterate through pages, update field values
944953 if PG .ANNOTS not in page :
945954 logger_warning ("No fields to update on this page" , __name__ )
946955 return
956+ # /Helvetica is just in case of but this is normally insufficient as we miss the font ressource
957+ default_da = af .get (
958+ InteractiveFormDictEntries .DA , TextStringObject ("/Helvetica 0 Tf 0 g" )
959+ )
947960 for writer_annot in page [PG .ANNOTS ]: # type: ignore
948961 writer_annot = cast (DictionaryObject , writer_annot .get_object ())
949962 # retrieve parent field values, if present
@@ -968,6 +981,17 @@ def update_page_form_field_values(
968981 or writer_annot .get (FA .FT ) == "/Ch"
969982 ):
970983 # textbox
984+ if AA .DA not in writer_annot :
985+ f = writer_annot
986+ da = default_da
987+ while AA .DA not in f :
988+ f = f .get ("/Parent" )
989+ if f is None :
990+ break
991+ f = f .get_object ()
992+ if AA .DA in f :
993+ da = f [AA .DA ]
994+ writer_annot [NameObject (AA .DA )] = da
971995 self ._update_text_field (writer_annot )
972996 elif writer_annot .get (FA .FT ) == "/Sig" :
973997 # signature
0 commit comments