forked from Lephenixnoir/unicode-fonts
116 lines
2.6 KiB
Python
116 lines
2.6 KiB
Python
|
#! /usr/bin/python3
|
||
|
|
||
|
import PIL.Image
|
||
|
import sys
|
||
|
import os
|
||
|
import re
|
||
|
|
||
|
if len(sys.argv) <= 1:
|
||
|
print(f"usage: {sys.argv[0]} <block files...>")
|
||
|
sys.exit(1)
|
||
|
|
||
|
files = sorted(sys.argv[1:])
|
||
|
chars = PIL.Image.open("gen-chars.png")
|
||
|
|
||
|
WHITE = (255, 255, 255)
|
||
|
BLACK = (0, 0, 0)
|
||
|
|
||
|
def empty_separator():
|
||
|
img = PIL.Image.new("RGB", (112, 9), color=WHITE)
|
||
|
|
||
|
for j in range(3, 6):
|
||
|
for i in range(1, 111):
|
||
|
if not ((i + j) & 1):
|
||
|
img.putpixel((i, j), BLACK)
|
||
|
|
||
|
return img
|
||
|
|
||
|
def char_index(c):
|
||
|
o = ord(c)
|
||
|
if ord('0') <= o <= ord('9'):
|
||
|
return o - ord('0')
|
||
|
if ord('A') <= o <= ord('F'):
|
||
|
return o - ord('A') + 10
|
||
|
if c == 'U':
|
||
|
return 16
|
||
|
if c == '+':
|
||
|
return 17
|
||
|
raise Exception(f"Unsupported char '{c}'")
|
||
|
|
||
|
def char_image(c):
|
||
|
index = 4 * char_index(c)
|
||
|
return chars.crop((index, 0, index + 3, 5))
|
||
|
|
||
|
def separator(start, end):
|
||
|
img = PIL.Image.new("RGB", (112, 9), color=WHITE)
|
||
|
|
||
|
for j in range(3, 6):
|
||
|
for i in range(1, 26):
|
||
|
if not ((i + j) & 1):
|
||
|
img.putpixel((i, j), BLACK)
|
||
|
for i in range(86, 111):
|
||
|
if not ((i + j) & 1):
|
||
|
img.putpixel((i, j), BLACK)
|
||
|
|
||
|
x = 27
|
||
|
for c in "U+{:04X}".format(start):
|
||
|
img.paste(char_image(c), (x, 2))
|
||
|
x += 4
|
||
|
|
||
|
for i in range(54, 58):
|
||
|
img.putpixel((i, 4), BLACK)
|
||
|
|
||
|
x = 62
|
||
|
for c in "U+{:04X}".format(end):
|
||
|
img.paste(char_image(c), (x, 2))
|
||
|
x += 4
|
||
|
|
||
|
return img
|
||
|
|
||
|
class Block:
|
||
|
def __init__(self, path):
|
||
|
basename = os.path.basename(path)
|
||
|
match = re.search(r'U\+([0-9A-Za-z]{4})', basename)
|
||
|
|
||
|
self.block_start = None
|
||
|
self.block_end = None
|
||
|
|
||
|
self.img = PIL.Image.open(path)
|
||
|
|
||
|
if match is not None:
|
||
|
self.block_start = int(match[1], 16)
|
||
|
self.block_end = self.block_start + 16 * (self.img.height // 9) - 1
|
||
|
print('{} U+{:04X} - U+{:04X}'.format(basename, self.block_start,
|
||
|
self.block_end))
|
||
|
else:
|
||
|
print(f'{basename} not a block')
|
||
|
|
||
|
def header(self):
|
||
|
if self.block_start is not None:
|
||
|
return separator(self.block_start, self.block_end)
|
||
|
else:
|
||
|
return empty_separator()
|
||
|
|
||
|
def body(self):
|
||
|
return self.img
|
||
|
|
||
|
def height(self):
|
||
|
return self.img.height + 9
|
||
|
|
||
|
blocks = [ Block(file) for file in files ]
|
||
|
height = sum(b.height() for b in blocks)
|
||
|
|
||
|
result = PIL.Image.new("RGB", (112, height))
|
||
|
|
||
|
y = 0
|
||
|
for b in blocks:
|
||
|
header = b.header()
|
||
|
result.paste(header, (0, y))
|
||
|
y += header.height
|
||
|
|
||
|
body = b.body()
|
||
|
result.paste(body, (0, y))
|
||
|
y += body.height
|
||
|
|
||
|
result.save("uf5x7.png")
|