Skip to content

Instantly share code, notes, and snippets.

@ogam
Last active August 18, 2025 14:18
Show Gist options
  • Select an option

  • Save ogam/0ebe3773c835a795c9f3357a1ec477d2 to your computer and use it in GitHub Desktop.

Select an option

Save ogam/0ebe3773c835a795c9f3357a1ec477d2 to your computer and use it in GitHub Desktop.
cute font debug view
#include <cute.h>
#include "cimgui.h"
#include "build/_deps/cute-src/src/internal/cute_font_internal.h"
#ifdef USE_PROGGY
#define FONT_NAME "ProggyClean"
#include "proggy.h"
#else
#define FONT_NAME "Calibri"
#endif
enum
{
font_state_text_aabb = 1 << 0,
font_state_glyph = 1 << 1,
};
int main(int argc, char *argv[])
{
int options = CF_APP_OPTIONS_WINDOW_POS_CENTERED_BIT | CF_APP_OPTIONS_RESIZABLE_BIT;
int display_index = 0;
int x = 0;
int y = 0;
int w = 640;
int h = 480;
CF_Result result = cf_make_app("cute text test", display_index, x, y, w, h, options, argv[0]);
if (cf_is_error(result)) return -1;
cf_app_init_imgui();
#ifdef USE_PROGGY
cf_make_font_from_memory(proggy_data, proggy_sz, FONT_NAME);
#endif
const char *text = "Some not so lOng Text";
int font_state = 0;
float font_size = 26.0f;
float font_size_min = font_size * 0.5f;
float font_size_max = font_size * 4.0f;
int glyph_index = 0;
int text_glyph_length = 0;
{
const char *s = text;
while (true)
{
int codepoint = 0;
s = cf_decode_UTF8(s, &codepoint);
if (codepoint == 0)
{
break;
}
text_glyph_length++;
}
}
while (cf_app_is_running())
{
cf_app_update(nullptr);
cf_push_font(FONT_NAME);
cf_push_font_size(font_size);
CF_V2 text_size = cf_text_size(text, -1);
CF_V2 text_position = cf_v2(0, 0);
text_position.x -= text_size.x * 0.5f;
CF_Aabb text_aabb = cf_make_aabb_from_top_left(text_position, text_size.x, text_size.y);
cf_draw_push_color(cf_color_white());
cf_draw_text(text, text_position, -1);
cf_draw_pop_color();
if (font_state & font_state_text_aabb)
{
cf_draw_push_color(cf_color_grey());
cf_draw_box(text_aabb, 0.0f, 1.0f);
cf_draw_pop_color();
}
if (font_state & font_state_glyph)
{
CF_Font* font = cf_font_get(FONT_NAME);
float x_offset = 0;
int prev_codepoint = 0;
int codepoint = 0;
int current_glyph_index = 0;
{
const char *s = text;
while (true)
{
prev_codepoint = codepoint;
s = cf_decode_UTF8(s, &codepoint);
if (current_glyph_index == glyph_index)
{
break;
}
if (codepoint == 0)
{
break;
}
CF_Glyph* glyph = cf_font_get_glyph(font, codepoint, font_size, 0);
x_offset += glyph->xadvance;
current_glyph_index ++;
}
}
if (codepoint)
{
CF_Font* font = cf_font_get(FONT_NAME);
CF_Glyph* glyph = cf_font_get_glyph(font, codepoint, font_size, 0);
float scale = stbtt_ScaleForPixelHeight(&font->info, font_size);
float ascent = font->ascent * scale;
float descent = font->descent * scale;
float line_gap = font->line_gap * scale;
float line_height = font->line_height * scale;
float kerning = cf_font_get_kern(font, font_size, prev_codepoint, codepoint);
CF_V2 glyph_position = text_position;
glyph_position.y -= line_height - ascent - descent;
glyph_position.x += x_offset;
CF_V2 glyph_min = glyph_position;
CF_V2 glyph_max = glyph_position;
glyph_min = cf_add_v2(glyph_min, glyph->q0);
glyph_max = cf_add_v2(glyph_max, glyph->q1);
CF_Aabb glyph_aabb = cf_make_aabb(glyph_min, glyph_max);
// origin
{
CF_V2 p0 = cf_v2(glyph_min.x, glyph_position.y);
CF_V2 p1 = cf_v2(glyph_max.x, glyph_position.y);
cf_draw_push_color(cf_color_red());
cf_draw_line(p0, p1, 1.0f);
cf_draw_pop_color();
}
// ascent
{
CF_V2 p0 = cf_v2(glyph_min.x, glyph_position.y + ascent);
CF_V2 p1 = cf_v2(glyph_max.x, glyph_position.y + ascent);
cf_draw_push_color(cf_color_cyan());
cf_draw_line(p0, p1, 1.0f);
cf_draw_pop_color();
}
// ascent
{
CF_V2 p0 = cf_v2(glyph_min.x, glyph_position.y + descent);
CF_V2 p1 = cf_v2(glyph_max.x, glyph_position.y + descent);
cf_draw_push_color(cf_color_orange());
cf_draw_line(p0, p1, 1.0f);
cf_draw_pop_color();
}
// xadvance
{
// offset y a bit so it doesn't overlap with origin line
CF_V2 p0 = cf_v2(glyph_min.x , glyph_position.y - descent);
CF_V2 p1 = cf_v2(glyph_min.x + glyph->xadvance, glyph_position.y - descent);
cf_draw_push_color(cf_color_yellow());
cf_draw_line(p0, p1, 1.0f);
cf_draw_pop_color();
}
cf_draw_push_color(cf_color_grey());
cf_draw_box(glyph_aabb, 0.0f, 1.0f);
cf_draw_pop_color();
}
}
cf_pop_font_size();
cf_pop_font();
igBegin("Font", 0, ImGuiWindowFlags_None);
{
igCheckboxFlags_IntPtr("Text Aabb", &font_state, font_state_text_aabb);
igCheckboxFlags_IntPtr("Glyph", &font_state, font_state_glyph);
igSliderInt("Glyph Index", &glyph_index, 0, text_glyph_length - 1, "%d", ImGuiSliderFlags_ClampOnInput);
igSliderFloat("Font Size", &font_size, font_size_min, font_size_max, "%.0f", ImGuiSliderFlags_ClampOnInput);
}
igEnd();
cf_app_draw_onto_screen(true);
}
cf_destroy_app();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment