Пишем на «Флиппере Зеро» по-русски
★
Вкратце: в русским текстом работать можно, но сложно, код лежит на «Гитхабе».
Не мог не обратить внимание, что несмотря на приличное количество русскоязычных авторов программ для «Флиппера Зеро» и российское происхождение устройства, в софте под него нигде не обнаружилось ни одной буквы
Flipper Zero
Стало интересно — а есть ли вообще в устройстве поддержка русского языка? Сел вечерком за исходники прошивки и оказалось, что однозначного ответа на заданный вопрос нет. Частичная поддержка есть и её можно заставить работать, но она работает как будто по недосмотру — никто её не собирался делать, так случайно вышло.
Сейчас расскажу, что я имею ввиду и постараюсь покороче, никто сейчас не любит длинные тексты.
Внутри «Флиппера» довольно много всякого АПИ для вывода текста, от незатейливого, выводящего строку в заданные координаты, до довольно навороченного, умеющего переносить и выравнивать текст. К сожалению, с русскими буквами оно работать не умеет.
Под капотом у этого АПИ — очень известная в своей нише библиотека U∞g2, у которой по историческим, видимо, причинам есть два набора функций для работы со строками. Одни принимают только однобайтовую кодировку ASCII, другие работают в Юникоде.
АПИ «Флиппера», к сожалению, использует функции, которые с Юникодом работать не умеют. К счастью,
Первый из них — canvas_set_custom_u8g2_font.
Чтобы
Вот как я это делаю:
#include <u8g2/u8g2_fonts.c>
// …
canvas_set_custom_u8g2_font(canvas, u8g2_font_haxrcorp4089_t_cyrillic);Файл u8g2/u8g2_fonts.c внутри себя содержит шрифты в особом формате, можно открыть его прямо в текстовом виде и посмотреть как всё устроено.
Шрифт мы выбрали, теперь надо
Плохая новость в том, что строки в коде мы обычно пишем в кодировке
Но canvas_draw_glyph, как можно понять из названия, выводит только один символ. Как же вывести строку? Достаточно просто — надо вывести её посимвольно, сдвигая координату на ширину символа. Звучит просто, но как это сделать?
Тут нас ждёт очередная засада. Дело в том, что canvas_glyph_width, которая должна бы это делать, принимает на вход только char, при том, что нижележащая u8g2_GetGlyphWidth преспокойно работает с Юникодом.
Поэтому я сделал просто — выдрал реализацию u8g2_GetGlyphWidth себе в исходники. В итоге мякотка моего решения выглядит вот так:
void unicode_draw_utf8_str(Canvas* canvas, uint8_t x, uint8_t y, char* str) {
FuriStringUTF8State state = FuriStringUTF8StateStarting;
FuriStringUnicodeValue value = 0;
for(; *str; str++) {
furi_string_utf8_decode(*str, &state, &value);
if(state == FuriStringUTF8StateError) furi_crash(NULL);
if(state == FuriStringUTF8StateStarting) {
canvas_draw_glyph(canvas, x, y, value);
x += unicode_GetGlyphWidth(&canvas->fb, value);
}
}
}Тут unicode_GetGlyphWidth — скопированная реализация u8g2_GetGlyphWidth, а furi_string_utf8_decode используется для кодирования
Читайте также


Комментарии 2