2 марта в 15:08

Создание собственных шрифтов для u8glib

Библиотека U8glib включает в себя достаточно большое количество базовых шрифтов, однако их не всегда бывает достаточно.

Общая суть алгоритма

Среди уже прописанных в библиотеке шрифтов, мало поддерживают кириллицу, то есть русский алфавит, а в некоторых проектах нужны уникальные символы. И что же в такой ситуации делать? Создавать шрифт самому.

Сам автор библиотеки предлагает нам специальную программу – конвертер. Она из переданного ей .bdf файла с данными шрифта создаст готовый массив данных, который нам останется только вставить в дата-файл библиотеки.

Первое, что нам нужно – это создать шрифт и сохранить его данные в .bdf формате. Для этого можно воспользоваться программами

Fontforge (для Windows)

fontforge.org/en-US/

Fony (для Windows)

hukka.ncn.fi/?fony

Fontlab (для Windows и Mac)

fontlab.com/font-editor/fontlab/

Bdfeditor (для Linux)

hea-www.harvard.edu/~fine/Tech/bdfedit.html

Создание самого шрифта

Рисовать весь шрифт долго, да и я не художник, поэтому для примера создадим в Fony простой шрифт для отображения часов (он будет включать только цифры и символ «:» для их разделения).

Работа в fony

Если вы умеете работать в другой программе, пропустите этот блок.

Переходим по ссылке выше, скачиваем и извлекаем архив.

Запускаем fony.

File -> New (или Ctrl + N)

Ascent здесь - высота в пикселях над базовой линией.

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

Так, что если мы хотим шрифт символ высотой в 20 пикселей, параметр Ascent нужно взять с запасом в расстояние между строками, например 24 пикселя. Height – общая высота (Ascent + высота нижнего выносного элемента). Так же необходимо указать какие символы мы собираемся рисовать. По таблице кодов ASCII.

Мы создаем шрифт, начинающийся с «0» и заканчивающийся «:». «0» имеет 48 номер, записываем его в параметр First char, а «:» - 58, записываем в Last char.

Жмем ОК.

Видим такое окно:

Красной чертой обозначена базовая линия.

И тут мы вспоминаем, что не указали ширину символа, ее нужно вписать в поле сверху.

При этом также необходимо помнить, что символы не должны соприкасаться с соседями и взять ширину с запасом, например 14.

Инструменты карандаш – 1, линия – 2, заливка – 3, позволяют заполнять пиксели, а окошко – 4 изменяет их масштаб.

Стрелки 5 и 6 двигают закрашенные пиксели влево и в право, а 7 и 8 – вверх и вниз. Панель служит для выбора и отображения рисуемого символа, а поле слева для предпросмотра.

Теперь рисуем наши символы от «0» до «:».

Теперь можно посмотреть, как будет выглядеть текст в нарисованном шрифте, для примера 12:58.

После того, как закончили рисовать, жмем:

File -> Export -> BDF Font

Назовем созданный шрифт Clock_font.

Сохраняем.

Конвертация дата-файла шрифта в код

Хорошо, теперь мы имеем файл bdf, который нужно перевести в формат, с которым сможет работать библиотека U8glib. Для этого ее автор предлагает воспользоваться программой bdf2u8g_101.

Убедитесь, что bdf2u8g_101.exe и файл вашего шрифта лежат в одной папке.

Теперь нужно с помощью командной строки запустить программу конвертации.

Win + R -> cmd -> OK -> cd “путь к папке, где лежат файлы”

Пример терминала:

Теперь вписываем следующую команду

start bdf2u8g.exe "опции" "полное название файла шрифта" "название шрифта для вызова" "полное название выходного файла"

опции:

[-b num] начать с номера num из таблицы ASCII. Диапазон num: 0..255.

[-e num] закончить номером num из таблицы ASCII. Диапазон num: 0..255.

[-l page] и [-u page] взять диапазон символов из таблицы ASCII от 0 до 512. page = 0 выбирает диапазон 0..127, page = 1 диапазон 128..255 и так далее.

Для создания конвертирования шрифта Clock_font вводим следующую команду:

start bdf2u8g.exe -b 48 -e 58 Clock_font.bdf clock_font Clock_font.c

и жмем Enter.

В папке теперь появился дата-файл.

Открываем его. Я использую редактор кода Visual Studio Code, но подойдет любой текстовый редактор вплоть до стандартного блокнота.

Теперь необходимо вставить этот фрагмент кода в дата-файлы библиотеки.

Для этого переходим в папку clib. Она лежит по адресу:

"путь, где храниться U8glib"\U8glib\src\

В этой директории необходимо найти и открыть файл u8g_font_data.c

Теперь копируем текст из Clock_font.c в u8g_font_data.c и, конечно, же сохраняем.

Но это еще не все. Там же находим и открываем файл u8g.h.

В этом файле пролистываем до начала объявления шрифтов.

Копируем сюда только объявление своего шрифта, дописав в начало extern, и также сохраняем.

Поздравляю, на этом собственный шрифт успешно интегрирован в библиотеку.

Тестовый скетч

Напишем простой скетч, показывающий время, чтобы проверить работоспособность шрифта.

#include "U8glib.h"

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE | U8G_I2C_OPT_DEV_0); // I2C / TWI

byte _hour = 0, _minet = 0; // переменные, хранящие время. Часы и минуты
long long last_millis = 0;  // переменная хранящая предыдущее значение числа миллисекунд
long delay_time = 1000;      // задержка по истечению котрой наступит следующя минута. Устанавливается в миллисекундах.

void setup(void) {
  // u8g.setRot180(); // поворот экрана, если нужен
}

void loop(void) {
  if (millis() - last_millis > delay_time) {    // если пришло время следующей минуты
    last_millis = millis();
    _minet ++;                                  // увеличиваем число минут
    if (_minet > 59) _minet = 0, _hour ++;      // если это уже следующий час, увеличиваем число часов, а минуты сбрасываем в 0
    if (_hour > 23) _minet = 0, _hour = 0;      // если это уже следующий день, сбрасываем в 0 часы и минуты
    
    u8g.firstPage();              // начало цикла отрисовки
    do {
      u8g.setFont(clock_font);      // устанавливаем свой шрифт
      u8g.setPrintPos(30, 40);      // устанавливаем позицию печати
      u8g.print(_hour);             // печатаем часы
      u8g.print(':');               // печатаем разделяющий знак
      u8g.print(_minet);            // печатаем минуты
    } while ( u8g.nextPage() );   // конец цикла отрисовки
  }
}

Для delay_time я поставил 1000, чтобы минуты обновлялись раз в секунду.

Если хотите реальную скорость обновления, поставьте 60000 (если хотите абсолютную точность, то рассчитайте этот параметр, исходя из времени выполнения проверки и частоты работы микроконтроллера. Там будет на пару десятков миллисекунд больше).