fix text menu render

This commit is contained in:
2025-07-16 05:03:40 -05:00
parent 13dd685f65
commit 874252db87
7 changed files with 49 additions and 59 deletions

View File

@@ -32,7 +32,7 @@ var clay_base = {
slice: 0, slice: 0,
font: 'smalle.16', font: 'smalle.16',
font_size: null, font_size: null,
color: [1,1,1,1], color: {r:1,g:1,b:1,a:1},
spacing:0, spacing:0,
padding:0, padding:0,
margin:0, margin:0,
@@ -212,10 +212,12 @@ clay.image = function image(path, ...configs)
clay.text = function text(str, ...configs) clay.text = function text(str, ...configs)
{ {
var config = rectify_configs(configs); var config = rectify_configs(configs);
config.size ??= {width:0, height:0}; config.size ??= [0,0];
// config.font = graphics.get_font(config.font) config.font = graphics.get_font(config.font)
var tsize = {width: 12*str.length, height: 8}; //config.font.text_size(str, 0, 0, config.size.width); var tsize = graphics.font_text_size(config.font, str, 0, config.size.x);
config.size = {width: Math.max(config.size.width, tsize.width), height: Math.max(config.size.height, tsize.height)}; tsize.x = Math.ceil(tsize.x)
tsize.y = Math.ceil(tsize.y)
config.size = config.size.map((x,i) => Math.max(x, tsize[i]));
config.text = str; config.text = str;
add_item(config); add_item(config);
} }
@@ -235,8 +237,8 @@ var button_base = Object.assign(Object.create(clay_base), {
clay.button = function button(str, action, config = {}) clay.button = function button(str, action, config = {})
{ {
config.__proto__ = button_base; config.__proto__ = button_base;
// config.font = graphics.get_font(config.font) config.font = graphics.get_font(config.font)
config.size = 12;//config.font.text_size(str) config.size = graphics.font_text_size(config.font, str, 0, 0)
add_item(config); add_item(config);
config.text = str; config.text = str;
config.action = action; config.action = action;
@@ -269,7 +271,7 @@ clay.draw_commands = function draw_commands(cmds, pos = {x:0, y:0}, mousepos = {
draw.rectangle(boundingbox, config.background_color); draw.rectangle(boundingbox, config.background_color);
if (config.text) if (config.text)
draw.text(config.text, content, config.font, config.font_size, config.color, config.size.width); draw.text(config.text, content, config.font, config.color, config.size.width);
if (config.image) if (config.image)
draw.image(config.image, content, 0, config.color); draw.image(config.image, content, 0, config.color);
} }

View File

@@ -158,12 +158,11 @@ draw.circle = function render_circle(pos, radius, defl, material) {
draw.ellipse(pos, [radius,radius], defl, material) draw.ellipse(pos, [radius,radius], defl, material)
} }
draw.text = function text(text, pos, font = 'fonts/c64.ttf', size = 8, color = {r:1,g:1,b:1,a:1}, wrap = 0) { draw.text = function text(text, pos, font = 'fonts/c64.8', color = {r:1,g:1,b:1,a:1}, wrap = 0) {
add_command("draw_text", { add_command("draw_text", {
text, text,
pos, pos,
font, font,
size,
wrap, wrap,
material: {color} material: {color}
}) })

View File

@@ -214,14 +214,13 @@ function translate_draw_commands(commands) {
if (!cmd.pos) break if (!cmd.pos) break
// Get font from the font string (e.g., "smalle.16") // Get font from the font string (e.g., "smalle.16")
var font = graphics.get_font(cmd.font, cmd.size) var font = graphics.get_font(cmd.font)
if (!font || !font.texture || !font.texture.id) break if (!font || !font.texture || !font.texture.id) break
// Create text geometry buffer // Create text geometry buffer
var text_mesh = graphics.make_text_buffer( var text_mesh = graphics.make_text_buffer(
cmd.text, cmd.text,
{x: cmd.pos.x, y: cmd.pos.y, width: 200, height: 50}, {x: cmd.pos.x, y: cmd.pos.y},
cmd.size,
[cmd.material.color.r, cmd.material.color.g, cmd.material.color.b, cmd.material.color.a], [cmd.material.color.r, cmd.material.color.g, cmd.material.color.b, cmd.material.color.a],
cmd.wrap || 0, cmd.wrap || 0,
font font

View File

@@ -400,8 +400,10 @@ Stores previously loaded fonts. Keyed by e.g. "path.ttf.16" -> fontObject.
var fontcache = {} var fontcache = {}
var datas = [] var datas = []
graphics.get_font = function get_font(path, size) { graphics.get_font = function get_font(path) {
if (typeof path != 'string') return path
var parts = path.split('.') var parts = path.split('.')
var size = 16 // default size
if (!isNaN(parts[1])) { if (!isNaN(parts[1])) {
path = parts[0] path = parts[0]
size = Number(parts[1]) size = Number(parts[1])
@@ -413,12 +415,7 @@ graphics.get_font = function get_font(path, size) {
if (fontcache[fontstr]) return fontcache[fontstr] if (fontcache[fontstr]) return fontcache[fontstr]
var data = io.slurpbytes(fullpath) var data = io.slurpbytes(fullpath)
// Ensure size is a proper number var font = graphics.make_font(data, size)
var numericSize = Number(size)
if (isNaN(numericSize) || numericSize <= 0) {
numericSize = 16 // default size
}
var font = graphics.make_font(data, numericSize)
// Load font texture via renderer actor (async) // Load font texture via renderer actor (async)
if (renderer_actor) { if (renderer_actor) {

View File

@@ -103,13 +103,13 @@ void sdrawCharacter(struct text_vert **buffer, stbtt_packedchar c, HMM_Vec2 curs
arrput(*buffer, vert); arrput(*buffer, vert);
} }
void draw_char_verts(struct text_vert **buffer, struct character c, HMM_Vec2 cursor, float scale, colorf color) void draw_char_verts(struct text_vert **buffer, struct character c, HMM_Vec2 cursor, colorf color)
{ {
// packedchar has // packedchar has
// Adds four verts: bottom left, bottom right, top left, top right // Adds four verts: bottom left, bottom right, top left, top right
text_vert bl; text_vert bl;
bl.pos.x = cursor.X + c.quad.x * scale; bl.pos.x = cursor.X + c.quad.x;
bl.pos.y = cursor.Y + c.quad.y * scale; bl.pos.y = cursor.Y + c.quad.y;
bl.uv.x = c.uv.x; bl.uv.x = c.uv.x;
bl.uv.y = c.uv.y; bl.uv.y = c.uv.y;
bl.color = color; bl.color = color;
@@ -117,12 +117,12 @@ void draw_char_verts(struct text_vert **buffer, struct character c, HMM_Vec2 cur
text_vert br = bl; text_vert br = bl;
br.pos.x += c.quad.w * scale; br.pos.x += c.quad.w;
br.uv.x += c.uv.w; br.uv.x += c.uv.w;
arrput(*buffer, br); arrput(*buffer, br);
text_vert ul = bl; text_vert ul = bl;
ul.pos.y += c.quad.h * scale; ul.pos.y += c.quad.h;
ul.uv.y += c.uv.h; ul.uv.y += c.uv.h;
arrput(*buffer, ul); arrput(*buffer, ul);
@@ -159,16 +159,14 @@ const char *esc_color(const char *c, struct rgba *color, struct rgba defc)
return c; return c;
} }
// text is a string, font f, size is height in pixels, wrap is how long a line is before wrapping. -1to not wrap // text is a string, font f, wrap is how long a line is before wrapping. -1to not wrap
HMM_Vec2 measure_text(const char *text, font *f, float size, float letterSpacing, float wrap) HMM_Vec2 measure_text(const char *text, font *f, float letterSpacing, float wrap)
{ {
int breakAtWord = 0; int breakAtWord = 0;
HMM_Vec2 dim = {0}; HMM_Vec2 dim = {0};
float maxWidth = 0; // Maximum width of any line float maxWidth = 0; // Maximum width of any line
float lineWidth = 0; // Current line width float lineWidth = 0; // Current line width
float scale = size / f->height; float lineHeight = f->ascent - f->descent;
float lineHeight = (f->ascent - f->descent) * scale;
letterSpacing *= scale;
float height = lineHeight; // Total height float height = lineHeight; // Total height
const char *wordStart = text; // Start of the current word for word wrapping const char *wordStart = text; // Start of the current word for word wrapping
@@ -233,36 +231,34 @@ HMM_Vec2 measure_text(const char *text, font *f, float size, float letterSpacing
return dim; return dim;
} }
/* pos given in screen coordinates */ /* pos given in screen coordinates */
struct text_vert *renderText(const char *text, HMM_Vec2 pos, font *f, float scale, colorf color, float wrap) { struct text_vert *renderText(const char *text, HMM_Vec2 pos, font *f, colorf color, float wrap) {
text_vert *buffer = NULL; text_vert *buffer = NULL;
HMM_Vec2 cursor = pos; HMM_Vec2 cursor = pos;
float lineHeight = (f->ascent - f->descent) * scale; float lineHeight = f->ascent - f->descent;
float lineWidth = 0; float lineWidth = 0;
float scaledLinegap = f->linegap * scale;
for (const char *c = text; *c != 0; c++) { for (const char *c = text; *c != 0; c++) {
if (*c == '\n') { if (*c == '\n') {
cursor.x = pos.x; cursor.x = pos.x;
cursor.y -= lineHeight + scaledLinegap; cursor.y -= lineHeight + f->linegap;
lineWidth = 0; lineWidth = 0;
continue; continue;
} }
struct character chara = f->Characters[(unsigned char)*c]; struct character chara = f->Characters[(unsigned char)*c];
float scaledAdvance = chara.advance * scale;
if (wrap > 0 && lineWidth + scaledAdvance > wrap) { if (wrap > 0 && lineWidth + chara.advance > wrap) {
cursor.x = pos.x; cursor.x = pos.x;
cursor.y -= lineHeight + scaledLinegap; cursor.y -= lineHeight + f->linegap;
lineWidth = 0; lineWidth = 0;
} }
if (!isspace(*c)) if (!isspace(*c))
draw_char_verts(&buffer, chara, cursor, scale, color); draw_char_verts(&buffer, chara, cursor, color);
lineWidth += scaledAdvance; lineWidth += chara.advance;
cursor.x += scaledAdvance; cursor.x += chara.advance;
} }
return buffer; return buffer;

View File

@@ -57,7 +57,7 @@ typedef struct Character glyph;
void font_free(JSRuntime *rt,font *f); void font_free(JSRuntime *rt,font *f);
struct sFont *MakeFont(void *data, size_t len, int height); struct sFont *MakeFont(void *data, size_t len, int height);
struct text_vert *renderText(const char *text, HMM_Vec2 pos, font *f, float scale, colorf color, float wrap); struct text_vert *renderText(const char *text, HMM_Vec2 pos, font *f, colorf color, float wrap);
HMM_Vec2 measure_text(const char *text, font *f, float scale, float letterSpacing, float wrap); HMM_Vec2 measure_text(const char *text, font *f, float letterSpacing, float wrap);
#endif #endif

View File

@@ -742,14 +742,11 @@ int point2segindex(HMM_Vec2 p, HMM_Vec2 *segs, double slop) {
JSC_CCALL(os_make_text_buffer, JSC_CCALL(os_make_text_buffer,
const char *s = JS_ToCString(js, argv[0]); const char *s = JS_ToCString(js, argv[0]);
rect rectpos = js2rect(js,argv[1]); rect rectpos = js2rect(js,argv[1]);
float size = js2number(js,argv[2]); font *f = js2font(js,argv[4]);
font *f = js2font(js,argv[5]); colorf c = js2color(js,argv[2]);
if (!size) size = f->height; int wrap = js2number(js,argv[3]);
colorf c = js2color(js,argv[3]);
int wrap = js2number(js,argv[4]);
HMM_Vec2 startpos = {.x = rectpos.x, .y = rectpos.y }; HMM_Vec2 startpos = {.x = rectpos.x, .y = rectpos.y };
float scale = size / f->height; text_vert *buffer = renderText(s, startpos, f, c, wrap);
text_vert *buffer = renderText(s, startpos, f, scale, c, wrap);
ret = quads_to_mesh(js,buffer); ret = quads_to_mesh(js,buffer);
JS_FreeCString(js, s); JS_FreeCString(js, s);
arrfree(buffer); arrfree(buffer);
@@ -1046,13 +1043,13 @@ JSC_GET(font, height, number)
JSC_GET(font, ascent, number) JSC_GET(font, ascent, number)
JSC_GET(font, descent, number) JSC_GET(font, descent, number)
JSC_SCALL(font_text_size, JSC_CCALL(graphics_font_text_size,
font *f = js2font(js,self); font *f = js2font(js,argv[0]);
float size = js2number(js,argv[0]); const char *str = JS_ToCString(js, argv[1]);
if (!size) size = f->height; float letterSpacing = js2number(js,argv[2]);
float letterSpacing = js2number(js,argv[1]); float wrap = js2number(js,argv[3]);
float wrap = js2number(js,argv[2]); ret = vec22js(js,measure_text(str, f, letterSpacing, wrap));
ret = vec22js(js,measure_text(str, f, size, letterSpacing, wrap)); JS_FreeCString(js, str);
) )
static const JSCFunctionListEntry js_font_funcs[] = { static const JSCFunctionListEntry js_font_funcs[] = {
@@ -1060,7 +1057,6 @@ static const JSCFunctionListEntry js_font_funcs[] = {
MIST_GET(font, height), MIST_GET(font, height),
MIST_GET(font, ascent), MIST_GET(font, ascent),
MIST_GET(font, descent), MIST_GET(font, descent),
MIST_FUNC_DEF(font, text_size, 3),
}; };
// input: (encoded image data of jpg, png, bmp, tiff) // input: (encoded image data of jpg, png, bmp, tiff)
@@ -1526,7 +1522,7 @@ JSC_CCALL(graphics_save_jpg,
) )
static const JSCFunctionListEntry js_graphics_funcs[] = { static const JSCFunctionListEntry js_graphics_funcs[] = {
MIST_FUNC_DEF(os, make_text_buffer, 6), MIST_FUNC_DEF(os, make_text_buffer, 5),
MIST_FUNC_DEF(os, rectpack, 3), MIST_FUNC_DEF(os, rectpack, 3),
MIST_FUNC_DEF(os, make_texture, 1), MIST_FUNC_DEF(os, make_texture, 1),
MIST_FUNC_DEF(os, make_gif, 1), MIST_FUNC_DEF(os, make_gif, 1),
@@ -1537,6 +1533,7 @@ static const JSCFunctionListEntry js_graphics_funcs[] = {
MIST_FUNC_DEF(graphics, hsl_to_rgb, 3), MIST_FUNC_DEF(graphics, hsl_to_rgb, 3),
MIST_FUNC_DEF(graphics, save_png, 4), MIST_FUNC_DEF(graphics, save_png, 4),
MIST_FUNC_DEF(graphics, save_jpg, 4), MIST_FUNC_DEF(graphics, save_jpg, 4),
MIST_FUNC_DEF(graphics, font_text_size, 4),
}; };
static const JSCFunctionListEntry js_video_funcs[] = { static const JSCFunctionListEntry js_video_funcs[] = {