@@ -139,15 +139,7 @@ def _generate_appearance_stream_data(
139139 text : str = "" ,
140140 selection : Optional [list [str ]] = None ,
141141 rectangle : Union [RectangleObject , tuple [float , float , float , float ]] = (0.0 , 0.0 , 0.0 , 0.0 ),
142- font_descriptor : Optional [FontDescriptor ] = None ,
143- font_glyph_byte_map : Optional [dict [str , bytes ]] = None ,
144- font_name : str = "/Helv" ,
145- font_size : float = 0.0 ,
146- font_color : str = "0 g" ,
147- is_multiline : bool = False ,
148- alignment : TextAlignment = TextAlignment .LEFT ,
149- is_comb : bool = False ,
150- max_length : Optional [int ] = None
142+ ** formatting_kwargs : Any
151143 ) -> bytes :
152144 """
153145 Generates the raw bytes of the PDF appearance stream for a text field.
@@ -159,30 +151,38 @@ def _generate_appearance_stream_data(
159151 Args:
160152 text: The text to be rendered in the form field.
161153 selection: An optional list of strings that should be highlighted as selected.
162- font_glyph_byte_map: An optional dictionary mapping characters to their
163- byte representation for glyph encoding.
164154 rect: The bounding box of the form field. Can be a `RectangleObject`
165155 or a tuple of four floats (x1, y1, x2, y2).
166- font_name: The name of the font resource to use (e.g., "/Helv").
167- font_size: The font size. If 0, it is automatically calculated
168- based on whether the field is multiline or not.
169- font_color: The color to apply to the font, represented as a PDF
170- graphics state string (e.g., "0 g" for black).
171- is_multiline: A boolean indicating if the text field is multiline.
172- alignment: Text alignment, can be TextAlignment.LEFT, .RIGHT, or .CENTER.
173- is_comb: Boolean that designates fixed-length fields, where every character
174- fills one "cell", such as in a postcode.
175- max_length: Used if is_comb is set. The maximum number of characters for a fixed-
176- length field.
156+ **formatting_kwargs: A series of keyword arguments that describe how the
157+ appearance stream should be formatted. Can include the following:
158+ font_descriptor: The font descriptor associated with the font resource.
159+ font_glyph_byte_map: An optional dictionary mapping characters to their
160+ byte representation for glyph encoding.
161+ font_name: The name of the font resource, e.g., "/Helv".
162+ font_size: The font size. If 0, it's auto-calculated.
163+ font_color: The font color string.
164+ is_multiline: A boolean indicating if the text field is multiline.
165+ alignment: Text alignment, can be TextAlignment.LEFT, .RIGHT, or .CENTER.
166+ is_comb: Boolean that designates fixed-length fields, where every character
167+ fills one "cell", such as in a postcode.
168+ max_length: Used if is_comb is set. The maximum number of characters for a fixed-
169+ length field.
177170
178171 Returns:
179172 A byte string containing the PDF content stream data.
180173
181174 """
182- font_glyph_byte_map = font_glyph_byte_map or {}
183175 if isinstance (rectangle , tuple ):
184176 rectangle = RectangleObject (rectangle )
185- font_descriptor = cast (FontDescriptor , font_descriptor )
177+ font_descriptor = cast (FontDescriptor , formatting_kwargs .get ("font_descriptor" ))
178+ font_glyph_byte_map = formatting_kwargs .get ("font_glyph_byte_map" , {})
179+ font_name = formatting_kwargs .get ("font_name" )
180+ font_size = formatting_kwargs .get ("font_size" , 0.0 )
181+ font_color = formatting_kwargs .get ("font_color" , "0 g" )
182+ is_multiline = formatting_kwargs .get ("is_multiline" , False )
183+ alignment = formatting_kwargs .get ("alignment" , TextAlignment .LEFT )
184+ is_comb = formatting_kwargs .get ("is_comb" , False )
185+ max_length = formatting_kwargs .get ("max_length" , len (text ))
186186
187187 # If font_size is 0, apply the logic for multiline or large-as-possible font
188188 if font_size == 0 :
@@ -203,7 +203,7 @@ def _generate_appearance_stream_data(
203203 is_multiline ,
204204 )
205205 elif is_comb :
206- if max_length and len (text ) > max_length :
206+ if len (text ) > max_length :
207207 logger_warning (
208208 f"Length of text { text } exceeds maximum length ({ max_length } ) of field, input truncated." ,
209209 __name__
@@ -212,7 +212,7 @@ def _generate_appearance_stream_data(
212212 lines = [(
213213 font_descriptor .text_width (char ) * font_size / 1000 ,
214214 char
215- ) for index , char in enumerate (text ) if index < ( max_length or len ( text )) ]
215+ ) for index , char in enumerate (text ) if index < max_length ]
216216 else :
217217 lines = [(
218218 font_descriptor .text_width (line ) * font_size / 1000 ,
@@ -288,14 +288,7 @@ def __init__(
288288 text : str = "" ,
289289 selection : Optional [list [str ]] = None ,
290290 rectangle : Union [RectangleObject , tuple [float , float , float , float ]] = (0.0 , 0.0 , 0.0 , 0.0 ),
291- font_resource : Optional [DictionaryObject ] = None ,
292- font_name : str = "/Helv" ,
293- font_size : float = 0.0 ,
294- font_color : str = "0 g" ,
295- is_multiline : bool = False ,
296- alignment : TextAlignment = TextAlignment .LEFT ,
297- is_comb : bool = False ,
298- max_length : Optional [int ] = None
291+ ** formatting_kwargs : Any ,
299292 ) -> None :
300293 """
301294 Initializes a TextStreamAppearance object.
@@ -307,28 +300,33 @@ def __init__(
307300 Args:
308301 text: The text to be rendered in the form field.
309302 selection: An optional list of strings that should be highlighted as selected.
310- rect : The bounding box of the form field. Can be a `RectangleObject`
303+ rectangle : The bounding box of the form field. Can be a `RectangleObject`
311304 or a tuple of four floats (x1, y1, x2, y2).
312- font_resource: An optional variable that represents a PDF font dictionary.
313- font_name: The name of the font resource, e.g., "/Helv".
314- font_size: The font size. If 0, it's auto-calculated.
315- font_color: The font color string.
316- is_multiline: A boolean indicating if the text field is multiline.
317- alignment: Text alignment, can be TextAlignment.LEFT, .RIGHT, or .CENTER.
318- is_comb: Boolean that designates fixed-length fields, where every character
319- fills one "cell", such as in a postcode.
320- max_length: Used if is_comb is set. The maximum number of characters for a fixed-
321- length field.
322-
305+ **formatting_kwargs: A series of keyword arguments that describe how the
306+ appearance stream should be formatted. Can include the following:
307+ font_resource: An optional variable that represents a PDF font dictionary.
308+ font_name: The name of the font resource, e.g., "/Helv".
309+ font_size: The font size. If 0, it's auto-calculated.
310+ font_color: The font color string.
311+ is_multiline: A boolean indicating if the text field is multiline.
312+ alignment: Text alignment, can be TextAlignment.LEFT, .RIGHT, or .CENTER.
313+ is_comb: Boolean that designates fixed-length fields, where every character
314+ fills one "cell", such as in a postcode.
315+ max_length: Used if is_comb is set. The maximum number of characters for a fixed-
316+ length field.
323317 """
324318 super ().__init__ ()
325319
326320 # If a font resource was added, get the font character map
327- if font_resource :
328- font_resource = cast (DictionaryObject , font_resource .get_object ())
321+ if formatting_kwargs . get ( " font_resource" ) :
322+ font_resource = cast (DictionaryObject , formatting_kwargs [ " font_resource" ] .get_object ())
329323 font_descriptor = FontDescriptor .from_font_resource (font_resource )
324+ font_name = formatting_kwargs .get ("font_name" )
330325 else :
331- logger_warning (f"Font dictionary for { font_name } not found; defaulting to Helvetica." , __name__ )
326+ logger_warning (
327+ f'Font dictionary for { formatting_kwargs .get ("font_name" )} not found; '
328+ "defaulting to Helvetica." , __name__
329+ )
332330 font_name = "/Helv"
333331 font_resource = DictionaryObject ({
334332 NameObject ("/Subtype" ): NameObject ("/Type1" ),
@@ -339,6 +337,9 @@ def __init__(
339337 })
340338 font_descriptor = CORE_FONT_METRICS ["Helvetica" ]
341339
340+ formatting_kwargs .pop ("font_resource" , None )
341+ formatting_kwargs .pop ("font_name" , None )
342+
342343 # Get the font glyph data
343344 _font_subtype , _ , font_encoding , font_map = build_char_map_from_dict (
344345 200 , font_resource
@@ -362,15 +363,10 @@ def __init__(
362363 text ,
363364 selection ,
364365 rectangle ,
365- font_descriptor ,
366- font_glyph_byte_map ,
367- font_name ,
368- font_size ,
369- font_color ,
370- is_multiline ,
371- alignment ,
372- is_comb ,
373- max_length
366+ font_descriptor = font_descriptor ,
367+ font_glyph_byte_map = font_glyph_byte_map ,
368+ font_name = font_name ,
369+ ** formatting_kwargs
374370 )
375371
376372 self [NameObject ("/Type" )] = NameObject ("/XObject" )
@@ -507,14 +503,14 @@ def from_text_annotation(
507503 text ,
508504 selection ,
509505 rectangle ,
510- font_resource ,
511- font_name ,
512- font_size ,
513- font_color ,
514- is_multiline ,
515- alignment ,
516- is_comb ,
517- max_length
506+ font_resource = font_resource ,
507+ font_name = font_name ,
508+ font_size = font_size ,
509+ font_color = font_color ,
510+ is_multiline = is_multiline ,
511+ alignment = alignment ,
512+ is_comb = is_comb ,
513+ max_length = max_length
518514 )
519515 if AnnotationDictionaryAttributes .AP in annotation :
520516 for key , value in (
0 commit comments