don't draw text outiside the bounding box

master
Alessandro Mauri 1 year ago
parent a7a2193ea6
commit 4f2a7fbf18
  1. 2
      text_rendering/main.c
  2. 112
      text_rendering/ren.c

@ -15,7 +15,7 @@ SDL_Window *win;
void draw(void)
{
ren_clear();
ren_render_text(str, 0, 0, 200, 100, 12);
ren_render_text(str, 0, 0, 100, 50, 12);
ren_render_box(100, 300, 50, 50, 0xffff0000);
SDL_GL_SwapWindow(win);
}

@ -515,11 +515,8 @@ int ren_set_scissor(int x, int y, int w, int h)
}
// TODO: implement font size
int ren_render_text(const char *str, int x, int y, int w, int h, int size)
static int ren_push_glyph(const struct font_glyph *g, int gx, int gy)
{
/* x4,y4 x3,y3
* +-------------+
* |(x,y) /|
@ -531,8 +528,55 @@ int ren_render_text(const char *str, int x, int y, int w, int h, int size)
* |/ |
* +-------------+
* x1,y1 x2,y2 */
struct v_text v;
struct font_glyph c;
c = *g;
//printf("g: u=%d v=%d w=%d h=%d a=%d x=%d y=%d\n", c.u, c.v, c.w, c.h, c.a, c.x, c.y);
//printf("v: x=%d y=%d u=%d v=%d\n", v.pos.x, v.pos.y, v.uv.u, v.uv.v);
// x1,y1
v = (struct v_text){
.pos = { .x = gx+c.x, .y = gy+c.y+c.h },
.uv = { .u = c.u, .v = c.v+c.h },
};
vtstack_push(&ren.font_stack, &v);
// x2,y2
v = (struct v_text){
.pos = { .x = gx+c.x+c.w, .y = gy+c.y+c.h },
.uv = { .u = c.u+c.w, .v = c.v+c.h },
};
vtstack_push(&ren.font_stack, &v);
// x3,y3
v = (struct v_text){
.pos = { .x = gx+c.x+c.w, .y = gy+c.y },
.uv = { .u = c.u+c.w, .v = c.v },
};
vtstack_push(&ren.font_stack, &v);
// x1,y1
v = (struct v_text){
.pos = { .x = gx+c.x, .y = gy+c.y+c.h },
.uv = { .u = c.u, .v = c.v+c.h },
};
vtstack_push(&ren.font_stack, &v);
// x3,y3
v = (struct v_text){
.pos = { .x = gx+c.x+c.w, .y = gy+c.y },
.uv = { .u = c.u+c.w, .v = c.v },
};
vtstack_push(&ren.font_stack, &v);
// x4,y4
v = (struct v_text){
.pos = { .x = gx+c.x, .y = gy+c.y },
.uv = { .u = c.u, .v = c.v },
};
vtstack_push(&ren.font_stack, &v);
return 0;
}
// TODO: stop drawing when outside the bounding box
// TODO: implement font size
int ren_render_text(const char *str, int x, int y, int w, int h, int size)
{
// TODO: check size, if the current font is not of the same size then load
// load a new font and use that texture instead, this implies making
// a system to store and use different fonts, like:
@ -540,13 +584,10 @@ 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;
struct font_glyph c;
size_t ret, off;
uint_least32_t cp;
int updated, gx = x, gy = y;
struct v_text v;
for (off = 0; (ret = grapheme_decode_utf8(str+off, SIZE_MAX, &cp)) > 0 && cp != 0; off += ret) {
// skip special characters that render a box (not present in font)
// FIXME: handle tab
@ -557,50 +598,14 @@ int ren_render_text(const char *str, int x, int y, int w, int h, int size)
if (update_font_texture())
REN_RET(-1, REN_TEXTURE);
}
c = *g;
//printf("g: u=%d v=%d w=%d h=%d a=%d x=%d y=%d\n", c.u, c.v, c.w, c.h, c.a, c.x, c.y);
//printf("v: x=%d y=%d u=%d v=%d\n", v.pos.x, v.pos.y, v.uv.u, v.uv.v);
// x1,y1
v = (struct v_text){
.pos = { .x = gx+c.x, .y = gy+c.y+c.h },
.uv = { .u = c.u, .v = c.v+c.h },
};
vtstack_push(&ren.font_stack, &v);
// x2,y2
v = (struct v_text){
.pos = { .x = gx+c.x+c.w, .y = gy+c.y+c.h },
.uv = { .u = c.u+c.w, .v = c.v+c.h },
};
vtstack_push(&ren.font_stack, &v);
// x3,y3
v = (struct v_text){
.pos = { .x = gx+c.x+c.w, .y = gy+c.y },
.uv = { .u = c.u+c.w, .v = c.v },
};
vtstack_push(&ren.font_stack, &v);
// x1,y1
v = (struct v_text){
.pos = { .x = gx+c.x, .y = gy+c.y+c.h },
.uv = { .u = c.u, .v = c.v+c.h },
};
vtstack_push(&ren.font_stack, &v);
// x3,y3
v = (struct v_text){
.pos = { .x = gx+c.x+c.w, .y = gy+c.y },
.uv = { .u = c.u+c.w, .v = c.v },
};
vtstack_push(&ren.font_stack, &v);
// x4,y4
v = (struct v_text){
.pos = { .x = gx+c.x, .y = gy+c.y },
.uv = { .u = c.u, .v = c.v },
};
vtstack_push(&ren.font_stack, &v);
// only push the glyph if it is inside the bounding box
if (gx <= x+w && gy <= y+h)
ren_push_glyph(g, gx, gy);
// TODO: possible kerning needs to be applied here
// TODO: handle other unicode control characters such as the
// right-to-left isolate (\u2067)
gx += c.x + c.a;
gx += g->x + g->a;
skip_render:
switch (cp) {
case '\r':
@ -632,6 +637,17 @@ int ren_render_text(const char *str, int x, int y, int w, int h, int size)
#define A(x) ((x>>24)&0xff)
static int ren_push_box(int x, int y, int w, int h, unsigned int color)
{
/* x4,y4 x3,y3
* +-------------+
* |(x,y) /|
* | / |
* | 2 / |
* | / |
* | / |
* | / 1 |
* |/ |
* +-------------+
* x1,y1 x2,y2 */
struct v_col v;
vec4_i c = {
.r = RENORM(R(color)),

Loading…
Cancel
Save