From: yu.dongliang <18588496441@163.com>
Date: Sun, 19 Apr 2026 05:56:36 +0000 (+0800)
Subject: html/css: support css for
, , -
X-Git-Url: http://baseworks.info/?a=commitdiff_plain;h=376f4119a0d82852cb7c1639798e49dfd4a5a5be;p=abc.git
html/css: support css for
, , -
---
diff --git a/examples/list.html b/examples/list.html
index 6e12ce1..a08662b 100644
--- a/examples/list.html
+++ b/examples/list.html
@@ -2,8 +2,13 @@
diff --git a/examples/sqpurple.gif b/examples/sqpurple.gif
new file mode 100644
index 0000000..7300882
Binary files /dev/null and b/examples/sqpurple.gif differ
diff --git a/html/abc_html.c b/html/abc_html.c
index 10cf7ed..60eaa47 100644
--- a/html/abc_html.c
+++ b/html/abc_html.c
@@ -1350,6 +1350,7 @@ static int __html_parse_obj(abc_html_t* html, abc_char_t* c)
scf_list_add_tail(&html->current->childs, &obj->list);
+ obj ->index = html->current->n_childs++;
html->current = obj;
}
@@ -1373,7 +1374,8 @@ static int __html_parse_obj(abc_html_t* html, abc_char_t* c)
} else
ret = __html_parse_text(html, obj);
- switch (obj->type) {
+ switch (obj->type)
+ {
case ABC_HTML_SCRIPT:
if (__html_run_js(html, obj) < 0)
return -1;
diff --git a/html/abc_obj.c b/html/abc_obj.c
index 147cba0..ac1beaf 100644
--- a/html/abc_obj.c
+++ b/html/abc_obj.c
@@ -129,22 +129,6 @@ int abc_obj_set_attr(abc_obj_t* obj, int key, const char* value, size_t len)
return -EINVAL;
}
-int abc_recursive_set_attr(abc_obj_t* obj, int key, const char* value, size_t len)
-{
- scf_list_t* l;
- abc_obj_t* child;
-
- abc_obj_set_attr(obj, key, value, len);
-
- for (l = scf_list_head(&obj->childs); l != scf_list_sentinel(&obj->childs); l = scf_list_next(l)) {
- child = scf_list_data(l, abc_obj_t, list);
-
- abc_recursive_set_attr(child, key, value, len);
- }
-
- return 0;
-}
-
abc_obj_t* abc_obj_get_attr(abc_obj_t* obj, int key)
{
scf_list_t* l;
@@ -344,3 +328,111 @@ scf_string_t* abc_obj_to_string(abc_obj_t* obj)
scf_logi("%s\n", s->data);
return s;
}
+
+static scf_string_t* __li_style_roman(int num, const char** roman)
+{
+ scf_string_t* s = scf_string_alloc();
+ if (!s)
+ return NULL;
+
+ uint32_t data[] = {1000,900, 500,400, 100,90, 50,40, 10,9, 5,4, 1};
+
+ if (num < 0) {
+ num = -num;
+
+ if (scf_string_cat_cstr_len(s, "-", 1) < 0) {
+ scf_string_free(s);
+ return NULL;
+ }
+ }
+
+ int i;
+ for (i = 0; i < sizeof(data) / sizeof(data[0]); i++)
+ {
+ while (num >= data[i])
+ {
+ int k = (i & 0x1) + 1;
+
+ if (scf_string_cat_cstr_len(s, roman[i], k) < 0) {
+ scf_string_free(s);
+ return NULL;
+ }
+
+ num -= data[i];
+ }
+ }
+
+ if (scf_string_cat_cstr_len(s, ". ", 2) < 0) {
+ scf_string_free(s);
+ return NULL;
+ }
+
+ return s;
+}
+
+static scf_string_t* __li_style_number(int num, uint32_t base, const char c0)
+{
+ scf_string_t* s = scf_string_alloc();
+ if (!s)
+ return NULL;
+
+ if (num < 0) {
+ num = -num;
+
+ if (scf_string_cat_cstr_len(s, "-", 1) < 0) {
+ scf_string_free(s);
+ return NULL;
+ }
+ }
+
+ int i = s->len;
+ do {
+ uint8_t c = num % base + c0;
+
+ if (scf_string_cat_cstr_len(s, &c, 1) < 0) {
+ scf_string_free(s);
+ return NULL;
+ }
+
+ num /= base;
+ } while (num > 0);
+
+ int j = s->len - 1;
+ while (i < j) {
+ SCF_XCHG(s->data[i], s->data[j]);
+ i++;
+ j--;
+ }
+
+ if (scf_string_cat_cstr_len(s, ". ", 2) < 0) {
+ scf_string_free(s);
+ return NULL;
+ }
+
+ return s;
+}
+
+static const char* ROMAN[] = {"M","CM", "D","CD", "C","XC", "L","XL","X","IX","V","IV","I"};
+static const char* roman[] = {"m","cm", "d","cd", "c","xc", "l","xl","x","ix","v","iv","i"};
+
+scf_string_t* abc_ol_list_style(abc_obj_t* obj, int num)
+{
+ abc_obj_t* attr = abc_obj_find_attr(obj, ABC_CSS_LIST_STYLE_TYPE);
+ if (attr) {
+ const char* p = attr->value->data;
+
+ if (!__html_strcmp(p, "upper-roman"))
+ return __li_style_roman(num + 1, ROMAN);
+
+ else if (!__html_strcmp(p, "lower-roman"))
+ return __li_style_roman(num + 1, roman);
+
+ else if (!__html_strcmp(p, "upper-alpha"))
+ return __li_style_number(num, 26, 'A');
+
+ else if (!__html_strcmp(p, "lower-alpha"))
+ return __li_style_number(num, 26, 'a');
+ }
+
+ return __li_style_number(num, 10, '0');
+}
diff --git a/html/abc_obj.h b/html/abc_obj.h
index 8f27334..523ba51 100644
--- a/html/abc_obj.h
+++ b/html/abc_obj.h
@@ -139,6 +139,8 @@ struct abc_obj_s
scf_list_t attrs;
scf_list_t childs;
+ int n_childs;
+ int index;
abc_obj_t* parent;
@@ -159,6 +161,10 @@ struct abc_obj_s
int w;
int h;
+ double y_bearing;
+ int margin;
+ int padding;
+
int progress;
uint32_t jiffies; // timeout numbers of sys timer
@@ -200,6 +206,6 @@ abc_obj_t* abc_obj_find_type(abc_obj_t* root, int type);
scf_string_t* abc_obj_to_string(abc_obj_t* obj);
-int abc_recursive_set_attr(abc_obj_t* obj, int key, const char* value, size_t len);
+scf_string_t* abc_ol_list_style(abc_obj_t* obj, int num);
#endif
diff --git a/ui/abc.h b/ui/abc.h
index 6c85004..ff3b339 100644
--- a/ui/abc.h
+++ b/ui/abc.h
@@ -76,6 +76,6 @@ int __init_program(GLuint* pprog, const char* vert_shader, const char* frag_sha
int __init_buffers(GLuint* vao, GLuint buffers[2]);
-int __init_text(cairo_t* cr, abc_obj_t* obj, double dx);
+int __init_text(cairo_t* cr, abc_obj_t* obj, int num_flag);
#endif
diff --git a/ui/abc_layout.c b/ui/abc_layout.c
index 84882f4..818668c 100644
--- a/ui/abc_layout.c
+++ b/ui/abc_layout.c
@@ -190,9 +190,6 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height)
if (ret < 0)
return ret;
- if (ABC_HTML_UL == root->type || ABC_HTML_OL == root->type)
- child->w += 16;
-
x = root->x + 4;
y = child->y + child->h;
h = 0;
diff --git a/ui/abc_layout_h1.c b/ui/abc_layout_h1.c
index a4ade87..2e869ab 100644
--- a/ui/abc_layout_h1.c
+++ b/ui/abc_layout_h1.c
@@ -5,6 +5,7 @@ int abc_layout_h1(abc_layout_t* layout, abc_obj_t* obj, int width, int height)
abc_obj_t* attr;
abc_obj_t* style;
cairo_text_extents_t extents;
+ cairo_text_extents_t extents2;
cairo_surface_t* surface;
cairo_t* cr;
@@ -31,9 +32,12 @@ int abc_layout_h1(abc_layout_t* layout, abc_obj_t* obj, int width, int height)
cairo_select_font_face(cr, attr->value->data, italic, bold);
}
+ int size = 16;
attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE);
- if (attr)
- cairo_set_font_size(cr, atoi(attr->value->data));
+ if (attr) {
+ size = atoi(attr->value->data);
+ cairo_set_font_size(cr, size);
+ }
cairo_font_options_t *options = cairo_font_options_create();
cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_SUBPIXEL);
@@ -43,13 +47,36 @@ int abc_layout_h1(abc_layout_t* layout, abc_obj_t* obj, int width, int height)
cairo_font_options_destroy(options);
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+
cairo_text_extents(cr, obj->text->data, &extents);
-// obj->x = 4;
-// obj->y = 4;
- obj->w = extents.width + extents.x_bearing;
- obj->h = extents.height + extents.height / 2;
+ int w = 0;
+ if (ABC_HTML_OL == obj->parent->type)
+ {
+ if (0 == obj->parent->padding) {
+ scf_string_t* s = abc_ol_list_style(obj->parent, obj->parent->n_childs);
+ if (s) {
+ cairo_text_extents(cr, s->data, &extents2);
+
+ obj->parent->padding = extents2.width + extents2.x_bearing + size / 2;
+
+ scf_string_free(s);
+ s = NULL;
+ }
+ }
+
+ obj->y_bearing = extents.y_bearing;
+
+ w = obj->parent->padding;
+ } else if (ABC_HTML_UL == obj->parent->type) {
+ w = size;
+ obj->parent->padding = size;
+ }
+
+ w += extents.width + extents.x_bearing;
+ obj->w = w;
+ obj->h = extents.height + extents.height / 2;
obj->w = (obj->w + 3) & ~0x3;
obj->h = (obj->h + 3) & ~0x3;
diff --git a/ui/abc_render_h1.c b/ui/abc_render_h1.c
index e6d90cd..461f259 100644
--- a/ui/abc_render_h1.c
+++ b/ui/abc_render_h1.c
@@ -38,7 +38,7 @@ static int _render_fini_h1(abc_render_t* render)
return 0;
}
-int __init_text(cairo_t* cr, abc_obj_t* obj, double dx)
+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) {
@@ -69,6 +69,13 @@ int __init_text(cairo_t* cr, abc_obj_t* obj, double dx)
cairo_set_font_size(cr, size);
}
+ cairo_font_options_t *options = cairo_font_options_create();
+ cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_SUBPIXEL);
+ cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_FULL);
+ cairo_font_options_set_hint_metrics(options, CAIRO_HINT_METRICS_ON);
+ cairo_set_font_options(cr, options);
+ cairo_font_options_destroy(options);
+
attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_COLOR);
if (attr)
abc_css_color(&r, &g, &b, attr->value->data);
@@ -76,7 +83,19 @@ int __init_text(cairo_t* cr, abc_obj_t* obj, double dx)
cairo_set_source_rgba(cr, r, g, b, 1.0);
cairo_text_extents (cr, obj->text->data, &extents);
- cairo_move_to (cr, extents.x_bearing + dx, -extents.y_bearing);
+ switch (obj->parent->type)
+ {
+ case ABC_HTML_OL:
+ if (num_flag)
+ cairo_move_to(cr, obj->parent->padding - (extents.x_bearing + extents.width + size / 2), -obj->y_bearing);
+ else
+ cairo_move_to(cr, extents.x_bearing + obj->parent->padding, -extents.y_bearing);
+ break;
+ default:
+ cairo_move_to(cr, extents.x_bearing + obj->parent->padding, -extents.y_bearing);
+ break;
+ };
+
cairo_show_text(cr, obj->text->data);
cairo_stroke(cr);
@@ -139,7 +158,7 @@ static int _render_draw_h1(abc_render_t* render, abc_obj_t* obj, int width, int
cairo_stroke(cr);
if (obj->text)
- __init_text(cr, obj, 0.0);
+ __init_text(cr, obj, 0);
// cairo_surface_write_to_png(surface, "tmp.png");
cairo_destroy(cr);
diff --git a/ui/abc_render_li.c b/ui/abc_render_li.c
index 9349b6b..138f4af 100644
--- a/ui/abc_render_li.c
+++ b/ui/abc_render_li.c
@@ -63,6 +63,12 @@ static int _render_draw_li(abc_render_t* render, abc_obj_t* obj, int width, int
double r = 0.0;
double g = 0.0;
double b = 0.0;
+ int size = 16;
+
+ 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_BG_COLOR);
if (attr)
abc_css_color(&r, &g, &b, attr->value->data);
@@ -76,40 +82,9 @@ static int _render_draw_li(abc_render_t* render, abc_obj_t* obj, int width, int
cairo_fill(cr);
cairo_stroke(cr);
+ int offset = obj->parent->padding;
if (obj->text)
- __init_text(cr, obj, 16);
-
- if (ABC_HTML_UL == obj->parent->type) {
- r = 0.0;
- g = 0.0;
- b = 0.0;
- attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_COLOR);
- if (attr)
- abc_css_color(&r, &g, &b, attr->value->data);
-
- cairo_set_source_rgb(cr, r, g, b);
-
- attr = abc_obj_find_attr(obj, ABC_CSS_LIST_STYLE_TYPE);
- if (attr) {
- if (!strcmp(attr->value->data, "circle"))
- cairo_arc (cr, 8, 8, 3, 0, 2 * M_PI);
-
- else if (!strcmp(attr->value->data, "square")) {
- cairo_rectangle(cr, 5, 5, 6, 6);
- cairo_fill(cr);
-
- } else if (!strcmp(attr->value->data, "disc")) {
- cairo_arc (cr, 8, 8, 3, 0, 2 * M_PI);
- cairo_fill(cr);
- }
- } else {
- cairo_arc (cr, 8, 8, 3, 0, 2 * M_PI);
- cairo_fill(cr);
- }
-
- cairo_stroke(cr);
- }
-// cairo_surface_write_to_png(surface, "tmp.png");
+ __init_text(cr, obj, 0);
cairo_destroy(cr);
cairo_surface_destroy(surface);
@@ -121,13 +96,79 @@ static int _render_draw_li(abc_render_t* render, abc_obj_t* obj, int width, int
GLfloat x = 0.0;
GLfloat y = 0.0;
- GLfloat w = 0.0;
- GLfloat h = 0.0;
+ GLfloat w = offset / (float)obj->w;
+ GLfloat h = size / (float)obj->h;
attr = abc_obj_find_attr(obj, ABC_CSS_LIST_STYLE_IMAGE);
- if (attr && attr->value && attr->value->len > 0)
+ if (ABC_HTML_OL == obj->parent->type || !attr || !attr->value || attr->value->len <= 0)
{
+ bgra1 = calloc(1, offset * size * 4);
+ if (!bgra1) {
+ free(bgra);
+ return -ENOMEM;
+ }
+
+ surface = cairo_image_surface_create_for_data(bgra1, CAIRO_FORMAT_ARGB32, offset, size, offset * 4);
+ cr = cairo_create(surface);
+
+ cairo_set_line_width(cr, 1);
+ cairo_set_source_rgb(cr, r, g, b);
+ cairo_rectangle(cr, 0, 0, offset, size);
+ cairo_fill(cr);
+ cairo_stroke(cr);
+
+ if (ABC_HTML_OL == obj->parent->type)
+ {
+ scf_string_t* s = abc_ol_list_style(obj, obj->index);
+ if (!s) {
+ free(bgra1);
+ free(bgra);
+ return -ENOMEM;
+ }
+
+ SCF_XCHG(obj->text, s);
+ __init_text(cr, obj, 1);
+ SCF_XCHG(obj->text, s);
+
+ scf_string_free(s);
+ s = NULL;
+ } else {
+ r = 0.0;
+ g = 0.0;
+ b = 0.0;
+ attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_COLOR);
+ if (attr)
+ abc_css_color(&r, &g, &b, attr->value->data);
+
+ cairo_set_source_rgb(cr, r, g, b);
+
+ attr = abc_obj_find_attr(obj, ABC_CSS_LIST_STYLE_TYPE);
+ if (attr) {
+ if (!strcmp(attr->value->data, "circle"))
+ cairo_arc (cr, offset / 2, size / 2, size / 4, 0, 2 * M_PI);
+
+ else if (!strcmp(attr->value->data, "square")) {
+ cairo_rectangle(cr, offset / 4, size / 4, size / 2, size / 2);
+ cairo_fill(cr);
+
+ } else if (!strcmp(attr->value->data, "disc")) {
+ cairo_arc (cr, offset / 2, size / 2, size / 4, 0, 2 * M_PI);
+ cairo_fill(cr);
+ }
+ } else {
+ cairo_arc (cr, offset / 2, size / 2, size / 4, 0, 2 * M_PI);
+ cairo_fill(cr);
+ }
+
+ cairo_stroke(cr);
+ }
+
+ cairo_destroy(cr);
+ cairo_surface_destroy(surface);
+ surface = NULL;
+ cr = NULL;
+ } else {
scf_string_t* spath = NULL;
abc_io_t* io = NULL;
@@ -163,13 +204,10 @@ static int _render_draw_li(abc_render_t* render, abc_obj_t* obj, int width, int
return ret;
}
- x = obj->h * 0.333 / (float)obj->w;
- y = 0.333;
- w = x;
- h = y;
-
- if (0 == texture_img)
- __init_texture(&texture_img, GL_RGBA, img->width, img->height, NULL);
+ x = size / 4 / (float)obj->w;
+ y = size / 4 / (float)obj->h;
+ w = x * 2;
+ h = y * 2;
}
if (0 == program)
@@ -181,6 +219,9 @@ static int _render_draw_li(abc_render_t* render, abc_obj_t* obj, int width, int
if (0 == texture_rgba)
__init_texture(&texture_rgba, GL_RGBA, obj->w, obj->h, NULL);
+ if (0 == texture_img)
+ __init_texture(&texture_img, GL_RGBA, offset, size, NULL);
+
float mvp[16];
__compute_mvp(mvp, 0, 0, 0);
@@ -213,14 +254,15 @@ static int _render_draw_li(abc_render_t* render, abc_obj_t* obj, int width, int
glActiveTexture(GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, texture_rgba);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, obj->w, obj->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, bgra);
- glUniform1i(uniform_rgba, 0);
-
- if (img) {
- glActiveTexture(GL_TEXTURE1);
- glBindTexture (GL_TEXTURE_2D, texture_img);
- glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, img->width, img->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bgra1);
- glUniform1i(uniform_img, 1);
- }
+ glUniform1i(uniform_rgba, 0);
+
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture (GL_TEXTURE_2D, texture_img);
+ if (img)
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img->width, img->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bgra1);
+ else
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, offset, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, bgra1);
+ glUniform1i(uniform_img, 1);
glUniform4f(uniform_rect, x, y, w, h);