fonteditor/project.py

115 lines
3.7 KiB
Python

import base64
import json
import PIL.Image
def create_zeroed_array(length):
output=[]
for _ in range(length):
output.append(0)
return output
class Project:
def __init__(self):
self.chars={}
self.char_res=(0,0)
self.path=None
self.export_path=None
self.loaded=False
self.modified=False
def load(self,path):
with open(path, "r") as f:
project_data = json.load(f)
if not "char_width" in project_data or not "char_height" in project_data:
raise AttributeError("Character metrics information not found")
if not isinstance(project_data["char_width"],int) or not isinstance(project_data["char_height"],int):
raise AttributeError("Invalid character metrics type, expected int")
if not "chars" in project_data:
raise AttributeError("Character data not found")
if not isinstance(project_data["chars"],dict):
raise AttributeError("Invalid character data type, expected object")
self.chars=project_data["chars"]
self.char_res=(project_data["char_width"],project_data["char_height"])
self.path=path
self.loaded=True
def save(self,path):
# save project data to file
with open(path, "w") as f:
json.dump({
"char_width": self.char_res[0],
"char_height": self.char_res[1],
"chars": self.chars
}, f, indent=4)
self.path=path
self.loaded=True
def export(self,path):
chars = tuple(self.chars.items())
# there will be 256 characters per page
last_char_idx = len(chars) - 1
page_res = (self.char_res[0] * 16,self.char_res[1] * 16)
page = 0
page_char_x = 0
page_char_y = 0
for char_idx, char in enumerate(chars):
if page_char_x == 0 and page_char_y == 0:
page_arr = create_zeroed_array(page_res[0]*page_res[1])
char_map_string = ""
char_bitmap=self.decode_char(char[0])
# put char_bitmap onto page_img at correct position
for i in range(len(char_bitmap)):
x=i//self.char_res[1]+page_char_x*self.char_res[0]
y=i%self.char_res[1]+page_char_y*self.char_res[1]
page_arr[y*page_res[0]+x]=char_bitmap[i]
char_map_string += char[0]
page_char_x += 1
if page_char_x == 16:
page_char_x = 0
page_char_y += 1
if page_char_y == 16 or char_idx == last_char_idx:
## save page
for x in range(len(page_arr)):
page_arr[x]*=255
page_img = PIL.Image.frombytes("L",page_res,bytes(page_arr))
# save page
page_img.save(f"{path}/page_{page}.png")
# save char map
with open(f"{path}/page_{page}.txt", "w", encoding="utf-8") as f:
f.write(char_map_string)
page += 1
page_char_y = 0
self.export_path=path
def decode_char(self,char):
result=[0 for _ in range(self.char_res[0]*self.char_res[1])]
pixels=base64.b64decode(self.chars[char].encode("ascii"))
pixel_index=0
for pixel in pixels:
if pixel_index>=len(result):
break
for x in range(8):
if pixel_index>=len(result):
break
result[pixel_index]=(pixel>>(7-x))&1
pixel_index+=1
return result
def does_char_exist(self,c):
return chr(c) in self.chars