mirror of
https://github.com/stasenso/ttf2bmp.git
synced 2026-06-26 21:42:43 +03:00
144 lines
4.9 KiB
C
144 lines
4.9 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#define STB_TRUETYPE_IMPLEMENTATION
|
|
#include "stb_truetype.h"
|
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
|
#include "stb_image_write.h"
|
|
|
|
// Функция для декодирования UTF-8 в кодовую точку Unicode
|
|
int utf8_to_unicode(const char *str, int *bytes_read) {
|
|
unsigned char c = str[0];
|
|
if (c < 0x80) {
|
|
*bytes_read = 1;
|
|
return c;
|
|
} else if ((c & 0xE0) == 0xC0) {
|
|
*bytes_read = 2;
|
|
return ((str[0] & 0x1F) << 6) | (str[1] & 0x3F);
|
|
} else if ((c & 0xF0) == 0xE0) {
|
|
*bytes_read = 3;
|
|
return ((str[0] & 0x0F) << 12) | ((str[1] & 0x3F) << 6) | (str[2] & 0x3F);
|
|
}
|
|
*bytes_read = 1;
|
|
return 0; // Некорректный символ
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
if (argc != 3) {
|
|
fprintf(stderr, "Usage: %s <font_path> <font_height>\n", argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
// Чтение файла шрифта
|
|
FILE *font_file = fopen(argv[1], "rb");
|
|
if (!font_file) {
|
|
fprintf(stderr, "Failed to open font file: %s\n", argv[1]);
|
|
return 1;
|
|
}
|
|
|
|
fseek(font_file, 0, SEEK_END);
|
|
long font_size = ftell(font_file);
|
|
fseek(font_file, 0, SEEK_SET);
|
|
unsigned char *font_data = malloc(font_size);
|
|
fread(font_data, 1, font_size, font_file);
|
|
fclose(font_file);
|
|
|
|
// Инициализация шрифта
|
|
stbtt_fontinfo font;
|
|
if (!stbtt_InitFont(&font, font_data, 0)) {
|
|
fprintf(stderr, "Failed to initialize font\n");
|
|
free(font_data);
|
|
return 1;
|
|
}
|
|
|
|
// Парсинг высоты шрифта
|
|
int font_height = atoi(argv[2]);
|
|
if (font_height <= 0) {
|
|
fprintf(stderr, "Invalid font height: %s\n", argv[2]);
|
|
free(font_data);
|
|
return 1;
|
|
}
|
|
|
|
// Набор символов (ASCII + кириллица)
|
|
const char *chars = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
|
|
"АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя";
|
|
|
|
// Подсчет кодовых точек
|
|
int char_count = 0;
|
|
for (int i = 0; chars[i]; ) {
|
|
int bytes_read;
|
|
utf8_to_unicode(&chars[i], &bytes_read);
|
|
i += bytes_read;
|
|
char_count++;
|
|
}
|
|
|
|
// Массив для хранения кодовых точек
|
|
int *codepoints = malloc(char_count * sizeof(int));
|
|
int idx = 0;
|
|
for (int i = 0; chars[i]; ) {
|
|
int bytes_read;
|
|
codepoints[idx++] = utf8_to_unicode(&chars[i], &bytes_read);
|
|
i += bytes_read;
|
|
}
|
|
|
|
// Расчет масштаба и метрик
|
|
float scale = stbtt_ScaleForPixelHeight(&font, font_height);
|
|
int ascent, descent, line_gap;
|
|
stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap);
|
|
ascent = (int)(ascent * scale);
|
|
descent = (int)(descent * scale);
|
|
|
|
// Расчет общей ширины с дополнительным отступом (20% от ширины символа)
|
|
const float spacing_factor = 1.3f; // 20% дополнительного пространства
|
|
int total_width = 0;
|
|
for (int i = 0; i < char_count; i++) {
|
|
int advance, lsb;
|
|
stbtt_GetCodepointHMetrics(&font, codepoints[i], &advance, &lsb);
|
|
total_width += (int)(advance * scale * spacing_factor);
|
|
}
|
|
|
|
// Создание битмапа
|
|
unsigned char *bitmap = calloc(total_width * font_height, 1);
|
|
if (!bitmap) {
|
|
fprintf(stderr, "Failed to allocate bitmap\n");
|
|
free(codepoints);
|
|
free(font_data);
|
|
return 1;
|
|
}
|
|
|
|
// Рендеринг каждого символа
|
|
int x_offset = 0;
|
|
for (int i = 0; i < char_count; i++) {
|
|
int w, h, xoff, yoff;
|
|
unsigned char *glyph = stbtt_GetCodepointBitmap(&font, 0, scale, codepoints[i], &w, &h, &xoff, &yoff);
|
|
|
|
// Копирование глифа в битмап
|
|
for (int y = 0; y < h; y++) {
|
|
for (int x = 0; x < w; x++) {
|
|
int bitmap_x = x_offset + x + xoff;
|
|
int bitmap_y = ascent + y + yoff;
|
|
if (bitmap_x >= 0 && bitmap_x < total_width && bitmap_y >= 0 && bitmap_y < font_height) {
|
|
bitmap[bitmap_y * total_width + bitmap_x] = glyph[y * w + x];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Обновление x_offset с учетом отступа
|
|
int advance, lsb;
|
|
stbtt_GetCodepointHMetrics(&font, codepoints[i], &advance, &lsb);
|
|
x_offset += (int)(advance * scale * spacing_factor);
|
|
|
|
stbtt_FreeBitmap(glyph, NULL);
|
|
}
|
|
|
|
// Запись BMP
|
|
if (!stbi_write_bmp("output.bmp", total_width, font_height, 1, bitmap)) {
|
|
fprintf(stderr, "Failed to write BMP file\n");
|
|
}
|
|
|
|
// Очистка
|
|
free(bitmap);
|
|
free(codepoints);
|
|
free(font_data);
|
|
return 0;
|
|
} |