From 805f633af0a199446b958983b8d3b663aade4eeb Mon Sep 17 00:00:00 2001 From: Alessandro Mauri Date: Thu, 16 Feb 2023 23:33:19 +0100 Subject: [PATCH] roooma --- text_rendering/atlas.png | Bin 20174 -> 20172 bytes text_rendering/font.c | 13 ++++++--- text_rendering/ren.c | 53 ++++++++++++++++++++++++++++++++++ text_rendering/stack.h | 61 +++++++++++++++++++++++++++++++++++++++ text_rendering/test | Bin 287952 -> 287968 bytes 5 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 text_rendering/ren.c create mode 100644 text_rendering/stack.h diff --git a/text_rendering/atlas.png b/text_rendering/atlas.png index c1e59c623a89ec04ec647ee12b34f223e1a767a0..754a74d794ab503cb772e32a4a99d0663bc64ee7 100644 GIT binary patch delta 13178 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 diff --git a/text_rendering/font.c b/text_rendering/font.c index 0188c43..c50ac54 100644 --- a/text_rendering/font.c +++ b/text_rendering/font.c @@ -123,14 +123,19 @@ const struct font_glyph * font_get_glyph_texture(struct font_atlas *atlas, unsig atlas->priv.scale, 2.0f/glyph_h, &atlas->priv.ctx); - if (!err) - return NULL; + // msdf_genGlyph returns 0 only when there are no contours, so only for + // whitespace and such, for those insert a zero uv map into the cache + // FIXME: this is a waste of space + if (!err) { + atlas->priv.msdf.width = 0; + atlas->priv.msdf.height = 0; + } unsigned int spot = cache_get(); unsigned int oy = (glyph_h * spot) / atlas->width; unsigned int ox = (glyph_h * spot) % atlas->height; - unsigned int w = atlas->width; + unsigned int w = atlas->width; // sum magic shit struct {unsigned char r,g,b;} *a = (void *)atlas->atlas; @@ -180,7 +185,7 @@ const struct font_glyph * font_get_glyph_texture(struct font_atlas *atlas, unsig void font_dump(const struct font_atlas *atlas, const char *path) { stbi_write_png( - path, + path, //atlas->width, //atlas->height, 128, 128, diff --git a/text_rendering/ren.c b/text_rendering/ren.c new file mode 100644 index 0000000..90313c4 --- /dev/null +++ b/text_rendering/ren.c @@ -0,0 +1,53 @@ +#include +#include +#include + + +#define GLSL_VERT_SHADER "vertex.glsl" +#define GLSL_FRAG_SHADER "fragment.glsl" +#define PACKED __attribute__((packed)) + + +struct { + SDL_Window *w; + SDL_GLContext *gl; + GLuint gl_vertbuffer; + GLuint gl_program; + GLuint font_texture; +} ren = {0}; + + +typedef struct PACKED { + union { GLint x, u; }; + union { GLint y, v; }; +} vec2_i; + +typedef struct PACKED { + union { GLint x, r; }; + union { GLint y, g; }; + union { GLint z, b; }; + union { GLint w, a; }; +} vec4_i; + +// textured vertex +struct PACKED v_text { + vec2_i pos; + vec2_i uv; +}; + +// colored vertex +struct PACKED v_col { + vec2_i pos; + vec2_i col; +}; + + +// different stacks +#define _STACK_NAME vtstack +#define _STACK_TYPE struct v_text +#include "stack.h" +#undef _STACK_NAME +#undef _STACK_TYPE +#define _STACK_NAME vcstack +#define _STACK_TYPE struct v_col +#include "stack.h" diff --git a/text_rendering/stack.h b/text_rendering/stack.h new file mode 100644 index 0000000..4074b1f --- /dev/null +++ b/text_rendering/stack.h @@ -0,0 +1,61 @@ +#ifdef _STACK_TYPE +#ifdef _STACK_NAME + + +#ifndef _STACK_REALLOC + #define _STACK_REALLOC(p, s) realloc(p,s) +#endif +#ifndef _STACK_MEMSET + #define _STACK_MEMSET(p, c, s) memset(p,c,s) +#endif +#ifndef _STACK_STEP + #define _STACK_STEP 8 +#endif +#ifndef _STACK_CAT + #define _STACK_CAT_I(a,b) a ## b + #define _STACK_CAT(a,b) _STACK_CAT_I(a,b) +#endif + + +// TODO: add a rolling hash +struct _STACK_NAME { + _STACK_TYPE *items; + int size, idx; +}; + + +int _STACK_CAT(stack_grow_,_STACK_NAME)(struct _STACK_NAME *stack, int step) +{ + if (!stack) + return -1; + stack->items = _STACK_REALLOC(stack->items, (stack->size+step)*sizeof(_STACK_TYPE)); + if(!stack->items) + return -1; + _STACK_MEMSET(&(stack->items[stack->size]), 0, step*sizeof(*(stack->items))); + stack->size += step; + return 0; +} + + +int _STACK_CAT(stack_push_,_STACK_NAME)(struct _STACK_NAME *stack, _STACK_TYPE *e) +{ + if (!stack || !e) + return -1; + if (stack->idx >= stack->size) + if (_STACK_CAT(stack_grow_,_STACK_NAME)(stack, _STACK_STEP)) + return -1; + stack->items[stack->idx++] = *e; + return 0; +} + + +int _STACK_CAT(stack_clear_,_STACK_NAME)(struct _STACK_NAME *stack) +{ + if (!stack) + return -1; + stack->idx = 0; +} + + +#endif +#endif diff --git a/text_rendering/test b/text_rendering/test index 7ba4c45b0949557d261ad794105c7c4855c05277..69d543bd43aa2e3c016cc7cea74a64b23ef97dfb 100755 GIT binary patch delta 3250 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