css: simple attribute selector ok, draw HTML <hr> ok master
authoryu.dongliang <18588496441@163.com>
Wed, 27 May 2026 09:42:54 +0000 (17:42 +0800)
committeryu.dongliang <18588496441@163.com>
Wed, 27 May 2026 09:42:54 +0000 (17:42 +0800)
examples/css_attr.html [new file with mode: 0644]
html/abc_css.c
html/abc_html.c
html/abc_obj.h
ui/Makefile
ui/abc_layout.c
ui/abc_layout_hr.c [new file with mode: 0644]
ui/abc_render.c
ui/abc_render_hr.c [new file with mode: 0644]

diff --git a/examples/css_attr.html b/examples/css_attr.html
new file mode 100644 (file)
index 0000000..4e8ce26
--- /dev/null
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+[title]
+{
+       color:blue;
+}
+</style>
+</head>
+
+<body>
+<h2>Will apply to:</h2>
+<h1 title="Hello world">Hello world</h1>
+<a title="runoob.com" href="https://www.runoob.com/">runoob.com</a>
+<hr>
+<h2>Will not apply to:</h2>
+<p>Hello!</p>
+</body>
+</html>
index 4c555ad2579bbe87554c5b1aee24b483aa2c77bb..a9203368128729cd4af5415f4db10cc451c09b8e 100644 (file)
@@ -93,7 +93,9 @@ static int __css_parse_str(abc_obj_t* css, scf_string_t* s, int (*end)(int c))
                        case ' ':
                                if (' ' == c0
                                                || '>' == c0 || '+' == c0 || '~' == c0
                        case ' ':
                                if (' ' == c0
                                                || '>' == c0 || '+' == c0 || '~' == c0
-                                               || ',' == c0 || ':' == c0 || '.' == c0 || '#' == c0)
+                                               || ',' == c0 || ':' == c0 || '.' == c0 || '#' == c0
+                                               || '[' == c0 || ']' == c0
+                                               || '(' == c0 || ')' == c0)
                                        break;
 
                                ret = scf_string_cat_cstr_len(s, " ", 1);
                                        break;
 
                                ret = scf_string_cat_cstr_len(s, " ", 1);
@@ -106,6 +108,10 @@ static int __css_parse_str(abc_obj_t* css, scf_string_t* s, int (*end)(int c))
                        case ',':
                        case ':':
                        case '.':
                        case ',':
                        case ':':
                        case '.':
+                       case '[':
+                       case ']':
+                       case '(':
+                       case ')':
 //                     case '#':
                                if (s->len > 0 && ' ' == s->data[s->len - 1]) {
                                        s->data[s->len - 1] = c->c;
 //                     case '#':
                                if (s->len > 0 && ' ' == s->data[s->len - 1]) {
                                        s->data[s->len - 1] = c->c;
@@ -248,6 +254,7 @@ static int __css_parse_comma(abc_obj_t* css, abc_obj_t* obj)
        int combinator = -1;
        int id         = 0;
        int class      = 0;
        int combinator = -1;
        int id         = 0;
        int class      = 0;
+       int attr       = 0;
        int pseClass   = -1;
        int pseElement = -1;
        int c;
        int pseClass   = -1;
        int pseElement = -1;
        int c;
@@ -284,6 +291,8 @@ static int __css_parse_comma(abc_obj_t* css, abc_obj_t* obj)
                                label = __html_find_label2(ABC_CSS_ID);
                        else if (class > 0)
                                label = __html_find_label2(ABC_CSS_CLASS);
                                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 (pseClass > 0)
                                label = __html_find_label2(ABC_CSS_PSE_CLASS);
@@ -332,6 +341,7 @@ static int __css_parse_comma(abc_obj_t* css, abc_obj_t* obj)
                        combinator = -1;
                        id         = 0;
                        class      = 0;
                        combinator = -1;
                        id         = 0;
                        class      = 0;
+                       attr       = 0;
                        pseClass   = -1;
                        pseElement = -1;
 
                        pseClass   = -1;
                        pseElement = -1;
 
@@ -351,6 +361,9 @@ static int __css_parse_comma(abc_obj_t* css, abc_obj_t* obj)
                        case '.':
                                class++;
                                break;
                        case '.':
                                class++;
                                break;
+                       case '[':
+                               attr++;
+                               break;
 
                        case ':':
                                if (pseClass < 0)
 
                        case ':':
                                if (pseClass < 0)
@@ -382,6 +395,8 @@ static int __css_parse_comma(abc_obj_t* css, abc_obj_t* obj)
                        label = __html_find_label2(ABC_CSS_ID);
                else if (class > 0)
                        label = __html_find_label2(ABC_CSS_CLASS);
                        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 (pseClass > 0)
                        label = __html_find_label2(ABC_CSS_PSE_CLASS);
@@ -585,7 +600,8 @@ int abc_css_parse(abc_obj_t* css)
                                || ('a'    <= c->c && 'z'    >= c->c)
                                || ('A'    <= c->c && 'Z'    >= c->c)
                                || (0x4e00 <= c->c && 0x9fa5 >= c->c)
                                || ('a'    <= c->c && 'z'    >= c->c)
                                || ('A'    <= c->c && 'Z'    >= c->c)
                                || (0x4e00 <= c->c && 0x9fa5 >= c->c)
-                               ||  '.'    == c->c) {
+                               ||  '.'    == c->c
+                               ||  '['    == c->c) {
 
                        ret = __css_parse_obj(css, c);
                        if (ret < 0) {
 
                        ret = __css_parse_obj(css, c);
                        if (ret < 0) {
@@ -934,6 +950,7 @@ int abc_css_merge(abc_html_t* html, abc_obj_t* css)
                                break;
 
                        case ABC_CSS_CLASS:
                                break;
 
                        case ABC_CSS_CLASS:
+                       case ABC_CSS_ATTR:
                                scf_list_del(&src->list);
                                scf_list_add_tail(&h_class, &src->list);
                                break;
                                scf_list_del(&src->list);
                                scf_list_add_tail(&h_class, &src->list);
                                break;
@@ -1095,7 +1112,7 @@ static abc_obj_t* __css_select_by_key(abc_obj_t* css, abc_obj_t* current, scf_ve
        return current;
 }
 
        return current;
 }
 
-static abc_obj_t* __css_select_by_attr(abc_obj_t* css, abc_obj_t* current, scf_vector_t* vec, int next, int type, const char* key, int len)
+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)
 {
        scf_list_t*  l;
        abc_obj_t*   tmp;
 {
        scf_list_t*  l;
        abc_obj_t*   tmp;
@@ -1117,7 +1134,7 @@ static abc_obj_t* __css_select_by_attr(abc_obj_t* css, abc_obj_t* current, scf_v
                        {
                                attr = abc_obj_get_attr(current, type);
 
                        {
                                attr = abc_obj_get_attr(current, type);
 
-                               if (attr && !__html_strncmp(attr->value->data, key, len))
+                               if (attr && !__html_strncmp(attr->value->data, value, len))
                                        break;
                        }
                        break;
                                        break;
                        }
                        break;
@@ -1127,7 +1144,7 @@ static abc_obj_t* __css_select_by_attr(abc_obj_t* css, abc_obj_t* current, scf_v
                        if (current) {
                                attr = abc_obj_get_attr(current, type);
 
                        if (current) {
                                attr = abc_obj_get_attr(current, type);
 
-                               if (!attr || __html_strncmp(attr->value->data, key, len))
+                               if (!attr || __html_strncmp(attr->value->data, value, len))
                                        return NULL;
                        }
                        break;
                                        return NULL;
                        }
                        break;
@@ -1143,7 +1160,7 @@ static abc_obj_t* __css_select_by_attr(abc_obj_t* css, abc_obj_t* current, scf_v
                        current = scf_list_data(l, abc_obj_t, list);
                        attr    = abc_obj_get_attr(current, type);
 
                        current = scf_list_data(l, abc_obj_t, list);
                        attr    = abc_obj_get_attr(current, type);
 
-                       if (!attr || __html_strncmp(attr->value->data, key, len))
+                       if (!attr || __html_strncmp(attr->value->data, value, len))
                                return NULL;
                        break;
 
                                return NULL;
                        break;
 
@@ -1156,7 +1173,7 @@ static abc_obj_t* __css_select_by_attr(abc_obj_t* css, abc_obj_t* current, scf_v
 
                                attr = abc_obj_get_attr(tmp, type);
 
 
                                attr = abc_obj_get_attr(tmp, type);
 
-                               if (attr && !__html_strncmp(attr->value->data, key, len))
+                               if (attr && !__html_strncmp(attr->value->data, value, len))
                                        break;
                        }
 
                                        break;
                        }
 
@@ -1175,7 +1192,7 @@ static abc_obj_t* __css_select_by_attr(abc_obj_t* css, abc_obj_t* current, scf_v
                        if (k <= j)
                                return NULL;
 
                        if (k <= j)
                                return NULL;
 
-                       current = __css_select_by_attr(css, current, vec, next - 1, type, key, len);
+                       current = __css_select_by_id_class(css, current, vec, next - 1, type, value, len);
                        if (!current)
                                return NULL;
 
                        if (!current)
                                return NULL;
 
@@ -1201,13 +1218,133 @@ static abc_obj_t* __css_select_by_attr(abc_obj_t* css, abc_obj_t* current, scf_v
                        css->css_pse_chain = pseLink;
                        pseLink = NULL;
 
                        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,
+                       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;
                default:
                        attr = abc_obj_get_attr(current, type);
 
                                        k - j, css->text->data + j);
                        break;
                default:
                        attr = abc_obj_get_attr(current, type);
 
-                       if (!attr || __html_strncmp(attr->value->data, key, len))
+                       if (!attr || __html_strncmp(attr->value->data, value, len))
+                               return NULL;
+                       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)
+{
+       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);
+
+       int j = (intptr_t)vec->data[next];
+       int k;
+       int c = 0;
+       if (j < css->text->len)
+               c = css->text->data[j];
+
+       switch (c) {
+               case ' ':
+                       for (current = current->parent; current; current = current->parent)
+                       {
+                               attr = abc_obj_get_attr2(current, key, len);
+
+                               if (attr && attr->value && attr->value->len > 0)
+                                       break;
+                       }
+                       break;
+
+               case '>':
+                       current = current->parent;
+                       if (current) {
+                               attr = abc_obj_get_attr2(current, key, len);
+
+                               if (!attr || !attr->value || 0 == attr->value->len)
+                                       return NULL;
+                       }
+                       break;
+
+               case '+':
+                       if (!current->parent)
+                               return NULL;
+
+                       l = scf_list_prev(&current->list);
+                       if (l == scf_list_sentinel(&current->parent->childs))
+                               return NULL;
+
+                       current = scf_list_data(l, abc_obj_t, list);
+                       attr = abc_obj_get_attr2(current, key, len);
+
+                       if (!attr || !attr->value || 0 == attr->value->len)
+                               return NULL;
+                       break;
+
+               case '~':
+                       if (!current->parent)
+                               return NULL;
+
+                       for (l  = scf_list_prev(&current->list); l != scf_list_sentinel(&current->parent->childs); l = scf_list_prev(l)) {
+                               tmp = scf_list_data(l, abc_obj_t, list);
+
+                               attr = abc_obj_get_attr2(tmp, key, len);
+
+                               if (attr && attr->value && attr->value->len > 0)
+                                       break;
+                       }
+
+                       if (l == scf_list_sentinel(&current->parent->childs))
+                               return NULL;
+
+                       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, 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_attr2(current, key, len);
+
+                       if (!attr || !attr->value || 0 == attr->value->len)
                                return NULL;
                        break;
        };
                                return NULL;
                        break;
        };
@@ -1235,6 +1372,8 @@ static int __css_use_complex(abc_obj_t* css, abc_obj_t* obj)
        css->css_pse_type = 0;
        scf_slist_clear(css->css_pse_chain, pse_link_t, next, free);
 
        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--) {
                c  = css->text->data[i];
 
        for (i = css->text->len - 1; i >= 0; i--) {
                c  = css->text->data[i];
 
@@ -1248,12 +1387,53 @@ static int __css_use_complex(abc_obj_t* css, abc_obj_t* obj)
                ret = 0;
                switch (c) {
                        case '#':
                ret = 0;
                switch (c) {
                        case '#':
-                               current = __css_select_by_attr(css, current, vec, vec->size - 1, ABC_CSS_ID, key, len);
+                               current = __css_select_by_id_class(css, current, vec, vec->size - 1, ABC_CSS_ID, key, len);
                                j = i;
                                break;
 
                        case '.':
                                j = i;
                                break;
 
                        case '.':
-                               current = __css_select_by_attr(css, current, vec, vec->size - 1, ABC_CSS_CLASS, key, len);
+                               current = __css_select_by_id_class(css, current, vec, vec->size - 1, ABC_CSS_CLASS, key, len);
+                               j = i;
+                               break;
+
+                       case ']':
+                               n_sqares++;
+                               j = i;
+                               break;
+
+                       case '~':
+                               if (n_sqares <= 0)
+                                       current = __css_select_by_key(css, current, vec, vec->size - 1, key, len);
+                               j = i;
+                               break;
+                       case '|':
+                       case '^':
+                       case '$':
+                       case '*':
+                               if (n_sqares > 0)
+                                       j = i;
+                               break;
+                       case '=':
+                               if (n_sqares > 0) {
+                                       if (i > 0 && ('~'  == css->text->data[i - 1]
+                                                               || '|' == css->text->data[i - 1]
+                                                               || '^' == css->text->data[i - 1]
+                                                               || '$' == css->text->data[i - 1]
+                                                               || '*' == css->text->data[i - 1]))
+                                               break;
+                                       j = i;
+                               }
+                               break;
+
+                       case '[':
+                               if (0 != --n_sqares) {
+                                       ret = -EINVAL;
+                                       goto end;
+                               }
+
+                               scf_logw("i: %d, %.*s\n", i, len, key);
+
+                               current = __css_select_by_attr(css, current, vec, vec->size - 1, key, len);
                                j = i;
                                break;
 
                                j = i;
                                break;
 
@@ -1273,7 +1453,6 @@ static int __css_use_complex(abc_obj_t* css, abc_obj_t* obj)
                        case ' ':
                        case '>':
                        case '+':
                        case ' ':
                        case '>':
                        case '+':
-                       case '~':
                                current = __css_select_by_key(css, current, vec, vec->size - 1, key, len);
                                j = i;
                                break;
                                current = __css_select_by_key(css, current, vec, vec->size - 1, key, len);
                                j = i;
                                break;
@@ -1324,6 +1503,7 @@ int abc_css_use(abc_html_t* html, abc_obj_t* obj)
                        {
                                case ABC_CSS_ID:
                                case ABC_CSS_CLASS:
                        {
                                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:
                                case ABC_CSS_PSE_CLASS:
                                case ABC_CSS_PSE_ELEMENT:
                                case ABC_CSS_COMBINATOR:
index 20bedb21571ccc8df53e30e12fd3b00930b0ba1f..70287b7a5770cd07adff8612d791440e31323309 100644 (file)
@@ -135,6 +135,7 @@ static char* style_keys[]      = {"style",      "样式",     NULL};
 // css selectors
 static char* css_id_keys[]          = {"#",      NULL};
 static char* css_class_keys[]       = {".",      NULL};
 // css selectors
 static char* css_id_keys[]          = {"#",      NULL};
 static char* css_class_keys[]       = {".",      NULL};
+static char* css_attr_keys[]        = {"[]",     NULL};
 static char* css_other_keys[]       = {"*",      NULL};
 static char* css_pse_class_keys[]   = {":",      NULL};
 static char* css_pse_element_keys[] = {"::",     NULL};
 static char* css_other_keys[]       = {"*",      NULL};
 static char* css_pse_class_keys[]   = {":",      NULL};
 static char* css_pse_element_keys[] = {"::",     NULL};
@@ -185,6 +186,7 @@ static html_attr_t  html_attrs[] =
 #define ABC_CSS_SELECTOR() \
        {style_keys,          "",        ABC_HTML_ATTR_STYLE,         ABC_HTML_FLAG_SHOW}, \
        {class_keys,          "",        ABC_HTML_ATTR_CLASS,         ABC_HTML_FLAG_SHOW}, \
 #define ABC_CSS_SELECTOR() \
        {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}, \
        {id_keys,             "",        ABC_HTML_ATTR_ID,            ABC_HTML_FLAG_SHOW},
 
 #define ABC_CSS_BACK_GROUND(color) \
        {id_keys,             "",        ABC_HTML_ATTR_ID,            ABC_HTML_FLAG_SHOW},
 
 #define ABC_CSS_BACK_GROUND(color) \
@@ -314,6 +316,17 @@ static html_attr_t  h6_attrs[] =
        ABC_CSS_TEXT(left, )
 };
 
        ABC_CSS_TEXT(left, )
 };
 
+static html_attr_t  hr_attrs[] =
+{
+       ABC_CSS_BOX( , , )
+       ABC_CSS_SCROLL( , , )
+       ABC_CSS_SELECTOR()
+       ABC_CSS_BACK_GROUND()
+
+       ABC_CSS_FONT(SimHei, 16, lightGray, )
+       ABC_CSS_TEXT(left, )
+};
+
 static html_attr_t  p_attrs[] =
 {
        ABC_CSS_BOX(2px, , 2px)
 static html_attr_t  p_attrs[] =
 {
        ABC_CSS_BOX(2px, , 2px)
@@ -547,7 +560,7 @@ static html_label_t  html_labels[] =
        {i_keys,          ABC_HTML_I,        abc_number_of(i_attrs),       i_attrs,       ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
 
        {br_keys,         ABC_HTML_BR,       0,                            NULL,          ABC_HTML_FLAG_OPEN  | ABC_HTML_FLAG_SHOW},
        {i_keys,          ABC_HTML_I,        abc_number_of(i_attrs),       i_attrs,       ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
 
        {br_keys,         ABC_HTML_BR,       0,                            NULL,          ABC_HTML_FLAG_OPEN  | ABC_HTML_FLAG_SHOW},
-       {hr_keys,         ABC_HTML_HR,       0,                            NULL,          ABC_HTML_FLAG_OPEN  | ABC_HTML_FLAG_SHOW},
+       {hr_keys,         ABC_HTML_HR,       abc_number_of(hr_attrs),      hr_attrs,      ABC_HTML_FLAG_OPEN  | ABC_HTML_FLAG_SHOW},
 
        {a_keys,          ABC_HTML_A,        abc_number_of(a_attrs),       a_attrs,       ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
        {img_keys,        ABC_HTML_IMG,      abc_number_of(img_attrs),     img_attrs,     ABC_HTML_FLAG_OPEN  | ABC_HTML_FLAG_SHOW},
 
        {a_keys,          ABC_HTML_A,        abc_number_of(a_attrs),       a_attrs,       ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
        {img_keys,        ABC_HTML_IMG,      abc_number_of(img_attrs),     img_attrs,     ABC_HTML_FLAG_OPEN  | ABC_HTML_FLAG_SHOW},
@@ -578,6 +591,7 @@ static html_label_t  html_labels[] =
 
        {css_id_keys,           ABC_CSS_ID,          abc_number_of(css_id_attrs),  css_id_attrs,  ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
        {css_class_keys,        ABC_CSS_CLASS,       abc_number_of(css_id_attrs),  css_id_attrs,  ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
 
        {css_id_keys,           ABC_CSS_ID,          abc_number_of(css_id_attrs),  css_id_attrs,  ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
        {css_class_keys,        ABC_CSS_CLASS,       abc_number_of(css_id_attrs),  css_id_attrs,  ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {css_attr_keys,         ABC_CSS_ATTR,        abc_number_of(css_id_attrs),  css_id_attrs,  ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
        {css_pse_class_keys,    ABC_CSS_PSE_CLASS,   abc_number_of(css_id_attrs),  css_id_attrs,  ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
        {css_pse_element_keys,  ABC_CSS_PSE_ELEMENT, abc_number_of(css_id_attrs),  css_id_attrs,  ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
        {css_other_keys,        ABC_CSS_COMBINATOR,  abc_number_of(css_id_attrs),  css_id_attrs,  ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
        {css_pse_class_keys,    ABC_CSS_PSE_CLASS,   abc_number_of(css_id_attrs),  css_id_attrs,  ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
        {css_pse_element_keys,  ABC_CSS_PSE_ELEMENT, abc_number_of(css_id_attrs),  css_id_attrs,  ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
        {css_other_keys,        ABC_CSS_COMBINATOR,  abc_number_of(css_id_attrs),  css_id_attrs,  ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
index ff49d6a15bc267baf423489f6342dc89125bd719..6b6faad32f8df74e6277bd06d9874d9a54f82e09 100644 (file)
@@ -77,6 +77,7 @@ enum abc_objs
        ABC_HTML_ATTR_NAME,
        ABC_HTML_ATTR_VALUE,
        ABC_HTML_ATTR_CLASS,
        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_STYLE,
 
        ABC_HTML_ATTR_HREF,
@@ -173,6 +174,7 @@ enum abc_objs
        ABC_HTML_CSS_NB = ABC_CSS_PSE_DYNAMIC, // total HTML & CSS attrs
 
        // css selectors
        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,
        ABC_CSS_PSE_CLASS,
        ABC_CSS_PSE_ELEMENT,
        ABC_CSS_COMBINATOR,
index e7567f98b39d8969bb48e5210281cd34d6b5b843..36f96a1b8ce0d39f42585e3679fa2841784c0660 100644 (file)
@@ -6,6 +6,7 @@ CFILES += abc_layout_div.c
 
 CFILES += abc_layout_text.c
 CFILES += abc_layout_h1.c
 
 CFILES += abc_layout_text.c
 CFILES += abc_layout_h1.c
+CFILES += abc_layout_hr.c
 CFILES += abc_layout_img.c
 
 CFILES += abc_layout_form.c
 CFILES += abc_layout_img.c
 
 CFILES += abc_layout_form.c
@@ -28,6 +29,7 @@ CFILES += abc_render_text.c
 CFILES += abc_render_empty.c
 
 CFILES += abc_render_h1.c
 CFILES += abc_render_empty.c
 
 CFILES += abc_render_h1.c
+CFILES += abc_render_hr.c
 CFILES += abc_render_a_href.c
 CFILES += abc_render_img.c
 CFILES += abc_render_form.c
 CFILES += abc_render_a_href.c
 CFILES += abc_render_img.c
 CFILES += abc_render_form.c
index c03ef1acd77467696594c18af82daf201047d8d7..01d01f3442fc780c9905104ff4c1ebaea78e482c 100644 (file)
@@ -6,6 +6,7 @@ int abc_layout_text(abc_layout_t* layout, 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_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_form (abc_layout_t* layout, abc_obj_t* obj, int width, int height);
 int abc_layout_img  (abc_layout_t* layout, abc_obj_t* obj, int width, int height);
 
 int abc_layout_form (abc_layout_t* layout, abc_obj_t* obj, int width, int height);
@@ -53,6 +54,7 @@ static abc_layout_pt abc_layouts[ABC_HTML_NB] =
 
        [ABC_HTML_P]        = abc_layout_h1,
        [ABC_HTML_BR]       = abc_layout_h1,
 
        [ABC_HTML_P]        = abc_layout_h1,
        [ABC_HTML_BR]       = abc_layout_h1,
+       [ABC_HTML_HR]       = abc_layout_hr,
 
        [ABC_HTML_IMG]      = abc_layout_img,
 
 
        [ABC_HTML_IMG]      = abc_layout_img,
 
@@ -359,6 +361,7 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height)
                                break;
 
                        case ABC_HTML_BR:
                                break;
 
                        case ABC_HTML_BR:
+                       case ABC_HTML_HR:
                        case ABC_HTML_TR:
                                x  = root->x + root->left;
                                y += h;
                        case ABC_HTML_TR:
                                x  = root->x + root->left;
                                y += h;
diff --git a/ui/abc_layout_hr.c b/ui/abc_layout_hr.c
new file mode 100644 (file)
index 0000000..6639222
--- /dev/null
@@ -0,0 +1,42 @@
+#include"abc.h"
+
+int abc_layout_hr(abc_layout_t* layout, abc_obj_t* obj, int width, int height)
+{
+       int size = 16;
+
+       if (obj->parent) {
+               scf_list_t* l;
+               abc_attr_t* attr;
+               abc_obj_t*  tmp;
+
+               l = scf_list_prev(&obj->list);
+               if (l  != scf_list_sentinel(&obj->parent->childs)) {
+                       tmp = scf_list_data(l, abc_obj_t, list);
+
+                       attr = abc_obj_find_attr(tmp, ABC_HTML_ATTR_FONT_SIZE);
+
+                       if (attr && attr->value && attr->value->len > 0)
+                               size = atoi(attr->value->data);
+               }
+
+               l = scf_list_next(&obj->list);
+               if (l  != scf_list_sentinel(&obj->parent->childs)) {
+                       tmp = scf_list_data(l, abc_obj_t, list);
+
+                       attr = abc_obj_find_attr(tmp, ABC_HTML_ATTR_FONT_SIZE);
+
+                       if (attr && attr->value && attr->value->len > 0) {
+                               int size2 = atoi(attr->value->data);
+                               if (size < size2)
+                                       size = size2;
+                       }
+               }
+       }
+
+       int w_set = abc_css_width (obj, width);
+       int h_set = abc_css_height(obj, height);
+
+       if (!h_set)
+               obj->h = size;
+       return 0;
+}
index 43a3d5096bc6011fa3d45e12a03e18698a72e457..a5e774a11563e474364dd788d63c85bf802b8cd8 100644 (file)
@@ -5,6 +5,7 @@ extern abc_render_t  abc_render_text;
 
 extern abc_render_t  __render_text;
 extern abc_render_t  abc_render_h1;
 
 extern abc_render_t  __render_text;
 extern abc_render_t  abc_render_h1;
+extern abc_render_t  abc_render_hr;
 
 extern abc_render_t  abc_render_a_href;
 extern abc_render_t  abc_render_img;
 
 extern abc_render_t  abc_render_a_href;
 extern abc_render_t  abc_render_img;
@@ -45,6 +46,7 @@ static abc_render_t* abc_renders[ABC_HTML_NB] =
 
        [ABC_HTML_P]        = &abc_render_h1,
        [ABC_HTML_BR]       = &abc_render_h1,
 
        [ABC_HTML_P]        = &abc_render_h1,
        [ABC_HTML_BR]       = &abc_render_h1,
+       [ABC_HTML_HR]       = &abc_render_hr,
 
        [ABC_HTML_A_HREF]   = &abc_render_a_href,
        [ABC_HTML_IMG]      = &abc_render_img,
 
        [ABC_HTML_A_HREF]   = &abc_render_a_href,
        [ABC_HTML_IMG]      = &abc_render_img,
diff --git a/ui/abc_render_hr.c b/ui/abc_render_hr.c
new file mode 100644 (file)
index 0000000..168ecf3
--- /dev/null
@@ -0,0 +1,177 @@
+#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 vec4  color; \n"
+       "uniform vec4  bgColor; \n"
+       "uniform float line_width; \n"
+       "\n"
+       "void main() { \n"
+       "    float x = v_texCoord.x; \n"
+       "    float y = v_texCoord.y; \n"
+       "    if (y > 0.5 - line_width && y < 0.5 + line_width) { \n"
+       "        outputColor = color; \n"
+       "    } else { \n"
+       "        outputColor = bgColor; \n"
+       "    } \n"
+       "} \n";
+
+
+static GLuint program = 0;
+
+static GLuint vao = 0;
+static GLuint buffers[2] = {0};
+
+static GLuint uniform_mvp;
+static GLuint uniform_color;
+static GLuint uniform_bgColor;
+static GLuint uniform_line_width;
+
+static int __render_fini_hr(abc_render_t* render)
+{
+       return 0;
+}
+
+static int __render_draw_hr(abc_render_t* render, abc_obj_t* obj, int width, int height)
+{
+       abc_obj_t* parent = obj->parent;
+
+       if (0 == program)
+               __init_program(&program, vert_shader, frag_shader);
+
+       if (0 == vao)
+               __init_buffers(&vao, buffers);
+
+       double fgColor[3] = {0.0, 0.0, 0.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);
+       }
+
+       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);
+
+       int x = obj->x + obj->margin_left;
+       int y = obj->y + obj->margin_top;
+       int w = obj->w - obj->margin_left - obj->margin_right;
+       int h = obj->h - obj->margin_top  - obj->margin_bottom;
+
+       obj->view_x = x;
+       obj->view_y = y;
+       obj->view_w = w;
+       obj->view_h = h;
+
+       attr = abc_obj_find_attr(obj, ABC_CSS_OVERFLOW);
+       if (attr)
+               obj->overflow_type = abc_css_overflow(attr->value->data);
+
+       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(&obj->view_x, &obj->view_y, &obj->view_w, &obj->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;
+       };
+
+       float mvp[16];
+       __compute_mvp(mvp, 0, 0, 0);
+
+       GLfloat vert_update[] =
+       {
+                2.0 *  obj->view_x                / (float)width  - 1.0,
+               -2.0 * (obj->view_y + obj->view_h) / (float)height + 1.0,
+
+                2.0 * (obj->view_x + obj->view_w) / (float)width  - 1.0,
+               -2.0 * (obj->view_y + obj->view_h) / (float)height + 1.0,
+
+                2.0 *  obj->view_x                / (float)width  - 1.0,
+               -2.0 *  obj->view_y                / (float)height + 1.0,
+
+                2.0 * (obj->view_x + obj->view_w) / (float)width  - 1.0,
+               -2.0 *  obj->view_y                / (float)height + 1.0,
+       };
+
+       GLfloat texture_update[] =
+       {
+               (obj->view_x - x)               / (float)w,
+               (obj->view_y + obj->view_h - y) / (float)h,
+
+               (obj->view_x + obj->view_w - x) / (float)w,
+               (obj->view_y + obj->view_h - y) / (float)h,
+
+               (obj->view_x - x)               / (float)w,
+               (obj->view_y - y)               / (float)h,
+
+               (obj->view_x + obj->view_w - x) / (float)w,
+               (obj->view_y - y)               / (float)h,
+       };
+
+       glUseProgram(program);
+       uniform_mvp        = glGetUniformLocation(program, "mvp");
+       uniform_color      = glGetUniformLocation(program, "color");
+       uniform_bgColor    = glGetUniformLocation(program, "bgColor");
+       uniform_line_width = glGetUniformLocation(program, "line_width");
+
+       glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, mvp);
+
+       glUniform4f(uniform_color,      fgColor[0], fgColor[1], fgColor[2], 1.0);
+       glUniform4f(uniform_bgColor,    bgColor[0], bgColor[1], bgColor[2], bgColor[3]);
+       glUniform1f(uniform_line_width, 1.0 / (float)h);
+
+       // 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_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+       glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+       glDisable(GL_BLEND);
+
+       glBindVertexArray(0);
+       glUseProgram(0);
+       return 0;
+}
+
+abc_render_t  abc_render_hr =
+{
+       .type = ABC_HTML_HR,
+
+       .draw = __render_draw_hr,
+       .fini = __render_fini_hr,
+};