@@ -2236,6 +2236,20 @@ def encode_string(self, s, fonttype):
22362236 return s .encode ('cp1252' , 'replace' )
22372237 return s .encode ('utf-16be' , 'replace' )
22382238
2239+ @staticmethod
2240+ def _font_supports_char (fonttype , char ):
2241+ """
2242+ Returns True if the font is able to provided the char in a PDF
2243+
2244+ For a Type 3 font, this method returns True only for single-byte
2245+ chars. For Type 42 fonts this method always returns True.
2246+ """
2247+ if fonttype == 3 :
2248+ return ord (char ) <= 255
2249+ if fonttype == 42 :
2250+ return True
2251+ raise NotImplementedError ()
2252+
22392253 def draw_text (self , gc , x , y , s , prop , angle , ismath = False , mtext = None ):
22402254 # docstring inherited
22412255
@@ -2270,26 +2284,27 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
22702284 }
22712285 self .file ._annotations [- 1 ][1 ].append (link_annotation )
22722286
2273- # If fonttype != 3 emit the whole string at once without manual
2274- # kerning.
2275- if fonttype != 3 :
2287+ # If fonttype is neither 3 nor 42, emit the whole string at once
2288+ # without manual kerning.
2289+ if fonttype not in [ 3 , 42 ] :
22762290 self .file .output (Op .begin_text ,
22772291 self .file .fontName (prop ), fontsize , Op .selectfont )
22782292 self ._setup_textpos (x , y , angle )
22792293 self .file .output (self .encode_string (s , fonttype ),
22802294 Op .show , Op .end_text )
22812295
2282- # There is no way to access multibyte characters of Type 3 fonts, as
2283- # they cannot have a CIDMap. Therefore, in this case we break the
2284- # string into chunks, where each chunk contains either a string of
2285- # consecutive 1-byte characters or a single multibyte character.
2286- # A sequence of 1-byte characters is broken into multiple chunks to
2287- # adjust the kerning between adjacent chunks. Each chunk is emitted
2288- # with a separate command: 1-byte characters use the regular text show
2289- # command (TJ) with appropriate kerning between chunks, whereas
2290- # multibyte characters use the XObject command (Do). (If using Type
2291- # 42 fonts, all of this complication is avoided, but of course,
2292- # subsetting those fonts is complex/hard to implement.)
2296+ # A sequence of characters is broken into multiple chunks. The chunking
2297+ # serves two purposes:
2298+ # - For Type 3 fonts, there is no way to access multibyte characters,
2299+ # as they cannot have a CIDMap. Therefore, in this case we break
2300+ # the string into chunks, where each chunk contains either a string
2301+ # of consecutive 1-byte characters or a single multibyte character.
2302+ # - A sequence of 1-byte characters is split into chunks to allow for
2303+ # kerning adjustments between consecutive chunks.
2304+ #
2305+ # Each chunk is emitted with a separate command: 1-byte characters use
2306+ # the regular text show command (TJ) with appropriate kerning between
2307+ # chunks, whereas multibyte characters use the XObject command (Do).
22932308 else :
22942309 # List of (start_x, [prev_kern, char, char, ...]), w/o zero kerns.
22952310 singlebyte_chunks = []
@@ -2298,7 +2313,7 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
22982313 prev_was_multibyte = True
22992314 for item in _text_helpers .layout (
23002315 s , font , kern_mode = KERNING_UNFITTED ):
2301- if ord ( item .char ) <= 255 :
2316+ if self . _font_supports_char ( fonttype , item .char ):
23022317 if prev_was_multibyte :
23032318 singlebyte_chunks .append ((item .x , []))
23042319 if item .prev_kern :
0 commit comments