Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 67aea08

Browse files
committed
Emit Type 42 text with TJ and kerning in PDF
The commit applies the same kerning algorithm used for Type 3 fonts also to Type 42 fonts. A string is split into chunks with kerning between the chunks.
1 parent 76b3b6e commit 67aea08

File tree

1 file changed

+30
-15
lines changed

1 file changed

+30
-15
lines changed

lib/matplotlib/backends/backend_pdf.py

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)