Commit d34d2199 authored by russhughes's avatar russhughes

utf8 support for write and write_len

parent c6a3e747
......@@ -33,6 +33,7 @@
#include <stdio.h>
#include <string.h>
#include "py/obj.h"
#include "py/objstr.h"
#include "py/objmodule.h"
#include "py/runtime.h"
#include "py/builtin.h"
......@@ -558,35 +559,40 @@ STATIC mp_obj_t dict_lookup(mp_obj_t self_in, mp_obj_t index)
STATIC mp_obj_t st7789_ST7789_write_len(size_t n_args, const mp_obj_t *args)
{
mp_obj_module_t *font = MP_OBJ_TO_PTR(args[1]);
char single_char_s[2] = {0, 0};
const char * str;
if (mp_obj_is_int(args[2])) {
mp_int_t c = mp_obj_get_int(args[2]);
single_char_s[0] = c & 0xff;
str = single_char_s;
} else {
str = mp_obj_str_get_str(args[2]);
}
mp_obj_dict_t *dict = MP_OBJ_TO_PTR(font->globals);
const char * map = mp_obj_str_get_str(mp_obj_dict_get(dict, MP_OBJ_NEW_QSTR(MP_QSTR_MAP)));
mp_obj_dict_t *dict = MP_OBJ_TO_PTR(font->globals);
mp_obj_t widths_data_buff = mp_obj_dict_get(dict, MP_OBJ_NEW_QSTR(MP_QSTR_WIDTHS));
mp_buffer_info_t widths_bufinfo;
mp_get_buffer_raise(widths_data_buff, &widths_bufinfo, MP_BUFFER_READ);
const uint8_t *widths_data = widths_bufinfo.buf;
uint16_t print_width = 0;
uint8_t chr;
while ((chr = *str++)) {
char *char_pointer = strchr(map, chr);
if (char_pointer) {
uint16_t char_index = char_pointer - map;
print_width += widths_data[char_index];
mp_obj_t map_obj = mp_obj_dict_get(dict, MP_OBJ_NEW_QSTR(MP_QSTR_MAP));
GET_STR_DATA_LEN(map_obj, map_data, map_len);
GET_STR_DATA_LEN(args[2], str_data, str_len);
const byte *s = str_data, *top = str_data + str_len;
while (s < top) {
unichar ch;
ch = utf8_get_char(s);
s = utf8_next_char(s);
const byte *map_s = map_data, *map_top = map_data + map_len;
uint16_t char_index = 0;
while (map_s < map_top) {
unichar map_ch;
map_ch = utf8_get_char(map_s);
map_s = utf8_next_char(map_s);
if (ch == map_ch) {
print_width += widths_data[char_index];
break;
}
char_index++;
}
}
return mp_obj_new_int(print_width);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(st7789_ST7789_write_len_obj, 3, 3, st7789_ST7789_write_len);
......@@ -598,18 +604,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(st7789_ST7789_write_len_obj, 3, 3, st
STATIC mp_obj_t st7789_ST7789_write(size_t n_args, const mp_obj_t *args)
{
st7789_ST7789_obj_t *self = MP_OBJ_TO_PTR(args[0]);
mp_obj_module_t * font = MP_OBJ_TO_PTR(args[1]);
char single_char_s[2] = {0, 0};
const char *str;
if (mp_obj_is_int(args[2])) {
mp_int_t c = mp_obj_get_int(args[2]);
single_char_s[0] = c & 0xff;
str = single_char_s;
} else {
str = mp_obj_str_get_str(args[2]);
}
mp_obj_module_t *font = MP_OBJ_TO_PTR(args[1]);
mp_int_t x = mp_obj_get_int(args[3]);
mp_int_t y = mp_obj_get_int(args[4]);
......@@ -620,7 +615,6 @@ STATIC mp_obj_t st7789_ST7789_write(size_t n_args, const mp_obj_t *args)
bg_color = (n_args > 6) ? _swap_bytes(mp_obj_get_int(args[6])) : _swap_bytes(BLACK);
mp_obj_dict_t *dict = MP_OBJ_TO_PTR(font->globals);
const char * map = mp_obj_str_get_str(mp_obj_dict_get(dict, MP_OBJ_NEW_QSTR(MP_QSTR_MAP)));
const uint8_t bpp = mp_obj_get_int(mp_obj_dict_get(dict, MP_OBJ_NEW_QSTR(MP_QSTR_BPP)));
const uint8_t height = mp_obj_get_int(mp_obj_dict_get(dict, MP_OBJ_NEW_QSTR(MP_QSTR_HEIGHT)));
const uint8_t offset_width = mp_obj_get_int(mp_obj_dict_get(dict, MP_OBJ_NEW_QSTR(MP_QSTR_OFFSET_WIDTH)));
......@@ -647,52 +641,68 @@ STATIC mp_obj_t st7789_ST7789_write(size_t n_args, const mp_obj_t *args)
}
uint16_t print_width = 0;
uint8_t chr;
while ((chr = *str++)) {
char *char_pointer = strchr(map, chr);
if (char_pointer) {
uint16_t char_index = char_pointer - map;
uint8_t width = widths_data[char_index];
bs_bit = 0;
switch (offset_width) {
case 1:
bs_bit = offsets_data[char_index * offset_width];
break;
case 2:
bs_bit = (offsets_data[char_index * offset_width] << 8) +
(offsets_data[char_index * offset_width + 1]);
break;
case 3:
bs_bit = (offsets_data[char_index * offset_width] << 16) +
(offsets_data[char_index * offset_width + 1] << 8) +
(offsets_data[char_index * offset_width + 2]);
break;
}
uint32_t ofs = 0;
for (int yy = 0; yy < height; yy++) {
for (int xx = 0; xx < width; xx++) {
self->i2c_buffer[ofs++] = get_color(bpp) ? fg_color : bg_color;
mp_obj_t map_obj = mp_obj_dict_get(dict, MP_OBJ_NEW_QSTR(MP_QSTR_MAP));
GET_STR_DATA_LEN(map_obj, map_data, map_len);
GET_STR_DATA_LEN(args[2], str_data, str_len);
const byte *s = str_data, *top = str_data + str_len;
while (s < top) {
unichar ch;
ch = utf8_get_char(s);
s = utf8_next_char(s);
const byte *map_s = map_data, *map_top = map_data + map_len;
uint16_t char_index = 0;
while (map_s < map_top) {
unichar map_ch;
map_ch = utf8_get_char(map_s);
map_s = utf8_next_char(map_s);
if (ch == map_ch) {
uint8_t width = widths_data[char_index];
bs_bit = 0;
switch (offset_width) {
case 1:
bs_bit = offsets_data[char_index * offset_width];
break;
case 2:
bs_bit = (offsets_data[char_index * offset_width] << 8) +
(offsets_data[char_index * offset_width + 1]);
break;
case 3:
bs_bit = (offsets_data[char_index * offset_width] << 16) +
(offsets_data[char_index * offset_width + 1] << 8) +
(offsets_data[char_index * offset_width + 2]);
break;
}
}
uint32_t data_size = width * height * 2;
uint16_t x1 = x + width - 1;
if (x1 < self->width) {
set_window(self, x, y, x1, y + height - 1);
DC_HIGH();
CS_LOW();
write_spi(self->spi_obj, (uint8_t *) self->i2c_buffer, data_size);
CS_HIGH();
uint32_t ofs = 0;
for (int yy = 0; yy < height; yy++) {
for (int xx = 0; xx < width; xx++) {
self->i2c_buffer[ofs++] = get_color(bpp) ? fg_color : bg_color;
}
}
uint32_t data_size = width * height * 2;
uint16_t x1 = x + width - 1;
if (x1 < self->width) {
set_window(self, x, y, x1, y + height - 1);
DC_HIGH();
CS_LOW();
write_spi(self->spi_obj, (uint8_t *) self->i2c_buffer, data_size);
CS_HIGH();
}
print_width += width;
} else
break;
x += width;
x += width;
break;
}
char_index++;
}
}
......
......@@ -46,46 +46,44 @@ import bisect
import freetype
def to_int(str):
return int(str, base=16) if str.startswith("0x") else int(str)
def to_int(string):
return int(string, base=16) if string.startswith("0x") else int(string)
def get_chars(str):
return ''.join([chr(b) for a in [
(lambda sub: range(sub[0], sub[-1] + 1))
(list(map(to_int, ele.split('-'))))
for ele in str.split(',')]
for b in a])
def get_chars(string):
return ''.join(chr(b) for a in [
(lambda sub: range(sub[0], sub[-1] + 1))
(list(map(to_int, ele.split('-'))))
for ele in string.split(',')] for b in a)
def wrap_list(lst, items_per_line=8):
lines = []
for i in range(0, len(lst), items_per_line):
chunk = lst[i:i + items_per_line]
line = ", ".join("0x{:02x}".format(x) for x in chunk)
lines.append(line)
return "[\n " + ",\n ".join(lines) + "]"
def wrap_str(str, items_per_line=32):
lines = [
str[i : i + items_per_line]
for i in range(0, len(str), items_per_line)
]
return "(\n '" + "'\n '".join(lines) + "'\n)"
def wrap_bytes(lst, items_per_line=16):
lines = []
for i in range(0, len(lst), items_per_line):
chunk = lst[i:i + items_per_line]
line = "".join("\\x{:02x}".format(x) for x in chunk)
lines.append(line)
lines = [
"".join("\\x{:02x}".format(x) for x in lst[i : i + items_per_line])
for i in range(0, len(lst), items_per_line)
]
return " b'" + "'\\\n b'".join(lines) + "'"
def wrap_longs(lst, items_per_line=16):
lines = []
for i in range(0, len(lst), items_per_line):
chunk = lst[i:i + items_per_line]
line = "".join("\\x{:02x}".format(x) for x in chunk)
lines.append(line)
lines = [
"".join("\\x{:02x}".format(x) for x in lst[i : i + items_per_line])
for i in range(0, len(lst), items_per_line)
]
return " b'" + "'\\\n b'".join(lines) + "'"
class Bitmap(object):
class Bitmap():
"""
A 2D bitmap image represented as a list of byte values. Each byte indicates
the state of a single pixel in the bitmap. A value of 0 indicates that the
......@@ -132,7 +130,7 @@ class Bitmap(object):
dstpixel += row_offset
class Glyph(object):
class Glyph():
def __init__(self, pixels, width, height, top, left, advance_width):
self.bitmap = Bitmap(width, height, pixels)
......@@ -216,7 +214,7 @@ class Glyph(object):
return data
class Font(object):
class Font():
def __init__(self, filename, width, height):
self.face = freetype.Face(filename)
self.face.set_pixel_sizes(width, height)
......@@ -310,7 +308,7 @@ class Font(object):
bit_string = ''.join(bits)
# escape '\' and '"' characters for char_map
char_map = text.replace('\\', '\\\\').replace('"', '\\"')
char_map = wrap_str(text.replace('\\', '\\\\').replace('"', '\\"'))
cmd_line = " ".join(map(shlex.quote, sys.argv))
max_width = max(widths)
......@@ -320,7 +318,8 @@ class Font(object):
print(f'# Converted from {font_file} using:')
print(f'# {cmd_line}')
print()
print(f'MAP = "{char_map}"')
print(f'MAP = {char_map}')
print('BPP = 1')
print(f'HEIGHT = {height}')
print(f'MAX_WIDTH = {max_width}')
......@@ -340,10 +339,7 @@ class Font(object):
print()
print('_BITMAPS =\\')
byte_values = []
for i in range(0, len(bit_string), 8):
byte_values.append(int(bit_string[i:i+8], 2))
byte_values = [int(bit_string[i:i+8], 2) for i in range(0, len(bit_string), 8)]
print(wrap_bytes(byte_values))
print("\nWIDTHS = memoryview(_WIDTHS)")
print("OFFSETS = memoryview(_OFFSETS)")
......@@ -392,8 +388,8 @@ def main():
font_file = args.font_file
height = args.font_height
width = args.font_height if args.font_width is None else args.font_width
characters = (
get_chars(args.characters) if args.string is None else args.string)
characters = ''.join(set(
get_chars(args.characters) if args.string is None else args.string))
fnt = Font(font_file, width, height)
fnt.write_python(characters, font_file)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment