Skip to content

Handle dvi font names as ASCII bytestrings #6977

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

Merged
merged 24 commits into from
Feb 26, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
705b021
Handle dvi font names as ASCII bytestrings
jkseppan Aug 25, 2016
dbc8b9e
Test that the KeyError is raised when the font is missing
jkseppan Aug 25, 2016
93fad55
Mention bytestrings in docstring
jkseppan Aug 25, 2016
4874e4e
Add a helpful note when raising KeyError from dviread.PsFonts
jkseppan Aug 25, 2016
a130ba7
Attempted fix for Python 3.4 compatibility
jkseppan Aug 25, 2016
0f0e41a
More python 3.4 compatibility
jkseppan Aug 26, 2016
a7b5772
Use numpydoc format for several dviread docstrings
jkseppan Dec 27, 2016
803a96e
Remove useless docstring
jkseppan Dec 27, 2016
ec5d80e
Raise a more useful exception
jkseppan Dec 27, 2016
fe52808
Remove misleading parentheses from assert
jkseppan Dec 27, 2016
aa8c4f6
Simplify parsing with regular expressions
jkseppan Dec 27, 2016
9de07aa
Perhaps simplify further with regular expressions
jkseppan Dec 27, 2016
c87b653
Remove useless assert
jkseppan Dec 29, 2016
2e19a61
Fix dvi font name handling in pdf backend
jkseppan Dec 31, 2016
119934a
Separate the handling of dvi fonts in the pdf backend
jkseppan Jan 1, 2017
8fa303f
Simplify enc file parsing
jkseppan Jan 2, 2017
94587b1
Small changes in response to code review
jkseppan Jan 3, 2017
254e3df
Simplify psfonts.map parsing further
jkseppan Jan 3, 2017
a8674b3
Try to fix the KeyError test
jkseppan Jan 29, 2017
25a8fed
ENH: make texFontMap a property
tacaswell Feb 11, 2017
92e2c52
Merge pull request #6 from tacaswell/dvi-ascii
jkseppan Feb 12, 2017
5ba21b0
Use file system encoding for the psfonts file name
jkseppan Feb 12, 2017
10135bf
Document minor API changes
jkseppan Feb 12, 2017
6de9813
Explain named group ordering
jkseppan Feb 12, 2017
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
8 changes: 8 additions & 0 deletions doc/api/api_changes/2017-02-12-JKS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Changes to PDF backend methods
``````````````````````````````

The methods `embedTeXFont` and `tex_font_mapping` of
`matplotlib.backend_pdf.PdfFile` have been removed.
It is unlikely that external users would have called
these methods, which are related to the font system
internal to the PDF backend.
5 changes: 5 additions & 0 deletions doc/api/dviread.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,9 @@ dviread
.. automodule:: matplotlib.dviread
:members:
:undoc-members:
:exclude-members: Dvi
:show-inheritance:

.. autoclass:: matplotlib.dviread.Dvi
:members: __iter__,close
:show-inheritance:
89 changes: 55 additions & 34 deletions lib/matplotlib/backends/backend_pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,8 @@ def __init__(self, filename, metadata=None):

self.fontNames = {} # maps filenames to internal font names
self.nextFont = 1 # next free internal font name
self.dviFontInfo = {} # information on dvi fonts
self.dviFontInfo = {} # maps dvi font names to embedding information
self._texFontMap = None # maps TeX font names to PostScript fonts
# differently encoded Type-1 fonts may share the same descriptor
self.type1Descriptors = {}
self.used_characters = {}
Expand Down Expand Up @@ -637,10 +638,10 @@ def fontName(self, fontprop):
"""
Select a font based on fontprop and return a name suitable for
Op.selectfont. If fontprop is a string, it will be interpreted
as the filename (or dvi name) of the font.
as the filename of the font.
"""

if is_string_like(fontprop):
if isinstance(fontprop, six.string_types):
filename = fontprop
elif rcParams['pdf.use14corefonts']:
filename = findfont(
Expand All @@ -662,21 +663,62 @@ def fontName(self, fontprop):

return Fx

@property
def texFontMap(self):
# lazy-load texFontMap, it takes a while to parse
# and usetex is a relatively rare use case
if self._texFontMap is None:
self._texFontMap = dviread.PsfontsMap(
dviread.find_tex_file('pdftex.map'))

return self._texFontMap

def dviFontName(self, dvifont):
"""
Given a dvi font object, return a name suitable for Op.selectfont.
This registers the font information in self.dviFontInfo if not yet
registered.
"""

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

psfont = self.texFontMap[dvifont.texname]
if psfont.filename is None:
raise ValueError(
("No usable font file found for {0} (TeX: {1}). "
"The font may lack a Type-1 version.")
.format(psfont.psname, dvifont.texname))

pdfname = Name('F%d' % self.nextFont)
self.nextFont += 1
matplotlib.verbose.report(
'Assigning font {0} = {1} (dvi)'.format(pdfname, dvifont.texname),
'debug')
self.dviFontInfo[dvifont.texname] = Bunch(
dvifont=dvifont,
pdfname=pdfname,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we care about this API change?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that's something that an external user would ever have called. Let's mark the function private with an underscore and document the change.

fontfile=psfont.filename,
basefont=psfont.psname,
encodingfile=psfont.encoding,
effects=psfont.effects)
return pdfname

def writeFonts(self):
fonts = {}
for dviname, info in sorted(self.dviFontInfo.items()):
Fx = info.pdfname
matplotlib.verbose.report('Embedding Type-1 font %s from dvi'
% dviname, 'debug')
fonts[Fx] = self._embedTeXFont(info)
for filename in sorted(self.fontNames):
Fx = self.fontNames[filename]
matplotlib.verbose.report('Embedding font %s' % filename, 'debug')
if filename.endswith('.afm'):
# from pdf.use14corefonts
matplotlib.verbose.report('Writing AFM font', 'debug')
fonts[Fx] = self._write_afm_font(filename)
elif filename in self.dviFontInfo:
# a Type 1 font from a dvi file;
# the filename is really the TeX name
matplotlib.verbose.report('Writing Type-1 font', 'debug')
fonts[Fx] = self.embedTeXFont(filename,
self.dviFontInfo[filename])
else:
# a normal TrueType font
matplotlib.verbose.report('Writing TrueType font', 'debug')
Expand All @@ -698,9 +740,9 @@ def _write_afm_font(self, filename):
self.writeObject(fontdictObject, fontdict)
return fontdictObject

def embedTeXFont(self, texname, fontinfo):
msg = ('Embedding TeX font ' + texname + ' - fontinfo=' +
repr(fontinfo.__dict__))
def _embedTeXFont(self, fontinfo):
msg = ('Embedding TeX font {0} - fontinfo={1}'
.format(fontinfo.dvifont.texname, fontinfo.__dict__))
matplotlib.verbose.report(msg, 'debug')

# Widths
Expand Down Expand Up @@ -1570,7 +1612,6 @@ def __init__(self, file, image_dpi, height, width):
self.gc = self.new_gc()
self.mathtext_parser = MathTextParser("Pdf")
self.image_dpi = image_dpi
self.tex_font_map = None

def finalize(self):
self.file.output(*self.gc.finalize())
Expand All @@ -1596,12 +1637,6 @@ def check_gc(self, gc, fillcolor=None):
gc._fillcolor = orig_fill
gc._effective_alphas = orig_alphas

def tex_font_mapping(self, texfont):
if self.tex_font_map is None:
self.tex_font_map = \
dviread.PsfontsMap(dviread.find_tex_file('pdftex.map'))
return self.tex_font_map[texfont]

def track_characters(self, font, s):
"""Keeps track of which characters are required from
each font."""
Expand Down Expand Up @@ -1894,21 +1929,7 @@ def draw_tex(self, gc, x, y, s, prop, angle, ismath='TeX!', mtext=None):
oldfont, seq = None, []
for x1, y1, dvifont, glyph, width in page.text:
if dvifont != oldfont:
pdfname = self.file.fontName(dvifont.texname)
if dvifont.texname not in self.file.dviFontInfo:
psfont = self.tex_font_mapping(dvifont.texname)
if psfont.filename is None:
self.file.broken = True
raise ValueError(
("No usable font file found for %s (%s). "
"The font may lack a Type-1 version.")
% (psfont.psname, dvifont.texname))
self.file.dviFontInfo[dvifont.texname] = Bunch(
fontfile=psfont.filename,
basefont=psfont.psname,
encodingfile=psfont.encoding,
effects=psfont.effects,
dvifont=dvifont)
pdfname = self.file.dviFontName(dvifont)
seq += [['font', pdfname, dvifont.size]]
oldfont = dvifont
# We need to convert the glyph numbers to bytes, and the easiest
Expand Down
Loading