Skip to content

Небольшой урок, как сделать свои кириллические шрифты

License

Notifications You must be signed in to change notification settings

LudmilaPetrovna/font-cyrillic-for-arduino

Repository files navigation

Fifaks доработанный ZX-Spectrum BGE Vendetta

Где я? Что я? Кто здесь?

Переодически возникает необходимость вывести какие-то буковки на экран. Иногда это экран компудастера, иногда это экран микроконтроллера. Все больше и больше популярности в нашей стране приобретает набор для образовательных целей «Ардуино», который уже достаточно широко распространен в школах, детских больницах, хосписах и гаражных кооперативах. К сожалению, наша молодеж и автолюбители сталкиваются с проблемой вывода кириллицы на свои экраны, так как наборчик Ардуино хоть и снабжен многочисленными примерами работы с текстом, но не учитывает потребности малых народов и узких языковых групп. Поэтому мы взяли на себя тяжелый труд по ликвидации колоссального языкового разрыва и восстановлению языковой справедливости.

Краткий ликбез

В основном шрифты бывают трех типов:

  • Пиксельные. Так как обычно экранчики пиксельные, то логично и шрифты хранить в этом же формате и просто быстро-быстро копировать эти самые пиксели. Обычно именно этот тип используется в микроконтроллерах, в библиотеках Arduino и древних компьютерах, вроде ZX-Spectrum. Недостатком этих шрифтов является то, что нельзя произвольно менять размер отрисовки: на экране или появятся артефакты масштабирования, или нужно будет добавлять все символы под новый размер.
  • Векторные штрихи. Если требуется рисовать большие буквы, а то и вообще в произвольном масштабе, то лучше использовать шрифты на основе векторных штрихов. Каждая линия такого шрифта - это штрих минимальной толщины. Подобные шрифты отлично подходят, если надо научить лазерный ЧПУ-станок делать надписи. На сегодняшний день практически не встречаются. Примером может выступать шрифт GOST type A (plotter)
  • Векторные контуры. Самый распространенный тип шрифтов на сегодняшний день. В этих шрифтах каждая линия задана парой контуров, внутренности которых закрашиваются. И хотя этот формат сегодня является доминирующим на компьютерах, в микроконтроллерах почти не используется из-за сложности реализации и фактической ненужности.

Есть и другие типы шрифтов, например, шрифты для emoji или цветные шрифты. Где-то используются PNG-картинки, почти как в древних пиксельных шрифтах, только теперь в цвете, где-то используются сложные системы растеризации и внутренние виртуальные машины, что позволяет задавать оттенки букв. Но в эту степь мы сегодня не пойдем.

Пример шрифта из штрихов:

Линии не имеют толщины

Пример шрифта из контуров:

Линии задаются парой контуров и имеют заливку

С этого момента будем считать, что нам надо где-то взять ПИКСЕЛЬНЫЕ ШРИФТЫ, желательно с кириллицей.

Где взять шрифты?

  • Нарисовать самим
  • Стырить из винды
  • Стырить из Linux
  • Стырить из древних компьютеров вроде C64 / ZX-Spectrum / демок под msdos
  • Растеризовать из ttf

Растеризовать из ttf

Так как шрифтов ttf в мире крайне много, то первым делом в голову приходит сделать растеризацию векторных шрифтов. Увы, но в общем и целом задача не имеет решения.

Если попробовать написать программу "в лоб", которая рисует отдельные глифы на экране, то мы получим огромное количество артефактов:

Шрифт Fifaks 1.0 dev1 явно сделан пиксельным, но сетка символов иногда не вмещает символы целиком:

Глифы вылезают за пределы своего размера

Шрифт Fixedsys Excelsior font with programming ligatures по большей части пиксельный, но некоторые символы выглядят размазанными, другие тоже не влезают в свои знакоместа:

Глифы выглядят помятыми и смазанными

Поэтому если очень хочется, то можно взять такую заготовку, взять древний mspaint.exe и ручками доработать шрифт там, где он выглядит совсем отвратительным. Или трансплантировать отдельные глифы из других шрифтов, где они выглядят лучше. Например, я ручками доработал шрифт Fifaks 1.0 dev1 и получил такую картинку:

Мои личные доработки и изменения к шрифту Fifaks 1.0 dev1

Для растеризации можно использовать прилагающийся скрипт ttf2png.pl или rasterizer.pl, оба скрипта крайне кривые и сделаны из говна и палок, но они могут служить отправной точкой (нет). Как ими пользоваться, читатель может догадаться сам.

К сожалению, подобные гибриды и прочие эксперименты нельзя распространять как готовый продукт, чтобы случайно не нарушить какую-нибудь лицензию.

Вытащить шрифты из файлов FON

Шрифты в формате FON обычно являются пиксельными и достаточно высокого качества. Если у вас есть лицензионное право или законы вашей страны разрешают использование таких ресурсов, то распаковываем файлы *.fnt:

mkdir fnt                             # создать директорию fnt
wrestool -x -R -t 8 -o fnt *fon       # распаковать ресурсы из файлов *.fon в текущей директории
perl perl fnt_renamer.pl              # переименовать файлы шрифтов во что-то вменяемое
perl fnt2png.pl 8514oem-oem-10x12.fnt # сконвертить один из шрифтов в картинку

Стырить из Linux

Одним из лучших открытых пиксельных шрифтов является GNU Unifont, который среди прочего распространяется в формате BDF. Увы, но мне лень писать конвертер этого формата. Он достаточно простой и читателю предлагается это упражнение для самостоятельного исполнения.

Стырить из древних компьютеров вроде C64 / ZX-Spectrum / демок под msdos

ZX-Spectrum BGE

Под старыми системами были замечательные шрифты, которые рисовались годами, даже после официальной смерти этих платформ на рынке. Множество красивых шрифтов можно найти здесь:

Самые лучшие шрифты конечно же лежат в демосцене, а как их оттуда выковыривать - зависит от самой демки. Увы, кириллица в таких шрифтах бывает не слишком часто. Если же она там есть, то это наверняка будет отличный шрифт.

Шрифт вытащенный из cracktro Vendetta:

Vendetta

Увы, не смотря на всю красоту шрифта, в нем нету кириллицы

Как такое вытащить? Берем GBS и долго крутим ползунки, пока не найдем что-то похожее на шрифты, записываем адреса. Потом как-то так:

# dd if=binary.exe bs=239487 skip=1 of=font.bin     # отрезаем от бинарника нужный кусочек
# mkdir aaa                                         # создаем временную директорию
# ffmpeg -f rawvideo -s 8x16 -pix_fmt monob -i font.bin aaa/tst%4d.png # нарезаем буковки
# montage -geometry 8x16+0+0 -tile 16x16 aaa/* font.png                # склеиваем буковки

Немного слов о кодировках

Для компьютера все буквы, которые он выводит на экран - на самом деле байты. К примеру, если в программе вывести байт со значением 48, то скорее всего компьютер отобразит символ 0 (ноль), а если значение будет 65, то будет выведена латинская A. Как компьютер узнает, какому коду какой символ соответствует? Для первых 128 значений есть хороший стандарт: ASCII, который потом был дополнен и во времена msdos был известен как cp437.

А что с кириллицей? Как вывести букву Я? Сегодня, когда мы почти повсеместно перешли на стандарт Unicode, нам нужно просто отобразить символ с номером 1071 (он же 0x42F в 16-ричной системе). И тут нас встречает первая проблема: как нам засунуть такое большое число в 1 байт? Возможно ли это? Чтобы сделать это возможным, можно воспользоваться одной из современных кодировок, таких как UTF-8. Увы, но в этой кодировке все кириллические символы занимают по 2 байта, что заставляет нас тратить байты с избытком, по сравнению, esli bi mi pisali tekst translitom. Латинские же символы в этой кодировке занимают по 1 байту, что делает сложным подсчет длинный строки. В принципе, есть и другие кодировки, к примеру UTF-16, где для большинства символов нужно по 2 байта, что решает проблему с измерением длинны строки, но не решает проблему с удвоением объема текста. Еще появляется вопрос: а какие символы нам вообще нужны в шрифте? Только базовая кириллица? Расширенная кириллица с поддержкой других языков? Стандарт Unicode версии 15.1, содержит 149878 символов, покрывая 161 язык мира. Мы точно хотим засунуть все это в наш маленький микроконтроллер?

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

Для кириллицы было изобретено множество таких таблиц, но вот основные, которые я смог вспомнить:

      cp866               cp1251          ISO/IEC_8859-5
  ☺☻♥♦♣♠•◘○◙♂♀♪♫☼     ☺☻♥♦♣♠•◘○◙♂♀♪♫☼     ☺☻♥♦♣♠•◘○◙♂♀♪♫☼
 ►◄↕‼¶§▬↨↑↓→←∟↔▲▼    ►◄↕‼¶§▬↨↑↓→←∟↔▲▼    ►◄↕‼¶§▬↨↑↓→←∟↔▲▼
  !"#$%&'()*+,-./     !"#$%&'()*+,-./     !"#$%&'()*+,-./
 0123456789:;<=>?    0123456789:;<=>?    0123456789:;<=>?
 @ABCDEFGHIJKLMNO    @ABCDEFGHIJKLMNO    @ABCDEFGHIJKLMNO
 PQRSTUVWXYZ[\]^_    PQRSTUVWXYZ[\]^_    PQRSTUVWXYZ[\]^_
 `abcdefghijklmno    `abcdefghijklmno    `abcdefghijklmno
 pqrstuvwxyz{|}~⌂    pqrstuvwxyz{|}~⌂    pqrstuvwxyz{|}~⌂
 АБВГДЕЖЗИЙКЛМНОП    ЂЃ‚ѓ„…†‡€‰Љ‹ЊЌЋЏ    ����������������
 РСТУФХЦЧШЩЪЫЬЭЮЯ    ђ‘’“”•–—�™љ›њќћџ    ����������������
 абвгдежзийклмноп     ЎўЈ¤Ґ¦§Ё©Є«¬­®Ї     ЁЂЃЄЅІЇЈЉЊЋЌ­ЎЏ
 ░▒▓│┤╡╢╖╕╣║╗╝╜╛┐    °±Ііґµ¶·ё№є»јЅѕї    АБВГДЕЖЗИЙКЛМНОП
 └┴┬├─┼╞╟╚╔╩╦╠═╬╧    АБВГДЕЖЗИЙКЛМНОП    РСТУФХЦЧШЩЪЫЬЭЮЯ
 ╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀    РСТУФХЦЧШЩЪЫЬЭЮЯ    абвгдежзийклмноп
 рстуфхцчшщъыьэюя    абвгдежзийклмноп    рстуфхцчшщъыьэюя
 ЁёЄєЇїЎў°∙·√№¤■     рстуфхцчшщъыьэюя    №ёђѓєѕіїјљњћќ§ўџ

    KOI8-R                KOI8-U            MacCyrillic
  ☺☻♥♦♣♠•◘○◙♂♀♪♫☼     ☺☻♥♦♣♠•◘○◙♂♀♪♫☼     ☺☻♥♦♣♠•◘○◙♂♀♪♫☼
 ►◄↕‼¶§▬↨↑↓→←∟↔▲▼    ►◄↕‼¶§▬↨↑↓→←∟↔▲▼    ►◄↕‼¶§▬↨↑↓→←∟↔▲▼
  !"#$%&'()*+,-./     !"#$%&'()*+,-./     !"#$%&'()*+,-./
 0123456789:;<=>?    0123456789:;<=>?    0123456789:;<=>?
 @ABCDEFGHIJKLMNO    @ABCDEFGHIJKLMNO    @ABCDEFGHIJKLMNO
 PQRSTUVWXYZ[\]^_    PQRSTUVWXYZ[\]^_    PQRSTUVWXYZ[\]^_
 `abcdefghijklmno    `abcdefghijklmno    `abcdefghijklmno
 pqrstuvwxyz{|}~⌂    pqrstuvwxyz{|}~⌂    pqrstuvwxyz{|}~⌂
 ─│┌┐└┘├┤┬┴┼▀▄█▌▐    ─│┌┐└┘├┤┬┴┼▀▄█▌▐    АБВГДЕЖЗИЙКЛМНОП
 ░▒▓⌠■∙√≈≤≥ ⌡°²·÷    ░▒▓⌠■∙√≈≤≥ ⌡°²·÷    РСТУФХЦЧШЩЪЫЬЭЮЯ
 ═║╒ё╓╔╕╖╗╘╙╚╛╜╝╞    ═║╒ёє╔ії╗╘╙╚╛ґ╝╞    †°Ґ£§•¶І®©™Ђђ≠Ѓѓ
 ╟╠╡Ё╢╣╤╥╦╧╨╩╪╫╬©    ╟╠╡ЁЄ╣ІЇ╦╧╨╩╪Ґ╬©    ∞±≤≥іµґЈЄєЇїЉљЊњ
 юабцдефгхийклмно    юабцдефгхийклмно    јЅ¬√ƒ≈∆«»… ЋћЌќѕ
 пярстужвьызшэщчъ    пярстужвьызшэщчъ    –—“”‘’÷„ЎўЏџ№Ёёя
 ЮАБЦДЕФГХИЙКЛМНО    ЮАБЦДЕФГХИЙКЛМНО    абвгдежзийклмноп
 ПЯРСТУЖВЬЫЗШЭЩЧЪ    ПЯРСТУЖВЬЫЗШЭЩЧЪ    рстуфхцчшщъыьэю€

Шрифт Fifaks может отобразить это так:

Шрифт Fifaks может отобразить это так

Если мы используем кодировку cp866, то для вывода буквы Я нужно вывести символ с номером 159 (или 0x9F), что отлично умещается в 1 байт и решает множество проблем нашего крохотного микроконтроллера. В довесок у нас есть символы псевдографики, которыми мы можем рисовать рамочки и даже есть несколько смайликов и иконок, которые тоже можно использовать. К недостаткам этой кодировки можно пожалуй отнести только отсутствие «ёлочек», которые есть в кодировке cp1251 (кодировке кириллицы в Windows), но если «ёлочки» или какой-то другой символ сильно нужны, никто не мешает выбрать другую кодировку. Лично я для себя сделал выбор в пользу cp866.

Всем любопытным крайне рекомендую: http://aspell.net/charsets/cyrillic.html - краткая история кодировок с кириллицей

Мы стырили шрифт... Картинку...? А что с ней дальше делать?

Так как у нас цель сконвертить шрифт под микроконтроллер, то такие фичи как кернинг нам не сильно нужны, равно как и полутона. Следовательно, чтобы уменьшить размер нашего битмапа, мы смело можем конвертить его в 1-битную картинку. К примеру, сконвертим шрифт от редактора BGE:

convert bge.png -colorspace gray -auto-level -negate -colors 2 bge-bw.png

bge-bw

Далее, нам надо как-то превратить нашу картинку в шрифт. Обычно шрифт представлен набором линий по 8 пикселей, которые кодируются 1 байтом.

Биты и байты

Порядок байтов и битов разнится от библиотеки к библиотеке и может меняться. К примеру, в FNT-файлах байты идут по вертикали, как только самые левые 8 пикселей символа будут записаны в файл, можно переходить к следующему вертикальному столбцу и кодировать следующие 8 пикселей. Чаще же шрифты хранятся по строчкам, в когда вся строка кодирована в байты, то осуществляется переход на новую строчку. Иногда глифы могут быть повернуты на 90 или 180 градусов, в некоторых случаях эта оптимизация имеет смысл.

На прилагаемой картинке видно, что место справа и снизу от глифа зачастую расходуется напрасно. Поэтому я предлагаю хранить картинку более оптимальным образом: в виде глифов, разложенных по сетке 16х16 пикселей. Как вариант, разложить все глифы в одну длинную картинку по горизонтали, но лично мне такие картинки сложнее воспринимать. Как и вертикальные строчки, с повернутыми символами на 90 градусов. Но такие варианты хранения могут быть более оптимальными в вашем конкретном случае.

Итак, превратим нашу картинку... В такую же картинку, но только пригодную для добавления в наш код:

convert bge-bw.png -negate bge_bw.xbm

И после этого получим файл bge_bw.xbm, пригодный для включения в наш код:

#define bge_bw_width 80
#define bge_bw_height 128
static char bge_bw_bits[] = {
  0x00, 0x00, 0x00, 0xC6, 0x62, 0x8C, 0x63, 0xC8, 0x14, 0x00, 0x00, 0x00,
  0x00, 0x00, 0xFE, 0x03, 0x7A, 0x0F, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00,
  (длинный файл)
  0xCF, 0xD1, 0x8B, 0x1D, 0x96, 0x00, 0xF0, 0x00, 0x40, 0x00, 0x00, 0x60,
  0x86, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };

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

gcc -Wall figlet.c && ./a.out "`echo 'Привет, мир' | iconv -tcp866`"

****
*  *           **
*  * ***  *  * * *  ***  ****           *  * *  * ***
*  * *  * *  * ***  ****   *            **** *  * *  *
*  * **** * ** *  * *      *    *       **** * ** ****
*  * *     * * ****  **    *    *       *  *  * * *
     *                         *                  *

В принципе, этот код можно переносить в наш микроконтроллер! Вместо выделения буфера, по всей видимости, за нас это сделает библиотека для работы с экраном. Эта же библиотека предоставит функцию setPixel, чтобы не обращаться к виртуальному холсту.

В случае arduino, возможно стоит переделать функции доступа к картинки через PGM, чтобы не тратить лишнюю память и без того слабого микроконтроллера.

Вот и все, у нас есть шрифты!

Добавим наши новые шрифты в какую-то библиотеку

Например, возьмем библиотеку pico-ssd1306, она уже умеет управлять экраном, выделять память и в ней даже есть свои шрифты. Конечно, никто не мешает портировать нашу функцию, которая рисует 1 символ и пользоватьсянашими шрифтами в этой библиотеке, но... Как же богатое API и его консистентность? Как такие фичи, как поворот текста? Давайте добавим шрифты в таком виде, в каком библиотека будет считать их родными!

Часть 1: знакомство с библиотекой

Открываем библиотеку и сразу открываем в ней первый попавшийся шрифт, пусть в нашем случае это будет файл pico-ssd1306-master/textRenderer/5x8_font.h:

#ifndef SSD1306_5X8_FONT_H
#define SSD1306_5X8_FONT_H

#ifndef SSD1306_ASCII_FULL

const unsigned char font_5x8[] = {
    0x5, 0x8, // font width, height

    0x0,
    0x0,
    0x0,
    0x0,
    0x0,

    0x0,
    0x0,
    0x5c,
    0x0,
    0x0,

Так, что мы узнали отсюда?

  • Ширину и высоту глифов эта библиотека хранит в самом файле шрифтов, без дефайнов в коде
  • Ширина и высота является частью массива самого битмапа
  • Есть какие-то предопределенные флаги, такие как SSD1306_ASCII_FULL
  • По всей видимости надо обращаться к переменной font_5x8 для доступа к битмапу
  • Каждые 5 байт есть перевод строки - скорее всего так разделяют отдельные глифы
  • Так как шрифт 5 пикселей в ширину и разделение по 5 пикселей, то скорее всего глифы повернуты на 90 градусов
  • Первый глиф содержит нули, скорее всего это пробел, второй глиф почти все нули - это похоже на символ "!", значит адресация начинается с 32 символа стандартной таблицы ASCII, а не с нулевого, как у нас. Да, смайлики не всем нужны :(

Продолжаем изучать библиотеку:

# grep -r SSD1306_ASCII_FULL .
./examples/text_extended_ascii/main.cpp:// Define SSD1306_ASCII_FULL to use full ascii range (32 - 255)

Наше предположение о том, что адресация начинается с 32-го символа подвердилась. Более того, оказывается флагом SSD1306_ASCII_FULL можно включать/выключать вторую половину символов (там как раз где кириллица), так как не всем это надо.

А нужно ли как-то регистрировать наш шрифт?

# grep -r font_5x8 .
./textRenderer/TextRenderer.h:#include "5x8_font.h"

Да, все шрифты должны быть перечислены в файле textRenderer/TextRenderer.h:, когда мы будем добавлять свои шрифты, надо пропатчить этот файл, добавив свои шрифты где-то рядом:

#include "5x8_font.h"
#include "8x8_font.h"
#include "12x16_font.h"
#include "16x32_font.h"

Вроде бы все понятно. Вроде бы. Вроде. Чтобы быть уверенным, что мы поняли все правильно, давайте перепишем наш figlet, сделаем так, чтобы он использовал эти файлы библиотеки. В качестве отправной точки, давайте портируем функцию drawChar из pico-ssd1306-master/textRenderer/TextRenderer.cpp

# gcc -Wall figlet2.c -o figlet_foreign && ./figlet_foreign "`echo 'Привет, мир' | iconv -tcp866`"
  *               *  * *
            *    *  * *   ***           *   *  *
 **                 *  *  *             *  *
*  *  ** *  *   **  ** *  *             * *    *   ** *
**** *  *  *   *  * ** *  *              *  * *   *  *
*  * *  * *  * *  * * **  *             *  ***  * *  *
*  *  ** * **   **  *  *  *     *         *** **   ** *
                               *            *

Ой, библиотека же не имеет кириллицы! Ладно, я хотел сказать...

# gcc -Wall figlet2.c -o figlet_foreign && ./figlet_foreign "`echo 'Hello, world!' | iconv -tcp866`"

           **   **                                 **
*  *        *    *                                  *     *   *
*  *  **    *    *   **            *  *  **   * *   *   ***   *
**** ****   *    *  *  *           *  * *  *  **    *  *  *   *
*  * *      *    *  *  *           **** *  *  *     *  *  *
*  *  ***  ***  ***  **    *       *  *  **   *    ***  ***   *
                          *

Если сделать размер шрифта побольше, то видно:

Hello

Значит мы полностью познакомились с библиотекой и можем быть точно уверены в ее устройстве! И даже если мы сделаем что-то не так, у нас уже есть готовый тест! Можно начинать генерировать шрифты в формате этой библиотеки!

Часть 2: конвертация

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

# convert bge_bw.xbm -negate bge.png
# perl png2picolib.pl bge.png
Converting file "bge.png" as font "bge" size: 5x8
#

Все, шрифт скопирован в pico-ssd1306-master/textRenderer/ (путь должен существовать), теперь можно посмотреть что там, в этом свежем файле:

# cat pico-ssd1306-master/textRenderer/bge_5x8_font.h

#ifndef SSD1306_BGE_5X8_FONT_H
#define SSD1306_BGE_5X8_FONT_H

#ifndef SSD1306_ASCII_FULL

const unsigned char font_bge_5x8[] = {
    5, 8, // font width, height
/* char 32 (0x20)   */ 0,0,0,0,0,
/* char 33 (0x21) ! */ 0,94,0,0,0,
/* char 34 (0x22) " */ 8,4,8,4,0,
/* char 35 (0x23) # */ 40,124,40,124,0,
/* char 36 (0x24) $ */ 40,110,36,20,0,
/* char 37 (0x25) % */ 72,32,16,72,0,
/* char 38 (0x26) & */ 104,84,40,64,0,
/* char 39 (0x27) ' */ 0,8,4,0,0,
/* char 40 (0x28) ( */ 0,0,60,66,0,
/* char 41 (0x29) ) */ 0,66,60,0,0,
/* char 42 (0x2a) * */ 72,48,48,72,0,
/* char 43 (0x2b) + */ 0,16,56,16,0,
/* char 44 (0x2c) , */ 0,128,96,0,0,
/* char 45 (0x2d) - */ 0,16,16,16,0,
/* char 46 (0x2e) . */ 0,0,64,0,0,
/* char 47 (0x2f) / */ 0,96,24,6,0,
/* char 48 (0x30) 0 */ 56,82,74,60,0,
/* char 49 (0x31) 1 */ 0,68,126,64,0,
/* char 50 (0x32) 2 */ 100,82,82,76,0,
/* char 51 (0x33) 3 */ 36,66,74,52,0,
/* char 52 (0x34) 4 */ 30,16,0,126,0,
/* char 53 (0x35) 5 */ 46,74,74,50,0,
/* char 54 (0x36) 6 */ 60,74,74,48,0,
/* char 55 (0x37) 7 */ 2,98,26,6,0,
/* char 56 (0x38) 8 */ 52,74,74,52,0,
/* char 57 (0x39) 9 */ 12,82,66,60,0,

Все отлично, наш новый шрифт готов!

Не забываем добавить новые шрифты в TextRenderer.h, чтобы система их увидела и все готово.

About

Небольшой урок, как сделать свои кириллические шрифты

Resources

License

Stars

Watchers

Forks