fonteditor/cli_ui.py

162 lines
4.6 KiB
Python
Raw Normal View History

2024-02-29 22:12:14 +01:00
import os
from tkinter import filedialog
import json
import base64
import numpy as np
def get_choice(text, choices):
line = "=" * len(text)
print(line)
print(text)
print(line)
choices_len = len(choices)
for i, choice in enumerate(choices):
print(f"{i+1}. {choice}")
while True:
try:
choice = int(input(f"> "))
except ValueError:
print("\nInvalid input! Input must be a number.")
continue
if choice < 1 or choice > choices_len:
print(f"\nInvalid input! Choose number from the list.")
continue
return choice - 1
def get_int_input(text, min_val=None, max_val=None):
while True:
try:
value = int(input(text))
except ValueError:
print("\nInvalid input! Input must be a number.")
continue
if (min_val is not None and value < min_val) or (max_val is not None and value > max_val):
print(f"\nInvalid input! Input must be between {min_val} and {max_val}.")
continue
return value
def key_tips():
print("\n======== CONTROLS ========")
print("Scroll - Select character")
print("Mouse click/drag - Draw")
print("Delete - Remove character")
print("G - Toggle grid")
print("E - Export font")
print("P - Reprint this controls info")
print("\nBlank characters are automatically removed.")
#print("Type any character into the console and press enter at any time to jump to it.")
print("============================\n")
def cli_main():
while True:
choices = ["Create new font", "Open font project"]
# if last_path_cache.txt exists, read it
try:
with open("last_path_cache.txt", "r") as file:
last_path = file.read()
2024-02-29 22:22:36 +01:00
choices.append(f"Open recent project ({os.path.basename(last_path)})")
2024-02-29 22:12:14 +01:00
except FileNotFoundError:
last_path = None
choice = get_choice(
2024-02-29 22:37:41 +01:00
"What do you want to do?" + (" No recently opened project found." if last_path is None else ""),
2024-02-29 22:12:14 +01:00
choices
)
#choice = 2
# create new font project
if choice == 0:
print("\n" + "=" * 30)
project_data = {
"char_width": get_int_input("Enter character width: ", min_val=2),
"char_height": get_int_input("Enter character height: ", min_val=2),
"chars": {}
}
# show file save dialog
file_path = filedialog.asksaveasfilename(
title="Save font project",
filetypes=[("Font project (json)", "*.fontproj")],
defaultextension=".fontproj"
)
if file_path == "":
print("\nCanceled.\n")
continue
# save project data to file
with open(file_path, "w") as f:
json.dump(project_data, f, indent=4)
# save last path to cache
with open("last_path_cache.txt", "w") as f:
f.write(file_path)
# open existing font project
elif choice == 1:
pass
2024-02-29 22:12:14 +01:00
# open last project
elif choice == 2:
file_path = last_path
try:
with open(file_path, "r") as f:
project_data = json.load(f)
except FileNotFoundError:
print("\nCouldn't open last project. File not found.\n")
continue
# process project data if opened existing project
if choice != 0:
# reverse the packed characters
unpacked_chars = {}
for key, value in project_data["chars"].items():
# decode from base64
decoded_data = base64.b64decode(value.encode("utf-8"))
# unpackbits
unpacked_data = np.unpackbits(np.frombuffer(decoded_data, dtype=np.uint8))
# remove padding
unpacked_data = unpacked_data[:project_data["char_width"] * project_data["char_height"]]
# reshape into original shape
unpacked_data = unpacked_data.reshape(project_data["char_width"], project_data["char_height"])
# store unpacked character
unpacked_chars[key] = unpacked_data.astype(bool)
project_data["chars"] = unpacked_chars
print("\n" + "=" * 30)
print(f"Font resolution: {project_data['char_width']}x{project_data['char_height']}")
key_tips()
return project_data, file_path