revolver

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

util_font.c (2870B)


      1 //////////////////////////////////////////////////////////////////
      2 // util_font.c
      3 
      4 #define STB_RECT_PACK_IMPLEMENTATION
      5 #include "../external/stb_rect_pack.h"
      6 #define STB_TRUETYPE_IMPLEMENTATION
      7 #include "../external/stb_truetype.h"
      8 
      9 RV_GLOBAL rv_ascii_font_t* rv_ascii_font_from_file(rv_arena* arena, rv_str8 filename, s32 point_size)
     10 {
     11     rv_temp_arena scratch = rv_scratch_begin(0, 0);
     12     rv_str8 f = rv_read_file(scratch.arena, filename);
     13     rv_ascii_font_t* res = rv_ascii_font_from_memory(arena, f, point_size);
     14     rv_scratch_end(scratch);
     15 
     16     return res;
     17 }
     18 
     19 RV_GLOBAL rv_ascii_font_t* rv_ascii_font_from_memory(rv_arena* arena, rv_str8 ttf_data, s32 point_size)
     20 {
     21     // TODO(Samdal): make index choosable?
     22     s32 index = 0;
     23 
     24     rv_ascii_font_t* font = rv_push(arena, rv_ascii_font_t);
     25 
     26     if (point_size < 0) {
     27         rv_unreachable();
     28         point_size = 10;
     29     }
     30     font->point_size = point_size;
     31 
     32     const int load_font = stbtt_InitFont(&font->info, ttf_data.str, stbtt_GetFontOffsetForIndex(ttf_data.str, index));
     33     rv_assert(load_font);
     34 
     35     float s = stbtt_ScaleForPixelHeight(&font->info, point_size);
     36     int a, d, l;
     37     stbtt_GetFontVMetrics(&font->info, &a, &d, &l);
     38     font->linedist = (a * s) - (d * s) + (l * s);
     39 
     40     // Poor attempt at an auto resized texture
     41     s32 w = (f32)point_size * sqrtf(RV_ASCII_FONT_GLYPH_COUNT) * sqrtf(0.45f);
     42     s32 h = (f32)point_size * sqrtf(RV_ASCII_FONT_GLYPH_COUNT) * sqrtf(0.45f);
     43     w = rv_align_pow2(w, 64);
     44     h = rv_align_pow2(h, 64);
     45 
     46     u8* bitmap = rv_arena_push(arena, w * h, 8);
     47 
     48     stbtt_pack_context pc;
     49     stbtt_PackBegin(&pc, bitmap, w, h, 0, 1, NULL);
     50     stbtt_PackSetOversampling(&pc, 1, 1);
     51     stbtt_PackFontRange(&pc, ttf_data.str, 0, point_size, 32, 96, font->cdata);
     52     stbtt_PackEnd(&pc);
     53 
     54     font->tex = rv_push_compound(arena, rv_texture_t, {
     55             .data = bitmap,
     56             .size = rv_v2(w, h),
     57             .format = RV_TEXTURE_FORMAT_R8,
     58             .min_filter = RV_TEXTURE_FILTER_LINEAR,
     59             .mag_filter = RV_TEXTURE_FILTER_LINEAR,
     60         });
     61 
     62     return font;
     63 }
     64 
     65 RV_GLOBAL rv_vec2 gs_asset_font_text_dimensions(rv_ascii_font_t* font, rv_str8 text)
     66 {
     67     rv_vec2 dimensions = {};
     68 
     69     s32 lines = 0;
     70     f32 x = 0;
     71     f32 yover  = font->point_size;
     72     f32 ybelow = 0;
     73 
     74     for (s32 i = 0; i < RV_ASCII_FONT_GLYPH_COUNT; i++) {
     75         ybelow = rv_max(ybelow, -font->cdata[i].yoff2);
     76     }
     77 
     78     for (s32 i = 0; i < text.len; i++) {
     79         if (text.str[i] == '\n') {
     80             lines++;
     81             dimensions.x = rv_max(dimensions.x, x);
     82             x = 0;
     83             continue;
     84         }
     85 
     86         if (text.str[i] >= 32 && text.str[i] <= 127) {
     87             x += font->cdata[text.str[i] - 32].xadvance;
     88         }
     89     };
     90     dimensions.y += (yover) * (lines+1) + ybelow;
     91     dimensions.x = rv_max(dimensions.x, x);
     92 
     93     return dimensions;
     94 }