From: yu.dongliang <18588496441@163.com> Date: Sun, 20 Oct 2024 13:23:14 +0000 (+0800) Subject: support HTML
, for text / password / submit X-Git-Url: http://baseworks.info/?a=commitdiff_plain;h=99f950fbd56d014ff863f350269c5171e190e963;p=abc.git support HTML , for text / password / submit --- diff --git a/examples/form.html b/examples/form.html new file mode 100644 index 0000000..8350c76 --- /dev/null +++ b/examples/form.html @@ -0,0 +1,19 @@ + +test + + + + + + +
+ + + +
+ + +
+ + + diff --git a/html/abc_html.c b/html/abc_html.c index 146b53b..d4c4e53 100644 --- a/html/abc_html.c +++ b/html/abc_html.c @@ -4,6 +4,7 @@ typedef struct { char* name; char* value; int type; + int flags; } html_attr_t; typedef struct { @@ -20,59 +21,87 @@ typedef struct { static html_attr_t h1_attrs[] = { - {"font", "SimHei", ABC_HTML_ATTR_FONT}, - {"font-size", "40", ABC_HTML_ATTR_FONT_SIZE}, + {"font", "SimHei", ABC_HTML_ATTR_FONT, 0}, + {"font-size", "40", ABC_HTML_ATTR_FONT_SIZE, 0}, }; static html_attr_t h2_attrs[] = { - {"font", "SimHei", ABC_HTML_ATTR_FONT}, - {"font-size", "32", ABC_HTML_ATTR_FONT_SIZE}, + {"font", "SimHei", ABC_HTML_ATTR_FONT, 0}, + {"font-size", "32", ABC_HTML_ATTR_FONT_SIZE, 0}, }; static html_attr_t h3_attrs[] = { - {"font", "SimHei", ABC_HTML_ATTR_FONT}, - {"font-size", "28", ABC_HTML_ATTR_FONT_SIZE}, + {"font", "SimHei", ABC_HTML_ATTR_FONT, 0}, + {"font-size", "28", ABC_HTML_ATTR_FONT_SIZE, 0}, }; static html_attr_t h4_attrs[] = { - {"font", "SimHei", ABC_HTML_ATTR_FONT}, - {"font-size", "24", ABC_HTML_ATTR_FONT_SIZE}, + {"font", "SimHei", ABC_HTML_ATTR_FONT, 0}, + {"font-size", "24", ABC_HTML_ATTR_FONT_SIZE, 0}, }; static html_attr_t h5_attrs[] = { - {"font", "SimHei", ABC_HTML_ATTR_FONT}, - {"font-size", "20", ABC_HTML_ATTR_FONT_SIZE}, + {"font", "SimHei", ABC_HTML_ATTR_FONT, 0}, + {"font-size", "20", ABC_HTML_ATTR_FONT_SIZE, 0}, }; static html_attr_t h6_attrs[] = { - {"font", "SimHei", ABC_HTML_ATTR_FONT}, - {"font-size", "16", ABC_HTML_ATTR_FONT_SIZE}, + {"font", "SimHei", ABC_HTML_ATTR_FONT, 0}, + {"font-size", "16", ABC_HTML_ATTR_FONT_SIZE, 0}, }; static html_attr_t p_attrs[] = { - {"font", "SimSong", ABC_HTML_ATTR_FONT}, - {"font-size", "16", ABC_HTML_ATTR_FONT_SIZE}, + {"font", "SimSong", ABC_HTML_ATTR_FONT, 0}, + {"font-size", "16", ABC_HTML_ATTR_FONT_SIZE, 0}, }; static html_attr_t a_attrs[] = { - {"href", "", ABC_HTML_ATTR_HREF}, - {"font", "SimHei", ABC_HTML_ATTR_FONT}, - {"font-size", "24", ABC_HTML_ATTR_FONT_SIZE}, - {"font-color", "blue", ABC_HTML_ATTR_FONT_COLOR}, + {"href", "", ABC_HTML_ATTR_HREF, ABC_HTML_FLAG_SHOW}, + {"font", "SimHei", ABC_HTML_ATTR_FONT, 0}, + {"font-size", "24", ABC_HTML_ATTR_FONT_SIZE, 0}, + {"font-color", "blue", ABC_HTML_ATTR_FONT_COLOR, 0}, }; static html_attr_t img_attrs[] = { - {"src", "", ABC_HTML_ATTR_SRC}, - {"width", "100", ABC_HTML_ATTR_WIDTH}, - {"height", "100", ABC_HTML_ATTR_HEIGHT}, + {"src", "", ABC_HTML_ATTR_SRC, ABC_HTML_FLAG_SHOW}, + {"width", "100", ABC_HTML_ATTR_WIDTH, ABC_HTML_FLAG_SHOW}, + {"height", "100", ABC_HTML_ATTR_HEIGHT, ABC_HTML_FLAG_SHOW}, +}; + +static html_attr_t input_attrs[] = +{ + {"type", "text", ABC_HTML_ATTR_TYPE, ABC_HTML_FLAG_SHOW}, + {"id", "", ABC_HTML_ATTR_ID, ABC_HTML_FLAG_SHOW}, + {"name", "", ABC_HTML_ATTR_NAME, ABC_HTML_FLAG_SHOW}, + {"value", "", ABC_HTML_ATTR_VALUE, ABC_HTML_FLAG_SHOW}, + + {"font", "SimSong", ABC_HTML_ATTR_FONT, 0}, + {"font-size", "16", ABC_HTML_ATTR_FONT_SIZE, 0}, +}; + +static html_attr_t label_attrs[] = +{ + {"for", "", ABC_HTML_ATTR_FOR, ABC_HTML_FLAG_SHOW}, + + {"font", "SimSong", ABC_HTML_ATTR_FONT, 0}, + {"font-size", "16", ABC_HTML_ATTR_FONT_SIZE, 0}, +}; + +static html_attr_t form_attrs[] = +{ + {"action", "/", ABC_HTML_ATTR_ACTION, ABC_HTML_FLAG_SHOW}, + {"method", "post", ABC_HTML_ATTR_METHOD, ABC_HTML_FLAG_SHOW}, + + {"font", "SimSong", ABC_HTML_ATTR_FONT, 0}, + {"font-size", "16", ABC_HTML_ATTR_FONT_SIZE, 0}, }; static html_label_t html_labels[] = @@ -84,18 +113,22 @@ static html_label_t html_labels[] = {"div", ABC_HTML_DIV, 0, NULL, ABC_HTML_FLAG_CLOSE}, - {"h1", ABC_HTML_H1, abc_number_of(h1_attrs), h1_attrs, ABC_HTML_FLAG_CLOSE}, - {"h2", ABC_HTML_H2, abc_number_of(h2_attrs), h2_attrs, ABC_HTML_FLAG_CLOSE}, - {"h3", ABC_HTML_H3, abc_number_of(h3_attrs), h3_attrs, ABC_HTML_FLAG_CLOSE}, - {"h4", ABC_HTML_H4, abc_number_of(h4_attrs), h4_attrs, ABC_HTML_FLAG_CLOSE}, - {"h5", ABC_HTML_H5, abc_number_of(h5_attrs), h5_attrs, ABC_HTML_FLAG_CLOSE}, - {"h6", ABC_HTML_H6, abc_number_of(h6_attrs), h6_attrs, ABC_HTML_FLAG_CLOSE}, + {"h1", ABC_HTML_H1, abc_number_of(h1_attrs), h1_attrs, ABC_HTML_FLAG_CLOSE}, + {"h2", ABC_HTML_H2, abc_number_of(h2_attrs), h2_attrs, ABC_HTML_FLAG_CLOSE}, + {"h3", ABC_HTML_H3, abc_number_of(h3_attrs), h3_attrs, ABC_HTML_FLAG_CLOSE}, + {"h4", ABC_HTML_H4, abc_number_of(h4_attrs), h4_attrs, ABC_HTML_FLAG_CLOSE}, + {"h5", ABC_HTML_H5, abc_number_of(h5_attrs), h5_attrs, ABC_HTML_FLAG_CLOSE}, + {"h6", ABC_HTML_H6, abc_number_of(h6_attrs), h6_attrs, ABC_HTML_FLAG_CLOSE}, + + {"p", ABC_HTML_P, abc_number_of(p_attrs), p_attrs, ABC_HTML_FLAG_CLOSE}, + {"br", ABC_HTML_BR, 0, NULL, ABC_HTML_FLAG_OPEN}, - {"p", ABC_HTML_P, abc_number_of(p_attrs), p_attrs, ABC_HTML_FLAG_CLOSE}, - {"br", ABC_HTML_BR, 0, NULL, ABC_HTML_FLAG_OPEN}, + {"a", ABC_HTML_A, abc_number_of(a_attrs), a_attrs, ABC_HTML_FLAG_CLOSE}, + {"img", ABC_HTML_IMG, abc_number_of(img_attrs), img_attrs, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SINGLE}, - {"a", ABC_HTML_A, abc_number_of(a_attrs), a_attrs, ABC_HTML_FLAG_CLOSE}, - {"img", ABC_HTML_IMG, abc_number_of(img_attrs), img_attrs, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SINGLE}, + {"form", ABC_HTML_FORM, abc_number_of(form_attrs), form_attrs, ABC_HTML_FLAG_CLOSE}, + {"input", ABC_HTML_INPUT, abc_number_of(input_attrs), input_attrs, ABC_HTML_FLAG_OPEN}, + {"label", ABC_HTML_LABEL, abc_number_of(label_attrs), label_attrs, ABC_HTML_FLAG_CLOSE}, }; static int __html_parse_obj(abc_html_t* html, abc_char_t* c); @@ -116,7 +149,7 @@ static html_label_t* __html_find_label(const char* name) return NULL; } -static int __html_add_attr(abc_obj_t* obj, int type, const char* name, const char* value) +static int __html_add_attr(abc_obj_t* obj, int type, const char* name, const char* value, int flags) { abc_obj_t* attr = abc_obj_alloc(NULL, 0, 0, type); if (!attr) @@ -134,6 +167,8 @@ static int __html_add_attr(abc_obj_t* obj, int type, const char* name, const cha return -ENOMEM; } + attr->flags = flags; + scf_list_add_tail(&obj->attrs, &attr->list); return 0; } @@ -149,7 +184,7 @@ static int __html_load_attrs(abc_obj_t* obj, html_attr_t* attrs, int n_attrs) if (attrs && n_attrs > 0) { for (i = 0; i < n_attrs; i++) { - ret = __html_add_attr(obj, attrs[i].type, attrs[i].name, attrs[i].value); + ret = __html_add_attr(obj, attrs[i].type, attrs[i].name, attrs[i].value, attrs[i].flags); if (ret < 0) return ret; } @@ -159,7 +194,7 @@ static int __html_load_attrs(abc_obj_t* obj, html_attr_t* attrs, int n_attrs) for (l = scf_list_head(&obj->parent->attrs); l != scf_list_sentinel(&obj->parent->attrs); l = scf_list_next(l)) { attr = scf_list_data(l, abc_obj_t, list); - ret = __html_add_attr(obj, attr->type, attr->key->data, attr->value->data); + ret = __html_add_attr(obj, attr->type, attr->key->data, attr->value->data, 0); if (ret < 0) return ret; } @@ -304,11 +339,12 @@ static int __html_parse_text(abc_html_t* html, abc_obj_t* obj) text = NULL; - if (ABC_HTML_BR == obj->type) { // single label + if (ABC_HTML_FLAG_OPEN == (obj->flags & 0x1)) { // single labels + __html_push_char(html, c); c = NULL; return 0; - } + }; html->pos++; free(c); diff --git a/html/abc_obj.c b/html/abc_obj.c index bc436e7..d7d0fd7 100644 --- a/html/abc_obj.c +++ b/html/abc_obj.c @@ -135,18 +135,16 @@ void abc_obj_print(abc_obj_t* obj) return; if (obj->value) - printf(" %s=%s", obj->key->data, obj->value->data); + printf(" %s=\"%s\"", obj->key->data, obj->value->data); else if (obj->key) printf("<%s", obj->key->data); - if (ABC_HTML_FLAG_CLOSE & obj->flags) { - - for (l = scf_list_head(&obj->attrs); l != scf_list_sentinel(&obj->attrs); l = scf_list_next(l)) { - attr = scf_list_data(l, abc_obj_t, list); + for (l = scf_list_head(&obj->attrs); l != scf_list_sentinel(&obj->attrs); l = scf_list_next(l)) { + attr = scf_list_data(l, abc_obj_t, list); + if (ABC_HTML_FLAG_SHOW & attr->flags) abc_obj_print(attr); - } } if (!obj->value) { diff --git a/html/abc_obj.h b/html/abc_obj.h index eaad4a6..92a8917 100644 --- a/html/abc_obj.h +++ b/html/abc_obj.h @@ -34,12 +34,25 @@ enum abc_objs // 15 ABC_HTML_IMG, + ABC_HTML_FORM, + ABC_HTML_LABEL, + ABC_HTML_INPUT, + ABC_HTML_NB, // total HTML objects ABC_HTML_ATTR_ID, + ABC_HTML_ATTR_TYPE, + ABC_HTML_ATTR_NAME, + ABC_HTML_ATTR_VALUE, + ABC_HTML_ATTR_HREF, ABC_HTML_ATTR_SRC, + ABC_HTML_ATTR_FOR, + + ABC_HTML_ATTR_ACTION, + ABC_HTML_ATTR_METHOD, + ABC_HTML_ATTR_FONT, ABC_HTML_ATTR_FONT_SIZE, ABC_HTML_ATTR_FONT_COLOR, @@ -64,6 +77,7 @@ struct abc_obj_s #define ABC_HTML_FLAG_OPEN 0 #define ABC_HTML_FLAG_CLOSE 1 #define ABC_HTML_FLAG_SINGLE 2 +#define ABC_HTML_FLAG_SHOW 4 uint32_t flags; int x; @@ -71,6 +85,9 @@ struct abc_obj_s int w; int h; + int progress; + uint32_t jiffies; // timeout numbers of sys timer + scf_string_t* key; scf_string_t* value; scf_string_t* text; @@ -78,6 +95,8 @@ struct abc_obj_s scf_string_t* file; // file name int line; // line int pos; // position + + uint32_t clicked:1; }; abc_obj_t* abc_obj_alloc(scf_string_t* file, int line, int pos, int type); diff --git a/ui/Makefile b/ui/Makefile index 4dc7d04..a83c489 100644 --- a/ui/Makefile +++ b/ui/Makefile @@ -9,6 +9,9 @@ CFILES += abc_layout_div.c CFILES += abc_layout_h1.c CFILES += abc_layout_a.c CFILES += abc_layout_img.c +CFILES += abc_layout_form.c +CFILES += abc_layout_label.c +CFILES += abc_layout_input.c CFILES += abc_render.c CFILES += abc_render_html.c @@ -20,6 +23,9 @@ CFILES += abc_render_h1.c CFILES += abc_render_a.c CFILES += abc_render_a_href.c CFILES += abc_render_img.c +CFILES += abc_render_form.c +CFILES += abc_render_label.c +CFILES += abc_render_input.c CFILES += ../html/abc_html.c CFILES += ../html/abc_html_util.c diff --git a/ui/abc.h b/ui/abc.h index 02ac07e..4ed637a 100644 --- a/ui/abc.h +++ b/ui/abc.h @@ -32,16 +32,18 @@ struct abc_render_s struct abc_ctx_s { - scf_list_t html_list; - abc_html_t* current; + scf_list_t html_list; + abc_html_t* current; - GtkBuilder* builder; + GtkBuilder* builder; - GtkGLArea* gl_area; + GtkGLArea* gl_area; - GtkButton* back; - GtkButton* forward; - GtkButton* refresh; + GtkButton* back; + GtkButton* forward; + GtkButton* refresh; + + GtkIMContext* im; }; #define ABC_CTX_INIT(__ctx) {SCF_LIST_INIT((__ctx).html_list), NULL, NULL, NULL, NULL, NULL, NULL} diff --git a/ui/abc_layout.c b/ui/abc_layout.c index 3dde5fb..7b64e5d 100644 --- a/ui/abc_layout.c +++ b/ui/abc_layout.c @@ -10,31 +10,34 @@ int abc_layout_h1 (abc_layout_t* layout, abc_obj_t* obj, int width, int height int abc_layout_a (abc_layout_t* layout, abc_obj_t* obj, int width, int height); int abc_layout_img (abc_layout_t* layout, abc_obj_t* obj, int width, int height); +int abc_layout_form (abc_layout_t* layout, abc_obj_t* obj, int width, int height); +int abc_layout_label(abc_layout_t* layout, abc_obj_t* obj, int width, int height); +int abc_layout_input(abc_layout_t* layout, abc_obj_t* obj, int width, int height); + static abc_layout_pt abc_layouts[ABC_HTML_NB] = { - abc_layout_html, - abc_layout_title, - abc_layout_head, - abc_layout_body, - - // 4 - abc_layout_div, - - // 5 - abc_layout_h1, - abc_layout_h1, - abc_layout_h1, - abc_layout_h1, - abc_layout_h1, - abc_layout_h1, - - // 11 - abc_layout_h1, //

- abc_layout_h1, //
- abc_layout_a, - NULL, - - abc_layout_img, + [ABC_HTML] = abc_layout_html, + [ABC_HTML_TITLE] = abc_layout_title, + [ABC_HTML_HEAD] = abc_layout_head, + [ABC_HTML_BODY] = abc_layout_body, + [ABC_HTML_DIV] = abc_layout_div, + + [ABC_HTML_H1] = abc_layout_h1, + [ABC_HTML_H2] = abc_layout_h1, + [ABC_HTML_H3] = abc_layout_h1, + [ABC_HTML_H4] = abc_layout_h1, + [ABC_HTML_H5] = abc_layout_h1, + [ABC_HTML_H6] = abc_layout_h1, + + [ABC_HTML_P] = abc_layout_h1, + [ABC_HTML_BR] = abc_layout_h1, + + [ABC_HTML_A] = abc_layout_a, + [ABC_HTML_IMG] = abc_layout_img, + + [ABC_HTML_FORM] = abc_layout_form, + [ABC_HTML_LABEL] = abc_layout_label, + [ABC_HTML_INPUT] = abc_layout_input, }; int abc_layout_obj(abc_layout_t* layout, abc_obj_t* obj, int width, int height) @@ -114,7 +117,7 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height) }; if (child->key) - scf_logi("key: %s, x: %d, y: %d, w: %d, h: %d\n\n", child->key->data, child->x, child->y, child->w, child->h); + scf_logd("key: %s, x: %d, y: %d, w: %d, h: %d\n\n", child->key->data, child->x, child->y, child->w, child->h); if (__w < child->x + child->w) __w = child->x + child->w; @@ -134,7 +137,7 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height) root->h = __h; if (root->key) - scf_logi("key: %s, x: %d, y: %d, w: %d, h: %d\n", root->key->data, root->x, root->y, root->w, root->h); + scf_logd("key: %s, x: %d, y: %d, w: %d, h: %d\n", root->key->data, root->x, root->y, root->w, root->h); return 0; } diff --git a/ui/abc_layout_form.c b/ui/abc_layout_form.c new file mode 100644 index 0000000..9b7d25f --- /dev/null +++ b/ui/abc_layout_form.c @@ -0,0 +1,43 @@ +#include"abc.h" + +int abc_layout_form(abc_layout_t* layout, abc_obj_t* obj, int width, int height) +{ + abc_obj_t* attr; + cairo_text_extents_t extents; + cairo_surface_t* surface; + cairo_t* cr; + + if (!obj->text) + return 0; + + surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + cr = cairo_create(surface); + + attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT); + if (attr) + cairo_select_font_face(cr, attr->value->data, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + + attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE); + if (attr) + cairo_set_font_size(cr, atoi(attr->value->data)); + + cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); + cairo_text_extents(cr, obj->text->data, &extents); + + obj->x = 4; + obj->y = 4; + obj->w = extents.width + extents.x_bearing; + obj->h = extents.height + extents.height / 2; + + obj->w = (obj->w + 3) & ~0x3; + obj->h = (obj->h + 3) & ~0x3; + + scf_logi("%s, w: %d, h: %d, x_bearing: %lg, y_bearing: %lg, width: %lg, height: %lg, x_advance: %lg, y_advance: %lg\n", + obj->text->data, obj->w, obj->h, + extents.x_bearing, extents.y_bearing, extents.width, extents.height, + extents.x_advance, extents.y_advance); + + cairo_destroy(cr); + cairo_surface_destroy(surface); + return 0; +} diff --git a/ui/abc_layout_input.c b/ui/abc_layout_input.c new file mode 100644 index 0000000..b08bdfe --- /dev/null +++ b/ui/abc_layout_input.c @@ -0,0 +1,54 @@ +#include"abc.h" + +int abc_layout_input(abc_layout_t* layout, abc_obj_t* obj, int width, int height) +{ + abc_obj_t* attr; + cairo_text_extents_t extents; + cairo_surface_t* surface; + cairo_t* cr; + + char* text = "Hello HTML INPUT"; + + attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_TYPE); + + if (!strcmp(attr->value->data, "submit")) { + + attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_VALUE); + + if (attr && attr->value && attr->value->len > 0) + text = attr->value->data; + else + text = "submit"; + } + + surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + cr = cairo_create(surface); + + attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT); + if (attr) + cairo_select_font_face(cr, attr->value->data, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + + attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE); + if (attr) + cairo_set_font_size(cr, atoi(attr->value->data)); + + cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); + cairo_text_extents(cr, text, &extents); + + obj->x = 4; + obj->y = 4; + obj->w = extents.width + extents.x_bearing; + obj->h = extents.height; + + obj->w = ((obj->w + 3) & ~0x3) + 8; + obj->h = ((obj->h + 3) & ~0x3) + 8; + + scf_logd("%s, w: %d, h: %d, x_bearing: %lg, y_bearing: %lg, width: %lg, height: %lg, x_advance: %lg, y_advance: %lg\n", + text, obj->w, obj->h, + extents.x_bearing, extents.y_bearing, extents.width, extents.height, + extents.x_advance, extents.y_advance); + + cairo_destroy(cr); + cairo_surface_destroy(surface); + return 0; +} diff --git a/ui/abc_layout_label.c b/ui/abc_layout_label.c new file mode 100644 index 0000000..7a7aa83 --- /dev/null +++ b/ui/abc_layout_label.c @@ -0,0 +1,43 @@ +#include"abc.h" + +int abc_layout_label(abc_layout_t* layout, abc_obj_t* obj, int width, int height) +{ + abc_obj_t* attr; + cairo_text_extents_t extents; + cairo_surface_t* surface; + cairo_t* cr; + + if (!obj->text) + return 0; + + surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + cr = cairo_create(surface); + + attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT); + if (attr) + cairo_select_font_face(cr, attr->value->data, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + + attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE); + if (attr) + cairo_set_font_size(cr, atoi(attr->value->data)); + + cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); + cairo_text_extents(cr, obj->text->data, &extents); + + obj->x = 4; + obj->y = 4; + obj->w = extents.width + extents.x_bearing; + obj->h = extents.height; + + obj->w = ((obj->w + 3) & ~0x3) + 4; + obj->h = ((obj->h + 3) & ~0x3) + 4; + + scf_logd("%s, w: %d, h: %d, x_bearing: %lg, y_bearing: %lg, width: %lg, height: %lg, x_advance: %lg, y_advance: %lg\n", + obj->text->data, obj->w, obj->h, + extents.x_bearing, extents.y_bearing, extents.width, extents.height, + extents.x_advance, extents.y_advance); + + cairo_destroy(cr); + cairo_surface_destroy(surface); + return 0; +} diff --git a/ui/abc_render.c b/ui/abc_render.c index 06c2d27..0b7960d 100644 --- a/ui/abc_render.c +++ b/ui/abc_render.c @@ -12,30 +12,35 @@ extern abc_render_t abc_render_a; extern abc_render_t abc_render_a_href; extern abc_render_t abc_render_img; +extern abc_render_t abc_render_form; +extern abc_render_t abc_render_label; +extern abc_render_t abc_render_input; + static abc_render_t* abc_renders[ABC_HTML_NB] = { - &abc_render_html, - &abc_render_title, - &abc_render_head, - &abc_render_body, - - // 4 - &abc_render_div, - - &abc_render_h1, - &abc_render_h1, - &abc_render_h1, - &abc_render_h1, - &abc_render_h1, - &abc_render_h1, - - // 11 - &abc_render_h1, //

- &abc_render_h1, //
- &abc_render_a, - &abc_render_a_href, - - &abc_render_img, + [ABC_HTML] = &abc_render_html, + [ABC_HTML_TITLE] = &abc_render_title, + [ABC_HTML_HEAD] = &abc_render_head, + [ABC_HTML_BODY] = &abc_render_body, + [ABC_HTML_DIV] = &abc_render_div, + + [ABC_HTML_H1] = &abc_render_h1, + [ABC_HTML_H2] = &abc_render_h1, + [ABC_HTML_H3] = &abc_render_h1, + [ABC_HTML_H4] = &abc_render_h1, + [ABC_HTML_H5] = &abc_render_h1, + [ABC_HTML_H6] = &abc_render_h1, + + [ABC_HTML_P] = &abc_render_h1, + [ABC_HTML_BR] = &abc_render_h1, + + [ABC_HTML_A] = &abc_render_a, + [ABC_HTML_A_HREF] = &abc_render_a_href, + [ABC_HTML_IMG] = &abc_render_img, + + [ABC_HTML_FORM] = &abc_render_form, + [ABC_HTML_LABEL] = &abc_render_label, + [ABC_HTML_INPUT] = &abc_render_input, }; int abc_renders_fini() @@ -113,7 +118,7 @@ int abc_render_root(abc_ctx_t* ctx, abc_obj_t* root, int width, int height) } } - scf_logi("-----------------\n\n"); + scf_logd("-----------------\n\n"); return 0; } diff --git a/ui/abc_render_form.c b/ui/abc_render_form.c new file mode 100644 index 0000000..34ccda5 --- /dev/null +++ b/ui/abc_render_form.c @@ -0,0 +1,147 @@ +#include"abc.h" + +static const char* vert_shader = + "#version 330 core\n" + "layout(location = 0) in vec4 position; \n" + "layout(location = 1) in vec2 a_texCoord; \n" + "out vec2 v_texCoord; \n" + "uniform mat4 mvp; \n" + "void main() { \n" + "gl_Position = mvp * position; \n" + "v_texCoord = a_texCoord; \n" + "} \n"; + +static const char* frag_shader = + "#version 330 core\n" + "in vec2 v_texCoord; \n" + "out vec4 outputColor; \n" + "uniform sampler2D tex_rgba; \n" + "void main() { \n" + " vec2 xy = v_texCoord; \n" + " vec4 v = texture2D(tex_rgba, xy).rgba; \n" + " outputColor = vec4(v.b, v.g, v.r, 1.0); \n" + "} \n"; + + +static GLuint program = 0; + +static GLuint vao = 0; +static GLuint buffers[2] = {0}; +static GLuint texture_rgba = 0; + +static GLuint uniform_mvp; +static GLuint uniform_rgba; + + +static int _render_fini_form(abc_render_t* render) +{ + return 0; +} + +static int _render_draw_form(abc_render_t* render, abc_obj_t* obj, int width, int height) +{ + if (!obj->text) + return 0; + + if (0 == program) + __init_program(&program, vert_shader, frag_shader); + + if (0 == vao) + __init_buffers(&vao, buffers); + + if (0 == texture_rgba) + __init_texture(&texture_rgba, GL_RGBA, obj->w, obj->h, NULL); + + abc_obj_t* attr; + cairo_text_extents_t extents; + cairo_surface_t* surface; + cairo_t* cr; + + uint8_t* bgra = calloc(1, obj->w * obj->h * 4); + if (!bgra) + return -ENOMEM; + + surface = cairo_image_surface_create_for_data(bgra, CAIRO_FORMAT_ARGB32, obj->w, obj->h, obj->w * 4); + cr = cairo_create(surface); + + cairo_set_line_width(cr, 1); + cairo_set_source_rgb(cr, 1, 1, 1); + cairo_rectangle(cr, 0, 0, obj->w, obj->h); + cairo_fill(cr); + cairo_stroke(cr); + + attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT); + if (attr) + cairo_select_font_face(cr, attr->value->data, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + + attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE); + if (attr) + cairo_set_font_size(cr, atoi(attr->value->data)); + + cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); + cairo_text_extents(cr, obj->text->data, &extents); + + cairo_move_to (cr, extents.x_bearing, -extents.y_bearing); + cairo_show_text(cr, obj->text->data); + +// cairo_surface_write_to_png(surface, "tmp.png"); + + cairo_destroy(cr); + cairo_surface_destroy(surface); + surface = NULL; + cr = NULL; + + float mvp[16]; + __compute_mvp(mvp, 0, 0, 0); + + scf_logi("%s, x: %d, y: %d, w: %d, h: %d\n", obj->text->data, obj->x, obj->y, obj->w, obj->h); + + GLfloat vert_update[] = + { + 2.0 * obj->x / (float)width - 1.0, + -2.0 * (obj->y + obj->h) / (float)height + 1.0, + + 2.0 * (obj->x + obj->w) / (float)width - 1.0, + -2.0 * (obj->y + obj->h) / (float)height + 1.0, + + 2.0 * obj->x / (float)width - 1.0, + -2.0 * obj->y / (float)height + 1.0, + + 2.0 * (obj->x + obj->w) / (float)width - 1.0, + -2.0 * obj->y / (float)height + 1.0, + }; + + glUseProgram(program); + uniform_rgba = glGetUniformLocation(program, "tex_rgba"); + uniform_mvp = glGetUniformLocation(program, "mvp"); + + glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, mvp); + + // board + glActiveTexture(GL_TEXTURE0); + glBindTexture (GL_TEXTURE_2D, texture_rgba); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, obj->w, obj->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, bgra); + glUniform1i(uniform_rgba, 0); + + // draw + glBindBuffer (GL_ARRAY_BUFFER, buffers[0]); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vert_update), vert_update); + + glBindVertexArray(vao); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + glBindVertexArray(0); + glUseProgram(0); + + free(bgra); + return 0; +} + +abc_render_t abc_render_form = +{ + .type = ABC_HTML_FORM, + + .draw = _render_draw_form, + .fini = _render_fini_form, +}; diff --git a/ui/abc_render_h1.c b/ui/abc_render_h1.c index f954d88..3503137 100644 --- a/ui/abc_render_h1.c +++ b/ui/abc_render_h1.c @@ -1,6 +1,6 @@ #include"abc.h" -const char* vert_shader = +static const char* vert_shader = "#version 330 core\n" "layout(location = 0) in vec4 position; \n" "layout(location = 1) in vec2 a_texCoord; \n" @@ -11,7 +11,7 @@ const char* vert_shader = "v_texCoord = a_texCoord; \n" "} \n"; -const char* frag_shader = +static const char* frag_shader = "#version 330 core\n" "in vec2 v_texCoord; \n" "out vec4 outputColor; \n" diff --git a/ui/abc_render_input.c b/ui/abc_render_input.c new file mode 100644 index 0000000..8c7ebe0 --- /dev/null +++ b/ui/abc_render_input.c @@ -0,0 +1,185 @@ +#include"abc.h" + +static const char* vert_shader = + "#version 330 core\n" + "layout(location = 0) in vec4 position; \n" + "layout(location = 1) in vec2 a_texCoord; \n" + "out vec2 v_texCoord; \n" + "uniform mat4 mvp; \n" + "void main() { \n" + "gl_Position = mvp * position; \n" + "v_texCoord = a_texCoord; \n" + "} \n"; + +static const char* frag_shader = + "#version 330 core\n" + "in vec2 v_texCoord; \n" + "out vec4 outputColor; \n" + "uniform sampler2D tex_rgba; \n" + "void main() { \n" + " vec2 xy = v_texCoord; \n" + " vec4 v = texture2D(tex_rgba, xy).rgba; \n" + " outputColor = vec4(v.b, v.g, v.r, 1.0); \n" + "} \n"; + + +static GLuint program = 0; + +static GLuint vao = 0; +static GLuint buffers[2] = {0}; +static GLuint texture_rgba = 0; + +static GLuint uniform_mvp; +static GLuint uniform_rgba; + + +static int _render_fini_input(abc_render_t* render) +{ + return 0; +} + +static int _render_draw_input(abc_render_t* render, abc_obj_t* obj, int width, int height) +{ + if (0 == program) + __init_program(&program, vert_shader, frag_shader); + + if (0 == vao) + __init_buffers(&vao, buffers); + + if (0 == texture_rgba) + __init_texture(&texture_rgba, GL_RGBA, obj->w, obj->h, NULL); + + abc_obj_t* type; + abc_obj_t* attr; + cairo_text_extents_t extents; + cairo_surface_t* surface; + cairo_t* cr; + + uint8_t* bgra = calloc(1, obj->w * obj->h * 4); + if (!bgra) + return -ENOMEM; + + surface = cairo_image_surface_create_for_data(bgra, CAIRO_FORMAT_ARGB32, obj->w, obj->h, obj->w * 4); + cr = cairo_create(surface); + + cairo_set_line_width(cr, 1); + cairo_set_source_rgb(cr, 1, 1, 1); + cairo_rectangle(cr, 0, 0, obj->w, obj->h); + cairo_fill(cr); + cairo_stroke(cr); + + cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); + cairo_set_line_width (cr, 2); + cairo_rectangle(cr, 2, 2, obj->w - 4, obj->h - 4); + cairo_stroke (cr); + + attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT); + if (attr) + cairo_select_font_face(cr, attr->value->data, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + + attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE); + if (attr) + cairo_set_font_size(cr, atoi(attr->value->data)); + + int x_cursor = 6; + + attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_VALUE); + type = abc_obj_find_attr(obj, ABC_HTML_ATTR_TYPE); + + if (attr && attr->value && attr->value->len > 0) { + + if (!strcmp(type->value->data, "password")) { + + char* passwd = strdup(attr->value->data); + if (!passwd) { + free(bgra); + return -ENOMEM; + } + + memset(passwd, '*', attr->value->len); + + cairo_text_extents(cr, passwd, &extents); + cairo_move_to (cr, extents.x_bearing + 4, -extents.y_bearing + (obj->h - extents.height) / 2); + cairo_show_text(cr, passwd); + + free(passwd); + passwd = NULL; + } else { + cairo_text_extents(cr, attr->value->data, &extents); + cairo_move_to (cr, extents.x_bearing + 4, -extents.y_bearing + (obj->h - extents.height) / 2); + cairo_show_text(cr, attr->value->data); + } + cairo_stroke(cr); + + x_cursor = 6 + extents.x_bearing + extents.width; + } + + if (obj->clicked && obj->jiffies % 72 < 36) { + cairo_set_line_width (cr, 1); + + cairo_move_to(cr, x_cursor, 4); + cairo_line_to(cr, x_cursor, obj->h - 4); + cairo_stroke (cr); + } + + cairo_surface_write_to_png(surface, "tmp.png"); + + cairo_destroy(cr); + cairo_surface_destroy(surface); + surface = NULL; + cr = NULL; + + float mvp[16]; + __compute_mvp(mvp, 0, 0, 0); + + scf_logd("x: %d, y: %d, w: %d, h: %d\n", obj->x, obj->y, obj->w, obj->h); + + GLfloat vert_update[] = + { + 2.0 * obj->x / (float)width - 1.0, + -2.0 * (obj->y + obj->h) / (float)height + 1.0, + + 2.0 * (obj->x + obj->w) / (float)width - 1.0, + -2.0 * (obj->y + obj->h) / (float)height + 1.0, + + 2.0 * obj->x / (float)width - 1.0, + -2.0 * obj->y / (float)height + 1.0, + + 2.0 * (obj->x + obj->w) / (float)width - 1.0, + -2.0 * obj->y / (float)height + 1.0, + }; + + glUseProgram(program); + uniform_rgba = glGetUniformLocation(program, "tex_rgba"); + uniform_mvp = glGetUniformLocation(program, "mvp"); + + glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, mvp); + + // board + glActiveTexture(GL_TEXTURE0); + glBindTexture (GL_TEXTURE_2D, texture_rgba); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, obj->w, obj->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, bgra); + glUniform1i(uniform_rgba, 0); + + // draw + glBindBuffer (GL_ARRAY_BUFFER, buffers[0]); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vert_update), vert_update); + + glBindVertexArray(vao); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + glBindVertexArray(0); + glUseProgram(0); + + free(bgra); + return 0; +} + +abc_render_t abc_render_input = +{ + .type = ABC_HTML_INPUT, + + .draw = _render_draw_input, + .fini = _render_fini_input, +}; diff --git a/ui/abc_render_label.c b/ui/abc_render_label.c new file mode 100644 index 0000000..c006420 --- /dev/null +++ b/ui/abc_render_label.c @@ -0,0 +1,147 @@ +#include"abc.h" + +static const char* vert_shader = + "#version 330 core\n" + "layout(location = 0) in vec4 position; \n" + "layout(location = 1) in vec2 a_texCoord; \n" + "out vec2 v_texCoord; \n" + "uniform mat4 mvp; \n" + "void main() { \n" + "gl_Position = mvp * position; \n" + "v_texCoord = a_texCoord; \n" + "} \n"; + +static const char* frag_shader = + "#version 330 core\n" + "in vec2 v_texCoord; \n" + "out vec4 outputColor; \n" + "uniform sampler2D tex_rgba; \n" + "void main() { \n" + " vec2 xy = v_texCoord; \n" + " vec4 v = texture2D(tex_rgba, xy).rgba; \n" + " outputColor = vec4(v.b, v.g, v.r, 1.0); \n" + "} \n"; + + +static GLuint program = 0; + +static GLuint vao = 0; +static GLuint buffers[2] = {0}; +static GLuint texture_rgba = 0; + +static GLuint uniform_mvp; +static GLuint uniform_rgba; + + +static int _render_fini_label(abc_render_t* render) +{ + return 0; +} + +static int _render_draw_label(abc_render_t* render, abc_obj_t* obj, int width, int height) +{ + if (!obj->text) + return 0; + + if (0 == program) + __init_program(&program, vert_shader, frag_shader); + + if (0 == vao) + __init_buffers(&vao, buffers); + + if (0 == texture_rgba) + __init_texture(&texture_rgba, GL_RGBA, obj->w, obj->h, NULL); + + abc_obj_t* attr; + cairo_text_extents_t extents; + cairo_surface_t* surface; + cairo_t* cr; + + uint8_t* bgra = calloc(1, obj->w * obj->h * 4); + if (!bgra) + return -ENOMEM; + + surface = cairo_image_surface_create_for_data(bgra, CAIRO_FORMAT_ARGB32, obj->w, obj->h, obj->w * 4); + cr = cairo_create(surface); + + cairo_set_line_width(cr, 1); + cairo_set_source_rgb(cr, 1, 1, 1); + cairo_rectangle(cr, 0, 0, obj->w, obj->h); + cairo_fill(cr); + cairo_stroke(cr); + + attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT); + if (attr) + cairo_select_font_face(cr, attr->value->data, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + + attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE); + if (attr) + cairo_set_font_size(cr, atoi(attr->value->data)); + + cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); + cairo_text_extents(cr, obj->text->data, &extents); + + cairo_move_to (cr, extents.x_bearing + 2, -extents.y_bearing + 2); + cairo_show_text(cr, obj->text->data); + +// cairo_surface_write_to_png(surface, "tmp.png"); + + cairo_destroy(cr); + cairo_surface_destroy(surface); + surface = NULL; + cr = NULL; + + float mvp[16]; + __compute_mvp(mvp, 0, 0, 0); + + scf_logd("%s, x: %d, y: %d, w: %d, h: %d\n", obj->text->data, obj->x, obj->y, obj->w, obj->h); + + GLfloat vert_update[] = + { + 2.0 * obj->x / (float)width - 1.0, + -2.0 * (obj->y + obj->h) / (float)height + 1.0, + + 2.0 * (obj->x + obj->w) / (float)width - 1.0, + -2.0 * (obj->y + obj->h) / (float)height + 1.0, + + 2.0 * obj->x / (float)width - 1.0, + -2.0 * obj->y / (float)height + 1.0, + + 2.0 * (obj->x + obj->w) / (float)width - 1.0, + -2.0 * obj->y / (float)height + 1.0, + }; + + glUseProgram(program); + uniform_rgba = glGetUniformLocation(program, "tex_rgba"); + uniform_mvp = glGetUniformLocation(program, "mvp"); + + glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, mvp); + + // board + glActiveTexture(GL_TEXTURE0); + glBindTexture (GL_TEXTURE_2D, texture_rgba); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, obj->w, obj->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, bgra); + glUniform1i(uniform_rgba, 0); + + // draw + glBindBuffer (GL_ARRAY_BUFFER, buffers[0]); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vert_update), vert_update); + + glBindVertexArray(vao); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + glBindVertexArray(0); + glUseProgram(0); + + free(bgra); + return 0; +} + +abc_render_t abc_render_label = +{ + .type = ABC_HTML_LABEL, + + .draw = _render_draw_label, + .fini = _render_fini_label, +}; diff --git a/ui/main.c b/ui/main.c index 04e445e..51d2397 100644 --- a/ui/main.c +++ b/ui/main.c @@ -7,23 +7,23 @@ static void resize(GtkGLArea* self, gint width, gint height, gpointer user_data) gtk_gl_area_make_current(self); if (gtk_gl_area_get_error(self) != NULL) { - printf("%s(),%d, error:\n", __func__, __LINE__); + scf_loge("\n"); return; } - printf("%s(),%d, width: %d, height: %d\n", __func__, __LINE__, width, height); + scf_logi("width: %d, height: %d\n", width, height); context = gtk_gl_area_get_context(self); if (gdk_gl_context_get_use_es(context)) - printf("%s(),%d, gles\n", __func__, __LINE__); + scf_logi("gles\n"); else - printf("%s(),%d, gl\n", __func__, __LINE__); + scf_logi("gl\n"); } static void unrealize(GtkWidget *widget) { - printf("%s(),%d\n", __func__, __LINE__); + scf_logi("\n"); } static gboolean render(GtkGLArea* self, GdkGLContext* context, gpointer user_data) @@ -60,6 +60,7 @@ static int __do_button_move(abc_ctx_t* ctx, int x, int y) abc_obj_t* prev = ctx->current->current; abc_obj_t* obj = abc_obj_find(ctx->current->root, x, y); + abc_obj_t* attr; int ret = 0; @@ -73,6 +74,7 @@ static int __do_button_move(abc_ctx_t* ctx, int x, int y) gdk_window_set_cursor(window, cursor); g_object_unref(cursor); + prev->clicked = 0; ret = 1; } @@ -80,7 +82,6 @@ static int __do_button_move(abc_ctx_t* ctx, int x, int y) scf_logd("obj: %s, x: %d, y: %d, w: %d, h: %d, event x: %d, y: %d\n", obj->key->data, obj->x, obj->y, obj->w, obj->h, x, y); - switch (obj->type) { case ABC_HTML_A: @@ -93,6 +94,22 @@ static int __do_button_move(abc_ctx_t* ctx, int x, int y) ret = 1; break; + + case ABC_HTML_INPUT: + attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_TYPE); + if (attr) { + if (!strcmp(attr->value->data, "text") || !strcmp(attr->value->data, "password")) { + + display = gtk_widget_get_display(GTK_WIDGET(ctx->gl_area)); + window = gtk_widget_get_window (GTK_WIDGET(ctx->gl_area)); + cursor = gdk_cursor_new_for_display(display, GDK_XTERM); + + gdk_window_set_cursor(window, cursor); + g_object_unref(cursor); + ret = 1; + } + } + break; default: break; }; @@ -103,56 +120,75 @@ static int __do_button_move(abc_ctx_t* ctx, int x, int y) return ret; } -static int __do_button_release(abc_ctx_t* ctx, int x, int y) +static int __do_button_release_a(abc_ctx_t* ctx, abc_obj_t* obj, int x, int y) { - abc_html_t* html; - abc_obj_t* attr; - abc_obj_t* obj = abc_obj_find(ctx->current->root, x, y); + abc_html_t* html = NULL; + abc_obj_t* attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_HREF); - if (!obj) - return -ENOMEM; + int ret = abc_html_open(&html, attr->value->data); + if (ret < 0) + return ret; - scf_logd("obj: %s, x: %d, y: %d, w: %d, h: %d, event x: %d, y: %d\n", - obj->key->data, obj->x, obj->y, obj->w, obj->h, x, y); + ret = abc_html_parse(html); + if (ret < 0) { + abc_html_close(html); + html = NULL; + return ret; + } - int ret = 0; + scf_list_add_tail(&ctx->html_list, &html->list); - if (ABC_HTML_A == obj->type) { + html->root->gtk_builder = ctx->builder; - html = NULL; - attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_HREF); + ctx->current = html; - ret = abc_html_open(&html, attr->value->data); - if (ret < 0) - return ret; + int width = gtk_widget_get_allocated_width (GTK_WIDGET(ctx->gl_area)); + int height = gtk_widget_get_allocated_height(GTK_WIDGET(ctx->gl_area)); - ret = abc_html_parse(html); - if (ret < 0) { - abc_html_close(html); - html = NULL; - return ret; - } + abc_layout_root(NULL, ctx->current->root, width, height); - scf_list_add_tail(&ctx->html_list, &html->list); + __do_button_move(ctx, x, y); - html->root->gtk_builder = ctx->builder; + gtk_widget_set_sensitive(GTK_WIDGET(ctx->back), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(ctx->forward), FALSE); - ctx->current = html; + return 1; +} - int width = gtk_widget_get_allocated_width (GTK_WIDGET(ctx->gl_area)); - int height = gtk_widget_get_allocated_height(GTK_WIDGET(ctx->gl_area)); +static int __do_button_release(abc_ctx_t* ctx, int x, int y) +{ + abc_obj_t* attr; + abc_obj_t* obj = abc_obj_find(ctx->current->root, x, y); + if (!obj) + return -ENOMEM; - abc_layout_root(NULL, ctx->current->root, width, height); + scf_logd("obj: %s, x: %d, y: %d, w: %d, h: %d, event x: %d, y: %d\n", + obj->key->data, obj->x, obj->y, obj->w, obj->h, x, y); - __do_button_move(ctx, x, y); + switch (obj->type) { - gtk_widget_set_sensitive(GTK_WIDGET(ctx->back), TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(ctx->forward), FALSE); + case ABC_HTML_A: + return __do_button_release_a(ctx, obj, x, y); + break; - ret = 1; - } + case ABC_HTML_INPUT: + obj->clicked = 1; + obj->jiffies = 0; - return ret; + attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_TYPE); + + if (!strcmp(attr->value->data, "submit")) { + abc_obj_print(ctx->current->root); + return 0; + } + + return __do_button_move(ctx, x, y); + break; + default: + break; + }; + + return 0; } static void back_clicked(GtkButton* self, gpointer user_data) @@ -244,6 +280,9 @@ static gboolean button_release_event(GtkWidget* self, GdkEventButton* event, gpo if (gtk_widget_get_window(GTK_WIDGET(ctx->gl_area)) == event->window) { + scf_logw("event x_root: %f, y_root: %f, x: %f, y: %f\n", + event->x_root, event->y_root, event->x, event->y); + int ret = __do_button_release(ctx, event->x, event->y); if (ret > 0) gtk_gl_area_queue_render(ctx->gl_area); @@ -252,6 +291,58 @@ static gboolean button_release_event(GtkWidget* self, GdkEventButton* event, gpo return TRUE; } +static void __utf8_delete(abc_ctx_t* ctx) +{ + abc_obj_t* obj; + abc_obj_t* attr; + + if (!ctx->current || !ctx->current->current) + return; + + obj = ctx->current->current; + if (ABC_HTML_INPUT != obj->type) + return; + + attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_TYPE); + + if (!strcmp(attr->value->data, "text") || !strcmp(attr->value->data, "password")) { + uint8_t c; + int i; + + attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_VALUE); + + for (i = attr->value->len - 1; i >= 0; i--) { + c = attr->value->data[i]; + + attr->value->data[--attr->value->len] = '\0'; + + if (c < 0x80) + break; + + if ((c >> 6) != 0x2) + break; + } + } +} + +static gboolean key_press_event(GtkWidget* self, GdkEventKey* event, gpointer user_data) +{ + abc_ctx_t* ctx = user_data; + + scf_logi("event keyval: %c, %d\n", event->keyval, event->keyval); + + switch (event->keyval) { + case GDK_KEY_BackSpace: + case GDK_KEY_Delete: + __utf8_delete(ctx); + break; + default: + break; + }; + + return gtk_im_context_filter_keypress(ctx->im, event); +} + static gboolean button_move_event(GtkWidget* self, GdkEventMotion* event, gpointer user_data) { abc_ctx_t* ctx = user_data; @@ -263,6 +354,67 @@ static gboolean button_move_event(GtkWidget* self, GdkEventMotion* event, gpoint return TRUE; } +static gboolean timer_handler(gpointer user_data) +{ + abc_ctx_t* ctx = user_data; + abc_obj_t* obj; + + if (ctx->current) { + obj = ctx->current->current; + + if (obj) { + obj->jiffies++; + gtk_gl_area_queue_render(ctx->gl_area); + } + } + + return TRUE; +} + +static void im_preedit_start(GtkIMContext* self, gpointer user_data) +{ +} + +static void im_preedit_end(GtkIMContext* self, gpointer user_data) +{ +} + +static void im_preedit_changed(GtkIMContext* self, gpointer user_data) +{ +} + +static gboolean im_retrieve_surrounding(GtkIMContext* self, gpointer user_data) +{ + return TRUE; +} + +static gboolean im_delete_surrounding(GtkIMContext* self, gint offset, gint n_chars, gpointer user_data) +{ + scf_logi("offset: %d, n_chars: %d\n", offset, n_chars); + return TRUE; +} + +static void im_commit(GtkIMContext* self, gchar* str, gpointer user_data) +{ + abc_ctx_t* ctx = user_data; + abc_obj_t* obj; + abc_obj_t* attr; + + scf_logw("str: %s\n", str); + + if (ctx->current) { + obj = ctx->current->current; + + if (obj && ABC_HTML_INPUT == obj->type) { + attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_VALUE); + + scf_string_cat_cstr(attr->value, str); + + gtk_gl_area_queue_render(ctx->gl_area); + } + } +} + int main(int argc, char *argv[]) { abc_ctx_t ctx = ABC_CTX_INIT(ctx); @@ -337,8 +489,27 @@ int main(int argc, char *argv[]) gtk_widget_add_events(GTK_WIDGET(gl_area), GDK_POINTER_MOTION_MASK); g_signal_connect(window, "button-release-event", G_CALLBACK(button_release_event), &ctx); + g_signal_connect(window, "key-press-event", G_CALLBACK(key_press_event), &ctx); g_signal_connect(gl_area, "motion-notify-event", G_CALLBACK(button_move_event), &ctx); + g_timeout_add(10, timer_handler, &ctx); + + ctx.im = gtk_im_multicontext_new(); + if (!ctx.im) { + scf_loge("\n"); + return -ENOMEM; + } + + gtk_im_context_set_client_window(ctx.im, gtk_widget_get_window(GTK_WIDGET(window))); + gtk_im_context_focus_in (ctx.im); + + g_signal_connect(ctx.im, "commit", G_CALLBACK(im_commit), &ctx); + g_signal_connect(ctx.im, "retrieve-surrounding", G_CALLBACK(im_preedit_changed), &ctx); + g_signal_connect(ctx.im, "delete-surrounding", G_CALLBACK(im_delete_surrounding), &ctx); + g_signal_connect(ctx.im, "preedit-changed", G_CALLBACK(im_preedit_changed), &ctx); + g_signal_connect(ctx.im, "preedit-start", G_CALLBACK(im_preedit_start), &ctx); + g_signal_connect(ctx.im, "preedit-end", G_CALLBACK(im_preedit_end), &ctx); + gtk_widget_show_all(GTK_WIDGET(window)); gtk_main();