css: text-align
authoryu.dongliang <18588496441@163.com>
Fri, 13 Mar 2026 06:13:18 +0000 (14:13 +0800)
committeryu.dongliang <18588496441@163.com>
Fri, 13 Mar 2026 06:13:18 +0000 (14:13 +0800)
examples/css.html
html/abc_css.c
html/abc_html.c
html/abc_obj.c
html/abc_obj.h
ui/abc_layout.c
ui/abc_layout_h1.c
ui/abc_render.c
ui/abc_render_h1.c

index bf8095a51d99916fd3d2153839724bf3b92b178f..5a0be37153dc3978d2ab7ee3626d2be9e295c774 100644 (file)
@@ -12,7 +12,7 @@ p
 
 <body>
 <p>Hello World!</p>
-<p>这个段落采用CSS样式化。</p>
+<p>这个段落<b>采用</b>CSS样式化。</p>
 </body>
 
 </html>
index ebcbb13974b26567cd7089050c5df99774c46569..66ecf581929855068509e7f54cb6c023d4380a08 100644 (file)
@@ -318,7 +318,7 @@ int abc_css_use(abc_html_t* html, abc_obj_t* obj)
                for (l   = scf_list_head(&label->attrs); l != scf_list_sentinel(&label->attrs); l = scf_list_next(l)) {
                        attr = scf_list_data(l, abc_obj_t, list);
 
-                       abc_obj_set_attr(obj, attr->type, attr->value->data);
+                       abc_recursive_set_attr(obj, attr->type, attr->value->data);
                }
        }
 
index 63a68fbd9961deb7200fc1a16ba4de4aec40f036..548510078a0297744ca6cbc7a7d1459e6b4eb540 100644 (file)
@@ -11,6 +11,9 @@ static char* font_keys[]       = {"font",       "字体",     NULL};
 static char* font_size_keys[]  = {"font-size",  "字号",     NULL};
 static char* font_color_keys[] = {"font-color", "字体颜色", "color", "颜色", NULL};
 
+static char* font_bold_keys[]   = {"bold",      "加粗",     NULL};
+static char* font_italic_keys[] = {"italic",    "斜体",     NULL};
+
 static char* text_align_keys[] = {"text-align", "对齐",     NULL};
 
 static char* type_keys[]       = {"type",       "类型",     NULL};
@@ -68,6 +71,8 @@ static char* h5_keys[]         = {"h5",         "标题5",    NULL};
 static char* h6_keys[]         = {"h6",         "标题6",    NULL};
 static char* p_keys[]          = {"p",          "段落",     NULL};
 static char* a_keys[]          = {"a",          "超链接",   NULL};
+static char* b_keys[]          = {"b",          "加粗",     NULL};
+static char* i_keys[]          = {"i",          "斜体",     NULL};
 
 static char* play_keys[]       = {"play",       "播放",     NULL};
 static char* progress_keys[]   = {"progress",   "进度条",   NULL};
@@ -139,6 +144,24 @@ static html_attr_t  p_attrs[] =
        {text_align_keys,  "left",       ABC_HTML_ATTR_TEXT_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_bold_keys,   "true",       ABC_HTML_ATTR_FONT_BOLD,  0},
+       {font_color_keys,  "black",      ABC_HTML_ATTR_FONT_COLOR, ABC_HTML_FLAG_SHOW},
+       {text_align_keys,  "left",       ABC_HTML_ATTR_TEXT_ALIGN, ABC_HTML_FLAG_SHOW},
+};
+
+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_italic_keys, "true",       ABC_HTML_ATTR_FONT_ITALIC, 0},
+       {font_color_keys,  "black",      ABC_HTML_ATTR_FONT_COLOR,  ABC_HTML_FLAG_SHOW},
+       {text_align_keys,  "left",       ABC_HTML_ATTR_TEXT_ALIGN,  ABC_HTML_FLAG_SHOW},
+};
+
 static html_attr_t  a_attrs[] =
 {
        {href_keys,        "",           ABC_HTML_ATTR_HREF,       ABC_HTML_FLAG_SHOW},
@@ -252,6 +275,9 @@ static html_label_t  html_labels[] =
        {script_keys,   ABC_HTML_SCRIPT,   abc_number_of(script_attrs), script_attrs, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
 
        {style_keys,    ABC_HTML_STYLE,    0,                           NULL,         ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+
+       {b_keys,        ABC_HTML_B,        abc_number_of(b_attrs),     b_attrs,       ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {i_keys,        ABC_HTML_I,        abc_number_of(i_attrs),     i_attrs,       ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
 };
 
 static int __html_parse_obj(abc_html_t* html, abc_char_t* c);
index b2ada1f7b2badcf63470594a9a55c06a4749010b..b026202bd21183ba6ab1e696924af5fed985df39 100644 (file)
@@ -129,6 +129,22 @@ int abc_obj_set_attr(abc_obj_t* obj, int key, const char* value)
        return -EINVAL;
 }
 
+int abc_recursive_set_attr(abc_obj_t* obj, int key, const char* value)
+{
+       scf_list_t*  l;
+       abc_obj_t*   child;
+
+       abc_obj_set_attr(obj, key, value);
+
+       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);
+       }
+
+       return 0;
+}
+
 abc_obj_t* abc_obj_get_attr(abc_obj_t* obj, int key)
 {
        scf_list_t*   l;
index 66663b70618de996ddb3abc61456bf4dee1140e8..812b69482dd56379aa6749e1973ede6aa31ab33d 100644 (file)
@@ -56,9 +56,11 @@ enum abc_objs
        ABC_HTML_PROGRESS,
 
        ABC_HTML_SCRIPT,
-
        ABC_HTML_STYLE,
 
+       ABC_HTML_B,
+       ABC_HTML_I,
+
        ABC_HTML_NB, // total HTML objects
 
        ABC_HTML_ATTR_ID,
@@ -77,6 +79,8 @@ enum abc_objs
        ABC_HTML_ATTR_FONT,
        ABC_HTML_ATTR_FONT_SIZE,
        ABC_HTML_ATTR_FONT_COLOR,
+       ABC_HTML_ATTR_FONT_BOLD,
+       ABC_HTML_ATTR_FONT_ITALIC,
 
        ABC_HTML_ATTR_TEXT_ALIGN,
 
@@ -158,4 +162,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);
+
 #endif
index 63c0a94fc4f91d053dfb14bde421cb9e8049f929..c8f61fa2d22313b6c8c8f31315f68e20ada3147d 100644 (file)
@@ -64,6 +64,9 @@ static abc_layout_pt abc_layouts[ABC_HTML_NB] =
 
        [ABC_HTML_SCRIPT]   = abc_layout_empty,
        [ABC_HTML_STYLE]    = abc_layout_empty,
+
+       [ABC_HTML_B]        = abc_layout_h1,
+       [ABC_HTML_I]        = abc_layout_h1,
 };
 
 int abc_layout_obj(abc_layout_t* layout, abc_obj_t* obj, int width, int height)
@@ -78,6 +81,54 @@ int abc_layout_obj(abc_layout_t* layout, abc_obj_t* obj, int width, int height)
        return f(layout, obj, width, height);
 }
 
+void abc_css_update_xy(abc_obj_t* root, int dx, int dy)
+{
+       scf_list_t*  l;
+       abc_obj_t*   obj;
+
+       for (l  = scf_list_head(&root->childs); l != scf_list_sentinel(&root->childs); l = scf_list_next(l)) {
+               obj = scf_list_data(l, abc_obj_t, list);
+
+               obj->x += dx;
+               obj->y += dy;
+
+               abc_css_update_xy(obj, dx, dy);
+       }
+}
+
+int abc_layout_css(abc_obj_t* root)
+{
+       abc_obj_t*  parent = root->parent;
+       abc_obj_t*  attr;
+
+       attr = abc_obj_get_attr(root, ABC_HTML_ATTR_TEXT_ALIGN);
+       if (attr) {
+               if (!parent || parent->w <= 0 || parent->h <= 0)
+                       return 0;
+
+               switch (parent->type)
+               {
+                       case ABC_HTML_BODY:
+                               break;
+                       default:
+                               return 0;
+                               break;
+               }
+
+               int x = root->x;
+
+               if (!strcmp(attr->value->data, "center"))
+                       root->x = parent->x + (parent->w - root->w) / 2 + 4;
+
+               else if (!strcmp(attr->value->data, "right"))
+                       root->x = parent->x + parent->w - root->w - 4;
+
+               abc_css_update_xy(root, root->x - x, 0);
+       }
+
+       return 0;
+}
+
 int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height)
 {
        scf_string_t* key;
@@ -90,6 +141,16 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height)
        if (width <= 0 || height <= 0)
                return -EINVAL;
 
+       switch (root->type)
+       {
+               case ABC_HTML_BODY:
+                       root->w = width;
+                       root->h = height;
+                       break;
+               default:
+                       break;
+       };
+
        int x = root->x + 4;
        int y = root->y + 4;
        int h = 0;
@@ -101,8 +162,8 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height)
                child = scf_list_data(l, abc_obj_t, list);
 
                int ret;
-               switch (child->type) {
-
+               switch (child->type)
+               {
                        case ABC_HTML_H1:
                        case ABC_HTML_H2:
                        case ABC_HTML_H3:
@@ -182,6 +243,8 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height)
        if (root->h < Y - root->y)
                root->h = Y - root->y;
 
+       abc_layout_css(root);
+
        if (root->keys)
                scf_logd("key: %s, x: %d, y: %d, w: %d, h: %d\n", root->keys[0], root->x, root->y, root->w, root->h);
 
index 56f7032c5d11a6540ba7cfbb57a1430d8d74a526..ebc69a905db3f681a810c8e11416513eb9f9776e 100644 (file)
@@ -14,13 +14,30 @@ int abc_layout_h1(abc_layout_t* layout, abc_obj_t* obj, int width, int height)
        cr      = cairo_create(surface);
 
        attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT);
-       if (attr)
-               cairo_select_font_face(cr, attr->value->data, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
+       if (attr) {
+               int bold   = CAIRO_FONT_WEIGHT_NORMAL;
+               int italic = CAIRO_FONT_SLANT_NORMAL;
+
+               if (abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_BOLD))
+                       bold = CAIRO_FONT_WEIGHT_BOLD;
+
+               if (abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_ITALIC))
+                       italic = CAIRO_FONT_SLANT_OBLIQUE;
+
+               cairo_select_font_face(cr, attr->value->data, italic, bold);
+       }
 
        attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE);
        if (attr)
                cairo_set_font_size(cr, atoi(attr->value->data));
 
+       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);
+
        cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
        cairo_text_extents(cr, obj->text->data, &extents);
 
index 2784190adeb6244e30b1373bab04d576694431c2..0ed4fde78202dea61f9889d7547baa30f5e82d8c 100644 (file)
@@ -66,6 +66,9 @@ static abc_render_t* abc_renders[ABC_HTML_NB] =
 
        [ABC_HTML_SCRIPT]   = &abc_render_empty,
        [ABC_HTML_STYLE]    = &abc_render_empty,
+
+       [ABC_HTML_B]        = &abc_render_h1,
+       [ABC_HTML_I]        = &abc_render_h1,
 };
 
 int abc_renders_fini()
index 810f6ef44059d4418540305b0f96511ab407bf8f..06a983464c4dd3c608f346f12550d60be3dda3bb 100644 (file)
@@ -71,13 +71,30 @@ static int _render_draw_h1(abc_render_t* render, abc_obj_t* obj, int width, int
        cairo_stroke(cr);
 
        attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT);
-       if (attr)
-               cairo_select_font_face(cr, attr->value->data, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
+       if (attr) {
+               int bold   = CAIRO_FONT_WEIGHT_NORMAL;
+               int italic = CAIRO_FONT_SLANT_NORMAL;
+
+               if (abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_BOLD))
+                       bold = CAIRO_FONT_WEIGHT_BOLD;
+
+               if (abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_ITALIC))
+                       italic = CAIRO_FONT_SLANT_OBLIQUE;
+
+               cairo_select_font_face(cr, attr->value->data, italic, bold);
+       }
 
        attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE);
        if (attr)
                cairo_set_font_size(cr, atoi(attr->value->data));
 
+       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);
+
        cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
        attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_COLOR);
        if (attr) {
@@ -96,7 +113,7 @@ static int _render_draw_h1(abc_render_t* render, abc_obj_t* obj, int width, int
        cairo_move_to  (cr, extents.x_bearing, -extents.y_bearing);
        cairo_show_text(cr, obj->text->data);
 
-//     cairo_surface_write_to_png(surface, "tmp.png");
+       cairo_surface_write_to_png(surface, "tmp.png");
 
        cairo_destroy(cr);
        cairo_surface_destroy(surface);