binFontsTool - редактор шрифтов AdafruitGFX, UTFT на MS Excel

DenSyo
Offline
Зарегистрирован: 13.01.2017

binFontsTool - редактор шрифтов для библиотек AdafruitGFX и UTFT на MS Excel VBA

Создание собственных шрифтов, чтение и запись файлов шрифтов AdafruitGFX, UTFT, бинарных файлов, файлов Adobe BDF. Изменение кодировки импортированных шрифтов. Функции редактирования символов.

ссылка на скачивание

Пример использования: с редактором идут досовские шрифты 8х16, в программе наживаем Open binary, задаем ширину 8, высоту 16, первый символ например 32, последний 255. После загрузки шрифта жмем Encoding и выбираем смену кодировки DOS 866 на Windows 1251. После смены кодировки жмем Save as fonts C, выбираем библиотеку для которой хотим сохранить шрифт. Задаем файл сохранения, имя шрифта и жмем Ок

DenSyo
Offline
Зарегистрирован: 13.01.2017

Последняя строка на листе имеющая не пустое значение считается последней строкой массива символов. Все операции сохранения шрифтов работают до этой строки, важно не создавать лишних строк. Сочетание клавиш Ctrl + End покажет вам последнюю строку имеющую значение.

В столбце 353 (char) первой строки каждого символа отображается десятичное значение кода которое будет присвоено символу при сохранении С файла. Код формируется последовательно начиная с заданного значения для первого символа. При чтении BDF файла коды символов из шрифта в файле вносятся в столбец 354 (code), диапазон этих кодов не всегда будет соответствовать диапазону значений в столбце char. В таком случае для корректного сохранения С файла сначала следует провести операцию смены кодировки по столбцу 354. Если нет необходимости менять кодовую страницу, следует указать текущую в полях From и To. Если после этого остались пустые строки вместо символов, следует провести операцию Refresh которая расставит нули в пропущенных символах. Такой шрифт уже можно использовать в глифовых версиях, например AdafruitGFX или UTFT glyph (для библиотеки UTFT_binFonts), либо можно заполнить пустые символы любыми своими по желанию. Пример: с редактором идут шрифты BDF, откройте LucidaSans-Typewriter14_koi8r задав код первого символа 32 и последнего 255. Сделайте смену кодировки из страницы row: 3 Russian KOI8-R (20866) в страницу row 1: Arduino (RUS) - Windows (1251). Сохраните шрифт как С файл выбрав желаемую библиотеку.

blackbird5
Offline
Зарегистрирован: 16.12.2016

Подскажите пожалуйста. Как в Вашем редакторе добавить символ в шрифт? У меня есть шрифт который состоит только из цифр. Мне туда надо добавить точку и тире. Как это сделать?

DenSyo
Offline
Зарегистрирован: 13.01.2017

цифры имеют коды с 48 по 57. тире код 45, точка 46. надо добавить в ваш шрифт 3 символа с начала. загружаем шрифт с цифрами, затем в settings меняем код первого символа шрифта на 45, жмем ОК без рефреш. выделеям любую группу столбцов: либо с изображением символов, либо группу столбцов бинарных значений, либо десятичных, либ шестнадцетиричных. важно выделить только столбцы принадлежащие к одной группе иначе при вставке столбцов разных групп программа не будет проводить отрисовку. выделять надо только начиная со значащей строки, выделенные первая и вторая строки так же не дадут отрисовки при вставке. т.е. выделяем с третьей строки только, например, ячейки содержащие бинарные значения символов (257-288), выделяем только имеющие значение столбцы, остальные нет смысла. выделили, нажимаем вырезать и устанавливаем курсор на первую ячейку бинарных значений четвертого по счету символа. жмем вставить. теперь можно сделать рефреш и программа заполнит нулями пустые символы сверху, либо начать рисовать их прямо с пустого места. соответственно для сборки символов из разных шрифтов в один можно воспользоваться временным листом экселя, в него по своему усмотрению вставлять значения символов и в последствии вставить все одним массивом в редактор.

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

еще вариант. после загрузки шрифта копируем столбец 353 (char) начиная с третьей строки до конца в столбец 354 (code). меняем в settings значение кода первого символа на 45 и делаем смену кодировки по столбцу 354 выбрав в качестве исходной и результирующей row 6: RUS Arduino - Windows (1251) либо любую другую содержащую символы основной таблицы (с 0 по 127). таблицы кодировок заполнены на листе Encoding, их можно строить только для дополнительных (региональных) символов, тогда основные символы не будут участвовать в перестроении. в нашем случае следует выбрать любую из кодировок содержащую символы с 0 по 255. смена кодировки расставит символы по порядку и добавит в начале массива три пустых символа.

PS в новой версии этот вариант значительно упрощается. после загрузки шрифта идем в settings меняем количество символов и код первого символа, жмем ОК без refresh, идем в encoding, жмем "copy chars to codes", ставим "sort by column 354" и жмем ОК, кодировка установленная по умолчанию включает все символы.

blackbird5
Offline
Зарегистрирован: 16.12.2016

Ну как бы все получилось. Спасибо! Будем ковырять )))

DenSyo
Offline
Зарегистрирован: 13.01.2017

доступна новая версия 0.2.6

существенно поднял скорость чтения файлов. если требуется только открыть файл и сохранить в другой версии, можно отключить раскраску в настройках для ускорения процесса. добавлена поддержка шрифтов: Squix V2, Squix V3, ILI9341_t3 V1, OLED_I2C

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

pilnikov
pilnikov аватар
Offline
Зарегистрирован: 28.08.2015

Доброго времени суток.

Делаю первые шаги в кастомизации шрифтов. Что есть x и y offset в окне сохранения?

Пытался редактировать шрифты для Adafruit GFX с глифами. В итоге получаю смещение на 1 символ в маленьких латиницей (вместо "d" рисует "e"; слово "Wed" пишет как "Wfe"), и на два символа для всей кириллицы. 

Тут https://yadi.sk/d/paeYsYWB3UXKbV оригинал и отредактированный (просто открытый и сохраненный) файлы

Оригинал получен фонтконвертером из либы Adafruit GFX, путем слива из двух кусков (с 1 по 191 и с 1040 по 1103 символы) шрифта colibrii.ttf  Пришлось вручную править таблицу глифов (русскую часть), прибавляя смещение.

Плюсом маленький вопросик /"хотелка"  - можно сделать вывод Bitmap data в файл .c (.h) по такому 

  
  // Bitmap Data:
  0x00, // ' '
  0xFF, 0xF8, 0xF0, // '!'
  0xDE, 0xF6, // '"'
  0x12, 0x32, 0x36, 0xFF, 0xFF, 0x24, 0xFF, 0xFF, 0x4C, 0x48, // '#'

шаблону ?

 Спасибо за ваш труд!

pilnikov
pilnikov аватар
Offline
Зарегистрирован: 28.08.2015

Еще в догонку

Гдето попадалось описание принципов кодировки шрифтов в Adafruit GFX и расшифровки глиф таблицы, а где? - не помню.

Не подскажите?

DenSyo
Offline
Зарегистрирован: 13.01.2017

В редакторе массив символов всегда представлен как отцентрованный по левому краю моноширный шрифт с шириной и высотой по максимальным значениям всех символов. Для пропорциональных шрифтов указывается правая граница символа в столбце 356 первой строки значений символа (подразумевается, что минимальное значение высоты символов может быть 1 и используется только первая строка для уникальных значений символов. для работы только с этой строкой есть чекбокс на основной панели). Форматы шрифтов AdafritGFX и ILI9341_t3 кроме ширины символа так же позволяют задать смещение глифа символа относительно оси координат. В редакторе в случае ненулевого значения смещения Y положительное значение означает количество строк сверху до первой значащей нижней строки символа «А» (это условно), отрицательное значение – количество строк снизу до той же строки. Смещение X по модулю задает количество строк слева до первого значащего столбца символа «а» (в следующей версии скорее всего сделаю отрицательное значение количеством строк справа относительно ширины шрифта) и действует для всего шрифта, все символы в редакторе считаются выровненными по смещению X. Сделаю раскраску границ ячеек по смещениям в следующей версии для наглядности, пока можно воспользоваться выделением столбцов с первого по значение смещения X, все что попадает в выделенную область условно говоря заходит на предыдущий символ при печати. Это для всяких завитушек и курсива, и по этой причине нет закраски фона символа при печати. Если добавляете в шрифт символ со смещением X большим чем текущий у шрифта, в редакторе прежде необходимо добавить столбцов слева для всех текущих символов до этого значения. Смещение X в редакторе, как и ширина с высотой имеет максимальное значение для всех символов шрифта. При сохранении шрифта в различные форматы программа вычисляет параметры глифов символов в столбцы 361-364 первой строки символов, эти значения имеют разный смысл в разных форматах и носят информативный характер.

Спасибо что обратили внимание на детский баг) плохой идеей было использовать в комментариях неэкранированные символы. Удалите знак слеш в комментарии к символу 92 «// symbol \» или возьмите его в одинарные кавычки '\' тогда все станет отображаться правильно. Надо подробнее почитать про спецсимволы С, в редакторе при чтении после двойного слеша отсекается все до конца строки и такой баг не проявляется, собственно такое поведение внешне и в IDE. В следующей версии редактора поправлю комментарии к символам, пока используйте Default схему добавления имен символов или экранируйте символы самостоятельно на листе Chars. 

Все реализованные форматы изучал по комментариям в библиотеках и идущих с ними шрифтах. Для Адафруит структура описана в gfxfont.h

typedef struct { // Data stored PER GLYPH
	uint16_t bitmapOffset;     // Pointer into GFXfont->bitmap
	uint8_t  width, height;    // Bitmap dimensions in pixels
	uint8_t  xAdvance;         // Distance to advance cursor (x axis)
	int8_t   xOffset, yOffset; // Dist from cursor pos to UL corner
} GFXglyph;

typedef struct { // Data stored for FONT AS A WHOLE:
	uint8_t  *bitmap;      // Glyph bitmaps, concatenated
	GFXglyph *glyph;       // Glyph array
	uint8_t   first, last; // ASCII extents
	uint8_t   yAdvance;    // Newline distance (y axis)
} GFXfont; 

Глиф занимает целое количество байт в массиве Bitmap от произведения высоты и ширины символа, остаток последнего байта принято забивать нолями, но не думаю, что это имеет значение. Хранится глиф построчно без выравнивания на байты, т.е. надо читать количество бит равное ширине символа и следом следующую строку количество раз равное высоте символа.

Ваша хотелку уже сделал в разрабатываемой версии, но до ее выхода еще не слишком скоро. Если очень хочется, можно заменить этим кодом аналогичный в процедуре SaveC модуля Main 

        Case 3      ' Adafruit GFX
            MakeGlyphs 1
            dds = False
            sC = "// Adafruit GFX font " & wsMain.Cells(1, 17).Value & " size: " & wsMain.Cells(1, 5).Value & "x" & wsMain.Cells(1, 7).Value & Chr(13) & Chr(10)
            s1 = "const uint8_t " & wsMain.Cells(1, 17).Value & "Bitmaps[] PROGMEM = {" & Chr(13) & Chr(10)
            s2 = "const GFXglyph " & wsMain.Cells(1, 17).Value & "Glyphs[] PROGMEM = {" & Chr(13) & Chr(10)
            s3 = "const GFXfont " & wsMain.Cells(1, 17).Value & " PROGMEM = {" & Chr(13) & Chr(10) & _
                " (uint8_t *)" & wsMain.Cells(1, 17).Value & "Bitmaps," & Chr(13) & Chr(10) & _
                " (GFXglyph *)" & wsMain.Cells(1, 17).Value & "Glyphs," & Chr(13) & Chr(10) & _
                " " & wsMain.Cells(1, 9).Value & ", " & (wsMain.Cells(1, 11).Value + wsMain.Cells(1, 9).Value - 1) & ", " & wsMain.Cells(1, 7).Value & "};"
            n = 0
            fXO = wsMain.Cells(1, 12).Value
            If fXO < 0 Then fXO = 0 - fXO
            fYO = wsMain.Cells(1, 13).Value
            If fYO > 0 Then fYO = wsMain.Cells(1, 7).Value - fYO - 1
            For i = 1 To wsMain.Cells(1, 11).Value
                j = 3 + (i - 1) * wsMain.Cells(1, 7).Value
                If wsMain.Cells(j, 361).Value > 0 Then bNum = (wsMain.Cells(j, 361).Value * wsMain.Cells(j, 362).Value - 1) \ 8 + 1 Else bNum = 0
                If wsMain.Cells(j, 356).Value > 0 And wsMain.Cells(j, 356).Value <= wsMain.Cells(1, 5).Value Then cXS = wsMain.Cells(j, 356).Value Else cXS = wsMain.Cells(j, 357).Value
                s2 = s2 & "  { " & n & ", " & wsMain.Cells(j, 361).Value & ", " & wsMain.Cells(j, 362).Value & ", " & cXS & ", " & (wsMain.Cells(j, 363).Value + fXO) & ", " & (wsMain.Cells(j, 364).Value + fYO) & " }"
                If i < wsMain.Cells(1, 11).Value Then s2 = s2 & ","
                s2 = s2 & Chr(9) & "// " & wsMain.Cells(j, 355).Value & Chr(13) & Chr(10)
                If bNum > 0 Then
                    x = 1
                    y = 0
                    k = 0
                    Do While y * 32 + x <= bNum
                        If k Mod 16 = 0 Then s1 = s1 & "  "
                        Select Case wsMain.Cells(1, 38).Value
                        Case 1
                            s1 = s1 & "B" & ToBinStr(wsMain.Cells(j + y, 364 + x).Value)
                        Case 2
                            s1 = s1 & ToInt(wsMain.Cells(j + y, 364 + x).Value)
                        Case Else
                            s1 = s1 & wsMain.Cells(j + y, 364 + x).Value
                        End Select
                        x = x + 1
                        If x = 33 Then
                            x = 1
                            y = y + 1
                        End If
                        If Not (i = wsMain.Cells(1, 11).Value And y * 32 + x > bNum) Then s1 = s1 & ","
                        k = k + 1
                        If k = bNum Then
                            s1 = s1 & Chr(9) & "// " & wsMain.Cells(j, 355).Value & Chr(13) & Chr(10)
                        Else
                            If k Mod 16 = 0 Then s1 = s1 & Chr(13) & Chr(10)
                        End If
                    Loop
                End If
                n = n + bNum
            Next i
            s1 = s1 & "};"
            s2 = s2 & "};"

немного про смещения глифов в адафруит здесь в конце 
https://github.com/adafruit/Adafruit-GFX-Library/blob/master/fontconvert...

PS много багов обнаружил сегодня, выложу вечером апдейт на текущий релиз

DenSyo
Offline
Зарегистрирован: 13.01.2017

выложил версию 0.2.6.2 

Кроме сказанного исправлена работа с шириной символа, убрано принудительное изменение, сделал допустимым значение меньше реальной ширины символа, так в адафруит рюшечки справа могут заходить на следующий символ. Исправил реплэйс шрифта адафруит при сохранении в существующий файл. Добавил внесение ширины символа при чтении BDF. В общем много на что начинаешь обращать внимание когда есть общение с пользователем) 

Для работы с региональными символами удобно использовать инструмент Encoding, надо только создать таблицу соответствия символов для UTF или чего угодно получаемого различными конвертерами в CP1251 или в любую иную кодировку. Можно создать свои кодировки без русских символов имеющих соответствие среди английских, например.

Для генерации шрифтов из установленных в системе рекомендую fonty, после генерации экспортировать в BDF и открывать его в редакторе. 

pilnikov
pilnikov аватар
Offline
Зарегистрирован: 28.08.2015

Доброго времени суток. Вот пускай я покажусь занудой, но у меня опять хотелка.

Копаюсь с библиотекой UCGLIB https://github.com/olikraus/ucglib/tree/master/tools/font 

По факту в либе есть только два шрифта с кирилицей и то она сдвинута выше чем обычно (шрифт unifont 08 русская А по адресу 90Н, а не С0Н)

https://github.com/olikraus/ucglib/wiki/fontgroupunifont_old

Описание шрифтов

/*=================================================*/
/* OLD FONT FORMAT */
 
/* size of the font data structure, there is no struct or class... */
/* this is the size for the new font format */
#define UCG_FONT_DATA_STRUCT_SIZE 21
 
/*
  OLD Font Data Struct 
  ... instead the fields of the font data structure are accessed directly by offset 
  font information 
  offset
  0             font format
  1             FONTBOUNDINGBOX width           unsigned
  2             FONTBOUNDINGBOX height          unsigned
  3             FONTBOUNDINGBOX x-offset         signed
  4             FONTBOUNDINGBOX y-offset        signed
  5             capital A height                                unsigned
  6             start 'A'
  8             start 'a'
  10            encoding start
  11            encoding end
  12            descent 'g'                     negative: below baseline
  13            font max ascent
  14            font min decent             negative: below baseline 
  15            font xascent
  16            font xdecent             negative: below baseline 
 
  new font data:
 
  offset bytes description
  0 1 glyph_cnt number of glyphs
  1 1 bbx_mode 0: proportional, 1: common height, 2: monospace, 3: multiple of 8
  2 1 bits_per_0 glyph rle parameter
  3 1 bits_per_1 glyph rle parameter
 
  4 1 bits_per_char_width glyph rle parameter
  5 1 bits_per_char_height glyph rle parameter
  6 1 bits_per_char_x glyph rle parameter
  7 1 bits_per_char_y glyph rle parameter
  8 1 bits_per_delta_x glyph rle parameter
 
  9 1 max_char_width
  10 1 max_char_height
  11 1 x offset
  12 1 y offset (descent)
  
  13 1 ascent (capital A)
  14 1 descent (lower g)
  15 1 ascent '('
  16 1 descent ')'
  
  17 1 start pos 'A' high byte
  18 1 start pos 'A' low byte
 
  19 1 start pos 'a' high byte
  20 1 start pos 'a' low byte
 
  Font build mode, 0: proportional, 1: common height, 2: monospace, 3: multiple of 8
 
  Font build mode 0:
    - "t"
    - Ref height mode: UCG_FONT_HEIGHT_MODE_TEXT, UCG_FONT_HEIGHT_MODE_XTEXT or UCG_FONT_HEIGHT_MODE_ALL
    - use in transparent mode only (does not look good in solid mode)
    - most compact format
    - different font heights possible
    
  Font build mode 1:
    - "h"
    - Ref height mode: UCG_FONT_HEIGHT_MODE_ALL
    - transparent or solid mode
    - The height of the glyphs depend on the largest glyph in the font. This means font height depends on postfix "r", "f" and "n".
 
*/
 
Редактора шрифта нет. Конвертеры есть но из .BDF или из OTF, из TTF нету. ttf2bdf тоже вменяемую не нашел. 
Напрямую .bdf с кирилицей уже наверно не найти - архаизм.
Как бы добавить к вашему редактору поддержку этой либы?
Заранее премного благодарен.
З.Ы. А фони умеет вроде ttf to bdf. Если так - то часть поблем в прошлом!

 

pavel_bbb
Offline
Зарегистрирован: 27.01.2014

Найти бы еще шрифты русские готовые в формате BDF или конвертор хороший..

DenSyo
Offline
Зарегистрирован: 13.01.2017

на странице по ссылке на скачивание есть ссылки на два хороших конвртера: FontForge и Fonty, их вполне хватит на любой случай. если нужны шрифты 8х16, то рекомендую погуглить DOS шрифты формата FNT, ссылка на моей странице к сожалению умерла, но их много в сети.
 

b707
Offline
Зарегистрирован: 26.05.2017

pavel_bbb пишет:

Найти бы еще шрифты русские готовые в формате BDF или конвертор хороший..

Русские фонты можно сделать в 2 приема.

В формате TTF - фонтов просто тысячи, в том числе и русских. Адафруитовская утилита легко конвертит их в свой формат. а потом конвертер уважаемого DenSyo - в любой другой

pavel_bbb
Offline
Зарегистрирован: 27.01.2014

b707 пишет:

Русские фонты можно сделать в 2 приема.

В формате TTF - фонтов просто тысячи, в том числе и русских. Адафруитовская утилита легко конвертит их в свой формат. а потом конвертер уважаемого DenSyo - в любой другой

Дайте пожалуйста ссылку на Адафруитовскую утилиту.

 

b707
Offline
Зарегистрирован: 26.05.2017

pavel_bbb пишет:

Дайте пожалуйста ссылку на Адафруитовскую утилиту.

 

вот тут лежат исходники и инструкция по сборке, но я где-то и в виде .exe находил, сейчас что-то не попадается

https://github.com/adafruit/Adafruit-GFX-Library/tree/master/fontconvert

и вот эта ссылка очень полезна

https://learn.adafruit.com/adafruit-gfx-graphics-library/using-fonts