From: yu.dongliang <18588496441@163.com> Date: Mon, 1 Jun 2026 12:07:58 +0000 (+0800) Subject: 1, css: support dynamic use, X-Git-Url: http://baseworks.info/?a=commitdiff_plain;ds=inline;p=abc.git 1, css: support dynamic use, 2, support opacity for simple image --- diff --git a/examples/img.png b/examples/img.png index 17f8bd1..a3a560b 100644 Binary files a/examples/img.png and b/examples/img.png differ diff --git a/examples/klematis.jpg b/examples/klematis.jpg new file mode 100644 index 0000000..b87e920 Binary files /dev/null and b/examples/klematis.jpg differ diff --git a/examples/klematis2.jpg b/examples/klematis2.jpg new file mode 100644 index 0000000..2f32901 Binary files /dev/null and b/examples/klematis2.jpg differ diff --git a/examples/opacity.html b/examples/opacity.html new file mode 100644 index 0000000..a2528cb --- /dev/null +++ b/examples/opacity.html @@ -0,0 +1,28 @@ + + +
+ +opacity 屿§éå¸¸ä¸ :hover éæ©å¨ä¸èµ·ä½¿ç¨ï¼å¨é¼ æ ç§»å¨å°å¾çä¸åæ¹åå¾ççéæåº¦ï¼
+
+
+
+注æ:å¨ IE ä¸å¿ 须声æ <!DOCTYPE> æè½ä¿è¯ :hover éæ©å¨è½å¤ææã
+ + diff --git a/examples/style.css b/examples/style.css index 23371ec..4416259 100644 --- a/examples/style.css +++ b/examples/style.css @@ -1,6 +1,7 @@ body { - background: #b0c4de url('img.png') repeat-x right ä¸ ; + background:#b0c4de url('img.png') repeat-x right top; + border: 2px solid red; } h1 {background-color:#6495ed;} diff --git a/html/abc_css.c b/html/abc_css.c index ed6793d..ddf0e17 100644 --- a/html/abc_css.c +++ b/html/abc_css.c @@ -4,24 +4,24 @@ int __html_add_attr (abc_obj_t* obj, int type, char** names, const html_label_t* __html_find_label (const char* name); html_label_t* __html_find_label2(const int type); -static int __css_drop_comment(abc_obj_t* css) +static int __css_drop_comment(abc_obj_t* style) { - abc_char_t* c = __io_pop_char(&css->io); + abc_char_t* c = __io_pop_char(&style->io); if (!c) return -EINVAL; if ('*' != c->c) { - __io_push_char(&css->io, c); + __io_push_char(&style->io, c); return 1; } - css->text_pos++; + style->text_pos++; free(c); c = NULL; int prev = 0; while (1) { - c = __io_pop_char(&css->io); + c = __io_pop_char(&style->io); if (!c) return -EINVAL; @@ -33,10 +33,10 @@ static int __css_drop_comment(abc_obj_t* css) return -EINVAL; if ('\n' == tmp) { - css->text_line++; - css->text_pos = 0; + style->text_line++; + style->text_pos = 0; } else { - css->text_pos++; + style->text_pos++; if ('*' == prev && '/' == tmp) break; @@ -55,20 +55,20 @@ static int __css_end_value(int c) return 0; } -static int __css_parse_str(abc_obj_t* css, scf_string_t* s, int (*end)(int c)) +static int __css_parse_str(abc_obj_t* style, scf_string_t* s, int (*end)(int c)) { abc_char_t* c = NULL; int c0 = ' '; while (1) { - c = __io_pop_char(&css->io); + c = __io_pop_char(&style->io); if (!c) return -EINVAL; - css->text_pos += c->len; + style->text_pos += c->len; if ('/' == c->c) { - int ret = __css_drop_comment(css); + int ret = __css_drop_comment(style); if (0 == ret) { free(c); continue; @@ -86,16 +86,15 @@ static int __css_parse_str(abc_obj_t* css, scf_string_t* s, int (*end)(int c)) int ret = 0; switch (c->c) { // drop more ' ' & add c to string case '\n': - css->text_line++; - css->text_pos = 0; + style->text_line++; + style->text_pos = 0; case '\t': case '\r': case ' ': if (' ' == c0 || '>' == c0 || '+' == c0 || '~' == c0 || ',' == c0 || ':' == c0 || '.' == c0 || '#' == c0 - || '[' == c0 || ']' == c0 - || '(' == c0 || ')' == c0) + || '[' == c0 || ']' == c0 || '(' == c0) break; ret = scf_string_cat_cstr_len(s, " ", 1); @@ -139,13 +138,13 @@ static int __css_parse_str(abc_obj_t* css, scf_string_t* s, int (*end)(int c)) return tmp; } -static int __css_parse_value(abc_obj_t* css, abc_attr_t* attr) +static int __css_parse_value(abc_obj_t* style, abc_attr_t* attr) { scf_string_t* value = scf_string_alloc(); if (!value) return -ENOMEM; - int tmp = __css_parse_str(css, value, __css_end_value); + int tmp = __css_parse_str(style, value, __css_end_value); switch (tmp) { case ';': @@ -171,13 +170,13 @@ static int __css_end_attr(int c) return 0; } -static int __css_parse_attr2(abc_obj_t* css, abc_obj_t* obj, const html_attr_t* attrs, int n_attrs) +static int __css_parse_attr2(abc_obj_t* style, css_rule_t* css, const html_attr_t* attrs, int n_attrs) { scf_string_t* key = scf_string_alloc(); if (!key) return -ENOMEM; - int tmp = __css_parse_str(css, key, __css_end_attr); + int tmp = __css_parse_str(style, key, __css_end_attr); switch (tmp) { case ':': @@ -194,45 +193,43 @@ static int __css_parse_attr2(abc_obj_t* css, abc_obj_t* obj, const html_attr_t* int i; int j; int k; - if (attrs && n_attrs > 0) { - for (i = 0; i < n_attrs; i++) { + for (i = 0; attrs && i < n_attrs; i++) { - for (j = 0; attrs[i].names[j]; j++) { - if (!__html_strcmp(attrs[i].names[j], key->data)) - goto found; - } + for (j = 0; attrs[i].names[j]; j++) { + if (!__html_strcmp(attrs[i].names[j], key->data)) + goto found; } } - scf_loge("invalid HTML attribute '%s' in file: %s, line: %d\n", key->data, css->file->data, css->text_pos); + scf_loge("invalid HTML attribute '%s' in file: %s, line: %d\n", key->data, style->file->data, style->text_pos); scf_string_free(key); return -EINVAL; found: k = attrs[i].type; - assert(k >= ABC_HTML_ATTR_ID && k < ABC_HTML_CSS_NB); + assert(k >= ABC_CSS_CLASS && k < ABC_HTML_CSS_NB); - attr = obj->attrs[k - ABC_HTML_ATTR_ID]; + attr = css->attrs[k - ABC_CSS_CLASS]; if (!attr) { - int ret = __html_add_attr(obj, attrs[i].type, attrs[i].names, attrs[i].value, attrs[i].flags); + int ret = __html_add_attr((abc_obj_t*)css, attrs[i].type, attrs[i].names, attrs[i].value, attrs[i].flags); if (ret < 0) return ret; - attr = obj->attrs[k - ABC_HTML_ATTR_ID]; + attr = css->attrs[k - ABC_CSS_CLASS]; } scf_string_free(key); key = NULL; - return __css_parse_value(css, attr); + return __css_parse_value(style, attr); } -static int __css_parse_attr(abc_obj_t* css, abc_obj_t* obj, const html_attr_t* attrs, int n_attrs) +static int __css_parse_attr(abc_obj_t* style, css_rule_t* css, const html_attr_t* attrs, int n_attrs) { int ret = 0; while (1) { - ret = __css_parse_attr2(css, obj, attrs, n_attrs); + ret = __css_parse_attr2(style, css, attrs, n_attrs); if ('}' == ret || EOF == ret) break; @@ -244,125 +241,51 @@ static int __css_parse_attr(abc_obj_t* css, abc_obj_t* obj, const html_attr_t* a return ret; } -static int __css_parse_comma(abc_obj_t* css, abc_obj_t* obj) +static int __css_parse_type(css_rule_t* css) { - html_label_t* label; - scf_list_t h; - - scf_list_init(&h); - int combinator = -1; - int id = 0; - int class = 0; - int attr = 0; + int id = -1; + int class = -1; + int attr = -1; int pseClass = -1; int pseElement = -1; int c; int i; + int j = -1; - int k = -1; + int k = css->text->len; - for (i = obj->text->len - 1; i >= 0; i--) { - c = obj->text->data[i]; + for (i = css->text->len - 1; i >= 0; i--) { + c = css->text->data[i]; assert('\t' != c); assert('\r' != c); assert('\n' != c); - - if (' ' == c) { - if (combinator < 0 && k >= 0) - combinator = i; - continue; - } - - if (',' == c) { - if (k < 0) - continue; - - assert(j >= 0); - - scf_string_t* key = scf_string_cstr_len(obj->text->data + j, k + 1 - j); - if (!key) { - scf_list_clear(&h, abc_obj_t, list, abc_obj_free); - return -ENOMEM; - } - - if (id > 0) - label = __html_find_label2(ABC_CSS_ID); - else if (class > 0) - label = __html_find_label2(ABC_CSS_CLASS); - else if (attr > 0) - label = __html_find_label2(ABC_CSS_ATTR); - - else if (pseClass > 0) - label = __html_find_label2(ABC_CSS_PSE_CLASS); - else if (pseElement > 0) - label = __html_find_label2(ABC_CSS_PSE_ELEMENT); - - else if (j < combinator && combinator < k) - label = __html_find_label2(ABC_CSS_COMBINATOR); - else { - label = __html_find_label(key->data); - if (!label) { - scf_loge("css selector '%s' invalid, file: %s, line: %d, pos: %d\n", key->data, obj->file->data, obj->line, j); - - scf_string_free(key); - scf_list_clear(&h, abc_obj_t, list, abc_obj_free); - return -EINVAL; - } - } - - abc_obj_t* rule = abc_obj_alloc(obj->file, obj->line, j, label->type); - if (!rule) { - scf_string_free(key); - scf_list_clear(&h, abc_obj_t, list, abc_obj_free); - return -ENOMEM; - } - - rule->flags = label->flags; - rule->keys = label->names; - rule->parent = css; - - if (rule->type < ABC_HTML_NB) - scf_string_free(key); - else - rule->text = key; - key = NULL; - - int ret = abc_obj_copy_attrs(rule, obj); - if (ret < 0) { - abc_obj_free(rule); - scf_list_clear(&h, abc_obj_t, list, abc_obj_free); - return ret; - } - - scf_list_add_front(&h, &rule->list); - - combinator = -1; - id = 0; - class = 0; - attr = 0; - pseClass = -1; - pseElement = -1; - - j = -1; - k = -1; - continue; - } - - j = i; - if (k < 0) - k = i; + assert (',' != c); switch (c) { case '#': - id++; + if (id < 0) + id = i; + + if (j < 0) + j = i; break; + case '.': - class++; + if (class < 0) + class = i; + + if (j < 0) + j = i; break; + case '[': - attr++; + if (attr < 0) + attr = i; + + if (j < 0) + j = i; break; case ':': @@ -372,140 +295,177 @@ static int __css_parse_comma(abc_obj_t* css, abc_obj_t* obj) pseElement = i; pseClass = -1; } + + if (j < 0) + k = i; break; + case ' ': case '>': case '+': case '~': if (combinator < 0) combinator = i; + + if (j < 0) + j = i; break; default: break; }; } - if (k >= 0) { - assert(k < obj->text->len); - - obj->text->data[k + 1] = '\0'; - obj->text->len = k + 1; - - if (id > 0) - label = __html_find_label2(ABC_CSS_ID); - else if (class > 0) - label = __html_find_label2(ABC_CSS_CLASS); - else if (attr > 0) - label = __html_find_label2(ABC_CSS_ATTR); - - else if (pseClass > 0) - label = __html_find_label2(ABC_CSS_PSE_CLASS); - else if (pseElement > 0) - label = __html_find_label2(ABC_CSS_PSE_ELEMENT); - - else if (0 < combinator && combinator < k) - label = __html_find_label2(ABC_CSS_COMBINATOR); - else { - label = __html_find_label(obj->text->data); - if (!label) { - scf_loge("css selector '%s' invalid, file: %s, line: %d, pos: %d\n", obj->text->data, obj->file->data, obj->line, k); - - scf_list_clear(&h, abc_obj_t, list, abc_obj_free); - return -EINVAL; - } - } + html_label_t* label; - obj->type = label->type; - obj->flags = label->flags; - obj->keys = label->names; - obj->parent = css; + if (id >= 0) + label = __html_find_label2(ABC_CSS_ID); - if (obj->type < ABC_HTML_NB) { - scf_string_free(obj->text); - obj->text = NULL; - } + else if (class >= 0) + label = __html_find_label2(ABC_CSS_CLASS); - scf_list_add_front(&h, &obj->list); + else if (attr >= 0) + label = __html_find_label2(ABC_CSS_ATTR); - scf_list_mov2(&css->childs, &h); - return 0; + else if (pseClass >= 0) + label = __html_find_label2(ABC_CSS_PSE_CLASS); + + else if (pseElement >= 0) + label = __html_find_label2(ABC_CSS_PSE_ELEMENT); + + else if (combinator >= 0) + label = __html_find_label2(ABC_CSS_COMBINATOR); + else { + label = __html_find_label(css->text->data); + if (!label) { + scf_loge("css selector '%s' invalid, file: %s, line: %d\n", css->text->data, css->file->data, css->line); + return -EINVAL; + } + + scf_string_free(css->text); + css->text = NULL; } - scf_list_clear(&h, abc_obj_t, list, abc_obj_free); - return -EINVAL; + css->type = label->type; + css->keys = label->names; + css->flags = label->flags; + + if (css->text) { + css->last_key = j < 0 ? 0 : j; + css->last_key_end = k; + + scf_logi("css selector '%s', last key: %.*s\n", css->text->data, + (int)(css->last_key_end - css->last_key), + css->text->data + css->last_key); + } + return 0; } static int __css_end_obj(int c) { - if ('{' == c || EOF == c) + if (',' == c || '{' == c || EOF == c) return 1; return 0; } -static int __css_parse_obj(abc_obj_t* css, abc_char_t* c) +static int __css_parse_selectors(abc_obj_t* style, scf_string_t* key, html_label_t* label, scf_list_t* h) +{ + int tmp = EOF; + do { + if (!key) { + key = scf_string_alloc(); + if (!key) + return -ENOMEM; + } + + tmp = __css_parse_str(style, key, __css_end_obj); + if (EOF == tmp) + break; + + if (key->len > 0) { + css_rule_t* css = css_rule_alloc(style->file, style->text_line, style->text_pos, label->type); + if (!css) { + scf_string_free(key); + return -ENOMEM; + } + + css->flags = label->flags; + css->keys = label->names; + css->parent = style; + + css->text = key; + key = NULL; + + scf_list_add_tail(h, &css->list); + } + } while ('{' != tmp); + + if (key) + scf_string_free(key); + + return tmp; +} + +static int __css_parse_obj(abc_obj_t* style, abc_char_t* c) { html_label_t* label; - abc_obj_t* obj; scf_string_t* key = scf_string_cstr_len(c->utf8, c->len); - css->text_pos += c->len; + style->text_pos += c->len; free(c); c = NULL; if (!key) return -ENOMEM; - int tmp = __css_parse_str(css, key, __css_end_obj); - switch (tmp) { - case '{': - break; - default: - scf_string_free(key); - return -EINVAL; - break; - }; - label = __html_find_label2(ABC_CSS_COMBINATOR); if (!label) { - scf_loge("invalid HTML label '%s' in file: %s, line: %d\n", key->data, css->file->data, css->text_line); + scf_loge("invalid HTML label '%s' in file: %s, line: %d\n", key->data, style->file->data, style->text_line); scf_string_free(key); return -EINVAL; } - obj = abc_obj_alloc(css->file, css->text_line, css->text_pos, label->type); - if (!obj) { - scf_string_free(key); - return -ENOMEM; - } - - obj->flags = label->flags; - obj->keys = label->names; - obj->parent = css; + scf_list_t h; + scf_list_t* l; + css_rule_t* css; + css_rule_t* src; - obj->text = key; - key = NULL; + scf_list_init(&h); - int ret; - switch (tmp) { - case '{': - ret = __css_parse_attr(css, obj, label->attrs, label->n_attrs); - if (ret < 0) { - abc_obj_free(obj); - return ret; - } - break; - default: - break; + int ret = __css_parse_selectors(style, key, label, &h); + if ('{' != ret) { + ret = -EINVAL; + goto error; }; - ret = __css_parse_comma(css, obj); - if (ret < 0) - abc_obj_free(obj); + if (scf_list_empty(&h)) + return 0; + + src = NULL; + for (l = scf_list_head(&h); l != scf_list_sentinel(&h); l = scf_list_next(l)) { + css = scf_list_data(l, css_rule_t, list); + + if (!src) { + src = css; + ret = __css_parse_attr(style, css, label->attrs, label->n_attrs); + } else + ret = abc_css_copy_attrs(css, src); + if (ret < 0) + goto error; + ret = __css_parse_type(css); + if (ret < 0) + goto error; + } + + scf_list_mov2(&style->css, &h); + return 0; + +error: + scf_list_clear(&h, css_rule_t, list, css_rule_free); return ret; } -int abc_css_parse(abc_obj_t* css) +int abc_css_parse(abc_obj_t* style) { scf_string_t* spath = NULL; abc_char_t* c; @@ -515,23 +475,23 @@ int abc_css_parse(abc_obj_t* css) char* path; int n; - switch (css->type) + switch (style->type) { case ABC_HTML_STYLE: - if (!css->text) + if (!style->text) return 0; n = 0; io = abc_io_array[ABC_PROTO_STR]; - path = css->text->data; + path = style->text->data; break; case ABC_HTML_LINK: - href = abc_obj_get_attr(css, ABC_HTML_ATTR_HREF); + href = abc_obj_get_attr(style, ABC_HTML_ATTR_HREF); if (!href) return 0; - n = __io_url_path(&io, &spath, css->file->data, href->value->data, href->value->len); + n = __io_url_path(&io, &spath, style->file->data, href->value->data, href->value->len); if (n < 0) return n; @@ -542,19 +502,19 @@ int abc_css_parse(abc_obj_t* css) break; }; - scf_logw("css->file: %s, path: %s\n", css->file->data, path); + scf_logw("style->file: %s, path: %s\n", style->file->data, path); - css->io.proto = io->proto; - css->io.priv = NULL; - css->io.open = io->open; - css->io.close = io->close; - css->io.popc = io->popc; - css->io.post = io->post; + style->io.proto = io->proto; + style->io.priv = NULL; + style->io.open = io->open; + style->io.close = io->close; + style->io.popc = io->popc; + style->io.post = io->post; - css->text_line = 1; - css->text_pos = 0; + style->text_line = 1; + style->text_pos = 0; - int ret = io->open(&css->io, path + n); + int ret = io->open(&style->io, path + n); if (spath) { scf_string_free(spath); spath = NULL; @@ -563,7 +523,7 @@ int abc_css_parse(abc_obj_t* css) return ret; while (1) { - c = __io_pop_char(&css->io); + c = __io_pop_char(&style->io); if (!c) { ret = -1; break; @@ -576,20 +536,20 @@ int abc_css_parse(abc_obj_t* css) } if ('\n' == c->c) { - css->text_line++; - css->text_pos = 0; + style->text_line++; + style->text_pos = 0; free(c); continue; } if (' ' == c->c || '\t' == c->c || '\r' == c->c) { - css->text_pos++; + style->text_pos++; free(c); continue; } if ('/' == c->c) { - ret = __css_drop_comment(css); + ret = __css_drop_comment(style); if (0 == ret) { free(c); continue; @@ -603,20 +563,20 @@ int abc_css_parse(abc_obj_t* css) || '.' == c->c || '[' == c->c) { - ret = __css_parse_obj(css, c); + ret = __css_parse_obj(style, c); if (ret < 0) { - scf_loge("css->text_line: %d, css->text_pos: %d\n", css->text_line, css->text_pos); + scf_loge("style->text_line: %d, style->text_pos: %d\n", style->text_line, style->text_pos); break; } } else { - scf_loge("'%c'(%#x), css->text_line: %d, css->text_pos: %d\n", c->c, c->c, css->text_line, css->text_pos); + scf_loge("'%c'(%#x), style->text_line: %d, style->text_pos: %d\n", c->c, c->c, style->text_line, style->text_pos); free(c); ret = -1; break; } } - io->close(&css->io); + io->close(&style->io); return ret; } @@ -822,161 +782,6 @@ static void __css_set_attr(abc_obj_t* obj, abc_attr_t* attr) }; } -static int __css_set_pse_dynamic(abc_obj_t* obj, abc_obj_t* pse) -{ - scf_list_t* l; - abc_obj_t* pse2; - - for (l = scf_list_head(&obj->css_pse_rules); l != scf_list_sentinel(&obj->css_pse_rules); l = scf_list_next(l)) { - pse2 = scf_list_data(l, abc_obj_t, list); - - if (pse2->type == pse->type - && pse2->text->len == pse->text->len - && !__html_strcmp(pse2->text->data, pse->text->data)) - break; - } - - if (l == scf_list_sentinel(&obj->css_pse_rules)) - { - pse2 = abc_obj_alloc(pse->file, pse->line, pse->pos, pse->type); - if (!pse2) - return -ENOMEM; - - pse2->text = scf_string_clone(pse->text); - if (!pse2->text) { - abc_obj_free(pse2); - return -ENOMEM; - } - - pse2->flags = pse->flags; - pse2->keys = pse->keys; - - scf_list_add_tail(&obj->css_pse_rules, &pse2->list); - } - - int ret = abc_obj_copy_attrs(pse2, pse); - if (ret < 0) - return ret; - - switch (pse->css_pse_type) { - case ABC_CSS_LINK: - abc_obj_set_css(obj, pse); - break; - default: - break; - }; - - scf_slist_clear(pse2->css_pse_chain, pse_link_t, next, free); - - pse2->css_pse_chain = pse->css_pse_chain; - pse ->css_pse_chain = NULL; -} - -static void __css_merge(abc_obj_t* dst, abc_obj_t* src) -{ - abc_attr_t* s; - abc_attr_t* d; - int i; - - for (i = 0; i < sizeof(src->attrs) / sizeof(src->attrs[0]); i++) { - s = src->attrs[i]; - - if (!s || !s->value || 0 == s->value->len) - continue; - - d = dst->attrs[i]; - if (d) - SCF_XCHG(d->value, s->value); - else { - dst->attrs[i] = s; - src->attrs[i] = NULL; - } - } -} - -int abc_css_merge(abc_html_t* html, abc_obj_t* css) -{ - if (!html || !css) - return -EINVAL; - - if (!html->css) - html->css = css; - else - scf_list_mov2(&html->css->childs, &css->childs); - - scf_list_t* s; - scf_list_t* d; - abc_obj_t* src; // merge from - abc_obj_t* dst; // merge to - - for (s = scf_list_tail(&html->css->childs); s != scf_list_sentinel(&html->css->childs); ) { - src = scf_list_data(s, abc_obj_t, list); - s = scf_list_prev(s); - - for (d = s; d != scf_list_sentinel(&html->css->childs); d = scf_list_prev(d)) { - dst = scf_list_data(d, abc_obj_t, list); - - if (src->type == dst->type) { - if (src->type > ABC_HTML_NB && scf_string_cmp(src->text, dst->text)) - continue; - - __css_merge(dst, src); - - scf_list_del(&src->list); - abc_obj_free(src); - break; - } - } - } - - scf_list_t h_id; - scf_list_t h_class; - scf_list_t h_pse_class; - scf_list_t h_pse_element; - - scf_list_init(&h_id); - scf_list_init(&h_class); - scf_list_init(&h_pse_class); - scf_list_init(&h_pse_element); - - for (s = scf_list_head(&html->css->childs); s != scf_list_sentinel(&html->css->childs); ) { - src = scf_list_data(s, abc_obj_t, list); - s = scf_list_next(s); - - switch (src->type) { - case ABC_CSS_ID: - scf_list_del(&src->list); - scf_list_add_tail(&h_id, &src->list); - break; - - case ABC_CSS_CLASS: - case ABC_CSS_ATTR: - scf_list_del(&src->list); - scf_list_add_tail(&h_class, &src->list); - break; - - case ABC_CSS_PSE_CLASS: - scf_list_del(&src->list); - scf_list_add_tail(&h_pse_class, &src->list); - break; - - case ABC_CSS_PSE_ELEMENT: - scf_list_del(&src->list); - scf_list_add_tail(&h_pse_element, &src->list); - break; - default: - break; - }; - } - - // sort css priority, the last is the highest - scf_list_mov2(&html->css->childs, &h_pse_element); - scf_list_mov2(&html->css->childs, &h_pse_class); - scf_list_mov2(&html->css->childs, &h_class); - scf_list_mov2(&html->css->childs, &h_id); - return 0; -} - static abc_obj_t* __css_filter_pse(abc_obj_t* current, abc_attr_t* pse) { scf_list_t* l; @@ -997,6 +802,13 @@ static abc_obj_t* __css_filter_pse(abc_obj_t* current, abc_attr_t* pse) } break; + case ABC_CSS_VISITED: + case ABC_CSS_HOVER: + case ABC_CSS_ACTIVE: + + if (!(pse->flags & ABC_CSS_FLAG_ON)) + return NULL; + break; default: break; }; @@ -1004,12 +816,11 @@ static abc_obj_t* __css_filter_pse(abc_obj_t* current, abc_attr_t* pse) return current; } -static abc_obj_t* __css_select_by_key(abc_obj_t* css, abc_obj_t* current, scf_vector_t* vec, int next, const char* key, int len) +static abc_obj_t* __css_select_by_key(css_rule_t* css, abc_obj_t* current, scf_vector_t* vec, int next, const char* key, int len) { scf_list_t* l; abc_obj_t* tmp; abc_attr_t* pse; - pse_link_t* pseLink; assert(next >= 0 && next < vec->size); @@ -1082,24 +893,10 @@ static abc_obj_t* __css_select_by_key(abc_obj_t* css, abc_obj_t* current, scf_ve if (!pse) return NULL; - if (css->css_pse_type < pse->type) - css->css_pse_type = pse->type; - current = __css_filter_pse(current, pse); if (!current) return NULL; - pseLink = calloc(1, sizeof(pse_link_t)); - if (!pseLink) - return NULL; - - pseLink->obj = current; - pseLink->pse_type = pse->type; - pseLink->next = css->css_pse_chain; - - css->css_pse_chain = pseLink; - pseLink = NULL; - scf_logd("current: %s, key: %.*s, j: %d, k: %d, next: %.*s\n", current->keys[0], len, key, j, k, k - j, css->text->data + j); break; @@ -1112,13 +909,12 @@ static abc_obj_t* __css_select_by_key(abc_obj_t* css, abc_obj_t* current, scf_ve return current; } -static abc_obj_t* __css_select_by_id_class(abc_obj_t* css, abc_obj_t* current, scf_vector_t* vec, int next, int type, const char* value, int len) +static abc_obj_t* __css_select_by_id_class(css_rule_t* css, abc_obj_t* current, scf_vector_t* vec, int next, int type, const char* value, int len) { scf_list_t* l; abc_obj_t* tmp; abc_attr_t* attr; abc_attr_t* pse; - pse_link_t* pseLink; assert(next >= 0 && next < vec->size); @@ -1200,24 +996,10 @@ static abc_obj_t* __css_select_by_id_class(abc_obj_t* css, abc_obj_t* current, s if (!pse) return NULL; - if (css->css_pse_type < pse->type) - css->css_pse_type = pse->type; - current = __css_filter_pse(current, pse); if (!current) return NULL; - pseLink = calloc(1, sizeof(pse_link_t)); - if (!pseLink) - return NULL; - - pseLink->obj = current; - pseLink->pse_type = pse->type; - pseLink->next = css->css_pse_chain; - - css->css_pse_chain = pseLink; - pseLink = NULL; - scf_logd("current: %s, key: %.*s, j: %d, k: %d, next: %.*s\n", current->keys[0], len, value, j, k, k - j, css->text->data + j); break; @@ -1232,13 +1014,12 @@ static abc_obj_t* __css_select_by_id_class(abc_obj_t* css, abc_obj_t* current, s return current; } -static abc_obj_t* __css_select_by_attr(abc_obj_t* css, abc_obj_t* current, scf_vector_t* vec, int next, const char* key, int len) +static abc_obj_t* __css_select_by_attr(css_rule_t* css, abc_obj_t* current, scf_vector_t* vec, int next, const char* key, int len) { scf_list_t* l; abc_obj_t* tmp; abc_attr_t* attr; abc_attr_t* pse; - pse_link_t* pseLink; assert(next >= 0 && next < vec->size); @@ -1408,25 +1189,11 @@ static abc_obj_t* __css_select_by_attr(abc_obj_t* css, abc_obj_t* current, scf_v if (!pse) return NULL; - if (css->css_pse_type < pse->type) - css->css_pse_type = pse->type; - current = __css_filter_pse(current, pse); if (!current) return NULL; - pseLink = calloc(1, sizeof(pse_link_t)); - if (!pseLink) - return NULL; - - pseLink->obj = current; - pseLink->pse_type = pse->type; - pseLink->next = css->css_pse_chain; - - css->css_pse_chain = pseLink; - pseLink = NULL; - - scf_logd("current: %s, key: %.*s, m: %d, n: %d, next: %.*s\n", current->keys[0], len, key, m, n, + scf_logi("current: %s, key: %.*s, m: %d, n: %d, next: %.*s\n", current->keys[0], len, key, m, n, n - m, css->text->data + m); break; default: @@ -1445,7 +1212,7 @@ static abc_obj_t* __css_select_by_attr(abc_obj_t* css, abc_obj_t* current, scf_v return current; } -static int __css_use_complex(abc_obj_t* css, abc_obj_t* obj) +static int __css_use_complex(css_rule_t* css, abc_obj_t* obj) { scf_vector_t* vec; abc_obj_t* current = obj; @@ -1462,9 +1229,6 @@ static int __css_use_complex(abc_obj_t* css, abc_obj_t* obj) if (ret < 0) goto end; - css->css_pse_type = 0; - scf_slist_clear(css->css_pse_chain, pse_link_t, next, free); - int n_sqares = 0; for (i = css->text->len - 1; i >= 0; i--) { @@ -1539,8 +1303,8 @@ static int __css_use_complex(abc_obj_t* css, abc_obj_t* obj) if (i > 0 && ':' == css->text->data[i - 1]) { if (j < css->text->len) { - scf_loge("pse element must be the last for combinators '%s', file: %s, line: %d\n", - css->text->data, css->file->data, css->text_line); + scf_loge("pse element must be the last for combinators '%s', file: %s\n", + css->text->data, css->file->data); ret = 0; goto end; } @@ -1575,18 +1339,76 @@ static int __css_use_complex(abc_obj_t* css, abc_obj_t* obj) } } - if (css->css_pse_type < ABC_CSS_PSE_STATIC) - abc_obj_set_css(obj, css); - else - __css_set_pse_dynamic(obj, css); + abc_obj_set_css(obj, css); ret = 0; end: - scf_slist_clear(css->css_pse_chain, pse_link_t, next, free); scf_vector_free(vec); return ret; } +int css_hash_update_attrs(css_hash_t* h, css_rule_t* r) +{ + abc_attr_t* attr; + abc_attr_t* copy; + int i; + + for (i = 0; i < sizeof(r->attrs) / sizeof(r->attrs[0]); i++) { + attr = r->attrs[i]; + if (!attr) + continue; + + copy = calloc(1, sizeof(abc_attr_t)); + if (!copy) + return -ENOMEM; + + copy->value = scf_string_clone(attr->value); + if (!copy->value) { + abc_attr_free(copy); + return -ENOMEM; + } + + copy->type = attr->type; + copy->keys = attr->keys; + copy->flags = attr->flags; + + if (h->attrs[i]) + abc_attr_free(h->attrs[i]); + + h->attrs[i] = copy; + } + + return 0; +} + +int abc_css_merge(abc_html_t* html, abc_obj_t* obj) +{ + if (!html || !obj) + return -EINVAL; + + if (!html->css) { + html->css = abc_css_alloc(); + if (!html->css) + return -ENOMEM; + } + + scf_list_t* l; + css_rule_t* css; + css_hash_t* h; + + for (l = scf_list_head(&obj->css); l != scf_list_sentinel(&obj->css); l = scf_list_next(l)) { + css = scf_list_data(l, css_rule_t, list); + + h = &(html->css->hash[css->type]); + + scf_list_add_tail(&h->rules, &css->hash); + + css_hash_update_attrs(h, css); + } + + return 0; +} + int abc_css_use(abc_html_t* html, abc_obj_t* obj) { if (!html || !obj) @@ -1594,28 +1416,28 @@ int abc_css_use(abc_html_t* html, abc_obj_t* obj) scf_list_t* l; abc_attr_t* attr; - abc_obj_t* css; + css_rule_t* css; + int64_t tv0 = gettime(); if (html->css) { - for (l = scf_list_head(&html->css->childs); l != scf_list_sentinel(&html->css->childs); l = scf_list_next(l)) { - css = scf_list_data(l, abc_obj_t, list); + css_hash_t* h = &(html->css->hash[obj->type]); - switch (css->type) - { - case ABC_CSS_ID: - case ABC_CSS_CLASS: - case ABC_CSS_ATTR: - case ABC_CSS_PSE_CLASS: - case ABC_CSS_PSE_ELEMENT: - case ABC_CSS_COMBINATOR: - __css_use_complex(css, obj); - break; + int i; + for (i = 0; i < sizeof(h->attrs) / sizeof(h->attrs[0]); i++) { + attr = h->attrs[i]; + if (attr) + __css_set_attr(obj, attr); + } - default: - if (css->type == obj->type) - abc_obj_set_css(obj, css); - break; - }; + for (i = ABC_CSS_COMBINATOR; i < ABC_CSS_SELECTOR_NB; i++) + { + h = &(html->css->hash[i]); + + for (l = scf_list_head(&h->rules); l != scf_list_sentinel(&h->rules); l = scf_list_next(l)) { + css = scf_list_data(l, css_rule_t, hash); + + __css_use_complex(css, obj); + } } } @@ -1627,7 +1449,7 @@ int abc_css_use(abc_html_t* html, abc_obj_t* obj) html_label_t* label = __html_find_label2(obj->type); abc_io_t* io = abc_io_array[ABC_PROTO_STR]; - css = abc_obj_alloc(obj->file, obj->line, obj->pos, ABC_HTML_STYLE); + abc_obj_t* css = abc_obj_alloc(obj->file, obj->line, obj->pos, ABC_HTML_STYLE); if (!css) return -ENOMEM; @@ -1647,7 +1469,7 @@ int abc_css_use(abc_html_t* html, abc_obj_t* obj) return ret; } - ret = __css_parse_attr(css, css, label->attrs, label->n_attrs); + ret = __css_parse_attr(css, (css_rule_t*)css, label->attrs, label->n_attrs); io->close(&css->io); if (ret < 0 && EOF != ret) { abc_obj_free(css); @@ -1666,10 +1488,12 @@ int abc_css_use(abc_html_t* html, abc_obj_t* obj) abc_obj_free(css); } + int64_t tv1 = gettime(); + scf_logi("tv1 - tv0: %ld\n", tv1 - tv0); return 0; } -void abc_obj_set_css(abc_obj_t* obj, abc_obj_t* css) +void abc_obj_set_css(abc_obj_t* obj, css_rule_t* css) { abc_attr_t* attr; int i; @@ -1682,29 +1506,28 @@ void abc_obj_set_css(abc_obj_t* obj, abc_obj_t* css) } } -int abc_css_active(abc_obj_t* obj) +int abc_css_clear(abc_obj_t* obj, int pse_start, int pse_end) { - scf_list_t* l; - abc_obj_t* css; - pse_link_t* pseLink; - - int n = 0; - for (l = scf_list_head(&obj->css_pse_rules); l != scf_list_sentinel(&obj->css_pse_rules); l = scf_list_next(l)) { - css = scf_list_data(l, abc_obj_t, list); + abc_attr_t* attr; + int i; - pseLink = css->css_pse_chain; - while (pseLink) { - if (pseLink->obj->css_pse_type != pseLink->pse_type) - break; + for (i = pse_start; i <= pse_end; i++) + { + attr = abc_obj_get_attr(obj, i); + if (attr) + attr->flags &= ~ABC_CSS_FLAG_ON; + } - pseLink = pseLink->next; - } + return 0; +} - if (!pseLink) { - abc_obj_set_css(obj, css); - n++; - } +int abc_css_active(abc_obj_t* obj, int pse) +{ + abc_attr_t* attr = abc_obj_get_attr(obj, pse); + if (attr) { + attr->flags |= ABC_CSS_FLAG_ON; + return 1; } - return n; + return 0; } diff --git a/html/abc_css_border.c b/html/abc_css_border.c index a696d7f..fcde40d 100644 --- a/html/abc_css_border.c +++ b/html/abc_css_border.c @@ -33,11 +33,12 @@ static void __css_border_type(int* type, const char* name, size_t name_len) } } -int abc_css_border2(double border_color[3], int* border_width, int* border_style, abc_obj_t* obj, int width, const uint8_t* str) +int abc_css_border2(double border_color[4], int* border_width, int* border_style, abc_obj_t* obj, int width, const uint8_t* str) { border_color[0] = 0.0; border_color[1] = 0.0; border_color[2] = 0.0; + border_color[3] = 1.0; *border_width = 0; *border_style = ABC_BORDER_SOLID; @@ -100,7 +101,7 @@ int abc_css_border2(double border_color[3], int* border_width, int* border_styl } else if (p) { if (i > 1) - abc_css_color(border_color, border_color + 1, border_color + 2, p, -1); + abc_css_color(border_color, p, -1); else if (1 == i) __css_border_type(border_style, p, (size_t)(str - p)); @@ -141,7 +142,7 @@ static int __css_margin(abc_obj_t* obj, int width, int type) static int __css_border(abc_obj_t* obj, int width, int type) { - double color[3]; + double color[4]; int style; int w = 0; diff --git a/html/abc_css_color.c b/html/abc_css_color.c index 3783bc3..a63dc92 100644 --- a/html/abc_css_color.c +++ b/html/abc_css_color.c @@ -319,61 +319,60 @@ static css_color_t css_colors[] = {css_YellowGreen, 0x9acd32}, }; -int abc_css_color(double* r, double* g, double* b, const uint8_t* str, size_t len) +int abc_css_color(double rgba[4], const uint8_t* str, size_t len) { - *r = 0.0; - *g = 0.0; - *b = 0.0; + rgba[0] = 0.0; + rgba[1] = 0.0; + rgba[2] = 0.0; + rgba[3] = 1.0; if (!str || 0 == len) return 0; if ('#' == *str) { - uint64_t value = 0; - long i; + int v = 0; + long i; for (i = 1; i < len && str[i]; i++) { int c = str[i]; if ('0' <= c && '9' >= c) { - value <<= 4; - value += c - '0'; + v <<= 4; + v += c - '0'; } else { c |= 0x20; if ('a' <= c && 'f' >= c) { - value <<= 4; - value += c - 'a' + 10; + v <<= 4; + v += c - 'a' + 10; } } + + if (0 == i % 2) { + rgba[i / 2 - 1] = v / 255.0; + v = 0; + } } - *r = ((value >> 16) & 0xff) / 255.0; - *g = ((value >> 8) & 0xff) / 255.0; - *b = ( value & 0xff) / 255.0; + } else if (!__html_strncmp(str, "rgb", 3) + || !__html_strncmp(str, "rgba", 4)) { - } else if (!__html_strncmp(str, "rgb(", 4)) { long i; - long j = 4; + for (i = 3; i < len && str[i]; i++) { + if ('(' == str[i]) + break; + } + + long j = ++i; int k = 0; - for (i = 4; i < len && str[i]; i++) { + for ( ; i < len && str[i]; i++) { int c = str[i]; if (',' == c || ')' == c) { - switch (k) { - case 0: - *r = atof(str + j) / 255.0; - break; - case 1: - *g = atof(str + j) / 255.0; - break; - case 2: - *b = atof(str + j) / 255.0; - break; - }; - - if (++k > 2) + rgba[k] = atof(str + j) / 255.0; + + if (++k > 3) break; j = i + 1; } @@ -385,10 +384,12 @@ int abc_css_color(double* r, double* g, double* b, const uint8_t* str, size_t le int j; for (j = 0; c->names[j]; j++) { + if (!__html_strncmp(c->names[j], str, len)) { - *r = ((c->color >> 16) & 0xff) / 255.0; - *g = ((c->color >> 8) & 0xff) / 255.0; - *b = ( c->color & 0xff) / 255.0; + + rgba[0] = ((c->color >> 16) & 0xff) / 255.0; + rgba[1] = ((c->color >> 8) & 0xff) / 255.0; + rgba[2] = ( c->color & 0xff) / 255.0; return 0; } } @@ -400,15 +401,17 @@ int abc_css_color(double* r, double* g, double* b, const uint8_t* str, size_t le return 0; } -int abc_css_scrollbar_color(double thumb[3], double track[3], const uint8_t* str) +int abc_css_scrollbar_color(double thumb[4], double track[4], const uint8_t* str) { thumb[0] = 0.0; thumb[1] = 0.0; thumb[2] = 0.0; + thumb[3] = 1.0; track[0] = 0.0; track[1] = 0.0; track[2] = 0.0; + track[3] = 0.0; if (!str) return 0; @@ -432,10 +435,10 @@ int abc_css_scrollbar_color(double thumb[3], double track[3], const uint8_t* str } else if ('\0' == c || ' ' == c || '\t' == c || '\r' == c || '\n' == c) { if (0 == k) { - abc_css_color(thumb, thumb + 1, thumb + 2, str + j, i - 1 - j); + abc_css_color(thumb, str + j, i - 1 - j); k = 1; } else { - abc_css_color(track, track + 1, track + 2, str + j, i - 1 - j); + abc_css_color(track, str + j, i - 1 - j); break; } diff --git a/html/abc_html.c b/html/abc_html.c index b193055..445eea5 100644 --- a/html/abc_html.c +++ b/html/abc_html.c @@ -3,6 +3,7 @@ // HTML & CSS attrs static char* src_keys[] = {"src", "æº", NULL}; static char* rel_keys[] = {"rel", "å ³ç³»", NULL}; +static char* alt_keys[] = {"alt", "æ¿ä»£ææ¬", NULL}; static char* href_keys[] = {"href", "å°å", NULL}; static char* width_keys[] = {"width", "宽度", NULL}; @@ -10,6 +11,8 @@ static char* height_keys[] = {"height", "é«åº¦", NULL}; static char* display_keys[] = {"display", "æ¾ç¤ºæ¨¡å¼", NULL}; static char* visible_keys[] = {"visibility", "å¯è§æ§", NULL}; +static char* opacity_keys[] = {"opacity", "éæåº¦", NULL}; +static char* filter_keys[] = {"filter", "滤é", NULL}; static char* margin_keys[] = {"margin", "å¤è¾¹è·", NULL}; static char* margin_top_keys[] = {"margin-top", "ä¸è¾¹ç¼", NULL}; @@ -191,18 +194,18 @@ static html_attr_t html_attrs[] = #define ABC_CSS_SELECTOR(type) \ {style_keys, "", ABC_HTML_ATTR_STYLE, ABC_HTML_FLAG_SHOW}, \ - {class_keys, "", ABC_HTML_ATTR_CLASS, ABC_HTML_FLAG_SHOW}, \ {title_keys, "", ABC_HTML_ATTR_TITLE, ABC_HTML_FLAG_SHOW}, \ {type_keys, #type, ABC_HTML_ATTR_TYPE, ABC_HTML_FLAG_SHOW}, \ {name_keys, "", ABC_HTML_ATTR_NAME, ABC_HTML_FLAG_SHOW}, \ - {id_keys, "", ABC_HTML_ATTR_ID, ABC_HTML_FLAG_SHOW}, + {class_keys, "", ABC_CSS_CLASS, ABC_HTML_FLAG_SHOW}, \ + {id_keys, "", ABC_CSS_ID, ABC_HTML_FLAG_SHOW}, #define ABC_CSS_BACK_GROUND(color) \ {bg_keys, "", ABC_HTML_ATTR_BG, ABC_HTML_FLAG_SHOW}, \ {bg_color_keys, #color, ABC_HTML_ATTR_BG_COLOR, ABC_HTML_FLAG_SHOW}, \ {bg_image_keys, "", ABC_HTML_ATTR_BG_IMAGE, ABC_HTML_FLAG_SHOW}, \ {bg_repeat_keys, "", ABC_HTML_ATTR_BG_REPEAT, ABC_HTML_FLAG_SHOW}, \ - {bg_position_keys, "", ABC_HTML_ATTR_BG_POSITION, ABC_HTML_FLAG_SHOW}, + {bg_position_keys, "", ABC_HTML_ATTR_BG_POSITION, ABC_HTML_FLAG_SHOW}, \ #define ABC_CSS_FONT(font, size, color, style) \ {font_keys, #font, ABC_HTML_ATTR_FONT, 0}, \ @@ -216,6 +219,12 @@ static html_attr_t html_attrs[] = {text_transform_keys, "", ABC_HTML_ATTR_TEXT_TRANSFORM, ABC_HTML_FLAG_SHOW}, \ {text_indent_keys, "", ABC_HTML_ATTR_TEXT_INDENT, ABC_HTML_FLAG_SHOW}, +#define ABC_CSS_PSE_MOUSE() \ + {css_link_keys, "", ABC_CSS_LINK, ABC_HTML_FLAG_SHOW}, \ + {css_visited_keys, "", ABC_CSS_VISITED, ABC_HTML_FLAG_SHOW}, \ + {css_hover_keys, "", ABC_CSS_HOVER, ABC_HTML_FLAG_SHOW}, \ + {css_active_keys, "", ABC_CSS_ACTIVE, ABC_HTML_FLAG_SHOW}, + ABC_CSS_BOX(block, , , 12px) ABC_CSS_SCROLL(scroll, 12px, orangeRed white) ABC_CSS_SELECTOR() @@ -227,6 +236,9 @@ static html_attr_t html_attrs[] = {xmlns_keys, "", ABC_HTML_ATTR_XMLNS, 0}, {xmlang_keys, "", ABC_HTML_ATTR_XMLANG, 0}, {lang_keys, "", ABC_HTML_ATTR_LANG, 0}, + + {opacity_keys, "1.0", ABC_CSS_OPACITY, ABC_HTML_FLAG_SHOW}, + {filter_keys, "", ABC_CSS_FILTER, 0}, }; static html_attr_t meta_attrs[] = @@ -245,6 +257,9 @@ static html_attr_t body_attrs[] = ABC_CSS_FONT(SimSong, 16, black, ) ABC_CSS_TEXT(left, ) + + {opacity_keys, "1.0", ABC_CSS_OPACITY, ABC_HTML_FLAG_SHOW}, + {filter_keys, "", ABC_CSS_FILTER, 0}, }; static html_attr_t div_attrs[] = @@ -256,6 +271,11 @@ static html_attr_t div_attrs[] = ABC_CSS_FONT(SimSong, 16, black, ) ABC_CSS_TEXT(left, ) + + ABC_CSS_PSE_MOUSE() + + {opacity_keys, "", ABC_CSS_OPACITY, ABC_HTML_FLAG_SHOW}, + {filter_keys, "", ABC_CSS_FILTER, 0}, }; static html_attr_t h1_attrs[] = @@ -267,6 +287,11 @@ static html_attr_t h1_attrs[] = ABC_CSS_FONT(SimHei, 40, black, ) ABC_CSS_TEXT(left, ) + + ABC_CSS_PSE_MOUSE() + + {opacity_keys, "", ABC_CSS_OPACITY, ABC_HTML_FLAG_SHOW}, + {filter_keys, "", ABC_CSS_FILTER, 0}, }; static html_attr_t h2_attrs[] = @@ -278,6 +303,11 @@ static html_attr_t h2_attrs[] = ABC_CSS_FONT(SimHei, 32, black, ) ABC_CSS_TEXT(left, ) + + ABC_CSS_PSE_MOUSE() + + {opacity_keys, "", ABC_CSS_OPACITY, ABC_HTML_FLAG_SHOW}, + {filter_keys, "", ABC_CSS_FILTER, 0}, }; static html_attr_t h3_attrs[] = @@ -289,6 +319,11 @@ static html_attr_t h3_attrs[] = ABC_CSS_FONT(SimHei, 28, black, ) ABC_CSS_TEXT(left, ) + + ABC_CSS_PSE_MOUSE() + + {opacity_keys, "", ABC_CSS_OPACITY, ABC_HTML_FLAG_SHOW}, + {filter_keys, "", ABC_CSS_FILTER, 0}, }; static html_attr_t h4_attrs[] = @@ -300,6 +335,11 @@ static html_attr_t h4_attrs[] = ABC_CSS_FONT(SimHei, 24, black, ) ABC_CSS_TEXT(left, ) + + ABC_CSS_PSE_MOUSE() + + {opacity_keys, "", ABC_CSS_OPACITY, ABC_HTML_FLAG_SHOW}, + {filter_keys, "", ABC_CSS_FILTER, 0}, }; static html_attr_t h5_attrs[] = @@ -311,6 +351,11 @@ static html_attr_t h5_attrs[] = ABC_CSS_FONT(SimHei, 20, black, ) ABC_CSS_TEXT(left, ) + + ABC_CSS_PSE_MOUSE() + + {opacity_keys, "", ABC_CSS_OPACITY, ABC_HTML_FLAG_SHOW}, + {filter_keys, "", ABC_CSS_FILTER, 0}, }; static html_attr_t h6_attrs[] = @@ -322,6 +367,11 @@ static html_attr_t h6_attrs[] = ABC_CSS_FONT(SimHei, 16, black, ) ABC_CSS_TEXT(left, ) + + ABC_CSS_PSE_MOUSE() + + {opacity_keys, "", ABC_CSS_OPACITY, ABC_HTML_FLAG_SHOW}, + {filter_keys, "", ABC_CSS_FILTER, 0}, }; static html_attr_t hr_attrs[] = @@ -333,6 +383,9 @@ static html_attr_t hr_attrs[] = ABC_CSS_FONT(SimHei, 16, lightGray, ) ABC_CSS_TEXT(left, ) + + {opacity_keys, "", ABC_CSS_OPACITY, ABC_HTML_FLAG_SHOW}, + {filter_keys, "", ABC_CSS_FILTER, 0}, }; static html_attr_t p_attrs[] = @@ -345,6 +398,11 @@ static html_attr_t p_attrs[] = ABC_CSS_FONT(SimSong, 16, black, ) ABC_CSS_TEXT(left, ) + ABC_CSS_PSE_MOUSE() + + {opacity_keys, "", ABC_CSS_OPACITY, ABC_HTML_FLAG_SHOW}, + {filter_keys, "", ABC_CSS_FILTER, 0}, + {css_first_child_keys, "", ABC_CSS_FIRST_CHILD, ABC_HTML_FLAG_SHOW}, }; @@ -365,6 +423,9 @@ static html_attr_t css_id_attrs[] = ABC_CSS_TEXT(left, ) ABC_CSS_LIST() + {opacity_keys, "", ABC_CSS_OPACITY, ABC_HTML_FLAG_SHOW}, + {filter_keys, "", ABC_CSS_FILTER, 0}, + {vertical_align_keys, "", ABC_HTML_ATTR_VERTICAL_ALIGN, ABC_HTML_FLAG_SHOW}, }; @@ -378,6 +439,9 @@ static html_attr_t b_attrs[] = ABC_CSS_FONT(SimHei, 16, , bold) ABC_CSS_TEXT(left, ) + {opacity_keys, "", ABC_CSS_OPACITY, ABC_HTML_FLAG_SHOW}, + {filter_keys, "", ABC_CSS_FILTER, 0}, + {css_first_child_keys, "", ABC_CSS_FIRST_CHILD, ABC_HTML_FLAG_SHOW}, }; @@ -391,6 +455,9 @@ static html_attr_t i_attrs[] = ABC_CSS_FONT(SimSong, 16, , italic) ABC_CSS_TEXT(left, ) + {opacity_keys, "", ABC_CSS_OPACITY, ABC_HTML_FLAG_SHOW}, + {filter_keys, "", ABC_CSS_FILTER, 0}, + {css_first_child_keys, "", ABC_CSS_FIRST_CHILD, ABC_HTML_FLAG_SHOW}, }; @@ -404,11 +471,12 @@ static html_attr_t a_attrs[] = ABC_CSS_FONT(SimSong, 16, blue, ) ABC_CSS_TEXT(left, underline) - {href_keys, "", ABC_HTML_ATTR_HREF, ABC_HTML_FLAG_SHOW}, - {css_link_keys, "", ABC_CSS_LINK, ABC_HTML_FLAG_SHOW}, - {css_visited_keys, "", ABC_CSS_VISITED, ABC_HTML_FLAG_SHOW}, - {css_hover_keys, "", ABC_CSS_HOVER, ABC_HTML_FLAG_SHOW}, - {css_active_keys, "", ABC_CSS_ACTIVE, ABC_HTML_FLAG_SHOW}, + ABC_CSS_PSE_MOUSE() + + {opacity_keys, "", ABC_CSS_OPACITY, ABC_HTML_FLAG_SHOW}, + {filter_keys, "", ABC_CSS_FILTER, 0}, + + {href_keys, "", ABC_HTML_ATTR_HREF, ABC_HTML_FLAG_SHOW}, }; static html_attr_t link_attrs[] = @@ -424,7 +492,13 @@ static html_attr_t img_attrs[] = ABC_CSS_SCROLL( , , ) ABC_CSS_SELECTOR() - {src_keys, "", ABC_HTML_ATTR_SRC, ABC_HTML_FLAG_SHOW}, + ABC_CSS_PSE_MOUSE() + + {src_keys, "", ABC_HTML_ATTR_SRC, ABC_HTML_FLAG_SHOW}, + {alt_keys, "", ABC_HTML_ATTR_ALT, ABC_HTML_FLAG_SHOW}, + + {opacity_keys, "", ABC_CSS_OPACITY, ABC_HTML_FLAG_SHOW}, + {filter_keys, "", ABC_CSS_FILTER, 0}, }; static html_attr_t video_attrs[] = @@ -433,7 +507,12 @@ static html_attr_t video_attrs[] = ABC_CSS_SCROLL( , , ) ABC_CSS_SELECTOR() + ABC_CSS_PSE_MOUSE() + {control_keys, "", ABC_HTML_ATTR_CONTROLS, 0}, + + {opacity_keys, "", ABC_CSS_OPACITY, ABC_HTML_FLAG_SHOW}, + {filter_keys, "", ABC_CSS_FILTER, 0}, }; static html_attr_t audio_attrs[] = @@ -457,8 +536,13 @@ static html_attr_t input_attrs[] = ABC_CSS_FONT(SimSong, 16, black, ) ABC_CSS_TEXT(left, ) + ABC_CSS_PSE_MOUSE() + {size_keys, "", ABC_HTML_ATTR_SIZE, ABC_HTML_FLAG_SHOW}, {value_keys, "", ABC_HTML_ATTR_VALUE, ABC_HTML_FLAG_SHOW}, + + {opacity_keys, "", ABC_CSS_OPACITY, ABC_HTML_FLAG_SHOW}, + {filter_keys, "", ABC_CSS_FILTER, 0}, }; static html_attr_t label_attrs[] = @@ -656,7 +740,7 @@ html_label_t* __html_find_label2(const int type) int __html_add_attr(abc_obj_t* obj, int type, char** names, const char* value, int flags) { - if (type < ABC_HTML_ATTR_ID || type >= ABC_HTML_CSS_NB) + if (type < ABC_CSS_CLASS || type >= ABC_HTML_CSS_NB) return -EINVAL; abc_attr_t* attr = calloc(1, sizeof(abc_attr_t)); @@ -673,7 +757,7 @@ int __html_add_attr(abc_obj_t* obj, int type, char** names, const char* value, i attr->keys = names; attr->flags = flags; - int i = type - ABC_HTML_ATTR_ID; + int i = type - ABC_CSS_CLASS; if (obj->attrs[i]) abc_attr_free(obj->attrs[i]); @@ -898,6 +982,9 @@ void abc_html_close(abc_html_t* html) if (html->file) scf_string_free(html->file); + if (html->css) + abc_css_free(html->css); + if (html->js) scf_parse_close(html->js); @@ -1519,10 +1606,8 @@ static int __html_parse_obj(abc_html_t* html, abc_char_t* c) if (abc_css_parse(obj) < 0) return -1; - if (abc_css_merge(html, obj) < 0) { - scf_loge("\n"); + if (abc_css_merge(html, obj) < 0) return -1; - } break; case ABC_HTML_VIDEO: @@ -1531,10 +1616,7 @@ static int __html_parse_obj(abc_html_t* html, abc_char_t* c) case ABC_HTML_AUDIO: if (__html_add_controls(obj) < 0) return -1; - default: - if (abc_css_use(html, obj) < 0) - return -1; break; }; diff --git a/html/abc_html.h b/html/abc_html.h index 760e3f6..9d78828 100644 --- a/html/abc_html.h +++ b/html/abc_html.h @@ -32,7 +32,8 @@ struct abc_html_s abc_obj_t* root; abc_obj_t* current; - abc_obj_t* css; + + abc_css_t* css; abc_io_t io; @@ -50,16 +51,18 @@ int abc_html_post (abc_html_t** pp, abc_html_t* form, abc_obj_t* submit); void abc_html_close(abc_html_t* html); int abc_html_parse(abc_html_t* html); -int abc_css_parse (abc_obj_t* css); -int abc_css_merge (abc_html_t* html, abc_obj_t* css); +int abc_css_parse (abc_obj_t* style); +int abc_css_merge (abc_html_t* html, abc_obj_t* obj); int abc_css_use (abc_html_t* html, abc_obj_t* obj); -int abc_css_active(abc_obj_t* obj); + +int abc_css_clear (abc_obj_t* obj, int pse_start, int pse_end); +int abc_css_active(abc_obj_t* obj, int pse); int abc_css_bg_position(float* x, float* y, float w, float h, abc_obj_t* obj, const uint8_t* str); -int abc_css_color (double* r, double* g, double* b, const uint8_t* str, size_t len); +int abc_css_color(double rgba[4], const uint8_t* str, size_t len); -int abc_css_border2(double border_color[3], int* border_width, int* border_style, abc_obj_t* obj, int width, const uint8_t* str); +int abc_css_border2(double border_color[4], int* border_width, int* border_style, abc_obj_t* obj, int width, const uint8_t* str); int abc_css_length (abc_obj_t* obj, int width, const uint8_t* str); void abc_css_margin (abc_obj_t* obj, int width); @@ -75,7 +78,7 @@ int abc_css_overflow(const uint8_t* str); int abc_css_display (const uint8_t* str); int abc_css_scrollbar_width(const uint8_t* str); -int abc_css_scrollbar_color(double thumb[3], double track[3], const uint8_t* str); +int abc_css_scrollbar_color(double thumb[4], double track[4], const uint8_t* str); void abc_overflow_show(int* x, int* y, int* w, int* h, int mask_x, int mask_y, int mask_w, int mask_h); diff --git a/html/abc_obj.c b/html/abc_obj.c index f3ca27f..40b0261 100644 --- a/html/abc_obj.c +++ b/html/abc_obj.c @@ -17,10 +17,9 @@ abc_obj_t* abc_obj_alloc(scf_string_t* file, int line, int pos, int type) scf_list_init(&obj->list); scf_list_init(&obj->childs); - scf_list_init(&obj->css_pse_rules); + scf_list_init(&obj->css); obj->type = type; - obj->line = line; obj->pos = pos; @@ -30,9 +29,6 @@ abc_obj_t* abc_obj_alloc(scf_string_t* file, int line, int pos, int type) void abc_obj_free(abc_obj_t* obj) { if (obj) { - if (obj->value) - scf_string_free(obj->value); - if (obj->text) scf_string_free(obj->text); @@ -61,14 +57,55 @@ void abc_obj_free(abc_obj_t* obj) abc_attr_free(obj->attrs[i]); } - scf_list_clear(&obj->childs, abc_obj_t, list, abc_obj_free); - scf_list_clear(&obj->css_pse_rules, abc_obj_t, list, abc_obj_free); - scf_slist_clear(obj->css_pse_chain, pse_link_t, next, free); + scf_list_clear(&obj->css, css_rule_t, list, css_rule_free); + scf_list_clear(&obj->childs, abc_obj_t, list, abc_obj_free); free(obj); } } +void abc_css_free(abc_css_t* css) +{ + if (css) { + scf_list_t* l; + css_rule_t* r; + css_hash_t* h; + int i; + int j; + + for (i = 0; i < ABC_CSS_SELECTOR_NB; i++) { + h = &(css->hash[i]); + + for (l = scf_list_head(&h->rules); l != scf_list_sentinel(&h->rules); ) { + r = scf_list_data(l, css_rule_t, hash); + l = scf_list_next(l); + + scf_list_del(&r->hash); + } + + for (j = 0; j < sizeof(h->attrs) / sizeof(h->attrs); j++) { + if (h->attrs[j]) + abc_attr_free(h->attrs[j]); + } + } + + free(css); + } +} + +abc_css_t* abc_css_alloc() +{ + abc_css_t* css = calloc(1, sizeof(abc_css_t)); + if (!css) + return NULL; + + int i; + for (i = 0; i < ABC_CSS_SELECTOR_NB; i++) + scf_list_init(&(css->hash[i].rules)); + + return css; +} + void abc_attr_free(abc_attr_t* attr) { if (attr) { @@ -79,6 +116,46 @@ void abc_attr_free(abc_attr_t* attr) } } +css_rule_t* css_rule_alloc(scf_string_t* file, int line, int pos, int type) +{ + css_rule_t* css = calloc(1, sizeof(css_rule_t)); + if (!css) + return NULL; + + if (file) { + css->file = scf_string_clone(file); + + if (!css->file) { + free(css); + return NULL; + } + } + + scf_list_init(&css->list); + + css->type = type; + return css; +} + +void css_rule_free(css_rule_t* css) +{ + if (css) { + if (css->text) + scf_string_free(css->text); + + if (css->file) + scf_string_free(css->file); + + int i; + for (i = 0; i < sizeof(css->attrs) / sizeof(css->attrs[0]); i++) { + if (css->attrs[i]) + abc_attr_free(css->attrs[i]); + } + + free(css); + } +} + void abc_dfs_update_xy(abc_obj_t* root, int dx, int dy) { scf_list_t* l; @@ -207,7 +284,7 @@ int abc_obj_cmp_keys(abc_obj_t* obj, const char* name, size_t len) return -1; } -int abc_obj_copy_attrs(abc_obj_t* dst, abc_obj_t* src) +int abc_css_copy_attrs(css_rule_t* dst, css_rule_t* src) { abc_attr_t* attr; abc_attr_t* copy; @@ -246,10 +323,10 @@ int abc_obj_set_attr(abc_obj_t* obj, int key, const char* value, size_t len) scf_string_t* s; abc_attr_t* attr; - if (key < ABC_HTML_ATTR_ID || key >= ABC_HTML_CSS_NB) + if (key < ABC_CSS_CLASS || key >= ABC_HTML_CSS_NB) return -EINVAL; - attr = obj->attrs[key - ABC_HTML_ATTR_ID]; + attr = obj->attrs[key - ABC_CSS_CLASS]; if (!attr) return -EINVAL; @@ -289,27 +366,26 @@ abc_attr_t* abc_obj_find_attr(abc_obj_t* obj, int key) return NULL; } -void abc_css_print(abc_obj_t* obj) +void abc_css_print(css_rule_t* css) { - if (!obj) + if (!css) return; - if (!(ABC_HTML_FLAG_SHOW & obj->flags)) + if (!(ABC_HTML_FLAG_SHOW & css->flags)) return; - if (obj->text) - printf("%s ", obj->text->data); - else if (obj->keys) - printf("%s ", obj->keys[0]); + if (css->text) + printf("%s ", css->text->data); + else if (css->keys) + printf("%s ", css->keys[0]); - pse_link_t* pseLink; abc_attr_t* attr; int i; printf("{\n"); - for (i = 0; i < sizeof(obj->attrs) / sizeof(obj->attrs[0]); i++) { - attr = obj->attrs[i]; + for (i = 0; i < sizeof(css->attrs) / sizeof(css->attrs[0]); i++) { + attr = css->attrs[i]; if (!attr || !attr->value || 0 == attr->value->len) continue; @@ -318,15 +394,6 @@ void abc_css_print(abc_obj_t* obj) printf(" %s: %s;\n", attr->keys[0], attr->value->data); } - pseLink = obj->css_pse_chain; - while (pseLink) { - attr = abc_obj_get_attr(pseLink->obj, pseLink->pse_type); - - printf("%s%s ", pseLink->obj->keys[0], attr->keys[0]); - - pseLink = pseLink->next; - } - printf("}\n"); } @@ -346,6 +413,7 @@ void abc_obj_print(abc_obj_t* obj) scf_list_t* l; abc_attr_t* attr; abc_obj_t* child; + css_rule_t* css; if (!obj) return; @@ -380,30 +448,16 @@ void abc_obj_print(abc_obj_t* obj) if (obj->text) printf("%s\n", obj->text->data); - for (l = scf_list_head(&obj->childs); l != scf_list_sentinel(&obj->childs); l = scf_list_next(l)) { - child = scf_list_data(l, abc_obj_t, list); + for (l = scf_list_head(&obj->css); l != scf_list_sentinel(&obj->css); l = scf_list_next(l)) { + css = scf_list_data(l, css_rule_t, list); - switch (obj->type) - { - case ABC_HTML_LINK: - attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_TYPE); - - if (!attr || __html_strcmp(attr->value->data, "text/css")) - break; - case ABC_HTML_STYLE: - abc_css_print(child); - break; - - default: - abc_obj_print(child); - break; - }; + abc_css_print(css); } - for (l = scf_list_head(&obj->css_pse_rules); l != scf_list_sentinel(&obj->css_pse_rules); l = scf_list_next(l)) { + for (l = scf_list_head(&obj->childs); l != scf_list_sentinel(&obj->childs); l = scf_list_next(l)) { child = scf_list_data(l, abc_obj_t, list); - abc_css_print(child); + abc_obj_print(child); } if (ABC_HTML_FLAG_CLOSE == (obj->flags & (ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SINGLE))) { diff --git a/html/abc_obj.h b/html/abc_obj.h index 6d98d44..452ea0d 100644 --- a/html/abc_obj.h +++ b/html/abc_obj.h @@ -9,7 +9,10 @@ typedef struct abc_obj_s abc_obj_t; typedef struct abc_attr_s abc_attr_t; typedef struct abc_text_s abc_text_t; -typedef struct pse_link_s pse_link_t; + +typedef struct abc_css_s abc_css_t; +typedef struct css_rule_s css_rule_t; +typedef struct css_hash_s css_hash_t; enum abc_objs { @@ -72,17 +75,26 @@ enum abc_objs ABC_CORE_TEXT, // not HTML label, only for browser core to layout & draw text ABC_HTML_NB, // total HTML objects - ABC_HTML_ATTR_ID, - ABC_HTML_ATTR_TYPE, + // css selectors + ABC_CSS_COMBINATOR = ABC_HTML_NB, + ABC_CSS_PSE_ELEMENT, + ABC_CSS_PSE_CLASS, + ABC_CSS_ATTR, + + ABC_CSS_CLASS, // also for html attr 'class' + ABC_CSS_ID, // also for html attr 'id' + ABC_CSS_SELECTOR_NB, + + ABC_HTML_ATTR_TYPE = ABC_CSS_SELECTOR_NB, ABC_HTML_ATTR_NAME, ABC_HTML_ATTR_VALUE, - ABC_HTML_ATTR_CLASS, ABC_HTML_ATTR_TITLE, ABC_HTML_ATTR_STYLE, ABC_HTML_ATTR_HREF, ABC_HTML_ATTR_SRC, ABC_HTML_ATTR_REL, + ABC_HTML_ATTR_ALT, ABC_HTML_ATTR_FOR, @@ -159,6 +171,9 @@ enum abc_objs ABC_CSS_SCROLLBAR_WIDTH, ABC_CSS_SCROLLBAR_COLOR, + ABC_CSS_OPACITY, + ABC_CSS_FILTER, + ABC_CSS_LIST_STYLE, ABC_CSS_LIST_STYLE_TYPE, ABC_CSS_LIST_STYLE_IMAGE, @@ -167,26 +182,12 @@ enum abc_objs // css pse class (element) ABC_CSS_FIRST_CHILD, - ABC_CSS_PSE_STATIC, // css pse static barrier, all pse classes (elements) above only based on HTML topology - ABC_CSS_LINK, - ABC_CSS_VISITED, ABC_CSS_HOVER, ABC_CSS_ACTIVE, + ABC_CSS_VISITED, - ABC_CSS_PSE_DYNAMIC, // css pse dynamic barrier, pse classes (elements) above based on user operations - - ABC_HTML_CSS_NB = ABC_CSS_PSE_DYNAMIC, // total HTML & CSS attrs - - // css selectors - ABC_CSS_ATTR, - ABC_CSS_PSE_CLASS, - ABC_CSS_PSE_ELEMENT, - ABC_CSS_COMBINATOR, - - // css selectors from html attrs above - ABC_CSS_ID = ABC_HTML_ATTR_ID, - ABC_CSS_CLASS = ABC_HTML_ATTR_CLASS, + ABC_HTML_CSS_NB, // total HTML & CSS attrs }; enum abc_display_type @@ -248,18 +249,11 @@ struct abc_text_s int h; }; -struct pse_link_s -{ - pse_link_t* next; - - abc_obj_t* obj; - int pse_type; -}; - #define ABC_HTML_FLAG_OPEN 0 #define ABC_HTML_FLAG_CLOSE 1 #define ABC_HTML_FLAG_SINGLE 2 #define ABC_HTML_FLAG_SHOW 4 +#define ABC_CSS_FLAG_ON 8 struct abc_attr_s { @@ -272,37 +266,74 @@ struct abc_attr_s abc_obj_t* parent; }; +struct css_rule_s +{ + int type; + uint32_t flags; + + char** keys; + scf_string_t* text; + + abc_obj_t* parent; + + scf_list_t list; + + abc_attr_t* attrs[ABC_HTML_CSS_NB - ABC_CSS_CLASS]; + + scf_string_t* file; // file name + int line; // line + int pos; // position + + int last_key; + int last_key_end; + scf_list_t hash; +}; + +struct css_hash_s +{ + scf_list_t rules; + abc_attr_t* attrs[ABC_HTML_CSS_NB - ABC_CSS_CLASS]; +}; + +struct abc_css_s +{ + css_hash_t hash[ABC_CSS_SELECTOR_NB]; +}; + struct abc_obj_s { int type; uint32_t flags; char** keys; - scf_string_t* value; + scf_string_t* text; abc_obj_t* parent; scf_list_t list; + + abc_attr_t* attrs[ABC_HTML_CSS_NB - ABC_CSS_CLASS]; + + scf_string_t* file; // file name + int line; // line + int pos; // position + + int text_line; + int text_pos; + scf_list_t css; + scf_list_t childs; int n_childs; int n_texts; - abc_attr_t* attrs[ABC_HTML_CSS_NB - ABC_HTML_ATTR_ID]; - void* gtk_builder; abc_filter_t* av_filter; abc_avio_t* vout; + abc_img_t* img; - scf_string_t* text; abc_text_t* text_splits; // for layout, split a long text to multi-lines and save every-line here - int text_line; - int text_pos; abc_io_t io; - pse_link_t* css_pse_chain; - scf_list_t css_pse_rules; - int css_pse_type; - int border_top; int border_bottom; int border_left; @@ -367,11 +398,6 @@ struct abc_obj_s int progress; uint32_t jiffies; // timeout numbers of sys timer - - scf_string_t* file; // file name - int line; // line - int pos; // position - scf_string_t* js_path; scf_string_t* js_obj; scf_string_t* js_so; @@ -380,6 +406,8 @@ struct abc_obj_s uint32_t clicked:1; uint32_t visited:1; + uint32_t css_use:1; + uint32_t w_set:1; uint32_t h_set:1; @@ -393,16 +421,22 @@ abc_obj_t* abc_obj_alloc(scf_string_t* file, int line, int pos, int type); void abc_obj_free (abc_obj_t* obj); void abc_attr_free(abc_attr_t* attr); +abc_css_t* abc_css_alloc(); +void abc_css_free (abc_css_t* css); + +css_rule_t* css_rule_alloc(scf_string_t* file, int line, int pos, int type); +void css_rule_free (css_rule_t* css); + abc_obj_t* abc_obj_find (abc_obj_t* root, int x, int y); void abc_obj_print(abc_obj_t* obj); -int abc_obj_cmp_keys (abc_obj_t* obj, const char* name, size_t len); -int abc_obj_copy_attrs(abc_obj_t* dst, abc_obj_t* src); +int abc_css_copy_attrs(css_rule_t* dst, css_rule_t* src); +void abc_obj_set_css (abc_obj_t* obj, css_rule_t* css); -void abc_obj_set_css (abc_obj_t* obj, abc_obj_t* css); int abc_obj_set_attr (abc_obj_t* obj, int key, const char* value, size_t len); -abc_attr_t* abc_obj_get_attr2(abc_obj_t* obj, const char* key, int len); +int abc_obj_cmp_keys (abc_obj_t* obj, const char* name, size_t len); +abc_attr_t* abc_obj_get_attr2(abc_obj_t* obj, const char* key, int len); abc_attr_t* abc_obj_find_attr(abc_obj_t* obj, int key); abc_obj_t* abc_obj_find_type(abc_obj_t* root, int type); @@ -417,10 +451,10 @@ scf_string_t* abc_ol_list_style(abc_obj_t* obj, int num); static inline abc_attr_t* abc_obj_get_attr(abc_obj_t* obj, int key) { - if (key < ABC_HTML_ATTR_ID || key >= ABC_HTML_CSS_NB) + if (key < ABC_CSS_CLASS || key >= ABC_HTML_CSS_NB) return NULL; - return obj->attrs[key - ABC_HTML_ATTR_ID]; + return obj->attrs[key - ABC_CSS_CLASS]; } #endif diff --git a/html/main.c b/html/main.c index 4a8eb4b..561c805 100644 --- a/html/main.c +++ b/html/main.c @@ -1,5 +1,27 @@ #include"abc_html.h" +void abc_css_recursive_use(abc_html_t* html, abc_obj_t* obj) +{ + scf_list_t* l; + abc_attr_t* attr; + abc_obj_t* child; + css_rule_t* css; + + if (!obj) + return; + + if (!obj->css_use && ABC_CORE_TEXT != obj->type) { + obj->css_use = 1; + abc_css_use(html, obj); + } + + for (l = scf_list_head(&obj->childs); l != scf_list_sentinel(&obj->childs); l = scf_list_next(l)) { + child = scf_list_data(l, abc_obj_t, list); + + abc_css_recursive_use(html, child); + } +} + int main(int argc, char* argv[]) { abc_html_t* html = NULL; @@ -24,6 +46,8 @@ int main(int argc, char* argv[]) printf("\n"); + abc_css_recursive_use(html, html->root); + if (html->root) abc_obj_print(html->root); diff --git a/ui/Makefile b/ui/Makefile index 44553a7..fe8d516 100644 --- a/ui/Makefile +++ b/ui/Makefile @@ -24,6 +24,8 @@ CFILES += abc_render_body.c CFILES += __render_border.c CFILES += __render_bg_image.c CFILES += __render_text.c +CFILES += __render_text_gl.c + CFILES += abc_render_text.c CFILES += abc_render_empty.c diff --git a/ui/__render_bg_image.c b/ui/__render_bg_image.c index 9e13429..7ccc008 100644 --- a/ui/__render_bg_image.c +++ b/ui/__render_bg_image.c @@ -97,12 +97,10 @@ static int __render_draw_bg_image(abc_render_t* render, abc_obj_t* obj, int widt return ret; } - double r = 0.0; - double g = 0.0; - double b = 0.0; + double rgba[4] = {0.0, 0.0, 0.0, 1.0}; attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_BG_COLOR); if (attr) - abc_css_color(&r, &g, &b, attr->value->data, attr->value->len); + abc_css_color(rgba, attr->value->data, attr->value->len); if (0 == program) __init_program(&program, vert_shader, frag_shader); @@ -113,6 +111,29 @@ static int __render_draw_bg_image(abc_render_t* render, abc_obj_t* obj, int widt if (0 == texture_rgba) __init_texture(&texture_rgba, GL_RGBA, img->width, img->height, NULL); + int x = obj->x + obj->margin_left + obj->border_left; + int y = obj->y + obj->margin_top + obj->border_top; + int w = obj->w - obj->margin_left - obj->border_left - obj->border_right - obj->margin_right; + int h = obj->h - obj->margin_top - obj->border_top - obj->border_bottom - obj->margin_bottom; + + int view_x = x; + int view_y = y; + int view_w = w; + int view_h = h; + + switch (obj->overflow_type) + { + case ABC_OVERFLOW_HIDDEN: + case ABC_OVERFLOW_SCROLL: + case ABC_OVERFLOW_AUTO: + abc_overflow_show(&view_x, &view_y, &view_w, &view_h, + obj->view_x, + obj->view_y, obj->view_w, obj->view_h); + break; + default: + break; + }; + float mvp[16]; __compute_mvp(mvp, 0, 0, 0); @@ -120,30 +141,45 @@ static int __render_draw_bg_image(abc_render_t* render, abc_obj_t* obj, int widt GLfloat vert_update[] = { - 2.0 * obj->x / (float)width - 1.0, - -2.0 * (obj->y + obj->h) / (float)height + 1.0, + 2.0 * view_x / (float)width - 1.0, + -2.0 * (view_y + view_h) / (float)height + 1.0, + + 2.0 * (view_x + view_w) / (float)width - 1.0, + -2.0 * (view_y + view_h) / (float)height + 1.0, + + 2.0 * view_x / (float)width - 1.0, + -2.0 * view_y / (float)height + 1.0, + + 2.0 * (view_x + view_w) / (float)width - 1.0, + -2.0 * view_y / (float)height + 1.0, + }; + + GLfloat texture_update[] = + { + (view_x - x) / (float)w, + (view_y + view_h - y) / (float)h, - 2.0 * (obj->x + obj->w) / (float)width - 1.0, - -2.0 * (obj->y + obj->h) / (float)height + 1.0, + (view_x + view_w - x) / (float)w, + (view_y + view_h - y) / (float)h, - 2.0 * obj->x / (float)width - 1.0, - -2.0 * obj->y / (float)height + 1.0, + (view_x - x) / (float)w, + (view_y - y) / (float)h, - 2.0 * (obj->x + obj->w) / (float)width - 1.0, - -2.0 * obj->y / (float)height + 1.0, + (view_x + view_w - x) / (float)w, + (view_y - y) / (float)h, }; - GLfloat x = 0.0; - GLfloat y = 0.0; - GLfloat w = img->width / (float)obj->w; - GLfloat h = img->height / (float)obj->h; + GLfloat ix = 0.0; + GLfloat iy = 0.0; + GLfloat iw = img->width / (float)w; + GLfloat ih = img->height / (float)h; - if (w > 1.0 || h > 1.0) + if (iw > 1.0 || ih > 1.0) { - GLfloat max = w > h ? w : h; + GLfloat max = iw > ih ? iw : ih; - w /= max; - h /= max; + iw /= max; + ih /= max; } GLint repeat_x = 1; @@ -153,14 +189,14 @@ static int __render_draw_bg_image(abc_render_t* render, abc_obj_t* obj, int widt attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_BG_POSITION); if (attr) { - abc_css_bg_position(&x, &y, w, h, obj, attr->value->data); + abc_css_bg_position(&ix, &iy, iw, ih, obj, attr->value->data); - scf_logd("background-position: %s, x: %f, y: %f, w: %f, h: %f\n", attr->value->data, x, y, w, h); + scf_logd("background-position: %s, ix: %f, iy: %f, iw: %f, ih: %f\n", attr->value->data, ix, iy, iw, ih); - if (x + w > 1.0) + if (ix + iw > 1.0) index_x = -1; - if (y + h > 1.0) + if (iy + ih > 1.0) index_y = -1; } @@ -178,7 +214,7 @@ static int __render_draw_bg_image(abc_render_t* render, abc_obj_t* obj, int widt } } - scf_logd("repeat_x: %d, repeat_y: %d, index_x: %d, index_y: %d\n", repeat_x, repeat_y, index_x, index_y); + scf_logi("repeat_x: %d, repeat_y: %d, index_x: %d, index_y: %d\n", repeat_x, repeat_y, index_x, index_y); glUseProgram(program); @@ -198,8 +234,8 @@ static int __render_draw_bg_image(abc_render_t* render, abc_obj_t* obj, int widt glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, img->width, img->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bgra); glUniform1i(uniform_rgba, 0); - glUniform4f(uniform_rect, x, y, w, h); - glUniform4f(uniform_color, r, g, b, 1.0); + glUniform4f(uniform_rect, ix, iy, iw, ih); + glUniform4f(uniform_color, rgba[0], rgba[1], rgba[2], rgba[3]); glUniform1i(uniform_repeat_x, repeat_x); glUniform1i(uniform_repeat_y, repeat_y); diff --git a/ui/__render_border.c b/ui/__render_border.c index 734c9a6..9a0adeb 100644 --- a/ui/__render_border.c +++ b/ui/__render_border.c @@ -188,13 +188,13 @@ static int __render_draw_border(abc_render_t* render, abc_obj_t* obj, int width, int border = 0; int border_style = ABC_BORDER_SOLID; - double fgColor[3] = {0.0, 0.0, 0.0}; + double fgColor[4] = {0.0, 0.0, 0.0, 1.0}; double bgColor[4] = {0.0, 0.0, 0.0, 0.0}; abc_attr_t* attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_BG_COLOR); if (attr && attr->value->len > 0) { bgColor[3] = 1.0; - abc_css_color(bgColor, bgColor + 1, bgColor + 2, attr->value->data, attr->value->len); + abc_css_color(bgColor, attr->value->data, attr->value->len); } attr = abc_obj_get_attr(obj, ABC_CSS_BORDER_TOP); @@ -203,7 +203,7 @@ static int __render_draw_border(abc_render_t* render, abc_obj_t* obj, int width, else { attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_COLOR); if (attr) - abc_css_color(fgColor, fgColor + 1, fgColor + 2, attr->value->data, attr->value->len); + abc_css_color(fgColor, attr->value->data, attr->value->len); } int x = obj->x + obj->margin_left; @@ -383,7 +383,7 @@ static int __render_draw_border(abc_render_t* render, abc_obj_t* obj, int width, glUniform1f(uniform_x_border, x_border); glUniform1f(uniform_y_border, y_border); - glUniform4f(uniform_color, fgColor[0], fgColor[1], fgColor[2], 1.0); + glUniform4f(uniform_color, fgColor[0], fgColor[1], fgColor[2], fgColor[3]); glUniform4f(uniform_bgColor, bgColor[0], bgColor[1], bgColor[2], bgColor[3]); glUniform4f(uniform_thumbColor, thumbColor[0], thumbColor[1], thumbColor[2], thumbColor[3]); diff --git a/ui/__render_text.c b/ui/__render_text.c index ec7db0f..121fdd0 100644 --- a/ui/__render_text.c +++ b/ui/__render_text.c @@ -1,38 +1,5 @@ #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, v.a); \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_text(abc_render_t* render) { return 0; @@ -99,10 +66,8 @@ int __init_text(cairo_t* cr, abc_obj_t* obj, int num_flag, double scale) } cairo_text_extents_t extents; - double r = 0.0; - double g = 0.0; - double b = 0.0; - double size = 16.0; + double rgba[4] = {0.0, 0.0, 0.0, 1.0}; + double size = 16.0; attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE); if (attr) @@ -110,10 +75,10 @@ int __init_text(cairo_t* cr, abc_obj_t* obj, int num_flag, double scale) attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_COLOR); if (attr) - abc_css_color(&r, &g, &b, attr->value->data, attr->value->len); + abc_css_color(rgba, attr->value->data, attr->value->len); cairo_set_font_size (cr, size * scale); - cairo_set_source_rgba(cr, r, g, b, 1.0); + cairo_set_source_rgba(cr, rgba[0], rgba[1], rgba[2], rgba[3]); if (ABC_HTML_OL == obj->parent->type && num_flag) { @@ -190,15 +155,6 @@ static int __render_draw_text(abc_render_t* render, abc_obj_t* obj, int width, i scf_logd("obj->type: %d, obj->w: %d, obj->h: %d, w: %d, h: %d\n", obj->type, obj->w, obj->h, w, h); - 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, w_text, h_text, NULL); - abc_attr_t* attr; cairo_surface_t* surface; cairo_t* cr; @@ -207,18 +163,16 @@ static int __render_draw_text(abc_render_t* render, abc_obj_t* obj, int width, i if (!bgra) return -ENOMEM; - double r = 0.0; - double g = 0.0; - double b = 0.0; - attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_BG_COLOR); - if (attr) - abc_css_color(&r, &g, &b, attr->value->data, attr->value->len); + double rgba[4] = {0.0, 0.0, 0.0, 0.0}; + attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_BG_COLOR); + if (attr && attr->value->len > 0) + abc_css_color(rgba, attr->value->data, attr->value->len); surface = cairo_image_surface_create_for_data(bgra, CAIRO_FORMAT_ARGB32, w_text, h_text, w_text * 4); cr = cairo_create(surface); - cairo_set_line_width(cr, 1); - cairo_set_source_rgba(cr, r, g, b, 0.0); + cairo_set_line_width (cr, 1); + cairo_set_source_rgba(cr, rgba[0], rgba[1], rgba[2], rgba[3]); cairo_rectangle(cr, 0, 0, w_text, h_text); cairo_fill(cr); cairo_stroke(cr); @@ -250,70 +204,17 @@ static int __render_draw_text(abc_render_t* render, abc_obj_t* obj, int width, i break; }; - 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 * view_x / (float)width - 1.0, - -2.0 * (view_y + view_h) / (float)height + 1.0, - - 2.0 * (view_x + view_w) / (float)width - 1.0, - -2.0 * (view_y + view_h) / (float)height + 1.0, - - 2.0 * view_x / (float)width - 1.0, - -2.0 * view_y / (float)height + 1.0, - - 2.0 * (view_x + view_w) / (float)width - 1.0, - -2.0 * view_y / (float)height + 1.0, - }; - - GLfloat texture_update[] = - { - (view_x - x) / (float)w, - (view_y + view_h - y) / (float)h, - - (view_x + view_w - x) / (float)w, - (view_y + view_h - y) / (float)h, - - (view_x - x) / (float)w, - (view_y - y) / (float)h, - - (view_x + view_w - x) / (float)w, - (view_y - y) / (float)h, - }; - - 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, w_text, h_text, 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); - - glBindBuffer (GL_ARRAY_BUFFER, buffers[1]); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(texture_update), texture_update); - - glBindVertexArray(vao); - - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glDisable(GL_BLEND); + float mvp[16]; + __compute_mvp(mvp, 0, 0, 0); - glBindVertexArray(0); - glUseProgram(0); + __render_text_gl(obj, bgra, w_text, h_text, width, height, + x, + y, + w, + h, + view_x, view_y, view_w, view_h, mvp); free(bgra); return 0; diff --git a/ui/__render_text_gl.c b/ui/__render_text_gl.c new file mode 100644 index 0000000..a8e7f11 --- /dev/null +++ b/ui/__render_text_gl.c @@ -0,0 +1,124 @@ +#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 float opacity; \n" + "uniform sampler2D tex_rgba; \n" + "void main() { \n" + " vec2 xy = v_texCoord; \n" + " vec4 v = texture2D(tex_rgba, xy).rgba; \n" + " v *= opacity;\n" + " outputColor = vec4(v.b, v.g, v.r, v.a); \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 GLuint uniform_opacity; + + +int __render_text_gl(abc_obj_t* obj, const char* bgra, int w_text, int h_text, int width, int height, + int x, + int y, + int w, + int h, + int view_x, int view_y, int view_w, int view_h, float mvp[16]) +{ + 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, w_text, h_text, NULL); + + GLfloat opacity = 1.0; + + abc_attr_t* attr = abc_obj_get_attr(obj, ABC_CSS_OPACITY); + if (attr && attr->value->len > 0) + opacity = atof(attr->value->data); + + GLfloat vert_update[] = + { + 2.0 * view_x / (float)width - 1.0, + -2.0 * (view_y + view_h) / (float)height + 1.0, + + 2.0 * (view_x + view_w) / (float)width - 1.0, + -2.0 * (view_y + view_h) / (float)height + 1.0, + + 2.0 * view_x / (float)width - 1.0, + -2.0 * view_y / (float)height + 1.0, + + 2.0 * (view_x + view_w) / (float)width - 1.0, + -2.0 * view_y / (float)height + 1.0, + }; + + GLfloat texture_update[] = + { + (view_x - x) / (float)w, + (view_y + view_h - y) / (float)h, + + (view_x + view_w - x) / (float)w, + (view_y + view_h - y) / (float)h, + + (view_x - x) / (float)w, + (view_y - y) / (float)h, + + (view_x + view_w - x) / (float)w, + (view_y - y) / (float)h, + }; + + glUseProgram(program); + uniform_mvp = glGetUniformLocation(program, "mvp"); + uniform_rgba = glGetUniformLocation(program, "tex_rgba"); + uniform_opacity = glGetUniformLocation(program, "opacity"); + + glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, mvp); + + // board + glActiveTexture(GL_TEXTURE0); + glBindTexture (GL_TEXTURE_2D, texture_rgba); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, w_text, h_text, 0, GL_RGBA, GL_UNSIGNED_BYTE, bgra); + glUniform1i(uniform_rgba, 0); + + glUniform1f(uniform_opacity, opacity); + + // draw + glBindBuffer (GL_ARRAY_BUFFER, buffers[0]); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vert_update), vert_update); + + glBindBuffer (GL_ARRAY_BUFFER, buffers[1]); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(texture_update), texture_update); + + glBindVertexArray(vao); + + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glDisable(GL_BLEND); + + glBindVertexArray(0); + glUseProgram(0); + return 0; +} diff --git a/ui/abc.h b/ui/abc.h index 61a0ec3..eec7d62 100644 --- a/ui/abc.h +++ b/ui/abc.h @@ -13,7 +13,7 @@ typedef struct abc_render_s abc_render_t; typedef struct abc_layout_s abc_layout_t; typedef struct abc_ctx_s abc_ctx_t; -typedef int (*abc_layout_pt)(abc_layout_t* layout, abc_obj_t* obj, int width, int height); +typedef int (*abc_layout_pt)(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height); struct abc_layout_s { @@ -83,6 +83,13 @@ void __draw_text(cairo_text_extents_t* extents, cairo_t* cr, const char* text, d int __init_text (cairo_t* cr, abc_obj_t* obj, int num_flag, double scale); int __layout_text(cairo_t* cr, abc_obj_t* obj, int x, int width, cairo_text_extents_t* extents); +int __render_text_gl(abc_obj_t* obj, const char* bgra, int w_text, int h_text, int width, int height, + int x, + int y, + int w, + int h, + int view_x, int view_y, int view_w, int view_h, float mvp[16]); + extern abc_render_t __render_border; extern abc_render_t __render_bg_image; extern abc_render_t __render_text; diff --git a/ui/abc_layout.c b/ui/abc_layout.c index 1a348a0..244380b 100644 --- a/ui/abc_layout.c +++ b/ui/abc_layout.c @@ -1,30 +1,30 @@ #include"abc.h" -int abc_layout_body (abc_layout_t* layout, abc_obj_t* obj, int width, int height); +int abc_layout_body (abc_ctx_t* ctx, abc_obj_t* obj, int width, int height); -int abc_layout_text(abc_layout_t* layout, abc_obj_t* obj, int width, int height); +int abc_layout_text(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height); -int abc_layout_div (abc_layout_t* layout, abc_obj_t* obj, int width, int height); -int abc_layout_h1 (abc_layout_t* layout, abc_obj_t* obj, int width, int height); -int abc_layout_hr (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_div (abc_ctx_t* ctx, abc_obj_t* obj, int width, int height); +int abc_layout_h1 (abc_ctx_t* ctx, abc_obj_t* obj, int width, int height); +int abc_layout_hr (abc_ctx_t* ctx, abc_obj_t* obj, int width, int height); +int abc_layout_img (abc_ctx_t* ctx, 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); +int abc_layout_form (abc_ctx_t* ctx, abc_obj_t* obj, int width, int height); +int abc_layout_label(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height); +int abc_layout_input(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height); -int abc_layout_table(abc_layout_t* layout, abc_obj_t* obj, int width, int height); -int abc_layout_td (abc_layout_t* layout, abc_obj_t* obj, int width, int height); +int abc_layout_table(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height); +int abc_layout_td (abc_ctx_t* ctx, abc_obj_t* obj, int width, int height); -int abc_layout_video(abc_layout_t* layout, abc_obj_t* obj, int width, int height); -int abc_layout_audio(abc_layout_t* layout, abc_obj_t* obj, int width, int height); +int abc_layout_video(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height); +int abc_layout_audio(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height); -int abc_layout_empty(abc_layout_t* layout, abc_obj_t* obj, int width, int height) +int abc_layout_empty(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height) { return 0; } -int abc_layout_html(abc_layout_t* layout, abc_obj_t* obj, int width, int height) +int abc_layout_html(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height) { obj->w = obj->w0; obj->h = obj->h0; @@ -83,7 +83,7 @@ static abc_layout_pt abc_layouts[ABC_HTML_NB] = [ABC_HTML_LINK] = abc_layout_empty, }; -int abc_layout_obj(abc_layout_t* layout, abc_obj_t* obj, int width, int height) +int abc_layout_obj(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height) { if (obj->type >= ABC_HTML_NB) return 0; @@ -92,7 +92,7 @@ int abc_layout_obj(abc_layout_t* layout, abc_obj_t* obj, int width, int height) if (!f) return -EINVAL; - return f(layout, obj, width, height); + return f(ctx, obj, width, height); } #define LAYOUT_POS_FIXED(X, W, W_SET, L_SET, R_SET, L, R) \ @@ -235,7 +235,7 @@ int abc_layout_css(abc_obj_t* obj) return obj->position_type; } -int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height) +int abc_layout_root(abc_ctx_t* ctx, abc_obj_t* root, int width, int height) { if (!root) return -EINVAL; @@ -248,6 +248,14 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height) || ABC_HTML_LINK == root->type) return 0; + if (!root->css_use && ABC_CORE_TEXT != root->type) { + root->css_use = 1; + + int ret = abc_css_use(ctx->current, root); + if (ret < 0) + return ret; + } + abc_attr_t* attr; int root_w = width; @@ -384,7 +392,7 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height) child->x = root->x + root->left; child->y = y + h; - ret = abc_layout_root(NULL, child, root_w, root_h); + ret = abc_layout_root(ctx, child, root_w, root_h); if (ret < 0) return ret; @@ -409,7 +417,7 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height) child->x = x; child->y = y; - ret = abc_layout_root(NULL, child, root_w, root_h); + ret = abc_layout_root(ctx, child, root_w, root_h); if (ret < 0) return ret; @@ -449,7 +457,7 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height) child->x = root->x + root->left; child->y = y; - ret = abc_layout_root(NULL, child, root_w, root_h); + ret = abc_layout_root(ctx, child, root_w, root_h); if (ret < 0) return ret; @@ -480,7 +488,7 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height) root->content_w = root->w; root->content_h = root->h; - int ret = abc_layout_obj(NULL, root, width, height); + int ret = abc_layout_obj(ctx, root, width, height); if (ret < 0) return ret; #if 0 diff --git a/ui/abc_layout_audio.c b/ui/abc_layout_audio.c index b8b7f75..5a84331 100644 --- a/ui/abc_layout_audio.c +++ b/ui/abc_layout_audio.c @@ -1,6 +1,6 @@ #include"abc.h" -int abc_layout_audio(abc_layout_t* layout, abc_obj_t* obj, int width, int height) +int abc_layout_audio(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height) { abc_obj_t* attr; diff --git a/ui/abc_layout_body.c b/ui/abc_layout_body.c index f374316..ba5e9ef 100644 --- a/ui/abc_layout_body.c +++ b/ui/abc_layout_body.c @@ -1,6 +1,6 @@ #include"abc.h" -int abc_layout_body(abc_layout_t* layout, abc_obj_t* obj, int width, int height) +int abc_layout_body(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height) { return 0; } diff --git a/ui/abc_layout_div.c b/ui/abc_layout_div.c index ea423e4..cd12b30 100644 --- a/ui/abc_layout_div.c +++ b/ui/abc_layout_div.c @@ -1,6 +1,6 @@ #include"abc.h" -int abc_layout_div(abc_layout_t* layout, abc_obj_t* obj, int width, int height) +int abc_layout_div(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height) { abc_attr_t* attr; cairo_text_extents_t extents; diff --git a/ui/abc_layout_form.c b/ui/abc_layout_form.c index a51e25e..e5d9ffa 100644 --- a/ui/abc_layout_form.c +++ b/ui/abc_layout_form.c @@ -1,6 +1,6 @@ #include"abc.h" -int abc_layout_form(abc_layout_t* layout, abc_obj_t* obj, int width, int height) +int abc_layout_form(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height) { abc_attr_t* attr; abc_attr_t* style; diff --git a/ui/abc_layout_h1.c b/ui/abc_layout_h1.c index 7a8bf00..c045ee8 100644 --- a/ui/abc_layout_h1.c +++ b/ui/abc_layout_h1.c @@ -1,6 +1,6 @@ #include"abc.h" -int abc_layout_h1(abc_layout_t* layout, abc_obj_t* obj, int width, int height) +int abc_layout_h1(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height) { abc_attr_t* attr; abc_attr_t* style; diff --git a/ui/abc_layout_hr.c b/ui/abc_layout_hr.c index 6639222..fb2f80f 100644 --- a/ui/abc_layout_hr.c +++ b/ui/abc_layout_hr.c @@ -1,6 +1,6 @@ #include"abc.h" -int abc_layout_hr(abc_layout_t* layout, abc_obj_t* obj, int width, int height) +int abc_layout_hr(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height) { int size = 16; diff --git a/ui/abc_layout_img.c b/ui/abc_layout_img.c index 5842d89..1e17a7c 100644 --- a/ui/abc_layout_img.c +++ b/ui/abc_layout_img.c @@ -1,10 +1,51 @@ #include"abc.h" -int abc_layout_img(abc_layout_t* layout, abc_obj_t* obj, int width, int height) +int abc_layout_img(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height) { obj->w_set = abc_css_width (obj, width); obj->h_set = abc_css_height(obj, height); + if (obj->w_set && obj->h_set) + return 0; + + abc_attr_t* attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_SRC); + if (!attr) { + scf_loge("src image not found\n"); + return -EINVAL; + } + + if (obj->img) { + abc_img_close(obj->img); + obj->img = NULL; + } + + scf_string_t* spath = NULL; + abc_io_t* io = NULL; + + int ret = __io_url_path(&io, &spath, obj->file->data, attr->value->data, attr->value->len); + if (ret < 0) + return ret; + + ret = abc_img_open(&obj->img, spath->data); + + scf_string_free(spath); + spath = NULL; + if (ret < 0) + return ret; + + int iw = obj->img->width; + int ih = obj->img->height; + + if (obj->w_set && obj->w > 0 && iw > 0) + obj->h = ih * obj->w / iw; + + else if (obj->h_set && obj->h > 0 && ih > 0) + obj->w = iw * obj->h / ih; + else { + obj->w = iw; + obj->h = ih; + } + scf_logi("w: %d, h: %d\n", obj->w, obj->h); return 0; } diff --git a/ui/abc_layout_input.c b/ui/abc_layout_input.c index 28bf15c..3ce2572 100644 --- a/ui/abc_layout_input.c +++ b/ui/abc_layout_input.c @@ -1,6 +1,6 @@ #include"abc.h" -int abc_layout_input(abc_layout_t* layout, abc_obj_t* obj, int width, int height) +int abc_layout_input(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height) { abc_attr_t* attr; cairo_text_extents_t extents; diff --git a/ui/abc_layout_label.c b/ui/abc_layout_label.c index 8e4d8e7..87e557c 100644 --- a/ui/abc_layout_label.c +++ b/ui/abc_layout_label.c @@ -1,6 +1,6 @@ #include"abc.h" -int abc_layout_label(abc_layout_t* layout, abc_obj_t* obj, int width, int height) +int abc_layout_label(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height) { abc_attr_t* attr; cairo_text_extents_t extents; diff --git a/ui/abc_layout_table.c b/ui/abc_layout_table.c index 95e6ee3..770b376 100644 --- a/ui/abc_layout_table.c +++ b/ui/abc_layout_table.c @@ -1,6 +1,6 @@ #include"abc.h" -int abc_layout_table(abc_layout_t* layout, abc_obj_t* obj, int width, int height) +int abc_layout_table(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height) { scf_list_t* l; scf_list_t* l2; diff --git a/ui/abc_layout_td.c b/ui/abc_layout_td.c index a770ec3..78ec13b 100644 --- a/ui/abc_layout_td.c +++ b/ui/abc_layout_td.c @@ -1,6 +1,6 @@ #include"abc.h" -int abc_layout_td(abc_layout_t* layout, abc_obj_t* obj, int width, int height) +int abc_layout_td(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height) { abc_obj_t* table; abc_attr_t* attr; diff --git a/ui/abc_layout_text.c b/ui/abc_layout_text.c index 4786d35..cb11c1b 100644 --- a/ui/abc_layout_text.c +++ b/ui/abc_layout_text.c @@ -58,6 +58,8 @@ int __layout_text(cairo_t* cr, abc_obj_t* obj, int x, int width, cairo_text_exte cairo_text_extents (cr, obj->text->data, extents); int w = extents->x_bearing + extents->x_advance; + + w = (w + size - 1) / size * size; if (x + w <= width) { extents->width = w; return 0; @@ -93,6 +95,7 @@ int __layout_text(cairo_t* cr, abc_obj_t* obj, int x, int width, cairo_text_exte return n; w = tmp.x_bearing + tmp.x_advance; + w = (w + size - 1) / size * size; if (x + w <= width) { x = 0; @@ -124,7 +127,7 @@ int __layout_text(cairo_t* cr, abc_obj_t* obj, int x, int width, cairo_text_exte return 0; } -int abc_layout_text(abc_layout_t* layout, abc_obj_t* obj, int width, int height) +int abc_layout_text(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height) { abc_obj_t* parent = obj->parent; abc_attr_t* attr; diff --git a/ui/abc_layout_video.c b/ui/abc_layout_video.c index f46e7b3..1cced80 100644 --- a/ui/abc_layout_video.c +++ b/ui/abc_layout_video.c @@ -108,7 +108,7 @@ error: return ret; } -int abc_layout_video(abc_layout_t* layout, abc_obj_t* obj, int width, int height) +int abc_layout_video(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height) { abc_attr_t* attr; @@ -116,7 +116,6 @@ int abc_layout_video(abc_layout_t* layout, abc_obj_t* obj, int width, int height int h = 0; if (!obj->av_filter) { - int ret = __av_filter_init(obj); if (ret < 0) { scf_loge("open video failed\n"); diff --git a/ui/abc_render_hr.c b/ui/abc_render_hr.c index 374bc6f..a450718 100644 --- a/ui/abc_render_hr.c +++ b/ui/abc_render_hr.c @@ -55,18 +55,18 @@ static int __render_draw_hr(abc_render_t* render, abc_obj_t* obj, int width, int if (0 == vao) __init_buffers(&vao, buffers); - double fgColor[3] = {0.0, 0.0, 0.0}; + double fgColor[4] = {0.0, 0.0, 0.0, 1.0}; double bgColor[4] = {0.0, 0.0, 0.0, 0.0}; abc_attr_t* attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_BG_COLOR); if (attr && attr->value->len > 0) { bgColor[3] = 1.0; - abc_css_color(bgColor, bgColor + 1, bgColor + 2, attr->value->data, attr->value->len); + abc_css_color(bgColor, attr->value->data, attr->value->len); } attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_COLOR); if (attr) - abc_css_color(fgColor, fgColor + 1, fgColor + 2, attr->value->data, attr->value->len); + abc_css_color(fgColor, attr->value->data, attr->value->len); int x = obj->x + obj->margin_left; int y = obj->y + obj->margin_top; @@ -144,7 +144,7 @@ static int __render_draw_hr(abc_render_t* render, abc_obj_t* obj, int width, int glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, mvp); - glUniform4f(uniform_color, fgColor[0], fgColor[1], fgColor[2], 1.0); + glUniform4f(uniform_color, fgColor[0], fgColor[1], fgColor[2], fgColor[3]); glUniform4f(uniform_bgColor, bgColor[0], bgColor[1], bgColor[2], bgColor[3]); glUniform1f(uniform_line_width, 1.0 / (float)h); diff --git a/ui/abc_render_img.c b/ui/abc_render_img.c index 8c4fede..a75f46e 100644 --- a/ui/abc_render_img.c +++ b/ui/abc_render_img.c @@ -1,39 +1,6 @@ #include"abc.h" #include"abc_ffmpeg.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_img(abc_render_t* render) { return 0; @@ -42,88 +9,84 @@ static int _render_fini_img(abc_render_t* render) static int _render_draw_img(abc_render_t* render, abc_obj_t* obj, int width, int height, abc_ctx_t* ctx) { abc_attr_t* attr; - abc_img_t* img = NULL; + int ret; + + if (!obj->img) { + attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_SRC); + if (!attr) { + scf_loge("src image not found\n"); + return -EINVAL; + } + + scf_string_t* spath = NULL; + abc_io_t* io = NULL; - attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_SRC); - if (!attr) { - scf_loge("src image of '%s' not found\n", obj->keys[0]); - return -1; + ret = __io_url_path(&io, &spath, obj->file->data, attr->value->data, attr->value->len); + if (ret < 0) + return ret; + + ret = abc_img_open(&obj->img, spath->data); + + scf_string_free(spath); + spath = NULL; + if (ret < 0) + return ret; } - int ret = abc_img_open(&img, attr->value->data); - if (ret < 0) - return ret; + int iw = obj->img->width; + int ih = obj->img->height; - uint8_t* bgra = calloc(1, img->width * img->height * 4); + uint8_t* bgra = calloc(1, iw * ih * 4); if (!bgra) { - abc_img_close(img); + abc_img_close(obj->img); + obj->img = NULL; return -ENOMEM; } - ret = abc_img_read(img, bgra, img->width * img->height * 4); + ret = abc_img_read(obj->img, bgra, iw * ih * 4); + + abc_img_close(obj->img); + obj->img = NULL; if (ret < 0) { - abc_img_close(img); free(bgra); return ret; } - 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, img->width, img->height, NULL); - - float mvp[16]; - __compute_mvp(mvp, 0, 0, 0); - - scf_logi("%s, x: %d, y: %d, w: %d, h: %d\n", obj->keys[0], obj->x, obj->y, obj->w, obj->h); - int x = obj->x + obj->left; int y = obj->y + obj->top; int w = obj->w - obj->left - obj->right; int h = obj->h - obj->top - obj->bottom; - GLfloat vert_update[] = - { - 2.0 * x / (float)width - 1.0, - -2.0 * (y + h) / (float)height + 1.0, - - 2.0 * (x + w) / (float)width - 1.0, - -2.0 * (y + h) / (float)height + 1.0, - - 2.0 * x / (float)width - 1.0, - -2.0 * y / (float)height + 1.0, + int view_x = x; + int view_y = y; + int view_w = w; + int view_h = h; - 2.0 * (x + w) / (float)width - 1.0, - -2.0 * y / (float)height + 1.0, + switch (obj->overflow_type) + { + case ABC_OVERFLOW_HIDDEN: + case ABC_OVERFLOW_SCROLL: + case ABC_OVERFLOW_AUTO: + abc_overflow_show(&view_x, &view_y, &view_w, &view_h, + obj->view_x, + obj->view_y, obj->view_w, obj->view_h); + break; + default: + break; }; - glUseProgram(program); - uniform_rgba = glGetUniformLocation(program, "tex_rgba"); - uniform_mvp = glGetUniformLocation(program, "mvp"); + scf_logd("%s, x: %d, y: %d, w: %d, h: %d\n", obj->keys[0], obj->x, obj->y, obj->w, obj->h); - glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, mvp); - - glActiveTexture(GL_TEXTURE0); - glBindTexture (GL_TEXTURE_2D, texture_rgba); - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, img->width, img->height, 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); + float mvp[16]; + __compute_mvp(mvp, 0, 0, 0); - glBindVertexArray(0); - glUseProgram(0); + __render_text_gl(obj, bgra, iw, ih, width, height, + x, + y, + w, + h, + view_x, view_y, view_w, view_h, mvp); - abc_img_close(img); free(bgra); return 0; } diff --git a/ui/abc_render_input.c b/ui/abc_render_input.c index 8bb74d6..13931aa 100644 --- a/ui/abc_render_input.c +++ b/ui/abc_render_input.c @@ -1,38 +1,5 @@ #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; @@ -50,15 +17,6 @@ static int _render_draw_input(abc_render_t* render, abc_obj_t* obj, int width, i int w_text = w * ctx->gl_scale; int h_text = h * ctx->gl_scale; - 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, w_text, h_text, NULL); - abc_attr_t* type; abc_attr_t* attr; cairo_text_extents_t extents; @@ -72,15 +30,13 @@ static int _render_draw_input(abc_render_t* render, abc_obj_t* obj, int width, i surface = cairo_image_surface_create_for_data(bgra, CAIRO_FORMAT_ARGB32, w_text, h_text, w_text * 4); cr = cairo_create(surface); - double r = 0.0; - double g = 0.0; - double b = 0.0; + double rgba[4] = {0.0, 0.0, 0.0, 0.0}; attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_BG_COLOR); - if (attr) - abc_css_color(&r, &g, &b, attr->value->data, attr->value->len); + if (attr && attr->value->len > 0) + abc_css_color(rgba, attr->value->data, attr->value->len); cairo_set_line_width (cr, 1); - cairo_set_source_rgba(cr, r, g, b, 1.0); + cairo_set_source_rgba(cr, rgba[0], rgba[1], rgba[2], rgba[3]); cairo_rectangle(cr, 0, 0, w_text, h_text); cairo_fill(cr); cairo_stroke(cr); @@ -89,9 +45,13 @@ static int _render_draw_input(abc_render_t* render, abc_obj_t* obj, int width, i if (attr) cairo_select_font_face(cr, attr->value->data, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + rgba[0] = 0.0; + rgba[1] = 0.0; + rgba[2] = 0.0; + rgba[3] = 1.0; attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_COLOR); if (attr) - abc_css_color(&r, &g, &b, attr->value->data, attr->value->len); + abc_css_color(rgba, attr->value->data, attr->value->len); int size = 16; attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE); @@ -99,7 +59,7 @@ static int _render_draw_input(abc_render_t* render, abc_obj_t* obj, int width, i size = atoi(attr->value->data); cairo_set_font_size (cr, size * ctx->gl_scale); - cairo_set_source_rgba(cr, r, g, b, 1.0); + cairo_set_source_rgba(cr, rgba[0], rgba[1], rgba[2], rgba[3]); int x_cursor = 2; @@ -172,61 +132,12 @@ static int _render_draw_input(abc_render_t* render, abc_obj_t* obj, int width, i scf_logd("x: %d, y: %d, w: %d, h: %d\n", obj->x, obj->y, obj->w, obj->h); - GLfloat vert_update[] = - { - 2.0 * view_x / (float)width - 1.0, - -2.0 * (view_y + view_h) / (float)height + 1.0, - - 2.0 * (view_x + view_w) / (float)width - 1.0, - -2.0 * (view_y + view_h) / (float)height + 1.0, - - 2.0 * view_x / (float)width - 1.0, - -2.0 * view_y / (float)height + 1.0, - - 2.0 * (view_x + view_w) / (float)width - 1.0, - -2.0 * view_y / (float)height + 1.0, - }; - - GLfloat texture_update[] = - { - (view_x - x) / (float)w, - (view_y + view_h - y) / (float)h, - - (view_x + view_w - x) / (float)w, - (view_y + view_h - y) / (float)h, - - (view_x - x) / (float)w, - (view_y - y) / (float)h, - - (view_x + view_w - x) / (float)w, - (view_y - y) / (float)h, - }; - - 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, w_text, h_text, 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); - - glBindBuffer (GL_ARRAY_BUFFER, buffers[1]); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(texture_update), texture_update); - - glBindVertexArray(vao); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - glBindVertexArray(0); - glUseProgram(0); + __render_text_gl(obj, bgra, w_text, h_text, width, height, + x, + y, + w, + h, + view_x, view_y, view_w, view_h, mvp); free(bgra); return 0; diff --git a/ui/abc_render_label.c b/ui/abc_render_label.c index e1394bf..c36a3cd 100644 --- a/ui/abc_render_label.c +++ b/ui/abc_render_label.c @@ -1,38 +1,5 @@ #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; @@ -53,15 +20,6 @@ static int _render_draw_label(abc_render_t* render, abc_obj_t* obj, int width, i int w_text = w * ctx->gl_scale; int h_text = h * ctx->gl_scale; - 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, w_text, h_text, NULL); - abc_attr_t* type; abc_attr_t* attr; cairo_text_extents_t extents; @@ -75,15 +33,14 @@ static int _render_draw_label(abc_render_t* render, abc_obj_t* obj, int width, i surface = cairo_image_surface_create_for_data(bgra, CAIRO_FORMAT_ARGB32, w_text, h_text, w_text * 4); cr = cairo_create(surface); - double r = 0.0; - double g = 0.0; - double b = 0.0; + double rgba[4] = {0.0, 0.0, 0.0, 0.0}; + attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_BG_COLOR); - if (attr) - abc_css_color(&r, &g, &b, attr->value->data, attr->value->len); + if (attr && attr->value->len > 0) + abc_css_color(rgba, attr->value->data, attr->value->len); cairo_set_line_width (cr, 1); - cairo_set_source_rgba(cr, r, g, b, 1.0); + cairo_set_source_rgba(cr, rgba[0], rgba[1], rgba[2], rgba[3]); cairo_rectangle(cr, 0, 0, w_text, h_text); cairo_fill(cr); cairo_stroke(cr); @@ -94,7 +51,7 @@ static int _render_draw_label(abc_render_t* render, abc_obj_t* obj, int width, i attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_COLOR); if (attr) - abc_css_color(&r, &g, &b, attr->value->data, attr->value->len); + abc_css_color(rgba, attr->value->data, attr->value->len); int size = 16; attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE); @@ -102,7 +59,7 @@ static int _render_draw_label(abc_render_t* render, abc_obj_t* obj, int width, i size = atoi(attr->value->data); cairo_set_font_size (cr, size * ctx->gl_scale); - cairo_set_source_rgba(cr, r, g, b, 1.0); + cairo_set_source_rgba(cr, rgba[0], rgba[1], rgba[2], rgba[3]); cairo_text_extents(cr, obj->text->data, &extents); cairo_move_to (cr, extents.x_bearing, -extents.y_bearing + (h_text - extents.height) / 2); @@ -139,61 +96,12 @@ static int _render_draw_label(abc_render_t* render, abc_obj_t* obj, int width, i scf_logd("x: %d, y: %d, w: %d, h: %d\n", obj->x, obj->y, obj->w, obj->h); - GLfloat vert_update[] = - { - 2.0 * view_x / (float)width - 1.0, - -2.0 * (view_y + view_h) / (float)height + 1.0, - - 2.0 * (view_x + view_w) / (float)width - 1.0, - -2.0 * (view_y + view_h) / (float)height + 1.0, - - 2.0 * view_x / (float)width - 1.0, - -2.0 * view_y / (float)height + 1.0, - - 2.0 * (view_x + view_w) / (float)width - 1.0, - -2.0 * view_y / (float)height + 1.0, - }; - - GLfloat texture_update[] = - { - (view_x - x) / (float)w, - (view_y + view_h - y) / (float)h, - - (view_x + view_w - x) / (float)w, - (view_y + view_h - y) / (float)h, - - (view_x - x) / (float)w, - (view_y - y) / (float)h, - - (view_x + view_w - x) / (float)w, - (view_y - y) / (float)h, - }; - - 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, w_text, h_text, 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); - - glBindBuffer (GL_ARRAY_BUFFER, buffers[1]); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(texture_update), texture_update); - - glBindVertexArray(vao); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - glBindVertexArray(0); - glUseProgram(0); + __render_text_gl(obj, bgra, w_text, h_text, width, height, + x, + y, + w, + h, + view_x, view_y, view_w, view_h, mvp); free(bgra); return 0; diff --git a/ui/abc_render_li.c b/ui/abc_render_li.c index 0a83184..2407ae7 100644 --- a/ui/abc_render_li.c +++ b/ui/abc_render_li.c @@ -63,24 +63,22 @@ static int _render_draw_li(abc_render_t* render, abc_obj_t* obj, int width, int if (!bgra) return -ENOMEM; - double r = 0.0; - double g = 0.0; - double b = 0.0; - int size = 16; + double rgba[4] = {0.0, 0.0, 0.0, 0.0}; + int size = 16; attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE); if (attr) size = atoi(attr->value->data); attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_BG_COLOR); - if (attr) - abc_css_color(&r, &g, &b, attr->value->data, attr->value->len); + if (attr && attr->value->len > 0) + abc_css_color(rgba, attr->value->data, attr->value->len); surface = cairo_image_surface_create_for_data(bgra, CAIRO_FORMAT_ARGB32, w_text, h_text, w_text * 4); cr = cairo_create(surface); - cairo_set_line_width(cr, 1); - cairo_set_source_rgb(cr, r, g, b); + cairo_set_line_width (cr, 1); + cairo_set_source_rgba(cr, rgba[0], rgba[1], rgba[2], rgba[3]); cairo_rectangle(cr, 0, 0, w_text, h_text); cairo_fill(cr); cairo_stroke(cr); @@ -118,8 +116,8 @@ static int _render_draw_li(abc_render_t* render, abc_obj_t* obj, int width, int surface = cairo_image_surface_create_for_data(bgra1, CAIRO_FORMAT_ARGB32, w_order, h_order, w_order * 4); cr = cairo_create(surface); - cairo_set_line_width(cr, 1.0 * ctx->gl_scale); - cairo_set_source_rgb(cr, r, g, b); + cairo_set_line_width (cr, 1); + cairo_set_source_rgba(cr, rgba[0], rgba[1], rgba[2], rgba[3]); cairo_rectangle(cr, 0, 0, w_order, h_order); cairo_fill(cr); cairo_stroke(cr); @@ -140,14 +138,15 @@ static int _render_draw_li(abc_render_t* render, abc_obj_t* obj, int width, int scf_string_free(s); s = NULL; } else { - r = 0.0; - g = 0.0; - b = 0.0; + rgba[0] = 0.0; + rgba[1] = 0.0; + rgba[2] = 0.0; + rgba[3] = 1.0; attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_COLOR); if (attr) - abc_css_color(&r, &g, &b, attr->value->data, attr->value->len); + abc_css_color(rgba, attr->value->data, attr->value->len); - cairo_set_source_rgb(cr, r, g, b); + cairo_set_source_rgba(cr, rgba[0], rgba[1], rgba[2], rgba[3]); attr = abc_obj_find_attr(obj, ABC_CSS_LIST_STYLE_TYPE); if (attr) { diff --git a/ui/abc_render_td.c b/ui/abc_render_td.c index 59dc044..bc27b56 100644 --- a/ui/abc_render_td.c +++ b/ui/abc_render_td.c @@ -1,38 +1,5 @@ #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_td(abc_render_t* render) { return 0; @@ -55,15 +22,6 @@ static int _render_draw_td(abc_render_t* render, abc_obj_t* obj, int width, int int w_text = w * ctx->gl_scale; int h_text = h * ctx->gl_scale; - 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, w_text, h_text, NULL); - uint8_t* bgra = calloc(1, w_text * h_text * 4); if (!bgra) return -ENOMEM; @@ -78,27 +36,27 @@ static int _render_draw_td(abc_render_t* render, abc_obj_t* obj, int width, int cairo_set_line_width(cr, 1); // clear table element's area with background-color - double r = 1.0; - double g = 1.0; - double b = 1.0; + double rgba[4] = {0.0, 0.0, 0.0, 0.0}; + attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_BG_COLOR); - if (attr) - abc_css_color(&r, &g, &b, attr->value->data, attr->value->len); + if (attr && attr->value->len > 0) + abc_css_color(rgba, attr->value->data, attr->value->len); - cairo_set_source_rgb(cr, r, g, b); + cairo_set_source_rgba(cr, rgba[0], rgba[1], rgba[2], rgba[3]); cairo_rectangle(cr, 0, 0, w_text, h_text); cairo_fill(cr); cairo_stroke(cr); // draw text - r = 0.0; - g = 0.0; - b = 0.0; + rgba[0] = 0.0; + rgba[1] = 0.0; + rgba[2] = 0.0; + rgba[3] = 1.0; attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_COLOR); if (attr) - abc_css_color(&r, &g, &b, attr->value->data, attr->value->len); + abc_css_color(rgba, attr->value->data, attr->value->len); - cairo_set_source_rgb(cr, r, g, b); + cairo_set_source_rgba(cr, rgba[0], rgba[1], rgba[2], rgba[3]); attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT); if (attr) @@ -143,47 +101,35 @@ static int _render_draw_td(abc_render_t* render, abc_obj_t* obj, int width, int 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); + int view_x = x; + int view_y = y; + int view_w = w; + int view_h = h; - GLfloat vert_update[] = + switch (obj->overflow_type) { - 2.0 * x / (float)width - 1.0, - -2.0 * (y + h) / (float)height + 1.0, - - 2.0 * (x + w) / (float)width - 1.0, - -2.0 * (y + h) / (float)height + 1.0, - - 2.0 * x / (float)width - 1.0, - -2.0 * y / (float)height + 1.0, - - 2.0 * (x + w) / (float)width - 1.0, - -2.0 * y / (float)height + 1.0, + case ABC_OVERFLOW_HIDDEN: + case ABC_OVERFLOW_SCROLL: + case ABC_OVERFLOW_AUTO: + abc_overflow_show(&view_x, &view_y, &view_w, &view_h, + obj->view_x, + obj->view_y, obj->view_w, obj->view_h); + break; + default: + break; }; - glUseProgram(program); - uniform_rgba = glGetUniformLocation(program, "tex_rgba"); - uniform_mvp = glGetUniformLocation(program, "mvp"); - - glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, mvp); - - glActiveTexture(GL_TEXTURE0); - glBindTexture (GL_TEXTURE_2D, texture_rgba); - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, w_text, h_text, 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); + scf_logd("%s, x: %d, y: %d, w: %d, h: %d\n", obj->text->data, obj->x, obj->y, obj->w, obj->h); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + float mvp[16]; + __compute_mvp(mvp, 0, 0, 0); - glBindVertexArray(0); - glUseProgram(0); + __render_text_gl(obj, bgra, w_text, h_text, width, height, + x, + y, + w, + h, + view_x, view_y, view_w, view_h, mvp); free(bgra); return 0; diff --git a/ui/abc_render_text.c b/ui/abc_render_text.c index ba04295..04da387 100644 --- a/ui/abc_render_text.c +++ b/ui/abc_render_text.c @@ -1,38 +1,5 @@ #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, v.a); \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_text(abc_render_t* render) { return 0; @@ -41,7 +8,7 @@ static int _render_fini_text(abc_render_t* render) static int _draw_text_line(abc_obj_t* obj, const char* text, int x, int y, int w, int h, int width, int height, float mvp[16], - double bcolor[3], double fcolor[3], int font_size, int bold, int italic, int line_type, double line_width, double scale) + double bcolor[4], double fcolor[4], int font_size, int bold, int italic, int line_type, double line_width, double scale) { int w_text = w * scale; int h_text = h * scale; @@ -57,8 +24,8 @@ static int _draw_text_line(abc_obj_t* obj, const char* text, surface = cairo_image_surface_create_for_data(bgra, CAIRO_FORMAT_ARGB32, w_text, h_text, w_text * 4); cr = cairo_create(surface); - cairo_set_line_width(cr, 1); - cairo_set_source_rgba(cr, bcolor[0], bcolor[1], bcolor[2], 0.0); + cairo_set_line_width (cr, 1); + cairo_set_source_rgba(cr, bcolor[0], bcolor[1], bcolor[2], bcolor[3]); cairo_rectangle(cr, 0, 0, w_text, h_text); cairo_fill(cr); cairo_stroke(cr); @@ -68,7 +35,7 @@ static int _draw_text_line(abc_obj_t* obj, const char* text, cairo_select_font_face(cr, attr->value->data, italic, bold); cairo_set_font_size (cr, font_size * scale); - cairo_set_source_rgba(cr, fcolor[0], fcolor[1], fcolor[2], 1.0); + cairo_set_source_rgba(cr, fcolor[0], fcolor[1], fcolor[2], fcolor[3]); __draw_text(&extents, cr, text, 0, 0, obj->y_bearing * scale, line_type, line_width * scale); @@ -79,52 +46,42 @@ static int _draw_text_line(abc_obj_t* obj, const char* text, surface = NULL; cr = NULL; - 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 * x / (float)width - 1.0, - -2.0 * (y + h) / (float)height + 1.0, - - 2.0 * (x + w) / (float)width - 1.0, - -2.0 * (y + h) / (float)height + 1.0, + abc_obj_t* parent = obj->parent; - 2.0 * x / (float)width - 1.0, - -2.0 * y / (float)height + 1.0, + int view_x = x; + int view_y = y; + int view_w = w; + int view_h = h; - 2.0 * (x + w) / (float)width - 1.0, - -2.0 * y / (float)height + 1.0, + switch (obj->overflow_type) + { + case ABC_OVERFLOW_SCROLL: + case ABC_OVERFLOW_AUTO: + case ABC_OVERFLOW_HIDDEN: + if (parent && (x < parent->view_x + || y < parent->view_y + || x + w > parent->view_x + parent->view_w + || y + h > parent->view_y + parent->view_h)) { + + abc_overflow_show(&view_x, &view_y, &view_w, &view_h, + parent->view_x, + parent->view_y, + parent->view_w - parent->border_right - parent->padding_right, + parent->view_h - parent->border_bottom - parent->padding_bottom); + } + break; + default: + break; }; - 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, w_text, h_text, 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); - - glBindBuffer (GL_ARRAY_BUFFER, buffers[1]); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(texture_array), texture_array); - - glBindVertexArray(vao); - - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glDisable(GL_BLEND); + scf_logd("%s, x: %d, y: %d, w: %d, h: %d\n", obj->text->data, obj->x, obj->y, obj->w, obj->h); - glBindVertexArray(0); - glUseProgram(0); + __render_text_gl(obj, bgra, w_text, h_text, width, height, + x, + y, + w, + h, + view_x, view_y, view_w, view_h, mvp); free(bgra); return 0; @@ -135,32 +92,23 @@ static int _render_draw_text(abc_render_t* render, abc_obj_t* obj, int width, in if (obj->w <= 0 || obj->h <= 0) 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_text_t* t; abc_attr_t* attr; - double bcolor[3] = {0.0}; - double fcolor[3] = {0.0}; + double bcolor[4] = {0.0, 0.0, 0.0, 0.0}; + double fcolor[4] = {0.0, 0.0, 0.0, 1.0}; double size = 16.0; int bold = CAIRO_FONT_WEIGHT_NORMAL; int italic = CAIRO_FONT_SLANT_NORMAL; - attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_BG_COLOR); - if (attr) - abc_css_color(bcolor, bcolor + 1, bcolor + 2, attr->value->data, attr->value->len); + attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_BG_COLOR); + if (attr && attr->value->len > 0) + abc_css_color(bcolor, attr->value->data, attr->value->len); attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_COLOR); if (attr) - abc_css_color(fcolor, fcolor + 1, fcolor + 2, attr->value->data, attr->value->len); + abc_css_color(fcolor, attr->value->data, attr->value->len); attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE); if (attr) diff --git a/ui/main.c b/ui/main.c index a0a64af..50a81fa 100644 --- a/ui/main.c +++ b/ui/main.c @@ -50,7 +50,7 @@ static gboolean render(GtkGLArea* self, GdkGLContext* context, gpointer user_dat glClearColor(1.0, 1.0, 1.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); - int ret = abc_layout_root(NULL, root, width, height); + int ret = abc_layout_root(ctx, root, width, height); ret = abc_render_root(ctx, root, width, height); @@ -88,32 +88,25 @@ static int __do_button_move(abc_ctx_t* ctx, int x, int y) gdk_window_set_cursor(window, cursor); g_object_unref(cursor); + abc_css_clear(prev, ABC_CSS_LINK, ABC_CSS_ACTIVE); if (prev->visited) - prev->css_pse_type = ABC_CSS_VISITED; + abc_css_active(prev, ABC_CSS_VISITED); else - prev->css_pse_type = ABC_CSS_LINK; - - abc_css_active(prev); + abc_css_active(prev, ABC_CSS_LINK); prev->mouse_down_x = -1; prev->mouse_down_y = -1; prev->mouse_move_x = -1; prev->mouse_move_y = -1; - if (ABC_HTML == prev->type) - scf_logw("prev: %p mouse down_x: %d, down_y: %d, move_x: %d, move_y: %d\n", prev, - prev->mouse_down_x, - prev->mouse_down_y, - prev->mouse_move_x, - prev->mouse_move_y); - + prev->css_use = 0; prev->clicked = 0; ret = 1; } if (obj) { - scf_logd("obj: %s, type: %d, x: %d, y: %d, w: %d, h: %d, event x: %d, y: %d\n", - obj->keys[0], obj->type, obj->x, obj->y, obj->w, obj->h, x, y); + scf_logi("obj: %p, type: %d, x: %d, y: %d, w: %d, h: %d, event x: %d, y: %d\n", + obj, obj->type, obj->x, obj->y, obj->w, obj->h, x, y); switch (obj->type) { @@ -153,18 +146,19 @@ static int __do_button_move(abc_ctx_t* ctx, int x, int y) break; }; - if (ABC_HTML == obj->type) + if (ABC_HTML_IMG == obj->type) scf_logw("obj: %p, mouse down_x: %d, down_y: %d, move_x: %d, move_y: %d\n", obj, obj->mouse_down_x, obj->mouse_down_y, obj->mouse_move_x, obj->mouse_move_y); - obj->css_pse_type = ABC_CSS_HOVER; + abc_css_clear(obj, ABC_CSS_LINK, ABC_CSS_ACTIVE); - ret |= abc_css_active(obj); + ret |= abc_css_active(obj, ABC_CSS_HOVER); ctx->current->current = obj; + obj->css_use = 0; } return ret; @@ -220,10 +214,9 @@ static int __do_button_release(abc_ctx_t* ctx, int x, int y) obj->mouse_move_x = -1; obj->mouse_move_y = -1; - obj->visited = 1; - obj->css_pse_type = ABC_CSS_VISITED; - - abc_css_active(obj); + abc_css_clear (obj, ABC_CSS_LINK, ABC_CSS_ACTIVE); + abc_css_active(obj, ABC_CSS_VISITED); + obj->css_use = 0; scf_logd("obj: %s, x: %d, y: %d, w: %d, h: %d, event x: %d, y: %d\n", obj->keys[0], obj->x, obj->y, obj->w, obj->h, x, y); @@ -391,9 +384,10 @@ static gboolean button_press_event(GtkWidget* self, GdkEventButton* event, gpoin obj->mouse_move_x, obj->mouse_move_y); - obj->css_pse_type = ABC_CSS_ACTIVE; + abc_css_clear (obj, ABC_CSS_LINK, ABC_CSS_ACTIVE); + abc_css_active(obj, ABC_CSS_ACTIVE); + obj->css_use = 0; - abc_css_active(obj); gtk_gl_area_queue_render(ctx->gl_area); } }