Text fixes

This commit is contained in:
Mid 2025-09-13 11:59:12 +03:00
parent c3daf57f24
commit 5e0966beb8
4 changed files with 180 additions and 79 deletions

View File

@ -14,18 +14,7 @@ static inline void immdraw_fill_rect(int16_t x, int16_t y, int16_t w, int16_t h,
} }
static inline void immdraw_font_draw(struct k3Font *font, int16_t x, int16_t y, int16_t w, float sz, size_t len, const char *txt, int alignment, float r, float g, float b, float a) { static inline void immdraw_font_draw(struct k3Font *font, int16_t x, int16_t y, int16_t w, float sz, size_t len, const char *txt, int alignment, float r, float g, float b, float a) {
struct k3RectF txtsz; k3FontDraw(font, x, GameWndH - y - sz, sz, txt, w, alignment, (vec4) {r, g, b, a});
k3FontSz(font, sz, txt, w, &txtsz);
if(alignment != k3M_ALIGN_LEFT) {
if(alignment == k3M_ALIGN_CENTER) {
x += w / 2.0f - txtsz.w / 2.0f;
} else {
x += w - txtsz.w;
}
}
k3FontDraw(font, x, GameWndH - y - sz, sz, txt, w, (vec4) {r, g, b, a});
} }
static inline void immdraw_font_size(struct k3Font *font, float sz, const char *txt, int16_t wall, int16_t aabb[2]) { static inline void immdraw_font_size(struct k3Font *font, float sz, const char *txt, int16_t wall, int16_t aabb[2]) {
struct k3RectF txtsz; struct k3RectF txtsz;

View File

@ -108,7 +108,9 @@ void k3FontSz(struct k3Font *this, float sz, const char *txt, float wall, struct
while(1) { while(1) {
uint32_t cp = read_utf8(&txt); uint32_t cp = read_utf8(&txt);
if(!cp) break; if(cp == 0) {
break;
}
if(cp == 10) { if(cp == 10) {
x = 0; x = 0;
@ -119,7 +121,7 @@ void k3FontSz(struct k3Font *this, float sz, const char *txt, float wall, struct
if(!g) continue; if(!g) continue;
if(x + g->width > wall) { if(x + g->width * this->lineScale * sz > wall) {
x = 0; x = 0;
y += sz; y += sz;
} }
@ -131,31 +133,57 @@ void k3FontSz(struct k3Font *this, float sz, const char *txt, float wall, struct
ret->w = maxX; ret->w = maxX;
ret->h = y; ret->h = y;
} }
void k3FontDraw(struct k3Font *this, float xStart, float yStart, float sz, const char *txt, float wall, vec4 color) { void k3FontDraw(struct k3Font *this, float xStart, float yStart, float sz, const char *txt, float wall, int alignment, vec4 color) {
if(wall < 0) { if(wall < 0) {
wall = HUGE_VALF; wall = HUGE_VALF;
} }
float x = xStart, y = yStart; float y = yStart;
while(1) { while(1) {
uint32_t cp = read_utf8(&txt); size_t lineLength = 0;
if(!cp) break; float lineWidth = 0;
if(cp == 10) { uint32_t cp2;
x = xStart; const char *txt2 = txt;
y -= sz; while(1) {
cp2 = read_utf8(&txt2);
if(cp2 == 0 || cp2 == 10) {
break;
} }
lineLength++;
struct k3FontGlyph *g = k3FontGetGlyph(this, cp2);
if(g) {
if(lineWidth + g->width * this->lineScale * sz > wall) {
break;
}
lineWidth += g->xadvance * this->lineScale * sz;
}
}
if(lineLength == 0 && cp2 == 0) {
break;
}
float x = 0;
if(alignment == 0) {
x = xStart;
} else if(alignment == 1) {
x = xStart + (wall - lineWidth) / 2;
} else if(alignment == 2) {
x = xStart + wall - lineWidth;
}
for(size_t i = 0; i < lineLength; i++) {
uint32_t cp = read_utf8(&txt);
struct k3FontGlyph *g = k3FontGetGlyph(this, cp); struct k3FontGlyph *g = k3FontGetGlyph(this, cp);
if(!g) continue; if(!g) continue;
if(x + g->width - xStart > wall) {
x = xStart;
y -= sz;
}
struct k3Tex *tex = this->pages[g->page]; struct k3Tex *tex = this->pages[g->page];
size_t texW = this->texW; size_t texW = this->texW;
size_t texH = this->texH; size_t texH = this->texH;
@ -171,6 +199,14 @@ void k3FontDraw(struct k3Font *this, float xStart, float yStart, float sz, const
x += g->xadvance * this->lineScale * sz; x += g->xadvance * this->lineScale * sz;
} }
// If the line break was caused directly by a LF, skip over it for next line
if(cp2 == 10) {
read_utf8(&txt);
}
y -= sz;
}
k3BatchFlush(); k3BatchFlush();
} }

View File

@ -4,6 +4,10 @@
#include"k3batch.h" #include"k3batch.h"
#include<string.h> #include<string.h>
#define k3_FONT_ALIGN_LEFT 0
#define k3_FONT_ALIGN_CENTER 1
#define k3_FONT_ALIGN_RIGHT 2
struct k3FontGlyph { struct k3FontGlyph {
uint32_t cp; uint32_t cp;
uint16_t x; uint16_t x;
@ -39,7 +43,7 @@ struct k3Font *k3FontCreate();
int k3FontLoad(struct k3Font*, const uint8_t *buf, size_t len, k3FontTexLoader); int k3FontLoad(struct k3Font*, const uint8_t *buf, size_t len, k3FontTexLoader);
void k3FontSz(struct k3Font*, float sz, const char *txt, float wall, struct k3RectF *ret); void k3FontSz(struct k3Font*, float sz, const char *txt, float wall, struct k3RectF *ret);
void k3FontDraw(struct k3Font*, float x, float y, float sz, const char *txt, float wall, vec4 color); void k3FontDraw(struct k3Font*, float x, float y, float sz, const char *txt, float wall, int alignment, vec4 color);
struct k3FontGlyph *k3FontGetGlyph(struct k3Font*, uint32_t cp); struct k3FontGlyph *k3FontGetGlyph(struct k3Font*, uint32_t cp);

View File

@ -54,6 +54,7 @@ static bool linear_measure(struct k3MEvent *ev, uint8_t *ud) {
o->wDesired = 0; o->wDesired = 0;
o->hDesired = 0; o->hDesired = 0;
intmax_t prevChildMargin[4] = {};
for(size_t i = 0; i < o->childCount; i++) { for(size_t i = 0; i < o->childCount; i++) {
struct k3MObj *c = o->children[i]; struct k3MObj *c = o->children[i];
@ -61,7 +62,19 @@ static bool linear_measure(struct k3MEvent *ev, uint8_t *ud) {
o->wDesired = c->wDesired; o->wDesired = c->wDesired;
} }
o->hDesired += c->hDesired; intmax_t margin[4] = {};
struct k3MProperty *prop = k3MFindProperty(o, k3M_PROP_MARGIN, true);
if(prop) {
for(int s = 0; s < 4; s++) {
if(prop->units[s] == k3M_UNIT_ABSOLUTE) {
margin[s] = prop->f[s];
} else if(prop->units[s] == k3M_UNIT_PROPORTION && o->parent) {
margin[s] = prop->f[s] * (s % 2 == 0 ? o->h : o->w);
}
}
}
o->hDesired += margin[0] + c->hDesired + margin[2];
} }
} }
static bool linear_arrange(struct k3MEvent *ev, uint8_t *ud) { static bool linear_arrange(struct k3MEvent *ev, uint8_t *ud) {
@ -87,7 +100,9 @@ static bool linear_arrange(struct k3MEvent *ev, uint8_t *ud) {
c->x = o->x + padding[3]; c->x = o->x + padding[3];
c->y = y; c->y = y;
if(c->w > o->w - padding[1] - padding[3]) {
c->w = o->w - padding[1] - padding[3]; c->w = o->w - padding[1] - padding[3];
}
if(!k3MEventSend(&(struct k3MEvent) {.original = o, .target = c, .code = k3M_EVENT_SET_HEIGHT_FROM_WIDTH})) { if(!k3MEventSend(&(struct k3MEvent) {.original = o, .target = c, .code = k3M_EVENT_SET_HEIGHT_FROM_WIDTH})) {
c->h = c->hDesired; c->h = c->hDesired;
@ -213,21 +228,48 @@ static bool label_draw(struct k3MEvent *ev, uint8_t *ud) {
obj_draw_direct((void*) this); obj_draw_direct((void*) this);
if(this->txt) { if(this->txt) {
int alignment = k3M_ALIGN_CENTER;
struct k3MProperty *propHA = k3MFindProperty(this, k3M_PROP_HORIZONTAL_ALIGNMENT, false);
if(propHA) alignment = propHA->si[0];
float sz = this->sz; float sz = this->sz;
struct k3MProperty *fontSize = k3MFindProperty(this, k3M_PROP_FONT_SIZE, false); struct k3MProperty *prop = k3MFindProperty(this, k3M_PROP_FONT_SIZE, false);
if(fontSize) sz = fontSize->f[0]; if(prop) sz = prop->f[0];
immdraw_font_draw(this->font, this->x, this->y, this->w, sz, strlen(this->txt), this->txt, alignment, int ha = k3M_ALIGN_LEFT;
prop = k3MFindProperty(this, k3M_PROP_HORIZONTAL_ALIGNMENT, false);
if(prop) ha = prop->si[0];
int va = k3M_ALIGN_CENTER;
prop = k3MFindProperty(this, k3M_PROP_VERTICAL_ALIGNMENT, false);
if(prop) va = prop->si[0];
int16_t x = this->x;
int16_t y = this->y;
if(va != k3M_ALIGN_TOP) {
struct k3RectF txtsz;
k3FontSz(this->font, this->sz, this->txt, this->w, &txtsz);
if(va == k3M_ALIGN_CENTER) {
y += (this->h - txtsz.h) / 2;
} else if(va == k3M_ALIGN_BOTTOM) {
y += this->h - txtsz.h;
}
}
immdraw_font_draw(this->font, x, y, this->w, sz, strlen(this->txt), this->txt, ha,
1, 1, 1, 1); 1, 1, 1, 1);
} }
return false; return false;
} }
static bool label_measure(struct k3MEvent *ev, uint8_t *ud) {
struct k3MLabel *this = (void*) ev->target;
struct k3RectF txtsz;
k3FontSz(this->font, this->sz, this->txt, -1, &txtsz);
this->w = ceilf(txtsz.w);
this->h = ceilf(txtsz.h);
return false;
}
static bool label_set_height_from_width(struct k3MEvent *ev, uint8_t *ud) { static bool label_set_height_from_width(struct k3MEvent *ev, uint8_t *ud) {
struct k3MLabel *this = (void*) ev->target; struct k3MLabel *this = (void*) ev->target;
@ -245,12 +287,9 @@ struct k3MLabel *k3MLabel(struct k3Font *font, float sz, const char *txt) {
ret->txt = strdup(txt); ret->txt = strdup(txt);
k3MRegisterEventHandler(ret, k3M_EVENT_DRAW, label_draw, NULL, 0); k3MRegisterEventHandler(ret, k3M_EVENT_DRAW, label_draw, NULL, 0);
k3MRegisterEventHandler(ret, k3M_EVENT_MEASURE, label_measure, NULL, 0);
k3MRegisterEventHandler(ret, k3M_EVENT_SET_HEIGHT_FROM_WIDTH, label_set_height_from_width, NULL, 0); k3MRegisterEventHandler(ret, k3M_EVENT_SET_HEIGHT_FROM_WIDTH, label_set_height_from_width, NULL, 0);
//int16_t lblsz[2];
//immdraw_font_size(font, sz, txt, lblsz);
//ret->w = lblsz[0];
//ret->h = lblsz[1];
return ret; return ret;
} }
@ -379,16 +418,22 @@ static bool screen_ev(struct k3MEvent *ev, uint8_t *ud) {
this->keyboardFocus = innermost; this->keyboardFocus = innermost;
} }
ev->kind = k3M_EVENTKIND_BUBBLE; k3MEventSend(&(struct k3MEvent) {
ev->target = innermost; .code = ev->code,
k3MEventSend(ev); .kind = k3M_EVENTKIND_BUBBLE,
.original = ev->original,
.target = innermost,
.mouse = ev->mouse,
});
if(ev->code == k3M_EVENT_MOUSE_RELEASE) { if(ev->code == k3M_EVENT_MOUSE_RELEASE) {
ev->code = k3M_EVENT_MOUSE_CLICK; k3MEventSend(&(struct k3MEvent) {
.code = k3M_EVENT_MOUSE_CLICK,
ev->kind = k3M_EVENTKIND_DIRECT; .kind = k3M_EVENTKIND_DIRECT,
ev->target = innermost; .original = ev->original,
k3MEventSend(ev); .target = innermost,
.mouse = ev->mouse,
});
} }
} }
@ -397,20 +442,25 @@ static bool screen_ev(struct k3MEvent *ev, uint8_t *ud) {
} else if(ev->code == k3M_EVENT_KEY_PRESS || ev->code == k3M_EVENT_KEY_RELEASE || ev->code == k3M_EVENT_INPUT) { } else if(ev->code == k3M_EVENT_KEY_PRESS || ev->code == k3M_EVENT_KEY_RELEASE || ev->code == k3M_EVENT_INPUT) {
if(this->keyboardFocus) { if(this->keyboardFocus) {
ev->kind = k3M_EVENTKIND_BUBBLE; k3MEventSend(&(struct k3MEvent) {
ev->target = (void*) this->keyboardFocus; .code = ev->code,
k3MEventSend(ev); .kind = k3M_EVENTKIND_BUBBLE,
.original = ev->original,
.target = this->keyboardFocus,
.key = ev->key,
});
} }
return true; return true;
} }
ev->kind = k3M_EVENTKIND_CAPTURE;
for(intmax_t i = this->childCount - 1; i >= 0; i--) { for(intmax_t i = this->childCount - 1; i >= 0; i--) {
if(!this->children[i]->invisible) { if(!this->children[i]->invisible) {
ev->target = this->children[i]; struct k3MEvent newev = *ev;
if(k3MEventSend(ev)) { newev.kind = k3M_EVENTKIND_CAPTURE;
newev.target = this->children[i];
if(k3MEventSend(&newev)) {
return true; return true;
} }
} }
@ -492,23 +542,44 @@ static bool textbutton_draw(struct k3MEvent *ev, uint8_t *ud) {
obj_draw_direct((void*) this); obj_draw_direct((void*) this);
if(this->txt) { if(this->txt) {
/*struct k3RectF txtsz; int ha = k3M_ALIGN_CENTER;
k3FontSz(this->font, this->sz, this->txt, &txtsz);
k3FontDraw(this->font, this->x + this->w / 2 - txtsz.w / 2, this->y, this->sz, this->txt, (vec4) {
1 - 0.8 * this->disabled, 1 - 0.8 * this->disabled, 1 - 0.8 * this->disabled, 1});*/
int alignment = k3M_ALIGN_CENTER;
struct k3MProperty *prop = k3MFindProperty(this, k3M_PROP_HORIZONTAL_ALIGNMENT, false); struct k3MProperty *prop = k3MFindProperty(this, k3M_PROP_HORIZONTAL_ALIGNMENT, false);
if(prop) alignment = prop->si[0]; if(prop) ha = prop->si[0];
immdraw_font_draw(this->font, this->x, this->y, this->w, this->sz, strlen(this->txt), this->txt, alignment, int va = k3M_ALIGN_CENTER;
prop = k3MFindProperty(this, k3M_PROP_VERTICAL_ALIGNMENT, false);
if(prop) va = prop->si[0];
int16_t x = this->x;
int16_t y = this->y;
if(va != k3M_ALIGN_TOP) {
struct k3RectF txtsz;
k3FontSz(this->font, this->sz, this->txt, this->w, &txtsz);
if(va == k3M_ALIGN_CENTER) {
y += (this->h - txtsz.h) / 2;
} else if(va == k3M_ALIGN_BOTTOM) {
y += this->h - txtsz.h;
}
}
immdraw_font_draw(this->font, x, y, this->w, this->sz, strlen(this->txt), this->txt, ha,
1 - 0.8 * this->disabled, 1 - 0.8 * this->disabled, 1 - 0.8 * this->disabled, 1); 1 - 0.8 * this->disabled, 1 - 0.8 * this->disabled, 1 - 0.8 * this->disabled, 1);
} }
return false; return false;
} }
static bool textbutton_measure(struct k3MEvent *ev, uint8_t *ud) {
struct k3MTextButton *this = (void*) ev->target;
struct k3RectF sz = {};
k3FontSz(this->font, this->sz, this->txt, -1, &sz);
this->w = ceilf(sz.w);
this->h = ceilf(sz.h);
return false;
}
struct k3MTextButton *k3MTextButton(struct k3Font *font, float sz, const char *txt) { struct k3MTextButton *k3MTextButton(struct k3Font *font, float sz, const char *txt) {
struct k3MTextButton *ret = calloc(1, sizeof(*ret)); struct k3MTextButton *ret = calloc(1, sizeof(*ret));
@ -516,6 +587,7 @@ struct k3MTextButton *k3MTextButton(struct k3Font *font, float sz, const char *t
ret->sz = sz; ret->sz = sz;
ret->txt = strdup(txt); ret->txt = strdup(txt);
k3MRegisterEventHandler(ret, k3M_EVENT_MEASURE, textbutton_measure, NULL, 0);
k3MRegisterEventHandler(ret, k3M_EVENT_DRAW, textbutton_draw, NULL, 0); k3MRegisterEventHandler(ret, k3M_EVENT_DRAW, textbutton_draw, NULL, 0);
return ret; return ret;