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

Skip to content

Commit 36a6703

Browse files
committed
Simplify dviFontInfo layout in backend pdf.
- Use a simpler deterministic mapping of tex font names to pdf embedding names. - Only resolve the required attributes when needed (in _embedTeXFont), which avoids e.g. having to carry around and worry about attributes with different names (e.g. "encoding" vs. "encodingfile").
1 parent 1c881a3 commit 36a6703

File tree

1 file changed

+49
-44
lines changed

1 file changed

+49
-44
lines changed

lib/matplotlib/backends/backend_pdf.py

Lines changed: 49 additions & 44 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
# differently encoded Type-1 fonts may share the same descriptor
726726
self._type1Descriptors = {}
727727
self._character_tracker = _backend_pdf_ps.CharacterTracker()
@@ -766,10 +766,30 @@ def __init__(self, filename, metadata=None):
766766
self.writeObject(self.resourceObject, resources)
767767

768768
fontNames = _api.deprecated("3.11")(property(lambda self: self._fontNames))
769-
dviFontInfo = _api.deprecated("3.11")(property(lambda self: self._dviFontInfo))
770769
type1Descriptors = _api.deprecated("3.11")(
771770
property(lambda self: self._type1Descriptors))
772771

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

@@ -930,39 +950,19 @@ def fontName(self, fontprop):
930950
def dviFontName(self, dvifont):
931951
"""
932952
Given a dvi font object, return a name suitable for Op.selectfont.
933-
This registers the font information internally (in ``_dviFontInfo``) if
934-
not yet registered.
935-
"""
936-
937-
dvi_info = self._dviFontInfo.get(dvifont.texname)
938-
if dvi_info is not None:
939-
return dvi_info.pdfname
940-
941-
tex_font_map = dviread.PsfontsMap(dviread.find_tex_file('pdftex.map'))
942-
psfont = tex_font_map[dvifont.texname]
943-
if psfont.filename is None:
944-
raise ValueError(
945-
"No usable font file found for {} (TeX: {}); "
946-
"the font may lack a Type-1 version"
947-
.format(psfont.psname, dvifont.texname))
948953
949-
pdfname = next(self._internal_font_seq)
954+
Register the font internally (in ``_dviFontInfo``) if not yet registered.
955+
"""
956+
pdfname = Name(f"F-{dvifont.texname.decode('ascii')}")
950957
_log.debug('Assigning font %s = %s (dvi)', pdfname, dvifont.texname)
951-
self._dviFontInfo[dvifont.texname] = types.SimpleNamespace(
952-
dvifont=dvifont,
953-
pdfname=pdfname,
954-
fontfile=psfont.filename,
955-
basefont=psfont.psname,
956-
encodingfile=psfont.encoding,
957-
effects=psfont.effects)
958-
return pdfname
958+
self._dviFontInfo[pdfname] = dvifont
959+
return Name(pdfname)
959960

960961
def writeFonts(self):
961962
fonts = {}
962-
for dviname, info in sorted(self._dviFontInfo.items()):
963-
Fx = info.pdfname
964-
_log.debug('Embedding Type-1 font %s from dvi.', dviname)
965-
fonts[Fx] = self._embedTeXFont(info)
963+
for pdfname, dvifont in sorted(self._dviFontInfo.items()):
964+
_log.debug('Embedding Type-1 font %s from dvi.', dvifont.texname)
965+
fonts[pdfname] = self._embedTeXFont(dvifont)
966966
for filename in sorted(self._fontNames):
967967
Fx = self._fontNames[filename]
968968
_log.debug('Embedding font %s.', filename)
@@ -990,13 +990,18 @@ def _write_afm_font(self, filename):
990990
self.writeObject(fontdictObject, fontdict)
991991
return fontdictObject
992992

993-
def _embedTeXFont(self, fontinfo):
994-
_log.debug('Embedding TeX font %s - fontinfo=%s',
995-
fontinfo.dvifont.texname, fontinfo.__dict__)
993+
def _embedTeXFont(self, dvifont):
994+
psfont = dviread.PsfontsMap(dviread.find_tex_file('pdftex.map'))[
995+
dvifont.texname]
996+
if psfont.filename is None:
997+
raise ValueError(
998+
"No usable font file found for {} (TeX: {}); "
999+
"the font may lack a Type-1 version"
1000+
.format(psfont.psname, dvifont.texname))
9961001

9971002
# Widths
9981003
widthsObject = self.reserveObject('font widths')
999-
tfm = fontinfo.dvifont._tfm
1004+
tfm = dvifont._tfm
10001005
# convert from TeX's 12.20 representation to 1/1000 text space units.
10011006
widths = [(1000 * metrics.tex_width) >> 20
10021007
if (metrics := tfm.get_metrics(char)) else 0
@@ -1014,28 +1019,28 @@ def _embedTeXFont(self, fontinfo):
10141019
}
10151020

10161021
# Encoding (if needed)
1017-
if fontinfo.encodingfile is not None:
1022+
if psfont.encoding is not None:
10181023
fontdict['Encoding'] = {
10191024
'Type': Name('Encoding'),
10201025
'Differences': [
1021-
0, *map(Name, dviread._parse_enc(fontinfo.encodingfile))],
1026+
0, *map(Name, dviread._parse_enc(psfont.encoding))],
10221027
}
10231028

10241029
# We have a font file to embed - read it in and apply any effects
1025-
t1font = _type1font.Type1Font(fontinfo.fontfile)
1026-
if fontinfo.effects:
1027-
t1font = t1font.transform(fontinfo.effects)
1030+
t1font = _type1font.Type1Font(psfont.filename)
1031+
if psfont.effects:
1032+
t1font = t1font.transform(psfont.effects)
10281033
fontdict['BaseFont'] = Name(t1font.prop['FontName'])
10291034

10301035
# Font descriptors may be shared between differently encoded
10311036
# Type-1 fonts, so only create a new descriptor if there is no
10321037
# existing descriptor for this font.
1033-
effects = (fontinfo.effects.get('slant', 0.0),
1034-
fontinfo.effects.get('extend', 1.0))
1035-
fontdesc = self._type1Descriptors.get((fontinfo.fontfile, effects))
1038+
effects = (psfont.effects.get('slant', 0.0),
1039+
psfont.effects.get('extend', 1.0))
1040+
fontdesc = self._type1Descriptors.get((psfont.filename, effects))
10361041
if fontdesc is None:
1037-
fontdesc = self.createType1Descriptor(t1font, fontinfo.fontfile)
1038-
self._type1Descriptors[(fontinfo.fontfile, effects)] = fontdesc
1042+
fontdesc = self._type1Descriptors[(psfont.filename, effects)] = \
1043+
self.createType1Descriptor(t1font, psfont.filename)
10391044
fontdict['FontDescriptor'] = fontdesc
10401045

10411046
self.writeObject(fontdictObject, fontdict)

0 commit comments

Comments
 (0)