From 3ee9002b2615a5fd50236cbde76282646b9dc147 Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Mon, 27 Apr 2026 18:53:38 +0800 Subject: [PATCH] css: text-align & vertical-align ok for
| , | --- examples/table.html | 21 ++++++++++++--- html/Makefile | 1 + html/abc_css_length.c | 62 +++++++++++++++++++++++++++++++++++++++++++ html/abc_html.c | 19 +++++++++++++ html/abc_html.h | 1 + html/abc_obj.h | 2 ++ ui/Makefile | 1 + ui/abc_layout_table.c | 60 +++++++++++++++++++++++++++++++++++++---- ui/abc_render_td.c | 27 ++++++++++++++++--- 9 files changed, 183 insertions(+), 11 deletions(-) create mode 100644 html/abc_css_length.c diff --git a/examples/table.html b/examples/table.html index 5c73bda..15b3ba1 100644 --- a/examples/table.html +++ b/examples/table.html @@ -2,13 +2,28 @@ diff --git a/html/Makefile b/html/Makefile index 88b0972..276d458 100644 --- a/html/Makefile +++ b/html/Makefile @@ -5,6 +5,7 @@ CFILES += abc_css.c CFILES += abc_css_color.c CFILES += abc_css_position.c CFILES += abc_css_border.c +CFILES += abc_css_length.c CFILES += abc_io_util.c CFILES += abc_io_file.c diff --git a/html/abc_css_length.c b/html/abc_css_length.c new file mode 100644 index 0000000..f51c989 --- /dev/null +++ b/html/abc_css_length.c @@ -0,0 +1,62 @@ +#include"abc_html.h" + +int abc_css_length(abc_obj_t* obj, const uint8_t* str, int len) +{ + const uint8_t* p = str; + const uint8_t* unit = NULL; + + int x = 0; + double value = 0.0; + int dot = 0; + int percent = 0; + int prev = 0; + int c = 0; + + do { + c = *str; + + if ('.' == c) + dot = 10; + else if ('%' == c) + percent++; + + else if ('a' <= c && 'z' >= c) { + 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 (' ' == prev || '\t' == prev || '\r' == prev || '\n' == prev) + goto next; + + if (percent) + x = value * 0.01 * len; + else if (unit) { + // for other css units, ignore + x = value; + } + + unit = NULL; + value = 0.0; + dot = 0; + percent = 0; + break; + } + +next: + prev = c; + str++; + } while (c); + + return x; +} diff --git a/html/abc_html.c b/html/abc_html.c index 1fc771a..af65462 100644 --- a/html/abc_html.c +++ b/html/abc_html.c @@ -21,6 +21,8 @@ static char* text_decoration_keys[] = {"text-decoration", "ä¸å线", static char* text_transform_keys[] = {"text-transform", "大å°å", NULL}; static char* text_indent_keys[] = {"text-transform", "缩è¿", NULL}; +static char* vertical_align_keys[] = {"vertical-align", "åç´å¯¹é½", NULL}; + static char* bg_keys[] = {"background", "èæ¯", NULL}; static char* bg_color_keys[] = {"background-color", "èæ¯é¢è²", NULL}; static char* bg_image_keys[] = {"background-image", "èæ¯å¾ç", NULL}; @@ -295,6 +297,8 @@ static html_attr_t css_id_attrs[] = {text_transform_keys, "", ABC_HTML_ATTR_TEXT_TRANSFORM, ABC_HTML_FLAG_SHOW}, {text_indent_keys, "", ABC_HTML_ATTR_TEXT_INDENT, ABC_HTML_FLAG_SHOW}, + {vertical_align_keys, "", ABC_HTML_ATTR_VERTICAL_ALIGN, ABC_HTML_FLAG_SHOW}, + {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}, @@ -444,6 +448,9 @@ static html_attr_t table_attrs[] = {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}, + {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}, @@ -463,6 +470,9 @@ static html_attr_t th_attrs[] = {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}, + {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}, @@ -472,6 +482,9 @@ static html_attr_t th_attrs[] = {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}, }; static html_attr_t td_attrs[] = @@ -480,6 +493,9 @@ static html_attr_t td_attrs[] = {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}, + {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}, @@ -489,6 +505,9 @@ static html_attr_t td_attrs[] = {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}, }; static html_attr_t script_attrs[] = diff --git a/html/abc_html.h b/html/abc_html.h index 2058468..8d5ea23 100644 --- a/html/abc_html.h +++ b/html/abc_html.h @@ -59,5 +59,6 @@ int abc_css_position(float* x, float* y, float w, float h, abc_obj_t* obj, int abc_css_border(double* r, double* g, double* b, int* width, int* type, abc_obj_t* obj, const uint8_t* str); int abc_css_margin(abc_obj_t* obj); +int abc_css_length(abc_obj_t* obj, const uint8_t* str, int len); #endif diff --git a/html/abc_obj.h b/html/abc_obj.h index 816fa7b..ee84845 100644 --- a/html/abc_obj.h +++ b/html/abc_obj.h @@ -95,6 +95,8 @@ enum abc_objs ABC_HTML_ATTR_TEXT_TRANSFORM, ABC_HTML_ATTR_TEXT_INDENT, + ABC_HTML_ATTR_VERTICAL_ALIGN, + ABC_HTML_ATTR_BG, ABC_HTML_ATTR_BG_COLOR, ABC_HTML_ATTR_BG_IMAGE, diff --git a/ui/Makefile b/ui/Makefile index 7ca2bea..91bc65c 100644 --- a/ui/Makefile +++ b/ui/Makefile @@ -50,6 +50,7 @@ CFILES += ../html/abc_css.c CFILES += ../html/abc_css_color.c CFILES += ../html/abc_css_position.c CFILES += ../html/abc_css_border.c +CFILES += ../html/abc_css_length.c CFILES += ../html/abc_io_util.c CFILES += ../html/abc_io_file.c diff --git a/ui/abc_layout_table.c b/ui/abc_layout_table.c index 8c4124d..b877475 100644 --- a/ui/abc_layout_table.c +++ b/ui/abc_layout_table.c @@ -18,13 +18,42 @@ int abc_layout_table(abc_layout_t* layout, abc_obj_t* obj, int width, int height } } - int d = abc_css_margin(obj); + int w_set = 0; + int h_set = 0; + int d = abc_css_margin(obj); + + attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_WIDTH); + if (attr && attr->value && attr->value->len > 0) + { + obj->w = abc_css_length(obj, attr->value->data, width); + obj->w += d * 2; + + if (obj->w > width - obj->x) + obj->w = width - obj->x; + + w_set = 1; + } + + attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_HEIGHT); + if (attr && attr->value && attr->value->len > 0) + { + obj->h = abc_css_length(obj, attr->value->data, height); + obj->h += d * 2; + + if (obj->h > height - obj->y) + obj->h = height - obj->y; + + h_set = 1; + } + int x = obj->x + d; int y = obj->y + d; for (l = scf_list_head(&obj->childs); l != scf_list_sentinel(&obj->childs); l = scf_list_next(l)) { tr = scf_list_data(l, abc_obj_t, list); + int w = obj->td_width; + int h = obj->td_height; int d2 = d; for (l2 = scf_list_head(&tr->childs); l2 != scf_list_sentinel(&tr->childs); l2 = scf_list_next(l2)) { @@ -35,18 +64,39 @@ int abc_layout_table(abc_layout_t* layout, abc_obj_t* obj, int width, int height d2 = abc_css_margin(td); + if (w_set) { + w_set = 0; + obj->td_width = (obj->w - d * 2) / tr->n_childs - d2 * 2; + } + + if (h_set) { + h_set = 0; + obj->td_height = (obj->h - d * 2) / obj->n_childs - d2 * 2; + } + + w = obj->td_width; + h = obj->td_height; + + attr = abc_obj_get_attr(td, ABC_HTML_ATTR_WIDTH); + if (attr && attr->value && attr->value->len > 0) + w = abc_css_length(td, attr->value->data, obj->w); + + attr = abc_obj_get_attr(td, ABC_HTML_ATTR_HEIGHT); + if (attr && attr->value && attr->value->len > 0) + h = abc_css_length(td, attr->value->data, obj->h); + td->x = x; td->y = y; - td->w = obj->td_width + d2 * 2; - td->h = obj->td_height + d2 * 2; + td->w = w + d2 * 2; + td->h = h + d2 * 2; x += td->w; } obj->w = x + d - obj->x; - x = obj->x + d; - y += obj->td_height + d2 * 2; + x = obj->x + d; + y += h + d2 * 2; } obj->h = y + d - obj->y; diff --git a/ui/abc_render_td.c b/ui/abc_render_td.c index 08670ee..558e87e 100644 --- a/ui/abc_render_td.c +++ b/ui/abc_render_td.c @@ -123,9 +123,30 @@ static int _render_draw_td(abc_render_t* render, abc_obj_t* obj, int width, int if (attr) cairo_set_font_size(cr, atoi(attr->value->data)); - cairo_text_extents(cr, obj->text->data, &extents); - cairo_move_to (cr, extents.x_bearing, -extents.y_bearing); - cairo_show_text (cr, obj->text->data); + cairo_text_extents(cr, obj->text->data, &extents); + double x_bearing = extents.x_bearing; + double y_bearing = -extents.y_bearing; + + attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_TEXT_ALIGN); + if (attr) { + if (!__html_strcmp(attr->value->data, "right")) + x_bearing = w - extents.width - x_bearing; + + else if (!__html_strcmp(attr->value->data, "center")) + x_bearing = (w - extents.width) / 2 - x_bearing; + } + + attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_VERTICAL_ALIGN); + if (attr) { + if (!__html_strcmp(attr->value->data, "bottom")) + y_bearing += h - extents.height; + + else if (!__html_strcmp(attr->value->data, "center")) + y_bearing += (h - extents.height) / 2; + } + + cairo_move_to (cr, x_bearing, y_bearing); + cairo_show_text(cr, obj->text->data); // cairo_surface_write_to_png(surface, "tmp.png"); -- 2.25.1 |
|---|