rdz_ttgo_sonde_dl9rdz/screens_editor/gfx_font.py

96 lines
3.5 KiB
Python

import traceback
import json
from kivy.graphics import Rectangle, Color
# gfx coordinates are (0,0) top left
# canvas coordinates are (0,0) bottom left
class GFXFont:
def __init__(self, json_path):
with open(json_path, 'r') as f:
self.font_data = json.load(f)
# to match Display.cpp
# find largest yoffset
min_yoffset = 0
for glyph in self.font_data["glyphs"]:
if glyph["yOffset"] < min_yoffset:
min_yoffset = glyph["yOffset"]
max_height = 0
for glyph in self.font_data["glyphs"]:
h = glyph["yOffset"] - min_yoffset + glyph["height"]
if h > max_height:
max_height = h
print("min_yoffset: ", min_yoffset, "max_height:", max_height)
self.base_line = self.font_data["font"]["yAdvance"] * 2 / 3 # offset from top to baseline
self.yclear = max_height
def render_glyph(self, canvas, glyph, x, y, scale=1, fg=(1, 1, 1), area_height=0):
bitmap = self.font_data["bitmap"]
width = glyph["width"]
height = glyph["height"]
offset = glyph["bitmapOffset"]
y_offset = glyph["yOffset"]
print("render_glyph: ", glyph, width, height, offset )
with canvas:
# Draw each pixel of the glyph
for row in range(height):
for col in range(width):
byte_index = offset + (row * width + col) // 8
bit_index = (row * width + col) % 8
if bitmap[byte_index] & (1 << (7 - bit_index)):
Color(*fg) # Foreground color
Rectangle(
pos=(x + col * scale, area_height - y + (- self.base_line - y_offset - row - 1) * scale),
size=(scale, scale),
)
def render_text(self, canvas, text, x, y, scale=1, width=0, fg=(1, 1, 1), bg=None, area_height=0):
try:
glyphs = self.font_data["glyphs"]
font_metadata = self.font_data["font"]
# Compute text width
text_width = 0
print("Text is '"+text+"'")
for char in text:
char_code = ord(char)
if font_metadata["firstChar"] <= char_code <= font_metadata["lastChar"]:
glyph_index = char_code - font_metadata["firstChar"]
glyph = glyphs[glyph_index]
text_width += glyph["xAdvance"]
if width < 0:
x += (-width - text_width) * scale
if width == 0:
width = text_width
print("Calculated width is ",text_width," new x is ",x,"y is",y)
# Draw the background if specified
if bg:
with canvas:
Color(*bg)
Rectangle(
pos=(x, area_height - y - self.yclear * scale),
size=(width * scale, self.yclear * scale),
)
# Render each character
x_cursor = x
for char in text:
char_code = ord(char)
if font_metadata["firstChar"] <= char_code <= font_metadata["lastChar"]:
glyph_index = char_code - font_metadata["firstChar"]
glyph = glyphs[glyph_index]
# Render the glyph
self.render_glyph(canvas, glyph, x_cursor, y, scale=scale, fg=fg, area_height=area_height)
# Advance the cursor
x_cursor += glyph["xAdvance"] * scale
except Exception as e:
print("Failed to render text")
traceback.print_exc()