4 #include "client/client.h"
5 #include "client/font.h"
6 #include "client/texture.h"
16 static FT_Library font_library;
17 static FT_Face font_face;
18 static Character font_chars[NUM_CHARS];
19 static GLfloat font_height;
23 v2f32 textureCoordinates;
24 } __attribute__((packed)) FontVertex;
25 static VertexLayout font_vertex_layout = {
26 .attributes = (VertexAttribute[]) {
27 {GL_FLOAT, 2, sizeof(v2f32)}, // position
28 {GL_FLOAT, 2, sizeof(v2f32)}, // textureCoordinates
31 .size = sizeof(FontVertex),
36 if (FT_Init_FreeType(&font_library)) {
37 fprintf(stderr, "[error] failed to initialize Freetype\n");
41 if (FT_New_Face(font_library, RESSOURCE_PATH "fonts/Minecraftia.ttf", 0, &font_face)) {
42 fprintf(stderr, "[error] failed to load Minecraftia.ttf\n");
46 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
47 FT_Set_Pixel_Sizes(font_face, 0, 16);
49 for (unsigned char c = 0; c < NUM_CHARS; c++) {
50 if (FT_Load_Char(font_face, c, FT_LOAD_RENDER)) {
51 fprintf(stderr, "[warning] failed to load glyph %c\n", c);
52 font_chars[c].texture.txo = 0;
56 font_chars[c].texture.width = font_face->glyph->bitmap.width;
57 font_chars[c].texture.height = font_face->glyph->bitmap.rows;
58 texture_upload(&font_chars[c].texture, font_face->glyph->bitmap.buffer, GL_RED, false);
60 font_chars[c].bearing = (v2s32) {font_face->glyph->bitmap_left, font_face->glyph->bitmap_top};
61 font_chars[c].advance = font_face->glyph->advance.x;
64 font_height = font_chars['|'].texture.height;
66 FT_Done_Face(font_face);
67 FT_Done_FreeType(font_library);
74 for (unsigned char c = 0; c < NUM_CHARS; c++)
75 texture_destroy(&font_chars[c].texture);
78 Font *font_create(const char *text)
80 Font *font = malloc(sizeof *font);
82 font->count = strlen(text);
83 font->meshes = malloc(font->count * sizeof *font->meshes);
84 font->textures = malloc(font->count * sizeof *font->textures);
86 GLfloat offset = 0.0f;
88 for (size_t i = 0; i < font->count; i++) {
89 unsigned char c = text[i];
91 if (c >= NUM_CHARS || !font_chars[c].texture.txo)
94 Character *ch = &font_chars[c];
96 GLfloat width = ch->texture.width;
97 GLfloat height = ch->texture.height;
99 GLfloat x = ch->bearing.x + offset;
100 GLfloat y = font_height - ch->bearing.y;
103 // selling this as NFT starting price is 10 BTC
104 font->meshes[i].data = (FontVertex[]) {
105 {{x, y }, {0.0f, 0.0f}},
106 {{x, y + height}, {0.0f, 1.0f}},
107 {{x + width, y + height}, {1.0f, 1.0f}},
108 {{x, y }, {0.0f, 0.0f}},
109 {{x + width, y + height}, {1.0f, 1.0f}},
110 {{x + width, y }, {1.0f, 0.0f}},
112 font->meshes[i].count = 6;
113 font->meshes[i].layout = &font_vertex_layout;
114 font->meshes[i].vao = font->meshes[i].vbo = 0;
115 font->meshes[i].free_data = false;
116 mesh_upload(&font->meshes[i]);
118 font->textures[i] = ch->texture.txo;
120 offset += ch->advance >> 6;
123 font->size = (v2f32) {offset, font_height};
128 void font_delete(Font *font)
130 for (size_t i = 0; i < font->count; i++)
131 mesh_destroy(&font->meshes[i]);
134 free(font->textures);
138 void font_render(Font *font)
140 for (size_t i = 0; i < font->count; i++) {
141 glBindTextureUnit(0, font->textures[i]);
142 mesh_render(&font->meshes[i]);