| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- #ifndef FREE_GLYPH_H
- #define FREE_GLYPH_H
- #include <stdbool.h>
- #include <stdint.h>
- #include <ft2build.h>
- #include FT_FREETYPE_H
- #include "vec2.h"
- #include "vec4.h"
- #include "glyph_attr.h"
- #include "simple_render.h"
- struct glyph_info {
- struct vec2i64 a;
- struct {
- uint32_t w;
- uint32_t h;
- int32_t l;
- int32_t t;
- } b;
- float tx;
- };
- struct free_glyph_atlas {
- uint32_t font_tex;
- struct vec2ui atlas_dim;
- struct glyph_info g_infos[128];
- };
- struct free_glyph_atlas fga_create(FT_Face font_face);
- float fga_calc_col(const struct free_glyph_atlas *fga, const struct app *app,
- const char *cstr, size_t cstr_size,
- struct vec2f pos, size_t index);
- float fga_calc_col_buffer(const struct free_glyph_atlas *fga,
- const struct app *app);
- void fga_calc(struct free_glyph_atlas *fga, struct simple_render *sr,
- const struct app *app, const char *cstr, size_t cstr_size,
- struct vec2f pos, struct vec4f fg_color, struct vec4f bg_color);
- void fga_calc_buffer(struct free_glyph_atlas *fga, struct simple_render *sr,
- const struct app *app, struct vec2f pos);
- void fga_load_texture_atlas_or_exit(struct free_glyph_atlas *fga,
- FT_Face font_face);
- struct vec2ui fga_calc_atlas_dimensions(FT_Face font_face);
- #if defined(FREE_GLYPH_IMP) || defined(IMP)
- #include "shader.h"
- #include "gl_util.h"
- struct free_glyph_atlas
- fga_create(FT_Face font_face)
- {
- struct free_glyph_atlas fga = {0};
- fga_load_texture_atlas_or_exit(&fga, font_face);
- return fga;
- }
- float
- fga_calc_col(const struct free_glyph_atlas *fga, const struct app *app,
- const char *cstr, size_t cstr_size, struct vec2f pos,
- size_t index)
- {
- struct vec2f pen = pos;
- struct vec2f dim = vec2f_from_ui(fga->atlas_dim);
- if ( index > cstr_size ) {
- index = cstr_size - 1;
- }
- for ( size_t i = 0; i < index; ++i ) {
- char c = cstr[i];
- if ( c == '\n' ) {
- pen.x = 0;
- pen.y -= dim.y;
- continue;
- }
- struct glyph_info gi = fga->g_infos[(int64_t)c];
- if ( c == '\t' ) {
- c = ' ';
- gi = fga->g_infos[(int64_t)c];
- gi.a.x *= app->cfg.tab_size;
- }
- pen.x += (float) gi.a.x;
- pen.y += (float) gi.a.y;
- }
- return pen.x;
- }
- float
- fga_calc_col_buffer(const struct free_glyph_atlas *fga,
- const struct app *app)
- {
- return fga_calc_col(fga, app, app->buf.data.items,
- app->buf.data.size, vec2fs(0),
- app->buf.cur);
- }
- /* struct free_glyph_atlas */
- /* fga_calc(struct free_glyph_atlas fga, struct app app, */
- /* const char *cstr, size_t cstr_size, struct vec2f pos, */
- /* struct vec4f fg_color, struct vec4f bg_color) */
- /* { */
- /* struct vec2f pen = pos; */
- /* struct vec2f dim = vec2f_from_ui(fga->atlas_dim); */
- /* for ( size_t i = 0; i < cstr_size; ++i ) { */
- /* char c = cstr[i]; */
- /* if ( c == '\n' ) { */
- /* pen.x = 0; */
- /* pen.y -= dim.y; */
- /* continue; */
- /* } */
- /* struct glyph_info gi = fga->g_infos[(int64_t)c]; */
- /* if ( c == '\t' ) { */
- /* c = ' '; */
- /* gi = fga->g_infos[(int64_t)c]; */
- /* gi.a.x *= app.cfg.tab_size; */
- /* } */
- /* float w = (float)gi.b.w; */
- /* float h = (float)gi.b.h; */
- /* struct free_glyph gly = { */
- /* .pos = { */
- /* pen.x + (float) gi.b.l, */
- /* pen.y + (float) gi.b.t */
- /* }, */
- /* .size = {w, -h}, */
- /* .uv_pos = { gi.tx, 0.0f }, */
- /* .uv_size = { w / dim.x, h / dim.y }, */
- /* .fg_color = fg_color, */
- /* .bg_color = bg_color, */
- /* }; */
- /* pen.x += (float) gi.a.x; */
- /* pen.y += (float) gi.a.y; */
- /* DA_APPEND(fga->glyphs, gly); */
- /* } */
- /* return fga; */
- /* } */
- /* struct free_glyph_atlas */
- /* fga_calc_buffer(struct free_glyph_atlas fga, */
- /* struct app app, */
- /* struct vec2f size) */
- /* { */
- /* return fga_calc(fga, app, */
- /* app.buf.data.items, app.buf.data.size, */
- /* size, vec4fs(1), vec4fs(0)); */
- /* } */
- void
- fga_load_texture_atlas_or_exit(struct free_glyph_atlas *fga,
- FT_Face font_face)
- {
- struct vec2ui dim = fga_calc_atlas_dimensions(font_face);
- fga->atlas_dim = dim;
- glActiveTexture(GL_TEXTURE0);
- glGenTextures(1, &fga->font_tex);
- glBindTexture(GL_TEXTURE_2D, fga->font_tex);
- 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, (int32_t)dim.x, (int32_t)dim.y,
- 0, GL_RED, GL_UNSIGNED_BYTE, 0);
- FT_GlyphSlot g = font_face->glyph;
- uint64_t x = 0;
- for ( uint64_t i = 0; i < 128; ++i ) {
- if ( FT_Load_Char(font_face, i, FT_LOAD_RENDER) ) {
- fprintf(stderr, "[ERROR] Failed to load char: %c\n",
- (char)i);
- exit(EXIT_FAILURE);
- }
- if ( FT_Render_Glyph(g, FT_RENDER_MODE_NORMAL) ) {
- fprintf(stderr, "[ERROR] Failed to render char: %c\n",
- (char)i);
- exit(EXIT_FAILURE);
- }
- glTexSubImage2D(GL_TEXTURE_2D, 0, (int32_t) x, 0,
- (int32_t) g->bitmap.width,
- (int32_t) g->bitmap.rows,
- GL_RED, GL_UNSIGNED_BYTE,
- g->bitmap.buffer);
- fga->g_infos[i] = (struct glyph_info) {
- .a = {
- .x = g->advance.x >> 6,
- .y = g->advance.y >> 6,
- },
- .b = {
- .w = g->bitmap.width,
- .h = g->bitmap.rows,
- .l = g->bitmap_left,
- .t = g->bitmap_top,
- },
- .tx = ((float) x) / ((float) dim.x),
- };
- x += g->bitmap.width;
- }
- }
- struct vec2ui
- fga_calc_atlas_dimensions(FT_Face font_face)
- {
- struct vec2ui dim = {0};
- for ( uint64_t i = 0; i < 128; ++i ) {
- if ( FT_Load_Char(font_face, i, FT_LOAD_RENDER) ) {
- fprintf(stderr, "[WARNING] Failed to load char: %c\n",
- (char)i);
- continue;
- }
- dim.x += font_face->glyph->bitmap.width;
- uint32_t row = font_face->glyph->bitmap.rows;
- dim.y = ( dim.y < row ) * row
- + ( ! (dim.y < row) ) * dim.y;
- }
- return dim;
- }
- #endif /* defined(FREE_GLYPH_IMP) || defined(IMP) */
- #endif
|