@@ -25,8 +25,8 @@ def _appearance_stream_data(
2525 self ,
2626 text : str = "" ,
2727 selection : Optional [list [str ]] = None ,
28- font_glyph_byte_map : Optional [dict [str , bytes ]] = None ,
2928 rect : Union [RectangleObject , tuple [float , float , float , float ]] = (0.0 , 0.0 , 0.0 , 0.0 ),
29+ font_glyph_byte_map : Optional [dict [str , bytes ]] = None ,
3030 font_name : str = "/Helv" ,
3131 font_size : float = 0.0 ,
3232 font_color : str = "0 g" ,
@@ -73,17 +73,39 @@ def __init__(
7373 self ,
7474 text : str = "" ,
7575 selection : Optional [list [str ]] = None ,
76- font_glyph_byte_map : Optional [dict [str , bytes ]] = None ,
7776 rect : Union [RectangleObject , tuple [float , float , float , float ]] = (0.0 , 0.0 , 0.0 , 0.0 ),
77+ font_resource : Optional [DictionaryObject ] = None ,
7878 font_name : str = "/Helv" ,
7979 font_size : float = 0.0 ,
8080 font_color : str = "0 g" ,
8181 multiline : bool = False
8282 ) -> None :
83- font_glyph_byte_map = font_glyph_byte_map or {}
83+ # If a font resource was added, get the font character map
84+ if font_resource :
85+ font_resource = cast (DictionaryObject , font_resource .get_object ())
86+ _font_subtype , _ , font_encoding , font_map = build_char_map_from_dict (
87+ 200 , font_resource
88+ )
89+ try : # remove width stored in -1 key
90+ del font_map [- 1 ]
91+ except KeyError :
92+ pass
93+ font_glyph_byte_map : dict [str , bytes ]
94+ if isinstance (font_encoding , str ):
95+ font_glyph_byte_map = {
96+ v : k .encode (font_encoding ) for k , v in font_map .items ()
97+ }
98+ else :
99+ font_glyph_byte_map = {v : bytes ((k ,)) for k , v in font_encoding .items ()}
100+ font_encoding_rev = {v : bytes ((k ,)) for k , v in font_encoding .items ()}
101+ for key , value in font_map .items ():
102+ font_glyph_byte_map [value ] = font_encoding_rev .get (key , key )
103+ else :
104+ logger_warning (f"Font dictionary for { font_name } not found." , __name__ )
105+ font_glyph_byte_map = {}
84106
85107 ap_stream_data = self ._appearance_stream_data (
86- text , selection , font_glyph_byte_map , rect , font_name , font_size , font_color , multiline
108+ text , selection , rect , font_glyph_byte_map , font_name , font_size , font_color , multiline
87109 )
88110
89111 super ().__init__ ()
@@ -92,6 +114,19 @@ def __init__(
92114 self [NameObject ("/BBox" )] = RectangleObject (rect )
93115 self .set_data (ByteStringObject (ap_stream_data ))
94116 self [NameObject ("/Length" )] = NumberObject (len (ap_stream_data ))
117+ # Update Resources with font information if necessary
118+ if font_resource is not None :
119+ self [NameObject ("/Resources" )] = DictionaryObject (
120+ {
121+ NameObject ("/Font" ): DictionaryObject (
122+ {
123+ NameObject (font_name ): getattr (
124+ font_resource , "indirect_reference" , font_resource
125+ )
126+ }
127+ )
128+ }
129+ )
95130
96131 @classmethod
97132 def from_text_annotation (
@@ -118,8 +153,10 @@ def from_text_annotation(
118153 else :
119154 default_appearance = default_appearance .get_object ()
120155
121- # Derive font size. Also embed user-provided font name and font size in the default
122- # appearance, if given. Uses the variable font_properties as an intermediate.
156+ # Derive font name, size and color from the default appearance. Also set
157+ # user-provided font name and font size in the default appearance, if given.
158+ # For a font name, this presumes that we can find an associated font resource
159+ # dictionary. Uses the variable font_properties as an intermediate.
123160 # As per the PDF spec:
124161 # "At a minimum, the string [that is, default_appearance] shall include a Tf (text
125162 # font) operator along with its two operands, font and size" (p. 519 of Version 2.0).
@@ -156,30 +193,8 @@ def from_text_annotation(
156193 )
157194 document_font_resources = document_resources .get_object ().get ("/Font" , DictionaryObject ()).get_object ()
158195 font_resource = document_font_resources .get (font_name , None )
159-
160- # If this annotation has a font resources, get the font character map
161196 if not is_null_or_none (font_resource ):
162197 font_resource = cast (DictionaryObject , font_resource .get_object ())
163- _font_subtype , _ , font_encoding , font_map = build_char_map_from_dict (
164- 200 , font_resource
165- )
166- try : # remove width stored in -1 key
167- del font_map [- 1 ]
168- except KeyError :
169- pass
170- font_glyph_byte_map : dict [str , bytes ]
171- if isinstance (font_encoding , str ):
172- font_glyph_byte_map = {
173- v : k .encode (font_encoding ) for k , v in font_map .items ()
174- }
175- else :
176- font_glyph_byte_map = {v : bytes ((k ,)) for k , v in font_encoding .items ()}
177- font_encoding_rev = {v : bytes ((k ,)) for k , v in font_encoding .items ()}
178- for key , value in font_map .items ():
179- font_glyph_byte_map [value ] = font_encoding_rev .get (key , key )
180- else :
181- logger_warning (f"Font dictionary for { font_name } not found." , __name__ )
182- font_glyph_byte_map = {}
183198
184199 # Retrieve field text, selected values and formatting information
185200 multiline = False
@@ -201,26 +216,11 @@ def from_text_annotation(
201216
202217 # Create the TextStreamAppearance instance
203218 new_appearance_stream = cls (
204- text , selection , font_glyph_byte_map , rect , font_name , font_size , font_color , multiline
219+ text , selection , rect , font_resource , font_name , font_size , font_color , multiline
205220 )
206-
207221 if AnnotationDictionaryAttributes .AP in annotation :
208222 for k , v in cast (DictionaryObject , annotation [AnnotationDictionaryAttributes .AP ]).get ("/N" , {}).items ():
209223 if k not in {"/BBox" , "/Length" , "/Subtype" , "/Type" , "/Filter" }:
210224 new_appearance_stream [k ] = v
211225
212- # Update Resources with font information if necessary
213- if font_resource is not None :
214- new_appearance_stream [NameObject ("/Resources" )] = DictionaryObject (
215- {
216- NameObject ("/Font" ): DictionaryObject (
217- {
218- NameObject (font_name ): getattr (
219- font_resource , "indirect_reference" , font_resource
220- )
221- }
222- )
223- }
224- )
225-
226226 return new_appearance_stream
0 commit comments