From 0a18bfc95131e705772348393baa0f772200c2b5 Mon Sep 17 00:00:00 2001 From: Alessandro Mauri Date: Mon, 6 Mar 2023 19:01:15 +0100 Subject: [PATCH] housekeeping --- text_rendering/Makefile | 4 +- text_rendering/{stack.h => generic_stack.h} | 0 text_rendering/genmake.sh | 2 +- text_rendering/main.c | 6 ++ text_rendering/ren.c | 87 +++++++++++++++------ text_rendering/ren.h | 3 +- ugui.c | 4 +- ugui.h | 7 +- 8 files changed, 82 insertions(+), 31 deletions(-) rename text_rendering/{stack.h => generic_stack.h} (100%) diff --git a/text_rendering/Makefile b/text_rendering/Makefile index 6838d1a..1b9cf93 100644 --- a/text_rendering/Makefile +++ b/text_rendering/Makefile @@ -1,6 +1,6 @@ CC = gcc LDFLAGS = -lm -lgrapheme -lSDL2 -lGLEW -lGL -CFLAGS = -g -Wall -Wextra -pedantic +CFLAGS = -g -Wall -Wextra -pedantic -fno-omit-frame-pointer .PHONY: clean all all: test @@ -9,7 +9,7 @@ font.o: font.c font.h stb_truetype.h stb_image_write.h util.h \ generic_cache.h hash.h hash.o: hash.c hash.h util.h main.o: main.c ren.h util.h -ren.o: ren.c util.h font.h ren.h stack.h +ren.o: ren.c util.h font.h ren.h generic_stack.h util.o: util.c util.h test: font.o hash.o main.o ren.o util.o ${CC} ${LDFLAGS} -o test font.o hash.o main.o ren.o util.o diff --git a/text_rendering/stack.h b/text_rendering/generic_stack.h similarity index 100% rename from text_rendering/stack.h rename to text_rendering/generic_stack.h diff --git a/text_rendering/genmake.sh b/text_rendering/genmake.sh index 09c925e..be25540 100755 --- a/text_rendering/genmake.sh +++ b/text_rendering/genmake.sh @@ -16,7 +16,7 @@ rm -f objlist cat > Makefile << EOF CC = gcc LDFLAGS = -lm -lgrapheme -lSDL2 -lGLEW -lGL -CFLAGS = -g -Wall -Wextra -pedantic +CFLAGS = -g -Wall -Wextra -pedantic -fno-omit-frame-pointer .PHONY: clean all all: test diff --git a/text_rendering/main.c b/text_rendering/main.c index fcc0519..6af1070 100644 --- a/text_rendering/main.c +++ b/text_rendering/main.c @@ -44,6 +44,12 @@ int main(void) } + int w, h; + const char *s = "ciao mamma"; + ren_get_text_box(s, &w, &h, 12); + printf("box for: %s -> (%d, %d)\n", s, w, h); + + SDL_Event e; while(1) { SDL_WaitEvent(&e); diff --git a/text_rendering/ren.c b/text_rendering/ren.c index 91f5515..26aa9ab 100644 --- a/text_rendering/ren.c +++ b/text_rendering/ren.c @@ -69,7 +69,7 @@ const char *glerr[] = { // different stacks -#include "stack.h" +#include "generic_stack.h" STACK_DECL(vtstack, struct v_text) STACK_DECL(vcstack, struct v_col) @@ -240,6 +240,15 @@ static GLuint ren_texturergb_2d(const char *buf, int w, int h, int upscale, int } +static void set_texture_parameters(GLuint type, GLuint wrap_s, GLuint wrap_t, GLuint upscale, GLuint downscale) +{ + GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s)) + GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t)) + GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, upscale)) + GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, downscale)) +} + + static GLuint ren_texturergba_2d(const char *buf, int w, int h, int upscale, int downscale) { GLuint t; @@ -252,11 +261,7 @@ static GLuint ren_texturergba_2d(const char *buf, int w, int h, int upscale, int GL(glBindTexture(GL_TEXTURE_2D, t)) GL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf)) - - GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)) - GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)) - GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, downscale)) - GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, upscale)) + set_texture_parameters(GL_TEXTURE_2D, GL_REPEAT, GL_REPEAT, upscale, downscale); return t; } @@ -274,11 +279,7 @@ static GLuint ren_texturer_2d(const char *buf, int w, int h, int upscale, int do GL(glBindTexture(GL_TEXTURE_2D, t)) GL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, buf)) - - GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)) - GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)) - GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, downscale)) - GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, upscale)) + set_texture_parameters(GL_TEXTURE_2D, GL_REPEAT, GL_REPEAT, upscale, downscale); return t; } @@ -296,13 +297,9 @@ static GLuint ren_texturer_rect(const char *buf, int w, int h, int upscale, int GL(glBindTexture(GL_TEXTURE_RECTANGLE, t)) GL(glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RED, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, buf)) - // a limitation of recatngle textures is that the wrapping mode is limited // to either clamp-to-edge or clamp-to-border - GL(glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)) - GL(glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)) - GL(glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, downscale)) - GL(glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, upscale)) + set_texture_parameters(GL_TEXTURE_RECTANGLE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, upscale, downscale); return t; } @@ -444,15 +441,18 @@ int ren_clear(void) // only one font size at the time can be used static int ren_draw_font_stack(int idx) { + struct font_atlas *font = ren.fonts[idx].font; + GLuint font_texture = ren.fonts[idx].texture; + GL(glUseProgram(ren.font_prog)) GL(glBindBuffer(GL_ARRAY_BUFFER, ren.font_buffer)) - GL(glBindTexture(GL_TEXTURE_RECTANGLE, ren.fonts[idx].texture)) + GL(glBindTexture(GL_TEXTURE_RECTANGLE, font_texture)) GL(glViewport(0, 0, ren.width, ren.height)) // this has caused me some trouble, convert from image coordiates to viewport GL(glScissor(ren.s_x, ren.height-ren.s_y-ren.s_h, ren.s_w, ren.s_h)) GL(glUniform2i(ren.viewsize_loc, ren.width, ren.height)) - GL(glUniform2i(ren.texturesize_loc, ren.fonts[idx].font->width, ren.fonts[idx].font->height)) + GL(glUniform2i(ren.texturesize_loc, font->width, font->height)) GL(glEnableVertexAttribArray(REN_VERTEX_IDX)) GL(glEnableVertexAttribArray(REN_UV_IDX)) @@ -632,15 +632,56 @@ static int ren_push_glyph(const struct font_glyph *g, int gx, int gy) } -// TODO: implement font size +// TODO: reduce repeating patterns in ren_get_text_box() and ren_render_text() +int ren_get_text_box(const char *str, int *rw, int *rh, int size) +{ + int w = 0, h = 0, x = 0, y = 0, updated; + const struct font_glyph *g; + size_t off, ret; + uint32_t cp; + int idx = ren_get_font(size); + if (idx < 0) + return -1; + + for (off = 0; (ret = grapheme_decode_utf8(str+off, SIZE_MAX, &cp)) > 0 && cp != 0; off += ret) { + if (iscntrl(cp)) goto skip_get; + g = font_get_glyph_texture(ren.fonts[idx].font, cp, &updated); + if (!g) REN_RET(-1, REN_FONT); + if (updated) { + if (update_font_texture(idx)) + REN_RET(-1, REN_TEXTURE); + } + + skip_get: + x += g->x + g->a; + switch (cp) { + case '\r': + x = 0; + break; + case '\n': + // TODO: encode and/or store line height + y += ren.fonts[idx].font->glyph_max_h; + x = 0; + break; + default: break; + } + + if (x > w) w = x; + if (y > h) h = y; + } + + if (rw) *rw = w; + if (rh) *rh = h; + + return 0; +} + + int ren_render_text(const char *str, int x, int y, int w, int h, int size) { - // FIXME: the bounding box (scissor) logic does not work - // TODO: create a method for calculating the total bounding box of a string - // given the box size const struct font_glyph *g; size_t ret, off; - uint_least32_t cp; + uint32_t cp; int updated, gx = x, gy = y; int idx = ren_get_font(size); if (idx < 0) diff --git a/text_rendering/ren.h b/text_rendering/ren.h index 443dec1..0bd1837 100644 --- a/text_rendering/ren.h +++ b/text_rendering/ren.h @@ -43,8 +43,9 @@ int ren_init(SDL_Window *sdl_window); int ren_free(void); const char * ren_strerror(void); int ren_update_viewport(int w, int h); -int ren_render_text(const char *str, int x, int y, int w, int h, int size); int ren_set_scissor(int x, int y, int w, int h); +int ren_get_text_box(const char *str, int *rw, int *rh, int size); +int ren_render_text(const char *str, int x, int y, int w, int h, int size); int ren_render_box(int x, int y, int w, int h, unsigned int color); int ren_clear(void); diff --git a/ugui.c b/ugui.c index 7e09c0e..57e83c9 100644 --- a/ugui.c +++ b/ugui.c @@ -244,7 +244,7 @@ static void push_text_command(ug_ctx_t *ctx, ug_vec2_t pos, int size, ug_color_t } -ug_cmd_t *ug_cmd_next(ug_ctx_t *ctx) +ug_cmd_t * ug_cmd_next(ug_ctx_t *ctx) { if(!ctx) return NULL; @@ -260,7 +260,7 @@ ug_cmd_t *ug_cmd_next(ug_ctx_t *ctx) // creates a new context, fills with default values, ctx is ready for ug_start() -ug_ctx_t *ug_ctx_new(void) +ug_ctx_t * ug_ctx_new(void) { ug_ctx_t *ctx = malloc(sizeof(ug_ctx_t)); if (!ctx) diff --git a/ugui.h b/ugui.h index c7b68e8..bb286a4 100644 --- a/ugui.h +++ b/ugui.h @@ -216,9 +216,12 @@ typedef struct { // context initialization -ug_ctx_t *ug_ctx_new(void); +ug_ctx_t * ug_ctx_new(void); void ug_ctx_free(ug_ctx_t *ctx); // updates the context with user information +// ppi: pixels per inch, the scale used for all em/mm to pixel calculations +// scale: it is the scale between the physical pixels on the screen and the pixels +// on the buffer, if unsure set to 1.0 int ug_ctx_set_displayinfo(ug_ctx_t *ctx, float scale, float ppi); int ug_ctx_set_drawableregion(ug_ctx_t *ctx, ug_vec2_t size); int ug_ctx_set_style(ug_ctx_t *ctx, const ug_style_t *style); @@ -273,7 +276,7 @@ int ug_frame_end(ug_ctx_t *ctx); // Commands // get the next command, save iteration state inside 'iterator' -ug_cmd_t *ug_cmd_next(ug_ctx_t *ctx); +ug_cmd_t * ug_cmd_next(ug_ctx_t *ctx); #undef UG_STACK