1 #include <assert.h> 2 #include <stdbool.h> 3 #include "./free_glyph.h" 4 5 void free_glyph_atlas_init(Free_Glyph_Atlas *atlas, FT_Face face) 6 { 7 // TODO: Introduction of SDF font slowed down the start up time 8 // We need to investigate what's up with that 9 FT_Int32 load_flags = FT_LOAD_RENDER | FT_LOAD_TARGET_(FT_RENDER_MODE_SDF); 10 for (int i = 32; i < 128; ++i) { 11 if (FT_Load_Char(face, i, load_flags)) { 12 fprintf(stderr, "ERROR: could not load glyph of a character with code %d\n", i); 13 exit(1); 14 } 15 16 atlas->atlas_width += face->glyph->bitmap.width; 17 if (atlas->atlas_height < face->glyph->bitmap.rows) { 18 atlas->atlas_height = face->glyph->bitmap.rows; 19 } 20 } 21 22 glActiveTexture(GL_TEXTURE0); 23 glGenTextures(1, &atlas->glyphs_texture); 24 glBindTexture(GL_TEXTURE_2D, atlas->glyphs_texture); 25 26 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 27 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 28 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 29 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 30 31 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 32 glTexImage2D( 33 GL_TEXTURE_2D, 34 0, 35 GL_RED, 36 (GLsizei) atlas->atlas_width, 37 (GLsizei) atlas->atlas_height, 38 0, 39 GL_RED, 40 GL_UNSIGNED_BYTE, 41 NULL); 42 43 int x = 0; 44 for (int i = 32; i < 128; ++i) { 45 if (FT_Load_Char(face, i, load_flags)) { 46 fprintf(stderr, "ERROR: could not load glyph of a character with code %d\n", i); 47 exit(1); 48 } 49 50 if (FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL)) { 51 fprintf(stderr, "ERROR: could not render glyph of a character with code %d\n", i); 52 exit(1); 53 } 54 55 atlas->metrics[i].ax = face->glyph->advance.x >> 6; 56 atlas->metrics[i].ay = face->glyph->advance.y >> 6; 57 atlas->metrics[i].bw = face->glyph->bitmap.width; 58 atlas->metrics[i].bh = face->glyph->bitmap.rows; 59 atlas->metrics[i].bl = face->glyph->bitmap_left; 60 atlas->metrics[i].bt = face->glyph->bitmap_top; 61 atlas->metrics[i].tx = (float) x / (float) atlas->atlas_width; 62 63 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 64 glTexSubImage2D( 65 GL_TEXTURE_2D, 66 0, 67 x, 68 0, 69 face->glyph->bitmap.width, 70 face->glyph->bitmap.rows, 71 GL_RED, 72 GL_UNSIGNED_BYTE, 73 face->glyph->bitmap.buffer); 74 x += face->glyph->bitmap.width; 75 } 76 } 77 78 float free_glyph_atlas_cursor_pos(const Free_Glyph_Atlas *atlas, const char *text, size_t text_size, Vec2f pos, size_t col) 79 { 80 for (size_t i = 0; i < text_size; ++i) { 81 if (i == col) { 82 return pos.x; 83 } 84 85 size_t glyph_index = text[i]; 86 if (glyph_index >= GLYPH_METRICS_CAPACITY) { 87 glyph_index = '?'; 88 } 89 90 Glyph_Metric metric = atlas->metrics[glyph_index]; 91 pos.x += metric.ax; 92 pos.y += metric.ay; 93 } 94 95 return pos.x; 96 } 97 98 void free_glyph_atlas_measure_line_sized(Free_Glyph_Atlas *atlas, const char *text, size_t text_size, Vec2f *pos) 99 { 100 for (size_t i = 0; i < text_size; ++i) { 101 size_t glyph_index = text[i]; 102 // TODO: support for glyphs outside of ASCII range 103 if (glyph_index >= GLYPH_METRICS_CAPACITY) { 104 glyph_index = '?'; 105 } 106 Glyph_Metric metric = atlas->metrics[glyph_index]; 107 108 pos->x += metric.ax; 109 pos->y += metric.ay; 110 } 111 } 112 113 void free_glyph_atlas_render_line_sized(Free_Glyph_Atlas *atlas, Simple_Renderer *sr, const char *text, size_t text_size, Vec2f *pos, Vec4f color) 114 { 115 for (size_t i = 0; i < text_size; ++i) { 116 size_t glyph_index = text[i]; 117 // TODO: support for glyphs outside of ASCII range 118 if (glyph_index >= GLYPH_METRICS_CAPACITY) { 119 glyph_index = '?'; 120 } 121 Glyph_Metric metric = atlas->metrics[glyph_index]; 122 float x2 = pos->x + metric.bl; 123 float y2 = -pos->y - metric.bt; 124 float w = metric.bw; 125 float h = metric.bh; 126 127 pos->x += metric.ax; 128 pos->y += metric.ay; 129 130 simple_renderer_image_rect( 131 sr, 132 vec2f(x2, -y2), 133 vec2f(w, -h), 134 vec2f(metric.tx, 0.0f), 135 vec2f(metric.bw / (float) atlas->atlas_width, metric.bh / (float) atlas->atlas_height), 136 color); 137 } 138 }
