Добро пожаловать в первую часть «Современного рендеринга текста в Linux». В каждой статье из этой серии мы разработаем самодостаточную программу на C для визуализации символа или последовательности символов. Каждая из этих программ будет реализовывать функцию, которую я считаю необходимой для современного рендеринга текста.
В первой части настроим FreeType и напишем простой рендерер символов в консоли.
Вот что мы будем писать. А вот и код.
Ubuntu 18.04.2 LTS (bionic)
clang version 6.0.0-1ubuntu2
$ sudo apt install libfreetype6 libfreetype6-dev
$ sudo apt install libpng16-16 libpng-dev
2.8.1-2ubuntu2
, хотя на момент написания статьи последняя версия FreeType-2.10.1
, она тоже подходит.(1.6.34-1ubuntu0.18.04.2)
main.c
в моём случае)#include <stdio.h>
int main() {
printf("Hello, world\n");
return 0;
}
$ clang -Wall -Werror -o main main.c
$ ./main
Hello, world
#include
) для FreeType запускаем:$ pkg-config --cflags freetype2
-I/usr/include/freetype2 -I/usr/include/libpng16
-I/usr/include/freetype2 -I/usr/include/libpng16
содержит флаги компиляции, необходимые для подключения FreeType в программу C.#include <stdio.h>
#include <freetype2/ft2build.h>
#include FT_FREETYPE_H
int main() {
printf("Hello, world\n");
return 0;
}
$ clang -I/usr/include/freetype2 -I/usr/include/libpng16 -Wall -Werror -o main main.c
$ ./main
Hello, world
main()
инициализируем FreeType с помощью FT_Init_FreeType(&ft)
и проверяем наличие ошибок (функции FreeType возвращают 0 при успешном выполнении).FT_Library ft;
FT_Error err = FT_Init_FreeType(&ft);
if (err != 0) {
printf("Failed to initialize FreeType\n");
exit(EXIT_FAILURE);
}
FT_Int major, minor, patch;
FT_Library_Version(ft, &major, &minor, &patch);
printf("FreeType's version is %d.%d.%d\n", major, minor, patch);
/tmp/main-d41304.o: In function `main':
main.c:(.text+0x14): undefined reference to `FT_Init_FreeType'
main.c:(.text+0x54): undefined reference to `FT_Library_Version'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
-lfreetype
.$ clang -I/usr/include/freetype2 -I/usr/include/libpng16 -Wall -Werror -o main -lfreetype main.c
$ ./main
FreeType's version is 2.8.1
FT_Face face;
err = FT_New_Face(ft, "./UbuntuMono.ttf", 0, &face);
if (err != 0) {
printf("Failed to load face\n");
exit(EXIT_FAILURE);
}
err = FT_Set_Pixel_Sizes(face, 0, 32);
if (err != 0) {
printf("Failed to set pixel size\n");
exit(EXIT_FAILURE);
}
char
, а глиф — это образ, который каким-то образом связан с этим символом. Это отношение довольно сложное, потому что char может соответствовать нескольким глифам: т. е. акцентам. А глиф может соответствовать многим символам: т. е. лигатурам, где -> представляется как одно изображение.FT_Get_Char_Index
. Как вы можете понять, это предусматривает сопоставление символов и глифов только один к одному. В будущей статье из этой серии мы решим проблему с помощью библиотеки HarfBuzz. FT_UInt glyph_index = FT_Get_Char_Index(face, 'a');
FT_Int32 load_flags = FT_LOAD_DEFAULT;
err = FT_Load_Glyph(face, glyph_index, load_flags);
if (err != 0) {
printf("Failed to load glyph\n");
exit(EXIT_FAILURE);
}
face->glyph
.FT_Int32 render_flags = FT_RENDER_MODE_NORMAL;
err = FT_Render_Glyph(face->glyph, render_flags);
if (err != 0) {
printf("Failed to render the glyph\n");
exit(EXIT_FAILURE);
}
face->glyph->bitmap.buffer
, где оно представлено в виде массива беззнаковых значений char, поэтому его значения находятся в диапазоне от 0 до 255.column * row_width + row
, как в bitmap.buffer[i * face->glyph->bitmap.pitch + j]
.bitmap.width
в цикле и bitmap.pitch
, потому что длина каждой строки пикселей равна bitmap.width
, но «ширина» буфера составляет bitmap.pitch
.for (size_t i = 0; i < face->glyph->bitmap.rows; i++) {
for (size_t j = 0; j < face->glyph->bitmap.width; j++) {
unsigned char pixel_brightness =
face->glyph->bitmap.buffer[i * face->glyph->bitmap.pitch + j];
if (pixel_brightness > 169) {
printf("*");
} else if (pixel_brightness > 84) {
printf(".");
} else {
printf(" ");
}
}
printf("\n");
}
$ clang -I/usr/include/freetype2 -I/usr/include/libpng16 -Wall -Werror -o main -lfreetype main.c && ./main
FreeType's version is 2.8.1
.*****.
.********.
.*********
. ***.
***
***
.********
***********
.**. ***
*** ***
*** ***
***. ***
.***********
***********
.*******..
К сожалению, не доступен сервер mySQL