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
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
View File

@ -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
View File

@ -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,

View File

@ -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);
/* ---------------------------------------------------------*/