@@ -320,3 +320,93 @@ def _gen_multi_font_text():
320320 # The resulting string contains 491 unique characters. Some file formats use 8-bit
321321 # tables, which the large number of characters exercises twice over.
322322 return fonts , test_str
323+
324+
325+ def _add_family_suffix (font , suffix ):
326+ """
327+ Add a suffix to all names in a font.
328+
329+ This code comes from a fontTools snippet:
330+ https://github.com/fonttools/fonttools/blob/main/Snippets/rename-fonts.py
331+ """
332+ WINDOWS_ENGLISH_IDS = 3 , 1 , 0x409
333+ MAC_ROMAN_IDS = 1 , 0 , 0
334+
335+ FAMILY_RELATED_IDS = dict (LEGACY_FAMILY = 1 , TRUETYPE_UNIQUE_ID = 3 , FULL_NAME = 4 ,
336+ POSTSCRIPT_NAME = 6 , PREFERRED_FAMILY = 16 , WWS_FAMILY = 21 )
337+
338+ def get_current_family_name (table ):
339+ family_name_rec = None
340+ for plat_id , enc_id , lang_id in (WINDOWS_ENGLISH_IDS , MAC_ROMAN_IDS ):
341+ for name_id in (FAMILY_RELATED_IDS ['PREFERRED_FAMILY' ],
342+ FAMILY_RELATED_IDS ['LEGACY_FAMILY' ]):
343+ family_name_rec = table .getName (nameID = name_id , platformID = plat_id ,
344+ platEncID = enc_id , langID = lang_id )
345+ if family_name_rec is not None :
346+ return family_name_rec .toUnicode ()
347+ raise ValueError ("family name not found; can't add suffix" )
348+
349+ def insert_suffix (string , family_name , suffix ):
350+ # check whether family_name is a substring
351+ start = string .find (family_name )
352+ if start != - 1 :
353+ # insert suffix after the family_name substring
354+ end = start + len (family_name )
355+ return string [:end ] + suffix + string [end :]
356+ else :
357+ # it's not, we just append the suffix at the end
358+ return string + suffix
359+
360+ def rename_record (name_record , family_name , suffix ):
361+ string = name_record .toUnicode ()
362+ new_string = insert_suffix (string , family_name , suffix )
363+ name_record .string = new_string
364+ return string , new_string
365+
366+ table = font ['name' ]
367+ family_name = get_current_family_name (table )
368+ ps_family_name = family_name .replace (' ' , '' )
369+ ps_suffix = suffix .replace (' ' , '' )
370+ for rec in table .names :
371+ name_id = rec .nameID
372+ if name_id not in FAMILY_RELATED_IDS .values ():
373+ continue
374+ if name_id == FAMILY_RELATED_IDS ['POSTSCRIPT_NAME' ]:
375+ old , new = rename_record (rec , ps_family_name , ps_suffix )
376+ elif name_id == FAMILY_RELATED_IDS ['TRUETYPE_UNIQUE_ID' ]:
377+ # The Truetype Unique ID rec may contain either the PostScript
378+ # Name or the Full Name string, so we try both
379+ if ps_family_name in rec .toUnicode ():
380+ old , new = rename_record (rec , ps_family_name , ps_suffix )
381+ else :
382+ old , new = rename_record (rec , family_name , suffix )
383+ else :
384+ old , new = rename_record (rec , family_name , suffix )
385+
386+ return family_name
387+
388+
389+ def _generate_font_subset (path , text ):
390+ """
391+ Generate a subset of a font for testing purposes.
392+
393+ The font name will be suffixed with ' MplSubset'.
394+
395+ Parameters
396+ ----------
397+ path : str or bytes or os.PathLike
398+ The path to the font to be subset. The new file will be saved in the same
399+ location with a ``-subset`` suffix.
400+ text : str
401+ The text from which characters to be subset will be derived. Usually fonts do
402+ not have a newline character, so any appearing in this text will be stripped
403+ before subsetting.
404+ """
405+ from fontTools import subset
406+ options = subset .Options ()
407+ font = subset .load_font (path , options )
408+ subsetter = subset .Subsetter (options = options )
409+ subsetter .populate (text = text .replace ('\n ' , '' ))
410+ subsetter .subset (font )
411+ _add_family_suffix (font , ' MplSubset' )
412+ subset .save_font (font , path .with_stem (path .stem + '-subset' ), options )
0 commit comments