font almost done

This commit is contained in:
vurtun 2015-03-07 17:02:37 +01:00
parent 24688273bb
commit 8793415d6b
4 changed files with 248 additions and 174 deletions

View File

@ -1,5 +1,5 @@
# Install # Install
BIN = x11 BIN = opengl
# Compiler # Compiler
CC = gcc CC = gcc
@ -15,7 +15,7 @@ CFLAGS += -Wshadow -Wpointer-arith -Wcast-qual -Wmissing-prototypes
CFLAGS += -Wswitch-default -Wundef -Wstrict-overflow=5 CFLAGS += -Wswitch-default -Wundef -Wstrict-overflow=5
CFLAGS += -Winit-self -Wstrict-aliasing -Wunused CFLAGS += -Winit-self -Wstrict-aliasing -Wunused
SRC = gui.c x11.c SRC = gui.c opengl.c
OBJ = $(SRC:.c=.o) OBJ = $(SRC:.c=.o)
# Modes # Modes

209
gui.c
View File

@ -128,7 +128,7 @@ gui_input_begin(struct gui_input *in)
{ {
if (!in) return; if (!in) return;
in->mouse_clicked = 0; in->mouse_clicked = 0;
in->glyph_count = 0; in->text_len = 0;
vec2_mov(in->mouse_prev, in->mouse_pos); vec2_mov(in->mouse_prev, in->mouse_pos);
} }
@ -162,9 +162,9 @@ gui_input_char(struct gui_input *in, gui_glyph glyph)
gui_long unicode; gui_long unicode;
if (!in) return; if (!in) return;
len = utf_decode(glyph, &unicode, GUI_UTF_SIZE); len = utf_decode(glyph, &unicode, GUI_UTF_SIZE);
if (len && in->glyph_count < GUI_INPUT_MAX) { if (len && ((in->text_len + len) < GUI_INPUT_MAX)) {
utf_encode(unicode, in->text[in->glyph_count], GUI_UTF_SIZE); utf_encode(unicode, &in->text[in->text_len], GUI_INPUT_MAX - in->text_len);
in->glyph_count++; in->text_len += len;
} }
} }
@ -193,26 +193,26 @@ gui_font_text_width(const struct gui_font *font, const gui_char *t, gui_size l)
} }
static struct gui_draw_command* static struct gui_draw_command*
gui_push_command(struct gui_draw_list *list, gui_size count, gui_push_command(struct gui_draw_queue *que, gui_size count,
const struct gui_rect *rect, gui_texture tex) const struct gui_rect *rect, gui_texture tex)
{ {
gui_size memory = 0; gui_size memory = 0;
gui_size current; gui_size current;
struct gui_draw_command *cmd = NULL; struct gui_draw_command *cmd = NULL;
if (!list || !rect) return NULL; if (!que || !rect) return NULL;
if (!list->end || !list->begin || list->end < list->begin) if (!que->end || !que->begin || que->end < que->begin)
return NULL; return NULL;
memory += sizeof(struct gui_draw_command); memory += sizeof(struct gui_draw_command);
memory += sizeof(struct gui_vertex) * count; memory += sizeof(struct gui_vertex) * count;
list->needed += memory; que->needed += memory;
list->vertex_count += count; que->vertex_count += count;
current = (gui_byte*)list->end - (gui_byte*)list->begin; current = (gui_byte*)que->end - (gui_byte*)que->begin;
if (list->size <= (current + memory)) if (que->size <= (current + memory))
return NULL; return NULL;
cmd = list->end; cmd = que->end;
list->end = (struct gui_draw_command*)((gui_byte*)list->end + memory); que->end = (struct gui_draw_command*)((gui_byte*)que->end + memory);
cmd->vertexes = (struct gui_vertex*)(cmd + 1); cmd->vertexes = (struct gui_vertex*)(cmd + 1);
cmd->vertex_write = 0; cmd->vertex_write = 0;
cmd->vertex_count = count; cmd->vertex_count = count;
@ -267,25 +267,25 @@ gui_vertex_line(struct gui_draw_command* cmd, gui_float x0, gui_float y0,
} }
static void static void
gui_line(struct gui_draw_list *list, gui_float x0, gui_float y0, gui_line(struct gui_draw_queue *que, gui_float x0, gui_float y0,
gui_float x1, gui_float y1, struct gui_color col) gui_float x1, gui_float y1, struct gui_color col)
{ {
struct gui_draw_command *cmd; struct gui_draw_command *cmd;
if (!list) return; if (!que) return;
if (col.a == 0) return; if (col.a == 0) return;
cmd = gui_push_command(list, 6, &null_rect, null_tex); cmd = gui_push_command(que, 6, &null_rect, null_tex);
if (!cmd) return; if (!cmd) return;
gui_vertex_line(cmd, x0, y0, x1, y1, col); gui_vertex_line(cmd, x0, y0, x1, y1, col);
} }
static void static void
gui_trianglef(struct gui_draw_list *list, gui_float x0, gui_float y0, gui_trianglef(struct gui_draw_queue *que, gui_float x0, gui_float y0,
gui_float x1, gui_float y1, gui_float x2, gui_float y2, struct gui_color c) gui_float x1, gui_float y1, gui_float x2, gui_float y2, struct gui_color c)
{ {
struct gui_draw_command *cmd; struct gui_draw_command *cmd;
if (!list) return; if (!que) return;
if (c.a == 0) return; if (c.a == 0) return;
cmd = gui_push_command(list, 3, &null_rect, null_tex); cmd = gui_push_command(que, 3, &null_rect, null_tex);
if (!cmd) return; if (!cmd) return;
gui_vertex(cmd, x0, y0, c, 0.0f, 0.0f); gui_vertex(cmd, x0, y0, c, 0.0f, 0.0f);
gui_vertex(cmd, x1, y1, c, 0.0f, 0.0f); gui_vertex(cmd, x1, y1, c, 0.0f, 0.0f);
@ -293,13 +293,13 @@ gui_trianglef(struct gui_draw_list *list, gui_float x0, gui_float y0,
} }
static void static void
gui_rect(struct gui_draw_list *list, gui_float x, gui_float y, gui_rect(struct gui_draw_queue *que, gui_float x, gui_float y,
gui_float w, gui_float h, struct gui_color col) gui_float w, gui_float h, struct gui_color col)
{ {
struct gui_draw_command *cmd; struct gui_draw_command *cmd;
if (!list) return; if (!que) return;
if (col.a == 0) return; if (col.a == 0) return;
cmd = gui_push_command(list, 6 * 4, &null_rect, null_tex); cmd = gui_push_command(que, 6 * 4, &null_rect, null_tex);
if (!cmd) return; if (!cmd) return;
gui_vertex_line(cmd, x, y, x + w, y, col); gui_vertex_line(cmd, x, y, x + w, y, col);
@ -309,13 +309,13 @@ gui_rect(struct gui_draw_list *list, gui_float x, gui_float y,
} }
static void static void
gui_rectf(struct gui_draw_list *list, gui_float x, gui_float y, gui_rectf(struct gui_draw_queue *que, gui_float x, gui_float y,
gui_float w, gui_float h, struct gui_color col) gui_float w, gui_float h, struct gui_color col)
{ {
struct gui_draw_command *cmd; struct gui_draw_command *cmd;
if (!list) return; if (!que) return;
if (col.a == 0) return; if (col.a == 0) return;
cmd = gui_push_command(list, 6, &null_rect, null_tex); cmd = gui_push_command(que, 6, &null_rect, null_tex);
if (!cmd) return; if (!cmd) return;
gui_vertex(cmd, x, y, col, 0.0f, 0.0f); gui_vertex(cmd, x, y, col, 0.0f, 0.0f);
@ -326,9 +326,8 @@ gui_rectf(struct gui_draw_list *list, gui_float x, gui_float y,
gui_vertex(cmd, x, y + h, col, 0.0f, 0.0f); gui_vertex(cmd, x, y + h, col, 0.0f, 0.0f);
} }
static void static void
gui_text(struct gui_draw_list *list, const struct gui_font *font, gui_float x, gui_text(struct gui_draw_queue *que, const struct gui_font *font, gui_float x,
gui_float y, gui_float w, gui_float h, gui_float y, gui_float w, gui_float h,
struct gui_color col, const gui_char *t, gui_size len) struct gui_color col, const gui_char *t, gui_size len)
{ {
@ -339,94 +338,143 @@ gui_text(struct gui_draw_list *list, const struct gui_font *font, gui_float x,
gui_long unicode; gui_long unicode;
const struct gui_font_glyph *g; const struct gui_font_glyph *g;
if (!list) return; if (!que || !t || !font || !len) return;
clip.x = x; clip.y = y; clip.x = x; clip.y = y;
clip.w = w; clip.h = h; clip.w = w; clip.h = h;
cmd = gui_push_command(list, 6 * len, &clip, font->texture); cmd = gui_push_command(que, 6 * len, &clip, font->texture);
if (!cmd) return; if (!cmd) return;
text_len = utf_decode(t, &unicode, len); text_len = utf_decode(t, &unicode, len);
while (text_len < len) { while (text_len <= len) {
gui_float x1, y1, x2, y2; gui_float x1, y1, x2, y2, char_width = 0;
if (unicode == UTF_INVALID) break; if (unicode == UTF_INVALID) break;
g = (unicode < font->glyph_count) ? &font->glyphes[unicode] : font->fallback; g = (unicode < font->glyph_count) ?
&font->glyphes[unicode] :
font->fallback;
g = (g->code == 0) ? font->fallback : g; g = (g->code == 0) ? font->fallback : g;
x1 = x + off; y1 = y;/*(gui_float)(y + (g->yoff * font->scale));*/
x2 = x + w + off; y2 = (gui_float)(y1 + (gui_float)g->height * font->scale);
off += g->width + g->xadvance; x1 = (gui_float)(x + g->xoff * font->scale);
x2 = (gui_float)(x1 + (gui_float)g->width * font->scale);
char_width = g->xadvance * font->scale;
gui_vertex(cmd, x1, y, col, g->uv[0].u, g->uv[0].v); gui_vertex(cmd, x1, y1, 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, y1, 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, x2, y2, 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, x1, y1, 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, x2, y2, col, g->uv[1].u, g->uv[1].v);
gui_vertex(cmd, x1, y+h, col, g->uv[0].u, g->uv[1].v); gui_vertex(cmd, x1, y2, col, g->uv[0].u, g->uv[1].v);
text_len += utf_decode(t + text_len, &unicode, len - text_len); text_len += utf_decode(t + text_len, &unicode, len - text_len);
x += char_width;
} }
} }
void void
gui_begin(struct gui_draw_list *list, gui_byte *memory, gui_size size) gui_begin(struct gui_draw_queue *que, gui_byte *memory, gui_size size)
{ {
if (!list || !memory || !size) return; if (!que || !memory || !size) return;
list->begin = (struct gui_draw_command*)memory; que->begin = (struct gui_draw_command*)memory;
list->end = (struct gui_draw_command*)memory; que->end = (struct gui_draw_command*)memory;
list->memory = memory; que->memory = memory;
list->size = size; que->size = size;
list->needed = 0; que->needed = 0;
} }
const struct gui_draw_command* const struct gui_draw_command*
gui_next(const struct gui_draw_list *list, const struct gui_draw_command *iter) gui_next(const struct gui_draw_queue *que, const struct gui_draw_command *iter)
{ {
gui_size size = 0; gui_size size = 0;
const struct gui_draw_command *cmd = NULL; const struct gui_draw_command *cmd = NULL;
if (!list || !list->memory || !list->begin || !list->end || !list->size) if (!que || !que->memory || !que->begin || !que->end || !que->size)
return NULL; return NULL;
if (!iter || !iter->vertexes || iter < list->begin || iter > list->end) if (!iter || !iter->vertexes || iter < que->begin || iter > que->end)
return NULL; return NULL;
size += sizeof(struct gui_draw_command); size += sizeof(struct gui_draw_command);
size += sizeof(struct gui_vertex) * iter->vertex_count; size += sizeof(struct gui_vertex) * iter->vertex_count;
cmd = (const struct gui_draw_command*)((const gui_byte*)iter + size); cmd = (const struct gui_draw_command*)((const gui_byte*)iter + size);
if (cmd >= list->end) return NULL; if (cmd >= que->end) return NULL;
return cmd; return cmd;
} }
gui_size gui_size
gui_end(struct gui_draw_list *list) gui_end(struct gui_draw_queue *que)
{ {
gui_size needed; gui_size needed;
if (!list) return 0; if (!que) return 0;
needed = list->needed; needed = que->needed;
list->needed = 0; que->needed = 0;
return needed; return needed;
} }
gui_int gui_int
gui_button(struct gui_draw_list *list, const struct gui_input *in, gui_button(struct gui_draw_queue *que, const struct gui_input *in,
const struct gui_font *font, struct gui_color bg, struct gui_color fg, 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, gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad,
const char *str, gui_int l) const char *str, gui_int l)
{ {
gui_int ret = gui_false; gui_int ret = gui_false;
const gui_char *t = (const gui_char*)str; const gui_char *t = (const gui_char*)str;
if (!list || !in) return gui_false; if (!que || !in) return gui_false;
if (!in->mouse_down && in->mouse_clicked) { if (!in->mouse_down && in->mouse_clicked) {
const gui_int clicked_x = in->mouse_clicked_pos.x; const gui_int clicked_x = in->mouse_clicked_pos.x;
const gui_int clicked_y = in->mouse_clicked_pos.y; const gui_int clicked_y = in->mouse_clicked_pos.y;
if (INBOX(clicked_x, clicked_y, x, y, x+w, y+h)) if (INBOX(clicked_x, clicked_y, x, y, x+w, y+h))
ret = gui_true; ret = gui_true;
} }
gui_rectf(list, x, y, w, h, bg); gui_rectf(que, x, y, w, h, bg);
gui_rect(list, x, y, w, h, fg); gui_rect(que, x+1, y, w-1, h, fg);
gui_text(list, font, x + pad, y + pad, w - 2 * pad, h - 2 * pad, fg, t, l); gui_text(que, font, x + pad, y + pad, w - 2 * pad, h - 2 * pad, fg, t, l);
return ret; return ret;
} }
gui_int gui_int
gui_slider(struct gui_draw_list *list, const struct gui_input *in, gui_toggle(struct gui_draw_queue *que, 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, gui_int active)
{
gui_int select_x, select_y;
gui_int select_size;
gui_int cursor_x, cursor_y;
gui_int cursor_pad, cursor_size;
gui_int label_x, label_w;
const struct gui_color white = {255, 255, 255, 255};
const gui_char *t = (const gui_char*)str;
w = MAX(w, font->height + 2 * pad);
h = MAX(h, font->height + 2 * pad);
select_x = x + pad;
select_y = y + pad;
select_size = font->height;
cursor_pad = select_size / 8;
cursor_x = select_x + cursor_pad;
cursor_y = select_y + cursor_pad;
cursor_size = select_size - 2 * cursor_pad;
label_x = x + select_size + pad * 2;
label_w = w - select_size + 3 * pad;
if (!in->mouse_down && in->mouse_clicked) {
const gui_int clicked_x = in->mouse_clicked_pos.x;
const gui_int clicked_y = in->mouse_clicked_pos.y;
const gui_int cursor_px = cursor_x + cursor_size;
const gui_int cursor_py = cursor_y + cursor_size;
if (INBOX(clicked_x, clicked_y, cursor_x, cursor_y, cursor_px, cursor_py))
active = !active;
}
gui_rectf(que, select_x, select_y, select_size, select_size, bg);
if (!active) gui_rectf(que, cursor_x, cursor_y, cursor_size, cursor_size, fg);
gui_text(que, font, label_x, y + pad, label_w, h - 2 * pad, white, t, len);
return active;
}
gui_int
gui_slider(struct gui_draw_queue *que, const struct gui_input *in,
struct gui_color bg, struct gui_color fg, struct gui_color bg, struct gui_color fg,
gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad, gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad,
gui_float min, gui_float value, gui_float max, gui_float step) gui_float min, gui_float value, gui_float max, gui_float step)
@ -450,7 +498,7 @@ gui_slider(struct gui_draw_list *list, const struct gui_input *in,
cursor_x = x + pad + (cursor_w * (value - min)); cursor_x = x + pad + (cursor_w * (value - min));
cursor_y = y + pad; cursor_y = y + pad;
if (!list || !in) return 0; if (!que || !in) return 0;
mouse_x = in->mouse_pos.x; mouse_x = in->mouse_pos.x;
mouse_y = in->mouse_pos.y; mouse_y = in->mouse_pos.y;
clicked_x = in->mouse_clicked_pos.x; clicked_x = in->mouse_clicked_pos.x;
@ -472,13 +520,13 @@ gui_slider(struct gui_draw_list *list, const struct gui_input *in,
cursor_x = cursor_next_x; cursor_x = cursor_next_x;
} }
} }
gui_rectf(list, x, y, w, h, bg); gui_rectf(que, x, y, w, h, bg);
gui_rectf(list, cursor_x, cursor_y, cursor_w, cursor_h, fg); gui_rectf(que, cursor_x, cursor_y, cursor_w, cursor_h, fg);
return value; return value;
} }
gui_int gui_int
gui_progress(struct gui_draw_list *list, const struct gui_input *in, gui_progress(struct gui_draw_queue *que, const struct gui_input *in,
struct gui_color bg, struct gui_color fg, struct gui_color bg, struct gui_color fg,
gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad, gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad,
gui_size value, gui_size max, gui_bool modifyable) gui_size value, gui_size max, gui_bool modifyable)
@ -488,7 +536,7 @@ gui_progress(struct gui_draw_list *list, const struct gui_input *in,
gui_int cursor_x, cursor_y; gui_int cursor_x, cursor_y;
gui_int cursor_w, cursor_h; gui_int cursor_w, cursor_h;
if (!list || !in) return 0; if (!que || !in) return 0;
mouse_x = in->mouse_pos.x; mouse_x = in->mouse_pos.x;
mouse_y = in->mouse_pos.y; mouse_y = in->mouse_pos.y;
@ -508,13 +556,13 @@ gui_progress(struct gui_draw_list *list, const struct gui_input *in,
cursor_w = (w - 2 * pad) * scale; cursor_w = (w - 2 * pad) * scale;
cursor_x = x + pad; cursor_x = x + pad;
cursor_y = y + pad; cursor_y = y + pad;
gui_rectf(list, x, y, w, h, bg); gui_rectf(que, x, y, w, h, bg);
gui_rectf(list, cursor_x, cursor_y, cursor_w, cursor_h, fg); gui_rectf(que, cursor_x, cursor_y, cursor_w, cursor_h, fg);
return value; return value;
} }
gui_int gui_int
gui_scroll(struct gui_draw_list *list, const struct gui_input *in, gui_scroll(struct gui_draw_queue *que, const struct gui_input *in,
struct gui_color bg, struct gui_color fg, struct gui_color bg, struct gui_color fg,
gui_int x, gui_int y, gui_int w, gui_int h, gui_int x, gui_int y, gui_int w, gui_int h,
gui_int offset, gui_int dst) gui_int offset, gui_int dst)
@ -537,8 +585,8 @@ gui_scroll(struct gui_draw_list *list, const struct gui_input *in,
gui_int xoff, yoff, boff; gui_int xoff, yoff, boff;
gui_int xpad, ypad, xmid; gui_int xpad, ypad, xmid;
if (!list || !in) return 0; if (!que || !in) return 0;
gui_rectf(list, x, y, w, h, bg); gui_rectf(que, x, y, w, h, bg);
if (dst <= h) return 0; if (dst <= h) return 0;
mouse_x = in->mouse_pos.x; mouse_x = in->mouse_pos.x;
@ -570,29 +618,30 @@ gui_scroll(struct gui_draw_list *list, const struct gui_input *in,
yoff = y + (button_size - pad); yoff = y + (button_size - pad);
boff = button_y + (button_size - pad); boff = button_y + (button_size - pad);
up = gui_button(list, in, NULL, fg, bg, x, y, button_size, button_size, 0, "", 0); up = gui_button(que, in, NULL, fg, bg, x, y, button_size, button_size, 0, "", 0);
down = gui_button(list,in,NULL, fg,bg,x,button_y,button_size,button_size,0,"", 0); down = gui_button(que,in,NULL, fg,bg,x,button_y,button_size,button_size,0,"", 0);
gui_trianglef(list, xmid, y + pad, xoff, yoff, xpad, yoff, bg); gui_trianglef(que, xmid, y + pad, xoff, yoff, xpad, yoff, bg);
gui_trianglef(list, xpad, ypad, xoff, ypad, xmid, boff, bg); gui_trianglef(que, xpad, ypad, xoff, ypad, xmid, boff, bg);
cursor_px = cursor_x + cursor_w; cursor_px = cursor_x + cursor_w;
cursor_py = cursor_y + cursor_h; cursor_py = cursor_y + cursor_h;
inscroll = INBOX(mouse_x, mouse_y, x, y, x + w, y + h); inscroll = INBOX(mouse_x, mouse_y, x, y, x + w, y + h);
incursor = INBOX(prev_x, prev_y, cursor_x, cursor_y, cursor_px, cursor_py); incursor = INBOX(prev_x, prev_y, cursor_x, cursor_y, cursor_px, cursor_py);
if (in->mouse_down && inscroll && incursor) { if (in->mouse_down && inscroll && incursor) {
const gui_float pixel = in->mouse_delta.y; const gui_float pixel = in->mouse_delta.y;
const gui_float delta = (pixel/(gui_float)bar_h) * (gui_float)dst; const gui_float delta = (pixel / (gui_float)bar_h) * (gui_float)dst;
offset = CLAMP(0, offset + delta, dst - bar_h); offset = CLAMP(0, offset + delta, dst - bar_h);
cursor_y += pixel; cursor_y += pixel;
} else if (up || down) { } else if (up || down) {
const gui_int h2 = h/2; const gui_int h2 = h/2;
offset = (down) ? MIN(offset + h2, dst - bar_h) : MAX(0, offset - h2); offset = (down) ? MIN(offset + h2, dst - bar_h) : MAX(0, offset - h2);
off = (gui_float)offset/(gui_float)dst; off = (gui_float)offset / (gui_float)dst;
cursor_y = bar_y + (gui_int)(off * bar_h); cursor_y = bar_y + (gui_int)(off * bar_h);
} }
gui_rectf(list, cursor_x, cursor_y, cursor_w, cursor_h, fg); gui_rectf(que, cursor_x, cursor_y, cursor_w, cursor_h, fg);
gui_rect(list, cursor_x, cursor_y, cursor_w, cursor_h, bg); gui_rect(que, cursor_x+1, cursor_y, cursor_w-1, cursor_h, bg);
return offset; return offset;
} }

28
gui.h
View File

@ -7,7 +7,7 @@
#define TINY_GUI_H_ #define TINY_GUI_H_
#define GUI_UTF_SIZE 4 #define GUI_UTF_SIZE 4
#define GUI_INPUT_MAX 8 #define GUI_INPUT_MAX 16
typedef int gui_int; typedef int gui_int;
typedef short gui_short; typedef short gui_short;
@ -18,7 +18,7 @@ typedef unsigned char gui_char;
typedef float gui_float; typedef float gui_float;
typedef void* gui_texture; typedef void* gui_texture;
typedef unsigned char gui_byte; typedef unsigned char gui_byte;
typedef unsigned long gui_flag; typedef unsigned int gui_flag;
typedef unsigned long gui_size; typedef unsigned long gui_size;
typedef gui_char gui_glyph[GUI_UTF_SIZE]; typedef gui_char gui_glyph[GUI_UTF_SIZE];
@ -42,7 +42,7 @@ struct gui_draw_command {
gui_texture texture; gui_texture texture;
}; };
struct gui_draw_list { struct gui_draw_queue {
struct gui_draw_command *begin; struct gui_draw_command *begin;
struct gui_draw_command *end; struct gui_draw_command *end;
gui_size vertex_count; gui_size vertex_count;
@ -64,8 +64,8 @@ enum gui_keys {
struct gui_input { struct gui_input {
gui_bool keys[GUI_KEY_MAX]; gui_bool keys[GUI_KEY_MAX];
gui_glyph text[GUI_INPUT_MAX]; gui_char text[GUI_INPUT_MAX];
gui_size glyph_count; gui_size text_len;
struct gui_vec2 mouse_pos; struct gui_vec2 mouse_pos;
struct gui_vec2 mouse_prev; struct gui_vec2 mouse_prev;
struct gui_vec2 mouse_delta; struct gui_vec2 mouse_delta;
@ -112,34 +112,34 @@ void gui_input_button(struct gui_input *in, gui_int x, gui_int y, gui_int down);
void gui_input_char(struct gui_input *in, gui_glyph glyph); void gui_input_char(struct gui_input *in, gui_glyph glyph);
void gui_input_end(struct gui_input *in); void gui_input_end(struct gui_input *in);
void gui_begin(struct gui_draw_list *list, gui_byte *memory, gui_size size); void gui_begin(struct gui_draw_queue *que, gui_byte *memory, gui_size size);
gui_size gui_end(struct gui_draw_list *list); gui_size gui_end(struct gui_draw_queue *que);
const struct gui_draw_command *gui_next(const struct gui_draw_list *list, const struct gui_draw_command *gui_next(const struct gui_draw_queue *que,
const struct gui_draw_command*); const struct gui_draw_command*);
gui_int gui_button(struct gui_draw_list *list, const struct gui_input *in, gui_int gui_button(struct gui_draw_queue *que, const struct gui_input *in,
const struct gui_font *font, const struct gui_font *font,
struct gui_color bg, struct gui_color fg, struct gui_color bg, struct gui_color fg,
gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad, 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 len);
gui_int gui_toggle(struct gui_draw_list *list, const struct gui_input *in, gui_int gui_toggle(struct gui_draw_queue *que, const struct gui_input *in,
const struct gui_font *font, const struct gui_font *font,
struct gui_color bg, struct gui_color fg, struct gui_color bg, struct gui_color fg,
gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad, gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad,
const char *str, gui_int len, gui_int active); const char *str, gui_int len, gui_int active);
gui_int gui_slider(struct gui_draw_list *list, const struct gui_input *in, gui_int gui_slider(struct gui_draw_queue *que, const struct gui_input *in,
struct gui_color bg, struct gui_color fg, struct gui_color bg, struct gui_color fg,
gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad, gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad,
gui_float min, gui_float v, gui_float max, gui_float step); gui_float min, gui_float v, gui_float max, gui_float step);
gui_int gui_progress(struct gui_draw_list *list, const struct gui_input *in, gui_int gui_progress(struct gui_draw_queue *que, const struct gui_input *in,
struct gui_color bg, struct gui_color fg, struct gui_color bg, struct gui_color fg,
gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad, gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad,
gui_size cur, gui_size max, gui_bool modifyable); gui_size cur, gui_size max, gui_bool modifyable);
gui_int gui_scroll(struct gui_draw_list *list, const struct gui_input *in, gui_int gui_scroll(struct gui_draw_queue *que, const struct gui_input *in,
struct gui_color bg, struct gui_color fg, struct gui_color bg, struct gui_color fg,
gui_int x, gui_int y, gui_int w, gui_int h, gui_int x, gui_int y, gui_int w, gui_int h,
gui_int offset, gui_int dst); gui_int offset, gui_int dst);
gui_int gui_input(struct gui_draw_list *list, const struct gui_input *in, gui_int gui_input(struct gui_draw_queue *que, const struct gui_input *in,
const struct gui_font *font, const struct gui_font *font,
struct gui_color bg, struct gui_color fg, struct gui_color bg, struct gui_color fg,
gui_int x, gui_int y, gui_int w, gui_int h, gui_int x, gui_int y, gui_int w, gui_int h,

View File

@ -38,7 +38,6 @@
#define CLAMP(i,v,x) (MAX(MIN(v,x), i)) #define CLAMP(i,v,x) (MAX(MIN(v,x), i))
#define LEN(a)(sizeof(a)/sizeof(a)[0]) #define LEN(a)(sizeof(a)/sizeof(a)[0])
#define UNUSED(a)((void)(a)) #define UNUSED(a)((void)(a))
#define glerror() glerror_(__FILE__, __LINE__)
/* types */ /* types */
struct XWindow { struct XWindow {
@ -55,8 +54,8 @@ struct XWindow {
struct GUI { struct GUI {
struct XWindow *win; struct XWindow *win;
struct gui_draw_list out; struct gui_draw_queue out;
struct gui_input input; struct gui_input in;
struct gui_font *font; struct gui_font *font;
}; };
@ -75,7 +74,7 @@ static void resize(struct GUI*, XEvent*);
static struct gui_font *ldfont(const char*, unsigned char); static struct gui_font *ldfont(const char*, unsigned char);
static void delfont(struct gui_font *font); static void delfont(struct gui_font *font);
static void draw(struct GUI*, int, int , const struct gui_draw_list*); static void draw(struct GUI*, int, int , const struct gui_draw_queue*);
/* gobals */ /* gobals */
static void static void
@ -117,49 +116,49 @@ sleep_for(long t)
} }
static void static void
kpress(struct GUI *con, XEvent* e) kpress(struct GUI *gui, XEvent* e)
{ {
int ret; int ret;
struct XWindow *xw = con->win; struct XWindow *xw = gui->win;
KeySym *keysym = XGetKeyboardMapping(xw->dpy, e->xkey.keycode, 1, &ret); KeySym *keysym = XGetKeyboardMapping(xw->dpy, e->xkey.keycode, 1, &ret);
if (*keysym == XK_Escape) xw->running = 0; if (*keysym == XK_Escape) xw->running = 0;
else if (*keysym == XK_Shift_L || *keysym == XK_Shift_R) else if (*keysym == XK_Shift_L || *keysym == XK_Shift_R)
gui_input_key(&con->input, GUI_KEY_SHIFT, gui_true); gui_input_key(&gui->in, GUI_KEY_SHIFT, gui_true);
else if (*keysym == XK_Control_L || *keysym == XK_Control_L) else if (*keysym == XK_Control_L || *keysym == XK_Control_L)
gui_input_key(&con->input, GUI_KEY_CTRL, gui_true); gui_input_key(&gui->in, GUI_KEY_CTRL, gui_true);
else if (*keysym == XK_Delete) else if (*keysym == XK_Delete)
gui_input_key(&con->input, GUI_KEY_DEL, gui_true); gui_input_key(&gui->in, GUI_KEY_DEL, gui_true);
else if (*keysym == XK_Return) else if (*keysym == XK_Return)
gui_input_key(&con->input, GUI_KEY_ENTER, gui_true); gui_input_key(&gui->in, GUI_KEY_ENTER, gui_true);
else if (*keysym == XK_BackSpace) else if (*keysym == XK_BackSpace)
gui_input_key(&con->input, GUI_KEY_BACKSPACE, gui_true); gui_input_key(&gui->in, GUI_KEY_BACKSPACE, gui_true);
} }
static void static void
krelease(struct GUI *con, XEvent* e) krelease(struct GUI *gui, XEvent* e)
{ {
int ret; int ret;
struct XWindow *xw = con->win; struct XWindow *xw = gui->win;
KeySym *keysym = XGetKeyboardMapping(xw->dpy, e->xkey.keycode, 1, &ret); KeySym *keysym = XGetKeyboardMapping(xw->dpy, e->xkey.keycode, 1, &ret);
if (*keysym == XK_Shift_L || *keysym == XK_Shift_R) if (*keysym == XK_Shift_L || *keysym == XK_Shift_R)
gui_input_key(&con->input, GUI_KEY_SHIFT, gui_false); gui_input_key(&gui->in, GUI_KEY_SHIFT, gui_false);
else if (*keysym == XK_Control_L || *keysym == XK_Control_L) else if (*keysym == XK_Control_L || *keysym == XK_Control_L)
gui_input_key(&con->input, GUI_KEY_CTRL, gui_false); gui_input_key(&gui->in, GUI_KEY_CTRL, gui_false);
else if (*keysym == XK_Delete) else if (*keysym == XK_Delete)
gui_input_key(&con->input, GUI_KEY_DEL, gui_false); gui_input_key(&gui->in, GUI_KEY_DEL, gui_false);
else if (*keysym == XK_Return) else if (*keysym == XK_Return)
gui_input_key(&con->input, GUI_KEY_ENTER, gui_false); gui_input_key(&gui->in, GUI_KEY_ENTER, gui_false);
else if (*keysym == XK_BackSpace) else if (*keysym == XK_BackSpace)
gui_input_key(&con->input, GUI_KEY_BACKSPACE, gui_false); gui_input_key(&gui->in, GUI_KEY_BACKSPACE, gui_false);
} }
static void static void
bpress(struct GUI *con, XEvent *evt) bpress(struct GUI *gui, XEvent *evt)
{ {
const float x = evt->xbutton.x; const float x = evt->xbutton.x;
const float y = evt->xbutton.y; const float y = evt->xbutton.y;
if (evt->xbutton.button == Button1) if (evt->xbutton.button == Button1)
gui_input_button(&con->input, x, y, gui_true); gui_input_button(&gui->in, x, y, gui_true);
} }
static void static void
@ -169,16 +168,16 @@ brelease(struct GUI *con, XEvent *evt)
const float y = evt->xbutton.y; const float y = evt->xbutton.y;
struct XWindow *xw = con->win; struct XWindow *xw = con->win;
if (evt->xbutton.button == Button1) if (evt->xbutton.button == Button1)
gui_input_button(&con->input, x, y, gui_false); gui_input_button(&con->in, x, y, gui_false);
} }
static void static void
bmotion(struct GUI *con, XEvent *evt) bmotion(struct GUI *gui, XEvent *evt)
{ {
const gui_int x = evt->xbutton.x; const gui_int x = evt->xbutton.x;
const gui_int y = evt->xbutton.y; const gui_int y = evt->xbutton.y;
struct XWindow *xw = con->win; struct XWindow *xw = gui->win;
gui_input_motion(&con->input, x, y); gui_input_motion(&gui->in, x, y);
} }
static void static void
@ -208,22 +207,61 @@ ldfile(const char* path, int flags, size_t* siz)
return buf; return buf;
} }
static void static GLuint
glerror_(const char *file, int line) ldbmp(gui_byte *data, uint32_t *width, uint32_t *height)
{ {
const GLenum code = glGetError(); /* texture */
if (code == GL_INVALID_ENUM) GLuint texture;
fprintf(stdout, "[GL] Error: (%s:%d) invalid value!\n", file, line); gui_byte *header;
else if (code == GL_INVALID_OPERATION) gui_byte *target;
fprintf(stdout, "[GL] Error: (%s:%d) invalid operation!\n", file, line); gui_byte *writer;
else if (code == GL_INVALID_FRAMEBUFFER_OPERATION) gui_byte *reader;
fprintf(stdout, "[GL] Error: (%s:%d) invalid frame op!\n", file, line); size_t mem;
else if (code == GL_OUT_OF_MEMORY) uint32_t ioff;
fprintf(stdout, "[GL] Error: (%s:%d) out of memory!\n", file, line); uint32_t j;
else if (code == GL_STACK_UNDERFLOW) int32_t i;
fprintf(stdout, "[GL] Error: (%s:%d) stack underflow!\n", file, line);
else if (code == GL_STACK_OVERFLOW) header = data;
fprintf(stdout, "[GL] Error: (%s:%d) stack overflow!\n", file, line); if (!width || !height) die("[BMP]: width or height is NULL!");
if (header[0] != 'B' || header[1] != 'M') die("[BMP]: invalid file");
*width = *(uint32_t*)&(header[0x12]);
*height = *(uint32_t*)&(header[0x12]);
ioff = *(uint32_t*)(&header[0x0A]);
data = data + ioff;
reader = data;
mem = *width * *height * 4;
target = xcalloc(mem, 1);
for (i = *height-1; i >= 0; i--) {
writer = target + (i * *width * 4);
for (j = 0; j < *width; j++) {
gui_byte a = *(reader + (j * 4) + 0);
gui_byte r = *(reader + (j * 4) + 1);
gui_byte g = *(reader + (j * 4) + 2);
gui_byte b = *(reader + (j * 4) + 3);
*writer++ = r;
*writer++ = g;
*writer++ = b;
*writer++ = a;
*writer += 4;
}
reader += *width * 4;
}
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, *width, *height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, target);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
free(target);
return texture;
} }
static struct gui_font* static struct gui_font*
@ -233,25 +271,21 @@ ldfont(const char *name, unsigned char height)
gui_texture handle; gui_texture handle;
uintptr_t ptr; uintptr_t ptr;
} convert; } convert;
GLuint texture;
size_t size; size_t size;
struct gui_font *font; struct gui_font *font;
short i = 0; uint32_t img_width, img_height;
uint32_t bpp;
short max_height = 0; short max_height = 0;
uint32_t ioff; size_t i = 0;
/* header */ /* header */
unsigned char *buffer = (unsigned char*)ldfile(name, O_RDONLY, &size); gui_byte *buffer = (gui_byte*)ldfile(name, O_RDONLY, &size);
uint16_t num = *(uint16_t*)buffer; uint16_t num = *(uint16_t*)buffer;
uint16_t indexes = *(uint16_t*)&buffer[0x02] + 1; uint16_t indexes = *(uint16_t*)&buffer[0x02] + 1;
uint16_t tex_width = *(uint16_t*)&buffer[0x04]; uint16_t tex_width = *(uint16_t*)&buffer[0x04];
uint16_t tex_height = *(uint16_t*)&buffer[0x06]; uint16_t tex_height = *(uint16_t*)&buffer[0x06];
/* glyphes */ /* glyphes */
unsigned char *header; gui_byte *iter = &buffer[0x08];
unsigned char *data;
unsigned char *iter = &buffer[0x08];
size_t mem = sizeof(struct gui_font_glyph) * indexes; size_t mem = sizeof(struct gui_font_glyph) * indexes;
struct gui_font_glyph *glyphes = xcalloc(mem, 1); struct gui_font_glyph *glyphes = xcalloc(mem, 1);
for(i = 0; i < num; ++i) { for(i = 0; i < num; ++i) {
@ -267,31 +301,17 @@ ldfont(const char *name, unsigned char height)
glyphes[id].xoff = *(float*)&iter[10]; glyphes[id].xoff = *(float*)&iter[10];
glyphes[id].yoff = *(float*)&iter[14]; glyphes[id].yoff = *(float*)&iter[14];
glyphes[id].xadvance = *(float*)&iter[18]; glyphes[id].xadvance = *(float*)&iter[18];
glyphes[id].uv[0].u = (gui_float)x/(gui_float)tex_width; glyphes[id].uv[0].u = (float)x/(float)tex_width;
glyphes[id].uv[0].v = (gui_float)(y+h)/(gui_float)tex_height; glyphes[id].uv[0].v = (float)(y)/(float)tex_height;
glyphes[id].uv[1].u = (gui_float)(x+w)/(gui_float)tex_width; glyphes[id].uv[1].u = (float)(x+w)/(float)tex_width;
glyphes[id].uv[1].v = (gui_float)y/(gui_float)tex_height; glyphes[id].uv[1].v = (float)(y+h)/(float)tex_height;
if (glyphes[id].height > max_height) max_height = glyphes[id].height; if (glyphes[id].height > max_height) max_height = glyphes[id].height;
iter += 22; iter += 22;
} }
/* texture */ /* texture */
header = iter; convert.ptr = ldbmp(iter, &img_width, &img_height);
assert(header[0] == 'B'); assert(img_width == tex_width && img_height == tex_height);
assert(header[1] == 'M');
ioff = *(uint32_t*)(&header[0x0A]);
data = iter + ioff;
glGenTextures(1, &texture);
convert.ptr = texture;
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0,
GL_BGRA, GL_UNSIGNED_BYTE, data);
glerror();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
/* font */ /* font */
font = xcalloc(sizeof(struct gui_font), 1); font = xcalloc(sizeof(struct gui_font), 1);
@ -317,7 +337,7 @@ delfont(struct gui_font *font)
} }
static void static void
draw(struct GUI *con, int width, int height, const struct gui_draw_list *list) draw(struct GUI *con, int width, int height, const struct gui_draw_queue *que)
{ {
const struct gui_draw_command *cmd; const struct gui_draw_command *cmd;
static const size_t v = sizeof(struct gui_vertex); static const size_t v = sizeof(struct gui_vertex);
@ -325,7 +345,7 @@ draw(struct GUI *con, int width, int height, const struct gui_draw_list *list)
static const size_t t = offsetof(struct gui_vertex, uv); static const size_t t = offsetof(struct gui_vertex, uv);
static const size_t c = offsetof(struct gui_vertex, color); static const size_t c = offsetof(struct gui_vertex, color);
if (!list) return; if (!que) return;
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@ -345,7 +365,7 @@ draw(struct GUI *con, int width, int height, const struct gui_draw_list *list)
glPushMatrix(); glPushMatrix();
glLoadIdentity(); glLoadIdentity();
cmd = list->begin; cmd = que->begin;
while (cmd) { while (cmd) {
const int x = (int)cmd->clip_rect.x; const int x = (int)cmd->clip_rect.x;
const int y = height - (int)(cmd->clip_rect.y + cmd->clip_rect.h); const int y = height - (int)(cmd->clip_rect.y + cmd->clip_rect.h);
@ -358,7 +378,7 @@ draw(struct GUI *con, int width, int height, const struct gui_draw_list *list)
glBindTexture(GL_TEXTURE_2D, (unsigned long)cmd->texture); glBindTexture(GL_TEXTURE_2D, (unsigned long)cmd->texture);
glScissor(x, y, w, h); glScissor(x, y, w, h);
glDrawArrays(GL_TRIANGLES, 0, cmd->vertex_count); glDrawArrays(GL_TRIANGLES, 0, cmd->vertex_count);
cmd = gui_next(list, cmd); cmd = gui_next(que, cmd);
} }
glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_COLOR_ARRAY);
@ -388,6 +408,8 @@ main(int argc, char *argv[])
gui_float slider = 5.0f; gui_float slider = 5.0f;
gui_float prog = 60.0f; gui_float prog = 60.0f;
gui_float offset = 300; gui_float offset = 300;
gui_int select = gui_false;
const char *selection[] = {"Inactive", "Active"};
/* x11 */ /* x11 */
UNUSED(argc); UNUSED(argv); UNUSED(argc); UNUSED(argv);
@ -423,11 +445,11 @@ main(int argc, char *argv[])
xw.running = 1; xw.running = 1;
gui.win = &xw; gui.win = &xw;
gui.font = ldfont("mono.font", 12); gui.font = ldfont("mono.font", 16);
while (xw.running) { while (xw.running) {
XEvent ev; XEvent ev;
started = timestamp(); started = timestamp();
gui_input_begin(&gui.input); gui_input_begin(&gui.in);
while (XCheckWindowEvent(xw.dpy, xw.win, xw.swa.event_mask, &ev)) { while (XCheckWindowEvent(xw.dpy, xw.win, xw.swa.event_mask, &ev)) {
if (ev.type == Expose||ev.type == ConfigureNotify) resize(&gui, &ev); if (ev.type == Expose||ev.type == ConfigureNotify) resize(&gui, &ev);
else if (ev.type == MotionNotify) bmotion(&gui, &ev); else if (ev.type == MotionNotify) bmotion(&gui, &ev);
@ -436,17 +458,20 @@ main(int argc, char *argv[])
else if (ev.type == KeyPress) kpress(&gui, &ev); else if (ev.type == KeyPress) kpress(&gui, &ev);
else if (ev.type == KeyRelease) krelease(&gui, &ev); else if (ev.type == KeyRelease) krelease(&gui, &ev);
} }
gui_input_end(&gui.input); gui_input_end(&gui.in);
/* ------------------------- GUI --------------------------*/ /* ------------------------- GUI --------------------------*/
gui_begin(&gui.out, buffer, MAX_VERTEX_BUFFER); gui_begin(&gui.out, buffer, MAX_VERTEX_BUFFER);
if (gui_button(&gui.out, &gui.input, gui.font, colorA, colorC, 50,50,150,30,5,"button",6)) if (gui_button(&gui.out, &gui.in, gui.font, colorA, colorC, 50,50,150,30,5,"button",6))
fprintf(stdout, "Button pressed!\n"); fprintf(stdout, "Button pressed!\n");
slider = gui_slider(&gui.out, &gui.input, colorA, colorB, slider = gui_slider(&gui.out, &gui.in, colorA, colorB,
50, 100, 150, 30, 2, 0.0f, slider, 10.0f, 1.0f); 50, 100, 150, 30, 2, 0.0f, slider, 10.0f, 1.0f);
prog = gui_progress(&gui.out, &gui.input, colorA, colorB, prog = gui_progress(&gui.out, &gui.in, colorA, colorB,
50, 150, 150, 30, 2, prog, 100.0f, gui_true); 50, 150, 150, 30, 2, prog, 100.0f, gui_true);
offset = gui_scroll(&gui.out, &gui.input, colorA, colorB, select = gui_toggle(&gui.out, &gui.in, gui.font, colorA, colorB,
50, 200, 150, 30, 2, selection[select],
strlen(selection[select]), select);
offset = gui_scroll(&gui.out, &gui.in, colorA, colorB,
250, 50, 16, 300, offset, 600); 250, 50, 16, 300, offset, 600);
gui_end(&gui.out); gui_end(&gui.out);
/* ---------------------------------------------------------*/ /* ---------------------------------------------------------*/