22from typing import Any , Optional , Union , cast
33
44from .._cmap import _default_fonts_space_width , build_char_map_from_dict
5+ from .._codecs .core_fontmetrics import CORE_FONT_METRICS
56from .._font import FontDescriptor
67from .._utils import logger_warning
78from ..constants import AnnotationDictionaryAttributes , FieldDictionaryAttributes
@@ -133,6 +134,7 @@ def _generate_appearance_stream_data(
133134 text : str = "" ,
134135 selection : Optional [list [str ]] = None ,
135136 rectangle : Union [RectangleObject , tuple [float , float , float , float ]] = (0.0 , 0.0 , 0.0 , 0.0 ),
137+ font_descriptor : FontDescriptor = CORE_FONT_METRICS ["Helvetica" ],
136138 font_glyph_byte_map : Optional [dict [str , bytes ]] = None ,
137139 font_name : str = "/Helv" ,
138140 font_size : float = 0.0 ,
@@ -170,10 +172,27 @@ def _generate_appearance_stream_data(
170172
171173 # If font_size is 0, apply the logic for multiline or large-as-possible font
172174 if font_size == 0 :
175+ if selection : # Don't wrap text when dealing with a /Ch field, in order to prevent problems
176+ is_multiline = False # with matching "selection" with "line" later on.
173177 if is_multiline :
174178 font_size = DEFAULT_FONT_SIZE_IN_MULTILINE
175179 else :
176180 font_size = rectangle .height - 2
181+ lines , font_size = self ._scale_text (
182+ font_descriptor ,
183+ font_size ,
184+ rectangle .width - 3 , # One point margin left and right, and an additional point because the first
185+ # offset takes one extra point (see below, under "line_number == 0:")
186+ rectangle .height - 3 , # One point margin for top and bottom, one point extra for the first line
187+ # (see y_offset)
188+ text ,
189+ is_multiline ,
190+ )
191+ else :
192+ lines = [(
193+ font_descriptor .text_width (line ) * font_size / 1000 ,
194+ line
195+ ) for line in text .replace ("\n " , "\r " ).split ("\r " )]
177196
178197 # Set the vertical offset
179198 y_offset = rectangle .height - 1 - font_size
@@ -184,7 +203,7 @@ def _generate_appearance_stream_data(
184203 f"re\n W\n BT\n { default_appearance } \n "
185204 ).encode ()
186205
187- for line_number , line in enumerate (text . replace ( " \n " , " \r " ). split ( " \r " ) ):
206+ for line_number , ( line_width , line ) in enumerate (lines ):
188207 if selection and line in selection :
189208 # Might be improved, but cannot find how to get fill working => replaced with lined box
190209 ap_stream += (
@@ -241,6 +260,7 @@ def __init__(
241260 # If a font resource was added, get the font character map
242261 if font_resource :
243262 font_resource = cast (DictionaryObject , font_resource .get_object ())
263+ font_descriptor = FontDescriptor .from_font_resource (font_resource )
244264 _font_subtype , _ , font_encoding , font_map = build_char_map_from_dict (
245265 200 , font_resource
246266 )
@@ -261,11 +281,13 @@ def __init__(
261281 else :
262282 logger_warning (f"Font dictionary for { font_name } not found." , __name__ )
263283 font_glyph_byte_map = {}
284+ font_descriptor = FontDescriptor ()
264285
265286 ap_stream_data = self ._generate_appearance_stream_data (
266287 text ,
267288 selection ,
268289 rectangle ,
290+ font_descriptor ,
269291 font_glyph_byte_map ,
270292 font_name ,
271293 font_size ,
0 commit comments