Всем поклонникам OpenSource приложений известна библиотека растеризации шрифтов FreeType. Ее используют практически все графические приложения под GNU/Linux. Попробуем и мы освоить этот несложный навык.
Сперва про используемые типы:
FT_Library
— представляет собой структуру для иницизации библиотекиFT_Face
— шрифт, который загружается при помощиFT_Library
FT_Glyph
— глиф шрифта, который создается при помощиFT_Face
Таким образом, для отображения символа нам надо создать объект типа FT_Library
, затем загрузить шрифт в объект типа FT_Face
, после этого рисовать символы при помощи FT_Glyph
.
Символ из шрифта можно извлечь двумя способами:
- Получить информацию для его рисования кривыми
- Получить готовое изображение
Первый способ нам неинтересен, будем использовать сразу второй. Поехали (проверка ошибок убрана для упрощения кода):
#include <ft2build.h> #include FT_FREETYPE_H int main() { // Библиотека FreeType FT_Library library = 0; // Инициализация библиотеки FT_Init_FreeType(&library); // Шрифт FT_Face face = 0; // Загрузка шрифта FT_New_Face(library, "tahoma.ttf", 0, &face); // Установка размера пикселя FT_Set_Pixel_Sizes(face, 24, 12); // Код символа (юникод) const FT_ULong charCode = L'W'; // Загрузка глифа из шрифта с его отрисовкой FT_Load_Char(face, charCode, FT_LOAD_RENDER); // Получение готового к использованию глифа FT_GlyphSlot glyph = face->glyph; // Получение размеров глифа const int width = glyph->bitmap.width; const int height = glyph->bitmap.rows; const int pitch = glyph->bitmap.pitch; // Вывод символа в консоли for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { // Получение прозрачности точки (x, y) const int a = glyph->bitmap.buffer[y * pitch + x]; if (a > 127) { printf("*"); } else { printf(" "); } } printf("\n"); } // Удаление шрифта FT_Done_Face(face); face = 0; // Удаление библиотеки FT_Done_FreeType(library); library = 0; } |
Консоль:
** *** *** ** **** ** ** **** *** ** ** ** ** ** * ** *** ** ** ** ** ** * * *** **** **** *** *** |
Отличная работа, но для вывода слова из нескольких букв простого изображения символа недостаточно. Необходимо иметь следующую информацию:
- положение горизонтальной базовой линии (например, «W» — внизу, «y» — примерно середина высоты)
- межстрочный интервал (если вы хотите вывести многострочный текст)
- кернинг (расстояние между различными буквами)
Подробнее об этом в следующей части.
Вместо ‘W’ хочу букву ‘Я’!
Используйте юникод для этих целей. Извините за столь долгий ответ.
Здравствуйте!
Подскажите пожалуйста, как извлечь символ из шрифта первым способом.
Никогда не возникало такой необходимости, поэтому не знаю об этом ничего даже в теории. В интернете с ходу нашёл два примера, попробуйте их изучить:
https://www.freetype.org/freetype2/docs/tutorial/example2.cpp
https://www.freetype.org/freetype2/docs/tutorial/example5.cpp
Код компилируется, но готовая программа при запуске останавливается с ошибкой. Ошибка где-то в FT_Load_Char(face, charCode, FT_LOAD_RENDER);
Шрифт «tahoma.ttf» лежит рядом с исполняемым файлом?
Спасибо автору за статью.
У меня возникла проблема: библиотеку freetype я собираю из исходников, используя makefile которые присутствуют в freetype.
Но как мне использовать ее в моем проекте? При компиляции MinGW выдает ошибку:
После компиляции библиотеки у вас, скорее всего, получается файл libfreetype2.a (статическая линковка) или libfreetype2.so (динамическая). Вам необходимо при компиляции своего проекта указать этот файл для линковки. Смотрите флаги компилятора «-l» и/или «-L».
Да, после компиляции получается статическая библиотека freetype.a
Вот мой Makefile. Разве из lib не должны подтянуться библиотеки?
Они бы с радостью подтянулись, но необходимо указать какие, компилятор не умеет угадывать )
Попробуйте прописать libfreetype2.a в переменную LIBRARIES.
Спасибо за помощь.
Все собралось, когда в переменную LIBRARIES я добавил lib/freetype.a
Уважаемый автор, имеется еще вопрос к вам.
В данной статье вы получаете глиф растром (с заливкой) — FT_Load_Char(face, charCode, FT_LOAD_RENDER);
Скажите, как можно получить координаты контрольных точек глифа, вписанного в область заданной высоты, чтобы ширина данной области изменялась автоматически, пропорционально заданной высоте?
Никогда такого не требовалось, так что ничем помочь не могу, увы…