From 8793415d6b26a0365378c365b447e6b655af2238 Mon Sep 17 00:00:00 2001 From: vurtun Date: Sat, 7 Mar 2015 17:02:37 +0100 Subject: [PATCH] font almost done --- Makefile | 4 +- gui.c | 209 ++++++++++++++++++++++++++++------------------ gui.h | 28 +++---- x11.c => opengl.c | 181 ++++++++++++++++++++++----------------- 4 files changed, 248 insertions(+), 174 deletions(-) rename x11.c => opengl.c (74%) diff --git a/Makefile b/Makefile index 767bdf9..0716705 100644 --- a/Makefile +++ b/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 diff --git a/gui.c b/gui.c index 75175fc..c238928 100644 --- a/gui.c +++ b/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; } diff --git a/gui.h b/gui.h index c857e61..e2e743a 100644 --- a/gui.h +++ b/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, diff --git a/x11.c b/opengl.c similarity index 74% rename from x11.c rename to opengl.c index ae214b4..ba2eb45 100644 --- a/x11.c +++ b/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); /* ---------------------------------------------------------*/