Page 1 of 5

FreeType2 для Колибри (масштабируемые векторные шрифты)

Posted: Fri Feb 11, 2011 5:24 pm
by SoUrcerer
30.03.2011: Для Колибри собраны и портированы библиотеки FreeType 1.3 и FreeType 2.4.4.

Подробности, файлы и самые свежие новости - на последних страницах темы.

Выкуривание мануалов по SVG, TTF и другим полезным вещам помогло мне понять, как устроены эти самые шрифты.
Между делом были написаны программы для вывода глифов из SVG-шрифтов и конвертер из SVG в VFO (формат векторных шрифтов библиотеки vectors.obj), обе написаны кое-как и на javascript.
Сегодня взялся переносить код из JavaScript на Си (к сожалению, знаниями ассемблера, достаточными для написания библиотеки, не обладаю, но надеюсь, что кто-нибудь, да поможет...когда я отлажу код так, что он будет работать более предсказуемо, чем сейчас). Как оказалось, переносить код с JS на C - одно удовольствие, знай себе function на void заменяй...

Итак, в прикрепленных архивах:
1) Шрифт DejaVu Mono в файле fnt_1.vfo и программа для его просмотра fn.kex (на самом деле эта программа написана IgorA, я просто немножко ее исправил, чтобы она открывала большие файлы шрифтов). Если мне не изменяет память, в файле шрифта все русские и английские буквы, а так же цифры и специальные символы. Если нет, значит, в каком-то другом архиве у меня на диске они есть :mrgreen: К сожалению, контуры шрифтов отображаются не всегда правильно, плюс контуры глифов разрываются, и заливать их невозможно
dejavumono.7z (10.9 KiB)
Downloaded 431 times
2) Программа на С fonter.kex, которая выводит контур глифа @ (пока что это hardcoded) из набора DejaVu Mono. Глиф отрисовывается в памяти, и лишь затем отрисовывается на экран (хотя сделано это криво). Кривые Безье и линии строятся по правильным формулам, но для них не рассчитывается необходимое количество точек, поэтому при большом масштабе наблюдаются разрывы в линиях. Алгоритм поддерживает и заливку, но я убрал эту функцию потому, что пока что не придумал, как определять точку, к которой применять заливку контура. Для глифа @ она должна находиться внутри части глифа "а", чтобы правильно залить его. Для заливки используется обход в ширину (в алгоритме имеется один момент, который стоит улучшить).
fonter.kex (3.02 KiB)
Downloaded 424 times
Ах да, шрифты, отрисованные программой fn.kex и залитые простой заливкой, выглядят вот так:
Снимок-01.png
Снимок-01.png (7.16 KiB)
Viewed 11560 times
Вот собственно и всё пока что. Как только код будет приведен в состояние "не очень стыдно показывать", так я его сразу выложу.

upd. Так же ковыряюсь в алгоритмах сглаживания. Если немножко подумать, можно реализовать субпиксельное сглаживание. Судя по найденным материалам, это не сложно. Интересная особенность: мне кажется, что глиф гораздо лучше выглядит, если его растеризовать в памяти несколько крупнее, чем нужно, а затем уменьшить с билинейным сглаживанием.
[/hr]

Re: Масштабируемые векторные шрифты

Posted: Fri Feb 11, 2011 6:57 pm
by SoUrcerer
А вот и вариант с заливкой. Когда отрисовывается глиф большого размера, заметно мерцание (в qemu по крайней мере).
Сейчас я работаю с массивом целых чисел для заливки, и вывожу его попиксельно. Если я заменю его на область памяти RGB, и буду выводить изображение через putimage, скорость работы повысится? Или это фантастика?

Re: Масштабируемые векторные шрифты

Posted: Fri Feb 11, 2011 7:05 pm
by Mario
Sorcerer
Теоретически должно - ты исключишь кучу переключений из Ring3 в Ring0, к тому же записывать данные большим куском в видеопамять все-же выгодней.

Все зависит от того через какую функцию Колибри реализован putimage.

Re: Масштабируемые векторные шрифты

Posted: Fri Feb 11, 2011 9:19 pm
by SoUrcerer
Через 7ю...
В Virtualbox мерцание практически исчезло, а в qemu, кажется, стало еще сильнее мерцать при перерисовке.
Попробую загнать весь шрифт в память и посмотреть, что из этого получится. А за одно допилить заливку как положено (а точнее, сделать заново)

Re: Масштабируемые векторные шрифты

Posted: Fri Feb 11, 2011 11:13 pm
by SoUrcerer
А если через 65ю выводить? Может стать быстрее или нет? Прозрачность не поддерживается, как я понимаю?

Re: Масштабируемые векторные шрифты

Posted: Sat Feb 12, 2011 2:57 am
by Mario
65 функция не будет быстрее. Она просто более гибкая в использовании.
Прозрачность придется обеспечить самому. Используй ф.36 и накладывай поверх полученного свой шрифт и выводи ф.7 или ф. 65.

Re: Масштабируемые векторные шрифты

Posted: Sat Feb 12, 2011 6:12 am
by Asper
Sorcerer

Неужели у нас всё-таки будут векторные шрифты? :)

Re: Масштабируемые векторные шрифты

Posted: Sat Feb 12, 2011 12:30 pm
by DmitrySokolowsky
Запустилось (медленно), и отобразился только значок @. Как мне кажется, он довольно-таки неряшливый. Что делать, чтобы отобразилось что-то ещё?

Re: Масштабируемые векторные шрифты

Posted: Sat Feb 12, 2011 3:10 pm
by Mario
Sorcerer
Есть подозрение, что расчет значений имеет недостаточную точность - маленькие символы сливаются. Производится ли округление значений по математическим правилам или дробная часть координаты отбрасывается?

Re: Масштабируемые векторные шрифты

Posted: Sat Feb 12, 2011 7:22 pm
by SoUrcerer
Атауальпа wrote:Запустилось (медленно), и отобразился только значок @. Как мне кажется, он довольно-таки неряшливый. Что делать, чтобы отобразилось что-то ещё?
Пока что программа не выводит больше никаких символов. Все глифы TrueType и SVG-шрифтов выводятся при помощи кривых Безье первого и второго порядка, соответственно, нет никакой разницы, какой из них выводить для проверки работоспособности алгоритма (а это пока что лишь демка). Остальные символы можно посмотреть с помощью программы fn.kex из другого архива (более того, этот шрифт в принципе можно использовать в своих программах, но пока что не стоит).
Mario wrote: Есть подозрение, что расчет значений имеет недостаточную точность - маленькие символы сливаются. Производится ли округление значений по математическим правилам или дробная часть координаты отбрасывается?
Маленькие символы сливаются не из-за алгоритма рисования, а из-за алгоритма заливки - в текущем варианте он работает корректно только в том случае, если толщина самой маленькой части глифа (ширина черт в букве, грубо говоря) больше пяти пикселей. Ума не приложу, как реализовали заливку в FreeType, и попробую почитать. Округление производится правильно, проверено в том числе в JS - там глифы отрисовываются точно так же, "заборчиком" (грабельками, да).

Причина некрасивости глифов очень простая. Какие бы шрифты не были хорошие, они даже в начальном варианте моей демо-программы отрисовываются в 1/32 от оригинального глифа. Вот и получаются лесенки и заборчики вместо гладких контуров. Судя по наблюдениям за программой просмотра изображений Gnome, SVG растеризуются в разрешении, заданном в параметрах документа, а затем масштабируются с линейной интерполяцией (если она включена в параметрах). Результат выглядит лучше, чем просто вывод глифа в масштабе. Возможно, там используются еще какие-то методы сглаживания.

Что касается заливки шрифтов небольших размеров (шириной менее 20 пикселей), то в "больших" системах для этого используют хинтинг - нечто вроде отдельных начертаний для маленьких размеров. Замтетить это можно на разнице между Times 8 и 14 кегля, например. Технология патентованная, и поэтому FreeType 2 генерирует начертания небольшого кегля на лету, насколько я знаю. Как во FreeType 1 - не знаю, но мне почему-то кажется (судя по тем демкам, что я видел), что там шрифт растеризуется в большом кегле, а затем масштабируется со сглаживанием. Сейчас я эксперементирую именно с этим направлением.

Re: Масштабируемые векторные шрифты

Posted: Sat Feb 12, 2011 11:38 pm
by SoUrcerer
Почитал документацию к FreeType 1.3 и исходные коды. Много думал. Если документация к FreeType 2 настолько же подробна, но при этом завершена, то веселые выходные мне обеспечены - буду разбираться и проверять, что и как.
Оказывается, все очень просто и удобно. Во-первых, символ сразу отрисовывается с анти-алиасингом с палитрой из 5 оттенков. Так удобнее.
Во-вторых, для того, чтобы отрисовывать небольшие кегли, имеется специальный алгоритм под названием Drop Out (который в руководстве к FT 1.3 не освещен, только вдумчивое чтение кодов).
В-третьих, заливка реализуется одновременно с растеризацией методом "веника". Делается это так (если простым языком): все элементы глифа (линии и кривые Безье) разбиваются на восходящие и нисходящие. Для определенности считаем, что первая встреченная нами линия - восходящая. Все. Теперь остается лишь залить те участки, которые находятся между восходящими и нисходящими линиями. Как там насчет внутренних пустот в контурах - не разбирался, но это дело времени. Всем, кому интересна реализация хороших векторных масштабируемых шрифтов, предлагаю взглянуть на прилагаемый файл.

Почему не портировать сам freetype? Потому что, признаюсь, знаний на это у меня не хватит. Те, у кого знаний хватило бы, заняты другими, более полезными делами. А красивые буковки, чтобы клиентов не отпугивали, хочется наверное всем. Вдобавок написать свою миниатюрную библиотеку - это как минимум интересно.

*ушел учить матчасть и эксперементировать на лисах с надеждой вернуться в ближайшее время с рабочими результатами, и в случае надобности получить помощь сообщества*

Re: Масштабируемые векторные шрифты

Posted: Sun Feb 13, 2011 12:07 am
by Mario
Sorcerer wrote:А красивые буковки, чтобы клиентов не отпугивали
Вот так скажет человек не особо раздумывая и все попал в списки цитат навечно. :mrgreen:

Re: Масштабируемые векторные шрифты

Posted: Sun Feb 13, 2011 12:31 am
by SoUrcerer
Mario, просто очень уж фраза подходит к ситуации... И ничего не поделать с этим.
Для интересующихся шрифтами добавляю еще пару ссылочек. Никаких алгоритмов, только общие слова, но для тех, кто действительно заинтересован в своей реализации, этого, думаю, более чем достаточно
Drop out control: устранение потерь, которые происходят когда ширина свободного места между элементами обводки становится тоньше 1/2 пиксела
Хинтинг и пиксельная подгонка
Антиалисинг

Re: Масштабируемые векторные шрифты

Posted: Sun Feb 13, 2011 8:57 am
by SoUrcerer
Кажется, начинаю понимать. SVG шрифты, которые я использовал прежде всего, не содержат никакой информации о хинтинге, даже минимальной, позволяющей выравнивать глифы по пикселам. Поэтому отображение кеглей небольшого размера для SVG практически невозможно без "искусственного" сглаживания, которое работает медленно и дает плохой результат.
Значит, для хороших результатов желательно понять формат TrueType или OpenType. Ну или хотя бы реализовать антиалиасинг для SVG.
Разработка алгоритма в процессе.

Re: Масштабируемые векторные шрифты

Posted: Sun Feb 13, 2011 4:30 pm
by SoUrcerer
:mrgreen: Нелепая ситуация. Следуя инструкциям install.any из freetype собрал freetype.a, все делалось с мейкфайлами, аналогичными тем, которые собирают libc и другие библиотеки. По именам экспортируемых функций вроде бы все, что должно быть в библиотеке, в ней есть.
А как проверить ее работоспособность - не знаю. Прилагаемые к freetype тесты собираться отказываются (что в принципе понятно - они заточены для dos или x11, на выбор).
В общем, прилагаю то, что получилось. Если кто-то знает, как проверить, все ли собралось как положено - буду благодарен за советы. Пока что просто читаю руководство, довольно много информации, и воспринять ее правильно за несколько часов очень трудно.

upd:
Пишу простую программу для проверки того, слинкуется ли библиотека.

main.c

Code: Select all

#include <menuet/os.h>
#include <stdio.h>
#include <freetype/freetype.h>
 TT_Engine engine;
void main(void){
TT_Init_FreeType(&engine);}
Makefile

Code: Select all

OUTFILE = demo
OBJS = main.o 
LIBS = -lfreetype
include $(MENUETDEV)/makefiles/Makefile_for_program
Файл freetype.a лежит в $(MENUETDEV)/lib, make выдает:

Code: Select all

mld demo main.o  -lfreetype  -n -Map demo.map 
ld: cannot find -lfreetype
Что-то еще нужно, чтобы библиотека находилась?:(