From 89d6a9d0d54fd4aa4c11a47b80eaf82e7817a7de Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Fri, 10 Apr 2026 21:04:03 +0800 Subject: [PATCH] css: background-image with repeat status --- examples/style.css | 2 + html/Makefile | 1 + html/abc_css_position.c | 119 +++++++++++++++++++++++++++++++++++++++ html/abc_html.c | 21 ++++--- html/abc_html.h | 3 +- html/abc_obj.h | 3 + ui/Makefile | 1 + ui/abc_render_bg_image.c | 72 ++++++++++++++++++++--- 8 files changed, 206 insertions(+), 16 deletions(-) create mode 100644 html/abc_css_position.c diff --git a/examples/style.css b/examples/style.css index 16354c1..ae78f89 100644 --- a/examples/style.css +++ b/examples/style.css @@ -2,6 +2,8 @@ body { background-color:#b0c4de; background-image:url('img.png'); + background-position:right top; + background-repeat:no-repeat; } h1 {background-color:#6495ed;} diff --git a/html/Makefile b/html/Makefile index 51ddf3e..7e04712 100644 --- a/html/Makefile +++ b/html/Makefile @@ -3,6 +3,7 @@ CFILES += abc_obj.c CFILES += abc_html.c CFILES += abc_css.c CFILES += abc_css_color.c +CFILES += abc_css_position.c CFILES += abc_io_util.c CFILES += abc_io_file.c diff --git a/html/abc_css_position.c b/html/abc_css_position.c new file mode 100644 index 0000000..18e1c54 --- /dev/null +++ b/html/abc_css_position.c @@ -0,0 +1,119 @@ +#include"abc_html.h" + +typedef struct css_pos_s +{ + char** names; + float value; +} css_pos_t; + +static char* css_left[] = {"left", "左", NULL}; +static char* css_right[] = {"right", "右", NULL}; +static char* css_top[] = {"top", "上", NULL}; +static char* css_bottom[] = {"bottom", "下", NULL}; + +static css_pos_t css_poss[] = +{ + {css_left, 0.0}, + {css_right, 1.0}, + {css_top, 0.0}, + {css_bottom, 1.0}, +}; + +static void __css_pos_value(float* value, const char* name, size_t name_len) +{ + int i; + for (i = 0; i < sizeof(css_poss) / sizeof(css_poss[0]); i++) { + css_pos_t* c = &css_poss[i]; + + int j; + for (j = 0; c->names[j]; j++) { + if (!strncmp(c->names[j], name, name_len)) { + *value = c->value; + return; + } + } + } +} + +int abc_css_position(float* x, float* y, float w, float h, abc_obj_t* obj, const uint8_t* str) +{ + *x = 0.5 - w / 2; + *y = 0.5 - h / 2; + + const uint8_t* p = str; + const uint8_t* unit = NULL; + + double value = 0.0; + int dot = 0; + int percent = 0; + int prev = 0; + int n = 0; + int c = 0; + + do { + c = *str; + + 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) { + + if (dot > 0) { + value += (c - '0') / (double)dot; + dot *= 10; + } else { + value *= 10.0; + value += c - '0'; + } + + } else if ('\0' == c || ' ' == c || '\t' == c || '\r' == c || '\n' == c) { + + if (c) { + if (' ' == prev || '\t' == prev || '\r' == prev || '\n' == prev) { + prev = c; + str++; + continue; + } + } + + if (percent) { + value *= 0.01; + + if (n > 0) + *y = value; + else + *x = value; + + } else if ('a' <= *p && *p <= 'z') { + if (n > 0) + __css_pos_value(y, p, (size_t)(str - p)); + else + __css_pos_value(x, p, (size_t)(str - p)); + + } else if (unit) { + // for other css units, ignore + } + + p = str; + unit = NULL; + value = 0.0; + dot = 0; + percent = 0; + n++; + } + + prev = c; + str++; + } while (c); + + return 0; +} diff --git a/html/abc_html.c b/html/abc_html.c index 5cf7171..855b2c2 100644 --- a/html/abc_html.c +++ b/html/abc_html.c @@ -15,10 +15,13 @@ static char* font_color_keys[] = {"font-color", "字体颜色", "color", "颜色 static char* font_bold_keys[] = {"bold", "加粗", NULL}; static char* font_italic_keys[] = {"italic", "斜体", NULL}; -static char* text_align_keys[] = {"text-align", "对齐", NULL}; +static char* text_align_keys[] = {"text-align", "对齐", NULL}; -static char* bg_color_keys[] = {"background-color", "背景颜色", NULL}; -static char* bg_image_keys[] = {"background-image", "背景图片", NULL}; +static char* bg_keys[] = {"background", "背景", NULL}; +static char* bg_color_keys[] = {"background-color", "背景颜色", NULL}; +static char* bg_image_keys[] = {"background-image", "背景图片", NULL}; +static char* bg_repeat_keys[] = {"background-repeat", "背景重复", NULL}; +static char* bg_position_keys[] = {"background-position", "背景位置", NULL}; static char* class_keys[] = {"class", "类名", NULL}; static char* type_keys[] = {"type", "类型", NULL}; @@ -105,10 +108,14 @@ 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}, - {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}, + {font_keys, "SimSong", ABC_HTML_ATTR_FONT, 0}, + {font_size_keys, "16", ABC_HTML_ATTR_FONT_SIZE, 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}, + {bg_position_keys, "", ABC_HTML_ATTR_BG_POSITION, ABC_HTML_FLAG_SHOW}, }; static html_attr_t h1_attrs[] = diff --git a/html/abc_html.h b/html/abc_html.h index 54aa23a..dd071ea 100644 --- a/html/abc_html.h +++ b/html/abc_html.h @@ -52,6 +52,7 @@ int abc_html_parse(abc_html_t* html); int abc_css_parse (abc_obj_t* css); int abc_css_use (abc_html_t* html, abc_obj_t* obj); -int abc_css_color (double* r, double* g, double* b, const uint8_t* str); +int abc_css_color (double* r, double* g, double* b, const uint8_t* str); +int abc_css_position(float* x, float* y, float w, float h, abc_obj_t* obj, const uint8_t* str); #endif diff --git a/html/abc_obj.h b/html/abc_obj.h index c114b4a..a7a680e 100644 --- a/html/abc_obj.h +++ b/html/abc_obj.h @@ -88,8 +88,11 @@ enum abc_objs ABC_HTML_ATTR_TEXT_ALIGN, + ABC_HTML_ATTR_BG, ABC_HTML_ATTR_BG_COLOR, ABC_HTML_ATTR_BG_IMAGE, + ABC_HTML_ATTR_BG_REPEAT, + ABC_HTML_ATTR_BG_POSITION, ABC_HTML_ATTR_WIDTH, ABC_HTML_ATTR_HEIGHT, diff --git a/ui/Makefile b/ui/Makefile index 6b09791..d154fd4 100644 --- a/ui/Makefile +++ b/ui/Makefile @@ -49,6 +49,7 @@ CFILES += ../html/abc_html.c CFILES += ../html/abc_obj.c CFILES += ../html/abc_css.c CFILES += ../html/abc_css_color.c +CFILES += ../html/abc_css_position.c CFILES += ../html/abc_io_util.c CFILES += ../html/abc_io_file.c diff --git a/ui/abc_render_bg_image.c b/ui/abc_render_bg_image.c index 4ac8667..6dd4802 100644 --- a/ui/abc_render_bg_image.c +++ b/ui/abc_render_bg_image.c @@ -17,13 +17,20 @@ static const char* frag_shader = "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" - " if (rect.x < xy.x && xy.x < rect.x + rect.z \n" - " && rect.y < xy.y && xy.y < rect.y + rect.w) { \n" - " xy.x = (xy.x - rect.x) / rect.z; \n" - " xy.y = (xy.y - rect.y) / rect.w; \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" @@ -42,6 +49,10 @@ 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) { @@ -135,11 +146,50 @@ static int _render_draw_bg_image(abc_render_t* render, abc_obj_t* obj, int width 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_logi("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 (!strcmp(attr->value->data, "repeat-x")) + repeat_y = 0; + + else if (!strcmp(attr->value->data, "repeat-y")) + repeat_x = 0; + + else if (!strcmp(attr->value->data, "no-repeat")) { + repeat_x = 0; + repeat_y = 0; + } + } + + scf_logi("repeat_x: %d, repeat_y: %d, index_x: %d, index_y: %d\n", repeat_x, repeat_y, index_x, index_y); + glUseProgram(program); - uniform_color = glGetUniformLocation(program, "bgColor"); - uniform_rgba = glGetUniformLocation(program, "tex_rgba"); - uniform_rect = glGetUniformLocation(program, "rect"); - uniform_mvp = glGetUniformLocation(program, "mvp"); + + 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); @@ -147,9 +197,15 @@ static int _render_draw_bg_image(abc_render_t* render, abc_obj_t* obj, int width 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); -- 2.25.1