From eb9b0078c28099435f147f1bbb388b6ebfb35712 Mon Sep 17 00:00:00 2001 From: Yann MAGNIN Date: Thu, 2 Jun 2022 10:16:25 +0200 Subject: [PATCH] VxKernel 0.6.0-3 : Fix dstack crash + pixel API + support assets generation @add <> include/vhex/display/draw/pixel : | add pixel drawing API <> modules/display/draw/dpixel | add pixel drawing API code @update <> board/fxcg50/board : | remove old DWIDTH/DHEIGHT display API dependencies (use the new driver | interface instead). <> include/vhex/display/font : | update the font structure information <> include/vhex/display/shader : | switch x/y to unsigned int to signed int to avoid many cast in render | primitives <> make/Makefile | support header modification detection (header dependencies) | support assets generation <> modules/display/text/font <> modules/display/text/text | prepare drawing algorithm (WIP) @fix <> kernel/drivers/screen/r61524/r61524 | proper handle geometry of each drawing area | fix clear loop boundary | fix render loop boundary <> modules/display/dstack | fix shader index | remove useless extern keyword --- board/fxcg50/board.ini | 2 +- board/fxcg50/fxcg50.ld | 11 -- include/vhex/display/draw/pixel.h | 24 +++++ include/vhex/display/font.h | 60 +++++------ include/vhex/display/shader.h | 4 +- make/Makefile | 47 +++++++-- src/drivers/screen/R61524/r61524.c | 7 +- src/kernel/exch.c | 1 - src/modules/display/draw/dhline.c | 3 +- src/modules/display/draw/dline.c | 2 + src/modules/display/draw/dpixel.c | 55 ++++++++-- src/modules/display/draw/drect.c | 2 + src/modules/display/dstack.c | 9 +- src/modules/display/text/dfont.c | 162 +++++++++++++++++++++++++++-- src/modules/display/text/dtext.c | 68 ++++++------ 15 files changed, 336 insertions(+), 121 deletions(-) create mode 100644 include/vhex/display/draw/pixel.h diff --git a/board/fxcg50/board.ini b/board/fxcg50/board.ini index 005b434..b04f743 100644 --- a/board/fxcg50/board.ini +++ b/board/fxcg50/board.ini @@ -7,5 +7,5 @@ mpu=sh7305 [toolchain] prefix=sh-elf-vhex- -cflags=-DFXCG50,-m4-nofpu,-mb,-DWIDTH=396,-DHEIGHT=224 +cflags=-DFXCG50,-m4-nofpu,-mb libs=-lgcc diff --git a/board/fxcg50/fxcg50.ld b/board/fxcg50/fxcg50.ld index ac05ac4..4801d82 100644 --- a/board/fxcg50/fxcg50.ld +++ b/board/fxcg50/fxcg50.ld @@ -100,17 +100,6 @@ SECTIONS /* dynamic BSS information (move me ?) */ *(.dynbss) - - /* Video RAM symbols - The video RAM contains a full pixel sized frame for the - screen. Its size is 396x224 and each pixel depth is 16its, - so (3996 * 224) * 2 = 177408 - */ - _vhex_vram = ALIGN(4); - - /* create the VRAM gap */ - . = _vhex_vram + 177408; - } > userram /* Vhex VBR management geometry diff --git a/include/vhex/display/draw/pixel.h b/include/vhex/display/draw/pixel.h new file mode 100644 index 0000000..72299ff --- /dev/null +++ b/include/vhex/display/draw/pixel.h @@ -0,0 +1,24 @@ +#ifndef __VHEX_DISPLAY_DRAW_PIXEL__ +# define __VHEX_DISPLAY_DRAW_PIXEL__ + +#include +#include + +//--- +// User-level API +//--- + +/* dpixel() : draw a pixel in screen */ +extern did_t dpixel(int x, int y, int color); + +//--- +// Kernel-level API +//--- + +/* dpixel_render_dstack() : dstack-API compatible render */ +extern void dpixel_render_dstack(struct dshader_surface *surface, uint32_t *arg); + +/* dpixel_render() : drawing algorithm */ +extern void dpixel_render(struct dshader_surface *surface, int x, int y, int c); + +#endif /* __VHEX_DISPLAY_DRAW_PIXEL__ */ diff --git a/include/vhex/display/font.h b/include/vhex/display/font.h index e9c7dff..23890cd 100644 --- a/include/vhex/display/font.h +++ b/include/vhex/display/font.h @@ -20,45 +20,41 @@ typedef struct font { uint8_t prop :1; ); - /* Line height */ - uint8_t line_height; - /* Storage height */ - uint8_t data_height; - - /* Number of Unicode blocks */ - uint8_t block_count; - /* Number of total glyphs */ - uint32_t glyph_count; - /* Character spacing (usually 1) */ uint8_t char_spacing; + /* glyph information */ struct { - /* Unicode point of first character in block */ - uint32_t start :20; - /* Length of block */ - uint32_t length :12; - } *blocks; + uint8_t height; + uint8_t line_height; + uint32_t *data; + uint32_t count; - /* Raw glyph data */ - uint32_t *data; + union { + /* For monospaced fonts */ + struct { + uint8_t width; + uint16_t storage_size; + } mono; + /* For proportional fonts */ + struct __workaround { + uint8_t width; + uint16_t index; + uint8_t shift; + } *prop; + }; + } glyph; - union { - /* For monospaced fonts */ + /* unicode blocks */ + struct { struct { - /* Width of glyphs */ - uint16_t width; - /* Storage size, in longwords, of each glyph */ - uint16_t storage_size; - }; - /* For proportional fonts */ - struct { - /* Storage index to find glyphs quickly */ - uint16_t *glyph_index; - /* Width of each individual glyph */ - uint8_t *glyph_width; - }; - }; + /* Unicode point of first character in block */ + uint32_t start :20; + /* Length of block */ + uint32_t length :12; + } *blocks; + uint8_t block_count; + } unicode; } VPACKED(4) font_t; diff --git a/include/vhex/display/shader.h b/include/vhex/display/shader.h index 90fd8ab..2948702 100644 --- a/include/vhex/display/shader.h +++ b/include/vhex/display/shader.h @@ -10,8 +10,8 @@ struct dshader_surface { void *frag; size_t width; size_t height; - unsigned int x; - unsigned int y; + int x; + int y; }; /* dshader - display shader definition */ diff --git a/make/Makefile b/make/Makefile index 025dbc5..d9ad5df 100644 --- a/make/Makefile +++ b/make/Makefile @@ -1,13 +1,11 @@ #!/usr/bin/make -f # --- # Project: vxKernek - Vhex project kernel -# Author: yann.magnin@epitech.eu +# Author: yann.magnin@protonmail.com # # TODO: -# <> support header modification detection -# <> remove "target" folder on any directory -# <> installation rule -# <> uninstall rule +# <> proper clean rule +# <> support asset generation # --- @@ -100,7 +98,8 @@ nocolor := \033[1;0m # *3 - source file path # *4 - build root directory path # *5 - object file compilation rule list -# *6 - unique id (used to generate unique variable name (workaround)) +# *6 - dependencies file compilation rule list +# *7 - unique id (used to generate unique variable name (workaround)) define generate-compile-file-rule # generate the object file path @@ -110,7 +109,7 @@ define generate-compile-file-rule # 1) ../board/path/file.c -> ../board/path/file # 2) .._board_path_file -> board_path_file # 3) board_path_file.o -> {build path}/board_path_file.o -tname := $(strip $6) +tname := $(strip $7) obj-$(tname)-name := $$(basename $3) obj-$(tname)-name := $$(subst /,_,$$(obj-$(tname)-name)) obj-$(tname)-name := $$(patsubst .._%,$4/%.o,$$(obj-$(tname)-name)) @@ -121,14 +120,15 @@ $$(obj-$(tname)-name): $3 @ mkdir -p $$(dir $$@) ifeq ($(CONFIG.VERBOSE),false) @ printf "$(green)>$(nocolor) $(white)$$@$(nocolor)\n" - @ $1 $2 -o $$@ -c $$< + @ $1 $2 -o $$@ -c $$< -MMD -MT $$@ -MF $$@.d -MP else - $1 $2 -o $$@ -c $$< + $1 $2 -o $$@ -c $$< -MMD -MT $$@ -MF $$@.d -MP endif -# register the buildinf rule +# register the build rules and dependencies file name $5 += $$(obj-$(tname)-name) +$6 += $$(obj-$(tname)-name).d endef @@ -190,6 +190,7 @@ endif # list variable, this will be used by the `main` rule t-$1-$2-obj := +t-$1-$2-dep := $$(foreach source,$$(t-$1-$2-src),$$(eval \ $$(call generate-compile-file-rule,\ $$(t-$1-$2-gcc),\ @@ -197,15 +198,33 @@ $$(foreach source,$$(t-$1-$2-src),$$(eval \ $$(source),\ $$(t-$1-$2-build),\ t-$1-$2-obj,\ + t-$1-$2-dep,\ $1-$2\ ))\ ) +# asset generation +t-$1-$2-asset := $(patsubst \ + $(VXSDK_ASSETS_SRC)/%,\ + $(VXSDK_ASSETS_BUILD)/$1/$2/%.o,\ + $(wildcard $(VXSDK_ASSETS_SRC)/*.c) \ +) + +$(VXSDK_ASSETS_BUILD)/$1/$2/%.o: $(VXSDK_ASSETS_SRC)/% +ifeq ($(CONFIG.VERBOSE),true) + @ mkdir -p $$(dir $$@) + sh-elf-vhex-gcc $$(t-$1-$2-cflags) -o $$@ -c $$< +else + @ mkdir -p $$(dir $$@) + @ printf "$(green)>$(nocolor) $(white)$@$(nocolor)\n" + @ sh-elf-vhex-gcc $$(t-$1-$2-cflags) -o $$@ -c $$< +endif # generate the "main" rule for this lib -$$(t-$1-$2-exec): $$(t-$1-$2-obj) +$$(t-$1-$2-exec): $$(t-$1-$2-obj) $$(t-$1-$2-asset) @ mkdir -p $$(dir $$@) + @ echo "dep : $$(t-$1-$2-dep)" @ printf "$(blue)Create the library $(red)$$@$(nocolor)\n" ifeq ($2,dynamic) $$(t-$1-$2-gcc) -shared $$(t-$1-$2-cflags) $$(t-$1-$2-gcc-libs) -o $$@ $$^ @@ -217,6 +236,12 @@ endif $3 += $$(t-$1-$2-exec) + +# import dependencies rules +-include $$(t-$1-$2-dep) +$$(t-$1-$2-dep): ; +.PRECIOUS: $$(t-$1-$2-dep) + endef diff --git a/src/drivers/screen/R61524/r61524.c b/src/drivers/screen/R61524/r61524.c index 70a33e9..afc1742 100644 --- a/src/drivers/screen/R61524/r61524.c +++ b/src/drivers/screen/R61524/r61524.c @@ -17,7 +17,7 @@ VINLINE void r61524_clear_surface(struct dshader_surface *surface) // > restrict / non-restrict uint32_t * restrict xram = surface->draw; uint32_t * restrict yram = surface->frag; - for (int i = 0; i < 2048; ++i) { + for (int i = 0; i < 1980; ++i) { xram[i] = 0x00010001; yram[i] = 0x00000000; } @@ -60,6 +60,7 @@ int r61524_frame_start(struct dshader_surface *surface) int r61524_frame_frag_next(struct dshader_surface *surface) { + //TODO: perf if culling at the end (220) surface->y += 10; if (surface->y >= 224) { surface->y -= 10; @@ -71,6 +72,8 @@ int r61524_frame_frag_next(struct dshader_surface *surface) int r61524_frame_frag_send(struct dshader_surface *surface) { + //static int counter = 0; + //TODO: assembly //TODO: check cache behaviour: // > full xram then yram @@ -80,7 +83,7 @@ int r61524_frame_frag_send(struct dshader_surface *surface) uint16_t pixel; uint16_t * restrict xram = surface->draw; uint16_t * restrict yram = surface->frag; - for (int i = 0; i < 4096; ++i) { + for (int i = 0; i < 3960; ++i) { pixel = xram[i]; if (pixel & 0x0001) { r61524_write(yram[i]); diff --git a/src/kernel/exch.c b/src/kernel/exch.c index 61c6442..43c0337 100644 --- a/src/kernel/exch.c +++ b/src/kernel/exch.c @@ -52,6 +52,5 @@ void vhex_kernel_exch_panic(void) dtext(6, 121, C_BLACK, "calculator."); dupdate(); #endif - while (1) { __asm__ volatile ("sleep"); } } diff --git a/src/modules/display/draw/dhline.c b/src/modules/display/draw/dhline.c index 0560337..85ca0d0 100644 --- a/src/modules/display/draw/dhline.c +++ b/src/modules/display/draw/dhline.c @@ -1,3 +1,4 @@ +#if 0 #include #include #include @@ -48,4 +49,4 @@ void dvline(int y1, int y2, int x, int color) while(height-- > 0) *v = color, v += 396; } - +#endif diff --git a/src/modules/display/draw/dline.c b/src/modules/display/draw/dline.c index 0e9703b..659f920 100644 --- a/src/modules/display/draw/dline.c +++ b/src/modules/display/draw/dline.c @@ -1,3 +1,4 @@ +#if 0 #include #include @@ -59,3 +60,4 @@ void dline(int x1, int y1, int x2, int y2, int color) dpixel(x2, y2, color); } +#endif diff --git a/src/modules/display/draw/dpixel.c b/src/modules/display/draw/dpixel.c index fa998d9..fa4145d 100644 --- a/src/modules/display/draw/dpixel.c +++ b/src/modules/display/draw/dpixel.c @@ -2,19 +2,56 @@ #include #include +//--- +// Kernel-level API +//--- -VWEAK void dpixel(int x, int y, int color) +/* dpixel_render() : drawing algorithm */ +void dpixel_render(struct dshader_surface *surface, int x, int y, int color) { - extern uint16_t vhex_vram[]; - if (color == C_NONE) return; - if ((unsigned int)x < 396 && (unsigned int)y < 224) { - if (color == C_INVERT) { - vhex_vram[(y * 396) + x] ^= 0xffff; - return; - } - vhex_vram[(y * 396) + x] = color; + + /* check point culling */ + if (y < surface->y + || x < surface->x + || y >= (int)(surface->y + surface->height) + || x >= (int)(surface->x + surface->width)) { + return; } + /* calculate the draw index */ + int real_y = (y - surface->y) * surface->width; + int real_x = (x - surface->x); + int draw_idx = real_y + real_x; + + /* handle special color */ + //uint16_t *draw = surface->draw; + uint16_t *frag = surface->frag; + if (color == C_INVERT) + color = frag[draw_idx] ^ 0xffff; + + /* set the pixel */ + frag[draw_idx] = color; } + +/* dpixel_render_dstack() : dstack-API compatible render */ +void dpixel_render_dstack(struct dshader_surface *surface, uint32_t *arg) +{ + dpixel_render(surface, arg[0], arg[1], arg[2]); +} + +//--- +// User-level API +//--- + +/* dpixel() : draw a pixel in screen */ +did_t dpixel(int x, int y, int color) +{ + return dstack_add_action( + &DSTACK_CALL(&dpixel_render_dstack, x, y, color), + NULL, + NULL + ); +} + diff --git a/src/modules/display/draw/drect.c b/src/modules/display/draw/drect.c index 7c92a2f..fda8f21 100644 --- a/src/modules/display/draw/drect.c +++ b/src/modules/display/draw/drect.c @@ -1,3 +1,4 @@ +#if 0 #include #include #include @@ -51,3 +52,4 @@ void drect(int x1, int y1, int x2, int y2, int color) base += 396; } } +#endif diff --git a/src/modules/display/dstack.c b/src/modules/display/dstack.c index dc09b1f..faf9bcf 100644 --- a/src/modules/display/dstack.c +++ b/src/modules/display/dstack.c @@ -97,6 +97,7 @@ static did_t dstack_action_alloc( } action = &dstack_info.pool.action[dstack_info.pool.idx]; memcpy(&action->call, call, sizeof(dstack_call_t)); + action->shader.idx = -1; if (shader != NULL) { for (i = 0; shader[i].routine != NULL; ++i) { if (i >= action->shader.number) { @@ -113,8 +114,8 @@ static did_t dstack_action_alloc( ); action->quit = quit; } + action->shader.idx = i; } - action->shader.idx = i; return dstack_info.pool.idx; } @@ -143,7 +144,7 @@ void dstack_render(void) do { for (int i = 0; i <= dstack_info.pool.idx; ++i) { action[i].call.routine(&surface, action[i].call.args); - for (int j = 0; j < action[i].shader.idx; j++) { + for (int j = 0; j <= action[i].shader.idx; j++) { action[i].shader.table[j].routine( &surface, action[i].call.args, @@ -164,13 +165,13 @@ void dstack_render(void) /* dstack_display_width() : return the display width */ -extern size_t dstack_display_width(void) +size_t dstack_display_width(void) { return dstack_info.driver.display_width; } /* dstack_display_height() : return the display height */ -extern size_t dstack_display_height(void) +size_t dstack_display_height(void) { return dstack_info.driver.display_height; } diff --git a/src/modules/display/text/dfont.c b/src/modules/display/text/dfont.c index 4c92be0..7b0e2ab 100644 --- a/src/modules/display/text/dfont.c +++ b/src/modules/display/text/dfont.c @@ -45,6 +45,7 @@ static uint32_t dfont_utf8_next(uint8_t const **str_pointer) return 0x20; } +#if 0 /* dfont_glyph_index(): Obtain the glyph index of a Unicode code point */ int dfont_glyph_index(font_t const *f, uint32_t code_point) { @@ -61,7 +62,152 @@ int dfont_glyph_index(font_t const *f, uint32_t code_point) return -1; } +#endif +/* dfont_glyph_index(): Obtain the glyph index of a Unicode code point */ +//TODO: suport unicode block +static int dfont_glyph_index(font_t const *f, uint32_t code_point) +{ + code_point -= ' '; + if ((int)code_point < 0 || code_point >= f->glyph.count) + return (-1); + return code_point; +} + +/* dfont_char_render() : */ +static void dfont_char_render( + struct dshader_surface *surface, + int glyph_idx, + int x, + int y +) { + int glyph_shift; + int glyph_width; + int glyph_size; +// int surfa_idx; +// int surfa_shift; + font_t *font; + int counter; + int sx; + + (void)surface; + + /* generate font index / shift information */ + font = dfont_get(); + if (font->shape.prop == 1) { + glyph_width = font->glyph.prop[glyph_idx].width; + glyph_shift = font->glyph.prop[glyph_idx].shift; + glyph_idx = font->glyph.prop[glyph_idx].index; + glyph_size = glyph_width * font->glyph.height; + } else { + glyph_width = font->glyph.mono.width; + glyph_size = font->glyph.mono.storage_size; + glyph_shift = glyph_size * glyph_idx; + glyph_idx = glyph_shift >> 8; + glyph_shift = glyph_shift & 0xff; + } + + /* drawing algo */ + //TODO: cache surface data (limit read/write) + sx = x; + counter = 0; + glyph_shift = 0x80000000 >> glyph_shift; + for (int i = 0; i < glyph_size; ++i) + { +#if 0 + if (x >= surface->x + && x <= surfa_mx + && y >= surface->y + && y <= surfa_my) { + tmp0 = (y - surface->y) * 396; + tmp1 = (x - surface->x); + surfa_idx = (tmp0 + tmp1) >> 2; + surfa_shift = (tmp0 + tmp1) & 0xff; + if (font->glyph.data[glyph_idx] & glyph_shift) { + surface->frag[surfa_idx] = (uint16_t)arg[4]; + } else { + surface->frag[surfa_idx] = (uint16_t)arg[5]; + } + } +#endif + + /* update font bitmap index / shift */ + glyph_shift >>= 1; + if (glyph_shift == 0x00000000) { + glyph_shift = 0x80000000; + glyph_idx += 1; + } + + /* update bitmap position */ + x += 1; + counter += 1; + if (counter >= glyph_width) { + counter = 0; + x = sx; + y += 1; + } + } +} + +//--- +// Kernel API +//--- + + +/* dfont_render() : draw caracter in surface */ +void dfont_text_render(struct dshader_surface *surface, uint32_t *arg) +{ + int x; + int y; + int mx; + int my; + + /* check culling */ + x = arg[0]; + y = arg[1]; + mx = arg[2]; + my = arg[3]; + if (my < surface->y + || mx < surface->x + || y > (int)(surface->y + surface->height) + || x > (int)(surface->x + surface->width)) { + return; + } + + uint8_t const *str = (void*)(uintptr_t)arg[6]; + int nb_char = arg[7]; + int counter = -1; + uint32_t code_point; + font_t *font = dfont_get(); + int glyph_idx; + int glyph_width; + + /* draw algo (update me) */ + while (++counter < nb_char) + { + /* get glyph geometry information */ + code_point = dfont_utf8_next(&str); + glyph_idx = dfont_glyph_index(font, code_point); + glyph_width = font->glyph.mono.width; + if (font->shape.prop == 1) + glyph_width = font->glyph.prop[glyph_idx].width; + + /* check char culling */ + if (x >= surface->x + && y >= surface->y + && y < (int)(surface->y + surface->height) + && x < (int)(surface->x + surface->width)) { + dfont_char_render(surface, glyph_idx, x, y); + } + + /* line discipline */ + x += glyph_width + font->char_spacing; + if (code_point == '\n') { + y += font->glyph.height; + x = arg[0]; + } + } +} //--- // Public API @@ -91,8 +237,8 @@ int dfont_text_geometry( size_t mx = 0; size_t x = 0; size_t y = 0; + int glyphidx; int limit; - int glyph; /* handle special behaviour */ if (font == NULL) @@ -107,18 +253,18 @@ int dfont_text_geometry( if (code_point == 0 || (limit > 0 && str0 - str1 >= limit)) break; - char_width = font->width; + char_width = font->glyph.mono.width; if (font->shape.prop == 1) { - glyph = dfont_glyph_index(font, code_point); - if (glyph < 0) + glyphidx = dfont_glyph_index(font, code_point); + if (glyphidx < 0) return (-1); - char_width = font->glyph_width[glyph]; + char_width = font->glyph.prop[glyphidx].width; } /* line discipline */ - x += char_width; + x += char_width + font->char_spacing; if (code_point == '\n') { - y += font->data_height; + y += font->glyph.height; x = 0; } if (x > mx) mx = x; @@ -127,7 +273,7 @@ int dfont_text_geometry( } /* set geometry information */ - if (w != NULL) *w = mx; + if (w != NULL) *w = mx - font->char_spacing; if (h != NULL) *h = y; if (size != NULL) *size = length; return (0); diff --git a/src/modules/display/text/dtext.c b/src/modules/display/text/dtext.c index 9418ca1..a448bb3 100644 --- a/src/modules/display/text/dtext.c +++ b/src/modules/display/text/dtext.c @@ -9,27 +9,21 @@ #include #include #include +#include -struct dtext_geometry { - struct { - char *raw; - size_t raw_size; - int size; - } text; - int x; - int y; -}; - static struct { struct { - struct dtext_geometry *geometry; + struct { + char *raw; + size_t size; + } *text; int number; int idx; } pool; } dtext_info = { .pool = { - .geometry = NULL, + .text = NULL, .number = 0, .idx = 0 } @@ -43,22 +37,21 @@ VCONSTRUCTOR static void __dtext_constructor(void) { dtext_info.pool.number = 16; dtext_info.pool.idx = -1; - dtext_info.pool.geometry = calloc( + dtext_info.pool.text = calloc( dtext_info.pool.number, - sizeof(struct dtext_geometry) + sizeof (*dtext_info.pool.text) ); for (int i = 0; i < dtext_info.pool.number; ++i) { - dtext_info.pool.geometry[i].text.raw = malloc(32); - dtext_info.pool.geometry[i].text.raw_size = 32; - dtext_info.pool.geometry[i].text.size = 0; + dtext_info.pool.text[i].raw = malloc(32); + dtext_info.pool.text[i].size = 32; } } VDESTRUCTOR void __dtext_destructor(void) { for (int i = 0; i < dtext_info.pool.number; ++i) - free(dtext_info.pool.geometry[i].text.raw); - free(dtext_info.pool.geometry); + free(dtext_info.pool.text[i].raw); + free(dtext_info.pool.text); } static void __dtext_quit(void) @@ -67,29 +60,22 @@ static void __dtext_quit(void) } //--- -// Drawing functions +// Private functions //--- -#if 0 -static void dtext_opt_draw(struct dshader_surface *surface, uint32_t *arg) +static char *dtext_info_register(char const * const str) { - uint32_t buff[5]; - char *str; - - buff[0] = (uintptr_t)dfont_get(); - buff[1] = arg[0]; // x - buff[2] = arg[1]; // y - buff[3] = arg[2]; // fg - buff[4] = arg[3]; // bg - - str = (void*)(uintptr_t)arg[4]; - for (int i = 0; i < (int)arg[5]; ++i) { - buff[5] = str[i]; - dfont_render(surface, buff); + dtext_info.pool.idx += 1; + if (dtext_info.pool.idx >= dtext_info.pool.number) { + dtext_info.pool.number += dtext_info.pool.number; + dtext_info.pool.text = realloc( + dtext_info.pool.text, + dtext_info.pool.number + ); } + strcpy(dtext_info.pool.text[dtext_info.pool.idx].raw, str); + return dtext_info.pool.text[dtext_info.pool.idx].raw; } -#endif - //--- // Public API @@ -104,6 +90,7 @@ did_t dtext_opt( ) { size_t width; size_t height; + void *real_str; /* get text geometry and handle obvious culling */ if (dfont_text_geometry(NULL, str, &size, &width, &height) != 0) @@ -121,13 +108,16 @@ did_t dtext_opt( if (valign == DTEXT_CENTER) y = y - (height / 2); if (valign == DTEXT_BOTTOM) y = y - (height); + /* register the string */ + real_str = dtext_info_register(str); + /* request draw call */ return dstack_add_action( &DSTACK_CALL( &dfont_text_render, - x, y, + x, y, x + width, y + height, fg, bg, - (uint32_t)(uintptr_t)str, size + (uint32_t)(uintptr_t)real_str, size, ), (dtext_info.pool.idx == 0) ? (void*)&__dtext_quit : NULL, NULL