@@ -230,6 +230,7 @@ def __init__(self, filename, dpi):
230230 self .dpi = dpi
231231 self .fonts = {}
232232 self .state = _dvistate .pre
233+ self ._missing_font = None
233234
234235 def __enter__ (self ):
235236 """Context manager enter method, does nothing."""
@@ -337,6 +338,8 @@ def _read(self):
337338 while True :
338339 byte = self .file .read (1 )[0 ]
339340 self ._dtable [byte ](self , byte )
341+ if self ._missing_font :
342+ raise self ._missing_font
340343 name = self ._dtable [byte ].__name__
341344 if name == "_push" :
342345 down_stack .append (down_stack [- 1 ])
@@ -364,11 +367,15 @@ def _arg(self, nbytes, signed=False):
364367 @_dispatch (min = 0 , max = 127 , state = _dvistate .inpage )
365368 def _set_char_immediate (self , char ):
366369 self ._put_char_real (char )
370+ if isinstance (self .fonts [self .f ], FileNotFoundError ):
371+ return
367372 self .h += self .fonts [self .f ]._width_of (char )
368373
369374 @_dispatch (min = 128 , max = 131 , state = _dvistate .inpage , args = ('olen1' ,))
370375 def _set_char (self , char ):
371376 self ._put_char_real (char )
377+ if isinstance (self .fonts [self .f ], FileNotFoundError ):
378+ return
372379 self .h += self .fonts [self .f ]._width_of (char )
373380
374381 @_dispatch (132 , state = _dvistate .inpage , args = ('s4' , 's4' ))
@@ -382,7 +389,9 @@ def _put_char(self, char):
382389
383390 def _put_char_real (self , char ):
384391 font = self .fonts [self .f ]
385- if font ._vf is None :
392+ if isinstance (font , FileNotFoundError ):
393+ self ._missing_font = font
394+ elif font ._vf is None :
386395 self .text .append (Text (self .h , self .v , font , char ,
387396 font ._width_of (char )))
388397 else :
@@ -486,7 +495,16 @@ def _fnt_def(self, k, c, s, d, a, l):
486495 def _fnt_def_real (self , k , c , s , d , a , l ):
487496 n = self .file .read (a + l )
488497 fontname = n [- l :].decode ('ascii' )
489- tfm = _tfmfile (fontname )
498+ try :
499+ tfm = _tfmfile (fontname )
500+ except FileNotFoundError as exc :
501+ # Explicitly allow defining missing fonts for Vf support; we only
502+ # register an error when trying to load a glyph from a missing font
503+ # and throw that error in Dvi._read. For Vf, _finalize_packet
504+ # checks whether a missing glyph has been used, and in that case
505+ # skips the glyph definition.
506+ self .fonts [k ] = exc
507+ return
490508 if c != 0 and tfm .checksum != 0 and c != tfm .checksum :
491509 raise ValueError ('tfm checksum mismatch: %s' % n )
492510 try :
@@ -712,12 +730,14 @@ def _init_packet(self, pl):
712730 self .h , self .v , self .w , self .x , self .y , self .z = 0 , 0 , 0 , 0 , 0 , 0
713731 self .stack , self .text , self .boxes = [], [], []
714732 self .f = self ._first_font
733+ self ._missing_font = None
715734 return self .file .tell () + pl
716735
717736 def _finalize_packet (self , packet_char , packet_width ):
718- self ._chars [packet_char ] = Page (
719- text = self .text , boxes = self .boxes , width = packet_width ,
720- height = None , descent = None )
737+ if not self ._missing_font : # Otherwise we don't have full glyph definition.
738+ self ._chars [packet_char ] = Page (
739+ text = self .text , boxes = self .boxes , width = packet_width ,
740+ height = None , descent = None )
721741 self .state = _dvistate .outer
722742
723743 def _pre (self , i , x , cs , ds ):
0 commit comments