From: yu.dongliang <18588496441@163.com> Date: Sun, 3 May 2026 08:17:02 +0000 (+0800) Subject: 1, split render code to 3 files: __render_border.c, __render_bg_image.c, __render_text.c, X-Git-Url: http://baseworks.info/?a=commitdiff_plain;h=f0444a7e582c7cd386edb0a7b4858ee2a5faf3ec;p=abc.git 1, split render code to 3 files: __render_border.c, __render_bg_image.c, __render_text.c, 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. --- diff --git a/examples/p_multi_line.html b/examples/p_multi_line.html index b90bf63..efb792e 100644 --- a/examples/p_multi_line.html +++ b/examples/p_multi_line.html @@ -4,8 +4,8 @@ diff --git a/examples/style.css b/examples/style.css index ddfedd4..23371ec 100644 --- a/examples/style.css +++ b/examples/style.css @@ -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;} diff --git a/html/abc_css_border.c b/html/abc_css_border.c index f2ef57b..adfc471 100644 --- a/html/abc_css_border.c +++ b/html/abc_css_border.c @@ -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; diff --git a/html/abc_css_position.c b/html/abc_css_position.c index 800d10d..52cb844 100644 --- a/html/abc_css_position.c +++ b/html/abc_css_position.c @@ -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; diff --git a/html/abc_html.c b/html/abc_html.c index ebfdcb7..bd4f58b 100644 --- a/html/abc_html.c +++ b/html/abc_html.c @@ -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}, diff --git a/html/abc_obj.h b/html/abc_obj.h index 9c639e2..787dacd 100644 --- a/html/abc_obj.h +++ b/html/abc_obj.h @@ -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, diff --git a/js/lex/scf_lex_util.c b/js/lex/scf_lex_util.c index 82159fd..2fda3c0 100644 --- a/js/lex/scf_lex_util.c +++ b/js/lex/scf_lex_util.c @@ -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; } diff --git a/js/util/Makefile b/js/util/Makefile index 5c98436..7449e00 100644 --- a/js/util/Makefile +++ b/js/util/Makefile @@ -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 diff --git a/js/util/scf_string.c b/js/util/scf_string.c index 249bb2b..ac82cd5 100644 --- a/js/util/scf_string.c +++ b/js/util/scf_string.c @@ -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 - diff --git a/js/util/scf_string.h b/js/util/scf_string.h index ca06d94..082d2b5 100644 --- a/js/util/scf_string.h +++ b/js/util/scf_string.h @@ -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 - diff --git a/ui/Makefile b/ui/Makefile index 91bc65c..e95b124 100644 --- a/ui/Makefile +++ b/ui/Makefile @@ -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 index 0000000..b7735dd --- /dev/null +++ b/ui/__render_bg_image.c @@ -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 index 0000000..e52787a --- /dev/null +++ b/ui/__render_border.c @@ -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 index 0000000..6ca9a8a --- /dev/null +++ b/ui/__render_text.c @@ -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, +}; diff --git a/ui/abc.h b/ui/abc.h index ff3b339..ba523a1 100644 --- 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 diff --git a/ui/abc_render_body.c b/ui/abc_render_body.c index 866a1a0..d5dd756 100644 --- a/ui/abc_render_body.c +++ b/ui/abc_render_body.c @@ -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; } diff --git a/ui/abc_render_h1.c b/ui/abc_render_h1.c index ed18e6a..ce28db5 100644 --- a/ui/abc_render_h1.c +++ b/ui/abc_render_h1.c @@ -1,275 +1,20 @@ #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; } diff --git a/ui/abc_render_table.c b/ui/abc_render_table.c index bd457f3..ed783e2 100644 --- a/ui/abc_render_table.c +++ b/ui/abc_render_table.c @@ -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; } diff --git a/ui/abc_render_td.c b/ui/abc_render_td.c index 558e87e..c9a8840 100644 --- a/ui/abc_render_td.c +++ b/ui/abc_render_td.c @@ -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;