#include "core/core.h" #include "core/core.c" #define STB_TRUETYPE_IMPLEMENTATION #define STBTT_ifloor(x) ((i32)f64_floor(x)) #define STBTT_iceil(x) ((i32)f64_ceil(x)) #define STBTT_sqrt(x) (f64_sqrt(x)) #define STBTT_fmod(x,y) (f64_mod(x,y)) #define STBTT_pow(x,y) (f64_pow(x,y)) #define STBTT_cos(x) (f64_cos(x)) #define STBTT_acos(x) (f64_acos(x)) #define STBTT_fabs(x) (f64_abs(x)) #define STBTT_malloc(x,u) ((void)u,ma_push_size(&tcx->temp,x)) #define STBTT_free(x,u) ((void)x,(void)u) #define STBTT_assert(x) assert(x) #define STBTT_strlen(x) str_len(x) #define STBTT_memcpy memory_copy #define STBTT_memset memory_set #include "vendor/stb/stb_truetype.h" #include "fira_code.c" typedef struct bitmap_t bitmap_t; struct bitmap_t { u32 *data; i32 x, y; }; typedef struct glyph_t glyph_t; struct glyph_t { bitmap_t bitmap; i32 xoff, yoff; i32 left_side_bearing, xadvance; r2f32_t tex; }; typedef struct font_t font_t; struct font_t { glyph_t glyphs[256]; bitmap_t atlas; i32 ascent, descent, line_gap, size; f32 scale; i32 height; }; fn font_t create_font(i32 size) { font_t font = {0}; font.size = size; stbtt_fontinfo stb_font; i32 rc = stbtt_InitFont(&stb_font, main_font_data, 0); assert_expr(rc != 0); font.scale = stbtt_ScaleForPixelHeight(&stb_font, (f32)font.size); stbtt_GetFontVMetrics(&stb_font, &font.ascent, &font.descent, &font.line_gap); font.height = f32_round((font.ascent - font.descent) + font.line_gap) * font.scale; for (i32 c = 0; c < 256; c += 1) { glyph_t *glyph = font.glyphs + c; u8 *temp_data = (u8 *)stbtt_GetCodepointBitmap(&stb_font, 0, font.scale, c, &glyph->bitmap.x, &glyph->bitmap.y, &glyph->xoff, &glyph->yoff); glyph->bitmap.data = ma_push_array(&tcx->temp, u32, glyph->bitmap.x * glyph->bitmap.y); for (i32 y = 0; y < glyph->bitmap.y; y += 1) { for (i32 x = 0; x < glyph->bitmap.x; x += 1) { glyph->bitmap.data[x + y * glyph->bitmap.x] = temp_data[x + y * glyph->bitmap.x] << 24; } } stbtt_GetCodepointHMetrics(&stb_font, c, &glyph->xadvance, &glyph->left_side_bearing); } return font; } fn font_t create_font_atlas(i32 size) { stbtt_fontinfo stb_font; i32 rc = stbtt_InitFont(&stb_font, main_font_data, 0); assert_expr(rc != 0); font_t font = { 0 }; font.size = size; font.atlas.x = 512; font.atlas.y = 512; font.atlas.data = ma_push_array(&tcx->temp, u32, font.atlas.x * font.atlas.y); font.scale = stbtt_ScaleForPixelHeight(&stb_font, (f32)font.size); stbtt_GetFontVMetrics(&stb_font, &font.ascent, &font.descent, &font.line_gap); i32 xiter = 2; i32 yiter = 2; i32 max_yiter_for_row = 0; for (i32 c = ' '; c < '~'; c += 1) { glyph_t *glyph = font.glyphs + (c - ' '); u8 *temp_data = (u8 *)stbtt_GetCodepointBitmap(&stb_font, 0, font.scale, c, &glyph->bitmap.x, &glyph->bitmap.y, &glyph->xoff, &glyph->yoff); if (xiter + glyph->bitmap.x >= font.atlas.x) { xiter = 0; yiter += max_yiter_for_row + 2; } glyph->tex.min.x = (f32)xiter / (f32)font.atlas.x; glyph->tex.min.y = (f32)yiter / (f32)font.atlas.y; glyph->tex.max.x = (f32)(xiter + glyph->bitmap.x)/ (f32)font.atlas.x; glyph->tex.max.y = (f32)(yiter + glyph->bitmap.y)/ (f32)font.atlas.y; max_yiter_for_row = MAX(max_yiter_for_row, glyph->bitmap.y); for (i32 y = 0; y < glyph->bitmap.y; y += 1) { for (i32 x = 0; x < glyph->bitmap.x; x += 1) { font.atlas.data[(xiter + x) + (yiter + y)*font.atlas.x] = temp_data[x + y * glyph->bitmap.x] << 24; } } xiter += glyph->bitmap.x + 2; } return font; } fn_export void init(void) { os_core_init(); } fn void draw_bitmap(bitmap_t *canvas, bitmap_t *bitmap, i32 x, i32 y) { i32 x0 = x; i32 y0 = y; i32 x1 = x + bitmap->x; i32 y1 = y + bitmap->y; i32 cx0 = CLAMP(x0, 0, canvas->x); i32 cy0 = CLAMP(y0, 0, canvas->y); i32 cx1 = CLAMP(x1, 0, canvas->x); i32 cy1 = CLAMP(y1, 0, canvas->y); if (cx0 >= cx1 || cy0 >= cy1) { return; } i32 sx_off = cx0 - x0; i32 sy_off = cy0 - y0; i32 sy = sy_off; for (i32 y = cy0; y < cy1; y += 1) { i32 sx = sx_off; for (i32 x = cx0; x < cx1; x += 1) { canvas->data[x + y * canvas->x] = bitmap->data[sx + sy * bitmap->x]; //canvas->data[x + y * canvas->x] = blend_pixel_u32(canvas->data[x + y * canvas->x], bitmap->data[sx + sy * bitmap->x]); sx += 1; } sy += 1; } } fn void draw_rect(bitmap_t *canvas, i32 x, i32 y, i32 w, i32 h, u32 color) { i32 x0 = x; i32 y0 = y; i32 x1 = x + w; i32 y1 = y + h; i32 cx0 = CLAMP(x0, 0, canvas->x); i32 cy0 = CLAMP(y0, 0, canvas->y); i32 cx1 = CLAMP(x1, 0, canvas->x); i32 cy1 = CLAMP(y1, 0, canvas->y); if (cx0 >= cx1 || cy0 >= cy1) { return; } i32 sx_off = cx0 - x0; i32 sy_off = cy0 - y0; for (i32 y = cy0; y < cy1; y += 1) { for (i32 x = cx0; x < cx1; x += 1) { canvas->data[x + y * canvas->x] = color; //canvas->data[x + y * canvas->x] = blend_pixel_u32(canvas->data[x + y * canvas->x], color); } } } fn v2i32_t draw_string(bitmap_t *canvas, font_t *font, i32 ix, i32 iy, b32 draw, char *string) { i32 xiter = 0; v2i32_t R = {0}; for (char *it = string; *it; it += 1) { glyph_t *g = font->glyphs + (*it); i32 curr_xiter = xiter; xiter += g->xadvance * font->scale; R.x = xiter; R.y = MAX(R.y, g->bitmap.y); if (!draw) { continue; } draw_bitmap(canvas, &g->bitmap, curr_xiter + g->xoff + ix, g->yoff + font->ascent*font->scale + iy); } return R; } fn_export u32 *update(i32 width, i32 height, f32 dpr) { ma_set0(&tcx->temp); u32 *pixels = ma_push_array(&tcx->temp, u32, width * height); bitmap_t canvas = {pixels, width, height}; font_t font = create_font_atlas(60); draw_bitmap(&canvas, &font.atlas, 0, 0); for (i32 i = 0; i < lengthof(font.glyphs); i += 1) { glyph_t *g = &font.glyphs[i]; i32 x = g->tex.min.x * font.atlas.x; i32 y = g->tex.min.y * font.atlas.y; i32 w = (g->tex.max.x - g->tex.min.x) * font.atlas.x; i32 h = (g->tex.max.y - g->tex.min.y) * font.atlas.y; //draw_rect(&canvas, x, y, w, h, 0xFF0000FF); } //bitmap_t canvas = {pixels, width, height}; //font_t font = create_font(60); //v2i32_t size = draw_string(&canvas, &font, 200, 500, false, "Hello world (stb)"); //draw_string(&canvas, &font, (width-size.x)/2, height - size.y*2, true, "Hello world (stb)"); return pixels; }