classes.c12_glyph
1from functools import cached_property 2from loguru import logger 3import drawBot 4import colorama 5from icecream import ic 6 7from lib import fonts, helpers, glyphs 8 9 10class KGlyph: 11 def __init__(self, source: str) -> None: 12 """Initialize a KGlyph instance.""" 13 self.source: str = source 14 """The glyph source identifier. Can be character, name, or unicode.""" 15 16 @cached_property 17 def name(self) -> str: 18 """ 19 Returns: 20 The glyph name, see `lib.glyphs.toName`. 21 22 Example: 23 ccaron 24 """ 25 return glyphs.toName(self.source) 26 27 @cached_property 28 def char(self) -> str: 29 """ 30 Returns: 31 The corresponding character, see `lib.glyphs.toChar`. 32 33 Example: 34 č 35 """ 36 return glyphs.toChar(self.source) 37 38 @cached_property 39 def charBase(self) -> str: 40 """ 41 Returns: 42 The base character of the glyph, see `lib.glyphs.toCharBase`. 43 44 Example: 45 Á.ss01 => Á 46 S.ss01.cv01 => S 47 """ 48 return glyphs.toCharBase(self.source) 49 50 @cached_property 51 def unicode(self) -> str: 52 """ 53 Returns: 54 The corresponding unicode string, see `lib.glyphs.toUni`. 55 56 Example: 57 uni010D 58 """ 59 return glyphs.toUni(self.source, "full") 60 61 @cached_property 62 def category(self) -> str: 63 """Returns the glyph category, see `lib.glyphs.getCategory`.""" 64 return glyphs.getCategory(self.source) 65 66 @cached_property 67 def canLigate(self) -> bool: 68 """Returns True if source is a multi-char sequence that can form a ligature. 69 70 See `lib.glyphs.canLigate`. 71 72 Examples: 73 KGlyph("fi").canLigate => True 74 KGlyph("f_i").canLigate => False 75 """ 76 return glyphs.canLigate(self.source) 77 78 @cached_property 79 def isLigature(self) -> bool: 80 """Returns True if source represents an actual ligature glyph. 81 82 See `lib.glyphs.isLigature`. 83 84 Examples: 85 KGlyph("fi").isLigature => True 86 KGlyph("f_i").isLigature => True 87 KGlyph("tt").isLigature => False 88 """ 89 return glyphs.isLigature(self.source) 90 91 def get(self, key: str, defaultValue=None): 92 """ 93 Retrieve an attribute by key, emulating `dict.get()`. 94 95 Args: 96 key: The attribute name to retrieve. 97 defaultValue: Value to return if the attribute is not found. 98 99 Returns: 100 The attribute value or defaultValue if not found. 101 """ 102 return getattr(self, key, defaultValue) 103 104 def getSupported(self, fontPath: str, warn: bool = True) -> str | None: 105 """ 106 Find the supported glyph name in the given font. 107 108 Args: 109 fontPath: The font path to check for glyph support. 110 111 Returns: 112 The name of the supported glyph in the font, or None if not found. 113 """ 114 glyphsInFont = glyphs.listAvailableGlyphs(fontPath) 115 116 possibleMatches = set( 117 helpers.removeNone( 118 [ 119 *helpers.coerceList(self.name), 120 self.char, 121 self.unicode, 122 glyphs.toSnakeCase(self.source), 123 glyphs.toPartBase(self.source), 124 ] 125 ) 126 ) 127 # ! Edge case: For certain ligatures like "t_t", some fonts may use a ".liga" suffix for the supported glyph name. 128 if self.canLigate: 129 possibleMatches.update( 130 [ 131 f"{variant}.liga" 132 for variant in [self.name, glyphs.toSnakeCase(self.source)] 133 ] 134 ) 135 136 for possibleMatch in possibleMatches: 137 if possibleMatch in glyphsInFont: 138 return possibleMatch 139 140 if warn: 141 logger.warning( 142 "{} doesn’t support glyph {}", 143 fonts.getFontName(fontPath), 144 f"{colorama.Back.LIGHTYELLOW_EX}{self.source}{colorama.Style.RESET_ALL}", 145 ) 146 147 def __str__(self) -> str: 148 """Returns a human-friendly string representation of the KGlyph, including name, character, unicode, and category.""" 149 output = f"{colorama.Back.BLACK}KGlyph{colorama.Style.RESET_ALL}" 150 151 if self.name: 152 # Can be multiple names 153 isMultipleNames = isinstance(self.name, list) 154 names = helpers.coerceList(self.name) 155 156 output += " Name" + ("s" if isMultipleNames else " ") 157 for ni, name in enumerate(names): 158 isNotFirst = ni != 0 159 if isNotFirst: 160 output += "\n" + " " * 12 161 output += f" {colorama.Back.LIGHTYELLOW_EX}{name.ljust(30)}{colorama.Style.RESET_ALL}" 162 163 if self.char: 164 output += f" Char {colorama.Back.BLUE}{self.char}{colorama.Style.RESET_ALL}" 165 # Justify text 166 charAllotedSpaces = 6 167 if self.name == "zerowidthspace": 168 charAllotedSpaces += 1 169 output += " " * (charAllotedSpaces - len(self.char)) 170 171 unicodeToPrint = self.unicode or "" 172 output += ( 173 f" Unicode {colorama.Back.CYAN}{unicodeToPrint}{colorama.Style.RESET_ALL}" 174 ) 175 output += " " * (9 - len(unicodeToPrint)) 176 177 output += f" Category {colorama.Back.LIGHTRED_EX}{self.category}{colorama.Style.RESET_ALL}" 178 179 return output
class
KGlyph:
11class KGlyph: 12 def __init__(self, source: str) -> None: 13 """Initialize a KGlyph instance.""" 14 self.source: str = source 15 """The glyph source identifier. Can be character, name, or unicode.""" 16 17 @cached_property 18 def name(self) -> str: 19 """ 20 Returns: 21 The glyph name, see `lib.glyphs.toName`. 22 23 Example: 24 ccaron 25 """ 26 return glyphs.toName(self.source) 27 28 @cached_property 29 def char(self) -> str: 30 """ 31 Returns: 32 The corresponding character, see `lib.glyphs.toChar`. 33 34 Example: 35 č 36 """ 37 return glyphs.toChar(self.source) 38 39 @cached_property 40 def charBase(self) -> str: 41 """ 42 Returns: 43 The base character of the glyph, see `lib.glyphs.toCharBase`. 44 45 Example: 46 Á.ss01 => Á 47 S.ss01.cv01 => S 48 """ 49 return glyphs.toCharBase(self.source) 50 51 @cached_property 52 def unicode(self) -> str: 53 """ 54 Returns: 55 The corresponding unicode string, see `lib.glyphs.toUni`. 56 57 Example: 58 uni010D 59 """ 60 return glyphs.toUni(self.source, "full") 61 62 @cached_property 63 def category(self) -> str: 64 """Returns the glyph category, see `lib.glyphs.getCategory`.""" 65 return glyphs.getCategory(self.source) 66 67 @cached_property 68 def canLigate(self) -> bool: 69 """Returns True if source is a multi-char sequence that can form a ligature. 70 71 See `lib.glyphs.canLigate`. 72 73 Examples: 74 KGlyph("fi").canLigate => True 75 KGlyph("f_i").canLigate => False 76 """ 77 return glyphs.canLigate(self.source) 78 79 @cached_property 80 def isLigature(self) -> bool: 81 """Returns True if source represents an actual ligature glyph. 82 83 See `lib.glyphs.isLigature`. 84 85 Examples: 86 KGlyph("fi").isLigature => True 87 KGlyph("f_i").isLigature => True 88 KGlyph("tt").isLigature => False 89 """ 90 return glyphs.isLigature(self.source) 91 92 def get(self, key: str, defaultValue=None): 93 """ 94 Retrieve an attribute by key, emulating `dict.get()`. 95 96 Args: 97 key: The attribute name to retrieve. 98 defaultValue: Value to return if the attribute is not found. 99 100 Returns: 101 The attribute value or defaultValue if not found. 102 """ 103 return getattr(self, key, defaultValue) 104 105 def getSupported(self, fontPath: str, warn: bool = True) -> str | None: 106 """ 107 Find the supported glyph name in the given font. 108 109 Args: 110 fontPath: The font path to check for glyph support. 111 112 Returns: 113 The name of the supported glyph in the font, or None if not found. 114 """ 115 glyphsInFont = glyphs.listAvailableGlyphs(fontPath) 116 117 possibleMatches = set( 118 helpers.removeNone( 119 [ 120 *helpers.coerceList(self.name), 121 self.char, 122 self.unicode, 123 glyphs.toSnakeCase(self.source), 124 glyphs.toPartBase(self.source), 125 ] 126 ) 127 ) 128 # ! Edge case: For certain ligatures like "t_t", some fonts may use a ".liga" suffix for the supported glyph name. 129 if self.canLigate: 130 possibleMatches.update( 131 [ 132 f"{variant}.liga" 133 for variant in [self.name, glyphs.toSnakeCase(self.source)] 134 ] 135 ) 136 137 for possibleMatch in possibleMatches: 138 if possibleMatch in glyphsInFont: 139 return possibleMatch 140 141 if warn: 142 logger.warning( 143 "{} doesn’t support glyph {}", 144 fonts.getFontName(fontPath), 145 f"{colorama.Back.LIGHTYELLOW_EX}{self.source}{colorama.Style.RESET_ALL}", 146 ) 147 148 def __str__(self) -> str: 149 """Returns a human-friendly string representation of the KGlyph, including name, character, unicode, and category.""" 150 output = f"{colorama.Back.BLACK}KGlyph{colorama.Style.RESET_ALL}" 151 152 if self.name: 153 # Can be multiple names 154 isMultipleNames = isinstance(self.name, list) 155 names = helpers.coerceList(self.name) 156 157 output += " Name" + ("s" if isMultipleNames else " ") 158 for ni, name in enumerate(names): 159 isNotFirst = ni != 0 160 if isNotFirst: 161 output += "\n" + " " * 12 162 output += f" {colorama.Back.LIGHTYELLOW_EX}{name.ljust(30)}{colorama.Style.RESET_ALL}" 163 164 if self.char: 165 output += f" Char {colorama.Back.BLUE}{self.char}{colorama.Style.RESET_ALL}" 166 # Justify text 167 charAllotedSpaces = 6 168 if self.name == "zerowidthspace": 169 charAllotedSpaces += 1 170 output += " " * (charAllotedSpaces - len(self.char)) 171 172 unicodeToPrint = self.unicode or "" 173 output += ( 174 f" Unicode {colorama.Back.CYAN}{unicodeToPrint}{colorama.Style.RESET_ALL}" 175 ) 176 output += " " * (9 - len(unicodeToPrint)) 177 178 output += f" Category {colorama.Back.LIGHTRED_EX}{self.category}{colorama.Style.RESET_ALL}" 179 180 return output
KGlyph(source: str)
12 def __init__(self, source: str) -> None: 13 """Initialize a KGlyph instance.""" 14 self.source: str = source 15 """The glyph source identifier. Can be character, name, or unicode."""
Initialize a KGlyph instance.
name: str
char: str
charBase: str
39 @cached_property 40 def charBase(self) -> str: 41 """ 42 Returns: 43 The base character of the glyph, see `lib.glyphs.toCharBase`. 44 45 Example: 46 Á.ss01 => Á 47 S.ss01.cv01 => S 48 """ 49 return glyphs.toCharBase(self.source)
Returns:
The base character of the glyph, see
lib.glyphs.toCharBase.
Example:
Á.ss01 => Á S.ss01.cv01 => S
unicode: str
category: str
62 @cached_property 63 def category(self) -> str: 64 """Returns the glyph category, see `lib.glyphs.getCategory`.""" 65 return glyphs.getCategory(self.source)
Returns the glyph category, see lib.glyphs.getCategory.
canLigate: bool
67 @cached_property 68 def canLigate(self) -> bool: 69 """Returns True if source is a multi-char sequence that can form a ligature. 70 71 See `lib.glyphs.canLigate`. 72 73 Examples: 74 KGlyph("fi").canLigate => True 75 KGlyph("f_i").canLigate => False 76 """ 77 return glyphs.canLigate(self.source)
Returns True if source is a multi-char sequence that can form a ligature.
See lib.glyphs.canLigate.
Examples:
KGlyph("fi").canLigate => True KGlyph("f_i").canLigate => False
isLigature: bool
79 @cached_property 80 def isLigature(self) -> bool: 81 """Returns True if source represents an actual ligature glyph. 82 83 See `lib.glyphs.isLigature`. 84 85 Examples: 86 KGlyph("fi").isLigature => True 87 KGlyph("f_i").isLigature => True 88 KGlyph("tt").isLigature => False 89 """ 90 return glyphs.isLigature(self.source)
Returns True if source represents an actual ligature glyph.
Examples:
KGlyph("fi").isLigature => True KGlyph("f_i").isLigature => True KGlyph("tt").isLigature => False
def
get(self, key: str, defaultValue=None):
92 def get(self, key: str, defaultValue=None): 93 """ 94 Retrieve an attribute by key, emulating `dict.get()`. 95 96 Args: 97 key: The attribute name to retrieve. 98 defaultValue: Value to return if the attribute is not found. 99 100 Returns: 101 The attribute value or defaultValue if not found. 102 """ 103 return getattr(self, key, defaultValue)
Retrieve an attribute by key, emulating dict.get().
Arguments:
- key: The attribute name to retrieve.
- defaultValue: Value to return if the attribute is not found.
Returns:
The attribute value or defaultValue if not found.
def
getSupported(self, fontPath: str, warn: bool = True) -> str | None:
105 def getSupported(self, fontPath: str, warn: bool = True) -> str | None: 106 """ 107 Find the supported glyph name in the given font. 108 109 Args: 110 fontPath: The font path to check for glyph support. 111 112 Returns: 113 The name of the supported glyph in the font, or None if not found. 114 """ 115 glyphsInFont = glyphs.listAvailableGlyphs(fontPath) 116 117 possibleMatches = set( 118 helpers.removeNone( 119 [ 120 *helpers.coerceList(self.name), 121 self.char, 122 self.unicode, 123 glyphs.toSnakeCase(self.source), 124 glyphs.toPartBase(self.source), 125 ] 126 ) 127 ) 128 # ! Edge case: For certain ligatures like "t_t", some fonts may use a ".liga" suffix for the supported glyph name. 129 if self.canLigate: 130 possibleMatches.update( 131 [ 132 f"{variant}.liga" 133 for variant in [self.name, glyphs.toSnakeCase(self.source)] 134 ] 135 ) 136 137 for possibleMatch in possibleMatches: 138 if possibleMatch in glyphsInFont: 139 return possibleMatch 140 141 if warn: 142 logger.warning( 143 "{} doesn’t support glyph {}", 144 fonts.getFontName(fontPath), 145 f"{colorama.Back.LIGHTYELLOW_EX}{self.source}{colorama.Style.RESET_ALL}", 146 )
Find the supported glyph name in the given font.
Arguments:
- fontPath: The font path to check for glyph support.
Returns:
The name of the supported glyph in the font, or None if not found.