Handle dvi font names as ASCII bytestrings #6977
Merged
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
705b021
Handle dvi font names as ASCII bytestrings
jkseppan dbc8b9e
Test that the KeyError is raised when the font is missing
jkseppan 93fad55
Mention bytestrings in docstring
jkseppan 4874e4e
Add a helpful note when raising KeyError from dviread.PsFonts
jkseppan a130ba7
Attempted fix for Python 3.4 compatibility
jkseppan 0f0e41a
More python 3.4 compatibility
jkseppan a7b5772
Use numpydoc format for several dviread docstrings
jkseppan 803a96e
Remove useless docstring
jkseppan ec5d80e
Raise a more useful exception
jkseppan fe52808
Remove misleading parentheses from assert
jkseppan aa8c4f6
Simplify parsing with regular expressions
jkseppan 9de07aa
Perhaps simplify further with regular expressions
jkseppan c87b653
Remove useless assert
jkseppan 2e19a61
Fix dvi font name handling in pdf backend
jkseppan 119934a
Separate the handling of dvi fonts in the pdf backend
jkseppan 8fa303f
Simplify enc file parsing
jkseppan 94587b1
Small changes in response to code review
jkseppan 254e3df
Simplify psfonts.map parsing further
jkseppan a8674b3
Try to fix the KeyError test
jkseppan 25a8fed
ENH: make texFontMap a property
tacaswell 92e2c52
Merge pull request #6 from tacaswell/dvi-ascii
jkseppan 5ba21b0
Use file system encoding for the psfonts file name
jkseppan 10135bf
Document minor API changes
jkseppan 6de9813
Explain named group ordering
jkseppan
Jump to file
No files or symbols found.
+8
−0
2017-02-12-JKS.rst
doc/api/api_changes/2017-02-12-JKS.rst
+5
−0
dviread.rst
doc/api/dviread.rst
+55
−34
backend_pdf.py
lib/matplotlib/backends/backend_pdf.py
+212
−152
dviread.py
lib/matplotlib/dviread.py
+4
−4
test.map
lib/matplotlib/tests/baseline_images/dviread/test.map
+22
−14
test_dviread.py
lib/matplotlib/tests/test_dviread.py
| @@ -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. |
| @@ -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 = {} | ||
| @@ -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( | ||
| @@ -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, | ||
| + 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') | ||
| @@ -698,9 +740,9 @@ def _write_afm_font(self, filename): | ||
| self.writeObject(fontdictObject, fontdict) | ||
| return fontdictObject | ||
| - def embedTeXFont(self, texname, fontinfo): | ||
jkseppan
Member
|
||
| - 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 | ||
| @@ -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()) | ||
| @@ -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.""" | ||
| @@ -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 | ||
Oops, something went wrong.
Do we care about this API change?