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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
|
#include "text.h"
#include <fcntl.h>
#include <mimalloc.h>
#include <unistd.h>
#include <utils.h>
#include "cglm/types.h"
#include "freetype/freetype.h"
#include "geometry.h"
#include "hash.h"
#include "utils.h"
static bool wayc_font_cache_lookup(struct font_s* font, codepoint_t codepoint,
struct glyph_s* out) {
struct glyph_s glyph;
bool ok = wayc_hashmap_get(&font->cache, &codepoint, &glyph);
if (ok) *out = glyph;
return ok;
}
/*
static void wayc_font_cache_insert(struct font_s* font, codepoint_t codepoint,
struct glyph_s glyph) {
wayc_notnull(font);
wayc_hashmap_insert(&font->cache, &codepoint, &glyph);
} */
enum font_context_error_e wayc_font_context_init(struct font_context_s* ctx) {
wayc_notnull(ctx);
FT_Error err = FT_Init_FreeType(&ctx->library);
if (err) return FONT_CONTEXT_ERROR_LIBRARY_LOADING;
return FONT_CONTEXT_ERROR_NONE;
}
void wayc_font_context_deinit(struct font_context_s* ctx) {
wayc_notnull(ctx);
FT_Done_FreeType(ctx->library);
}
enum font_error_e wayc_font_init(struct font_s* font,
struct font_context_s* ctx, u32 fsize,
const char* path) {
wayc_notnull(font);
wayc_notnull(ctx);
wayc_notnull(path);
bool success = false;
i32 fd = open(path, O_RDONLY);
if (fd < 0) return FONT_ERROR_FILE_LOAD;
wayc_defer(close(fd));
isize size = lseek(fd, 0, SEEK_END);
if (size < 0) return FONT_ERROR_FILE_LOAD;
lseek(fd, 0, SEEK_SET);
u8* data = (u8*)mi_malloc(size);
wayc_defer_cond({ mi_free(data); }, success, true);
isize _read = read(fd, data, size);
if (_read < 0 || _read != size) return FONT_ERROR_FILE_LOAD;
FT_Error err = FT_New_Memory_Face(ctx->library, data, size, 0, &font->face);
if (err) return FONT_ERROR_FONT_LOAD;
wayc_defer_cond(FT_Done_Face(font->face);, success, true);
err = FT_Set_Pixel_Sizes(font->face, 0, fsize);
if (err) return FONT_ERROR_FONT_LOAD;
font->data = data;
wayc_hashmap_init(&font->cache);
success = true;
return FONT_ERROR_NONE;
}
enum font_error_e wayc_font_lookup(struct font_s* font, codepoint_t codepoint,
struct glyph_s* out) {
wayc_notnull(font);
wayc_notnull(out);
FT_Face face = font->face;
bool found = wayc_font_cache_lookup(font, codepoint, out);
if (found) return FONT_ERROR_NONE;
FT_UInt glyph_index = FT_Get_Char_Index(face, codepoint);
if (glyph_index == 0) return FONT_ERROR_NOT_MATCH;
FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
FT_GlyphSlot slot = face->glyph;
FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
FT_Bitmap bitmap = slot->bitmap;
if (bitmap.pitch != (i32)bitmap.width) wayc_panic("unsupported pitch");
/*
ivec2 size = {(i32)bitmap.width, (i32)bitmap.rows};
ivec2 uv0;
bool ok = wayc_atlas_packer_allocate(packer, WAYC_X(size), WAYC_Y(size),
uv0); if (!ok) return FONT_ERROR_ATLAS_FULL;
ok = wayc_atlas_set(atlas, IMAGE_DATA_TYPE_UNSIGNED_BYTE, uv0, WAYC_X(size),
WAYC_Y(size), IMAGE_FORMAT_RED_ALIGNMENT,
bitmap.buffer); if (!ok) return FONT_ERROR_ATLAS_FULL;
struct glyph_s glyph = {};
glyph.bearing_x = slot->bitmap_left;
glyph.bearing_y = slot->bitmap_top;
glyph.advance = (f32)slot->advance.x / WAYC_SCALE;
glyph.uv0[0] = uv0[0];
glyph.uv0[1] = uv0[1];
glyph.uv1[0] = uv0[0] + size[0];
glyph.uv1[1] = uv0[1] + size[1];
wayc_font_cache_insert(font, codepoint, glyph);
*out = glyph;
*/
wayc_panic("Atlas packing not implemented yet");
return FONT_ERROR_NONE;
}
void wayc_font_deinit(struct font_s* font) {
wayc_notnull(font);
wayc_hashmap_deinit(&font->cache);
FT_Done_Face(font->face);
mi_free(font->data);
}
/*
static void wayc_text_assemble_one(const struct glyph_s* glyph, vec2* pen,
f32 atlas_width, f32 atlas_height,
struct text_vertex_s* out_verts,
text_index_t* out_indices,
text_index_t base) {
wayc_notnull(glyph);
wayc_notnull(pen);
wayc_notnull(out_verts);
wayc_notnull(out_indices);
const f32 left = WAYC_X(*pen) + glyph->bearing_x;
const f32 top = WAYC_Y(*pen) - glyph->bearing_y;
const f32 right = left + (WAYC_X(glyph->uv1) - WAYC_X(glyph->uv0));
const f32 bottom = top + (WAYC_Y(glyph->uv1) - WAYC_Y(glyph->uv0));
const f32 uv_left = (f32)WAYC_X(glyph->uv0) / atlas_width;
const f32 uv_top = (f32)WAYC_Y(glyph->uv0) / atlas_height;
const f32 uv_right = (f32)WAYC_X(glyph->uv1) / atlas_width;
const f32 uv_bottom = (f32)WAYC_Y(glyph->uv1) / atlas_height;
struct quad_s quad;
wayc_quad_init(&quad, left, top, right, bottom);
out_verts[0] = {{WAYC_X(quad.vertices[0]), WAYC_Y(quad.vertices[0])},
{uv_left, uv_top}};
out_verts[1] = {{WAYC_X(quad.vertices[1]), WAYC_Y(quad.vertices[1])},
{uv_right, uv_top}};
out_verts[2] = {{WAYC_X(quad.vertices[2]), WAYC_Y(quad.vertices[2])},
{uv_right, uv_bottom}};
out_verts[3] = {{WAYC_X(quad.vertices[3]), WAYC_Y(quad.vertices[3])},
{uv_left, uv_bottom}};
#pragma GCC unroll 6
for (usize i = 0; i < WAYC_QUAD_NINDICES; ++i)
out_indices[i] = base + (text_index_t)quad.indices[i];
} */
enum text_error_e wayc_text_assemble(struct text_s* text, usize* out_size,
text_index_t** out_indices,
struct text_vertex_s** out_verts) {
wayc_notnull(text);
wayc_notnull(out_size);
wayc_notnull(out_indices);
wayc_notnull(out_verts);
/*
bool success = false;
usize glyph_count = wayc_string_length(&text->string);
usize vertex_count = glyph_count * WAYC_QUAD_NVERTS;
usize index_count = glyph_count * WAYC_QUAD_NINDICES;
usize vertex_bytes = vertex_count * sizeof(struct text_vertex_s);
usize index_bytes = index_count * sizeof(text_index_t);
struct text_vertex_s* vertices =
(struct text_vertex_s*)mi_malloc(vertex_bytes);
wayc_defer_cond(mi_free(vertices), success, true);
text_index_t* indices = (text_index_t*)mi_malloc(index_bytes);
wayc_defer_cond(mi_free(indices), success, true);
struct atlas_s* atlas = text->atlas;
f32 atlas_width = (f32)atlas->width;
f32 atlas_height = (f32)atlas->height;
vec2 pen = {0, 0};
for (usize i = 0; i < glyph_count; i++) {
codepoint_t codepoint = text->string.data[i];
struct glyph_s glyph;
enum font_error_e err = wayc_font_lookup(text->font, text->atlas,
text->packer, codepoint, &glyph);
if (err != FONT_ERROR_NONE) return TEXT_ERROR_ATLAS;
usize vertex_offset = i * WAYC_QUAD_NVERTS;
usize index_offset = i * WAYC_QUAD_NINDICES;
struct text_vertex_s* vertices_writer = &vertices[vertex_offset];
text_index_t* indices_writer = &indices[index_offset];
text_index_t base = (text_index_t)vertex_offset;
wayc_text_assemble_one(&glyph, &pen, atlas_width, atlas_height,
vertices_writer, indices_writer, base);
pen[0] += glyph.advance;
}
*out_size = index_count;
*out_indices = indices;
*out_verts = vertices;
success = true;
*/
wayc_panic("Text assembly not implemented yet");
return TEXT_ERROR_NONE;
}
|