Это мой персональный дневник. Пишу, по большей части, про историю, свою жизнь и немного про программирование.

Работа над Юникодом во «Флиппере Зеро»

Вот что значит живой, развивающийся проект. Стоило закоммитить в репозиторий «Флиппера Зеро» своё второе предложение по улучшению поддержки Юникода во «Флиппере», почти сразу его рассмотрели и дали обратную связь. Так далеко не всегда бывает.

Похоже зря я опасался, что поддержка Юникода никому не нужна, пока всё идёт очень гладко. Одно одобрение коммита из необходимых трёх я получил, но мне напомнили, что работа ещё не окончена.

«Most of the methods in elements library are not ready for unicode…»

Я это понял и сам, но, честно сказать, всего за несколько минут до того как получил сообщение от ревьювера. Мои правки пока касались только вывода текста, тогда как во «Флиппере» поверх него работает АПИ, позволяющее выводить ещё и различные элементы интерфейса — окошки, кнопки и тому подобное.

Весь список публичных функций, потенциально нуждающихся в исправлении, можно легко получить:

< targets/f7/api_symbols.csv awk -F, '$3~/^elements_/&&/char|String/{print$3}'
elements_bubble_str
elements_button_center
elements_button_left
elements_button_right
elements_multiline_text
elements_multiline_text_aligned
elements_multiline_text_framed
elements_progress_bar_with_text
elements_scrollable_text_line
elements_string_fit_width
elements_text_box

До этого всё решалось заменой функций нижележащего фреймворка, тут же проблемы чуть посложнее — функции перебирают строки побайтово, а мне надо их переделать на посимвольный перебор. Какой-то опыт у меня уже есть — натренировался в своих экспериментах с русским языком под «Флиппер».

Не везде, кстати, побайтовый перебор является проблемой. В первой же функции по списку всё будет работать нормально и без правок:

uint8_t lines = 1;
const char* t = text;
while(*t != '\0') {
    if(*t == '\n') {
        lines++;
        uint16_t temp_width = canvas_string_width(canvas, t + 1);
        str_width = temp_width > str_width ? temp_width : str_width;
    }
    t++;
}

Тут идёт подсчёт количества строк и вычисление их максимальной ширины. Для этого функция разбивает последовательность байтов по символу перевода строки — \n. Это работает, так как кодировка UTF-8, используемая тут, устроена так, что символ \n однобайтовый и не может встретиться внутри многобайтовой последовательности.

В других же случаях кое-что придётся довольно существенно переписать, работы предстоит немало.