From 99f950fbd56d014ff863f350269c5171e190e963 Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Sun, 20 Oct 2024 21:23:14 +0800 Subject: [PATCH] support HTML
+ + + 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();
--
2.25.1