4 #include "client/client.h"
5 #include "client/font.h"
6 #include "client/opengl.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, ASSET_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);
73 for (unsigned char c = 0; c < NUM_CHARS; c++)
74 texture_destroy(&font_chars[c].texture);
77 Font *font_create(const char *text)
79 Font *font = malloc(sizeof *font);
81 font->count = strlen(text);
82 font->meshes = malloc(font->count * sizeof *font->meshes);
83 font->textures = malloc(font->count * sizeof *font->textures);
85 GLfloat offset = 0.0f;
87 for (size_t i = 0; i < font->count; i++) {
88 unsigned char c = text[i];
90 if (c >= NUM_CHARS || !font_chars[c].texture.txo)
93 Character *ch = &font_chars[c];
95 GLfloat width = ch->texture.width;
96 GLfloat height = ch->texture.height;
98 GLfloat x = ch->bearing.x + offset;
99 GLfloat y = font_height - ch->bearing.y;
102 // selling this as NFT starting price is 10 BTC
103 font->meshes[i].data = (FontVertex[]) {
104 {{x, y }, {0.0f, 0.0f}},
105 {{x, y + height}, {0.0f, 1.0f}},
106 {{x + width, y + height}, {1.0f, 1.0f}},
107 {{x, y }, {0.0f, 0.0f}},
108 {{x + width, y + height}, {1.0f, 1.0f}},
109 {{x + width, y }, {1.0f, 0.0f}},
111 font->meshes[i].count = 6;
112 font->meshes[i].layout = &font_vertex_layout;
113 font->meshes[i].vao = font->meshes[i].vbo = 0;
114 font->meshes[i].free_data = false;
115 mesh_upload(&font->meshes[i]);
117 font->textures[i] = ch->texture.txo;
119 offset += ch->advance >> 6;
122 font->size = (v2f32) {offset, font_height};
127 void font_delete(Font *font)
129 for (size_t i = 0; i < font->count; i++)
130 mesh_destroy(&font->meshes[i]);
133 free(font->textures);
137 void font_render(Font *font)
139 for (size_t i = 0; i < font->count; i++) {
140 glBindTextureUnit(0, font->textures[i]); GL_DEBUG
141 mesh_render(&font->meshes[i]);