From: yu.dongliang <18588496441@163.com> Date: Sat, 16 May 2026 11:14:58 +0000 (+0800) Subject: html: use an array to save label's attrs, now get it O(1), X-Git-Url: http://baseworks.info/?a=commitdiff_plain;h=ef6df300098e0612d1e73cfa185a9306d43c5146;p=abc.git html: use an array to save label's attrs, now get it O(1), css : support complex pse class (element) chain for HTML object. --- diff --git a/examples/overflow.html b/examples/overflow.html new file mode 100644 index 0000000..89fb8f7 --- /dev/null +++ b/examples/overflow.html @@ -0,0 +1,25 @@ + + + + + + + + + +
+

这里的文本内容会溢出元素框。

+

这里的文本内容会溢出元素框。

+

这里的文本内容会溢出元素框。

+
+ + + diff --git a/examples/p_pse_class.html b/examples/p_pse_class.html index 2e1e5ea..7e13772 100644 --- a/examples/p_pse_class.html +++ b/examples/p_pse_class.html @@ -12,12 +12,20 @@ p:first-child b { color:red; } + +.violet:first-child b +{ + color:violet; +} +

I am a strong man. I am a strong man.

+

I am a strong man. I am a strong man.

I am a strong man. I am a strong man.

+

注意: 当 :first-child 作用于 IE8 以及更早版本的浏览器, !DOCTYPE 必须已经定义.

diff --git a/examples/position.html b/examples/position.html new file mode 100644 index 0000000..59f698f --- /dev/null +++ b/examples/position.html @@ -0,0 +1,28 @@ + + + + + + + + +

这是位于正常位置的标题

+

这个标题相对于其正常位置向左移动

+

这个标题相对于其正常位置向右移动

+

相对定位会按照元素的原始位置对该元素进行移动。

+

样式 "left:-20px" 从元素的原始左侧位置减去 20 像素。

+

样式 "left:20px" 向元素的原始左侧位置增加 20 像素。

+ + diff --git a/html/abc_css.c b/html/abc_css.c index cb71c3d..25aeac1 100644 --- a/html/abc_css.c +++ b/html/abc_css.c @@ -187,6 +187,7 @@ static int __css_parse_attr2(abc_obj_t* css, abc_obj_t* obj, const html_attr_t* int i; int j; + int k; if (attrs && n_attrs > 0) { for (i = 0; i < n_attrs; i++) { @@ -202,22 +203,16 @@ static int __css_parse_attr2(abc_obj_t* css, abc_obj_t* obj, const html_attr_t* return -EINVAL; found: - for (l = scf_list_head(&obj->attrs); l != scf_list_sentinel(&obj->attrs); l = scf_list_next(l)) { - attr = scf_list_data(l, abc_obj_t, list); - - for (j = 0; attr->keys[j]; j++) { - if (!__html_strcmp(attr->keys[j], key->data)) - break; - } - } + k = attrs[i].type; + assert(k >= ABC_HTML_ATTR_ID && k < ABC_HTML_CSS_NB); - if (l == scf_list_sentinel(&obj->attrs)) { + attr = obj->attrs[k - ABC_HTML_ATTR_ID]; + if (!attr) { int ret = __html_add_attr(obj, attrs[i].type, attrs[i].names, attrs[i].value, attrs[i].flags); if (ret < 0) return ret; - l = scf_list_tail(&obj->attrs); - attr = scf_list_data(l, abc_obj_t, list); + attr = obj->attrs[k - ABC_HTML_ATTR_ID]; } scf_string_free(key); @@ -738,91 +733,74 @@ static void __css_set_attr(abc_obj_t* obj, abc_obj_t* attr) }; } -static void __css_set_pse(abc_obj_t* obj, abc_obj_t* pse, int colon) +static int __css_set_pse_dynamic(abc_obj_t* obj, abc_obj_t* pse) { - scf_string_t* s; - scf_list_t* l; - abc_obj_t* attr; - abc_obj_t* attr2; - abc_obj_t* pse2; - - if (scf_list_empty(&pse->attrs)) - return; + scf_list_t* l; + abc_obj_t* pse2; - if (colon > 0 && ':' == pse->text->data[colon - 1]) - colon--; + 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); - char* key = pse->text->data + colon; - int len = pse->text->len - colon; + if (pse2->type == pse->type + && pse2->text->len == pse->text->len + && !__html_strcmp(pse2->text->data, pse->text->data)) + break; + } - pse2 = abc_obj_get_attr2(obj, key, len); - if (!pse2) { + if (l == scf_list_sentinel(&obj->css_pse_rules)) + { pse2 = abc_obj_alloc(pse->file, pse->line, pse->pos, pse->type); if (!pse2) - return; + 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; - } - - s = scf_string_clone(pse->text); - if (!s) - return; - - if (pse2->text) - scf_string_free(pse2->text); - - pse2->text = s; - - for (l = scf_list_head(&pse->attrs); l != scf_list_sentinel(&pse->attrs); l = scf_list_next(l)) { - attr = scf_list_data(l, abc_obj_t, list); - - if (!attr->value || 0 == attr->value->len) - continue; - attr2 = abc_obj_alloc(attr->file, attr->line, attr->pos, attr->type); - if (!attr2) - return; + scf_list_add_tail(&obj->css_pse_rules, &pse2->list); + } - attr2->value = scf_string_clone(attr->value); - if (!attr2->value) { - abc_obj_free(attr2); - return; - } + int ret = abc_obj_copy_attrs(pse2, pse); + if (ret < 0) + return ret; - attr2->keys = attr->keys; - attr2->flags = attr->flags; + switch (pse->css_pse_type) { + case ABC_CSS_LINK: + abc_obj_set_css(obj, pse); + break; + default: + break; + }; - scf_list_add_tail(&pse2->attrs, &attr2->list); + scf_slist_clear(pse2->css_pse_chain, pse_link_t, next, free); - switch (pse->css_pse_type) - { - case ABC_CSS_FIRST_CHILD: - case ABC_CSS_LINK: - __css_set_attr(obj, attr); - break; - default: - break; - }; - } + 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) { - scf_list_t* l; - abc_obj_t* s; - abc_obj_t* d; + abc_obj_t* s; + abc_obj_t* d; + int i; - for (l = scf_list_head(&src->attrs); l != scf_list_sentinel(&src->attrs); ) { - s = scf_list_data(l, abc_obj_t, list); - l = scf_list_next(l); + for (i = 0; i < sizeof(src->attrs) / sizeof(src->attrs[0]); i++) { + s = src->attrs[i]; - d = abc_obj_get_attr(dst, s->type); + if (!s || !s->value || 0 == s->value->len) + continue; + + d = dst->attrs[i]; if (d) SCF_XCHG(d->value, s->value); else { - scf_list_del(&s->list); - scf_list_add_tail(&dst->attrs, &s->list); + dst->attrs[i] = s; + src->attrs[i] = NULL; } } } @@ -941,6 +919,7 @@ static abc_obj_t* __css_select_by_key(abc_obj_t* css, abc_obj_t* current, scf_ve scf_list_t* l; abc_obj_t* tmp; abc_obj_t* pse; + pse_link_t* pseLink; assert(next >= 0 && next < vec->size); @@ -1020,6 +999,17 @@ static abc_obj_t* __css_select_by_key(abc_obj_t* css, abc_obj_t* current, scf_ve 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; @@ -1037,6 +1027,8 @@ static abc_obj_t* __css_select_by_attr(abc_obj_t* css, abc_obj_t* current, scf_v scf_list_t* l; abc_obj_t* tmp; abc_obj_t* attr; + abc_obj_t* pse; + pse_link_t* pseLink; assert(next >= 0 && next < vec->size); @@ -1100,6 +1092,45 @@ static abc_obj_t* __css_select_by_attr(abc_obj_t* css, abc_obj_t* current, scf_v current = tmp; break; + + case ':': + assert(next - 1 >= 0 && next - 1 < vec->size); + + scf_logd("current: %s, key: %.*s, j: %d, next: %s\n", current->keys[0], len, key, j, css->text->data + j); + + k = (intptr_t) vec->data[next - 1]; + if (k <= j) + return NULL; + + current = __css_select_by_attr(css, current, vec, next - 1, type, key, len); + if (!current) + return NULL; + + pse = abc_obj_get_attr2(current, css->text->data + j, k - j); + 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; default: attr = abc_obj_get_attr(current, type); @@ -1116,7 +1147,6 @@ static int __css_use_complex(abc_obj_t* css, abc_obj_t* obj) scf_vector_t* vec; abc_obj_t* current = obj; - int colon = -1; int c; int i; int j = css->text->len; @@ -1130,6 +1160,7 @@ static int __css_use_complex(abc_obj_t* css, abc_obj_t* obj) goto end; css->css_pse_type = 0; + scf_slist_clear(css->css_pse_chain, pse_link_t, next, free); for (i = css->text->len - 1; i >= 0; i--) { c = css->text->data[i]; @@ -1154,9 +1185,6 @@ static int __css_use_complex(abc_obj_t* css, abc_obj_t* obj) break; case ':': - if (colon < 0) - colon = i; - if (i > 0 && ':' == css->text->data[i - 1]) { if (j < css->text->len) { @@ -1194,13 +1222,14 @@ static int __css_use_complex(abc_obj_t* css, abc_obj_t* obj) } } - if (colon < 0) + if (css->css_pse_type < ABC_CSS_PSE_STATIC) abc_obj_set_css(obj, css); else - __css_set_pse(obj, css, colon); + __css_set_pse_dynamic(obj, css); ret = 0; end: + scf_slist_clear(css->css_pse_chain, pse_link_t, next, free); scf_vector_free(vec); return ret; } @@ -1264,15 +1293,16 @@ int abc_css_use(abc_html_t* html, abc_obj_t* obj) if (ret < 0 && EOF != ret) return ret; - for (l = scf_list_head(&css->attrs); l != scf_list_sentinel(&css->attrs); ) { - attr = scf_list_data(l, abc_obj_t, list); - l = scf_list_next(l); + int i; + for (i = 0; i < sizeof(css->attrs) / sizeof(css->attrs[0]); i++) { + attr = css->attrs[i]; + if (!attr) + continue; __css_set_attr(obj, attr); - scf_list_del(&attr->list); abc_obj_free(attr); - attr = NULL; + css->attrs[i] = NULL; } } @@ -1280,13 +1310,41 @@ int abc_css_use(abc_html_t* html, abc_obj_t* obj) } void abc_obj_set_css(abc_obj_t* obj, abc_obj_t* css) +{ + abc_obj_t* attr; + int i; + + for (i = 0; i < sizeof(css->attrs) / sizeof(css->attrs[0]); i++) { + attr = css->attrs[i]; + + if (attr) + __css_set_attr(obj, attr); + } +} + +int abc_css_active(abc_obj_t* obj) { scf_list_t* l; - abc_obj_t* attr; + abc_obj_t* css; + pse_link_t* pseLink; - for (l = scf_list_head(&css->attrs); l != scf_list_sentinel(&css->attrs); l = scf_list_next(l)) { - attr = scf_list_data(l, abc_obj_t, list); + 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); - __css_set_attr(obj, attr); + pseLink = css->css_pse_chain; + while (pseLink) { + if (pseLink->obj->css_pse_type != pseLink->pse_type) + break; + + pseLink = pseLink->next; + } + + if (!pseLink) { + abc_obj_set_css(obj, css); + n++; + } } + + return n; } diff --git a/html/abc_css_border.c b/html/abc_css_border.c index adfc471..47b8f9a 100644 --- a/html/abc_css_border.c +++ b/html/abc_css_border.c @@ -38,7 +38,7 @@ int abc_css_border(double* r, double* g, double* b, int* width, int* type, abc_o *r = 0.0; *g = 0.0; *b = 0.0; - *width = 1; + *width = 0; *type = ABC_BORDER_SOLID; const uint8_t* p = NULL; @@ -141,15 +141,15 @@ int abc_css_margin(abc_obj_t* obj) double g = 0.0; double b = 0.0; - abc_obj_t* attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_MARGIN); + abc_obj_t* attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_MARGIN); if (attr) margin = atoi(attr->value->data); - attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_BORDER); + attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_BORDER); if (attr) abc_css_border(&r, &g, &b, &border, &type, obj, attr->value->data); - attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_PADDING); + attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_PADDING); if (attr) padding = atoi(attr->value->data); diff --git a/html/abc_css_length.c b/html/abc_css_length.c index 45d2c7e..2a4f479 100644 --- a/html/abc_css_length.c +++ b/html/abc_css_length.c @@ -7,6 +7,8 @@ int abc_css_length(abc_obj_t* obj, const uint8_t* str, int len) int x = 0; double value = 0.0; + double decimal = 0.1; + int neg = 0; int dot = 0; int percent = 0; int prev = 0; @@ -15,8 +17,10 @@ int abc_css_length(abc_obj_t* obj, const uint8_t* str, int len) do { c = *str; - if ('.' == c) - dot = 10; + if ('-' == c) + neg++; + else if ('.' == c) + dot++; else if ('%' == c) percent++; @@ -26,9 +30,9 @@ int abc_css_length(abc_obj_t* obj, const uint8_t* str, int len) } else if ('0' <= c && '9' >= c) { - if (dot > 0) { - value += (c - '0') / (double)dot; - dot *= 10; + if (dot) { + value += (c - '0') * decimal; + decimal *= 0.1; } else { value *= 10.0; value += c - '0'; @@ -39,12 +43,16 @@ int abc_css_length(abc_obj_t* obj, const uint8_t* str, int len) if (' ' == prev || '\t' == prev || '\r' == prev || '\n' == prev) goto next; + if (neg) + value = -value; + if (percent) x = value * 0.01 * len; else if (unit) { // for other css units, ignore x = value; - } + } else + x = value; unit = NULL; value = 0.0; diff --git a/html/abc_css_position.c b/html/abc_css_position.c index 52cb844..bd82a81 100644 --- a/html/abc_css_position.c +++ b/html/abc_css_position.c @@ -35,7 +35,7 @@ static void __css_pos_value(float* value, const char* name, size_t name_len) } } -int abc_css_position(float* x, float* y, float w, float h, abc_obj_t* obj, const uint8_t* str) +int abc_css_bg_position(float* x, float* y, float w, float h, abc_obj_t* obj, const uint8_t* str) { *x = 0.5 - w / 2; *y = 0.5 - h / 2; @@ -118,3 +118,20 @@ next: return 0; } + +int abc_css_position(const uint8_t* str) +{ + if (!__html_strcmp(str, "relative")) + return ABC_POSITION_RELATIVE; + + else if (!__html_strcmp(str, "absolute")) + return ABC_POSITION_ABSOLUTE; + + else if (!__html_strcmp(str, "fixed")) + return ABC_POSITION_FIXED; + + else if (!__html_strcmp(str, "sticky")) + return ABC_POSITION_STICKY; + + return ABC_POSITION_STATIC; +} diff --git a/html/abc_html.c b/html/abc_html.c index f2f2715..bd87a4f 100644 --- a/html/abc_html.c +++ b/html/abc_html.c @@ -11,6 +11,14 @@ static char* margin_keys[] = {"margin", "外边距", NULL}; static char* border_keys[] = {"border", "边框", NULL}; static char* padding_keys[] = {"padding", "内边距", NULL}; +static char* overflow_keys[] = {"overflow", NULL}; + +static char* position_keys[] = {"position", "定位", NULL}; +static char* top_keys[] = {"top", "上", NULL}; +static char* bottom_keys[] = {"bottom", "下", NULL}; +static char* left_keys[] = {"left", "å·¦", NULL}; +static char* right_keys[] = {"right", "右", NULL}; + static char* font_keys[] = {"font", "字体", NULL}; static char* font_size_keys[] = {"font-size", "字号", NULL}; static char* font_color_keys[] = {"font-color", "字体颜色", "color", "颜色", NULL}; @@ -141,8 +149,16 @@ static html_attr_t body_attrs[] = {border_keys, #border, ABC_HTML_ATTR_BORDER, ABC_HTML_FLAG_SHOW}, \ {padding_keys, #padding, ABC_HTML_ATTR_PADDING, ABC_HTML_FLAG_SHOW}, \ \ - {width_keys, "", ABC_HTML_ATTR_WIDTH, ABC_HTML_FLAG_SHOW}, \ - {height_keys, "", ABC_HTML_ATTR_HEIGHT, ABC_HTML_FLAG_SHOW}, + {overflow_keys, "", ABC_HTML_ATTR_OVERFLOW, ABC_HTML_FLAG_SHOW}, \ + \ + {position_keys, "", ABC_HTML_ATTR_POSITION, ABC_HTML_FLAG_SHOW}, \ + {top_keys, "", ABC_HTML_ATTR_TOP, ABC_HTML_FLAG_SHOW}, \ + {bottom_keys, "", ABC_HTML_ATTR_BOTTOM, ABC_HTML_FLAG_SHOW}, \ + {left_keys, "", ABC_HTML_ATTR_LEFT, ABC_HTML_FLAG_SHOW}, \ + {right_keys, "", ABC_HTML_ATTR_RIGHT, ABC_HTML_FLAG_SHOW}, \ + \ + {width_keys, "", ABC_HTML_ATTR_WIDTH, ABC_HTML_FLAG_SHOW}, \ + {height_keys, "", ABC_HTML_ATTR_HEIGHT, ABC_HTML_FLAG_SHOW}, #define ABC_CSS_SELECTOR() \ {style_keys, "", ABC_HTML_ATTR_STYLE, ABC_HTML_FLAG_SHOW}, \ @@ -176,6 +192,16 @@ static html_attr_t body_attrs[] = ABC_CSS_TEXT(left, ) }; +static html_attr_t div_attrs[] = +{ + ABC_CSS_BOX(2px, , 2px) + ABC_CSS_SELECTOR() + ABC_CSS_BACK_GROUND() + + ABC_CSS_FONT(SimSong, 16, black, ) + ABC_CSS_TEXT(left, ) +}; + static html_attr_t h1_attrs[] = { ABC_CSS_BOX(2px, , 2px) @@ -441,7 +467,7 @@ static html_label_t html_labels[] = {head_keys, ABC_HTML_HEAD, 0, NULL, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW}, {title_keys, ABC_HTML_TITLE, 0, NULL, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW}, {body_keys, ABC_HTML_BODY, abc_number_of(body_attrs), body_attrs, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW}, - {div_keys, ABC_HTML_DIV, abc_number_of(body_attrs), body_attrs, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW}, + {div_keys, ABC_HTML_DIV, abc_number_of(div_attrs), div_attrs, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW}, {h1_keys, ABC_HTML_H1, abc_number_of(h1_attrs), h1_attrs, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW}, {h2_keys, ABC_HTML_H2, abc_number_of(h2_attrs), h2_attrs, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW}, @@ -530,6 +556,9 @@ html_label_t* __html_find_label2(const int type) int __html_add_attr(abc_obj_t* obj, int type, char** names, const char* value, int flags) { + if (type < ABC_HTML_ATTR_ID || type >= ABC_HTML_CSS_NB) + return -EINVAL; + abc_obj_t* attr = abc_obj_alloc(NULL, 0, 0, type); if (!attr) return -ENOMEM; @@ -544,7 +573,11 @@ int __html_add_attr(abc_obj_t* obj, int type, char** names, const char* value, i attr->flags = flags; - scf_list_add_tail(&obj->attrs, &attr->list); + int i = type - ABC_HTML_ATTR_ID; + if (obj->attrs[i]) + abc_obj_free(obj->attrs[i]); + + obj->attrs[i] = attr; return 0; } @@ -597,8 +630,10 @@ static int __html_load_attrs(abc_obj_t* obj, html_attr_t* attrs, int n_attrs) } else if (obj->parent) { - for (l = scf_list_head(&obj->parent->attrs); l != scf_list_sentinel(&obj->parent->attrs); l = scf_list_next(l)) { - attr = scf_list_data(l, abc_obj_t, list); + for (i = 0; i < sizeof(obj->parent->attrs) / sizeof(obj->parent->attrs[0]); i++) { + attr = obj->parent->attrs[i]; + if (!attr) + continue; ret = __html_add_attr(obj, attr->type, attr->keys, attr->value->data, 0); if (ret < 0) @@ -1043,22 +1078,23 @@ static int __html_parse_attr2(abc_html_t* html, abc_obj_t* obj, const html_attr_ free(c); c = NULL; - scf_list_t* l; abc_obj_t* attr; + int i; + int j; - for (l = scf_list_head(&obj->attrs); l != scf_list_sentinel(&obj->attrs); l = scf_list_next(l)) { - attr = scf_list_data(l, abc_obj_t, list); - - int j; - for (j = 0; attr->keys[j]; j++) { + for (i = 0; i < sizeof(obj->attrs) / sizeof(obj->attrs[0]); i++) { + attr = obj->attrs[i]; + if (!attr) + continue; + for (j = 0; attr->keys[j]; j++) + { if (!__html_strcmp(attr->keys[j], key->data)) goto found; } } - if (l == scf_list_sentinel(&obj->attrs)) { - + if (i >= sizeof(obj->attrs) / sizeof(obj->attrs[0])) { scf_loge("invalid HTML attribute '%s' in file: %s, line: %d\n", key->data, html->file->data, html->n_lines); scf_string_free(key); return -1; diff --git a/html/abc_html.h b/html/abc_html.h index 6bfb8f3..617cff4 100644 --- a/html/abc_html.h +++ b/html/abc_html.h @@ -53,10 +53,11 @@ 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_use (abc_html_t* html, abc_obj_t* obj); +int abc_css_active(abc_obj_t* obj); -int abc_css_color (double* r, double* g, double* b, const uint8_t* str); -int abc_css_position(float* x, float* y, float w, float h, abc_obj_t* obj, const uint8_t* str); +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); int abc_css_border(double* r, double* g, double* b, int* width, int* type, abc_obj_t* obj, const uint8_t* str); int abc_css_margin(abc_obj_t* obj); int abc_css_length(abc_obj_t* obj, const uint8_t* str, int len); @@ -64,4 +65,6 @@ int abc_css_length(abc_obj_t* obj, const uint8_t* str, int len); int abc_css_width (abc_obj_t* obj, int width, int margin); int abc_css_height(abc_obj_t* obj, int height, int margin); +int abc_css_position(const uint8_t* str); + #endif diff --git a/html/abc_obj.c b/html/abc_obj.c index 91c39d2..b455357 100644 --- a/html/abc_obj.c +++ b/html/abc_obj.c @@ -16,8 +16,8 @@ abc_obj_t* abc_obj_alloc(scf_string_t* file, int line, int pos, int type) } scf_list_init(&obj->list); - scf_list_init(&obj->attrs); scf_list_init(&obj->childs); + scf_list_init(&obj->css_pse_rules); obj->type = type; @@ -56,8 +56,9 @@ void abc_obj_free(abc_obj_t* obj) abc_filter_close(obj->av_filter, 0); #endif - scf_list_clear(&obj->attrs, abc_obj_t, list, abc_obj_free); - scf_list_clear(&obj->childs, abc_obj_t, list, abc_obj_free); + 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); free(obj); } @@ -119,12 +120,14 @@ 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) { - scf_list_t* l; - abc_obj_t* attr; - abc_obj_t* copy; + abc_obj_t* attr; + abc_obj_t* copy; + int i; - for (l = scf_list_head(&src->attrs); l != scf_list_sentinel(&src->attrs); l = scf_list_next(l)) { - attr = scf_list_data(l, abc_obj_t, list); + for (i = 0; i < sizeof(src->attrs) / sizeof(src->attrs[0]); i++) { + attr = src->attrs[i]; + if (!attr) + continue; copy = abc_obj_alloc(attr->file, attr->line, attr->pos, attr->type); if (!copy) @@ -139,7 +142,10 @@ int abc_obj_copy_attrs(abc_obj_t* dst, abc_obj_t* src) copy->keys = attr->keys; copy->flags = attr->flags; - scf_list_add_tail(&dst->attrs, ©->list); + if (dst->attrs[i]) + abc_obj_free(dst->attrs[i]); + + dst->attrs[i] = copy; } return 0; @@ -148,70 +154,94 @@ int abc_obj_copy_attrs(abc_obj_t* dst, abc_obj_t* src) int abc_obj_set_attr(abc_obj_t* obj, int key, const char* value, size_t len) { scf_string_t* s; - scf_list_t* l; abc_obj_t* attr; - for (l = scf_list_head(&obj->attrs); l != scf_list_sentinel(&obj->attrs); l = scf_list_next(l)) { - attr = scf_list_data(l, abc_obj_t, list); + if (key < ABC_HTML_ATTR_ID || key >= ABC_HTML_CSS_NB) + return -EINVAL; - if (attr->type == key) { - s = scf_string_cstr_len(value, len); - if (s) { - scf_string_free(attr->value); - attr->value = s; - return 0; - } - return -ENOMEM; - } - } + attr = obj->attrs[key - ABC_HTML_ATTR_ID]; + if (!attr) + return -EINVAL; + + s = scf_string_cstr_len(value, len); + if (!s) + return -ENOMEM; - return -EINVAL; + scf_string_free(attr->value); + attr->value = s; + return 0; } abc_obj_t* abc_obj_get_attr2(abc_obj_t* obj, const char* key, int len) { - scf_list_t* l; - abc_obj_t* attr; + abc_obj_t* attr; + int i; - for (l = scf_list_head(&obj->attrs); l != scf_list_sentinel(&obj->attrs); l = scf_list_next(l)) { - attr = scf_list_data(l, abc_obj_t, list); + for (i = 0; i < sizeof(obj->attrs) / sizeof(obj->attrs[0]); i++) { + attr = obj->attrs[i]; - if (!abc_obj_cmp_keys(attr, key, len)) + if (attr && !abc_obj_cmp_keys(attr, key, len)) return attr; } return NULL; } -abc_obj_t* abc_obj_get_attr(abc_obj_t* obj, int key) +abc_obj_t* abc_obj_find_attr(abc_obj_t* obj, int key) { - scf_list_t* l; - abc_obj_t* attr; + abc_obj_t* attr; - for (l = scf_list_head(&obj->attrs); l != scf_list_sentinel(&obj->attrs); l = scf_list_next(l)) { - attr = scf_list_data(l, abc_obj_t, list); + while (obj) { + attr = abc_obj_get_attr(obj, key); - if (attr->type == key) + if (attr && attr->value && attr->value->len > 0) return attr; + + obj = obj->parent; } return NULL; } -abc_obj_t* abc_obj_find_attr(abc_obj_t* obj, int key) +void abc_css_print(abc_obj_t* obj) { - abc_obj_t* attr; + if (!obj) + return; - while (obj) { - attr = abc_obj_get_attr(obj, key); + if (!(ABC_HTML_FLAG_SHOW & obj->flags)) + return; - if (attr && attr->value && attr->value->len > 0) - return attr; + if (obj->text) + printf("%s ", obj->text->data); + else if (obj->keys) + printf("%s ", obj->keys[0]); - obj = obj->parent; + pse_link_t* pseLink; + abc_obj_t* attr; + int i; + + printf("{\n"); + + for (i = 0; i < sizeof(obj->attrs) / sizeof(obj->attrs[0]); i++) { + attr = obj->attrs[i]; + + if (!attr || !attr->value || 0 == attr->value->len) + continue; + + if (ABC_HTML_FLAG_SHOW & attr->flags) + printf(" %s: %s;\n", attr->keys[0], attr->value->data); } - return NULL; + 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"); } void abc_obj_print(abc_obj_t* obj) @@ -232,8 +262,11 @@ void abc_obj_print(abc_obj_t* obj) } else if (obj->keys) printf("<%s", obj->keys[0]); - for (l = scf_list_head(&obj->attrs); l != scf_list_sentinel(&obj->attrs); l = scf_list_next(l)) { - attr = scf_list_data(l, abc_obj_t, list); + int i; + for (i = 0; i < sizeof(obj->attrs) / sizeof(obj->attrs[0]); i++) { + attr = obj->attrs[i]; + if (!attr) + continue; if (ABC_HTML_FLAG_SHOW & attr->flags) abc_obj_print(attr); @@ -252,7 +285,27 @@ void abc_obj_print(abc_obj_t* 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_obj_print(child); + 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; + }; + } + + for (l = scf_list_head(&obj->css_pse_rules); l != scf_list_sentinel(&obj->css_pse_rules); l = scf_list_next(l)) { + child = scf_list_data(l, abc_obj_t, list); + + abc_css_print(child); } if (ABC_HTML_FLAG_CLOSE == (obj->flags & (ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SINGLE))) { @@ -306,8 +359,11 @@ static int __abc_obj_to_string(abc_obj_t* obj, scf_string_t* s) return ret; } - for (l = scf_list_head(&obj->attrs); l != scf_list_sentinel(&obj->attrs); l = scf_list_next(l)) { - attr = scf_list_data(l, abc_obj_t, list); + int i; + for (i = 0; i < sizeof(obj->attrs) / sizeof(obj->attrs[0]); i++) { + attr = obj->attrs[i]; + if (!attr) + continue; if (ABC_HTML_FLAG_SHOW & attr->flags) { ret = __abc_obj_to_string(attr, s); diff --git a/html/abc_obj.h b/html/abc_obj.h index 85a8b51..c63fb66 100644 --- a/html/abc_obj.h +++ b/html/abc_obj.h @@ -6,8 +6,9 @@ #include"abc_ffmpeg.h" #include"abc_io.h" -typedef struct abc_obj_s abc_obj_t; -typedef struct abc_text_s abc_text_t; +typedef struct abc_obj_s abc_obj_t; +typedef struct abc_text_s abc_text_t; +typedef struct pse_link_s pse_link_t; enum abc_objs { @@ -112,6 +113,14 @@ enum abc_objs ABC_HTML_ATTR_BORDER, ABC_HTML_ATTR_PADDING, + ABC_HTML_ATTR_POSITION, + ABC_HTML_ATTR_TOP, + ABC_HTML_ATTR_BOTTOM, + ABC_HTML_ATTR_LEFT, + ABC_HTML_ATTR_RIGHT, + + ABC_HTML_ATTR_OVERFLOW, + ABC_HTML_ATTR_XMLNS, ABC_HTML_ATTR_XMLANG, ABC_HTML_ATTR_LANG, @@ -124,7 +133,7 @@ enum abc_objs ABC_HTML_ATTR_CONTROLS, - // css objects + // css attrs ABC_CSS_LIST_STYLE, ABC_CSS_LIST_STYLE_TYPE, ABC_CSS_LIST_STYLE_IMAGE, @@ -132,16 +141,19 @@ enum abc_objs ABC_CSS_BORDER_COLLAPSE, - // css pse class or pse element, first status onload + // css pse class (element) ABC_CSS_FIRST_CHILD, - ABC_CSS_LINK, - // status after user operations + 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, - // ... new css add here + 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_PSE_CLASS, @@ -149,8 +161,10 @@ enum abc_objs ABC_CSS_COMBINATOR, // css selectors from html attrs above - ABC_CSS_ID = ABC_HTML_ATTR_ID, - ABC_CSS_CLASS = ABC_HTML_ATTR_CLASS, + ABC_CSS_ID = ABC_HTML_ATTR_ID, + ABC_CSS_CLASS = ABC_HTML_ATTR_CLASS, + ABC_CSS_POSITION = ABC_HTML_ATTR_POSITION, + ABC_CSS_OVERFLOW = ABC_HTML_ATTR_OVERFLOW, }; enum abc_border_style @@ -160,6 +174,15 @@ enum abc_border_style ABC_BORDER_DASHED, }; +enum abc_position_style +{ + ABC_POSITION_STATIC, + ABC_POSITION_RELATIVE, + ABC_POSITION_ABSOLUTE, + ABC_POSITION_FIXED, + ABC_POSITION_STICKY, +}; + enum abc_line_style { ABC_LINE_NONE, @@ -179,28 +202,49 @@ struct abc_text_s int h; }; +struct pse_link_s +{ + pse_link_t* next; + + abc_obj_t* obj; + int pse_type; +}; + +#define ABC_HTML_FLAG_OPEN 0 +#define ABC_HTML_FLAG_CLOSE 1 +#define ABC_HTML_FLAG_SINGLE 2 +#define ABC_HTML_FLAG_SHOW 4 + struct abc_obj_s { - scf_list_t list; + int type; + uint32_t flags; - scf_list_t attrs; + char** keys; + scf_string_t* value; + + abc_obj_t* parent; + + scf_list_t list; scf_list_t childs; int n_childs; int index; - abc_obj_t* parent; + abc_obj_t* attrs[ABC_HTML_CSS_NB - ABC_HTML_ATTR_ID]; void* gtk_builder; abc_filter_t* av_filter; abc_avio_t* vout; - int type; + 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; -#define ABC_HTML_FLAG_OPEN 0 -#define ABC_HTML_FLAG_CLOSE 1 -#define ABC_HTML_FLAG_SINGLE 2 -#define ABC_HTML_FLAG_SHOW 4 - uint32_t flags; + pse_link_t* css_pse_chain; + scf_list_t css_pse_rules; + int css_pse_type; int d; // margin + border + padding int w0; @@ -221,16 +265,6 @@ struct abc_obj_s int progress; uint32_t jiffies; // timeout numbers of sys timer - char** keys; - scf_string_t* value; - 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; - - int css_pse_type; scf_string_t* file; // file name int line; // line @@ -260,7 +294,6 @@ 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_obj_t* abc_obj_get_attr2(abc_obj_t* obj, const char* key, int len); -abc_obj_t* abc_obj_get_attr (abc_obj_t* obj, int key); abc_obj_t* abc_obj_find_attr(abc_obj_t* obj, int key); abc_obj_t* abc_obj_find_type(abc_obj_t* root, int type); @@ -269,4 +302,13 @@ scf_string_t* abc_obj_to_string(abc_obj_t* obj); scf_string_t* abc_ol_list_style(abc_obj_t* obj, int num); + +static inline abc_obj_t* abc_obj_get_attr(abc_obj_t* obj, int key) +{ + if (key < ABC_HTML_ATTR_ID || key >= ABC_HTML_CSS_NB) + return NULL; + + return obj->attrs[key - ABC_HTML_ATTR_ID]; +} + #endif diff --git a/ui/Makefile b/ui/Makefile index 0bb821b..78042e2 100644 --- a/ui/Makefile +++ b/ui/Makefile @@ -239,7 +239,7 @@ CFILES += ../js/parse/scf_dfa_label.c CFILES += ../js/parse/scf_dfa_async.c CFILES += ../js/parse/scf_dfa_block.c -CFLAGS += -g -O3 -D_GNU_SOURCE +CFLAGS += -g -D_GNU_SOURCE CFLAGS += -I./ CFLAGS += -I../html CFLAGS += -I../ffmpeg diff --git a/ui/__render_bg_image.c b/ui/__render_bg_image.c index b7735dd..84375ce 100644 --- a/ui/__render_bg_image.c +++ b/ui/__render_bg_image.c @@ -153,7 +153,7 @@ static int __render_draw_bg_image(abc_render_t* render, abc_obj_t* obj, int widt attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_BG_POSITION); if (attr) { - abc_css_position(&x, &y, w, h, obj, attr->value->data); + abc_css_bg_position(&x, &y, w, h, 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); diff --git a/ui/abc_layout.c b/ui/abc_layout.c index a7e7796..3528b78 100644 --- a/ui/abc_layout.c +++ b/ui/abc_layout.c @@ -36,6 +36,9 @@ static abc_layout_pt abc_layouts[ABC_HTML_NB] = [ABC_HTML_DIV] = abc_layout_div, [ABC_CORE_TEXT] = abc_layout_text, + [ABC_HTML_B] = abc_layout_text, + [ABC_HTML_I] = abc_layout_text, + [ABC_HTML_A] = abc_layout_text, [ABC_HTML_H1] = abc_layout_h1, [ABC_HTML_H2] = abc_layout_h1, @@ -47,7 +50,6 @@ static abc_layout_pt abc_layouts[ABC_HTML_NB] = [ABC_HTML_P] = abc_layout_h1, [ABC_HTML_BR] = abc_layout_h1, - [ABC_HTML_A] = abc_layout_h1, [ABC_HTML_IMG] = abc_layout_img, [ABC_HTML_FORM] = abc_layout_form, @@ -73,9 +75,6 @@ static abc_layout_pt abc_layouts[ABC_HTML_NB] = [ABC_HTML_SCRIPT] = abc_layout_empty, [ABC_HTML_STYLE] = abc_layout_empty, [ABC_HTML_LINK] = abc_layout_empty, - - [ABC_HTML_B] = abc_layout_text, - [ABC_HTML_I] = abc_layout_text, }; int abc_layout_obj(abc_layout_t* layout, abc_obj_t* obj, int width, int height) @@ -105,9 +104,52 @@ void abc_css_update_xy(abc_obj_t* root, int dx, int dy) } } -int abc_layout_css(abc_obj_t* root) +#define LAYOUT_POS_FIXED(X, W, SET, L, R) \ + do { \ + if (!obj->SET) { \ + if (L && R) { \ + obj->X = parent->X + L; \ + obj->W = parent->W - L - R; \ + } else if (L) \ + obj->X = parent->X + L; \ + else if (R) \ + obj->X = parent->X + parent->W - R - obj->W; \ + } else if (L) \ + obj->X = parent->X + L; \ + else if (R) \ + obj->X = parent->X + parent->W - R - obj->W; \ + } while (0) + +#define LAYOUT_POS_RELATIVE(X, L, R) \ + do { \ + if (L) \ + obj->X += L; \ + else if (R) \ + obj->X += R; \ + } while (0) + +#define LAYOUT_POS_ABSOLUTE(X, W, L, R) \ + do { \ + abc_obj_t* tmp = parent; \ + while (tmp && ABC_HTML != tmp->type) { \ + abc_obj_t* attr = abc_obj_get_attr(tmp, ABC_HTML_ATTR_POSITION); \ + \ + if (attr && attr->value->len > 0 \ + && __html_strcmp(attr->value->data, "static")) \ + break; \ + tmp = tmp->parent; \ + } \ + if (tmp) { \ + if (L) \ + obj->X = tmp->X + L; \ + else if (R) \ + obj->X = tmp->X + tmp->W - R - obj->W; \ + } \ + } while (0) + +int abc_layout_css(abc_obj_t* obj) { - abc_obj_t* parent = root->parent; + abc_obj_t* parent = obj->parent; abc_obj_t* attr; if (!parent || parent->w <= 0) @@ -123,20 +165,75 @@ int abc_layout_css(abc_obj_t* root) break; }; - attr = abc_obj_get_attr(root, ABC_HTML_ATTR_TEXT_ALIGN); + attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_TEXT_ALIGN); if (attr) { - int x = root->x; + int x = obj->x; if (!__html_strcmp(attr->value->data, "center")) - root->x = parent->x + (parent->w - root->w) / 2 + 4; + obj->x = parent->x + (parent->w - obj->w) / 2 + 4; else if (!__html_strcmp(attr->value->data, "right")) - root->x = parent->x + parent->w - root->w - 8; + obj->x = parent->x + parent->w - obj->w - 8; - abc_css_update_xy(root, root->x - x, 0); + abc_css_update_xy(obj, obj->x - x, 0); } - return 0; + attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_POSITION); + if (!attr || 0 == attr->value->len) + return 0; + + int pos_type = abc_css_position(attr->value->data); + if (ABC_POSITION_STATIC == pos_type) + return 0; + + int top = 0; + int bottom = 0; + int left = 0; + int right = 0; + + attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_TOP); + if (attr) + top = abc_css_length(obj, attr->value->data, obj->h); + + attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_BOTTOM); + if (attr) + bottom = abc_css_length(obj, attr->value->data, obj->h); + + attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_LEFT); + if (attr) + left = abc_css_length(obj, attr->value->data, obj->w); + + attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_RIGHT); + if (attr) + right = abc_css_length(obj, attr->value->data, obj->w); + + int x = obj->x; + int y = obj->y; + + switch (pos_type) + { + case ABC_POSITION_FIXED: + LAYOUT_POS_FIXED(x, w, w_set, left, right); + LAYOUT_POS_FIXED(y, h, h_set, top, bottom); + break; + + case ABC_POSITION_RELATIVE: + scf_logd("top: %d, bottom: %d, left: %d, right: %d, obj->w: %d, parent->w: %d\n", top, bottom, left, right, obj->w, parent->w); + LAYOUT_POS_RELATIVE(x, left, right); + LAYOUT_POS_RELATIVE(y, top, bottom); + break; + + case ABC_POSITION_ABSOLUTE: + LAYOUT_POS_ABSOLUTE(x, w, left, right); + LAYOUT_POS_ABSOLUTE(y, h, top, bottom); + break; + default: + break; + }; + + abc_css_update_xy(obj, obj->x - x, obj->y - y); + + return pos_type; } int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height) @@ -158,6 +255,18 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height) return 0; break; + case ABC_HTML: + root->d = abc_css_margin(root); + root->w = width; + root->h = height; + + root->w0 = width; + root->h0 = height; + + root->w_set = 1; + root->h_set = 1; + break; + case ABC_HTML_BODY: case ABC_HTML_DIV: root->d = abc_css_margin(root); @@ -167,9 +276,6 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height) if (root->w_set) { root->w0 = root->w; root_w = root->w; - } else { -// if (ABC_HTML_BODY != root->type) -// root->w = 0; } if (root->h_set) { @@ -181,6 +287,7 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height) } break; default: + root->d = abc_css_margin(root); break; }; @@ -194,6 +301,9 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height) int X = 0; int Y = 0; + root_w -= root->d * 2; + root_h -= root->d * 2; + for (l = scf_list_head(&root->childs); l != scf_list_sentinel(&root->childs); l = scf_list_next(l)) { child = scf_list_data(l, abc_obj_t, list); @@ -217,6 +327,10 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height) if (ret < 0) return ret; + ret = abc_layout_css(child); + if (ABC_POSITION_FIXED == ret || ABC_POSITION_ABSOLUTE == ret) + break; + x = root->x + root->d; y = child->y + child->h; h = 0; @@ -235,6 +349,10 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height) if (ret < 0) return ret; + ret = abc_layout_css(child); + if (ABC_POSITION_FIXED == ret || ABC_POSITION_ABSOLUTE == ret) + break; + if (ABC_CORE_TEXT == child->type && child->text_splits) { abc_text_t* t = child->text_splits; @@ -256,9 +374,7 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height) x += t->w; } - scf_logd("--- x: %d, y: %d, h: %d ---\n\n", x, y, h); - - } else if (x + child->w < root_w) { + } else if (x + child->w < root->x + root->d + root_w) { if (h < child->h) h = child->h; @@ -273,6 +389,8 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height) if (ret < 0) return ret; + abc_layout_css(child); + h = child->h; x = child->x + child->w; } @@ -304,8 +422,6 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height) int ret = abc_layout_obj(NULL, root, width, height); if (ret < 0) return ret; - - abc_layout_css(root); #if 0 if (root->keys) scf_logw("key: %s, ", root->keys[0]); diff --git a/ui/abc_layout_div.c b/ui/abc_layout_div.c index 3fd9d7c..6de919b 100644 --- a/ui/abc_layout_div.c +++ b/ui/abc_layout_div.c @@ -38,19 +38,14 @@ int abc_layout_div(abc_layout_t* layout, abc_obj_t* obj, int width, int height) surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, height); cr = cairo_create(surface); - w = w / size * size; - - int ret = __layout_text(cr, obj, 0, w, &extents); + int ret = __layout_text(cr, obj, 0, w / size * size, &extents); if (ret < 0) scf_loge("ret: %d\n", ret); - w = extents.width + extents.x_bearing + obj->d * 2; h = extents.height + extents.height / 2 + obj->d * 2; obj->w = obj->w_set ? obj->w0 : w; obj->h = obj->h_set ? obj->h0 : h + obj->h; -// obj->w = (obj->w + 3) & ~0x3; -// obj->h = (obj->h + 3) & ~0x3; scf_logd("%s, w: %d, h: %d, d: %d, x_bearing: %lg, y_bearing: %lg, width: %lg, height: %lg, x_advance: %lg, y_advance: %lg, width: %d, height: %d\n", obj->text->data, obj->w, obj->h, d, diff --git a/ui/abc_layout_h1.c b/ui/abc_layout_h1.c index 981b11e..bcf6f83 100644 --- a/ui/abc_layout_h1.c +++ b/ui/abc_layout_h1.c @@ -45,8 +45,7 @@ int abc_layout_h1(abc_layout_t* layout, abc_obj_t* obj, int width, int height) if (attr) size = atoi(attr->value->data); - cairo_set_font_size (cr, size); - cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); + cairo_set_font_size(cr, size); int d = abc_css_margin(obj); int w_set = abc_css_width (obj, width, d); @@ -86,12 +85,8 @@ int abc_layout_h1(abc_layout_t* layout, abc_obj_t* obj, int width, int height) obj->y_bearing = extents.y_bearing; - w = extents.x_advance + extents.x_bearing + d * 2 + dw; - - obj->w = w; + obj->w = extents.width + d * 2 + dw; obj->h = extents.height + extents.height / 2 + d * 2; -// obj->w = (obj->w + 3) & ~0x3; -// obj->h = (obj->h + 3) & ~0x3; scf_logd("%s, w: %d, h: %d, d: %d, x_bearing: %lg, y_bearing: %lg, width: %lg, height: %lg, x_advance: %lg, y_advance: %lg, width: %d, height: %d\n", obj->text->data, obj->w, obj->h, d, diff --git a/ui/abc_layout_img.c b/ui/abc_layout_img.c index 4e6a814..cab1669 100644 --- a/ui/abc_layout_img.c +++ b/ui/abc_layout_img.c @@ -2,32 +2,9 @@ int abc_layout_img(abc_layout_t* layout, abc_obj_t* obj, int width, int height) { - scf_list_t* l; - abc_obj_t* attr; + obj->w_set = abc_css_width (obj, width, obj->d); + obj->h_set = abc_css_height(obj, height, obj->d); - for (l = scf_list_head(&obj->attrs); l != scf_list_sentinel(&obj->attrs); l = scf_list_next(l)) { - attr = scf_list_data(l, abc_obj_t, list); - - switch (attr->type) { - - case ABC_HTML_ATTR_WIDTH: - obj->w = atoi(attr->value->data); - break; - - case ABC_HTML_ATTR_HEIGHT: - obj->h = atoi(attr->value->data); - break; - default: - break; - }; - } - -// obj->x = 4; -// obj->y = 4; - - obj->w = (obj->w + 3) & ~0x3; - obj->h = (obj->h + 3) & ~0x3; - - scf_logd("%s, w: %d, h: %d\n", obj->text->data, obj->w, obj->h); + scf_logi("w: %d, h: %d, d: %d\n", obj->w, obj->h, obj->d); return 0; } diff --git a/ui/abc_layout_text.c b/ui/abc_layout_text.c index 694f7d8..6640045 100644 --- a/ui/abc_layout_text.c +++ b/ui/abc_layout_text.c @@ -58,8 +58,10 @@ int __layout_text(cairo_t* cr, abc_obj_t* obj, int x, int width, cairo_text_exte cairo_text_extents (cr, obj->text->data, extents); int w = extents->x_bearing + extents->x_advance; - if (x + w <= width) + if (x + w <= width) { + extents->width = w; return 0; + } extents->width = width; extents->height = 0; @@ -90,7 +92,7 @@ int __layout_text(cairo_t* cr, abc_obj_t* obj, int x, int width, cairo_text_exte if (n < 0) return n; - w = (tmp.x_bearing + tmp.x_advance + size - 1) / size * size; + w = tmp.x_bearing + tmp.x_advance; if (x + w <= width) { x = 0; @@ -126,23 +128,18 @@ int abc_layout_text(abc_layout_t* layout, abc_obj_t* obj, int width, int height) { abc_obj_t* parent = obj->parent; abc_obj_t* attr; - abc_obj_t* style; cairo_text_extents_t extents; - cairo_text_extents_t extents2; cairo_surface_t* surface; cairo_t* cr; if (!obj->text) return 0; - int x = obj->x - parent->x; - int w = parent->w_set ? parent->w0 : width; int d = parent->d; - int h; + int x = obj->x - (parent->x + d); + int w = width; scf_logd("obj->x: %d, parent->x: %d, w: %d, d: %d\n", obj->x, parent->x, w, d); - x -= d; - w -= d * 2; surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, height); cr = cairo_create(surface); @@ -152,11 +149,7 @@ int abc_layout_text(abc_layout_t* layout, abc_obj_t* obj, int width, int height) if (attr) size = atoi(attr->value->data); - w = w / size * size; - - scf_logd("text: %s, w: %d\n", obj->text->data, w); - - int ret = __layout_text(cr, obj, x, w, &extents); + int ret = __layout_text(cr, obj, x, w / size * size, &extents); if (ret < 0) scf_loge("ret: %d\n", ret); @@ -165,10 +158,8 @@ int abc_layout_text(abc_layout_t* layout, abc_obj_t* obj, int width, int height) if (parent->y_bearing > obj->y_bearing) parent->y_bearing = obj->y_bearing; - obj->w = extents.x_bearing + extents.x_advance; - obj->h = extents.height + extents.height / 2; -// obj->w = (obj->w + 3) & ~0x3; -// obj->h = (obj->h + 3) & ~0x3; + obj->w = extents.width; + obj->h = extents.height + extents.height / 2; scf_logd("%s, w: %d, h: %d, d: %d, x_bearing: %lg, y_bearing: %lg, width: %lg, height: %lg, x_advance: %lg, y_advance: %lg, width: %d, height: %d\n", obj->text->data, obj->w, obj->h, d, diff --git a/ui/abc_render.c b/ui/abc_render.c index 0e0b02c..961f059 100644 --- a/ui/abc_render.c +++ b/ui/abc_render.c @@ -37,6 +37,7 @@ static abc_render_t* abc_renders[ABC_HTML_NB] = [ABC_CORE_TEXT] = &abc_render_text, [ABC_HTML_B] = &abc_render_text, [ABC_HTML_I] = &abc_render_text, + [ABC_HTML_A] = &abc_render_text, [ABC_HTML_H1] = &abc_render_h1, [ABC_HTML_H2] = &abc_render_h1, @@ -48,7 +49,6 @@ static abc_render_t* abc_renders[ABC_HTML_NB] = [ABC_HTML_P] = &abc_render_h1, [ABC_HTML_BR] = &abc_render_h1, - [ABC_HTML_A] = &abc_render_h1, [ABC_HTML_A_HREF] = &abc_render_a_href, [ABC_HTML_IMG] = &abc_render_img, diff --git a/ui/abc_render_audio.c b/ui/abc_render_audio.c index a6106c1..7fd0394 100644 --- a/ui/abc_render_audio.c +++ b/ui/abc_render_audio.c @@ -41,19 +41,10 @@ static int _render_fini_audio(abc_render_t* render) static int _render_draw_audio(abc_render_t* render, abc_obj_t* obj, int width, int height) { - scf_list_t* l; - abc_obj_t* attr; - - for (l = scf_list_head(&obj->attrs); l != scf_list_sentinel(&obj->attrs); l = scf_list_next(l)) { - attr = scf_list_data(l, abc_obj_t, list); - - if (ABC_HTML_ATTR_SRC == attr->type) - break; - } - - if (l == scf_list_sentinel(&obj->attrs)) { - scf_loge("src image of '%s' not found\n", obj->keys[0]); - return -1; + abc_obj_t* attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_SRC); + if (!attr) { + scf_loge("src audio of '%s' not found\n", obj->keys[0]); + return -EINVAL; } if (0 == program) diff --git a/ui/abc_render_img.c b/ui/abc_render_img.c index 20323ca..511e144 100644 --- a/ui/abc_render_img.c +++ b/ui/abc_render_img.c @@ -81,19 +81,24 @@ static int _render_draw_img(abc_render_t* render, abc_obj_t* obj, int width, int 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->d; + int y = obj->y + obj->d; + int w = obj->w - obj->d * 2; + int h = obj->h - obj->d * 2; + GLfloat vert_update[] = { - 2.0 * obj->x / (float)width - 1.0, - -2.0 * (obj->y + obj->h) / (float)height + 1.0, + 2.0 * x / (float)width - 1.0, + -2.0 * (y + h) / (float)height + 1.0, - 2.0 * (obj->x + obj->w) / (float)width - 1.0, - -2.0 * (obj->y + obj->h) / (float)height + 1.0, + 2.0 * (x + w) / (float)width - 1.0, + -2.0 * (y + h) / (float)height + 1.0, - 2.0 * obj->x / (float)width - 1.0, - -2.0 * obj->y / (float)height + 1.0, + 2.0 * x / (float)width - 1.0, + -2.0 * y / (float)height + 1.0, - 2.0 * (obj->x + obj->w) / (float)width - 1.0, - -2.0 * obj->y / (float)height + 1.0, + 2.0 * (x + w) / (float)width - 1.0, + -2.0 * y / (float)height + 1.0, }; glUseProgram(program); diff --git a/ui/main.c b/ui/main.c index c931f2c..2c2f4d3 100644 --- a/ui/main.c +++ b/ui/main.c @@ -83,11 +83,11 @@ static int __do_button_move(abc_ctx_t* ctx, int x, int y) g_object_unref(cursor); if (prev->visited) - css = abc_obj_get_attr(prev, ABC_CSS_VISITED); + prev->css_pse_type = ABC_CSS_VISITED; else - css = abc_obj_get_attr(prev, ABC_CSS_LINK); - if (css) - abc_obj_set_css(prev, css); + prev->css_pse_type = ABC_CSS_LINK; + + abc_css_active(prev); prev->clicked = 0; ret = 1; @@ -129,11 +129,9 @@ static int __do_button_move(abc_ctx_t* ctx, int x, int y) break; }; - css = abc_obj_get_attr(obj, ABC_CSS_HOVER); - if (css) { - abc_obj_set_css(obj, css); - ret = 1; - } + obj->css_pse_type = ABC_CSS_HOVER; + + ret |= abc_css_active(obj); ctx->current->current = obj; } @@ -186,11 +184,10 @@ static int __do_button_release(abc_ctx_t* ctx, int x, int y) if (!obj) return __do_button_move(ctx, x, y); - obj->visited = 1; + obj->visited = 1; + obj->css_pse_type = ABC_CSS_VISITED; - css = abc_obj_get_attr(obj, ABC_CSS_VISITED); - if (css) - abc_obj_set_css(obj, css); + abc_css_active(obj); 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); @@ -344,12 +341,10 @@ static gboolean button_press_event(GtkWidget* self, GdkEventButton* event, gpoin abc_obj_t* css; if (obj) { - css = abc_obj_get_attr(obj, ABC_CSS_ACTIVE); - if (css) { - abc_obj_set_css(obj, css); + obj->css_pse_type = ABC_CSS_ACTIVE; + if (abc_css_active(obj) > 0) gtk_gl_area_queue_render(ctx->gl_area); - } } }