|
7 | 7 | Likely could refactor these into the respective modules, but for now they are here.
|
8 | 8 | """
|
9 | 9 |
|
| 10 | +import os |
| 11 | +import shutil |
| 12 | +import sys |
| 13 | +from typing import Union |
| 14 | + |
10 | 15 | from .constants import MAX_WORMHOLES
|
11 | 16 |
|
12 | 17 |
|
@@ -62,3 +67,84 @@ def wormhole_exists(wormholes: list[int], a: int, b: int) -> bool:
|
62 | 67 | return True
|
63 | 68 |
|
64 | 69 | return False
|
| 70 | + |
| 71 | + |
| 72 | +class FontManager: |
| 73 | + |
| 74 | + linux_font_path = "~/.fonts/" |
| 75 | + |
| 76 | + @classmethod |
| 77 | + def init_font_manager(cls): |
| 78 | + # Linux |
| 79 | + if sys.platform.startswith("linux"): |
| 80 | + try: |
| 81 | + if not os.path.isdir(os.path.expanduser(cls.linux_font_path)): |
| 82 | + os.mkdir(os.path.expanduser(cls.linux_font_path)) |
| 83 | + return True |
| 84 | + except Exception as err: |
| 85 | + sys.stderr.write("FontManager error: " + str(err) + "\n") |
| 86 | + return False |
| 87 | + |
| 88 | + # other platforms |
| 89 | + else: |
| 90 | + return True |
| 91 | + |
| 92 | + @classmethod |
| 93 | + def windows_load_font(cls, font_path: Union[str, bytes], private: bool = True, enumerable: bool = False) -> bool: |
| 94 | + """Function taken from: https://stackoverflow.com/questions/11993290/truly-custom-font-in-tkinter/30631309#30631309""" |
| 95 | + |
| 96 | + from ctypes import byref, create_string_buffer, create_unicode_buffer, windll |
| 97 | + |
| 98 | + FR_PRIVATE = 0x10 |
| 99 | + FR_NOT_ENUM = 0x20 |
| 100 | + |
| 101 | + if isinstance(font_path, bytes): |
| 102 | + path_buffer = create_string_buffer(font_path) |
| 103 | + add_font_resource_ex = windll.gdi32.AddFontResourceExA |
| 104 | + elif isinstance(font_path, str): |
| 105 | + path_buffer = create_unicode_buffer(font_path) |
| 106 | + add_font_resource_ex = windll.gdi32.AddFontResourceExW |
| 107 | + else: |
| 108 | + raise TypeError("font_path must be of type bytes or str") |
| 109 | + |
| 110 | + flags = (FR_PRIVATE if private else 0) | (FR_NOT_ENUM if not enumerable else 0) |
| 111 | + num_fonts_added = add_font_resource_ex(byref(path_buffer), flags, 0) |
| 112 | + return bool(min(num_fonts_added, 1)) |
| 113 | + |
| 114 | + @classmethod |
| 115 | + def load_font(cls, font_path: str) -> bool: |
| 116 | + # Windows |
| 117 | + if sys.platform.startswith("win"): |
| 118 | + return cls.windows_load_font(font_path, private=True, enumerable=False) |
| 119 | + |
| 120 | + # Linux |
| 121 | + elif sys.platform.startswith("linux"): |
| 122 | + try: |
| 123 | + shutil.copy(font_path, os.path.expanduser(cls.linux_font_path)) |
| 124 | + return True |
| 125 | + except Exception as err: |
| 126 | + sys.stderr.write("FontManager error: " + str(err) + "\n") |
| 127 | + return False |
| 128 | + |
| 129 | + # macOS |
| 130 | + elif sys.platform.startswith("darwin"): |
| 131 | + customtkinter_directory = os.path.dirname( |
| 132 | + os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) |
| 133 | + ) |
| 134 | + font_path = os.path.join(customtkinter_directory, "assets", "fonts", "noto_sans", "regular.ttf") |
| 135 | + try: |
| 136 | + # Define the path to the Fonts folder in the user's home directory |
| 137 | + fonts_folder = os.path.join(os.path.expanduser("~"), "Library", "Fonts") |
| 138 | + # Check if the Fonts folder exists, if not, create it |
| 139 | + if not os.path.exists(fonts_folder): |
| 140 | + os.makedirs(fonts_folder) |
| 141 | + # Copy the font file to the Fonts folder |
| 142 | + shutil.copy(font_path, fonts_folder) |
| 143 | + return True |
| 144 | + except Exception as err: |
| 145 | + sys.stderr.write("FontManager error: " + str(err) + "\n") |
| 146 | + return False |
| 147 | + |
| 148 | + # others |
| 149 | + else: |
| 150 | + return |
0 commit comments