mirror of
https://github.com/EdgeTX/edgetx.git
synced 2025-07-13 19:40:16 +03:00
* Resolve a problem in font generation when y_offset is negative. * Change to use full dynamic detection of special chars, generalized for all languages including cjk. * Isolated colorlcd and bwlcd translation encoding method. * Fixed the cz char mapping. * Only cz requires subset lowercase handling.
153 lines
5.3 KiB
Python
Executable file
153 lines
5.3 KiB
Python
Executable file
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import argparse
|
|
import os
|
|
import sys
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
from charset import get_chars, special_chars, extra_chars, standard_chars
|
|
|
|
EXTRA_BITMAP_MAX_WIDTH = 297
|
|
|
|
class FontBitmap:
|
|
def __init__(self, language, font_size, font_name, foreground, background):
|
|
self.language = language
|
|
self.chars = get_chars(language)
|
|
self.font_size = font_size
|
|
self.foreground = foreground
|
|
self.background = background
|
|
self.font = self.load_font(font_name)
|
|
self.extra_bitmap = self.load_extra_bitmap()
|
|
self.extra_bitmap_added = False
|
|
self.extra_bitmap_width = EXTRA_BITMAP_MAX_WIDTH
|
|
if self.extra_bitmap is not None:
|
|
self.extra_bitmap_width = self.extra_bitmap.width
|
|
|
|
def load_extra_bitmap(self):
|
|
try:
|
|
tools_path = os.path.dirname(os.path.realpath(__file__))
|
|
filename = "extra_%dpx.png" % self.font_size
|
|
path = os.path.join(tools_path, "../radio/src/fonts", filename)
|
|
extra_image = Image.open(path)
|
|
return extra_image.convert('RGB')
|
|
except IOError:
|
|
return None
|
|
|
|
def load_font(self, font_name):
|
|
# print(font_name)
|
|
for ext in (".ttf", ".otf"):
|
|
tools_path = os.path.dirname(os.path.realpath(__file__))
|
|
path = os.path.join(tools_path, "../radio/src/fonts", font_name + ext)
|
|
if os.path.exists(path):
|
|
return ImageFont.truetype(path, self.font_size)
|
|
print("Font file %s not found" % font_name)
|
|
|
|
def get_text_dimensions(self, text_string):
|
|
# https://stackoverflow.com/a/46220683/9263761
|
|
_, descent = self.font.getmetrics()
|
|
text_width = self.font.getmask(text_string).getbbox()[2]
|
|
text_height = self.font.getmask(text_string).getbbox()[3] + descent
|
|
|
|
return (text_width, text_height)
|
|
|
|
def draw_char(self, draw, x, y, c):
|
|
|
|
# default width for space
|
|
width = 4
|
|
if c != ' ':
|
|
if "0123456789".find(c) >= 0 :
|
|
width = self.font.getmask("4").getbbox()[2]
|
|
_, (offset_x, offset_y) = self.font.font.getsize(c)
|
|
_, (offset_x2, offset_y2) = self.font.font.getsize("4")
|
|
offset_x = (offset_x + offset_x2) / 2
|
|
else :
|
|
width = self.font.getmask(c).getbbox()[2]
|
|
_, (offset_x, offset_y) = self.font.font.getsize(c)
|
|
|
|
draw.text((x - offset_x, y), c, fill=self.foreground, font=self.font)
|
|
|
|
return width
|
|
|
|
def generate(self, filename, generate_coords_file=True):
|
|
coords = []
|
|
|
|
(_,baseline), (offset_x, offset_y) = self.font.font.getsize(self.chars)
|
|
(text_width, text_height) = self.get_text_dimensions(self.chars)
|
|
y_shifts = 0
|
|
if offset_y < 0:
|
|
y_shifts = -offset_y
|
|
text_height += y_shifts
|
|
offset_y = 0
|
|
|
|
img_width = text_width + self.extra_bitmap_width
|
|
image = Image.new("RGB", (img_width, text_height), self.background)
|
|
draw = ImageDraw.Draw(image)
|
|
|
|
width = 0
|
|
for c in self.chars:
|
|
if c in extra_chars:
|
|
if not self.extra_bitmap_added:
|
|
# append same width for non-existing characters
|
|
for i in range(128 - 32 - len(standard_chars)):
|
|
coords.append(width)
|
|
|
|
if self.extra_bitmap:
|
|
|
|
# copy extra_bitmap at once
|
|
image.paste(self.extra_bitmap, (width, offset_y + y_shifts))
|
|
|
|
# append width for extra_bitmap symbols
|
|
for coord in [14, 14, 12, 12, 13, 13, 13, 13, 13] + [15] * 12:
|
|
coords.append(width)
|
|
width += coord
|
|
else:
|
|
for coord in range(21):
|
|
coords.append(width)
|
|
|
|
# once inserted, disable insert again
|
|
self.extra_bitmap_added = True
|
|
|
|
# skip
|
|
continue
|
|
|
|
# normal characters + CJK
|
|
w = self.draw_char(draw, width, y_shifts, c)
|
|
|
|
coords.append(width)
|
|
width += w
|
|
|
|
# append the last computed width
|
|
coords.append(width)
|
|
|
|
# trim image to correct size
|
|
image = image.crop((0, offset_y, width, baseline + offset_y))
|
|
|
|
# insert the size of the image
|
|
coords.insert(0, image.height)
|
|
|
|
# convert to 8-bit and save
|
|
image = image.convert("L")
|
|
image.save(filename + ".png")
|
|
|
|
if generate_coords_file:
|
|
with open(filename + ".specs", "w") as f:
|
|
f.write(",".join(str(tmp) for tmp in coords))
|
|
|
|
def main():
|
|
if sys.version_info < (3, 0, 0):
|
|
print("%s requires Python 3. Terminating." % __file__)
|
|
sys.exit(1)
|
|
|
|
parser = argparse.ArgumentParser(description="Builder for OpenTX font files")
|
|
parser.add_argument('--output', help="Output file name")
|
|
parser.add_argument('--subset', help="Subset")
|
|
parser.add_argument('--size', type=int, help="Font size")
|
|
parser.add_argument('--font', help="Font name")
|
|
args = parser.parse_args()
|
|
|
|
font = FontBitmap(args.subset, args.size, args.font, (0, 0, 0), (255, 255, 255))
|
|
font.generate(args.output)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|