]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/client/font.c
Replace Ubuntu font by Minecraftia
[dragonblocks_alpha.git] / src / client / font.c
1 #include <string.h>
2 #include <ft2build.h>
3 #include FT_FREETYPE_H
4 #include "client/client.h"
5 #include "client/font.h"
6 #include "client/hud.h"
7
8 #define NUM_CHARS 128
9
10
11 typedef struct
12 {
13         Texture *texture;
14         v2s32 bearing;
15         u32 advance;
16 } Character;
17
18 static struct
19 {
20         FT_Library library;
21         FT_Face face;
22         Character chars[NUM_CHARS];
23         GLfloat height;
24 } font;
25
26 typedef struct
27 {
28         GLfloat x, y;
29 } __attribute__((packed)) VertexFontPosition;
30
31 typedef struct
32 {
33         GLfloat s, t;
34 } __attribute__((packed)) VertexFontTextureCoordinates;
35
36 typedef struct
37 {
38         VertexFontPosition position;
39         VertexFontTextureCoordinates textureCoordinates;
40 } __attribute__((packed)) VertexFont;
41
42 static VertexAttribute vertex_attributes[2] = {
43         // position
44         {
45                 .type = GL_FLOAT,
46                 .length = 2,
47                 .size = sizeof(VertexFontPosition),
48         },
49         // textureCoordinates
50         {
51                 .type = GL_FLOAT,
52                 .length = 2,
53                 .size = sizeof(VertexFontTextureCoordinates),
54         },
55 };
56
57 static VertexLayout vertex_layout = {
58         .attributes = vertex_attributes,
59         .count = 2,
60         .size = sizeof(VertexFont),
61 };
62
63 bool font_init()
64 {
65         if (FT_Init_FreeType(&font.library)) {
66                 fprintf(stderr, "Failed to initialize Freetype\n");
67                 return false;
68         }
69
70         if (FT_New_Face(font.library, RESSOURCEPATH "fonts/Minecraftia.ttf", 0, &font.face)) {
71                 fprintf(stderr, "Failed to load Minecraftia.ttf\n");
72                 return false;
73         }
74
75         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
76         FT_Set_Pixel_Sizes(font.face, 0, 16);
77
78         for (unsigned char c = 0; c < NUM_CHARS; c++) {
79                 if (FT_Load_Char(font.face, c, FT_LOAD_RENDER)) {
80                         fprintf(stderr, "Failed to load glyph %c\n", c);
81
82                         font.chars[c] = (Character) {
83                                 .texture = NULL,
84                                 .bearing = {0, 0},
85                                 .advance = 0,
86                         };
87                 } else {
88                         font.chars[c] = (Character) {
89                                 .texture = texture_create(font.face->glyph->bitmap.buffer, font.face->glyph->bitmap.width, font.face->glyph->bitmap.rows, GL_RED),
90                                 .bearing = {font.face->glyph->bitmap_left, font.face->glyph->bitmap_top},
91                                 .advance = font.face->glyph->advance.x,
92                         };
93                 }
94         }
95
96         font.height = font.chars['|'].texture->height;
97
98         FT_Done_Face(font.face);
99         FT_Done_FreeType(font.library);
100
101         return true;
102 }
103
104 void font_deinit()
105 {
106         for (unsigned char c = 0; c < NUM_CHARS; c++) {
107                 if (font.chars[c].texture)
108                         texture_delete(font.chars[c].texture);
109         }
110 }
111
112 Font *font_create(char *text)
113 {
114         Font *fnt = malloc(sizeof(fnt));
115
116         size_t len = strlen(text);
117
118         fnt->meshes = malloc(sizeof(Mesh *) * len);
119         fnt->meshes_count = len;
120
121         GLfloat offset = 0.0f;
122
123         for (size_t i = 0; i < len; i++) {
124                 unsigned char c = text[i];
125
126                 if (c >= NUM_CHARS || ! font.chars[c].texture)
127                         c = '?';
128
129                 Character *ch = &font.chars[c];
130
131                 GLfloat width = ch->texture->width;
132         GLfloat height = ch->texture->height;
133
134                 GLfloat x = ch->bearing.x + offset;
135         GLfloat y = font.height - ch->bearing.y;
136
137         VertexFont vertices[6] = {
138             {{x,         y         }, {0.0f, 0.0f}},
139             {{x,         y + height}, {0.0f, 1.0f}},
140             {{x + width, y + height}, {1.0f, 1.0f}},
141             {{x,         y         }, {0.0f, 0.0f}},
142             {{x + width, y + height}, {1.0f, 1.0f}},
143             {{x + width, y         }, {1.0f, 0.0f}},
144         };
145
146                 Mesh *mesh = fnt->meshes[i] = mesh_create();
147                 mesh->texture = ch->texture->id;
148                 mesh->layout = &vertex_layout;
149                 mesh->vertices = vertices;
150                 mesh->vertices_count = 6;
151                 mesh_configure(mesh);
152
153                 offset += ch->advance >> 6;
154         }
155
156         return fnt;
157 }
158
159 void font_delete(Font *fnt)
160 {
161         for (size_t i = 0; i < fnt->meshes_count; i++)
162                 mesh_delete(fnt->meshes[i]);
163
164         free(fnt);
165 }
166
167 void font_render(Font *fnt)
168 {
169         for (size_t i = 0; i < fnt->meshes_count; i++)
170                 mesh_render(fnt->meshes[i]);
171 }