from typing import TypedDict from typing import Dict from dataclasses import dataclass from pathlib import Path # convenience dictionary for translating names to glyph ids # note: overwritten/extended by the content of "glypNamesToUnicode.txt" # when addon is registered in __init__.py name_to_glyph_d = { "zero": "0", "one": "1", "two": "2", "three": "3", "four": "4", "five": "5", "six": "6", "seven": "7", "eight": "8", "nine": "9", "ampersand": "&", "backslash": "\\", "colon": ":", "comma": ",", "equal": "=", "exclam": "!", "hyphen": "-", "minus": "−", "parenleft": "(", "parenright": "(", "period": ".", "plus": "+", "question": "?", "quotedblleft": "“", "quotedblright": "”", "semicolon": ";", "slash": "/", "space": " ", } known_misspellings = { # simple misspelling "excent" : "accent", "overdot" : "dotaccent", "diaresis": "dieresis", "diaeresis": "dieresis", # character does not exist.. maybe something else "Odoubleacute": "Ohungarumlaut", "Udoubleacute": "Uhungarumlaut", "Wcaron": "Wcircumflex", "Neng": "Nlongrightleg", "Lgrave": "Lacute", # currency stuff "doller": "dollar", "euro": "Euro", "yuan": "yen", # https://en.wikipedia.org/wiki/Yen_and_yuan_sign "pound": "sterling", # whoopsie "__": "_", } def fix_glyph_name_misspellings(name): for misspelling in known_misspellings: if misspelling in name: return name.replace(misspelling, known_misspellings[misspelling]) return name def name_to_glyph(name): if len(name) == 1: return name if name in name_to_glyph_d: return name_to_glyph_d[name] else: return None def generate_name_to_glyph_d(): d = {} with open(f"{Path(__file__).parent}/glyphNamesToUnicode.txt") as f: for line in f: if line[0] == '#': continue (name, hexstr) = line.split(' ') val = chr(int(hexstr, base=16)) d[name] = val return d class FontFace: """FontFace is a class holding glyphs :param glyphs: dictionary of glyphs, defaults to ``{}`` :type glyphs: dict, optional """ def __init__(self, glyphs = {}): self.glyphs = glyphs class Font: """Font holds the faces and various metadata for a font :param faces: dictionary of faces, defaults to ``Dict[str, FontFace]`` :type faces: Dict[str, FontFace] """ def __init__(self, faces = Dict[str, FontFace]): self.faces = faces # TODO: better class structure? # TODO: get fonts and faces directly def add_glyph(font_name, face_name, glyph_id, glyph_object): """ add_glyph adds a glyph to a FontFace it creates the :class:`Font` and :class:`FontFace` if it does not exist yet :param font_name: The Font you want to add the glyph to :type font_name: str :param face_name: The FontFace you want to add the glyph to :type face_name: str :param glyph_id: The glyph_id you want this glyph to be stored under :type glyph_id: str :param glyph_object: The object containing the glyph :type glyph_object: `Object` """ if not fonts.keys().__contains__(font_name): fonts[font_name] = Font({}) # print("is it has been added", fonts.keys()) if fonts[font_name].faces.get(face_name) == None: fonts[font_name].faces[face_name] = FontFace({}) # print("is it has been added faces", fonts[font_name].faces[face_name]) if fonts[font_name].faces[face_name].glyphs.get(glyph_id) == None: fonts[font_name].faces[face_name].glyphs[glyph_id] = [] # print("is it has been added glyph", fonts[font_name].faces[face_name].glyphs[glyph_id]) fonts[font_name].faces[face_name].glyphs.get(glyph_id).append(glyph_object) def get_glyph(font_name, face_name, glyph_id, alternate=0): """ add_glyph adds a glyph to a FontFace it creates the :class:`Font` and :class:`FontFace` if it does not exist yet :param font_name: The :class:`Font` you want to get the glyph from :type font_name: str :param face_name: The :class:`FontFace` you want to get the glyph from :type face_name: str :param glyph_id: The ``glyph_id`` from the glyph you want :type glyph_id: str ... :return: returns the glyph object, or ``None`` if it does not exist :rtype: `Object` """ # print(fonts) if not fonts.keys().__contains__(font_name): print(f"ABC3D::get_glyph: font name({font_name}) not found") print(fonts.keys()) return None face = fonts[font_name].faces.get(face_name) if face == None: print(f"ABC3D::get_glyph: font({font_name}) face({face_name}) not found") print(fonts[font_name].faces.keys()) return None glyphs_for_id = face.glyphs.get(glyph_id) if glyphs_for_id == None or len(glyphs_for_id) <= alternate: print(f"ABC3D::get_glyph: font({font_name}) face({face_name}) glyph({glyph_id})[{alternate}] not found") return None return fonts[font_name].faces[face_name].glyphs.get(glyph_id)[alternate] def get_loaded_fonts(): return fonts.keys() # holds all fonts fonts = {}