Skip to content

Commit fed8c20

Browse files
authored
Merge pull request #30082 from anntzer/simple-dvifontinfo
Simplify dviFontInfo layout in backend pdf.
2 parents 68c67c9 + e3c7a64 commit fed8c20

File tree

1 file changed

+46
-43
lines changed

1 file changed

+46
-43
lines changed

lib/matplotlib/backends/backend_pdf.py

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,7 @@ def __init__(self, filename, metadata=None):
721721

722722
self._internal_font_seq = (Name(f'F{i}') for i in itertools.count(1))
723723
self._fontNames = {} # maps filenames to internal font names
724-
self._dviFontInfo = {} # maps dvi font names to embedding information
724+
self._dviFontInfo = {} # maps pdf names to dvifonts
725725
self._character_tracker = _backend_pdf_ps.CharacterTracker()
726726

727727
self.alphaStates = {} # maps alpha values to graphics state objects
@@ -764,9 +764,30 @@ def __init__(self, filename, metadata=None):
764764
self.writeObject(self.resourceObject, resources)
765765

766766
fontNames = _api.deprecated("3.11")(property(lambda self: self._fontNames))
767-
dviFontInfo = _api.deprecated("3.11")(property(lambda self: self._dviFontInfo))
768767
type1Descriptors = _api.deprecated("3.11")(property(lambda _: {}))
769768

769+
@_api.deprecated("3.11")
770+
@property
771+
def dviFontInfo(self):
772+
d = {}
773+
tex_font_map = dviread.PsfontsMap(dviread.find_tex_file('pdftex.map'))
774+
for pdfname, dvifont in self._dviFontInfo.items():
775+
psfont = tex_font_map[dvifont.texname]
776+
if psfont.filename is None:
777+
raise ValueError(
778+
"No usable font file found for {} (TeX: {}); "
779+
"the font may lack a Type-1 version"
780+
.format(psfont.psname, dvifont.texname))
781+
d[dvifont.texname] = types.SimpleNamespace(
782+
dvifont=dvifont,
783+
pdfname=pdfname,
784+
fontfile=psfont.filename,
785+
basefont=psfont.psname,
786+
encodingfile=psfont.encoding,
787+
effects=psfont.effects,
788+
)
789+
return d
790+
770791
def newPage(self, width, height):
771792
self.endStream()
772793

@@ -938,39 +959,19 @@ def fontName(self, fontprop):
938959
def dviFontName(self, dvifont):
939960
"""
940961
Given a dvi font object, return a name suitable for Op.selectfont.
941-
This registers the font information internally (in ``_dviFontInfo``) if
942-
not yet registered.
943-
"""
944-
945-
dvi_info = self._dviFontInfo.get(dvifont.texname)
946-
if dvi_info is not None:
947-
return dvi_info.pdfname
948-
949-
tex_font_map = dviread.PsfontsMap(dviread.find_tex_file('pdftex.map'))
950-
psfont = tex_font_map[dvifont.texname]
951-
if psfont.filename is None:
952-
raise ValueError(
953-
"No usable font file found for {} (TeX: {}); "
954-
"the font may lack a Type-1 version"
955-
.format(psfont.psname, dvifont.texname))
956962
957-
pdfname = next(self._internal_font_seq)
963+
Register the font internally (in ``_dviFontInfo``) if not yet registered.
964+
"""
965+
pdfname = Name(f"F-{dvifont.texname.decode('ascii')}")
958966
_log.debug('Assigning font %s = %s (dvi)', pdfname, dvifont.texname)
959-
self._dviFontInfo[dvifont.texname] = types.SimpleNamespace(
960-
dvifont=dvifont,
961-
pdfname=pdfname,
962-
fontfile=psfont.filename,
963-
basefont=psfont.psname,
964-
encodingfile=psfont.encoding,
965-
effects=psfont.effects)
966-
return pdfname
967+
self._dviFontInfo[pdfname] = dvifont
968+
return Name(pdfname)
967969

968970
def writeFonts(self):
969971
fonts = {}
970-
for dviname, info in sorted(self._dviFontInfo.items()):
971-
Fx = info.pdfname
972-
_log.debug('Embedding Type-1 font %s from dvi.', dviname)
973-
fonts[Fx] = self._embedTeXFont(info)
972+
for pdfname, dvifont in sorted(self._dviFontInfo.items()):
973+
_log.debug('Embedding Type-1 font %s from dvi.', dvifont.texname)
974+
fonts[pdfname] = self._embedTeXFont(dvifont)
974975
for filename in sorted(self._fontNames):
975976
Fx = self._fontNames[filename]
976977
_log.debug('Embedding font %s.', filename)
@@ -998,9 +999,14 @@ def _write_afm_font(self, filename):
998999
self.writeObject(fontdictObject, fontdict)
9991000
return fontdictObject
10001001

1001-
def _embedTeXFont(self, fontinfo):
1002-
_log.debug('Embedding TeX font %s - fontinfo=%s',
1003-
fontinfo.dvifont.texname, fontinfo.__dict__)
1002+
def _embedTeXFont(self, dvifont):
1003+
tex_font_map = dviread.PsfontsMap(dviread.find_tex_file('pdftex.map'))
1004+
psfont = tex_font_map[dvifont.texname]
1005+
if psfont.filename is None:
1006+
raise ValueError(
1007+
"No usable font file found for {} (TeX: {}); "
1008+
"the font may lack a Type-1 version"
1009+
.format(psfont.psname, dvifont.texname))
10041010

10051011
# The font dictionary is the top-level object describing a font
10061012
fontdictObject = self.reserveObject('font dictionary')
@@ -1010,17 +1016,17 @@ def _embedTeXFont(self, fontinfo):
10101016
}
10111017

10121018
# Read the font file and apply any encoding changes and effects
1013-
t1font = _type1font.Type1Font(fontinfo.fontfile)
1014-
if fontinfo.encodingfile is not None:
1019+
t1font = _type1font.Type1Font(psfont.filename)
1020+
if psfont.encoding is not None:
10151021
t1font = t1font.with_encoding(
1016-
{i: c for i, c in enumerate(dviread._parse_enc(fontinfo.encodingfile))}
1022+
{i: c for i, c in enumerate(dviread._parse_enc(psfont.encoding))}
10171023
)
1018-
if fontinfo.effects:
1019-
t1font = t1font.transform(fontinfo.effects)
1024+
if psfont.effects:
1025+
t1font = t1font.transform(psfont.effects)
10201026

10211027
# Reduce the font to only the glyphs used in the document, get the encoding
10221028
# for that subset, and compute various properties based on the encoding.
1023-
chars = frozenset(self._character_tracker.used[fontinfo.dvifont.fname])
1029+
chars = frozenset(self._character_tracker.used[dvifont.fname])
10241030
t1font = t1font.subset(chars, self._get_subset_prefix(chars))
10251031
fontdict['BaseFont'] = Name(t1font.prop['FontName'])
10261032
# createType1Descriptor writes the font data as a side effect
@@ -1031,17 +1037,15 @@ def _embedTeXFont(self, fontinfo):
10311037
lc = fontdict['LastChar'] = max(encoding.keys(), default=255)
10321038

10331039
# Convert glyph widths from TeX 12.20 fixed point to 1/1000 text space units
1034-
tfm = fontinfo.dvifont._tfm
1040+
tfm = dvifont._tfm
10351041
widths = [(1000 * metrics.tex_width) >> 20
10361042
if (metrics := tfm.get_metrics(char)) else 0
10371043
for char in range(fc, lc + 1)]
10381044
fontdict['Widths'] = widthsObject = self.reserveObject('glyph widths')
10391045
self.writeObject(widthsObject, widths)
1040-
10411046
self.writeObject(fontdictObject, fontdict)
10421047
return fontdictObject
10431048

1044-
10451049
def _generate_encoding(self, encoding):
10461050
prev = -2
10471051
result = []
@@ -1055,7 +1059,6 @@ def _generate_encoding(self, encoding):
10551059
'Differences': result
10561060
}
10571061

1058-
10591062
@_api.delete_parameter("3.11", "fontfile")
10601063
def createType1Descriptor(self, t1font, fontfile=None):
10611064
# Create and write the font descriptor and the font file

0 commit comments

Comments
 (0)