Использование Freetype. Получение битового образа символов
Что прочитать перед этим материалом
В этом уроке вы подробнее познакомитесь с библиотекой Freetype, чтобы в дальнейшем использовать эти знания для рендера текста в OpenGL с ее помощью.
Скачать проект (Visual studio 2008) �
В этом проекте используется полная, статическая, “тяжелая” MT версия Freetype, собранная мной. Хотя Fretype можно собрать по модулям, я не стал этого делать. Также в проекте есть папочка to_SDK, к которой в свойствах проекта прописан путь к ней. В ней лежат заголовки (Heareds) Freetype. И если у Вас по какой-либо причине не отображаются какие-то заголовки, переместите содержимое папки в C:\Program Files\Microsoft SDKs\Windows\v6.0A\Include или поправьте свойства проекта.
Полезные ссылки:
Если говорить конкретно, то Freetype - это шрифтовый движок.
С помощью этой библиотеки можно читать файлы шрифтов, таких как TrueType fonts, OpenType fonts, BDF fonts и другие. Она позволяет извлекать битовые образы глифов, различную дополнительную информацию о шрифтах и глифах, необходимую для их правильной отрисовки.
Практически весь текст в Linux и других Unix подобных системах был считан с помощью этой библиотеки.
Кстати, сама библиотека не имеет методов для обработки и непосредственной отрисовки на экран графики.
Разберем небольшой пример использования Freetype.
В данном случае Freetype “вытягивает” пиксельный образ символа из шрифта. Пиксельный образ содержит один байт на пиксель, можно сказать, “альфа канал” - степень закраски пикселя.
Код:
/* Небольшой пример использования Freetype. */
/* Пример сделан на основе примера из документации к Freetype */
/* Отрисуем строку в текстовый файл. */
/* FreeType 2 library. */
// Подключаем Freetype
#include <ft2build.h>
#include FT_FREETYPE_H
// Подключаем стандартные классы и функции работы с файлами
#include <fstream>
// Для потоков ввода/вывода (cin, cout...)
#include <iostream>
// Для работы со строками
#include <string>
// ! Подключаем отдельные классы, чтоб не писать std::
// но и не засорять глобальное пространство имен
using std::string;
using std::wstring;
using std::cout;
using std::cin;
// ! Указатели на библиотеку и Face
FT_Library ft;
FT_Face face;
// ! Объект для работы с файлами
std::ofstream file;
int main( int argc, char** argv )
{
// ! Устанавлеваем локаль для нормальной работы с кирилицей
std::wcin.imbue(std::locale("rus_rus.866"));
string font_file_name; // путь к шритфу
wstring draw_str; // юникод текст для отрисовки
string render_to_file_name;// файл для сохранения отрисованной строки
// ! Просим путь к файлу шрифта
cout<<"Enter font file path: \n";
std::getline(std::cin, font_file_name);
// ! Инициализация библиотеки Freetype
if(FT_Init_FreeType(&ft))
{
cout<<"Could not init freetype library\n";
return 1;
}
// ! Загрузка шрифта
if(FT_New_Face(ft, font_file_name.c_str(), 0, &face))
{
// ! Не удалось загрузить
cout<<"Could not "<<font_file_name<<"\n";
return 1;
}
// ! Просим ввести текст для отрисовки
cout<<"Enter text to render: \n";
std::getline(std::wcin, draw_str);
// ! Просим ввести путь к файлу для сохранения
cout<<"Enter file to save render result: \n";
std::getline(std::cin, render_to_file_name);
// ! Открываем файл для записи (или создаем, если его нет)
file.open(render_to_file_name.c_str(), std::ios_base::out);
if(!file)
{
// ! Не удалось открыть файл
cout<<"Could open file: "<<render_to_file_name<<"\n";
return 1;
}
// ! Установка размера пикселя (специфическое понятие в Freetype)
// и обязательное для FT_Load_Glyph
FT_Set_Pixel_Sizes(face, 0, 36);
// ! Указатель на глиф
FT_GlyphSlot g = face->glyph;
// ! Цикл отрисовки образов символов из строки в файл
for(unsigned int i = 0; i < draw_str.size(); ++i)
{
// ! Пытаемся загрузить образ одного символа
// эта функция(FT_Load_Char) вызывает FT_Load_Glyph и FT_Get_Char_Index
if(FT_Load_Char(face, draw_str.at(i), FT_LOAD_RENDER))
{
// ! Не удалось загрузить битовый образ символа
cout<<"glyph not load!! \n";
continue;
}
// ! Отрисовываем образ в файл
for (int y = 0; y < g->bitmap.rows; ++y)
{
for (int i = 0; i < g->bitmap.width; ++i)
{
// ! Вытяваем значение байта образа
unsigned char c = g->bitmap.buffer[y * g->bitmap.width + i];
if(c == 0)
file<<' '; // Если ноль, записываем пробел
else if(c < 128)
file<<'+'; // Если "прозрачность" ниже 128
else
file<<'#'; // Если "прозрачность" выше 128
}
file<<'\n';
}
file<<"\n\n";
}
// ! Заставлем сбросить внутренний буфер Ofstream в файл
file.flush();
// ! Закрываем файл
file.close();
// ! Освобождаем выделенные ресурсы и библиотеку
FT_Done_Face(face);
FT_Done_FreeType(ft);
}
Здесь намеренно все происходит в Main, для простоты.

