4 #include "client/client.h"
5 #include "client/font.h"
6 #include "client/gl_debug.h"
7 #include "client/texture.h"
17 static FT_Library font_library;
18 static FT_Face font_face;
19 static Character font_chars[NUM_CHARS];
20 static GLfloat font_height;
24 v2f32 textureCoordinates;
25 } __attribute__((packed)) FontVertex;
26 static VertexLayout font_vertex_layout = {
27 .attributes = (VertexAttribute[]) {
28 {GL_FLOAT, 2, sizeof(v2f32)}, // position
29 {GL_FLOAT, 2, sizeof(v2f32)}, // textureCoordinates
32 .size = sizeof(FontVertex),
37 if (FT_Init_FreeType(&font_library)) {
38 fprintf(stderr, "[error] failed to initialize Freetype\n");
42 if (FT_New_Face(font_library, RESSOURCE_PATH "fonts/Minecraftia.ttf", 0, &font_face)) {
43 fprintf(stderr, "[error] failed to load Minecraftia.ttf\n");
47 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); GL_DEBUG
48 FT_Set_Pixel_Sizes(font_face, 0, 16);
50 for (unsigned char c = 0; c < NUM_CHARS; c++) {
51 if (FT_Load_Char(font_face, c, FT_LOAD_RENDER)) {
52 fprintf(stderr, "[warning] failed to load glyph %c\n", c);
53 font_chars[c].texture.txo = 0;
57 font_chars[c].texture.width = font_face->glyph->bitmap.width;
58 font_chars[c].texture.height = font_face->glyph->bitmap.rows;
59 texture_upload(&font_chars[c].texture, font_face->glyph->bitmap.buffer, GL_RED, false);
61 font_chars[c].bearing = (v2s32) {font_face->glyph->bitmap_left, font_face->glyph->bitmap_top};
62 font_chars[c].advance = font_face->glyph->advance.x;
65 font_height = font_chars['|'].texture.height;
67 FT_Done_Face(font_face);
68 FT_Done_FreeType(font_library);
75 for (unsigned char c = 0; c < NUM_CHARS; c++)
76 texture_destroy(&font_chars[c].texture);
79 Font *font_create(const char *text)
81 Font *font = malloc(sizeof *font);
83 font->count = strlen(text);
84 font->meshes = malloc(font->count * sizeof *font->meshes);
85 font->textures = malloc(font->count * sizeof *font->textures);
87 GLfloat offset = 0.0f;
89 for (size_t i = 0; i < font->count; i++) {
90 unsigned char c = text[i];
92 if (c >= NUM_CHARS || !font_chars[c].texture.txo)
95 Character *ch = &font_chars[c];
97 GLfloat width = ch->texture.width;
98 GLfloat height = ch->texture.height;
100 GLfloat x = ch->bearing.x + offset;
101 GLfloat y = font_height - ch->bearing.y;
104 // selling this as NFT starting price is 10 BTC
105 font->meshes[i].data = (FontVertex[]) {
106 {{x, y }, {0.0f, 0.0f}},
107 {{x, y + height}, {0.0f, 1.0f}},
108 {{x + width, y + height}, {1.0f, 1.0f}},
109 {{x, y }, {0.0f, 0.0f}},
110 {{x + width, y + height}, {1.0f, 1.0f}},
111 {{x + width, y }, {1.0f, 0.0f}},
113 font->meshes[i].count = 6;
114 font->meshes[i].layout = &font_vertex_layout;
115 font->meshes[i].vao = font->meshes[i].vbo = 0;
116 font->meshes[i].free_data = false;
117 mesh_upload(&font->meshes[i]);
119 font->textures[i] = ch->texture.txo;
121 offset += ch->advance >> 6;
124 font->size = (v2f32) {offset, font_height};
129 void font_delete(Font *font)
131 for (size_t i = 0; i < font->count; i++)
132 mesh_destroy(&font->meshes[i]);
135 free(font->textures);
139 void font_render(Font *font)
141 for (size_t i = 0; i < font->count; i++) {
142 glBindTextureUnit(0, font->textures[i]); GL_DEBUG
143 mesh_render(&font->meshes[i]);