diff --git a/Makefile b/Makefile index 0a6e353..767bdf9 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ CC = gcc DCC = clang # Flags -CFLAGS = -std=c89 -pedantic -Wno-deprecated-declarations -D_POSIX_C_SOURCE=200809L +CFLAGS = -std=c89 -pedantic-errors -Wno-deprecated-declarations -D_POSIX_C_SOURCE=200809L CFLAGS += -g -Wall -Wextra -Werror -Wformat -Wunreachable-code CFLAGS += -Winline -Wshadow -Wwrite-strings -Wno-unused-variable -Wno-unused-parameter -Wno-unused-function CFLAGS += -Wstrict-prototypes -Wold-style-definition diff --git a/gui.c b/gui.c index ff32c85..75175fc 100644 --- a/gui.c +++ b/gui.c @@ -66,7 +66,7 @@ utf_validate(long *u, gui_size i) return i; } -static long +static gui_long utf_decode_byte(gui_char c, gui_size *i) { if (!i) return 0; @@ -78,10 +78,10 @@ utf_decode_byte(gui_char c, gui_size *i) } static gui_size -utf_decode(gui_char *c, long *u, gui_size clen) +utf_decode(const gui_char *c, gui_long *u, gui_size clen) { gui_size i, j, len, type; - long udecoded; + gui_long udecoded; *u = UTF_INVALID; if (!c || !u) return 0; @@ -103,13 +103,13 @@ utf_decode(gui_char *c, long *u, gui_size clen) } static gui_char -utf_encode_byte(long u, gui_size i) +utf_encode_byte(gui_long u, gui_size i) { return utfbyte[i] | (u & ~utfmask[i]); } static gui_size -utf_encode(long u, gui_char *c, gui_size clen) +utf_encode(gui_long u, gui_char *c, gui_size clen) { gui_size len, i; len = utf_validate(&u, 0); @@ -159,7 +159,7 @@ void gui_input_char(struct gui_input *in, gui_glyph glyph) { gui_size len = 0; - long unicode; + gui_long unicode; if (!in) return; len = utf_decode(glyph, &unicode, GUI_UTF_SIZE); if (len && in->glyph_count < GUI_INPUT_MAX) { @@ -175,6 +175,23 @@ gui_input_end(struct gui_input *in) vec2_sub(in->mouse_delta, in->mouse_pos, in->mouse_prev); } +static gui_size +gui_font_text_width(const struct gui_font *font, const gui_char *t, gui_size l) +{ + gui_long unicode; + gui_size len = 0; + const struct gui_font_glyph *g; + gui_size text_len = utf_decode(t, &unicode, l); + while (text_len < l) { + if (unicode == UTF_INVALID) return 0; + g = (unicode < font->glyph_count) ? &font->glyphes[unicode] : font->fallback; + g = (g->code == 0) ? font->fallback : g; + len += g->width + g->xadvance; + text_len += utf_decode(t + text_len, &unicode, l - text_len); + } + return (gui_size)((gui_float)len * font->scale); +} + static struct gui_draw_command* gui_push_command(struct gui_draw_list *list, gui_size count, const struct gui_rect *rect, gui_texture tex) @@ -206,7 +223,7 @@ gui_push_command(struct gui_draw_list *list, gui_size count, static void gui_vertex(struct gui_draw_command *cmd, gui_float x, gui_float y, - struct gui_color col) + struct gui_color col, gui_float u, gui_float v) { gui_size i; if (!cmd) return; @@ -215,8 +232,8 @@ gui_vertex(struct gui_draw_command *cmd, gui_float x, gui_float y, cmd->vertexes[i].pos.x = x; cmd->vertexes[i].pos.y = y; cmd->vertexes[i].color = col; - cmd->vertexes[i].uv.u = 0.0f; - cmd->vertexes[i].uv.v = 0.0f; + cmd->vertexes[i].uv.u = u; + cmd->vertexes[i].uv.v = v; cmd->vertex_write++; } @@ -241,12 +258,12 @@ gui_vertex_line(struct gui_draw_command* cmd, gui_float x0, gui_float y0, vec2_load(hp0, +hn.y, -hn.x); vec2_load(hp1, -hn.y, +hn.x); - gui_vertex(cmd, a.x + hp0.x, a.y + hp0.y, col); - gui_vertex(cmd, b.x + hp0.x, b.y + hp0.y, col); - gui_vertex(cmd, a.x + hp1.x, a.y + hp1.y, col); - gui_vertex(cmd, b.x + hp0.x, b.y + hp0.y, col); - gui_vertex(cmd, b.x + hp1.x, b.y + hp1.y, col); - gui_vertex(cmd, a.x + hp1.x, a.y + hp1.y, col); + gui_vertex(cmd, a.x + hp0.x, a.y + hp0.y, col, 0.0f, 0.0f); + gui_vertex(cmd, b.x + hp0.x, b.y + hp0.y, col, 0.0f, 0.0f); + gui_vertex(cmd, a.x + hp1.x, a.y + hp1.y, col, 0.0f, 0.0f); + gui_vertex(cmd, b.x + hp0.x, b.y + hp0.y, col, 0.0f, 0.0f); + gui_vertex(cmd, b.x + hp1.x, b.y + hp1.y, col, 0.0f, 0.0f); + gui_vertex(cmd, a.x + hp1.x, a.y + hp1.y, col, 0.0f, 0.0f); } static void @@ -270,9 +287,9 @@ gui_trianglef(struct gui_draw_list *list, gui_float x0, gui_float y0, if (c.a == 0) return; cmd = gui_push_command(list, 3, &null_rect, null_tex); if (!cmd) return; - gui_vertex(cmd, x0, y0, c); - gui_vertex(cmd, x1, y1, c); - gui_vertex(cmd, x2, y2, c); + gui_vertex(cmd, x0, y0, c, 0.0f, 0.0f); + gui_vertex(cmd, x1, y1, c, 0.0f, 0.0f); + gui_vertex(cmd, x2, y2, c, 0.0f, 0.0f); } static void @@ -301,19 +318,52 @@ gui_rectf(struct gui_draw_list *list, gui_float x, gui_float y, cmd = gui_push_command(list, 6, &null_rect, null_tex); if (!cmd) return; - gui_vertex(cmd, x, y, col); - gui_vertex(cmd, x + w, y, col); - gui_vertex(cmd, x + w, y + h, col); - gui_vertex(cmd, x, y, col); - gui_vertex(cmd, x + w, y + h, col); - gui_vertex(cmd, x, y + h, col); + gui_vertex(cmd, x, y, col, 0.0f, 0.0f); + gui_vertex(cmd, x + w, y, col, 0.0f, 0.0f); + gui_vertex(cmd, x + w, y + h, col, 0.0f, 0.0f); + gui_vertex(cmd, x, y, col, 0.0f, 0.0f); + gui_vertex(cmd, x + w, y + h, col, 0.0f, 0.0f); + gui_vertex(cmd, x, y + h, col, 0.0f, 0.0f); } -static void -gui_text(const struct gui_draw_list *list, gui_float x, gui_float y, - gui_float w, gui_float h, const gui_char *txt, gui_size len) -{ +static void +gui_text(struct gui_draw_list *list, const struct gui_font *font, gui_float x, + gui_float y, gui_float w, gui_float h, + struct gui_color col, const gui_char *t, gui_size len) +{ + struct gui_draw_command *cmd; + struct gui_rect clip; + gui_size text_len; + gui_float off = 0; + gui_long unicode; + const struct gui_font_glyph *g; + + if (!list) return; + clip.x = x; clip.y = y; + clip.w = w; clip.h = h; + cmd = gui_push_command(list, 6 * len, &clip, font->texture); + if (!cmd) return; + + text_len = utf_decode(t, &unicode, len); + while (text_len < len) { + gui_float x1, y1, x2, y2; + if (unicode == UTF_INVALID) break; + g = (unicode < font->glyph_count) ? &font->glyphes[unicode] : font->fallback; + g = (g->code == 0) ? font->fallback : g; + + x1 = x + off; + x2 = x + w + off; + off += g->width + g->xadvance; + + gui_vertex(cmd, x1, y, col, g->uv[0].u, g->uv[0].v); + gui_vertex(cmd, x2, y, col, g->uv[1].u, g->uv[0].v); + gui_vertex(cmd, x2, y+h, col, g->uv[1].u, g->uv[1].v); + gui_vertex(cmd, x1, y, col, g->uv[0].u, g->uv[0].v); + gui_vertex(cmd, x2, y+h, col, g->uv[1].u, g->uv[1].v); + gui_vertex(cmd, x1, y+h, col, g->uv[0].u, g->uv[1].v); + text_len += utf_decode(t + text_len, &unicode, len - text_len); + } } void @@ -358,9 +408,10 @@ gui_int gui_button(struct gui_draw_list *list, const struct gui_input *in, const struct gui_font *font, struct gui_color bg, struct gui_color fg, gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad, - const char *str, gui_int len) + const char *str, gui_int l) { gui_int ret = gui_false; + const gui_char *t = (const gui_char*)str; if (!list || !in) return gui_false; if (!in->mouse_down && in->mouse_clicked) { const gui_int clicked_x = in->mouse_clicked_pos.x; @@ -370,6 +421,7 @@ gui_button(struct gui_draw_list *list, const struct gui_input *in, } gui_rectf(list, x, y, w, h, bg); gui_rect(list, x, y, w, h, fg); + gui_text(list, font, x + pad, y + pad, w - 2 * pad, h - 2 * pad, fg, t, l); return ret; } diff --git a/gui.h b/gui.h index 99e8bf7..c857e61 100644 --- a/gui.h +++ b/gui.h @@ -10,7 +10,8 @@ #define GUI_INPUT_MAX 8 typedef int gui_int; -typedef int gui_short; +typedef short gui_short; +typedef long gui_long; typedef int gui_bool; typedef unsigned int gui_flags; typedef unsigned char gui_char; @@ -87,7 +88,7 @@ struct gui_font { gui_texture texture; struct gui_vec2 tex_size; struct gui_font_glyph *glyphes; - gui_size glyph_count; + gui_long glyph_count; const struct gui_font_glyph *fallback; }; diff --git a/x11.c b/x11.c index 55e2b6d..ae214b4 100644 --- a/x11.c +++ b/x11.c @@ -268,9 +268,9 @@ ldfont(const char *name, unsigned char height) glyphes[id].yoff = *(float*)&iter[14]; glyphes[id].xadvance = *(float*)&iter[18]; glyphes[id].uv[0].u = (gui_float)x/(gui_float)tex_width; - glyphes[id].uv[0].v = (gui_float)y/(gui_float)tex_height; + glyphes[id].uv[0].v = (gui_float)(y+h)/(gui_float)tex_height; glyphes[id].uv[1].u = (gui_float)(x+w)/(gui_float)tex_width; - glyphes[id].uv[1].v = (gui_float)(y+h)/(gui_float)tex_height; + glyphes[id].uv[1].v = (gui_float)y/(gui_float)tex_height; if (glyphes[id].height > max_height) max_height = glyphes[id].height; iter += 22; } @@ -423,7 +423,7 @@ main(int argc, char *argv[]) xw.running = 1; gui.win = &xw; - gui.font = ldfont("mono.font", 16); + gui.font = ldfont("mono.font", 12); while (xw.running) { XEvent ev; started = timestamp(); @@ -440,7 +440,7 @@ main(int argc, char *argv[]) /* ------------------------- GUI --------------------------*/ gui_begin(&gui.out, buffer, MAX_VERTEX_BUFFER); - if (gui_button(&gui.out, &gui.input, NULL, colorA, colorC, 50,50,150,30,5,"",0)) + if (gui_button(&gui.out, &gui.input, gui.font, colorA, colorC, 50,50,150,30,5,"button",6)) fprintf(stdout, "Button pressed!\n"); slider = gui_slider(&gui.out, &gui.input, colorA, colorB, 50, 100, 150, 30, 2, 0.0f, slider, 10.0f, 1.0f);