-
Here is the font I have: https://fonts.google.com/share?selection.family=Akshar:wght@300;400;500;600;700 I know that this font contain these fullname: "Akshar Light", "Akshar", "Akshar Medium", "Akshar SemiBold", "Akshar". But, if I do something like this, it will only print "Akshar Light": font = ttLib.TTFont("Akshar-VariableFont_wght.ttf")
for name in font["name"].names:
if name.nameID == 4:
print(name.toUnicode()) How can I get all the font fullname? I think I simply don't understand how we can manipulate variation font with fonttools. PS: This is not a solution, because I don't want postscriptName ! font = ttLib.TTFont("Akshar-VariableFont_wght.ttf")
for instance in font["fvar"].instances:
print(font["name"].getDebugName(instance.postscriptNameID)) Edit 2022-06-06: My goal was to get the same thing that windows can provide, but finally, I think that it does some kind of operation and these name are not directly in the font. |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 5 replies
-
So you want to get the names for each fvar instance? font = ttLib.TTFont("Akshar-VariableFont_wght.ttf")
for instance in font["fvar"].instances:
print(font["name"].getName(instance.postscriptNameID, 3, 1, 0x409).toUnicode()) |
Beta Was this translation helpful? Give feedback.
-
I’d use each from fontTools import ttLib
font = ttLib.TTFont("Akshar-VariableFont_wght.ttf")
family = font["name"].getName(16, 3, 1, 0x409)
if family is None:
family = font["name"].getName(1, 3, 1, 0x409)
for instance in font["fvar"].instances:
style = font["name"].getName(instance.subfamilyNameID, 3, 1, 0x409)
print(f"{family} {style}") This gives you the instance names from the |
Beta Was this translation helpful? Give feedback.
-
Hey, again me. I just saw that it was write in the stat page in the opentype documentation. Windows (DirectWrite) seems to follow the R/B/I/BI model + an validation for the family (if nameID 16 does not exist, take nameID 1) so here is the code for it. import sys
from typing import Dict, List
from fontTools import ttLib
from fontTools.ttLib import ttFont
from fontTools.ttLib.tables._f_v_a_r import NamedInstance
from fontTools.ttLib.tables._n_a_m_e import NameRecord
def sortNamingTable(names: List[NameRecord]) -> List[NameRecord]:
"""
Parameters:
names (List[NameRecord]): Naming table
Returns:
The sorted naming table.
Based on FontConfig:
- https://gitlab.freedesktop.org/fontconfig/fontconfig/-/blob/d863f6778915f7dd224c98c814247ec292904e30/src/fcfreetype.c#L1127-1140
"""
def isEnglish(name: NameRecord) -> bool:
# From: https://gitlab.freedesktop.org/fontconfig/fontconfig/-/blob/d863f6778915f7dd224c98c814247ec292904e30/src/fcfreetype.c#L1111-1125
return (name.platformID, name.langID) in ((1, 0), (3, 0x409))
# From: https://github.com/freetype/freetype/blob/b98dd169a1823485e35b3007ce707a6712dcd525/include/freetype/ttnameid.h#L86-L91
PLATFORM_ID_APPLE_UNICODE = 0
PLATFORM_ID_MACINTOSH = 1
PLATFORM_ID_ISO = 2
PLATFORM_ID_MICROSOFT = 3
# From: https://gitlab.freedesktop.org/fontconfig/fontconfig/-/blob/d863f6778915f7dd224c98c814247ec292904e30/src/fcfreetype.c#L1078
PLATFORM_ID_ORDER = [
PLATFORM_ID_MICROSOFT,
PLATFORM_ID_APPLE_UNICODE,
PLATFORM_ID_MACINTOSH,
PLATFORM_ID_ISO,
]
return sorted(names, key=lambda name: (PLATFORM_ID_ORDER.index(name.platformID), name.nameID, name.platEncID, -isEnglish(name), name.langID))
def getFirstDecodedName(nameID: int, names: List[NameRecord]) -> str:
"""
Parameters:
names (List[NameRecord]): Naming table
Returns:
The first decoded name.
"""
names = sortNamingTable(names)
for name in names:
if name.nameID != nameID:
continue
try:
unistr = name.toUnicode()
except UnicodeDecodeError:
continue
return unistr
def createFamilyNamedInstanceDict(font: ttFont) -> Dict[str, NamedInstance]:
"""
Parameters:
font (ttFont): A font
Returns:
An dictionnary. The key is the font name and the value an NamedInstance
The dictionnary support the R/B/I/BI family model: https://learn.microsoft.com/en-us/typography/opentype/spec/stat#alternate-font-family-models
"""
if "fvar" not in font:
raise Exception("The font is not an Variable Font.")
# Read the note about the R/B/I/BI model: https://learn.microsoft.com/en-us/typography/opentype/spec/stat#alternate-font-family-models
INVALID_STYLE = ("regular", "bold", "italic", "oblique")
family_name = getFirstDecodedName(16, font['name'].names)
# If nameID 16 is None, try nameID 1https://learn.microsoft.com/en-us/typography/opentype/spec/otvaroverview#terminology
if family_name is None:
family_name = getFirstDecodedName(1, font['name'].names)
instances_by_name: Dict[str, NamedInstance] = {}
for instance in font["fvar"].instances:
style = getFirstDecodedName(instance.subfamilyNameID, font['name'].names)
if style.lower().strip() in INVALID_STYLE:
font_name = family_name
else:
font_name = f"{family_name} {style}"
instances_by_name[font_name] = instance
return instances_by_name
def main():
font_path = r"FONT_PATH"
font = ttLib.TTFont(font_path)
instances_by_name = createFamilyNamedInstanceDict(font)
# Example: instances_by_name["Bahnschrift"]
if __name__ == "__main__":
sys.exit(main()) |
Beta Was this translation helpful? Give feedback.
Hey, again me.
I just saw that it was write in the stat page in the opentype documentation.
Windows (DirectWrite) seems to follow the R/B/I/BI model + an validation for the family (if nameID 16 does not exist, take nameID 1) so here is the code for it.