UTFT -русификация ПРОПОРЦИОНАЛЬНЫМ шрифтом
- Войдите на сайт для отправки комментариев
Приветствую всех пользователей Arduino!
Разобраться в теме русификации вывода на TTF экраны подключенные к Arduino меня подтолкнуло бедность шрифтов с русскими символами при русификации библиотеки UTFT. В особенности то, что BigFont такой ШИРОКИЙ!
1. Результат работы.
Тем кому надо просто воспользоваться результатом этот абзац для Вас.
- скачиваем библиотеку UTFT_DLB, устанавливаем ее в каталог библиотек
https://sites.google.com/site/dlbarduino/downloads
- добавляем в папку проекта файл со шрифтом "FontRusProp18.c"
- используем следующие части кода
Объявление экрана
#include <UTFT_DLB.h>
UTFT_DLB myGLCD(CTE32_R2,38,39,40,41); // инициализация дисплея
Объявление шрифтов
extern uint8_t FontRusProp18[];
Задаем нужный шрифт
myGLCD.setFont(FontRusProp18);
Используем модифицированную функцию печати строки
RusPrintStr(myGLCD,"Ура! Работает!",0,24,0);
файл FontRusProp18.c
функция перекодировки символов и вывод на экран
Пример использования
А теперь интересное для тех, кто хочет ЗНАТЬ!
Проблемы с кодировками символов
Проблема с кодированием русских букв в компьютере. А точнее наличие разных кодировок (определенному символу в разных кодировках соответствует разное число и что еще хуже – разное количество байт в этом числе). Для тех кто хорошо ориентируется в ASCII и UNICODE просто скажу, что я для передачи на печать приводил русские символы к кодировке cp866 (ее же использовал для описания шрифтов). И им данная часть не интересна. А вот остальным советую почитать – если и не разберетесь, то хоть будете иметь представление о данной теме.
Начнем с интересного факта, что если вы объявите в программе символьные строки:
char szText1[]="123";
char szText2[]="FRG";
char szText3[]="БУД";
а затем функцией strlen(); узнаете их размер, Вы будете удивлены! Первые две имеют размер равный 3 байта. А третья – 6 байт! Среда программирования ARDUINO IDE для русских символов использует кодировку UNICODE, в которой символ описывается ДВУМЯ байтами. А для цифр и английских букв использует по 1 байту. И потом вся эта мешанина записывается в код Arduino и передается в экран для отображения.
Пример:
Символ ‘F’ храниться в текстовой строке как байт со значением 70 (0x46)
Символ ‘У’ храниться в текстовой строке как ДВА байта со значениями 208 и 163 (0xD0 и 0xA3)
И это первая проблема которую надо решить при выводе русских букв на экран. Решают ее довольно просто – пишут функцию которая заменяет два байта с кодом русского символа на один байт с кодом этого символа. На какой код менять? Я просто перевожу в код ASCII (cp866). В нем все символы кодируются 1 байтом. В рамках использования Arduino можно использовать свою таблицу соответствия. Вместо русских букв которые аналогичны по изображению английским – подставить код таких английских. Для оставшихся букв присвоить кода которые свободные. Соответственно потом в файле шрифта описать начертание символа с этим кодом. Такой подход оправдан. Он позволяет уменьшить затраты памяти на хранение шрифта. (https://грибовы.рф/?p=2240)
С приведением к виду – один символ – один байт разобрались. Двигаемся дальше.
Файл описания шрифта.
В таком файле хранится описание изображения символов. Каждому коду символа соответствует своя картинка. Именно эти данные библиотека вывода на экран использует при прорисовке символа на экране. В файле символы описываются по правилам той библиотеке которую вы используете (в нашем случае UTFT). Основной принцип (применительно для ардуино)– один бит – один пиксел на экране. Один байт – 8 пиксел. Символ размером 16х16 это 256 пиксел=256 бит= 32 байта. Если мы знаем какой пиксел какому биту в этих 32 байтах соответствует – то мы можем вносить изменения в изображения символа. При этом еще надо знать где эти 32 байта дня нашего символа расположены в массиве шрифта.
Хорошо расписано как шрифт храниться в библиотеке UTFT здесь:
http://devicter.blogspot.ru/2013/03/rusUTFT-SmallFont.html
Оба этих этапа реализованы и успешно работают. Весь комплект описан здесь:
http://adatum.ru/podklyuchenie-displeya-240x320-2-2-tft-spi-ili9340-k-ar...
Как я уже вначале писал меня не устроил набор шрифтов. Поиск в интернете привел к сайту
http://www.rinkydinkelectronics.com/r_fonts.php
куча разных шрифтов для UTFT – дописывай русские буквы и будет тебе счастье! Но анализ показал – все шрифты по ширине кратны 8 пикселям. Ширина 8-16-24-32 пикселей. Нет узких шрифтов. Есть 8х12 но он уже русифицирован. А типа 6х10 или 12х16 нет. Попытаться самому с нуля написать файл шрифта не имея образец – сомнительное удовольствие. А мне хотелось иметь шрифт узкий – чтоб больше символов влезло на экран. Да и закралось подозрение что UTFT может и не поддерживать шрифты с шириной шрифта не кратной 8.
И я отложил решение этой проблемы до лучших времен.
И вот мне попалась на глаза библиотека UTFT_DLB. Она выводит ПРОПОРЦИОНАЛЬНЫЕ шрифты. В комплекте два шрифта. Используется как надстройка над UTFT. Попробовал – полученный результат понравился. Решил – если разберусь как устроен файл шрифта – русифицирую. Оказалось что формат описания шрифта принципиально другой чем в самой UTFT (но родные шрифты тоже работают). Но разобраться не сложно – описание что и как в самом файле шрифта есть. Когда стал экспериментировать – понравилось еще больше. Формат описания шрифта очень гибкий и довольно удобный для корректировки. Я взял за основу имеющийся там шрифт «DejaVuSans18.c» и добавил изображения русских букв. Я старался сделать их покомпактней в ширину.
Преимущества и недостатки данного варианта русификации
Плюсы:
- т.к. описание каждого символа начинается с кода символа – легко найти для исправления
- описание символов в произвольном порядке и любой символ можно исключить (если не используете)– остальные не пострадают.
- без проблем можно создавать шрифты любых размеров (8*16,4*10, 7*14) причем принципиальной разницы при использовании моноширных и пропорциональных шрифтов нет. Как опишите так и отобразиться.
- отступ с верху и спереди до начала самого изображения символа задается отдельными байтами для каждого числа отдельно – легко регулировать расстояние до предыдущего и последующего символа. Причем для каждого символа в отдельности.
Минусы:
- увеличение размера массива описания шрифта (спорный вопрос) т.к. пустые байты в начале и в конце можно задать начальным смещением сверху и спереди. И это поможет экономить место. И можно описание не нужных символов безболезненно выкинуть – просто закомментировать строчку (если эти символы не используете в проекте) При этом вернуть можно в любой момент.
Кто хочет поэкспериментировать и помочь с написанием шрифтов – пишите. Подскажу если что не понятно с форматом описания шрифта и подкину заготовку в экселе - чтоб рисовать символ и сразу получать строку байт в шестнадцатеричном коде.
Продолжаю эксперименты.
Шрифт размером 5*8 пока только цифры.
Шрифт размером 5*8 пока только цифры.
Русский шрифт размером 5*8 есть здесь:
http://arduino.ru/forum/programmirovanie/rusifikatsiya-biblioteki-adafru...
sva_khv - шикарная работа.
Сколько места в итоге занимает массив шрифта? Он весь помещается во флеш?
И чего только люди не придумают, чтобы не разбираться со стандартными fontconvert.c-ами :)
Сколько места в итоге занимает массив шрифта? Он весь помещается во флеш?
Точный размер не знаю. Примерно 4 килобайта.
Русский шрифт размером 5*8 есть здесь:
http://arduino.ru/forum/programmirovanie/rusifikatsiya-biblioteki-adafru...
Да, именно шрифты из Adafruit-GFX
(использовал в дозиметре http://arduino.ru/forum/proekty/delaem-dozimetr?page=8#comment-281176 )
меня и вдохновили на эту работу (для экрана который с Adafruit-GFX не запустился).
А теперь интересное для тех, кто хочет ЗНАТЬ!
...
А вот остальным советую почитать – если и не разберетесь, то хоть будете иметь представление о данной теме.
sva_khv, если уж решили провести ликбез, то не нужно хотя бы вводить людей в заблуждение. Иначе они точно "не разберутся", да и "представления" будут иметь весьма сомнительные.
Среда программирования ARDUINO IDE для русских символов использует кодировку UNICODE, в которой символ описывается ДВУМЯ байтами.
Вы всерез считаете, что часть текста может быть представлена в одной кодировке, а часть в другой?
Кроме некоторых уж очень экзотических случаев текст всегда представлен в одной кодировке. В частности, Arduino IDE использует UTF-8. Другими словами, не только русские, но также и латинские, и даже, страшно сказать, цифры и знаки препинания - все кодируются в Unicode.
Если же под Unicode Вы подразумеваете исключительно UTF-16, то должен Вас разочаровать, ни у одного кириллического символа кодировка в UTF-8 и UTF-16 (вне зависимости от того, UTF-16LE или UTF-16BE) не совпадает.
И, кстати, в Unicode символ далеко не всегда описывается ДВУМЯ байтами: на самом деле от одного до шести. Хотя конкретно кириллица - в UTF-8 и UTF-16, действительно, - двумя (но в UTF-32 - четырьмя).
Все эти тонкости, конечно, излагать не было необходимости, но следовало бы указать, что в Arduino IDE используется UTF-8, в которой разные символы кодируются различным количеством байтов.
[quote=andriano]
ыva_khv, если уж решили провести ликбез, то не нужно хотя бы вводить людей в заблуждение. Иначе они точно "не разберутся", да и "представления" будут иметь весьма сомнительные.
Спасибо за поправики. Теорию я так глубоко не копал. Век живи - век учись.
Плохо что использовали цитирование - нельзя исправить мое сообщение.
Или есть способы? - может модераторы от своего имени вставят ссылку на Ваше уточнение. Замечание действительно важное.
Мелкий шрифт FontRusProp10.c
Высота (полная) 10, основные знаки - высота 8,
Ширина от 4 до 8
Использование описано ранее
Со шрифтом FontRusProp18 не работает:
CENTER - печатает от центра строки и далее вправо, а не как в UTFT центрирует строку.
RIGHT - выводит строку слева с потерей половины строки.
LEFT - работает.
С родными шрифтами UTFT такого не происходит.
Похоже, UTFT_DLB ДЛБ и писал :-)
На фото первая строка - стандартный шрифт UTFT
Ниже - CENTER, RIGHT, LEFT шрифт FontRusProp18.
RIGHT должно быть пять слов, выведено два с половиной, и в последнем слове нет последней буквы,
остальное и так понятно.
Со шрифтом FontRusProp18 не работает:
CENTER - печатает от центра строки и далее вправо, а не как в UTFT центрирует строку.
RIGHT - выводит строку слева с потерей половины строки.
LEFT - работает.
С родными шрифтами UTFT такого не происходит.
Совершенно верно подмечены ограничения.
Это связано с тем что у пропорционального шрифта нет ФИКСИРОВАНОЙ ширины символа и расчет длины строки дело муторное. Конечно это можно сделать - но кто бы этим занялся. Так что что имеем, то и мучаем.
А технически это ограничение связано с тем что в модифицированых шрифтах в параметрах ширина символа указана равная нулю. И как следствие длина строки при стандартном расчете тоже нулевая и получается такое размещение строки на экране как на фото.
Совершенно верно подмечены ограничения.
....
Жаль. Шрифт вроде простенький, но довольно симпатичный, и, главное, убористый,
в отличие от штатных шрифтов UTFT.
Но пользоваться можно, далеко не всегда нужны эти CENTER и прочие LEFT RIGHT,
а место на экране такие шрифты здорово экономят.
В Adafruit GFX со шрифтами получше, но есть свои ограничения, так что приходится выбирать.
...расчет длины строки дело муторное. Конечно это можно сделать - но кто бы этим занялся.
Жаль...
Вот-вот.
Заниматься никто не хочет - остается только жалеть.
Хотя просуммировать горизонтальные размеры символов в строке - не так уж и сложно. Более того, насколько я понял (извините, не пользуюсь стандартными библиотеками, поэтому наверняка не знаю), и процедура суммирования то есть, осталось лишь тупо прописать ширину символов в нужное место (я так думаю, что если бы действительно ширины символов были прописано как 0, то вывод на экран не мог бы нормально работать). Но всем лень.
А технически это ограничение связано с тем что в модифицированых шрифтах в параметрах ширина символа указана равная нулю. И как следствие длина строки при стандартном расчете тоже нулевая и получается такое размещение строки на экране как на фото.
ПОка писал предыдущий ответ, пришел к выводу, что это невозможно. Если бы ширина символов нигде не была бы прописана, процедура вывода на экран не смогла бы работать. И не было бы на экране никакого пропорционального шрифта. Значит - она есть. Возможно, в виде адресов начала для каждого символа. Отсюда два варианта:
- либо подкорректировать функцию подсчета ширины строки, чтобы она брала данные не из отдельного массива, а какие есть,
- либо написать функцию, заполняющую массив ширин символов по имеющимся данным.
...два варианта:
- либо подкорректировать функцию подсчета ширины строки, чтобы она брала данные не из отдельного массива, а какие есть,
- либо написать функцию, заполняющую массив ширин символов по имеющимся данным.
[/quote]
Ну тут я не великий специалист, скорее чайник, хоть и со свистком.
Нашёл еще один неприятный момент: не работают printNumI и printNumF - просто ничего не выводится.
Это будет похуже неработающих CENTER и RIGHT - вывод чисел очень часто нужен.
Можно, конечно, на кривой козе объехать, но нафига это надо?
А технически это ограничение связано с тем что в модифицированых шрифтах в параметрах ширина символа указана равная нулю. И как следствие длина строки при стандартном расчете тоже нулевая и получается такое размещение строки на экране как на фото.
ПОка писал предыдущий ответ, пришел к выводу, что это невозможно. Если бы ширина символов нигде не была бы прописана, процедура вывода на экран не смогла бы работать.
Правильно рассуждаете. В моноширном (родном) шрифте ширина символа задается ОДИН раз в описании шрифта.
В файле описания модифицированого шрифта (в данном конкретном случае) для указания что он не моноширный (не стандартный) это значение задется равное 0. А в описании КАЖДОГО символа есть данные о его ширине. Это все можно увидеть в файле шрифта который я выложил в начале темы. Даже часть коментариев по русски написал, чтоб самому не запутаться.
А насчет что часть функций не работает. Жаль конечно. Но я этой темой занялся что бы решить СВОЮ конкретную проблему (размещеения максимум текстовой информации на экране). Я ее решил. Меня имеющийся функционал устраивает боле чем. Народ мучает и находит косяки - молодцы, другие меньше мучаться будут.
Кто захочет дальше модифицировать/дополнять функционал - спрашивайте, поясню в чем сам разобрался.
Нашёл еще один неприятный момент: не работают printNumI и printNumF - просто ничего не выводится.
Можно, конечно, на кривой козе объехать, но нафига это надо?
Мое личное мнение - правильнее все же в программе переводить числа в строку и потом стоку выводить на экран. Не зависишь от реализации библиотек вывода и контролируешь формат преобразования. Особенно актуально для float. Согласен что при выводе в монитор последовательного порта удобнее не заморачиваться и пихать все как есть. Пусть само конвертирует.
Нашёл еще один неприятный момент: не работают printNumI и printNumF - просто ничего не выводится.
Можно, конечно, на кривой козе объехать, но нафига это надо?
Мое личное мнение - правильнее все же в программе переводить числа в строку и потом стоку выводить на экран. Не зависишь от реализации библиотек вывода и контролируешь формат преобразования. Особенно актуально для float. Согласен что при выводе в монитор последовательного порта удобнее не заморачиваться и пихать все как есть. Пусть само конвертирует.
Всё это хорошо, если бы не одно НО:
вот кусочек кода для рисования цифр 1-5 на кнопках тачскрина (int x; объявлено заранее, принимает
значения 0-4):
String b = String(x+1);
myGLCD.print(b, 18+(x*40), 18);
UTFT_DLB при компиляции выдаёт "НИЗЗЯ":
no matching function for call to 'UTFT_DLB::print(String&, int, int)'
UTFT выводит всё как положено, да и не нужно это, вполне себе работает стандартное
myGLCD.printNumI(x+1, 18+(x*40), 18);
В порт мне не надо данные гнать, на экран выводить надо.
Можно, конечно, тупо прописать для каждой кнопки отдельно, но там в цикле
ещё и сами кнопки рисуются - всё за один раз - и рисование, и вычисление координат, и надписи.
Ну и память, которой и так негусто, каждая лишняя библиотека отъедает.
Всё это хорошо, если бы не одно НО:
вот кусочек кода для рисования цифр 1-5 на кнопках тачскрина (int x; объявлено заранее, принимает
значения 0-4):
String b = String(x+1);
myGLCD.print(b, 18+(x*40), 18);
UTFT_DLB при компиляции выдаёт "НИЗЗЯ":
no matching function for call to 'UTFT_DLB::print(String&, int, int)'
UTFT выводит всё как положено, да и не нужно это, вполне себе работает стандартное
Попытайтесь myGLCD.print(b.c_str(), 18+(x*40), 18);
(это - из общих соображений, сам я ни той, ни другой библиотекой не пользуюсь)
Попытайтесь myGLCD.print(b.c_str(), 18+(x*40), 18);
(это - из общих соображений, сам я ни той, ни другой библиотекой не пользуюсь)
Спасибо, работает, как int так и float. Век живи - век учись.
Но всё это (+доп. библиотека, переводы типов данных и т.д.) занимают изрядный кусок памяти - около 28К
При использовании только UTFT - 24К, причём без куска собственно вычислений, только вывод на экран.
Кто хочет поэкспериментировать и помочь с написанием шрифтов – пишите. Подскажу если что не понятно с форматом описания шрифта и подкину заготовку в экселе - чтоб рисовать символ и сразу получать строку байт в шестнадцатеричном коде.
Приветствую! Спасибо за вашу работу. Заготовочкой можете поделиться? Я хочу поэкспериментировать ))
Но всё это (+доп. библиотека, переводы типов данных и т.д.) занимают изрядный кусок памяти - около 28К
При использовании только UTFT - 24К, причём без куска собственно вычислений, только вывод на экран.
UTFT тяжёлая библиотека, просится Мега.
Хоть убейте, не пойму как строится матрица символа UTFT_DLB. Может кто-нибудь пояснить?
Спасибо за ответ.
Да, с символом шириной 8 понятно. Неудачный я пример привел. Вот, например, символ "Ж" имеет размер 20*14.
Еще интереснее, восклицательный знак. Размер у него 2*13
Здравствуйте. Подскажите пожалуйста библиотеку для больших русских шрифтов. BigRusFont - маловаты
Спасибо Вам. Может у Вас есть уже готовый такой шрифт больше чем BigRusFont??
я начал делать, но из-за работы пока приостановил, не хватает времени :(
Отблагодарю Вас если поможете сделать большой шрифт наподобии
Arial_round_16x24
или
Calibri24x32GR
от сюда http://www.rinkydinkelectronics.com/r_fonts.php
как-то бы связаться вне форума, чтобы тему не захламлять
можете мне написать на почту pavts80@mail.ru
да, написал. вы уже разобрались в структуре данного шрифта?
Структура ясна в общем, но более детально нет опыта переделывать.
Года 4 назад когда нужен был русский шрифт в библиотеке UTFT я просто латинские символы перерисовал на русские, и писал латинскими, но выдавала русский шрифт. Не очень удобно.
Здравствуйте. Подскажите пожалуйста библиотеку для больших русских шрифтов. BigRusFont - маловаты
в Adafruit_GFX можно создавать свои шрифты любого размера из TTF фонтов, например фонтов из комплекта Винды
да, написал. вы уже разобрались в структуре данного шрифта?
так вроде в сообщениях #34 #36 negavoid все подробно обьяснил
да, я знаю. потому и спросил человека, разобрался он или нет. ведь все равно вопрос задает про большой шрифт.
я начал программу писать, которая может с любого ттф шрифта выдать формат по сабжу, с нужным размером. осталось-то не много допилить, да руки не доходят
я начал программу писать, которая может с любого ттф шрифта выдать формат по сабжу, с нужным размером. осталось-то не много допилить, да руки не доходят
через Адафруит fontconvert ?
нет. свое, для UTFT_DLB. Приглянулась мне почему-то эта надстройка UTFT. Рекомендуете лучше использовать Адафруит?
нет. свое, для UTFT_DLB.
я и имел в виду UTFT_DLB. Просто у Адафруита уже есть программа, которая из любого TTF шрифта делает их фонт. А форматы фонтов Адафруит и UTFT_DLB. очень похожи, там буквально один-два байта поменять надо.
А вы что, начали писать конвертер TTF с чистого листа? интересно было бы посмотреть, если код не секретный