1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#include <fontconfig/fontconfig.h>
#include "font.h"
char* get_font(const char* font_name) {
FcPattern* pattern = FcNameParse((const FcChar8*)font_name);
if (!pattern) {
fprintf(stderr, "Failed to create font pattern\n");
return NULL;
}
FcConfigSubstitute(0, pattern, FcMatchPattern);
FcDefaultSubstitute(pattern);
FcResult result = 0;
FcFontSet* font_patterns = FcFontSort(0, pattern, FcTrue, 0, &result);
if (!font_patterns || !font_patterns->nfont) {
fprintf(stderr, "No fonts installed on system\n");
return NULL;
}
FcFontSet* fs = FcFontSetCreate();
FcPattern* font_pattern = FcFontRenderPrepare(0, pattern, font_patterns->fonts[0]);
if (!font_pattern) {
fprintf(stderr, "Could not prepare matched font for loading\n");
return NULL;
}
FcFontSetAdd(fs, font_pattern);
FcFontSetSortDestroy(font_patterns);
FcPatternDestroy(pattern);
if (!fs || !font_patterns->nfont) {
fprintf(stderr, "Could not prepare font set\n");
}
FcObjectSet* os = FcObjectSetBuild(FC_FILE, (char*)0);
FcValue v = { 0 };
FcPattern* fontp = FcPatternFilter(fs->fonts[0], os);
FcPatternGet(fontp, FC_FILE, 0, &v);
char* font = strdup((char*)v.u.f);
FcPatternDestroy(fontp);
FcFontSetDestroy(fs);
FcObjectSetDestroy(os);
return font;
}
bool init_freetype(client_state* state, const char* file) {
if (FT_Init_FreeType(&state->ft_library)) {
fprintf(stderr, "Failed to intalize FreeType Library\n");
return false;
}
if (FT_New_Face(state->ft_library, file, 0, &state->ft_face)) {
fprintf(stderr, "Failed to create font\n");
return false;
}
if (FT_Set_Char_Size(state->ft_face, 0, 12 << 6, 0, 0)) {
fprintf(stderr, "Failed to set font size\n");
return false;
}
return true;
}
bool init_atlas(client_state* state) {
FT_Int32 load_flags = FT_LOAD_RENDER | FT_LOAD_TARGET_(FT_RENDER_MODE_SDF);
for (int i = 32; i < 128; i++) {
if (FT_Load_Char(state->ft_face, i, load_flags)) {
fprintf(stderr, "Failed to render character %c\n", (char)i);
}
printf("%c: %u, %u\n", (char)i, state->ft_face->glyph->bitmap.width, state->ft_face->glyph->bitmap.rows);
state->atlas.width += state->ft_face->glyph->bitmap.width;
state->atlas.height = MAX(state->atlas.height, state->ft_face->glyph->bitmap.rows);
}
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &state->atlas.texture);
glBindTexture(GL_TEXTURE_2D, state->atlas.texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RED,
(GLsizei) state->atlas.width,
(GLsizei) state->atlas.height,
0,
GL_RED,
GL_UNSIGNED_BYTE,
NULL);
uint32_t x = 0;
for (int i = 32; i < 128; i++) {
if (FT_Load_Char(state->ft_face, i, load_flags)) {
fprintf(stderr, "Failed to render character %c\n", (char)i);
}
if (FT_Render_Glyph(state->ft_face->glyph, FT_RENDER_MODE_NORMAL)) {
fprintf(stderr, "ERROR: could not render glyph of a character with code %d\n", i);
}
state->atlas.metrics[i].advance_x = (float)state->ft_face->glyph->advance.x / 64;
state->atlas.metrics[i].advance_y = (float)state->ft_face->glyph->advance.y / 64;
state->atlas.metrics[i].bitmap_width = state->ft_face->glyph->bitmap.width;
state->atlas.metrics[i].bitmap_height = state->ft_face->glyph->bitmap.rows;
state->atlas.metrics[i].texture_offset = x;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexSubImage2D(
GL_TEXTURE_2D,
0,
x,
0,
state->ft_face->glyph->bitmap.width,
state->ft_face->glyph->bitmap.rows,
GL_RED,
GL_UNSIGNED_BYTE,
state->ft_face->glyph->bitmap.buffer);
x += state->ft_face->glyph->bitmap.width;
}
return true;
}
|