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