2020-06-03 18:40:05 -04:00
|
|
|
# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
|
|
|
#
|
|
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
|
2019-01-24 20:25:08 -05:00
|
|
|
import argparse
|
|
|
|
|
|
|
|
import os
|
2019-01-25 19:59:18 -05:00
|
|
|
import struct
|
2019-01-24 20:25:08 -05:00
|
|
|
import sys
|
|
|
|
|
2021-02-05 19:05:37 -05:00
|
|
|
sys.path.insert(0, "bitmap_font")
|
|
|
|
sys.path.insert(0, "../../tools/bitmap_font")
|
2019-01-24 20:25:08 -05:00
|
|
|
|
|
|
|
from adafruit_bitmap_font import bitmap_font
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser(description='Generate USB descriptors.')
|
|
|
|
parser.add_argument('--font', type=str,
|
2019-01-29 20:10:17 -05:00
|
|
|
help='Font path', required=True)
|
|
|
|
parser.add_argument('--extra_characters', type=str,
|
|
|
|
help='Unicode string of extra characters')
|
|
|
|
parser.add_argument('--sample_file', type=argparse.FileType('r'),
|
|
|
|
help='Text file that includes strings to support.')
|
2019-01-24 20:25:08 -05:00
|
|
|
parser.add_argument('--output_c_file', type=argparse.FileType('w'), required=True)
|
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
class BitmapStub:
|
|
|
|
def __init__(self, width, height, color_depth):
|
|
|
|
self.width = width
|
|
|
|
self.rows = [b''] * height
|
|
|
|
|
|
|
|
def _load_row(self, y, row):
|
|
|
|
self.rows[y] = bytes(row)
|
|
|
|
|
|
|
|
f = bitmap_font.load_font(args.font, BitmapStub)
|
|
|
|
|
2019-01-29 20:10:17 -05:00
|
|
|
# Load extra characters from the sample file.
|
|
|
|
sample_characters = set()
|
|
|
|
if args.sample_file:
|
|
|
|
for line in args.sample_file:
|
|
|
|
# Skip comments because we add additional characters in our huffman comments.
|
|
|
|
if line.startswith("//"):
|
|
|
|
continue
|
|
|
|
for c in line.strip():
|
|
|
|
sample_characters.add(c)
|
|
|
|
|
|
|
|
# Merge visible ascii, sample characters and extra characters.
|
2019-01-24 20:25:08 -05:00
|
|
|
visible_ascii = bytes(range(0x20, 0x7f)).decode("utf-8")
|
2019-01-29 20:10:17 -05:00
|
|
|
all_characters = visible_ascii
|
|
|
|
for c in sample_characters:
|
|
|
|
if c not in all_characters:
|
|
|
|
all_characters += c
|
|
|
|
if args.extra_characters:
|
|
|
|
all_characters.extend(args.extra_characters)
|
2019-12-19 17:26:01 -05:00
|
|
|
all_characters = "".join(sorted(set(all_characters)))
|
2019-01-25 19:59:18 -05:00
|
|
|
filtered_characters = all_characters
|
2019-01-29 20:10:17 -05:00
|
|
|
|
|
|
|
# Try to pre-load all of the glyphs. Misses will still be slow later.
|
2019-12-19 17:26:01 -05:00
|
|
|
f.load_glyphs(set(ord(c) for c in all_characters))
|
2019-01-29 20:10:17 -05:00
|
|
|
|
2020-08-18 20:17:59 -04:00
|
|
|
missing = 0
|
2019-01-29 20:10:17 -05:00
|
|
|
# Get each glyph.
|
2019-12-19 17:26:01 -05:00
|
|
|
for c in set(all_characters):
|
|
|
|
if ord(c) not in f._glyphs:
|
2020-08-18 20:17:59 -04:00
|
|
|
missing += 1
|
2019-01-25 19:59:18 -05:00
|
|
|
filtered_characters = filtered_characters.replace(c, "")
|
|
|
|
continue
|
2019-12-19 17:26:01 -05:00
|
|
|
g = f.get_glyph(ord(c))
|
2019-01-24 20:25:08 -05:00
|
|
|
if g["shift"][1] != 0:
|
|
|
|
raise RuntimeError("y shift")
|
|
|
|
|
2020-08-18 20:17:59 -04:00
|
|
|
if missing > 0:
|
|
|
|
print("Font missing", missing, "characters", file=sys.stderr)
|
|
|
|
|
2019-06-29 19:10:47 -04:00
|
|
|
x, y, dx, dy = f.get_bounding_box()
|
|
|
|
tile_x, tile_y = x - dx, y - dy
|
2019-01-25 19:59:18 -05:00
|
|
|
total_bits = tile_x * len(all_characters)
|
|
|
|
total_bits += 32 - total_bits % 32
|
|
|
|
bytes_per_row = total_bits // 8
|
|
|
|
b = bytearray(bytes_per_row * tile_y)
|
2019-01-24 20:25:08 -05:00
|
|
|
|
2019-01-25 19:59:18 -05:00
|
|
|
for x, c in enumerate(filtered_characters):
|
2019-01-24 20:25:08 -05:00
|
|
|
g = f.get_glyph(ord(c))
|
2019-01-25 19:59:18 -05:00
|
|
|
start_bit = x * tile_x + g["bounds"][2]
|
|
|
|
start_y = (tile_y - 2) - (g["bounds"][1] + g["bounds"][3])
|
|
|
|
for y, row in enumerate(g["bitmap"].rows):
|
2019-01-24 20:25:08 -05:00
|
|
|
for i in range(g["bounds"][0]):
|
|
|
|
byte = i // 8
|
|
|
|
bit = i % 8
|
2019-01-25 19:59:18 -05:00
|
|
|
if row[byte] & (1 << (7-bit)) != 0:
|
|
|
|
overall_bit = start_bit + (start_y + y) * bytes_per_row * 8 + i
|
|
|
|
b[overall_bit // 8] |= 1 << (7 - (overall_bit % 8))
|
2019-01-29 20:10:17 -05:00
|
|
|
|
|
|
|
|
|
|
|
extra_characters = ""
|
|
|
|
for c in filtered_characters:
|
|
|
|
if c not in visible_ascii:
|
|
|
|
extra_characters += c
|
2019-01-25 19:59:18 -05:00
|
|
|
|
|
|
|
c_file = args.output_c_file
|
|
|
|
|
|
|
|
c_file.write("""\
|
|
|
|
|
|
|
|
#include "shared-bindings/displayio/Palette.h"
|
|
|
|
#include "supervisor/shared/display.h"
|
|
|
|
|
|
|
|
""")
|
|
|
|
|
|
|
|
c_file.write("""\
|
2019-07-05 22:01:54 -04:00
|
|
|
_displayio_color_t terminal_colors[2] = {
|
|
|
|
{
|
|
|
|
.rgb888 = 0x000000,
|
|
|
|
.rgb565 = 0x0000,
|
2019-08-02 19:17:38 -04:00
|
|
|
.luma = 0x00,
|
|
|
|
.chroma = 0
|
2019-07-05 22:01:54 -04:00
|
|
|
},
|
|
|
|
{
|
|
|
|
.rgb888 = 0xffffff,
|
|
|
|
.rgb565 = 0xffff,
|
2019-08-02 19:17:38 -04:00
|
|
|
.luma = 0xff,
|
|
|
|
.chroma = 0
|
2019-07-05 22:01:54 -04:00
|
|
|
},
|
|
|
|
};
|
2019-01-25 19:59:18 -05:00
|
|
|
|
|
|
|
displayio_palette_t supervisor_terminal_color = {
|
|
|
|
.base = {.type = &displayio_palette_type },
|
|
|
|
.colors = terminal_colors,
|
|
|
|
.color_count = 2,
|
|
|
|
.needs_refresh = false
|
|
|
|
};
|
|
|
|
""")
|
|
|
|
|
|
|
|
c_file.write("""\
|
|
|
|
displayio_tilegrid_t supervisor_terminal_text_grid = {{
|
|
|
|
.base = {{ .type = &displayio_tilegrid_type }},
|
2019-02-06 15:13:17 -05:00
|
|
|
.bitmap = (displayio_bitmap_t*) &supervisor_terminal_font_bitmap,
|
2019-01-25 19:59:18 -05:00
|
|
|
.pixel_shader = &supervisor_terminal_color,
|
2019-06-06 18:11:02 -04:00
|
|
|
.x = 16,
|
|
|
|
.y = 0,
|
|
|
|
.pixel_width = {1},
|
|
|
|
.pixel_height = {2},
|
2019-01-25 19:59:18 -05:00
|
|
|
.bitmap_width_in_tiles = {0},
|
2019-07-18 19:47:28 -04:00
|
|
|
.tiles_in_bitmap = {0},
|
2019-01-25 19:59:18 -05:00
|
|
|
.width_in_tiles = 1,
|
|
|
|
.height_in_tiles = 1,
|
|
|
|
.tile_width = {1},
|
|
|
|
.tile_height = {2},
|
|
|
|
.tiles = NULL,
|
2019-06-06 18:11:02 -04:00
|
|
|
.partial_change = false,
|
|
|
|
.full_change = false,
|
2019-08-27 19:03:05 -04:00
|
|
|
.hidden = false,
|
|
|
|
.hidden_by_parent = false,
|
2019-06-06 18:11:02 -04:00
|
|
|
.moved = false,
|
|
|
|
.inline_tiles = false,
|
|
|
|
.in_group = true
|
2019-01-25 19:59:18 -05:00
|
|
|
}};
|
|
|
|
""".format(len(all_characters), tile_x, tile_y))
|
|
|
|
|
|
|
|
c_file.write("""\
|
|
|
|
const uint32_t font_bitmap_data[{}] = {{
|
|
|
|
""".format(bytes_per_row * tile_y // 4))
|
|
|
|
|
|
|
|
for i, word in enumerate(struct.iter_unpack(">I", b)):
|
|
|
|
c_file.write("0x{:08x}, ".format(word[0]))
|
|
|
|
if (i + 1) % (bytes_per_row // 4) == 0:
|
|
|
|
c_file.write("\n")
|
|
|
|
|
|
|
|
c_file.write("""\
|
|
|
|
};
|
|
|
|
""")
|
|
|
|
|
|
|
|
c_file.write("""\
|
2019-07-18 19:47:28 -04:00
|
|
|
displayio_bitmap_t supervisor_terminal_font_bitmap = {{
|
2019-01-25 19:59:18 -05:00
|
|
|
.base = {{.type = &displayio_bitmap_type }},
|
|
|
|
.width = {},
|
|
|
|
.height = {},
|
2019-04-04 15:50:35 -04:00
|
|
|
.data = (size_t*) font_bitmap_data,
|
2019-01-25 19:59:18 -05:00
|
|
|
.stride = {},
|
|
|
|
.bits_per_value = 1,
|
|
|
|
.x_shift = 5,
|
|
|
|
.x_mask = 0x1f,
|
2019-02-06 15:13:17 -05:00
|
|
|
.bitmask = 0x1,
|
|
|
|
.read_only = true
|
2019-01-25 19:59:18 -05:00
|
|
|
}};
|
|
|
|
""".format(len(all_characters) * tile_x, tile_y, bytes_per_row / 4))
|
|
|
|
|
2019-02-06 15:13:17 -05:00
|
|
|
|
2019-01-25 19:59:18 -05:00
|
|
|
c_file.write("""\
|
2019-03-19 19:22:09 -04:00
|
|
|
const fontio_builtinfont_t supervisor_terminal_font = {{
|
|
|
|
.base = {{.type = &fontio_builtinfont_type }},
|
2019-02-06 15:13:17 -05:00
|
|
|
.bitmap = &supervisor_terminal_font_bitmap,
|
|
|
|
.width = {},
|
|
|
|
.height = {},
|
2019-01-25 19:59:18 -05:00
|
|
|
.unicode_characters = (const uint8_t*) "{}",
|
|
|
|
.unicode_characters_len = {}
|
|
|
|
}};
|
2019-02-06 15:13:17 -05:00
|
|
|
""".format(tile_x, tile_y, extra_characters, len(extra_characters.encode("utf-8"))))
|
|
|
|
|
|
|
|
c_file.write("""\
|
|
|
|
terminalio_terminal_obj_t supervisor_terminal = {
|
|
|
|
.base = { .type = &terminalio_terminal_type },
|
|
|
|
.font = &supervisor_terminal_font,
|
|
|
|
.cursor_x = 0,
|
|
|
|
.cursor_y = 0,
|
|
|
|
.tilegrid = &supervisor_terminal_text_grid
|
|
|
|
};
|
|
|
|
""")
|