ded

Dramatic EDitor
Index Commits Files Refs README LICENSE
src/free_glyph.c (4524B)
   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 }