8000 Merge pull request #6428 from jkseppan/missing-ps-fonts · matplotlib/matplotlib@f99a985 · GitHub
[go: up one dir, main page]

Skip to content

Commit f99a985

Browse files
authored
Merge pull request #6428 from jkseppan/missing-ps-fonts
ENH: Give a better error message on missing PostScript fonts
2 parents 8c5b548 + 4fcc0e7 commit f99a985

File tree

4 files changed

+80
-6
lines changed

4 files changed

+80
-6
lines changed

lib/matplotlib/backends/backend_pdf.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -567,9 +567,10 @@ def newTextnote(self, text, positionRect=[-100, -100, 0, 0]):
567567
self.writeObject(annotObject, theNote)
568568
self.pageAnnotations.append(annotObject)
569569

570-
def close(self):
570+
def finalize(self):
571+
"Write out the various deferred objects and the pdf end matter."
572+
571573
self.endStream()
572-
# Write out the various deferred objects
573574
self.writeFonts()
574575
self.writeObject(
575576
self.alphaStateObject,
@@ -598,12 +599,16 @@ def close(self):
598599
# Finalize the file
599600
self.writeXref()
600601
self.writeTrailer()
602+
603+
def close(self):
604+
"Flush all buffers and free all resources."
605+
606+
self.endStream()
601607
if self.passed_in_file_object:
602608
self.fh.flush()
603-
elif self.original_file_like is not None:
604-
self.original_file_like.write(self.fh.getvalue())
605-
self.fh.close()
606609
else:
610+
if self.original_file_like is not None:
611+
self.original_file_like.write(self.fh.getvalue())
607612
self.fh.close()
608613

609614
def write(self, data):
@@ -1889,6 +1894,12 @@ def draw_tex(self, gc, x, y, s, prop, angle, ismath='TeX!', mtext=None):
18891894
pdfname = self.file.fontName(dvifont.texname)
18901895
if dvifont.texname not in self.file.dviFontInfo:
18911896
psfont = self.tex_font_mapping(dvifont.texname)
1897+
if psfont.filename is None:
1898+
self.file.broken = True
1899+
raise ValueError(
1900+
("No usable font file found for %s (%s). "
1901+
"The font may lack a Type-1 version.")
1902+
% (psfont.psname, dvifont.texname))
18921903
self.file.dviFontInfo[dvifont.texname] = Bunch(
18931904
fontfile=psfont.filename,
18941905
basefont=psfont.psname,
@@ -2456,6 +2467,7 @@ def close(self):
24562467
Finalize this object, making the underlying file a complete
24572468
PDF file.
24582469
"""
2470+
self._file.finalize()
24592471
self._file.close()
24602472
if (self.get_pagecount() == 0 and not self.keep_empty and
24612473
not self._file.passed_in_file_object):
@@ -2554,6 +2566,7 @@ def print_pdf(self, filename, **kwargs):
25542566
bbox_inches_restore=_bbox_inches_restore)
25552567
self.figure.draw(renderer)
25562568
renderer.finalize()
2569+
file.finalize()
25572570
finally:
25582571
if isinstance(filename, PdfPages): # finish off this page
25592572
file.endStream()

lib/matplotlib/tests/test_backend_pdf.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,23 @@
77

88
import io
99
import os
10+
import tempfile
11+
12+
try:
13+
from unittest.mock import patch
14+
except ImportError:
15+
from mock import patch
16+
from nose.tools import raises
1017

1118
import numpy as np
12-
from matplotlib import cm, rcParams
19+
from matplotlib import checkdep_tex, cm, rcParams
1320
from matplotlib.backends.backend_pdf import PdfPages
1421
from matplotlib import pyplot as plt
1522
from matplotlib.testing.determinism import (_determinism_source_date_epoch,
1623
_determinism_check)
1724
from matplotlib.testing.decorators import (image_comparison, knownfailureif,
1825
cleanup)
26+
from matplotlib import dviread
1927

2028

2129
@image_comparison(baseline_images=['pdf_use14corefonts'],
@@ -39,6 +47,10 @@ def test_use14corefonts():
3947
fontsize=14)
4048
ax.axhline(0.5, linewidth=0.5)
4149

50+
needs_tex = knownfailureif(
51+
not checkdep_tex(),
52+
"This test needs a TeX installation")
53+
4254

4355
@cleanup
4456
def test_type42():
@@ -178,3 +190,19 @@ def test_grayscale_alpha():
178190
ax.imshow(dd, interpolation='none', cmap='gray_r')
179191
ax.set_xticks([])
180192
ax.set_yticks([])
193+
194+
195+
@cleanup
196+
@needs_tex
197+
@raises(ValueError)
198+
@patch('matplotlib.dviread.PsfontsMap.__getitem__')
199+
def test_missing_psfont(mock):
200+
"""An error is raised if a TeX font lacks a Type-1 equivalent"""
201+
psfont = dviread.PsFont(texname='texfont', psname='Some Font',
202+
effects=None, encoding=None, filename=None)
203+
mock.configure_mock(return_value=psfont)
204+
rcParams['text.usetex'] = True
205+
fig, ax = plt.subplots()
206+
ax.text(0.5, 0.5, 'hello')
207+
with tempfile.TemporaryFile() as tmpfile:
208+
fig.savefig(tmpfile, format='pdf')

lib/matplotlib/tests/test_backend_svg.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,22 @@
55

66
import numpy as np
77
from io import BytesIO
8+
import os
9+
import tempfile
810
import xml.parsers.expat
911

12+
try:
13+
from unittest.mock import patch
14+
except ImportError:
15+
from mock import patch
16+
from nose.tools import raises
17+
1018
import matplotlib.pyplot as plt
1119
from matplotlib.testing.decorators import cleanup
1220
from matplotlib.testing.decorators import image_comparison, knownfailureif
1321
import matplotlib
22+
from matplotlib import dviread
23+
1424

1525
needs_tex = knownfailureif(
1626
not matplotlib.checkdep_tex(),
@@ -194,6 +204,23 @@ def test_determinism_tex():
194204
_test_determinism('determinism_tex.svg', usetex=True)
195205

196206

207+
@cleanup
208+
@needs_tex
209+
@raises(ValueError)
210+
@patch('matplotlib.dviread.PsfontsMap.__getitem__')
211+
def test_missing_psfont(mock):
212+
"""An error is raised if a TeX font lacks a Type-1 equivalent"""
213+
from matplotlib import rc
214+
psfont = dviread.PsFont(texname='texfont', psname='Some Font',
215+
effects=None, encoding=None, filename=None)
216+
mock.configure_mock(return_value=psfont)
217+
rc('text', usetex=True)
218+
fig, ax = plt.subplots()
219+
ax.text(0.5, 0.5, 'hello')
220+
with tempfile.NamedTemporaryFile(suffix='.svg') as tmpfile:
221+
fig.savefig(tmpfile.name)
222+
223+
197224
if __name__ == '__main__':
198225
import nose
199226
nose.runmodule(argv=['-s', '--with-doctest'], exit=False)

lib/matplotlib/textpath.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,12 @@ def get_glyphs_tex(self, prop, s, glyph_map=None,
335335
font_bunch = self.tex_font_map[dvifont.texname]
336336

337337
if font_and_encoding is None:
338+
if font_bunch.filename is None:
339+
raise ValueError(
340+
("No usable font file found for %s (%s). "
341+
"The font may lack a Type-1 version.")
342+
% (font_bunch.psname, dvifont.texname))
343+
338344
font = get_font(font_bunch.filename)
339345

340346
for charmap_name, charmap_code in [("ADOBE_CUSTOM",

0 commit comments

Comments
 (0)
0