Использование библиотеки FreeType для растеризации символов

Всем поклонникам OpenSource приложений известна библиотека растеризации шрифтов FreeType. Ее используют практически все графические приложения под GNU/Linux. Попробуем и мы освоить этот несложный навык.

Сперва про используемые типы:

  • FT_Library — представляет собой структуру для иницизации библиотеки
  • FT_Face — шрифт, который загружается при помощи FT_Library
  • FT_Glyph — глиф шрифта, который создается при помощи FT_Face

Таким образом, для отображения символа нам надо создать объект типа FT_Library, затем загрузить шрифт в объект типа FT_Face, после этого рисовать символы при помощи FT_Glyph.

Символ из шрифта можно извлечь двумя способами:

  1. Получить информацию для его рисования кривыми
  2. Получить готовое изображение

Первый способ нам неинтересен, будем использовать сразу второй. Поехали (проверка ошибок убрана для упрощения кода):

#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» — примерно середина высоты)
  • межстрочный интервал (если вы хотите вывести многострочный текст)
  • кернинг (расстояние между различными буквами)

Подробнее об этом в следующей части.

Выводим текст в OpenGL ES 2.0

Перед каждый разработчиком, если он пишет приложение графическое на своём движке, рано или поздно встаёт вопрос: каким образом вывести текст. Я напомню, что OpenGL(ES) умеет только рисовать треугольники и накладывать на них текстуру.

Таким образом, учитывая доступные средства, вывести текст можно несколькими способами:

  • статическая текстура с готовыми надписями и текстурные координаты каждой надписи (два треугольника на надпись)
  • статическая текстура с символами и текстурные координаты каждого символа (два треугольника на символ)
  • динамическая текстура с символами и файл шрифта (два треугольника на символ)

Статическая текстура с готовыми надписями и текстурные координаты каждой надписи

Все надписи, которые встречаются в игре, рисуются заранее в текстуру. Такой вариант самый быстрый и простой в реализации для программиста. Фактически, вам надо взять текстуру и ее нарисовать (надеюсь вы это уже умеете).
Раскрывает полный простор для творчества, можно рисовать любую надпись, любым стилем и цветом.
Для оптимизации можно все надписи поместить в одну текстуру и рисовать все надписи на экране в один проход. При локализации необходимо рисовать другую текстуру с переведенным текстом.

Плюс/минусы:
+ самый быстрый вариант по скорости работы
+ всю работу за вас делает художник
+ надпись в любом стиле
− медленная локализация
− тратит много памяти
− статическая надпись

Статическая текстура с символами и текстурные координаты каждого символа

Для реализации этого способа необходимо каким-то образом сгенерировать текстурный атлас с каждым символом из шрифта.
Самый медленный в реализации способ из предложенных, зато каждый символ может быть нарисован в любом стиле. Но помните, что для каждого языка придётся заново рисовать каждый символ в выбранном вами стиле.

Плюсы/минусы:
+ относительно быстрая локализация (сгенерировать новую текстуру для языка)
+ шрифт в любом стиле
+ динамическое изменение надписи
− необходимо написать генератор этих текстур
− локализация увеличивает размер приложения

Динамическая текстура и файл шрифта

Фактически этот вариант представляет собой второй способ, но вместо текстуры с символами, используется файл шрифта (например ttf), где все эти символы описаны в векторном формате. В этом случае вместо мегабайтных текстур вам необходимо хранить один файл шрифта размером в десятки, максимум сотни, килобайт.

Текстуру можно создавать двумя способами: заполнить её всеми используемыми символами (26 — латинский алфавит, 33 — кириллица) или добавлять символ только тогда, когда он понадобится. Уже сложившейся традицией для генерации символа из шрифта является использование библиотеки FreeType.

Плюсы/минусы:
+ самая быстрая локализация
+ динамическое изменение надписи
+ самый маленький размер
− шрифт в одном стиле

Про работу с FreeType (+пример) можно почитать в моем следующем посте: «Использование библиотеки FreeType для растеризации символов».

Музей LEGO в Петербурге

Посетили в выходные музей LEGO на Вознесенском 44-46. Стоимость билета 300 рублей для взрослых, детям до трёх лет — бесплатно.

Что можно сказать по результатам посещения — отличное место!

Самолет. Музей LEGO

Рекомендую обязательно посетить вместе с детьми.

Звездные войны. Музей LEGO

В экспозициях спрятаны фигурки разбойника в белой шляпе и маске на лице. За десять найденных фигурок дают значок. Всего таких фигурок в музее пятнадцать. Нашедшему всех дают ещё один подарок.

Зимний дворец. Музей LEGO

По залу носятся дети и периодически слышны возгласы: «Мы нашли семь!», «Осталось пять!», «Вот-вот, смотри!».

Мотоциклы. Музей LEGO

Мы нашли всех и каждого сфотографировали, но я вам ничего не покажу, чтобы не испортить сюрприз. Дам только подсказку: фигурки есть в каждом стенде, кроме одного. Этого стенда, кстати, на моих фотографиях нет.

Пушка. Музей LEGO

Ещё в музее есть специальный игровой уголок с кучей деталек, где каждый ребёнок может собрать что угодно.

Тысячелетний сокол. Музей LEGO

Приходите, не пожалеете!

Кран. Музей LEGO

Если вам понравилась запись, читайте также про посещение гранд макета России.

Как перевести бабушку через КАД

crossy-road КАД опасное для пешеходов место, поэтому тренироваться в этом нелёгком деле лучше на симуляторе.

Представляю вашему вниманию игру Crossy Road. Задача игры — перевести кубического персонажа а-ля Minecraft через шоссе, реку и железную дорогу.

Установил я эту игру давно, а вот запустил только после восторженных отзывов коллеги (привет, Юра!).

На выбор доступны: Франкенштейн, собака, улитка и ещё куча разных существ. У многих есть своя фишка: кит-хипстер фоткает, корова-тусовщица танцует, дохлая рыбка делает шлёп-шлёп, а ржавый робот искрит. В общем, качайте — не пожалеете. К разработчикам игры не имею отношения, а жаль. (:

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

Для нетерпеливых и состоятельных пацанов есть возможность купить персонажа сразу за 50 настоящих рублей.

Ссылки на игру: для Android, для iOS.

Ресторан компании Lucky Pizza на 2-й красноармейской

Не так давно компания Lucky Pizza открыла свой первый ресторан на 2-й красноармейской, 3. Эта компания известна в Петербурге заказами доставки пиццы по телефону и через интернет.

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

Минусов всего два: чайник чая на троих слишком маленький, особенно учитывая размер кружек для чая. Пришлось попросить долить кипяточка. Второе — в меню очень мелкий шрифт. Мне, в принципе, все равно. А вот людям со слабым зрением тяжело прочитать эти буковки даже в очках.

В плюсах все остальное: заказали рис с мидиями, пиццу террияки и пиццу с морепродуктами. Все понравилось, все вкусно. Очень приятная атмосфера.

Главное не знание, а умение

P.S. Я понимаю, что ресторан открыли недавно, но дайте больше рекламы! Вывеска с надписью «Кафе» и дверь без обозначений это как-то неспортивно!

Личный блог Евгения Жирнова