22A PostScript backend, which can produce both PostScript .ps and .eps.
33"""
44
5- import binascii
65import bisect
76import codecs
87import datetime
98from enum import Enum
109import functools
11- from io import BytesIO , StringIO
10+ from io import StringIO
1211import itertools
1312import logging
1413import math
@@ -272,6 +271,7 @@ def _serialize_type42(font, subset, fontdata):
272271def _version_and_breakpoints (loca , fontdata ):
273272 """
274273 Read the version number of the font and determine sfnts breakpoints.
274+
275275 When a TrueType font file is written as a Type 42 font, it has to be
276276 broken into substrings of at most 65535 bytes. These substrings must
277277 begin at font table boundaries or glyph boundaries in the glyf table.
@@ -289,31 +289,24 @@ def _version_and_breakpoints(loca, fontdata):
289289
290290 Returns
291291 -------
292- tuple
293- ((v1, v2), breakpoints) where v1 is the major version number,
294- v2 is the minor version number and breakpoints is a sorted list
295- of offsets into fontdata; if loca is not available, just the table
296- boundaries
292+ version : tuple[int, int]
293+ A 2-tuple of the major version number and minor version number.
294+ breakpoints : list[int]
295+ The breakpoints is a sorted list of offsets into fontdata; if loca is not
296+ available, just the table boundaries.
297297 """
298298 v1 , v2 , numTables = struct .unpack ('>3h' , fontdata [:6 ])
299299 version = (v1 , v2 )
300300
301301 tables = {}
302302 for i in range (numTables ):
303- tag , _ , offset , _ = struct .unpack (
304- '>4sIII' ,
305- fontdata [12 + i * 16 :12 + (i + 1 )* 16 ]
306- )
303+ tag , _ , offset , _ = struct .unpack ('>4sIII' , fontdata [12 + i * 16 :12 + (i + 1 )* 16 ])
307304 tables [tag .decode ('ascii' )] = offset
308305 if loca is not None :
309- glyf_breakpoints = {
310- tables ['glyf' ] + offset for offset in loca .locations [:- 1 ]
311- }
306+ glyf_breakpoints = {tables ['glyf' ] + offset for offset in loca .locations [:- 1 ]}
312307 else :
313308 glyf_breakpoints = set ()
314- breakpoints = sorted (
315- set (tables .values ()) | glyf_breakpoints | {len (fontdata )}
316- )
309+ breakpoints = sorted ({* tables .values (), * glyf_breakpoints , len (fontdata )})
317310
318311 return version , breakpoints
319312
@@ -359,13 +352,12 @@ def _charstrings(font):
359352 str
360353 A definition of the CharStrings dictionary in PostScript
361354 """
362- s = StringIO ()
363355 go = font .getGlyphOrder ()
364- s . write ( f'/CharStrings { len (go )} dict dup begin\n ' )
356+ s = f'/CharStrings { len (go )} dict dup begin\n '
365357 for i , name in enumerate (go ):
366- s . write ( f'/{ name } { i } def\n ' )
367- s . write ( 'end readonly def' )
368- return s . getvalue ()
358+ s += f'/{ name } { i } def\n '
359+ s += 'end readonly def'
360+ return s
369361
370362
371363def _sfnts (fontdata , font , breakpoints ):
@@ -389,21 +381,17 @@ def _sfnts(fontdata, font, breakpoints):
389381 The sfnts array for the font definition, consisting
390382 of hex-encoded strings in PostScript format
391383 """
392- b = BytesIO ()
393- b .write (b'/sfnts[' )
384+ s = '/sfnts['
394385 pos = 0
395386 while pos < len (fontdata ):
396387 i = bisect .bisect_left (breakpoints , pos + 65534 )
397388 newpos = breakpoints [i - 1 ]
398389 if newpos <= pos :
399390 # have to accept a larger string
400391 newpos = breakpoints [- 1 ]
401- b .write (b'<' )
402- b .write (binascii .hexlify (fontdata [pos :newpos ]))
403- b .write (b'00>' ) # need an extra zero byte on every string
392+ s += f'<{ fontdata [pos :newpos ].hex ()} 00>' # Always NUL terminate.
404393 pos = newpos
405- b .write (b']def' )
406- s = b .getvalue ().decode ('ascii' )
394+ s += ']def'
407395 return '\n ' .join (s [i :i + 100 ] for i in range (0 , len (s ), 100 ))
408396
409397
0 commit comments