free_glyph.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. #ifndef FREE_GLYPH_H
  2. #define FREE_GLYPH_H
  3. #include <stdbool.h>
  4. #include <stdint.h>
  5. #include <ft2build.h>
  6. #include FT_FREETYPE_H
  7. #include "vec2.h"
  8. #include "vec4.h"
  9. #include "glyph_attr.h"
  10. struct glyph_info {
  11. struct vec2i64 a;
  12. struct {
  13. uint32_t w;
  14. uint32_t h;
  15. int32_t l;
  16. int32_t t;
  17. } b;
  18. float tx;
  19. };
  20. struct free_glyph {
  21. struct vec2f pos;
  22. struct vec2f size;
  23. struct vec2f uv_pos;
  24. struct vec2f uv_size;
  25. struct vec4f fg_color;
  26. struct vec4f bg_color;
  27. };
  28. DA_DEF_STRUCT(struct free_glyph, free_glyph_da);
  29. struct free_glyph_render {
  30. uint32_t font_tex;
  31. struct vec2ui atlas_dim;
  32. struct free_glyph_da glyphs;
  33. struct {
  34. uint32_t vert;
  35. uint32_t frag;
  36. } shaders;
  37. uint32_t prog;
  38. struct {
  39. int32_t resolution;
  40. int32_t time;
  41. int32_t camera;
  42. } uniforms;
  43. uint32_t vao;
  44. uint32_t vbo;
  45. struct glyph_info g_infos[128];
  46. };
  47. enum free_glyph_attr_enum {
  48. FREE_GLYPH_ATTR_POS = 0,
  49. FREE_GLYPH_ATTR_SIZE,
  50. FREE_GLYPH_ATTR_UV_POS,
  51. FREE_GLYPH_ATTR_UV_SIZE,
  52. FREE_GLYPH_ATTR_FG_COLOR,
  53. FREE_GLYPH_ATTR_BG_COLOR,
  54. FREE_GLYPH_ATTR_TOTAL
  55. };
  56. struct free_glyph_render free_glyph_render_create(FT_Face font_face,
  57. const char *vert_path,
  58. const char *frag_path);
  59. struct free_glyph_da free_glyph_da_create(void);
  60. const struct glyph_attr* free_glyph_get_attrs(void);
  61. void free_glyph_render_use(struct free_glyph_render fgr);
  62. float free_glyph_render_calc_col(struct free_glyph_render fgr, struct app app,
  63. const char *cstr, size_t cstr_size,
  64. struct vec2f pos, size_t index);
  65. float free_glyph_render_calc_col_buffer(struct free_glyph_render fgr,
  66. struct app app);
  67. struct free_glyph_render free_glyph_render_calc(
  68. struct free_glyph_render fgr, struct app app,
  69. const char *cstr, size_t cstr_size, struct vec2f pos,
  70. struct vec4f fg_color, struct vec4f bg_color);
  71. struct free_glyph_render free_glyph_render_calc_buffer(
  72. struct free_glyph_render fgr, struct app app,
  73. struct vec2f pos);
  74. void free_glyph_render_sync(struct free_glyph_render fgr);
  75. struct free_glyph_render free_glyph_render_gen_buffer(
  76. struct free_glyph_render fgr);
  77. struct free_glyph_render free_glyph_render_load_texture_atlas_or_exit(
  78. struct free_glyph_render fgr,
  79. FT_Face font_face);
  80. struct vec2ui free_glyph_render_calc_atlas_dimensions(FT_Face font_face);
  81. #if defined(FREE_GLYPH_IMP) || defined(IMP)
  82. #include "shader.h"
  83. #include "gl_util.h"
  84. struct free_glyph_render
  85. free_glyph_render_create(FT_Face font_face, const char *vert_path,
  86. const char *frag_path)
  87. {
  88. struct free_glyph_render fgr = {0};
  89. fgr = free_glyph_render_load_texture_atlas_or_exit(fgr, font_face);
  90. fgr.glyphs = free_glyph_da_create();
  91. fgr.shaders.vert = shader_compile_file_or_exit(
  92. vert_path, GL_VERTEX_SHADER);
  93. fgr.shaders.frag = shader_compile_file_or_exit(
  94. frag_path, GL_FRAGMENT_SHADER);
  95. fgr.prog = program_link_or_exit(fgr.shaders.vert, fgr.shaders.frag);
  96. glUseProgram(fgr.prog);
  97. fgr.uniforms.resolution = get_uniform_or_exit(fgr.prog, "resolution");
  98. fgr.uniforms.time = get_uniform_or_exit(fgr.prog, "time");
  99. fgr.uniforms.camera = get_uniform_or_exit(fgr.prog, "camera");
  100. fgr = free_glyph_render_gen_buffer(fgr);
  101. return fgr;
  102. }
  103. struct free_glyph_da
  104. free_glyph_da_create(void)
  105. {
  106. struct free_glyph_da glys;
  107. glys.cap = 1024 * 1024;
  108. glys.size = 0;
  109. glys.items = calloc(glys.cap, sizeof(struct free_glyph));
  110. return glys;
  111. }
  112. const struct glyph_attr *
  113. free_glyph_get_attrs(void)
  114. {
  115. static const struct glyph_attr
  116. free_glyph_attr[FREE_GLYPH_ATTR_TOTAL] = {
  117. [FREE_GLYPH_ATTR_POS] = {
  118. .size = 2,
  119. .type = GL_FLOAT,
  120. .norm = GL_FALSE,
  121. .stride = sizeof(struct free_glyph),
  122. .offset = offsetof(struct free_glyph, pos)
  123. },
  124. [FREE_GLYPH_ATTR_SIZE] = {
  125. .size = 2,
  126. .type = GL_FLOAT,
  127. .norm = GL_FALSE,
  128. .stride = sizeof(struct free_glyph),
  129. .offset = offsetof(struct free_glyph, size)
  130. },
  131. [FREE_GLYPH_ATTR_UV_POS] = {
  132. .size = 2,
  133. .type = GL_FLOAT,
  134. .norm = GL_FALSE,
  135. .stride = sizeof(struct free_glyph),
  136. .offset = offsetof(struct free_glyph, uv_pos)
  137. },
  138. [FREE_GLYPH_ATTR_UV_SIZE] = {
  139. .size = 2,
  140. .type = GL_FLOAT,
  141. .norm = GL_FALSE,
  142. .stride = sizeof(struct free_glyph),
  143. .offset = offsetof(struct free_glyph, uv_size)
  144. },
  145. [FREE_GLYPH_ATTR_FG_COLOR] = {
  146. .size = 4,
  147. .type = GL_FLOAT,
  148. .norm = GL_FALSE,
  149. .stride = sizeof(struct free_glyph),
  150. .offset = offsetof(struct free_glyph, fg_color)
  151. },
  152. [FREE_GLYPH_ATTR_BG_COLOR] = {
  153. .size = 4,
  154. .type = GL_FLOAT,
  155. .norm = GL_FALSE,
  156. .stride = sizeof(struct free_glyph),
  157. .offset = offsetof(struct free_glyph, bg_color)
  158. },
  159. };
  160. return free_glyph_attr;
  161. }
  162. void
  163. free_glyph_render_use(struct free_glyph_render fgr)
  164. {
  165. glBindVertexArray(fgr.vao);
  166. glBindBuffer(GL_ARRAY_BUFFER, fgr.vbo);
  167. glUseProgram(fgr.prog);
  168. }
  169. float
  170. free_glyph_render_calc_col(struct free_glyph_render fgr, struct app app,
  171. const char *cstr, size_t cstr_size, struct vec2f pos,
  172. size_t index)
  173. {
  174. struct vec2f pen = pos;
  175. struct vec2f dim = vec2f_from_ui(fgr.atlas_dim);
  176. if ( index > cstr_size ) {
  177. index = cstr_size - 1;
  178. }
  179. for ( size_t i = 0; i < index; ++i ) {
  180. char c = cstr[i];
  181. if ( c == '\n' ) {
  182. pen.x = 0;
  183. pen.y -= dim.y;
  184. continue;
  185. }
  186. struct glyph_info gi = fgr.g_infos[(int64_t)c];
  187. if ( c == '\t' ) {
  188. c = ' ';
  189. gi = fgr.g_infos[(int64_t)c];
  190. gi.a.x *= app.cfg.tab_size;
  191. }
  192. pen.x += (float) gi.a.x;
  193. pen.y += (float) gi.a.y;
  194. }
  195. return pen.x;
  196. }
  197. float
  198. free_glyph_render_calc_col_buffer(struct free_glyph_render fgr,
  199. struct app app)
  200. {
  201. return free_glyph_render_calc_col(fgr, app, app.buf.data.items,
  202. app.buf.data.size, vec2fs(0),
  203. app.buf.cur);
  204. }
  205. struct free_glyph_render
  206. free_glyph_render_calc(struct free_glyph_render fgr, struct app app,
  207. const char *cstr, size_t cstr_size, struct vec2f pos,
  208. struct vec4f fg_color, struct vec4f bg_color)
  209. {
  210. struct vec2f pen = pos;
  211. struct vec2f dim = vec2f_from_ui(fgr.atlas_dim);
  212. for ( size_t i = 0; i < cstr_size; ++i ) {
  213. char c = cstr[i];
  214. if ( c == '\n' ) {
  215. pen.x = 0;
  216. pen.y -= dim.y;
  217. continue;
  218. }
  219. struct glyph_info gi = fgr.g_infos[(int64_t)c];
  220. if ( c == '\t' ) {
  221. c = ' ';
  222. gi = fgr.g_infos[(int64_t)c];
  223. gi.a.x *= app.cfg.tab_size;
  224. }
  225. float w = (float)gi.b.w;
  226. float h = (float)gi.b.h;
  227. struct free_glyph gly = {
  228. .pos = {
  229. pen.x + (float) gi.b.l,
  230. pen.y + (float) gi.b.t
  231. },
  232. .size = {w, -h},
  233. .uv_pos = { gi.tx, 0.0f },
  234. .uv_size = { w / dim.x, h / dim.y },
  235. .fg_color = fg_color,
  236. .bg_color = bg_color,
  237. };
  238. pen.x += (float) gi.a.x;
  239. pen.y += (float) gi.a.y;
  240. DA_APPEND(fgr.glyphs, gly);
  241. }
  242. return fgr;
  243. }
  244. struct free_glyph_render
  245. free_glyph_render_calc_buffer(struct free_glyph_render fgr,
  246. struct app app,
  247. struct vec2f size)
  248. {
  249. return free_glyph_render_calc(fgr, app,
  250. app.buf.data.items, app.buf.data.size,
  251. size, vec4fs(1), vec4fs(0));
  252. }
  253. void
  254. free_glyph_render_sync(struct free_glyph_render fgr)
  255. {
  256. glBufferSubData(GL_ARRAY_BUFFER, 0,
  257. (ssize_t) (fgr.glyphs.size * sizeof(struct free_glyph)),
  258. fgr.glyphs.items);
  259. }
  260. struct free_glyph_render
  261. free_glyph_render_gen_buffer(struct free_glyph_render fgr)
  262. {
  263. glGenVertexArrays(1, &fgr.vao);
  264. glBindVertexArray(fgr.vao);
  265. glGenBuffers(1, &fgr.vbo);
  266. glBindBuffer(GL_ARRAY_BUFFER, fgr.vbo);
  267. glBufferData(GL_ARRAY_BUFFER,
  268. (ssize_t)(fgr.glyphs.cap * sizeof(struct free_glyph)),
  269. fgr.glyphs.items,
  270. GL_DYNAMIC_DRAW);
  271. glyph_attr_declare(free_glyph_get_attrs(), FREE_GLYPH_ATTR_TOTAL);
  272. return fgr;
  273. }
  274. struct free_glyph_render
  275. free_glyph_render_load_texture_atlas_or_exit(struct free_glyph_render fgr,
  276. FT_Face font_face)
  277. {
  278. struct vec2ui dim = free_glyph_render_calc_atlas_dimensions(font_face);
  279. fgr.atlas_dim = dim;
  280. glActiveTexture(GL_TEXTURE0);
  281. glGenTextures(1, &fgr.font_tex);
  282. glBindTexture(GL_TEXTURE_2D, fgr.font_tex);
  283. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  284. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  285. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  286. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  287. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  288. glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, (int32_t)dim.x, (int32_t)dim.y,
  289. 0, GL_RED, GL_UNSIGNED_BYTE, 0);
  290. FT_GlyphSlot g = font_face->glyph;
  291. uint64_t x = 0;
  292. for ( uint64_t i = 0; i < 128; ++i ) {
  293. if ( FT_Load_Char(font_face, i, FT_LOAD_RENDER) ) {
  294. fprintf(stderr, "[ERROR] Failed to load char: %c\n",
  295. (char)i);
  296. exit(EXIT_FAILURE);
  297. }
  298. if ( FT_Render_Glyph(g, FT_RENDER_MODE_NORMAL) ) {
  299. fprintf(stderr, "[ERROR] Failed to render char: %c\n",
  300. (char)i);
  301. exit(EXIT_FAILURE);
  302. }
  303. glTexSubImage2D(GL_TEXTURE_2D, 0, (int32_t) x, 0,
  304. (int32_t) g->bitmap.width,
  305. (int32_t) g->bitmap.rows,
  306. GL_RED, GL_UNSIGNED_BYTE,
  307. g->bitmap.buffer);
  308. fgr.g_infos[i] = (struct glyph_info) {
  309. .a = {
  310. .x = g->advance.x >> 6,
  311. .y = g->advance.y >> 6,
  312. },
  313. .b = {
  314. .w = g->bitmap.width,
  315. .h = g->bitmap.rows,
  316. .l = g->bitmap_left,
  317. .t = g->bitmap_top,
  318. },
  319. .tx = ((float) x) / ((float) dim.x),
  320. };
  321. x += g->bitmap.width;
  322. }
  323. return fgr;
  324. }
  325. struct vec2ui
  326. free_glyph_render_calc_atlas_dimensions(FT_Face font_face)
  327. {
  328. struct vec2ui dim = {0};
  329. for ( uint64_t i = 0; i < 128; ++i ) {
  330. if ( FT_Load_Char(font_face, i, FT_LOAD_RENDER) ) {
  331. fprintf(stderr, "[WARNING] Failed to load char: %c\n",
  332. (char)i);
  333. continue;
  334. }
  335. dim.x += font_face->glyph->bitmap.width;
  336. uint32_t row = font_face->glyph->bitmap.rows;
  337. dim.y = ( dim.y < row ) * row
  338. + ( ! (dim.y < row) ) * dim.y;
  339. }
  340. return dim;
  341. }
  342. #endif /* defined(FREE_GLYPH_IMP) || defined(IMP) */
  343. #endif