font almost done
This commit is contained in:
parent
24688273bb
commit
8793415d6b
4
Makefile
4
Makefile
|
@ -1,5 +1,5 @@
|
|||
# Install
|
||||
BIN = x11
|
||||
BIN = opengl
|
||||
|
||||
# Compiler
|
||||
CC = gcc
|
||||
|
@ -15,7 +15,7 @@ CFLAGS += -Wshadow -Wpointer-arith -Wcast-qual -Wmissing-prototypes
|
|||
CFLAGS += -Wswitch-default -Wundef -Wstrict-overflow=5
|
||||
CFLAGS += -Winit-self -Wstrict-aliasing -Wunused
|
||||
|
||||
SRC = gui.c x11.c
|
||||
SRC = gui.c opengl.c
|
||||
OBJ = $(SRC:.c=.o)
|
||||
|
||||
# Modes
|
||||
|
|
209
gui.c
209
gui.c
|
@ -128,7 +128,7 @@ gui_input_begin(struct gui_input *in)
|
|||
{
|
||||
if (!in) return;
|
||||
in->mouse_clicked = 0;
|
||||
in->glyph_count = 0;
|
||||
in->text_len = 0;
|
||||
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;
|
||||
if (!in) return;
|
||||
len = utf_decode(glyph, &unicode, GUI_UTF_SIZE);
|
||||
if (len && in->glyph_count < GUI_INPUT_MAX) {
|
||||
utf_encode(unicode, in->text[in->glyph_count], GUI_UTF_SIZE);
|
||||
in->glyph_count++;
|
||||
if (len && ((in->text_len + len) < GUI_INPUT_MAX)) {
|
||||
utf_encode(unicode, &in->text[in->text_len], GUI_INPUT_MAX - in->text_len);
|
||||
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*
|
||||
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)
|
||||
{
|
||||
gui_size memory = 0;
|
||||
gui_size current;
|
||||
struct gui_draw_command *cmd = NULL;
|
||||
if (!list || !rect) return NULL;
|
||||
if (!list->end || !list->begin || list->end < list->begin)
|
||||
if (!que || !rect) return NULL;
|
||||
if (!que->end || !que->begin || que->end < que->begin)
|
||||
return NULL;
|
||||
|
||||
memory += sizeof(struct gui_draw_command);
|
||||
memory += sizeof(struct gui_vertex) * count;
|
||||
list->needed += memory;
|
||||
list->vertex_count += count;
|
||||
current = (gui_byte*)list->end - (gui_byte*)list->begin;
|
||||
if (list->size <= (current + memory))
|
||||
que->needed += memory;
|
||||
que->vertex_count += count;
|
||||
current = (gui_byte*)que->end - (gui_byte*)que->begin;
|
||||
if (que->size <= (current + memory))
|
||||
return NULL;
|
||||
|
||||
cmd = list->end;
|
||||
list->end = (struct gui_draw_command*)((gui_byte*)list->end + memory);
|
||||
cmd = que->end;
|
||||
que->end = (struct gui_draw_command*)((gui_byte*)que->end + memory);
|
||||
cmd->vertexes = (struct gui_vertex*)(cmd + 1);
|
||||
cmd->vertex_write = 0;
|
||||
cmd->vertex_count = count;
|
||||
|
@ -267,25 +267,25 @@ gui_vertex_line(struct gui_draw_command* cmd, gui_float x0, gui_float y0,
|
|||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct gui_draw_command *cmd;
|
||||
if (!list) return;
|
||||
if (!que) 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;
|
||||
gui_vertex_line(cmd, x0, y0, x1, y1, col);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct gui_draw_command *cmd;
|
||||
if (!list) return;
|
||||
if (!que) 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;
|
||||
gui_vertex(cmd, x0, y0, 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
|
||||
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)
|
||||
{
|
||||
struct gui_draw_command *cmd;
|
||||
if (!list) return;
|
||||
if (!que) 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;
|
||||
|
||||
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
|
||||
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)
|
||||
{
|
||||
struct gui_draw_command *cmd;
|
||||
if (!list) return;
|
||||
if (!que) 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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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,
|
||||
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;
|
||||
const struct gui_font_glyph *g;
|
||||
|
||||
if (!list) return;
|
||||
if (!que || !t || !font || !len) return;
|
||||
clip.x = x; clip.y = y;
|
||||
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;
|
||||
|
||||
text_len = utf_decode(t, &unicode, len);
|
||||
while (text_len < len) {
|
||||
gui_float x1, y1, x2, y2;
|
||||
while (text_len <= len) {
|
||||
gui_float x1, y1, x2, y2, char_width = 0;
|
||||
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;
|
||||
|
||||
x1 = x + off;
|
||||
x2 = x + w + off;
|
||||
off += g->width + g->xadvance;
|
||||
y1 = y;/*(gui_float)(y + (g->yoff * font->scale));*/
|
||||
y2 = (gui_float)(y1 + (gui_float)g->height * font->scale);
|
||||
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, 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);
|
||||
gui_vertex(cmd, x1, y1, col, g->uv[0].u, g->uv[0].v);
|
||||
gui_vertex(cmd, x2, y1, col, g->uv[1].u, g->uv[0].v);
|
||||
gui_vertex(cmd, x2, y2, col, g->uv[1].u, g->uv[1].v);
|
||||
gui_vertex(cmd, x1, y1, col, g->uv[0].u, g->uv[0].v);
|
||||
gui_vertex(cmd, x2, y2, col, g->uv[1].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);
|
||||
x += char_width;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
list->begin = (struct gui_draw_command*)memory;
|
||||
list->end = (struct gui_draw_command*)memory;
|
||||
list->memory = memory;
|
||||
list->size = size;
|
||||
list->needed = 0;
|
||||
if (!que || !memory || !size) return;
|
||||
que->begin = (struct gui_draw_command*)memory;
|
||||
que->end = (struct gui_draw_command*)memory;
|
||||
que->memory = memory;
|
||||
que->size = size;
|
||||
que->needed = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
if (!iter || !iter->vertexes || iter < list->begin || iter > list->end)
|
||||
if (!iter || !iter->vertexes || iter < que->begin || iter > que->end)
|
||||
return NULL;
|
||||
|
||||
size += sizeof(struct gui_draw_command);
|
||||
size += sizeof(struct gui_vertex) * iter->vertex_count;
|
||||
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;
|
||||
}
|
||||
|
||||
gui_size
|
||||
gui_end(struct gui_draw_list *list)
|
||||
gui_end(struct gui_draw_queue *que)
|
||||
{
|
||||
gui_size needed;
|
||||
if (!list) return 0;
|
||||
needed = list->needed;
|
||||
list->needed = 0;
|
||||
if (!que) return 0;
|
||||
needed = que->needed;
|
||||
que->needed = 0;
|
||||
return needed;
|
||||
}
|
||||
|
||||
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,
|
||||
gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad,
|
||||
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 (!que || !in) return gui_false;
|
||||
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;
|
||||
if (INBOX(clicked_x, clicked_y, x, y, x+w, y+h))
|
||||
ret = gui_true;
|
||||
}
|
||||
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);
|
||||
gui_rectf(que, x, y, w, h, bg);
|
||||
gui_rect(que, x+1, y, w-1, h, fg);
|
||||
gui_text(que, font, x + pad, y + pad, w - 2 * pad, h - 2 * pad, fg, t, l);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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,
|
||||
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)
|
||||
|
@ -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_y = y + pad;
|
||||
|
||||
if (!list || !in) return 0;
|
||||
if (!que || !in) return 0;
|
||||
mouse_x = in->mouse_pos.x;
|
||||
mouse_y = in->mouse_pos.y;
|
||||
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;
|
||||
}
|
||||
}
|
||||
gui_rectf(list, x, y, w, h, bg);
|
||||
gui_rectf(list, cursor_x, cursor_y, cursor_w, cursor_h, fg);
|
||||
gui_rectf(que, x, y, w, h, bg);
|
||||
gui_rectf(que, cursor_x, cursor_y, cursor_w, cursor_h, fg);
|
||||
return value;
|
||||
}
|
||||
|
||||
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,
|
||||
gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad,
|
||||
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_w, cursor_h;
|
||||
|
||||
if (!list || !in) return 0;
|
||||
if (!que || !in) return 0;
|
||||
mouse_x = in->mouse_pos.x;
|
||||
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_x = x + pad;
|
||||
cursor_y = y + pad;
|
||||
gui_rectf(list, x, y, w, h, bg);
|
||||
gui_rectf(list, cursor_x, cursor_y, cursor_w, cursor_h, fg);
|
||||
gui_rectf(que, x, y, w, h, bg);
|
||||
gui_rectf(que, cursor_x, cursor_y, cursor_w, cursor_h, fg);
|
||||
return value;
|
||||
}
|
||||
|
||||
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,
|
||||
gui_int x, gui_int y, gui_int w, gui_int h,
|
||||
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 xpad, ypad, xmid;
|
||||
|
||||
if (!list || !in) return 0;
|
||||
gui_rectf(list, x, y, w, h, bg);
|
||||
if (!que || !in) return 0;
|
||||
gui_rectf(que, x, y, w, h, bg);
|
||||
if (dst <= h) return 0;
|
||||
|
||||
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);
|
||||
boff = button_y + (button_size - pad);
|
||||
|
||||
up = gui_button(list, 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);
|
||||
gui_trianglef(list, xmid, y + pad, xoff, yoff, xpad, yoff, bg);
|
||||
gui_trianglef(list, xpad, ypad, xoff, ypad, xmid, boff, bg);
|
||||
up = gui_button(que, in, NULL, fg, bg, x, 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(que, xmid, y + pad, xoff, yoff, xpad, yoff, bg);
|
||||
gui_trianglef(que, xpad, ypad, xoff, ypad, xmid, boff, bg);
|
||||
|
||||
cursor_px = cursor_x + cursor_w;
|
||||
cursor_py = cursor_y + cursor_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);
|
||||
|
||||
if (in->mouse_down && inscroll && incursor) {
|
||||
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);
|
||||
cursor_y += pixel;
|
||||
} else if (up || down) {
|
||||
const gui_int h2 = h/2;
|
||||
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);
|
||||
}
|
||||
|
||||
gui_rectf(list, cursor_x, cursor_y, cursor_w, cursor_h, fg);
|
||||
gui_rect(list, cursor_x, cursor_y, cursor_w, cursor_h, bg);
|
||||
gui_rectf(que, cursor_x, cursor_y, cursor_w, cursor_h, fg);
|
||||
gui_rect(que, cursor_x+1, cursor_y, cursor_w-1, cursor_h, bg);
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
|
28
gui.h
28
gui.h
|
@ -7,7 +7,7 @@
|
|||
#define TINY_GUI_H_
|
||||
|
||||
#define GUI_UTF_SIZE 4
|
||||
#define GUI_INPUT_MAX 8
|
||||
#define GUI_INPUT_MAX 16
|
||||
|
||||
typedef int gui_int;
|
||||
typedef short gui_short;
|
||||
|
@ -18,7 +18,7 @@ typedef unsigned char gui_char;
|
|||
typedef float gui_float;
|
||||
typedef void* gui_texture;
|
||||
typedef unsigned char gui_byte;
|
||||
typedef unsigned long gui_flag;
|
||||
typedef unsigned int gui_flag;
|
||||
typedef unsigned long gui_size;
|
||||
typedef gui_char gui_glyph[GUI_UTF_SIZE];
|
||||
|
||||
|
@ -42,7 +42,7 @@ struct gui_draw_command {
|
|||
gui_texture texture;
|
||||
};
|
||||
|
||||
struct gui_draw_list {
|
||||
struct gui_draw_queue {
|
||||
struct gui_draw_command *begin;
|
||||
struct gui_draw_command *end;
|
||||
gui_size vertex_count;
|
||||
|
@ -64,8 +64,8 @@ enum gui_keys {
|
|||
|
||||
struct gui_input {
|
||||
gui_bool keys[GUI_KEY_MAX];
|
||||
gui_glyph text[GUI_INPUT_MAX];
|
||||
gui_size glyph_count;
|
||||
gui_char text[GUI_INPUT_MAX];
|
||||
gui_size text_len;
|
||||
struct gui_vec2 mouse_pos;
|
||||
struct gui_vec2 mouse_prev;
|
||||
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_end(struct gui_input *in);
|
||||
|
||||
void gui_begin(struct gui_draw_list *list, gui_byte *memory, gui_size size);
|
||||
gui_size gui_end(struct gui_draw_list *list);
|
||||
const struct gui_draw_command *gui_next(const struct gui_draw_list *list,
|
||||
void gui_begin(struct gui_draw_queue *que, gui_byte *memory, gui_size size);
|
||||
gui_size gui_end(struct gui_draw_queue *que);
|
||||
const struct gui_draw_command *gui_next(const struct gui_draw_queue *que,
|
||||
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,
|
||||
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 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,
|
||||
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 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,
|
||||
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_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,
|
||||
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_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,
|
||||
gui_int x, gui_int y, gui_int w, gui_int h,
|
||||
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,
|
||||
struct gui_color bg, struct gui_color fg,
|
||||
gui_int x, gui_int y, gui_int w, gui_int h,
|
||||
|
|
181
x11.c → opengl.c
181
x11.c → opengl.c
|
@ -38,7 +38,6 @@
|
|||
#define CLAMP(i,v,x) (MAX(MIN(v,x), i))
|
||||
#define LEN(a)(sizeof(a)/sizeof(a)[0])
|
||||
#define UNUSED(a)((void)(a))
|
||||
#define glerror() glerror_(__FILE__, __LINE__)
|
||||
|
||||
/* types */
|
||||
struct XWindow {
|
||||
|
@ -55,8 +54,8 @@ struct XWindow {
|
|||
|
||||
struct GUI {
|
||||
struct XWindow *win;
|
||||
struct gui_draw_list out;
|
||||
struct gui_input input;
|
||||
struct gui_draw_queue out;
|
||||
struct gui_input in;
|
||||
struct gui_font *font;
|
||||
};
|
||||
|
||||
|
@ -75,7 +74,7 @@ static void resize(struct GUI*, XEvent*);
|
|||
|
||||
static struct gui_font *ldfont(const char*, unsigned char);
|
||||
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 */
|
||||
static void
|
||||
|
@ -117,49 +116,49 @@ sleep_for(long t)
|
|||
}
|
||||
|
||||
static void
|
||||
kpress(struct GUI *con, XEvent* e)
|
||||
kpress(struct GUI *gui, XEvent* e)
|
||||
{
|
||||
int ret;
|
||||
struct XWindow *xw = con->win;
|
||||
struct XWindow *xw = gui->win;
|
||||
KeySym *keysym = XGetKeyboardMapping(xw->dpy, e->xkey.keycode, 1, &ret);
|
||||
if (*keysym == XK_Escape) xw->running = 0;
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
gui_input_key(&con->input, GUI_KEY_BACKSPACE, gui_true);
|
||||
gui_input_key(&gui->in, GUI_KEY_BACKSPACE, gui_true);
|
||||
}
|
||||
|
||||
static void
|
||||
krelease(struct GUI *con, XEvent* e)
|
||||
krelease(struct GUI *gui, XEvent* e)
|
||||
{
|
||||
int ret;
|
||||
struct XWindow *xw = con->win;
|
||||
struct XWindow *xw = gui->win;
|
||||
KeySym *keysym = XGetKeyboardMapping(xw->dpy, e->xkey.keycode, 1, &ret);
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
gui_input_key(&con->input, GUI_KEY_BACKSPACE, gui_false);
|
||||
gui_input_key(&gui->in, GUI_KEY_BACKSPACE, gui_false);
|
||||
}
|
||||
|
||||
static void
|
||||
bpress(struct GUI *con, XEvent *evt)
|
||||
bpress(struct GUI *gui, XEvent *evt)
|
||||
{
|
||||
const float x = evt->xbutton.x;
|
||||
const float y = evt->xbutton.y;
|
||||
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
|
||||
|
@ -169,16 +168,16 @@ brelease(struct GUI *con, XEvent *evt)
|
|||
const float y = evt->xbutton.y;
|
||||
struct XWindow *xw = con->win;
|
||||
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
|
||||
bmotion(struct GUI *con, XEvent *evt)
|
||||
bmotion(struct GUI *gui, XEvent *evt)
|
||||
{
|
||||
const gui_int x = evt->xbutton.x;
|
||||
const gui_int y = evt->xbutton.y;
|
||||
struct XWindow *xw = con->win;
|
||||
gui_input_motion(&con->input, x, y);
|
||||
struct XWindow *xw = gui->win;
|
||||
gui_input_motion(&gui->in, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -208,22 +207,61 @@ ldfile(const char* path, int flags, size_t* siz)
|
|||
return buf;
|
||||
}
|
||||
|
||||
static void
|
||||
glerror_(const char *file, int line)
|
||||
static GLuint
|
||||
ldbmp(gui_byte *data, uint32_t *width, uint32_t *height)
|
||||
{
|
||||
const GLenum code = glGetError();
|
||||
if (code == GL_INVALID_ENUM)
|
||||
fprintf(stdout, "[GL] Error: (%s:%d) invalid value!\n", file, line);
|
||||
else if (code == GL_INVALID_OPERATION)
|
||||
fprintf(stdout, "[GL] Error: (%s:%d) invalid operation!\n", file, line);
|
||||
else if (code == GL_INVALID_FRAMEBUFFER_OPERATION)
|
||||
fprintf(stdout, "[GL] Error: (%s:%d) invalid frame op!\n", file, line);
|
||||
else if (code == GL_OUT_OF_MEMORY)
|
||||
fprintf(stdout, "[GL] Error: (%s:%d) out of memory!\n", file, line);
|
||||
else if (code == GL_STACK_UNDERFLOW)
|
||||
fprintf(stdout, "[GL] Error: (%s:%d) stack underflow!\n", file, line);
|
||||
else if (code == GL_STACK_OVERFLOW)
|
||||
fprintf(stdout, "[GL] Error: (%s:%d) stack overflow!\n", file, line);
|
||||
/* texture */
|
||||
GLuint texture;
|
||||
gui_byte *header;
|
||||
gui_byte *target;
|
||||
gui_byte *writer;
|
||||
gui_byte *reader;
|
||||
size_t mem;
|
||||
uint32_t ioff;
|
||||
uint32_t j;
|
||||
int32_t i;
|
||||
|
||||
header = data;
|
||||
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*
|
||||
|
@ -233,25 +271,21 @@ ldfont(const char *name, unsigned char height)
|
|||
gui_texture handle;
|
||||
uintptr_t ptr;
|
||||
} convert;
|
||||
GLuint texture;
|
||||
size_t size;
|
||||
struct gui_font *font;
|
||||
short i = 0;
|
||||
uint32_t bpp;
|
||||
uint32_t img_width, img_height;
|
||||
short max_height = 0;
|
||||
uint32_t ioff;
|
||||
size_t i = 0;
|
||||
|
||||
/* 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 indexes = *(uint16_t*)&buffer[0x02] + 1;
|
||||
uint16_t tex_width = *(uint16_t*)&buffer[0x04];
|
||||
uint16_t tex_height = *(uint16_t*)&buffer[0x06];
|
||||
|
||||
/* glyphes */
|
||||
unsigned char *header;
|
||||
unsigned char *data;
|
||||
unsigned char *iter = &buffer[0x08];
|
||||
gui_byte *iter = &buffer[0x08];
|
||||
size_t mem = sizeof(struct gui_font_glyph) * indexes;
|
||||
struct gui_font_glyph *glyphes = xcalloc(mem, 1);
|
||||
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].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+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/(gui_float)tex_height;
|
||||
glyphes[id].uv[0].u = (float)x/(float)tex_width;
|
||||
glyphes[id].uv[0].v = (float)(y)/(float)tex_height;
|
||||
glyphes[id].uv[1].u = (float)(x+w)/(float)tex_width;
|
||||
glyphes[id].uv[1].v = (float)(y+h)/(float)tex_height;
|
||||
if (glyphes[id].height > max_height) max_height = glyphes[id].height;
|
||||
iter += 22;
|
||||
}
|
||||
|
||||
/* texture */
|
||||
header = iter;
|
||||
assert(header[0] == 'B');
|
||||
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);
|
||||
convert.ptr = ldbmp(iter, &img_width, &img_height);
|
||||
assert(img_width == tex_width && img_height == tex_height);
|
||||
|
||||
/* font */
|
||||
font = xcalloc(sizeof(struct gui_font), 1);
|
||||
|
@ -317,7 +337,7 @@ delfont(struct gui_font *font)
|
|||
}
|
||||
|
||||
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;
|
||||
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 c = offsetof(struct gui_vertex, color);
|
||||
|
||||
if (!list) return;
|
||||
if (!que) return;
|
||||
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
|
||||
glEnable(GL_BLEND);
|
||||
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();
|
||||
glLoadIdentity();
|
||||
|
||||
cmd = list->begin;
|
||||
cmd = que->begin;
|
||||
while (cmd) {
|
||||
const int x = (int)cmd->clip_rect.x;
|
||||
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);
|
||||
glScissor(x, y, w, h);
|
||||
glDrawArrays(GL_TRIANGLES, 0, cmd->vertex_count);
|
||||
cmd = gui_next(list, cmd);
|
||||
cmd = gui_next(que, cmd);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
|
@ -388,6 +408,8 @@ main(int argc, char *argv[])
|
|||
gui_float slider = 5.0f;
|
||||
gui_float prog = 60.0f;
|
||||
gui_float offset = 300;
|
||||
gui_int select = gui_false;
|
||||
const char *selection[] = {"Inactive", "Active"};
|
||||
|
||||
/* x11 */
|
||||
UNUSED(argc); UNUSED(argv);
|
||||
|
@ -423,11 +445,11 @@ main(int argc, char *argv[])
|
|||
|
||||
xw.running = 1;
|
||||
gui.win = &xw;
|
||||
gui.font = ldfont("mono.font", 12);
|
||||
gui.font = ldfont("mono.font", 16);
|
||||
while (xw.running) {
|
||||
XEvent ev;
|
||||
started = timestamp();
|
||||
gui_input_begin(&gui.input);
|
||||
gui_input_begin(&gui.in);
|
||||
while (XCheckWindowEvent(xw.dpy, xw.win, xw.swa.event_mask, &ev)) {
|
||||
if (ev.type == Expose||ev.type == ConfigureNotify) resize(&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 == KeyRelease) krelease(&gui, &ev);
|
||||
}
|
||||
gui_input_end(&gui.input);
|
||||
gui_input_end(&gui.in);
|
||||
|
||||
/* ------------------------- GUI --------------------------*/
|
||||
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");
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
gui_end(&gui.out);
|
||||
/* ---------------------------------------------------------*/
|
Loading…
Reference in New Issue