1, split render code to 3 files: __render_border.c, __render_bg_image.c, __render_text.c,
authoryu.dongliang <18588496441@163.com>
Sun, 3 May 2026 08:17:02 +0000 (16:17 +0800)
committeryu.dongliang <18588496441@163.com>
Sun, 3 May 2026 08:17:07 +0000 (16:17 +0800)
2, use GL_BLEND to show background-image when draw text,
3, scf: add scf_utf8_len() to get a UTF-8 char & its bytes,
4, css: support Chinese Char (中文) in border,
5, css: use macro ABC_CSS_BOX() to add HTML labels' attrs for css box model,
ABC_CSS_SELECTOR() for css selector,
ABC_CSS_BACK_GROUND() for back-ground attrs,
ABC_CSS_FONT() for font attrs,
ABC_CSS_TEXT() for text align, etc.
6, and render the margin of HTML objects transparent / clearing.

19 files changed:
examples/p_multi_line.html
examples/style.css
html/abc_css_border.c
html/abc_css_position.c
html/abc_html.c
html/abc_obj.h
js/lex/scf_lex_util.c
js/util/Makefile
js/util/scf_string.c
js/util/scf_string.h
ui/Makefile
ui/__render_bg_image.c [new file with mode: 0644]
ui/__render_border.c [new file with mode: 0644]
ui/__render_text.c [new file with mode: 0644]
ui/abc.h
ui/abc_render_body.c
ui/abc_render_h1.c
ui/abc_render_table.c
ui/abc_render_td.c

index b90bf63b61d8a00d7f78d22edc80e3c85762e075..efb792e79e5e63b7ccdf659ebbf2f2a057d50faa 100644 (file)
@@ -4,8 +4,8 @@
 <style>
 p
 {
-       border:1px solid red;
-       background-color:green;
+       border:1px solid ;
+       background-color: 绿;
        color:white;
 }
 </style>
index ddfedd42570a8ff096b979b84c27694a94ae687c..23371ec52a18fb89b6c147f1fb478df6e71ee696 100644 (file)
@@ -1,6 +1,6 @@
 body
 {
-       background: #b0c4de  url('img.png')     no-repeat right top ;
+       background: #b0c4de  url('img.png')     repeat-x right 上 ;
 }
 h1 {background-color:#6495ed;}
 
index f2ef57bfcfb3885674ac1af07662a15d4881e311..adfc471839126bffae99e9caba79c4326b05af5b 100644 (file)
@@ -41,18 +41,22 @@ int abc_css_border(double* r, double* g, double* b, int* width, int* type, abc_o
        *width = 1;
        *type  = ABC_BORDER_SOLID;
 
-       const uint8_t* p    = str;
+       const uint8_t* p    = NULL;
        const uint8_t* unit = NULL;
 
        double  value   = 0.0;
        int     dot     = 0;
        int     percent = 0;
-       int     prev    = 0;
+       int     prev    = ' ';
        int     i       = 0;
        int     c       = 0;
 
        do {
-               c = *str;
+               size_t n = -1;
+
+               c = scf_utf8_len(str, &n);
+               if (c < 0)
+                       return -EINVAL;
 
                if ('.' == c)
                        dot = 10;
@@ -63,7 +67,9 @@ int abc_css_border(double* r, double* g, double* b, int* width, int* type, abc_o
                        if (' ' == prev || '\t' == prev || '\r' == prev || '\n' == prev)
                                p = str;
 
-               } else if ('a' <= c && 'z' >= c) {
+               } else if (('a' <= c && 'z' >= c)
+                               || ('A' <= c && 'Z' >= c)
+                               || (0x4e00 <= c && 0x9fa5 >= c)) {
 
                        if (' ' == prev || '\t' == prev || '\r' == prev || '\n' == prev)
                                p = str;
@@ -91,15 +97,12 @@ int abc_css_border(double* r, double* g, double* b, int* width, int* type, abc_o
                                if (0 == i)
                                        *width = value;
 
-                       } else if ('a' <= *p && *p <= 'z') {
-                               if (1 == i)
-                                       __css_border_type(type, p, (size_t)(str - p));
-                               else if (i > 1)
-                                       abc_css_color(r, g, b, p);
+                       } else if (p) {
 
-                       } else if ('#' == *p) {
                                if (i > 1)
                                        abc_css_color(r, g, b, p);
+                               else if (1 == i)
+                                       __css_border_type(type, p, (size_t)(str - p));
 
                        } else if (unit) {
                                // for other css units, ignore
@@ -108,7 +111,7 @@ int abc_css_border(double* r, double* g, double* b, int* width, int* type, abc_o
                                        *width = value;
                        }
 
-                       p       = str;
+                       p       = NULL;
                        unit    = NULL;
                        value   = 0.0;
                        dot     = 0;
@@ -121,7 +124,7 @@ int abc_css_border(double* r, double* g, double* b, int* width, int* type, abc_o
 
 next:
                prev = c;
-               str++;
+               str += n;
        } while (c);
 
        return 0;
index 800d10d918af9817573c60323ecc56ded072b6be..52cb844befe853477bd9e89cca551e8378c10554 100644 (file)
@@ -40,33 +40,29 @@ int abc_css_position(float* x, float* y, float w, float h, abc_obj_t* obj, const
        *x = 0.5 - w / 2;
        *y = 0.5 - h / 2;
 
-       const uint8_t* p    = str;
+       const uint8_t* p    = NULL;
        const uint8_t* unit = NULL;
 
        double  value   = 0.0;
        int     dot     = 0;
        int     percent = 0;
-       int     prev    = 0;
+       int     prev    = ' ';
        int     i       = 0;
        int     c       = 0;
 
        do {
-               c = *str;
+               size_t n = -1;
+
+               c = scf_utf8_len(str, &n);
+               if (c < 0)
+                       return -EINVAL;
 
                if ('.' == c)
                        dot = 10;
                else if ('%' == c)
                        percent++;
 
-               else if ('a' <= c && 'z' >= c) {
-
-                       if (' ' == prev || '\t' == prev || '\r' == prev || '\n' == prev)
-                               p = str;
-                       else if (!unit)
-                               unit = str;
-
-               } else if ('0' <= c && '9' >= c) {
-
+               else if ('0' <= c && '9' >= c) {
                        if (dot > 0) {
                                value += (c - '0') / (double)dot;
                                dot   *= 10;
@@ -75,6 +71,15 @@ int abc_css_position(float* x, float* y, float w, float h, abc_obj_t* obj, const
                                value += c - '0';
                        }
 
+               } else if (('a' <= c && 'z' >= c)
+                               || ('A' <= c && 'Z' >= c)
+                               || (0x4e00 <= c && 0x9fa5 >= c)) {
+
+                       if (' ' == prev || '\t' == prev || '\r' == prev || '\n' == prev)
+                               p = str;
+                       else if (!unit)
+                               unit = str;
+
                } else if ('\0' == c || ' ' == c || '\t' == c || '\r' == c || '\n' == c) {
 
                        if (' ' == prev || '\t' == prev || '\r' == prev || '\n' == prev)
@@ -88,7 +93,7 @@ int abc_css_position(float* x, float* y, float w, float h, abc_obj_t* obj, const
                                else
                                        *x = value;
 
-                       } else if ('a' <= *p && *p <= 'z') {
+                       } else if (p) {
                                if (i > 0)
                                        __css_pos_value(y, p, (size_t)(str - p));
                                else
@@ -98,7 +103,7 @@ int abc_css_position(float* x, float* y, float w, float h, abc_obj_t* obj, const
                                // for other css units, ignore
                        }
 
-                       p       = str;
+                       p       = NULL;
                        unit    = NULL;
                        value   = 0.0;
                        dot     = 0;
@@ -108,7 +113,7 @@ int abc_css_position(float* x, float* y, float w, float h, abc_obj_t* obj, const
 
 next:
                prev = c;
-               str++;
+               str += n;
        } while (c);
 
        return 0;
index ebfdcb73c0e843025479284c28a10f3e5d96cc61..bd4f58b8c9a011ba123bad10ac6ac927100ab2c7 100644 (file)
@@ -132,385 +132,286 @@ static html_attr_t  meta_attrs[] =
 
 static html_attr_t  body_attrs[] =
 {
-       {font_keys,        "SimSong",  ABC_HTML_ATTR_FONT,            0},
-       {font_size_keys,   "16",       ABC_HTML_ATTR_FONT_SIZE,       0},
-       {font_color_keys,  "black",    ABC_HTML_ATTR_FONT_COLOR,      ABC_HTML_FLAG_SHOW},
-       {font_style_keys,  "",         ABC_HTML_ATTR_FONT_STYLE,      0},
-
-       {bg_keys,          "",         ABC_HTML_ATTR_BG,              ABC_HTML_FLAG_SHOW},
-       {bg_color_keys,    "white",    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},
+#define ABC_CSS_BOX(margin, border, padding) \
+       {margin_keys,     #margin,     ABC_HTML_ATTR_MARGIN,          ABC_HTML_FLAG_SHOW}, \
+       {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},
+
+#define ABC_CSS_SELECTOR() \
+       {style_keys,       "",         ABC_HTML_ATTR_STYLE,           ABC_HTML_FLAG_SHOW}, \
+       {class_keys,       "",         ABC_HTML_ATTR_CLASS,           ABC_HTML_FLAG_SHOW}, \
+       {id_keys,          "",         ABC_HTML_ATTR_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},
 
-       {text_align_keys,      "left", ABC_HTML_ATTR_TEXT_ALIGN,      ABC_HTML_FLAG_SHOW},
-       {text_decoration_keys, "",     ABC_HTML_ATTR_TEXT_DECORATION, ABC_HTML_FLAG_SHOW},
-       {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_FONT(font, size, color, style) \
+       {font_keys,        #font,      ABC_HTML_ATTR_FONT,            0}, \
+       {font_size_keys,   #size,      ABC_HTML_ATTR_FONT_SIZE,       0}, \
+       {font_color_keys,  #color,     ABC_HTML_ATTR_FONT_COLOR,      ABC_HTML_FLAG_SHOW}, \
+       {font_style_keys,  #style,     ABC_HTML_ATTR_FONT_STYLE,      0},
+
+#define ABC_CSS_TEXT(align, underline) \
+       {text_align_keys,      #align,      ABC_HTML_ATTR_TEXT_ALIGN,      ABC_HTML_FLAG_SHOW}, \
+       {text_decoration_keys, #underline,  ABC_HTML_ATTR_TEXT_DECORATION, ABC_HTML_FLAG_SHOW}, \
+       {text_transform_keys,  "",          ABC_HTML_ATTR_TEXT_TRANSFORM,  ABC_HTML_FLAG_SHOW}, \
+       {text_indent_keys,     "",          ABC_HTML_ATTR_TEXT_INDENT,     ABC_HTML_FLAG_SHOW},
+
+       ABC_CSS_BOX(4px, , 4px)
+       ABC_CSS_SELECTOR()
+       ABC_CSS_BACK_GROUND(white)
+
+       ABC_CSS_FONT(SimSong, 16, black, )
+       ABC_CSS_TEXT(left, )
 };
 
 static html_attr_t  h1_attrs[] =
 {
-       {class_keys,       "",         ABC_HTML_ATTR_CLASS,           ABC_HTML_FLAG_SHOW},
-       {style_keys,       "",         ABC_HTML_ATTR_STYLE,           ABC_HTML_FLAG_SHOW},
-       {id_keys,          "",         ABC_HTML_ATTR_ID,              ABC_HTML_FLAG_SHOW},
-       {font_keys,        "SimHei",   ABC_HTML_ATTR_FONT,            0},
-       {font_size_keys,   "40",       ABC_HTML_ATTR_FONT_SIZE,       0},
-       {font_color_keys,  "black",    ABC_HTML_ATTR_FONT_COLOR,      ABC_HTML_FLAG_SHOW},
-       {font_style_keys,  "",         ABC_HTML_ATTR_FONT_STYLE,      0},
+       ABC_CSS_BOX(2px, , 2px)
+       ABC_CSS_SELECTOR()
+       ABC_CSS_BACK_GROUND()
 
-       {bg_color_keys,    "",         ABC_HTML_ATTR_BG_COLOR,        ABC_HTML_FLAG_SHOW},
-
-       {text_align_keys,      "left", ABC_HTML_ATTR_TEXT_ALIGN,      ABC_HTML_FLAG_SHOW},
-       {text_decoration_keys, "",     ABC_HTML_ATTR_TEXT_DECORATION, ABC_HTML_FLAG_SHOW},
-       {text_transform_keys,  "",     ABC_HTML_ATTR_TEXT_TRANSFORM,  ABC_HTML_FLAG_SHOW},
-       {text_indent_keys,     "",     ABC_HTML_ATTR_TEXT_INDENT,     ABC_HTML_FLAG_SHOW},
+       ABC_CSS_FONT(SimHei, 40, black, )
+       ABC_CSS_TEXT(left, )
 };
 
 static html_attr_t  h2_attrs[] =
 {
-       {class_keys,       "",         ABC_HTML_ATTR_CLASS,           ABC_HTML_FLAG_SHOW},
-       {style_keys,       "",         ABC_HTML_ATTR_STYLE,           ABC_HTML_FLAG_SHOW},
-       {id_keys,          "",         ABC_HTML_ATTR_ID,              ABC_HTML_FLAG_SHOW},
-       {font_keys,        "SimHei",   ABC_HTML_ATTR_FONT,            0},
-       {font_size_keys,   "32",       ABC_HTML_ATTR_FONT_SIZE,       0},
-       {font_color_keys,  "black",    ABC_HTML_ATTR_FONT_COLOR,      ABC_HTML_FLAG_SHOW},
-       {font_style_keys,  "",         ABC_HTML_ATTR_FONT_STYLE,      0},
+       ABC_CSS_BOX(2px, , 2px)
+       ABC_CSS_SELECTOR()
+       ABC_CSS_BACK_GROUND()
 
-       {bg_color_keys,    "",         ABC_HTML_ATTR_BG_COLOR,        ABC_HTML_FLAG_SHOW},
-
-       {text_align_keys,      "left", ABC_HTML_ATTR_TEXT_ALIGN,      ABC_HTML_FLAG_SHOW},
-       {text_decoration_keys, "",     ABC_HTML_ATTR_TEXT_DECORATION, ABC_HTML_FLAG_SHOW},
-       {text_transform_keys,  "",     ABC_HTML_ATTR_TEXT_TRANSFORM,  ABC_HTML_FLAG_SHOW},
-       {text_indent_keys,     "",     ABC_HTML_ATTR_TEXT_INDENT,     ABC_HTML_FLAG_SHOW},
+       ABC_CSS_FONT(SimHei, 32, black, )
+       ABC_CSS_TEXT(left, )
 };
 
 static html_attr_t  h3_attrs[] =
 {
-       {class_keys,       "",         ABC_HTML_ATTR_CLASS,           ABC_HTML_FLAG_SHOW},
-       {style_keys,       "",         ABC_HTML_ATTR_STYLE,           ABC_HTML_FLAG_SHOW},
-       {id_keys,          "",         ABC_HTML_ATTR_ID,              ABC_HTML_FLAG_SHOW},
-       {font_keys,        "SimHei",   ABC_HTML_ATTR_FONT,            0},
-       {font_size_keys,   "28",       ABC_HTML_ATTR_FONT_SIZE,       0},
-       {font_color_keys,  "black",    ABC_HTML_ATTR_FONT_COLOR,      ABC_HTML_FLAG_SHOW},
-       {font_style_keys,  "",         ABC_HTML_ATTR_FONT_STYLE,      0},
-
-       {bg_color_keys,    "",         ABC_HTML_ATTR_BG_COLOR,        ABC_HTML_FLAG_SHOW},
+       ABC_CSS_BOX(2px, , 2px)
+       ABC_CSS_SELECTOR()
+       ABC_CSS_BACK_GROUND()
 
-       {text_align_keys,      "left", ABC_HTML_ATTR_TEXT_ALIGN,      ABC_HTML_FLAG_SHOW},
-       {text_decoration_keys, "",     ABC_HTML_ATTR_TEXT_DECORATION, ABC_HTML_FLAG_SHOW},
-       {text_transform_keys,  "",     ABC_HTML_ATTR_TEXT_TRANSFORM,  ABC_HTML_FLAG_SHOW},
-       {text_indent_keys,     "",     ABC_HTML_ATTR_TEXT_INDENT,     ABC_HTML_FLAG_SHOW},
+       ABC_CSS_FONT(SimHei, 28, black, )
+       ABC_CSS_TEXT(left, )
 };
 
 static html_attr_t  h4_attrs[] =
 {
-       {class_keys,       "",         ABC_HTML_ATTR_CLASS,           ABC_HTML_FLAG_SHOW},
-       {style_keys,       "",         ABC_HTML_ATTR_STYLE,           ABC_HTML_FLAG_SHOW},
-       {id_keys,          "",         ABC_HTML_ATTR_ID,              ABC_HTML_FLAG_SHOW},
-       {font_keys,        "SimHei",   ABC_HTML_ATTR_FONT,            0},
-       {font_size_keys,   "24",       ABC_HTML_ATTR_FONT_SIZE,       0},
-       {font_color_keys,  "black",    ABC_HTML_ATTR_FONT_COLOR,      ABC_HTML_FLAG_SHOW},
-       {font_style_keys,  "",         ABC_HTML_ATTR_FONT_STYLE,      0},
-
-       {bg_color_keys,    "",         ABC_HTML_ATTR_BG_COLOR,        ABC_HTML_FLAG_SHOW},
+       ABC_CSS_BOX(2px, , 2px)
+       ABC_CSS_SELECTOR()
+       ABC_CSS_BACK_GROUND()
 
-       {text_align_keys,      "left", ABC_HTML_ATTR_TEXT_ALIGN,      ABC_HTML_FLAG_SHOW},
-       {text_decoration_keys, "",     ABC_HTML_ATTR_TEXT_DECORATION, ABC_HTML_FLAG_SHOW},
-       {text_transform_keys,  "",     ABC_HTML_ATTR_TEXT_TRANSFORM,  ABC_HTML_FLAG_SHOW},
-       {text_indent_keys,     "",     ABC_HTML_ATTR_TEXT_INDENT,     ABC_HTML_FLAG_SHOW},
+       ABC_CSS_FONT(SimHei, 24, black, )
+       ABC_CSS_TEXT(left, )
 };
 
 static html_attr_t  h5_attrs[] =
 {
-       {class_keys,       "",         ABC_HTML_ATTR_CLASS,           ABC_HTML_FLAG_SHOW},
-       {style_keys,       "",         ABC_HTML_ATTR_STYLE,           ABC_HTML_FLAG_SHOW},
-       {id_keys,          "",         ABC_HTML_ATTR_ID,              ABC_HTML_FLAG_SHOW},
-       {font_keys,        "SimHei",   ABC_HTML_ATTR_FONT,            0},
-       {font_size_keys,   "20",       ABC_HTML_ATTR_FONT_SIZE,       0},
-       {font_color_keys,  "black",    ABC_HTML_ATTR_FONT_COLOR,      ABC_HTML_FLAG_SHOW},
-       {font_style_keys,  "",         ABC_HTML_ATTR_FONT_STYLE,      0},
-
-       {bg_color_keys,    "",         ABC_HTML_ATTR_BG_COLOR,        ABC_HTML_FLAG_SHOW},
+       ABC_CSS_BOX(2px, , 2px)
+       ABC_CSS_SELECTOR()
+       ABC_CSS_BACK_GROUND()
 
-       {text_align_keys,      "left", ABC_HTML_ATTR_TEXT_ALIGN,      ABC_HTML_FLAG_SHOW},
-       {text_decoration_keys, "",     ABC_HTML_ATTR_TEXT_DECORATION, ABC_HTML_FLAG_SHOW},
-       {text_transform_keys,  "",     ABC_HTML_ATTR_TEXT_TRANSFORM,  ABC_HTML_FLAG_SHOW},
-       {text_indent_keys,     "",     ABC_HTML_ATTR_TEXT_INDENT,     ABC_HTML_FLAG_SHOW},
+       ABC_CSS_FONT(SimHei, 20, black, )
+       ABC_CSS_TEXT(left, )
 };
 
 static html_attr_t  h6_attrs[] =
 {
-       {class_keys,       "",         ABC_HTML_ATTR_CLASS,           ABC_HTML_FLAG_SHOW},
-       {style_keys,       "",         ABC_HTML_ATTR_STYLE,           ABC_HTML_FLAG_SHOW},
-       {id_keys,          "",         ABC_HTML_ATTR_ID,              ABC_HTML_FLAG_SHOW},
-       {font_keys,        "SimHei",   ABC_HTML_ATTR_FONT,            0},
-       {font_size_keys,   "16",       ABC_HTML_ATTR_FONT_SIZE,       0},
-       {font_color_keys,  "black",    ABC_HTML_ATTR_FONT_COLOR,      ABC_HTML_FLAG_SHOW},
-       {font_style_keys,  "",         ABC_HTML_ATTR_FONT_STYLE,      0},
-
-       {bg_color_keys,    "",         ABC_HTML_ATTR_BG_COLOR,        ABC_HTML_FLAG_SHOW},
+       ABC_CSS_BOX(2px, , 2px)
+       ABC_CSS_SELECTOR()
+       ABC_CSS_BACK_GROUND()
 
-       {text_align_keys,      "left", ABC_HTML_ATTR_TEXT_ALIGN,      ABC_HTML_FLAG_SHOW},
-       {text_decoration_keys, "",     ABC_HTML_ATTR_TEXT_DECORATION, ABC_HTML_FLAG_SHOW},
-       {text_transform_keys,  "",     ABC_HTML_ATTR_TEXT_TRANSFORM,  ABC_HTML_FLAG_SHOW},
-       {text_indent_keys,     "",     ABC_HTML_ATTR_TEXT_INDENT,     ABC_HTML_FLAG_SHOW},
+       ABC_CSS_FONT(SimHei, 16, black, )
+       ABC_CSS_TEXT(left, )
 };
 
 static html_attr_t  p_attrs[] =
 {
-       {margin_keys,      "",         ABC_HTML_ATTR_MARGIN,          ABC_HTML_FLAG_SHOW},
-       {border_keys,      "",         ABC_HTML_ATTR_BORDER,          ABC_HTML_FLAG_SHOW},
-       {padding_keys,     "",         ABC_HTML_ATTR_PADDING,         ABC_HTML_FLAG_SHOW},
+       ABC_CSS_BOX(2px, , 2px)
+       ABC_CSS_SELECTOR()
+       ABC_CSS_BACK_GROUND()
 
-       {width_keys,       "",         ABC_HTML_ATTR_WIDTH,           ABC_HTML_FLAG_SHOW},
-       {height_keys,      "",         ABC_HTML_ATTR_HEIGHT,          ABC_HTML_FLAG_SHOW},
-
-       {class_keys,       "",         ABC_HTML_ATTR_CLASS,           ABC_HTML_FLAG_SHOW},
-       {style_keys,       "",         ABC_HTML_ATTR_STYLE,           ABC_HTML_FLAG_SHOW},
-       {id_keys,          "",         ABC_HTML_ATTR_ID,              ABC_HTML_FLAG_SHOW},
-       {font_keys,        "SimSong",  ABC_HTML_ATTR_FONT,            0},
-       {font_size_keys,   "16",       ABC_HTML_ATTR_FONT_SIZE,       0},
-       {font_color_keys,  "black",    ABC_HTML_ATTR_FONT_COLOR,      ABC_HTML_FLAG_SHOW},
-       {font_style_keys,  "",         ABC_HTML_ATTR_FONT_STYLE,      0},
-
-       {bg_color_keys,    "",         ABC_HTML_ATTR_BG_COLOR,        ABC_HTML_FLAG_SHOW},
-
-       {text_align_keys,      "left", ABC_HTML_ATTR_TEXT_ALIGN,      ABC_HTML_FLAG_SHOW},
-       {text_decoration_keys, "",     ABC_HTML_ATTR_TEXT_DECORATION, ABC_HTML_FLAG_SHOW},
-       {text_transform_keys,  "",     ABC_HTML_ATTR_TEXT_TRANSFORM,  ABC_HTML_FLAG_SHOW},
-       {text_indent_keys,     "",     ABC_HTML_ATTR_TEXT_INDENT,     ABC_HTML_FLAG_SHOW},
+       ABC_CSS_FONT(SimSong, 16, black, )
+       ABC_CSS_TEXT(left, )
 };
 
 static html_attr_t  css_id_attrs[] =
 {
-       {margin_keys,      "2",        ABC_HTML_ATTR_MARGIN,          ABC_HTML_FLAG_SHOW},
-       {border_keys,      "1",        ABC_HTML_ATTR_BORDER,          ABC_HTML_FLAG_SHOW},
-       {padding_keys,     "4",        ABC_HTML_ATTR_PADDING,         ABC_HTML_FLAG_SHOW},
-
-       {font_keys,         "SimSong",  ABC_HTML_ATTR_FONT,            0},
-       {font_size_keys,    "16",       ABC_HTML_ATTR_FONT_SIZE,       0},
-       {font_color_keys,   "black",    ABC_HTML_ATTR_FONT_COLOR,      ABC_HTML_FLAG_SHOW},
-       {font_style_keys,   "",         ABC_HTML_ATTR_FONT_STYLE,      0},
-
-       {bg_color_keys,     "",         ABC_HTML_ATTR_BG_COLOR,        ABC_HTML_FLAG_SHOW},
+#define ABC_CSS_LIST() \
+       {list_style_keys,       "",     ABC_CSS_LIST_STYLE,            ABC_HTML_FLAG_SHOW}, \
+       {list_style_type_keys,  "",     ABC_CSS_LIST_STYLE_TYPE,       ABC_HTML_FLAG_SHOW}, \
+       {list_style_image_keys, "",     ABC_CSS_LIST_STYLE_IMAGE,      ABC_HTML_FLAG_SHOW}, \
+       {list_style_pos_keys,   "",     ABC_CSS_LIST_STYLE_POSITION,   ABC_HTML_FLAG_SHOW},
 
-       {text_align_keys,       "left", ABC_HTML_ATTR_TEXT_ALIGN,      ABC_HTML_FLAG_SHOW},
-       {text_decoration_keys,  "",     ABC_HTML_ATTR_TEXT_DECORATION, ABC_HTML_FLAG_SHOW},
-       {text_transform_keys,   "",     ABC_HTML_ATTR_TEXT_TRANSFORM,  ABC_HTML_FLAG_SHOW},
-       {text_indent_keys,      "",     ABC_HTML_ATTR_TEXT_INDENT,     ABC_HTML_FLAG_SHOW},
+       ABC_CSS_BOX(2px, , 2px)
+       ABC_CSS_SELECTOR()
+       ABC_CSS_BACK_GROUND()
 
-       {vertical_align_keys,   "",     ABC_HTML_ATTR_VERTICAL_ALIGN,  ABC_HTML_FLAG_SHOW},
+       ABC_CSS_FONT(SimSong, 16, black, )
+       ABC_CSS_TEXT(left, )
+       ABC_CSS_LIST()
 
-       {list_style_keys,       "",     ABC_CSS_LIST_STYLE,            ABC_HTML_FLAG_SHOW},
-       {list_style_type_keys,  "",     ABC_CSS_LIST_STYLE_TYPE,       ABC_HTML_FLAG_SHOW},
-       {list_style_image_keys, "",     ABC_CSS_LIST_STYLE_IMAGE,      ABC_HTML_FLAG_SHOW},
-       {list_style_pos_keys,   "",     ABC_CSS_LIST_STYLE_POSITION,   ABC_HTML_FLAG_SHOW},
+       {vertical_align_keys,  "",  ABC_HTML_ATTR_VERTICAL_ALIGN,  ABC_HTML_FLAG_SHOW},
 };
 
 static html_attr_t  b_attrs[] =
 {
-       {font_keys,        "SimHei",   ABC_HTML_ATTR_FONT,            0},
-       {font_size_keys,   "16",       ABC_HTML_ATTR_FONT_SIZE,       0},
-       {font_color_keys,  "",         ABC_HTML_ATTR_FONT_COLOR,      ABC_HTML_FLAG_SHOW},
-       {font_style_keys,  "bold",     ABC_HTML_ATTR_FONT_STYLE,      0},
+       ABC_CSS_BOX( , , )
+       ABC_CSS_SELECTOR()
+       ABC_CSS_BACK_GROUND()
 
-       {bg_color_keys,    "",         ABC_HTML_ATTR_BG_COLOR,        ABC_HTML_FLAG_SHOW},
-
-       {text_align_keys,      "left", ABC_HTML_ATTR_TEXT_ALIGN,      ABC_HTML_FLAG_SHOW},
-       {text_decoration_keys, "",     ABC_HTML_ATTR_TEXT_DECORATION, ABC_HTML_FLAG_SHOW},
-       {text_transform_keys,  "",     ABC_HTML_ATTR_TEXT_TRANSFORM,  ABC_HTML_FLAG_SHOW},
-       {text_indent_keys,     "",     ABC_HTML_ATTR_TEXT_INDENT,     ABC_HTML_FLAG_SHOW},
+       ABC_CSS_FONT(SimHei, 16, , bold)
+       ABC_CSS_TEXT(left, )
 };
 
 static html_attr_t  i_attrs[] =
 {
-       {font_keys,        "SimSong",  ABC_HTML_ATTR_FONT,            0},
-       {font_size_keys,   "16",       ABC_HTML_ATTR_FONT_SIZE,       0},
-       {font_color_keys,  "",         ABC_HTML_ATTR_FONT_COLOR,      ABC_HTML_FLAG_SHOW},
-       {font_style_keys,  "italic",   ABC_HTML_ATTR_FONT_STYLE,      0},
-
-       {bg_color_keys,    "",         ABC_HTML_ATTR_BG_COLOR,        ABC_HTML_FLAG_SHOW},
+       ABC_CSS_BOX( , , )
+       ABC_CSS_SELECTOR()
+       ABC_CSS_BACK_GROUND()
 
-       {text_align_keys,      "left", ABC_HTML_ATTR_TEXT_ALIGN,      ABC_HTML_FLAG_SHOW},
-       {text_decoration_keys, "",     ABC_HTML_ATTR_TEXT_DECORATION, ABC_HTML_FLAG_SHOW},
-       {text_transform_keys,  "",     ABC_HTML_ATTR_TEXT_TRANSFORM,  ABC_HTML_FLAG_SHOW},
-       {text_indent_keys,     "",     ABC_HTML_ATTR_TEXT_INDENT,     ABC_HTML_FLAG_SHOW},
+       ABC_CSS_FONT(SimSong, 16, , italic)
+       ABC_CSS_TEXT(left, )
 };
 
 static html_attr_t  a_attrs[] =
 {
-       {href_keys,        "",         ABC_HTML_ATTR_HREF,            ABC_HTML_FLAG_SHOW},
-       {class_keys,       "",         ABC_HTML_ATTR_CLASS,           ABC_HTML_FLAG_SHOW},
-       {style_keys,       "",         ABC_HTML_ATTR_STYLE,           ABC_HTML_FLAG_SHOW},
-       {id_keys,          "",         ABC_HTML_ATTR_ID,              ABC_HTML_FLAG_SHOW},
-
-       {font_keys,        "SimSong",  ABC_HTML_ATTR_FONT,            0},
-       {font_size_keys,   "16",       ABC_HTML_ATTR_FONT_SIZE,       0},
-       {font_color_keys,  "blue",     ABC_HTML_ATTR_FONT_COLOR,      ABC_HTML_FLAG_SHOW},
-       {font_style_keys,  "",         ABC_HTML_ATTR_FONT_STYLE,      0},
+       ABC_CSS_BOX( , , )
+       ABC_CSS_SELECTOR()
+       ABC_CSS_BACK_GROUND()
 
-       {bg_color_keys,    "",         ABC_HTML_ATTR_BG_COLOR,        ABC_HTML_FLAG_SHOW},
+       ABC_CSS_FONT(SimSong, 16, blue, )
+       ABC_CSS_TEXT(left, underline)
 
-       {text_align_keys,      "left",      ABC_HTML_ATTR_TEXT_ALIGN,      ABC_HTML_FLAG_SHOW},
-       {text_decoration_keys, "underline", ABC_HTML_ATTR_TEXT_DECORATION, ABC_HTML_FLAG_SHOW},
-       {text_transform_keys,  "",          ABC_HTML_ATTR_TEXT_TRANSFORM,  ABC_HTML_FLAG_SHOW},
-       {text_indent_keys,     "",          ABC_HTML_ATTR_TEXT_INDENT,     ABC_HTML_FLAG_SHOW},
+       {href_keys,  "",  ABC_HTML_ATTR_HREF,  ABC_HTML_FLAG_SHOW},
 };
 
 static html_attr_t  link_attrs[] =
 {
-       {rel_keys,         "",           ABC_HTML_ATTR_REL,        ABC_HTML_FLAG_SHOW},
-       {type_keys,        "",           ABC_HTML_ATTR_TYPE,       ABC_HTML_FLAG_SHOW},
-       {href_keys,        "",           ABC_HTML_ATTR_HREF,       ABC_HTML_FLAG_SHOW},
+       {rel_keys,   "",  ABC_HTML_ATTR_REL,   ABC_HTML_FLAG_SHOW},
+       {type_keys,  "",  ABC_HTML_ATTR_TYPE,  ABC_HTML_FLAG_SHOW},
+       {href_keys,  "",  ABC_HTML_ATTR_HREF,  ABC_HTML_FLAG_SHOW},
 };
 
 static html_attr_t  img_attrs[] =
 {
-       {margin_keys,      "",         ABC_HTML_ATTR_MARGIN,       ABC_HTML_FLAG_SHOW},
-       {border_keys,      "",         ABC_HTML_ATTR_BORDER,       ABC_HTML_FLAG_SHOW},
-       {padding_keys,     "",         ABC_HTML_ATTR_PADDING,      ABC_HTML_FLAG_SHOW},
+       ABC_CSS_BOX( , , )
+       ABC_CSS_SELECTOR()
 
-       {src_keys,         "",         ABC_HTML_ATTR_SRC,          ABC_HTML_FLAG_SHOW},
-       {width_keys,       "100",      ABC_HTML_ATTR_WIDTH,        ABC_HTML_FLAG_SHOW},
-       {height_keys,      "100",      ABC_HTML_ATTR_HEIGHT,       ABC_HTML_FLAG_SHOW},
+       {src_keys,  "",  ABC_HTML_ATTR_SRC,  ABC_HTML_FLAG_SHOW},
 };
 
 static html_attr_t  video_attrs[] =
 {
-       {margin_keys,      "",         ABC_HTML_ATTR_MARGIN,       ABC_HTML_FLAG_SHOW},
-       {border_keys,      "",         ABC_HTML_ATTR_BORDER,       ABC_HTML_FLAG_SHOW},
-       {padding_keys,     "",         ABC_HTML_ATTR_PADDING,      ABC_HTML_FLAG_SHOW},
+       ABC_CSS_BOX( , , )
+       ABC_CSS_SELECTOR()
 
-       {width_keys,       "100",        ABC_HTML_ATTR_WIDTH,      ABC_HTML_FLAG_SHOW},
-       {height_keys,      "100",        ABC_HTML_ATTR_HEIGHT,     ABC_HTML_FLAG_SHOW},
-       {control_keys,     "",           ABC_HTML_ATTR_CONTROLS,   0},
+       {control_keys,  "",  ABC_HTML_ATTR_CONTROLS,  0},
 };
 
 static html_attr_t  audio_attrs[] =
 {
-       {control_keys,     "",           ABC_HTML_ATTR_CONTROLS,   0},
+       {control_keys,  "",  ABC_HTML_ATTR_CONTROLS,  0},
 };
 
 static html_attr_t  source_attrs[] =
 {
-       {src_keys,         "",           ABC_HTML_ATTR_SRC,        ABC_HTML_FLAG_SHOW},
-       {type_keys,        "",           ABC_HTML_ATTR_TYPE,       ABC_HTML_FLAG_SHOW},
+       {src_keys,   "",  ABC_HTML_ATTR_SRC,   ABC_HTML_FLAG_SHOW},
+       {type_keys,  "",  ABC_HTML_ATTR_TYPE,  ABC_HTML_FLAG_SHOW},
 };
 
 static html_attr_t  input_attrs[] =
 {
-       {type_keys,        "text",       ABC_HTML_ATTR_TYPE,       ABC_HTML_FLAG_SHOW},
-       {id_keys,          "",           ABC_HTML_ATTR_ID,         ABC_HTML_FLAG_SHOW},
-       {name_keys,        "",           ABC_HTML_ATTR_NAME,       ABC_HTML_FLAG_SHOW},
-       {value_keys,       "",           ABC_HTML_ATTR_VALUE,      ABC_HTML_FLAG_SHOW},
+       ABC_CSS_BOX(1px, 1px, 1px)
+       ABC_CSS_SELECTOR()
+       ABC_CSS_BACK_GROUND()
 
-       {font_keys,        "SimSong",    ABC_HTML_ATTR_FONT,       0},
-       {font_size_keys,   "16",         ABC_HTML_ATTR_FONT_SIZE,  0},
+       ABC_CSS_FONT(SimSong, 16, black, )
+       ABC_CSS_TEXT(left, )
+
+       {type_keys,   "text",  ABC_HTML_ATTR_TYPE,   ABC_HTML_FLAG_SHOW},
+       {name_keys,   "",      ABC_HTML_ATTR_NAME,   ABC_HTML_FLAG_SHOW},
+       {value_keys,  "",      ABC_HTML_ATTR_VALUE,  ABC_HTML_FLAG_SHOW},
 };
 
 static html_attr_t  label_attrs[] =
 {
-       {for_keys,         "",           ABC_HTML_ATTR_FOR,        ABC_HTML_FLAG_SHOW},
+       ABC_CSS_BOX(1px, 1px, 1px)
+       ABC_CSS_SELECTOR()
+       ABC_CSS_BACK_GROUND()
+
+       ABC_CSS_FONT(SimSong, 16, black, )
+       ABC_CSS_TEXT(left, )
 
-       {font_keys,        "SimSong",    ABC_HTML_ATTR_FONT,       0},
-       {font_size_keys,   "16",         ABC_HTML_ATTR_FONT_SIZE,  0},
+       {for_keys,  "",  ABC_HTML_ATTR_FOR,  ABC_HTML_FLAG_SHOW},
 };
 
 static html_attr_t  form_attrs[] =
 {
-       {action_keys,      "/",          ABC_HTML_ATTR_ACTION,     ABC_HTML_FLAG_SHOW},
-       {method_keys,      "post",       ABC_HTML_ATTR_METHOD,     ABC_HTML_FLAG_SHOW},
+       ABC_CSS_BOX(1px, 1px, 1px)
+       ABC_CSS_SELECTOR()
+       ABC_CSS_BACK_GROUND()
 
-       {font_keys,        "SimSong",    ABC_HTML_ATTR_FONT,       0},
-       {font_size_keys,   "16",         ABC_HTML_ATTR_FONT_SIZE,  0},
+       ABC_CSS_FONT(SimSong, 16, black, )
+       ABC_CSS_TEXT(left, )
 
-       {enctype_keys,     "",           ABC_HTML_ATTR_ENCTYPE,    0},
+       {action_keys,   "/",     ABC_HTML_ATTR_ACTION,   ABC_HTML_FLAG_SHOW},
+       {method_keys,   "post",  ABC_HTML_ATTR_METHOD,   ABC_HTML_FLAG_SHOW},
+       {enctype_keys,  "",      ABC_HTML_ATTR_ENCTYPE,  0},
 };
 
 static html_attr_t  ol_attrs[] =
 {
-       {class_keys,       "",         ABC_HTML_ATTR_CLASS,           ABC_HTML_FLAG_SHOW},
-       {style_keys,       "",         ABC_HTML_ATTR_STYLE,           ABC_HTML_FLAG_SHOW},
-       {id_keys,          "",         ABC_HTML_ATTR_ID,              ABC_HTML_FLAG_SHOW},
-       {font_keys,        "SimSong",  ABC_HTML_ATTR_FONT,            0},
-       {font_size_keys,   "16",       ABC_HTML_ATTR_FONT_SIZE,       0},
-       {font_color_keys,  "black",    ABC_HTML_ATTR_FONT_COLOR,      ABC_HTML_FLAG_SHOW},
-       {font_style_keys,  "",         ABC_HTML_ATTR_FONT_STYLE,      0},
-
-       {bg_color_keys,    "",         ABC_HTML_ATTR_BG_COLOR,        ABC_HTML_FLAG_SHOW},
+       ABC_CSS_BOX(2px, , 2px)
+       ABC_CSS_SELECTOR()
+       ABC_CSS_BACK_GROUND()
 
-       {list_style_type_keys,  "",    ABC_CSS_LIST_STYLE_TYPE,       ABC_HTML_FLAG_SHOW},
-       {list_style_image_keys, "",    ABC_CSS_LIST_STYLE_IMAGE,      ABC_HTML_FLAG_SHOW},
-       {list_style_pos_keys,   "",    ABC_CSS_LIST_STYLE_POSITION,   ABC_HTML_FLAG_SHOW},
+       ABC_CSS_FONT(SimSong, 16, black, )
+       ABC_CSS_TEXT(left, )
+       ABC_CSS_LIST()
 };
 
 static html_attr_t  table_attrs[] =
 {
-       {margin_keys,      "2",        ABC_HTML_ATTR_MARGIN,          ABC_HTML_FLAG_SHOW},
-       {border_keys,      "1",        ABC_HTML_ATTR_BORDER,          ABC_HTML_FLAG_SHOW},
-       {padding_keys,     "4",        ABC_HTML_ATTR_PADDING,         ABC_HTML_FLAG_SHOW},
+       ABC_CSS_BOX(2px, 2px, 4px)
+       ABC_CSS_SELECTOR()
+       ABC_CSS_BACK_GROUND()
 
-       {width_keys,       "",         ABC_HTML_ATTR_WIDTH,           ABC_HTML_FLAG_SHOW},
-       {height_keys,      "",         ABC_HTML_ATTR_HEIGHT,          ABC_HTML_FLAG_SHOW},
-
-       {class_keys,       "",         ABC_HTML_ATTR_CLASS,           ABC_HTML_FLAG_SHOW},
-       {style_keys,       "",         ABC_HTML_ATTR_STYLE,           ABC_HTML_FLAG_SHOW},
-       {id_keys,          "",         ABC_HTML_ATTR_ID,              ABC_HTML_FLAG_SHOW},
-       {font_keys,        "SimSong",  ABC_HTML_ATTR_FONT,            0},
-       {font_size_keys,   "16",       ABC_HTML_ATTR_FONT_SIZE,       0},
-       {font_color_keys,  "black",    ABC_HTML_ATTR_FONT_COLOR,      ABC_HTML_FLAG_SHOW},
-       {font_style_keys,  "",         ABC_HTML_ATTR_FONT_STYLE,      0},
+       ABC_CSS_FONT(SimSong, 16, black, )
+       ABC_CSS_TEXT(left, )
 
-       {bg_color_keys,    "",         ABC_HTML_ATTR_BG_COLOR,        ABC_HTML_FLAG_SHOW},
-
-       {border_collapse_keys, "",     ABC_CSS_BORDER_COLLAPSE,       ABC_HTML_FLAG_SHOW},
+       {border_collapse_keys,  "",  ABC_CSS_BORDER_COLLAPSE,  ABC_HTML_FLAG_SHOW},
 };
 
 static html_attr_t  th_attrs[] =
 {
-       {margin_keys,      "2",        ABC_HTML_ATTR_MARGIN,          ABC_HTML_FLAG_SHOW},
-       {border_keys,      "1",        ABC_HTML_ATTR_BORDER,          ABC_HTML_FLAG_SHOW},
-       {padding_keys,     "4",        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},
+       ABC_CSS_BOX(2px, 2px, 4px)
+       ABC_CSS_SELECTOR()
+       ABC_CSS_BACK_GROUND()
 
-       {class_keys,       "",         ABC_HTML_ATTR_CLASS,           ABC_HTML_FLAG_SHOW},
-       {style_keys,       "",         ABC_HTML_ATTR_STYLE,           ABC_HTML_FLAG_SHOW},
-       {id_keys,          "",         ABC_HTML_ATTR_ID,              ABC_HTML_FLAG_SHOW},
-       {font_keys,        "SimHei",   ABC_HTML_ATTR_FONT,            0},
-       {font_size_keys,   "18",       ABC_HTML_ATTR_FONT_SIZE,       0},
-       {font_color_keys,  "black",    ABC_HTML_ATTR_FONT_COLOR,      ABC_HTML_FLAG_SHOW},
-       {font_style_keys,  "",         ABC_HTML_ATTR_FONT_STYLE,      0},
+       ABC_CSS_FONT(SimHei, 24, black, )
+       ABC_CSS_TEXT( , )
 
-       {bg_color_keys,    "",         ABC_HTML_ATTR_BG_COLOR,        ABC_HTML_FLAG_SHOW},
-
-       {text_align_keys,      "",     ABC_HTML_ATTR_TEXT_ALIGN,      ABC_HTML_FLAG_SHOW},
-       {vertical_align_keys,  "",     ABC_HTML_ATTR_VERTICAL_ALIGN,  ABC_HTML_FLAG_SHOW},
+       {vertical_align_keys,  "",  ABC_HTML_ATTR_VERTICAL_ALIGN,  ABC_HTML_FLAG_SHOW},
 };
 
 static html_attr_t  td_attrs[] =
 {
-       {margin_keys,      "2",        ABC_HTML_ATTR_MARGIN,          ABC_HTML_FLAG_SHOW},
-       {border_keys,      "1",        ABC_HTML_ATTR_BORDER,          ABC_HTML_FLAG_SHOW},
-       {padding_keys,     "4",        ABC_HTML_ATTR_PADDING,         ABC_HTML_FLAG_SHOW},
+       ABC_CSS_BOX(2px, 2px, 4px)
+       ABC_CSS_SELECTOR()
+       ABC_CSS_BACK_GROUND()
 
-       {width_keys,       "",         ABC_HTML_ATTR_WIDTH,           ABC_HTML_FLAG_SHOW},
-       {height_keys,      "",         ABC_HTML_ATTR_HEIGHT,          ABC_HTML_FLAG_SHOW},
+       ABC_CSS_FONT(SimSong, 16, black, )
+       ABC_CSS_TEXT( , )
 
-       {class_keys,       "",         ABC_HTML_ATTR_CLASS,           ABC_HTML_FLAG_SHOW},
-       {style_keys,       "",         ABC_HTML_ATTR_STYLE,           ABC_HTML_FLAG_SHOW},
-       {id_keys,          "",         ABC_HTML_ATTR_ID,              ABC_HTML_FLAG_SHOW},
-       {font_keys,        "SimSong",  ABC_HTML_ATTR_FONT,            0},
-       {font_size_keys,   "16",       ABC_HTML_ATTR_FONT_SIZE,       0},
-       {font_color_keys,  "black",    ABC_HTML_ATTR_FONT_COLOR,      ABC_HTML_FLAG_SHOW},
-       {font_style_keys,  "",         ABC_HTML_ATTR_FONT_STYLE,      0},
-
-       {bg_color_keys,    "",         ABC_HTML_ATTR_BG_COLOR,        ABC_HTML_FLAG_SHOW},
-
-       {text_align_keys,      "",     ABC_HTML_ATTR_TEXT_ALIGN,      ABC_HTML_FLAG_SHOW},
-       {vertical_align_keys,  "",     ABC_HTML_ATTR_VERTICAL_ALIGN,  ABC_HTML_FLAG_SHOW},
+       {vertical_align_keys,  "",  ABC_HTML_ATTR_VERTICAL_ALIGN,  ABC_HTML_FLAG_SHOW},
 };
 
 static html_attr_t  script_attrs[] =
@@ -523,10 +424,10 @@ static html_label_t  html_labels[] =
 {
        {html_keys,       ABC_HTML,          abc_number_of(html_attrs),    html_attrs,    ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
        {meta_keys,       ABC_HTML_META,     abc_number_of(meta_attrs),    meta_attrs,    ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SINGLE},
-       {body_keys,       ABC_HTML_BODY,     abc_number_of(body_attrs),    body_attrs,    ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-       {title_keys,      ABC_HTML_TITLE,    0,                            NULL,          ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
        {head_keys,       ABC_HTML_HEAD,     0,                            NULL,          ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-       {div_keys,        ABC_HTML_DIV,      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},
 
        {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},
index 9c639e22892a31023022ed52e7b81e1b9b947a46..787dacd5005204b32211d31b2befc88632ab9600 100644 (file)
@@ -91,6 +91,7 @@ enum abc_objs
        ABC_HTML_ATTR_FONT_COLOR,
        ABC_HTML_ATTR_FONT_STYLE,
 
+       ABC_HTML_ATTR_TEXT,
        ABC_HTML_ATTR_TEXT_ALIGN,
        ABC_HTML_ATTR_TEXT_DECORATION,
        ABC_HTML_ATTR_TEXT_TRANSFORM,
index 82159fd77ed285f747627ddb2d47053531ef4a1f..2fda3c05ac3817d13e609236cb8e6353b3ae76c8 100644 (file)
@@ -39,25 +39,26 @@ scf_char_t* _lex_pop_char(scf_lex_t* lex)
                return c;
        }
 
+       int n = 0;
        if (0x6 == (ret >> 5)) {
-               c->c   = ret & 0x1f;
-               c->len = 2;
+               c->c = ret & 0x1f;
+               n = 2;
 
        } else if (0xe == (ret >> 4)) {
-               c->c   = ret & 0xf;
-               c->len = 3;
+               c->c = ret & 0xf;
+               n = 3;
 
        } else if (0x1e == (ret >> 3)) {
-               c->c   = ret & 0x7;
-               c->len = 4;
+               c->c = ret & 0x7;
+               n = 4;
 
        } else if (0x3e == (ret >> 2)) {
-               c->c   = ret & 0x3;
-               c->len = 5;
+               c->c = ret & 0x3;
+               n = 5;
 
        } else if (0x7e == (ret >> 1)) {
-               c->c   = ret & 0x1;
-               c->len = 6;
+               c->c = ret & 0x1;
+               n = 6;
        } else {
                scf_loge("utf8 first byte wrong %#x, file: %s, line: %d\n", ret, lex->file->data, lex->nb_lines);
                free(c);
@@ -67,7 +68,7 @@ scf_char_t* _lex_pop_char(scf_lex_t* lex)
        c->utf8[0] = ret;
 
        int i;
-       for (i = 1; i < c->len; i++) {
+       for (i = 1; i < n; i++) {
 
                ret = __lex_getc(lex);
 
@@ -83,6 +84,7 @@ scf_char_t* _lex_pop_char(scf_lex_t* lex)
                }
        }
 
+       c->len = n;
        return c;
 }
 
index 5c9843631359e63cba276124f6f26ff07a9db8be..7449e005db92c7867d8b1117e1409bd8593872af 100644 (file)
@@ -1,10 +1,10 @@
-#CFILES += scf_string.c
+CFILES += scf_string.c
 #CFILES += scf_list_test.c
 #CFILES += scf_stack_test.c
 #CFILES += scf_vector_test.c
 #CFILES += scf_graph_test.c
 #CFILES += scf_graph.c
-CFILES += scf_rbtree.c
+#CFILES += scf_rbtree.c
 
 CFLAGS += -g -O3
 
index 249bb2bc9efc0e7de7bbf005a51d5152d3c48b62..ac82cd5c2d958bff7b9429c64c54db98b220dd7c 100644 (file)
@@ -344,6 +344,59 @@ int scf_string_get_offset(scf_string_t* str, const char* data, size_t len)
        return ret;
 }
 
+int scf_utf8_len(const uint8_t* str, size_t* len)
+{
+       size_t n = *len;
+       int    c = *str;
+       int    i;
+
+       if (c < 0x80)
+               n = 1;
+       else if (0x6 == (c >> 5)) {
+               c &= 0x1f;
+               n  = 2;
+
+       } else if (0xe == (c >> 4)) {
+               c &= 0xf;
+               n  = 3;
+
+       } else if (0x1e == (c >> 3)) {
+               c &= 0x7;
+               n  = 4;
+
+       } else if (0x3e == (c >> 2)) {
+               c &= 0x3;
+               n  = 5;
+
+       } else if (0x7e == (c >> 1)) {
+               c &= 0x1;
+               n  = 6;
+       } else {
+               scf_loge("utf8 first byte wrong %#x\n", c);
+               return -EINVAL;
+       }
+
+       if (n > *len) {
+               scf_loge("utf8 len error, needs %ld, real: %ld\n", n, *len);
+               return -EINVAL;
+       }
+
+       for (i = 1; i < n; i++) {
+               int c2 = str[i];
+
+               if (0x2 == (c2 >> 6)) {
+                       c <<= 6;
+                       c  |= c2 & 0x3f;
+               } else {
+                       scf_loge("utf8 byte[%d] wrong %#x\n", i, c2);
+                       return -EINVAL;
+               }
+       }
+
+       *len = n;
+       return c;
+}
+
 #if 0
 int main(int argc, char* argv[])
 {
@@ -386,6 +439,23 @@ int main(int argc, char* argv[])
                printf("i: %d, offset: %d\n", i, offset);
        }
 
+       uint8_t* utf8 = "你好, hello";
+       size_t   N = strlen(utf8);
+       size_t   n = N;
+
+       int c = scf_utf8_len(utf8, &n);
+       printf("c: %.*s:%d, n: %ld\n", (int)n, utf8, c, n);
+
+       utf8 += n;
+       n = N - n;
+       c = scf_utf8_len(utf8, &n);
+       printf("c: %.*s:%d, n: %ld\n", (int)n, utf8, c, n);
+
+       utf8 += n;
+       n = N - n;
+       c = scf_utf8_len(utf8, &n);
+       printf("c: %.*s:%d, n: %ld\n", (int)n, utf8, c, n);
+
        scf_string_free(s0);
        scf_string_free(s1);
        scf_string_free(s2);
@@ -393,4 +463,3 @@ int main(int argc, char* argv[])
        return 0;
 }
 #endif
-
index ca06d945fc986ca1eab06bf35691c298aa413fc0..082d2b5adf77ecbf58525bb0606516a53b43aa0d 100644 (file)
@@ -4,9 +4,9 @@
 #include"scf_vector.h"
 
 typedef struct {
-       int      capacity;
+       intptr_t capacity;
        size_t   len;
-       char*    data;
+       uint8_t* data;
 } scf_string_t;
 
 
@@ -45,5 +45,5 @@ int             scf_string_match_kmp_cstr_len(const scf_string_t* T, const uint8
 
 int             scf_string_get_offset(scf_string_t* str, const char* data, size_t len);
 
+int             scf_utf8_len(const uint8_t* str, size_t* len);
 #endif
-
index 91bc65ccd3b33df01516d0ef69f0773505918a33..e95b12431f0fc76ce70e97f1aff05a697f6b2cdb 100644 (file)
@@ -25,8 +25,9 @@ CFILES += abc_render_head.c
 CFILES += abc_render_body.c
 CFILES += abc_render_div.c
 
-CFILES += abc_render_bg_color.c
-CFILES += abc_render_bg_image.c
+CFILES += __render_border.c
+CFILES += __render_bg_image.c
+CFILES += __render_text.c
 
 CFILES += abc_render_empty.c
 
diff --git a/ui/__render_bg_image.c b/ui/__render_bg_image.c
new file mode 100644 (file)
index 0000000..b7735dd
--- /dev/null
@@ -0,0 +1,231 @@
+#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 bgColor; \n"
+       "uniform vec4 rect; \n"
+       "uniform int repeat_x; \n"
+       "uniform int repeat_y; \n"
+       "uniform int index_x; \n"
+       "uniform int index_y; \n"
+       "uniform sampler2D tex_rgba; \n"
+       "void main() { \n"
+       "    vec2 xy = v_texCoord; \n"
+       "    float i = floor((xy.x - rect.x) / rect.z); \n"
+       "    float j = floor((xy.y - rect.y) / rect.w); \n"
+       "    if ((repeat_x > 0 || int(round(i)) == index_x) && (repeat_y > 0 || int(round(j)) == index_y)) { \n"
+       "        float x = rect.x + i * rect.z; \n"
+       "        float y = rect.y + j * rect.w; \n"
+       "        xy.x = (xy.x - x) / rect.z; \n"
+       "        xy.y = (xy.y - y) / rect.w; \n"
+       "        vec4 v = texture2D(tex_rgba, xy).rgba; \n"
+       "        outputColor = vec4(v.b, v.g, v.r, 1.0); \n"
+       "    } else { \n"
+       "        outputColor = bgColor; \n"
+       "    } \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_rect;
+static GLuint uniform_color;
+static GLuint uniform_repeat_x;
+static GLuint uniform_repeat_y;
+static GLuint uniform_index_x;
+static GLuint uniform_index_y;
+
+static int __render_fini_bg_image(abc_render_t* render)
+{
+       return 0;
+}
+
+static int __render_draw_bg_image(abc_render_t* render, abc_obj_t* obj, int width, int height)
+{
+       abc_obj_t* attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_BG_IMAGE);
+       if (!attr)
+               return 0;
+       if (!attr->value || attr->value->len <= 0)
+               return 0;
+
+       scf_string_t* spath = NULL;
+       abc_io_t*     io    = NULL;
+       abc_img_t*    img   = NULL;
+
+       int ret = __io_url_css(&io, &spath, obj->file->data, attr->value->data);
+       if (ret < 0)
+               return ret;
+
+       scf_logd("background-image: %s\n", spath->data);
+
+       ret = abc_img_open(&img, spath->data);
+
+       scf_string_free(spath);
+       spath = NULL;
+       if (ret < 0)
+               return ret;
+
+       uint8_t* bgra = calloc(1, img->width * img->height * 4);
+       if (!bgra) {
+               abc_img_close(img);
+               return -ENOMEM;
+       }
+
+       ret = abc_img_read(img, bgra, img->width * img->height * 4);
+       if (ret < 0) {
+               abc_img_close(img);
+               free(bgra);
+               return ret;
+       }
+
+       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);
+
+       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_logd("%s, x: %d, y: %d, w: %d, h: %d\n", obj->text->data, obj->x, obj->y, obj->w, obj->h);
+
+       GLfloat vert_update[] =
+       {
+                2.0 *  obj->x           / (float)width  - 1.0,
+               -2.0 * (obj->y + obj->h) / (float)height + 1.0,
+
+                2.0 * (obj->x + obj->w) / (float)width  - 1.0,
+               -2.0 * (obj->y + obj->h) / (float)height + 1.0,
+
+                2.0 *  obj->x           / (float)width  - 1.0,
+               -2.0 *  obj->y           / (float)height + 1.0,
+
+                2.0 * (obj->x + obj->w) / (float)width  - 1.0,
+               -2.0 *  obj->y           / (float)height + 1.0,
+       };
+
+       GLfloat x = 0.0;
+       GLfloat y = 0.0;
+       GLfloat w = img->width  / (float)obj->w;
+       GLfloat h = img->height / (float)obj->h;
+
+       if (w > 1.0 || h > 1.0)
+       {
+               GLfloat max = w > h ? w : h;
+
+               w /= max;
+               h /= max;
+       }
+
+       GLint repeat_x = 1;
+       GLint repeat_y = 1;
+       GLint index_x  = 0;
+       GLint index_y  = 0;
+
+       attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_BG_POSITION);
+       if (attr) {
+               abc_css_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);
+
+               if (x + w > 1.0)
+                       index_x = -1;
+
+               if (y + h > 1.0)
+                       index_y = -1;
+       }
+
+       attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_BG_REPEAT);
+       if (attr) {
+               if (!__html_strcmp(attr->value->data, "repeat-x"))
+                       repeat_y = 0;
+
+               else if (!__html_strcmp(attr->value->data, "repeat-y"))
+                       repeat_x = 0;
+
+               else if (!__html_strcmp(attr->value->data, "no-repeat")) {
+                       repeat_x = 0;
+                       repeat_y = 0;
+               }
+       }
+
+       scf_logd("repeat_x: %d, repeat_y: %d, index_x: %d, index_y: %d\n", repeat_x, repeat_y, index_x, index_y);
+
+       glUseProgram(program);
+
+       uniform_mvp      = glGetUniformLocation(program, "mvp");
+       uniform_rgba     = glGetUniformLocation(program, "tex_rgba");
+       uniform_rect     = glGetUniformLocation(program, "rect");
+       uniform_color    = glGetUniformLocation(program, "bgColor");
+       uniform_repeat_x = glGetUniformLocation(program, "repeat_x");
+       uniform_repeat_y = glGetUniformLocation(program, "repeat_y");
+       uniform_index_x  = glGetUniformLocation(program, "index_x");
+       uniform_index_y  = glGetUniformLocation(program, "index_y");
+
+       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);
+
+       glUniform4f(uniform_rect,  x, y, w, h);
+       glUniform4f(uniform_color, r, g, b, 1.0);
+
+       glUniform1i(uniform_repeat_x, repeat_x);
+       glUniform1i(uniform_repeat_y, repeat_y);
+       glUniform1i(uniform_index_x,  index_x);
+       glUniform1i(uniform_index_y,  index_y);
+
+       // draw
+       glBindBuffer   (GL_ARRAY_BUFFER, buffers[0]);
+       glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vert_update), vert_update);
+
+       glBindVertexArray(vao);
+
+       glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+       glBindVertexArray(0);
+       glUseProgram(0);
+
+       abc_img_close(img);
+       free(bgra);
+       return 0;
+}
+
+abc_render_t  __render_bg_image =
+{
+       .type = ABC_HTML_ATTR_BG_IMAGE,
+
+       .draw = __render_draw_bg_image,
+       .fini = __render_fini_bg_image,
+};
diff --git a/ui/__render_border.c b/ui/__render_border.c
new file mode 100644 (file)
index 0000000..e52787a
--- /dev/null
@@ -0,0 +1,155 @@
+#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 x_border; \n"
+       "uniform float y_border; \n"
+       "uniform vec4  color; \n"
+       "uniform vec4  bgColor; \n"
+       "void main() { \n"
+       "    float x = v_texCoord.x; \n"
+       "    float y = v_texCoord.y; \n"
+       "    if ((x >= 0.0 && x <= x_border) || (x >= 1.0 - x_border && x <= 1.0)) { \n"
+       "        outputColor = color; \n"
+       "    } else if ((y >= 0.0 && y <= y_border) || (y >= 1.0 - y_border && y <= 1.0)) { \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_x_border;
+static GLuint uniform_y_border;
+static GLuint uniform_color;
+static GLuint uniform_bgColor;
+
+
+static int __render_fini_border(abc_render_t* render)
+{
+       return 0;
+}
+
+static int __render_draw_border(abc_render_t* render, abc_obj_t* obj, int width, int height)
+{
+       if (0 == program)
+               __init_program(&program, vert_shader, frag_shader);
+
+       if (0 == vao)
+               __init_buffers(&vao, buffers);
+
+       int margin = 0;
+       int border = 0;
+       int border_type = ABC_BORDER_SOLID;
+
+       double r0 = 0.0;
+       double g0 = 0.0;
+       double b0 = 0.0;
+
+       double r1 = 0.0;
+       double g1 = 0.0;
+       double b1 = 0.0;
+       double a1 = 0.0;
+
+       abc_obj_t* attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_BG_COLOR);
+       if (attr && attr->value->len > 0) {
+               a1 = 1.0;
+               abc_css_color(&r1, &g1, &b1, attr->value->data);
+       }
+
+       attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_MARGIN);
+       if (attr)
+               margin = atoi(attr->value->data);
+
+       attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_BORDER);
+       if (attr)
+               abc_css_border(&r0, &g0, &b0, &border, &border_type, obj, attr->value->data);
+       else {
+               attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_COLOR);
+               if (attr)
+                       abc_css_color(&r0, &g0, &b0, attr->value->data);
+       }
+
+       int x = obj->x + margin;
+       int y = obj->y + margin;
+       int w = obj->w - margin * 2;
+       int h = obj->h - margin * 2;
+
+       float mvp[16];
+       __compute_mvp(mvp, 0, 0, 0);
+
+       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,
+
+                2.0 * (x + w) / (float)width  - 1.0,
+               -2.0 *  y      / (float)height + 1.0,
+       };
+
+       GLfloat x_border = border / (float)w;
+       GLfloat y_border = border / (float)h;
+
+       glUseProgram(program);
+       uniform_mvp      = glGetUniformLocation(program, "mvp");
+       uniform_x_border = glGetUniformLocation(program, "x_border");
+       uniform_y_border = glGetUniformLocation(program, "y_border");
+       uniform_color    = glGetUniformLocation(program, "color");
+       uniform_bgColor  = glGetUniformLocation(program, "bgColor");
+
+       glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, mvp);
+
+       glUniform1f(uniform_x_border, x_border);
+       glUniform1f(uniform_y_border, y_border);
+       glUniform4f(uniform_color,    r0, g0, b0, 1.0);
+       glUniform4f(uniform_bgColor,  r1, g1, b1, a1);
+
+       // draw
+       glBindBuffer   (GL_ARRAY_BUFFER, buffers[0]);
+       glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vert_update), vert_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  __render_border =
+{
+       .type = ABC_HTML_ATTR_BORDER,
+
+       .draw = __render_draw_border,
+       .fini = __render_fini_border,
+};
diff --git a/ui/__render_text.c b/ui/__render_text.c
new file mode 100644 (file)
index 0000000..6ca9a8a
--- /dev/null
@@ -0,0 +1,282 @@
+#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;
+}
+
+void __draw_text(cairo_text_extents_t* extents, cairo_t* cr, const char* text, double x, double y, int line_type, int line_width)
+{
+       cairo_text_extents(cr, text, extents);
+       double w = extents->width;
+
+       x += extents->x_bearing;
+       y -= extents->y_bearing;
+
+       cairo_set_line_width(cr, 1);
+       cairo_move_to(cr, x, y);
+       cairo_show_text(cr, text);
+       cairo_stroke(cr);
+
+       cairo_set_line_width(cr, line_width);
+       switch (line_type)
+       {
+               case ABC_LINE_UNDER:
+                       cairo_move_to(cr, x, y + line_width + 1.0);
+                       cairo_line_to(cr, w, y + line_width + 1.0);
+                       break;
+
+               case ABC_LINE_OVER:
+                       cairo_move_to(cr, x, 1.0);
+                       cairo_line_to(cr, w, 1.0);
+                       break;
+
+               case ABC_LINE_THROUGH:
+                       cairo_move_to(cr, x, y + extents->y_bearing / 2.0 + line_width);
+                       cairo_line_to(cr, w, y + extents->y_bearing / 2.0 + line_width);
+                       break;
+               default:
+                       break;
+       };
+       cairo_stroke(cr);
+}
+
+int __init_text(cairo_t* cr, abc_obj_t* obj, int num_flag)
+{
+       abc_obj_t* attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT);
+       if (attr) {
+               int bold   = CAIRO_FONT_WEIGHT_NORMAL;
+               int italic = CAIRO_FONT_SLANT_NORMAL;
+
+               abc_obj_t* style = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_STYLE);
+               if (style) {
+                       if (!__html_strcmp(style->value->data, "bold"))
+                               bold = CAIRO_FONT_WEIGHT_BOLD;
+
+                       else if (!__html_strcmp(style->value->data, "italic") || !__html_strcmp(style->value->data, "oblique"))
+                               italic = CAIRO_FONT_SLANT_OBLIQUE;
+               }
+
+               cairo_select_font_face(cr, attr->value->data, italic, bold);
+       }
+
+       cairo_text_extents_t  extents;
+       double r = 0.0;
+       double g = 0.0;
+       double b = 0.0;
+       double size = 16.0;
+
+       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_FONT_COLOR);
+       if (attr)
+               abc_css_color(&r, &g, &b, attr->value->data);
+
+       cairo_set_font_size  (cr, size);
+       cairo_set_source_rgba(cr, r, g, b, 1.0);
+
+       if (ABC_HTML_OL == obj->parent->type && num_flag)
+       {
+               cairo_text_extents(cr, obj->text->data, &extents);
+
+               cairo_move_to  (cr, obj->parent->padding - (extents.x_bearing + extents.width + size / 2), -obj->y_bearing);
+               cairo_show_text(cr, obj->text->data);
+               cairo_stroke(cr);
+               return 0;
+       }
+
+       double line_width = 0.5 + size / 16.0;
+       int    line_type  = ABC_LINE_NONE;
+
+       attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_TEXT_DECORATION);
+       if (attr) {
+               if (!__html_strcmp(attr->value->data, "underline"))
+                       line_type = ABC_LINE_UNDER;
+
+               else if (!__html_strcmp(attr->value->data, "overline"))
+                       line_type = ABC_LINE_OVER;
+
+               else if (!__html_strcmp(attr->value->data, "line-through"))
+                       line_type = ABC_LINE_THROUGH;
+       }
+
+       if (!obj->text_splits) {
+               __draw_text(&extents, cr, obj->text->data, obj->parent->padding, 0.0, line_type, line_width);
+               return 0;
+       }
+
+       scf_string_t* s;
+       abc_text_t*   t;
+
+       double x = obj->parent->padding;
+       double y = 0.0;
+
+       while  (obj->text_splits) {
+               t = obj->text_splits;
+
+               s = scf_string_cstr_len(obj->text->data + t->start, t->len);
+               if (!s) {
+                       scf_slist_clear(obj->text_splits, abc_text_t, next, free);
+                       return -ENOMEM;
+               }
+
+               __draw_text(&extents, cr, s->data, x, y, line_type, line_width);
+               y += extents.height;
+
+               obj->text_splits = t->next;
+
+               scf_string_free(s);
+               free(t);
+       }
+
+       return 0;
+}
+
+static int __render_draw_text(abc_render_t* render, abc_obj_t* obj, int width, int height)
+{
+       if (obj->w <= 0 || obj->h <= 0)
+               return 0;
+
+       int d = abc_css_margin(obj);
+       int x = obj->x + d;
+       int y = obj->y + d;
+       int w = obj->w - d * 2;
+       int h = obj->h - d * 2;
+
+       scf_logd("obj->type: %d, obj->w: %d, obj->h: %d, w: %d, h: %d, d: %d\n", obj->type, obj->w, obj->h, w, h, d);
+
+       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, h, NULL);
+
+       abc_obj_t*        attr;
+       cairo_surface_t*  surface;
+       cairo_t*          cr;
+
+       uint8_t* bgra = calloc(1, w * h * 4);
+       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);
+
+       surface = cairo_image_surface_create_for_data(bgra, CAIRO_FORMAT_ARGB32, w, h, w * 4);
+       cr      = cairo_create(surface);
+
+       cairo_set_line_width(cr, 1);
+       cairo_set_source_rgba(cr, r, g, b, 0.0);
+       cairo_rectangle(cr, 0, 0, w, h);
+       cairo_fill(cr);
+       cairo_stroke(cr);
+
+       if (obj->text)
+               __init_text(cr, obj, 0);
+//     cairo_surface_write_to_png(surface, "tmp.png");
+
+       cairo_destroy(cr);
+       cairo_surface_destroy(surface);
+       surface = NULL;
+       cr = NULL;
+
+       float mvp[16];
+       __compute_mvp(mvp, 0, 0, 0);
+
+       scf_logd("%s, x: %d, y: %d, w: %d, h: %d\n", obj->text->data, obj->x, obj->y, obj->w, obj->h);
+
+       GLfloat vert_update[] =
+       {
+                2.0 *  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,
+       };
+
+       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, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, bgra);
+       glUniform1i(uniform_rgba, 0);
+
+       // draw
+       glBindBuffer   (GL_ARRAY_BUFFER, buffers[0]);
+       glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vert_update), vert_update);
+
+       glBindVertexArray(vao);
+
+       glEnable(GL_BLEND);
+       glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+       glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+       glDisable(GL_BLEND);
+
+       glBindVertexArray(0);
+       glUseProgram(0);
+
+       free(bgra);
+       return 0;
+}
+
+abc_render_t  __render_text =
+{
+       .type = ABC_HTML_ATTR_TEXT,
+
+       .draw = __render_draw_text,
+       .fini = __render_fini_text,
+};
index ff3b339d8d1c09e1d9589ee60517f0a2aa8661b5..ba523a1f1911dee20799fb29502f0323aa190587 100644 (file)
--- a/ui/abc.h
+++ b/ui/abc.h
@@ -78,4 +78,7 @@ int  __init_buffers(GLuint* vao, GLuint buffers[2]);
 
 int __init_text(cairo_t* cr, abc_obj_t* obj, int num_flag);
 
+extern abc_render_t  __render_border;
+extern abc_render_t  __render_bg_image;
+extern abc_render_t  __render_text;
 #endif
index 866a1a07e26743972c98c1ad46cbe569ce210735..d5dd75648f17240bbaf81926732b5ec2496d04f2 100644 (file)
@@ -1,9 +1,5 @@
 #include"abc.h"
 
-extern abc_render_t  abc_render_h1;
-extern abc_render_t  abc_render_bg_color;
-extern abc_render_t  abc_render_bg_image;
-
 static int _render_fini_body(abc_render_t* render)
 {
        return 0;
@@ -11,16 +7,16 @@ static int _render_fini_body(abc_render_t* render)
 
 static int _render_draw_body(abc_render_t* render, abc_obj_t* obj, int width, int height)
 {
-       abc_obj_t* attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_BG_IMAGE);
+       __render_border.draw(&__render_border, obj, width, height);
 
+       abc_obj_t* attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_BG_IMAGE);
        if (attr && attr->value && attr->value->len > 0)
        {
-               abc_render_bg_image.draw(&abc_render_bg_image, obj, width, height);
-       } else
-               abc_render_bg_color.draw(&abc_render_bg_color, obj, width, height);
+               __render_bg_image.draw(&__render_bg_image, obj, width, height);
+       }
 
        if (obj->text)
-               abc_render_h1.draw(&abc_render_h1, obj, width, height);
+               __render_text.draw(&__render_text, obj, width, height);
 
        return 0;
 }
index ed18e6aae2416f0b1a0b29b1215f1bb817560f44..ce28db5c318ddb80eb7894e2115401227b371626 100644 (file)
 #include"abc.h"
 
-extern abc_render_t  abc_render_table;
-
-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_h1(abc_render_t* render)
 {
        return 0;
 }
 
-void __draw_text(cairo_text_extents_t* extents, cairo_t* cr, const char* text, double x, double y, int line_type, int line_width)
-{
-       cairo_text_extents(cr, text, extents);
-       double w = extents->width;
-
-       x += extents->x_bearing;
-       y -= extents->y_bearing;
-
-       cairo_set_line_width(cr, 1);
-       cairo_move_to(cr, x, y);
-       cairo_show_text(cr, text);
-       cairo_stroke(cr);
-
-       cairo_set_line_width(cr, line_width);
-       switch (line_type)
-       {
-               case ABC_LINE_UNDER:
-                       cairo_move_to(cr, x, y + line_width + 1.0);
-                       cairo_line_to(cr, w, y + line_width + 1.0);
-                       break;
-
-               case ABC_LINE_OVER:
-                       cairo_move_to(cr, x, 1.0);
-                       cairo_line_to(cr, w, 1.0);
-                       break;
-
-               case ABC_LINE_THROUGH:
-                       cairo_move_to(cr, x, y + extents->y_bearing / 2.0 + line_width);
-                       cairo_line_to(cr, w, y + extents->y_bearing / 2.0 + line_width);
-                       break;
-               default:
-                       break;
-       };
-       cairo_stroke(cr);
-}
-
-int __init_text(cairo_t* cr, abc_obj_t* obj, int num_flag)
-{
-       abc_obj_t* attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT);
-       if (attr) {
-               int bold   = CAIRO_FONT_WEIGHT_NORMAL;
-               int italic = CAIRO_FONT_SLANT_NORMAL;
-
-               abc_obj_t* style = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_STYLE);
-               if (style) {
-                       if (!__html_strcmp(style->value->data, "bold"))
-                               bold = CAIRO_FONT_WEIGHT_BOLD;
-
-                       else if (!__html_strcmp(style->value->data, "italic") || !__html_strcmp(style->value->data, "oblique"))
-                               italic = CAIRO_FONT_SLANT_OBLIQUE;
-               }
-
-               cairo_select_font_face(cr, attr->value->data, italic, bold);
-       }
-
-       cairo_text_extents_t  extents;
-       double r = 0.0;
-       double g = 0.0;
-       double b = 0.0;
-       double size = 16.0;
-
-       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_FONT_COLOR);
-       if (attr)
-               abc_css_color(&r, &g, &b, attr->value->data);
-
-       cairo_set_font_size  (cr, size);
-       cairo_set_source_rgba(cr, r, g, b, 1.0);
-
-       if (ABC_HTML_OL == obj->parent->type && num_flag)
-       {
-               cairo_text_extents(cr, obj->text->data, &extents);
-
-               cairo_move_to  (cr, obj->parent->padding - (extents.x_bearing + extents.width + size / 2), -obj->y_bearing);
-               cairo_show_text(cr, obj->text->data);
-               cairo_stroke(cr);
-               return 0;
-       }
-
-       double line_width = 0.5 + size / 16.0;
-       int    line_type  = ABC_LINE_NONE;
-
-       attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_TEXT_DECORATION);
-       if (attr) {
-               if (!__html_strcmp(attr->value->data, "underline"))
-                       line_type = ABC_LINE_UNDER;
-
-               else if (!__html_strcmp(attr->value->data, "overline"))
-                       line_type = ABC_LINE_OVER;
-
-               else if (!__html_strcmp(attr->value->data, "line-through"))
-                       line_type = ABC_LINE_THROUGH;
-       }
-
-       if (!obj->text_splits) {
-               __draw_text(&extents, cr, obj->text->data, obj->parent->padding, 0.0, line_type, line_width);
-               return 0;
-       }
-
-       scf_string_t* s;
-       abc_text_t*   t;
-
-       double x = obj->parent->padding;
-       double y = 0.0;
-
-       while  (obj->text_splits) {
-               t = obj->text_splits;
-
-               s = scf_string_cstr_len(obj->text->data + t->start, t->len);
-               if (!s) {
-                       scf_slist_clear(obj->text_splits, abc_text_t, next, free);
-                       return -ENOMEM;
-               }
-
-               __draw_text(&extents, cr, s->data, x, y, line_type, line_width);
-               y += extents.height;
-
-               obj->text_splits = t->next;
-
-               scf_string_free(s);
-               free(t);
-       }
-
-       return 0;
-}
-
 static int _render_draw_h1(abc_render_t* render, abc_obj_t* obj, int width, int height)
 {
        if (obj->w <= 0 || obj->h <= 0)
                return 0;
 
-       abc_render_table.draw(&abc_render_table, obj, width, height);
-
-       int d = abc_css_margin(obj);
-       int x = obj->x + d;
-       int y = obj->y + d;
-       int w = obj->w - d * 2;
-       int h = obj->h - d * 2;
-
-       scf_logd("obj->type: %d, obj->w: %d, obj->h: %d, w: %d, h: %d, d: %d\n", obj->type, obj->w, obj->h, w, h, d);
-
-       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, h, NULL);
-
-       abc_obj_t*        attr;
-       cairo_surface_t*  surface;
-       cairo_t*          cr;
-
-       uint8_t* bgra = calloc(1, w * h * 4);
-       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);
-
-       surface = cairo_image_surface_create_for_data(bgra, CAIRO_FORMAT_ARGB32, w, h, w * 4);
-       cr      = cairo_create(surface);
-
-       cairo_set_line_width(cr, 1);
-       cairo_set_source_rgb(cr, r, g, b);
-       cairo_rectangle(cr, 0, 0, w, h);
-       cairo_fill(cr);
-       cairo_stroke(cr);
+       __render_border.draw(&__render_border, obj, width, height);
 
        if (obj->text)
-               __init_text(cr, obj, 0);
-//     cairo_surface_write_to_png(surface, "tmp.png");
-
-       cairo_destroy(cr);
-       cairo_surface_destroy(surface);
-       surface = NULL;
-       cr = NULL;
-
-       float mvp[16];
-       __compute_mvp(mvp, 0, 0, 0);
-
-       scf_logd("%s, x: %d, y: %d, w: %d, h: %d\n", obj->text->data, obj->x, obj->y, obj->w, obj->h);
-
-       GLfloat vert_update[] =
-       {
-                2.0 *  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,
-       };
-
-       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, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, bgra);
-       glUniform1i(uniform_rgba, 0);
-
-       // draw
-       glBindBuffer   (GL_ARRAY_BUFFER, buffers[0]);
-       glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vert_update), vert_update);
-
-       glBindVertexArray(vao);
-
-       glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-
-       glBindVertexArray(0);
-       glUseProgram(0);
+               __render_text.draw(&__render_text, obj, width, height);
 
-       free(bgra);
        return 0;
 }
 
index bd457f3481c3510bb670c27452713008246669f5..ed783e2672ed17ca16aa6ae0133c2b21922426bf 100644 (file)
@@ -1,54 +1,6 @@
 #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 x_margin; \n"
-       "uniform float y_margin; \n"
-       "uniform float x_border; \n"
-       "uniform float y_border; \n"
-       "uniform vec4  color; \n"
-       "uniform vec4  bgColor; \n"
-       "void main() { \n"
-       "    float x = v_texCoord.x; \n"
-       "    float y = v_texCoord.y; \n"
-       "    if (((x > x_margin && x < x_margin + x_border) || (x > 1.0 - x_margin - x_border && x < 1.0 - x_margin)) \n"
-       "      && (y > y_margin && y < 1.0 - y_margin)) { \n"
-       "        outputColor = color; \n"
-       "    } else if (((y > y_margin && y < y_margin + y_border) || (y > 1.0 - y_margin - y_border && y < 1.0 - y_margin)) \n"
-       "             && (x > x_margin && x < 1.0 - x_margin)) { \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_x_margin;
-static GLuint uniform_y_margin;
-static GLuint uniform_x_border;
-static GLuint uniform_y_border;
-static GLuint uniform_color;
-static GLuint uniform_bgColor;
-
+extern abc_render_t  __render_border;
 
 static int _render_fini_table(abc_render_t* render)
 {
@@ -57,93 +9,7 @@ static int _render_fini_table(abc_render_t* render)
 
 static int _render_draw_table(abc_render_t* render, abc_obj_t* obj, int width, int height)
 {
-       if (0 == program)
-               __init_program(&program, vert_shader, frag_shader);
-
-       if (0 == vao)
-               __init_buffers(&vao, buffers);
-
-       int margin = 0;
-       int border = 0;
-       int border_type = ABC_BORDER_SOLID;
-
-       double r0 = 0.0;
-       double g0 = 0.0;
-       double b0 = 0.0;
-
-       double r1 = 0.0;
-       double g1 = 0.0;
-       double b1 = 0.0;
-
-       abc_obj_t* attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_BG_COLOR);
-       if (attr)
-               abc_css_color(&r1, &g1, &b1, attr->value->data);
-
-       attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_MARGIN);
-       if (attr)
-               margin = atoi(attr->value->data);
-
-       attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_BORDER);
-       if (attr)
-               abc_css_border(&r0, &g0, &b0, &border, &border_type, obj, attr->value->data);
-       else {
-               attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_COLOR);
-               if (attr)
-                       abc_css_color(&r0, &g0, &b0, attr->value->data);
-       }
-
-       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 * (obj->x + obj->w) / (float)width  - 1.0,
-               -2.0 * (obj->y + obj->h) / (float)height + 1.0,
-
-                2.0 *  obj->x           / (float)width  - 1.0,
-               -2.0 *  obj->y           / (float)height + 1.0,
-
-                2.0 * (obj->x + obj->w) / (float)width  - 1.0,
-               -2.0 *  obj->y           / (float)height + 1.0,
-       };
-
-       GLfloat x_margin = margin / (float)obj->w;
-       GLfloat y_margin = margin / (float)obj->h;
-
-       GLfloat x_border = border / (float)obj->w;
-       GLfloat y_border = border / (float)obj->h;
-
-       glUseProgram(program);
-       uniform_mvp      = glGetUniformLocation(program, "mvp");
-       uniform_x_margin = glGetUniformLocation(program, "x_margin");
-       uniform_y_margin = glGetUniformLocation(program, "y_margin");
-       uniform_x_border = glGetUniformLocation(program, "x_border");
-       uniform_y_border = glGetUniformLocation(program, "y_border");
-       uniform_color    = glGetUniformLocation(program, "color");
-       uniform_bgColor  = glGetUniformLocation(program, "bgColor");
-
-       glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, mvp);
-
-       glUniform1f(uniform_x_margin, x_margin);
-       glUniform1f(uniform_y_margin, y_margin);
-       glUniform1f(uniform_x_border, x_border);
-       glUniform1f(uniform_y_border, y_border);
-       glUniform4f(uniform_color,    r0, g0, b0, 1.0);
-       glUniform4f(uniform_bgColor,  r1, g1, b1, 1.0);
-
-       // draw
-       glBindBuffer   (GL_ARRAY_BUFFER, buffers[0]);
-       glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vert_update), vert_update);
-
-       glBindVertexArray(vao);
-
-       glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-
-       glBindVertexArray(0);
-       glUseProgram(0);
+       __render_border.draw(&__render_border, obj, width, height);
        return 0;
 }
 
index 558e87e90f29111c5d3b9a66cdb351cca4c1f78b..c9a884092bbe71d54702a4083193401adaf46595 100644 (file)
@@ -1,7 +1,5 @@
 #include"abc.h"
 
-extern abc_render_t  abc_render_table;
-
 static const char* vert_shader =
        "#version 330 core\n"
        "layout(location = 0) in vec4 position; \n"
@@ -42,7 +40,7 @@ static int _render_fini_td(abc_render_t* render)
 
 static int _render_draw_td(abc_render_t* render, abc_obj_t* obj, int width, int height)
 {
-       abc_render_table.draw(&abc_render_table, obj, width, height);
+       __render_border.draw(&__render_border, obj, width, height);
 
        if (!obj->text)
                return 0;