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

Skip to content

Simplify dviFontInfo layout in backend pdf. #30082

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 49 additions & 44 deletions lib/matplotlib/backends/backend_pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,7 @@

self._internal_font_seq = (Name(f'F{i}') for i in itertools.count(1))
self._fontNames = {} # maps filenames to internal font names
self._dviFontInfo = {} # maps dvi font names to embedding information
self._dviFontInfo = {} # maps pdf names to dvifonts
# differently encoded Type-1 fonts may share the same descriptor
self._type1Descriptors = {}
self._character_tracker = _backend_pdf_ps.CharacterTracker()
Expand Down Expand Up @@ -766,10 +766,30 @@
self.writeObject(self.resourceObject, resources)

fontNames = _api.deprecated("3.11")(property(lambda self: self._fontNames))
dviFontInfo = _api.deprecated("3.11")(property(lambda self: self._dviFontInfo))
type1Descriptors = _api.deprecated("3.11")(
property(lambda self: self._type1Descriptors))

@_api.deprecated("3.11")
def dviFontInfo(self):
d = {}
tex_font_map = dviread.PsfontsMap(dviread.find_tex_file('pdftex.map'))

Check warning on line 775 in lib/matplotlib/backends/backend_pdf.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_pdf.py#L774-L775

Added lines #L774 - L775 were not covered by tests
for pdfname, dvifont in self._dviFontInfo.items():
psfont = tex_font_map[dvifont.texname]

Check warning on line 777 in lib/matplotlib/backends/backend_pdf.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_pdf.py#L777

Added line #L777 was not covered by tests
if psfont.filename is None:
raise ValueError(

Check warning on line 779 in lib/matplotlib/backends/backend_pdf.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_pdf.py#L779

Added line #L779 was not covered by tests
"No usable font file found for {} (TeX: {}); "
"the font may lack a Type-1 version"
.format(psfont.psname, dvifont.texname))
d[pdfname] = types.SimpleNamespace(

Check warning on line 783 in lib/matplotlib/backends/backend_pdf.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_pdf.py#L783

Added line #L783 was not covered by tests
dvifont=dvifont,
pdfname=pdfname,
fontfile=psfont.filename,
basefont=psfont.psname,
encodingfile=psfont.encoding,
effects=psfont.effects,
)
return d

Check warning on line 791 in lib/matplotlib/backends/backend_pdf.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_pdf.py#L791

Added line #L791 was not covered by tests

def newPage(self, width, height):
self.endStream()

Expand Down Expand Up @@ -930,39 +950,19 @@
def dviFontName(self, dvifont):
"""
Given a dvi font object, return a name suitable for Op.selectfont.
This registers the font information internally (in ``_dviFontInfo``) if
not yet registered.
"""

dvi_info = self._dviFontInfo.get(dvifont.texname)
if dvi_info is not None:
return dvi_info.pdfname

tex_font_map = dviread.PsfontsMap(dviread.find_tex_file('pdftex.map'))
psfont = tex_font_map[dvifont.texname]
if psfont.filename is None:
raise ValueError(
"No usable font file found for {} (TeX: {}); "
"the font may lack a Type-1 version"
.format(psfont.psname, dvifont.texname))

pdfname = next(self._internal_font_seq)
Register the font internally (in ``_dviFontInfo``) if not yet registered.
"""
pdfname = Name(f"F-{dvifont.texname.decode('ascii')}")
_log.debug('Assigning font %s = %s (dvi)', pdfname, dvifont.texname)
self._dviFontInfo[dvifont.texname] = types.SimpleNamespace(
dvifont=dvifont,
pdfname=pdfname,
fontfile=psfont.filename,
basefont=psfont.psname,
encodingfile=psfont.encoding,
effects=psfont.effects)
return pdfname
self._dviFontInfo[pdfname] = dvifont
return Name(pdfname)

def writeFonts(self):
fonts = {}
for dviname, info in sorted(self._dviFontInfo.items()):
Fx = info.pdfname
_log.debug('Embedding Type-1 font %s from dvi.', dviname)
fonts[Fx] = self._embedTeXFont(info)
for pdfname, dvifont in sorted(self._dviFontInfo.items()):
_log.debug('Embedding Type-1 font %s from dvi.', dvifont.texname)
fonts[pdfname] = self._embedTeXFont(dvifont)
for filename in sorted(self._fontNames):
Fx = self._fontNames[filename]
_log.debug('Embedding font %s.', filename)
Expand Down Expand Up @@ -990,13 +990,18 @@
self.writeObject(fontdictObject, fontdict)
return fontdictObject

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

# Widths
widthsObject = self.reserveObject('font widths')
tfm = fontinfo.dvifont._tfm
tfm = dvifont._tfm
# convert from TeX's 12.20 representation to 1/1000 text space units.
widths = [(1000 * metrics.tex_width) >> 20
if (metrics := tfm.get_metrics(char)) else 0
Expand All @@ -1014,28 +1019,28 @@
}

# Encoding (if needed)
if fontinfo.encodingfile is not None:
if psfont.encoding is not None:
fontdict['Encoding'] = {
'Type': Name('Encoding'),
'Differences': [
0, *map(Name, dviread._parse_enc(fontinfo.encodingfile))],
0, *map(Name, dviread._parse_enc(psfont.encoding))],
}

# We have a font file to embed - read it in and apply any effects
t1font = _type1font.Type1Font(fontinfo.fontfile)
if fontinfo.effects:
t1font = t1font.transform(fontinfo.effects)
t1font = _type1font.Type1Font(psfont.filename)
if psfont.effects:
t1font = t1font.transform(psfont.effects)

Check warning on line 1032 in lib/matplotlib/backends/backend_pdf.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_pdf.py#L1032

Added line #L1032 was not covered by tests
fontdict['BaseFont'] = Name(t1font.prop['FontName'])

# Font descriptors may be shared between differently encoded
# Type-1 fonts, so only create a new descriptor if there is no
# existing descriptor for this font.
effects = (fontinfo.effects.get('slant', 0.0),
fontinfo.effects.get('extend', 1.0))
fontdesc = self._type1Descriptors.get((fontinfo.fontfile, effects))
effects = (psfont.effects.get('slant', 0.0),
psfont.effects.get('extend', 1.0))
fontdesc = self._type1Descriptors.get((psfont.filename, effects))
if fontdesc is None:
fontdesc = self.createType1Descriptor(t1font, fontinfo.fontfile)
self._type1Descriptors[(fontinfo.fontfile, effects)] = fontdesc
fontdesc = self._type1Descriptors[(psfont.filename, effects)] = \
self.createType1Descriptor(t1font, psfont.filename)
fontdict['FontDescriptor'] = fontdesc

self.writeObject(fontdictObject, fontdict)
Expand Down
Loading