diff options
Diffstat (limited to 'code/amr_fonts.h')
-rw-r--r-- | code/amr_fonts.h | 156 |
1 files changed, 143 insertions, 13 deletions
diff --git a/code/amr_fonts.h b/code/amr_fonts.h index f44893c..81666a0 100644 --- a/code/amr_fonts.h +++ b/code/amr_fonts.h @@ -1,25 +1,46 @@ #ifndef AMR_FONTS_H #define AMR_FONTS_H -typedef struct amr_glyph_info { - u32 charset_start_index; - u32 charset_end_index; -} amr_glyph_info; +#define LATIN_BASIC_START_INDEX 32 +#define LATIN_BASIC_END_INDEX 126 -typedef struct amr_font_details_debug { +typedef struct amr_letter_details_debug { i32 advance; i32 lsb; i32 x0, y0, x1, y1; - i32 kern; - f32 lx; - f32 ly; i32 byte_offset; - i32 baseline; -} debug_font_details; + // @TODO: check if offsets are in PX + f32 StartingYOffset; + f32 StartingXOffset; +} amr_letter_details_debug; typedef struct amr_font_state_debug { stbtt_fontinfo font_info; + amr_letter_details_debug font_details; + // font metrics + f32 font_size; + f32 scale_factor; + i32 ascent; + i32 descent; + i32 line_gap; + // glyphs + u32 charset_start_index; + u32 charset_end_index; + + // @TODO: make this array + u32 *glyph_index_array; + u32 glyph_count; + + // text specific metrics + // @TODO: these should probably be moved to an array or remain out of this struct + f32 Baseline; + f32 MaxLineWidthPx; + // font bitmap info + unsigned char *FontBitmap; + u32 FontBitmapWidth; + u32 FontBitmapHeight; } amr_font_state; + // initialise a font and loads the font in the fontbuffer // input: // - font path @@ -28,7 +49,16 @@ typedef struct amr_font_state_debug { // output: // - error code u32 amr_InitFont(const u8 *FontPath, u8 *FontBuffer, u32 FontFz); -u32 amr_GetGlyphIdFromCodepoint(amr_glyph_info glyph, u32 *GlyphIndexArray, u32 Codepoint); +void amr_LoadFontMetrics(amr_font_state font, u32 FontSize); +void amr_LoadGlyphsFromFont(amr_DebugArena *MemoryArena, amr_font_state *font); +u32 amr_GetGlyphIdFromCodepoint(amr_font_state font, u32 Codepoint); + +////////////////////////////////////////////////////////////////////////////// +/// Naive Font Bitmap generation +/// This approach is fast but usese more memory +/// We make a single draw call, but load the entire text in a single bitmap +////////////////////////////////////////////////////////////////////////////// +void amr_MakeFontBitmapNaive(GameState *State, amr_font_state *Font, char *Text, u32 TextSize); u32 amr_InitFont(stbtt_fontinfo *font_info, const char *FontPath, u8 *FontBuffer, u32 FontSz) { @@ -42,10 +72,110 @@ u32 amr_InitFont(stbtt_fontinfo *font_info, const char *FontPath, u8 *FontBuffer return 0; } -u32 amr_GetGlyphIdFromCodepoint(amr_glyph_info glyph, u32 *GlyphIndexArray, u32 Codepoint) +void amr_LoadFontMetrics(amr_font_state *Font, f32 FontSize) +{ + // get a SF (scale factor) + Font->scale_factor = stbtt_ScaleForPixelHeight(&(Font->font_info), FontSize); + + // get vertical metrics + stbtt_GetFontVMetrics(&(Font->font_info), &(Font->ascent), + &(Font->descent), &(Font->line_gap)); +} + +void amr_LoadGlyphsFromFont(amr_DebugArena *MemoryArena, amr_font_state *Font) +{ + Font->glyph_count = Font->charset_end_index - Font->charset_start_index; + Font->glyph_index_array = (u32 *)amr_ArenaAlloc(MemoryArena, + sizeof(Font->glyph_count) * Font->glyph_count); + + u32 *array_iter = Font->glyph_index_array; + for (u32 i = 0; i < Font->glyph_count; i++) + { + u32 offset_codepoint = Font->charset_start_index + i; + *array_iter = stbtt_FindGlyphIndex(&(Font->font_info), offset_codepoint); + array_iter++; + } +} + +u32 amr_GetGlyphIdFromCodepoint(amr_font_state Font, u32 Codepoint) { - u32 glyph_id = *(GlyphIndexArray + (Codepoint - glyph.charset_start_index)); + u32 glyph_id = *(Font.glyph_index_array + (Codepoint - Font.charset_start_index)); return glyph_id; } +void amr_MakeFontBitmapNaive(GameState *State, amr_font_state *Font, char *Text, u32 TextSize) +{ + Font->MaxLineWidthPx = 0.0f; + Font->Baseline = roundf(Font->ascent * Font->scale_factor); + + u32 fd_sz = sizeof(amr_letter_details_debug)*TextSize; + amr_letter_details_debug *fd_arr = (amr_letter_details_debug *)amr_ArenaAlloc(&(State->Memory.Arena), fd_sz); + amr_letter_details_debug *_fi = fd_arr; + + f32 RunningXOffset = 0.0f; + // convert str to font + for (i32 i = 0; i < TextSize; ++i) + { + _fi->StartingXOffset = RunningXOffset; + if (Text[i] == '\n') + { + // if new line, move baseline down + Font->Baseline += (i32)roundf((Font->ascent - Font->descent + + Font->line_gap) * Font->scale_factor); + RunningXOffset = 0; + ++_fi; + continue; + } + + u32 GlyphId = amr_GetGlyphIdFromCodepoint(*Font, Text[i]); + stbtt_GetGlyphHMetrics(&(Font->font_info), GlyphId, + &_fi->advance, &_fi->lsb); + stbtt_GetGlyphBitmapBox(&(Font->font_info), GlyphId, + Font->scale_factor, Font->scale_factor, + &_fi->x0, &_fi->y0, &_fi->x1, &_fi->y1); + + _fi->StartingYOffset = (f32)(Font->Baseline + _fi->y0); + RunningXOffset += (_fi->advance * Font->scale_factor); + + if (i < TextSize - 1 && Text[i+1] != '\n') + { + i32 kern = stbtt_GetGlyphKernAdvance(&(Font->font_info), + GlyphId, amr_GetGlyphIdFromCodepoint(*Font, Text[i+1])); + RunningXOffset += roundf(kern * Font->scale_factor); + } + + if (RunningXOffset > Font->MaxLineWidthPx) + { + Font->MaxLineWidthPx = RunningXOffset; + } + ++_fi; + } + + // make all the glyphs into bitmaps. + _fi = fd_arr; + Font->FontBitmapWidth = (u32)Font->MaxLineWidthPx; + Font->FontBitmapHeight = (u32)(Font->Baseline - + roundf(Font->scale_factor * Font->descent)); + + u32 bitmap_size = sizeof(unsigned char)*Font->FontBitmapWidth*Font->FontBitmapHeight; + Font->FontBitmap = (unsigned char *)amr_ArenaAlloc(&(State->Memory.Arena), bitmap_size); + + _fi = fd_arr; + for (int i = 0; i < TextSize; i++) + { + if (Text[i] == '\n') { + ++_fi; + continue; + } + _fi->byte_offset = (i32)(_fi->StartingXOffset + roundf(_fi->lsb * Font->scale_factor) + + (_fi->StartingYOffset * Font->FontBitmapWidth)) ; + // store image data in bitmap + stbtt_MakeGlyphBitmap(&(Font->font_info), Font->FontBitmap + _fi->byte_offset, + _fi->x1 - _fi->x0, _fi->y1 - _fi->y0, Font->FontBitmapWidth, + Font->scale_factor, Font->scale_factor, + amr_GetGlyphIdFromCodepoint(*Font, Text[i])); + _fi++; + } +} + #endif |