--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>菜鸟教程(runoob.com)</title>
+<style>
+img
+{
+ opacity:0.4;
+ filter:alpha(opacity=40); /* 适用 IE8 及其更早版本 */
+}
+img:hover
+{
+ opacity:1.0;
+ filter:alpha(opacity=100); /* 适用 IE8 及其更早版本 */
+}
+</style>
+</head>
+<body>
+
+<h1>图片透明度</h1>
+<p>opacity 属性通常与 :hover 选择器一起使用,在鼠标移动到图片上后改变图片的透明度:</p>
+<img src="klematis.jpg" width="150" height="113" alt="klematis">
+<img src="klematis2.jpg" width="150" height="113" alt="klematis">
+
+<p><b>注意:</b>在 IE 中必须声明 <!DOCTYPE> 才能保证 :hover 选择器能够有效。</p>
+</body>
+</html>
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;}
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;
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;
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;
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);
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 ';':
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 ':':
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;
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 ':':
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;
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;
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;
return ret;
while (1) {
- c = __io_pop_char(&css->io);
+ c = __io_pop_char(&style->io);
if (!c) {
ret = -1;
break;
}
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;
|| '.' == 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;
}
};
}
-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;
}
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;
};
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);
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;
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);
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;
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);
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:
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;
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--) {
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;
}
}
}
- 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)
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);
+ }
}
}
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;
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);
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;
}
}
-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;
}
}
}
-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;
} 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));
static int __css_border(abc_obj_t* obj, int width, int type)
{
- double color[3];
+ double color[4];
int style;
int w = 0;
{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;
}
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;
}
}
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;
} 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;
}
// 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};
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};
#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}, \
{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()
{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[] =
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[] =
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[] =
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[] =
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[] =
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[] =
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[] =
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[] =
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[] =
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[] =
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},
};
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},
};
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},
};
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},
};
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[] =
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[] =
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[] =
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[] =
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));
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]);
if (html->file)
scf_string_free(html->file);
+ if (html->css)
+ abc_css_free(html->css);
+
if (html->js)
scf_parse_close(html->js);
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:
case ABC_HTML_AUDIO:
if (__html_add_controls(obj) < 0)
return -1;
-
default:
- if (abc_css_use(html, obj) < 0)
- return -1;
break;
};
abc_obj_t* root;
abc_obj_t* current;
- abc_obj_t* css;
+
+ abc_css_t* css;
abc_io_t io;
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);
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);
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;
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);
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) {
}
}
+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;
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;
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;
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;
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");
}
scf_list_t* l;
abc_attr_t* attr;
abc_obj_t* child;
+ css_rule_t* css;
if (!obj)
return;
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))) {
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
{
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,
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,
// 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
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
{
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;
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;
uint32_t clicked:1;
uint32_t visited:1;
+ uint32_t css_use:1;
+
uint32_t w_set:1;
uint32_t h_set:1;
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);
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
#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;
printf("\n");
+ abc_css_recursive_use(html, html->root);
+
if (html->root)
abc_obj_print(html->root);
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
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);
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);
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;
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;
}
}
}
- 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);
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);
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);
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;
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]);
#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;
}
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)
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)
{
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;
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);
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;
--- /dev/null
+#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;
+}
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
{
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;
#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;
[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;
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) \
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;
|| 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;
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;
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;
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;
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
#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;
#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;
}
#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;
#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;
#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;
#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;
#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;
}
#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;
#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;
#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;
#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;
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;
return n;
w = tmp.x_bearing + tmp.x_advance;
+ w = (w + size - 1) / size * size;
if (x + w <= width) {
x = 0;
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;
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;
int h = 0;
if (!obj->av_filter) {
-
int ret = __av_filter_init(obj);
if (ret < 0) {
scf_loge("open video failed\n");
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;
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);
#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;
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;
}
#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;
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;
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);
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);
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;
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;
#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;
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;
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);
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);
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);
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;
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);
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);
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) {
#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;
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;
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)
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;
#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;
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;
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);
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);
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;
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)
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);
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)
{
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;
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);
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);
}
}