summaryrefslogtreecommitdiff
path: root/code/amr_fonts.h
diff options
context:
space:
mode:
authortalha <talha@talhaamir.xyz>2023-09-02 22:10:39 +0500
committertalha <talha@talhaamir.xyz>2023-09-02 22:10:39 +0500
commitb718dead6ffdef7df5836b7d9b112b4f38e82378 (patch)
treefeb5cd34cfd21199799a5864d7b9ba11d03c8200 /code/amr_fonts.h
parentdf0d5fcea9682c7890f3b0ae5e8caea2a3867199 (diff)
Adding basic font rendering functions:HEADmain
- moving existing code into separate function calls to make it easier
Diffstat (limited to 'code/amr_fonts.h')
-rw-r--r--code/amr_fonts.h156
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