int n_attrs;
html_attr_t* attrs;
+
+ uint32_t flags;
} html_label_t;
+#define abc_number_of(__array) (sizeof(__array) / sizeof(__array[0]))
static html_attr_t h1_attrs[] =
{
- {"font", "Liberation Serif", ABC_HTML_ATTR_FONT},
- {"font-size", "32", ABC_HTML_ATTR_FONT_SIZE},
+ {"font", "SimHei", ABC_HTML_ATTR_FONT},
+ {"font-size", "40", ABC_HTML_ATTR_FONT_SIZE},
};
static html_attr_t h2_attrs[] =
{
- {"font", "Liberation Serif", ABC_HTML_ATTR_FONT},
- {"font-size", "28", ABC_HTML_ATTR_FONT_SIZE},
+ {"font", "SimHei", ABC_HTML_ATTR_FONT},
+ {"font-size", "32", ABC_HTML_ATTR_FONT_SIZE},
};
static html_attr_t h3_attrs[] =
{
- {"font", "Liberation Serif", ABC_HTML_ATTR_FONT},
- {"font-size", "24", ABC_HTML_ATTR_FONT_SIZE},
+ {"font", "SimHei", ABC_HTML_ATTR_FONT},
+ {"font-size", "28", ABC_HTML_ATTR_FONT_SIZE},
};
static html_attr_t h4_attrs[] =
{
- {"font", "Liberation Serif", ABC_HTML_ATTR_FONT},
- {"font-size", "20", ABC_HTML_ATTR_FONT_SIZE},
+ {"font", "SimHei", ABC_HTML_ATTR_FONT},
+ {"font-size", "24", ABC_HTML_ATTR_FONT_SIZE},
};
static html_attr_t h5_attrs[] =
{
- {"font", "Liberation Serif", ABC_HTML_ATTR_FONT},
- {"font-size", "16", ABC_HTML_ATTR_FONT_SIZE},
+ {"font", "SimHei", ABC_HTML_ATTR_FONT},
+ {"font-size", "20", ABC_HTML_ATTR_FONT_SIZE},
};
static html_attr_t h6_attrs[] =
{
- {"font", "Liberation Serif", ABC_HTML_ATTR_FONT},
- {"font-size", "12", ABC_HTML_ATTR_FONT_SIZE},
+ {"font", "SimHei", ABC_HTML_ATTR_FONT},
+ {"font-size", "16", ABC_HTML_ATTR_FONT_SIZE},
+};
+
+static html_attr_t p_attrs[] =
+{
+ {"font", "SimSong", ABC_HTML_ATTR_FONT},
+ {"font-size", "16", ABC_HTML_ATTR_FONT_SIZE},
};
static html_attr_t a_attrs[] =
{
- {"href", "", ABC_HTML_ATTR_HREF},
- {"font", "serif", ABC_HTML_ATTR_FONT},
- {"font-size", "28", ABC_HTML_ATTR_FONT_SIZE},
- {"font-color", "blue", ABC_HTML_ATTR_FONT_COLOR},
+ {"href", "", ABC_HTML_ATTR_HREF},
+ {"font", "SimHei", ABC_HTML_ATTR_FONT},
+ {"font-size", "24", ABC_HTML_ATTR_FONT_SIZE},
+ {"font-color", "blue", ABC_HTML_ATTR_FONT_COLOR},
};
static html_attr_t img_attrs[] =
{
- {"src", "", ABC_HTML_ATTR_SRC},
- {"width", "100", ABC_HTML_ATTR_WIDTH},
- {"height", "100", ABC_HTML_ATTR_HEIGHT},
+ {"src", "", ABC_HTML_ATTR_SRC},
+ {"width", "100", ABC_HTML_ATTR_WIDTH},
+ {"height", "100", ABC_HTML_ATTR_HEIGHT},
};
static html_label_t html_labels[] =
{
- {"html", ABC_HTML, 0, NULL},
- {"title", ABC_HTML_TITLE, 0, NULL},
- {"head", ABC_HTML_HEAD, 0, NULL},
- {"body", ABC_HTML_BODY, 0, NULL},
-
- {"div", ABC_HTML_DIV, 0, NULL},
-
- {"h1", ABC_HTML_H1, sizeof(h1_attrs) / sizeof(h1_attrs[0]), h1_attrs},
- {"h2", ABC_HTML_H2, sizeof(h2_attrs) / sizeof(h2_attrs[0]), h2_attrs},
- {"h3", ABC_HTML_H3, sizeof(h3_attrs) / sizeof(h3_attrs[0]), h3_attrs},
- {"h4", ABC_HTML_H4, sizeof(h4_attrs) / sizeof(h4_attrs[0]), h4_attrs},
- {"h5", ABC_HTML_H5, sizeof(h5_attrs) / sizeof(h5_attrs[0]), h5_attrs},
- {"h6", ABC_HTML_H6, sizeof(h6_attrs) / sizeof(h6_attrs[0]), h6_attrs},
-
- {"a", ABC_HTML_A, sizeof(a_attrs) / sizeof(a_attrs[0]), a_attrs},
- {"img", ABC_HTML_IMG, sizeof(img_attrs) / sizeof(img_attrs[0]), img_attrs},
+ {"html", ABC_HTML, 0, NULL, ABC_HTML_FLAG_CLOSE},
+ {"title", ABC_HTML_TITLE, 0, NULL, ABC_HTML_FLAG_CLOSE},
+ {"head", ABC_HTML_HEAD, 0, NULL, ABC_HTML_FLAG_CLOSE},
+ {"body", ABC_HTML_BODY, 0, NULL, ABC_HTML_FLAG_CLOSE},
+
+ {"div", ABC_HTML_DIV, 0, NULL, ABC_HTML_FLAG_CLOSE},
+
+ {"h1", ABC_HTML_H1, abc_number_of(h1_attrs), h1_attrs, ABC_HTML_FLAG_CLOSE},
+ {"h2", ABC_HTML_H2, abc_number_of(h2_attrs), h2_attrs, ABC_HTML_FLAG_CLOSE},
+ {"h3", ABC_HTML_H3, abc_number_of(h3_attrs), h3_attrs, ABC_HTML_FLAG_CLOSE},
+ {"h4", ABC_HTML_H4, abc_number_of(h4_attrs), h4_attrs, ABC_HTML_FLAG_CLOSE},
+ {"h5", ABC_HTML_H5, abc_number_of(h5_attrs), h5_attrs, ABC_HTML_FLAG_CLOSE},
+ {"h6", ABC_HTML_H6, abc_number_of(h6_attrs), h6_attrs, ABC_HTML_FLAG_CLOSE},
+
+ {"p", ABC_HTML_P, abc_number_of(p_attrs), p_attrs, ABC_HTML_FLAG_CLOSE},
+ {"br", ABC_HTML_BR, 0, NULL, ABC_HTML_FLAG_OPEN},
+
+ {"a", ABC_HTML_A, abc_number_of(a_attrs), a_attrs, ABC_HTML_FLAG_CLOSE},
+ {"img", ABC_HTML_IMG, abc_number_of(img_attrs), img_attrs, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SINGLE},
};
static int __html_parse_obj(abc_html_t* html, abc_char_t* c);
return NULL;
}
+static int __html_add_attr(abc_obj_t* obj, int type, const char* name, const char* value)
+{
+ abc_obj_t* attr = abc_obj_alloc(NULL, 0, 0, type);
+ if (!attr)
+ return -ENOMEM;
+
+ attr->key = scf_string_cstr(name);
+ if (!attr->key) {
+ abc_obj_free(attr);
+ return -ENOMEM;
+ }
+
+ attr->value = scf_string_cstr(value);
+ if (!attr->value) {
+ abc_obj_free(attr);
+ return -ENOMEM;
+ }
+
+ scf_list_add_tail(&obj->attrs, &attr->list);
+ return 0;
+}
+
static int __html_load_attrs(abc_obj_t* obj, html_attr_t* attrs, int n_attrs)
{
- abc_obj_t* attr;
+ scf_list_t* l;
+ abc_obj_t* attr;
+ int ret;
int i;
- for (i = 0; i < n_attrs; i++) {
- attr = abc_obj_alloc(NULL, 0, 0, attrs[i].type);
- if (!attr)
- return -ENOMEM;
+ if (attrs && n_attrs > 0) {
- attr->key = scf_string_cstr(attrs[i].name);
- if (!attr->key) {
- abc_obj_free(attr);
- return -ENOMEM;
+ for (i = 0; i < n_attrs; i++) {
+ ret = __html_add_attr(obj, attrs[i].type, attrs[i].name, attrs[i].value);
+ if (ret < 0)
+ return ret;
}
- attr->value = scf_string_cstr(attrs[i].value);
- if (!attr->value) {
- abc_obj_free(attr);
- return -ENOMEM;
- }
+ } else if (obj->parent) {
+
+ for (l = scf_list_head(&obj->parent->attrs); l != scf_list_sentinel(&obj->parent->attrs); l = scf_list_next(l)) {
+ attr = scf_list_data(l, abc_obj_t, list);
- scf_list_add_tail(&obj->attrs, &attr->list);
+ ret = __html_add_attr(obj, attr->type, attr->key->data, attr->value->data);
+ if (ret < 0)
+ return ret;
+ }
}
return 0;
}
}
-static int __html_parse_text(abc_html_t* html, abc_obj_t* obj)
+static int __html_parse_end(abc_html_t* html, abc_obj_t* obj)
{
- scf_string_t* text = scf_string_alloc();
- if (!text)
+ scf_string_t* end = scf_string_alloc();
+ if (!end)
return -ENOMEM;
- abc_char_t* c;
- abc_char_t* c2;
+ abc_char_t* c = NULL;
while (1) {
c = __html_pop_char(html);
if (!c) {
scf_loge("\n");
- scf_string_free(text);
+ scf_string_free(end);
return -1;
}
html->pos += c->len;
- if ('<' == c->c)
+ if ('>' == c->c)
break;
- if ('\n' == c->c) {
- html->n_lines++;
- html->pos = 0;
- free(c);
- continue;
- }
-
- scf_string_cat_cstr_len(text, c->utf8, c->len);
+ scf_string_cat_cstr_len(end, c->utf8, c->len);
free(c);
c = NULL;
}
- c2 = __html_pop_char(html);
- if (!c2) {
- scf_loge("\n");
- free(c);
- scf_string_free(text);
- return -1;
+ free(c);
+ c = NULL;
+
+ int ret = 0;
+ if (scf_string_cmp(obj->key, end)) {
+ ret = -1;
+
+ scf_loge("end label '%s' file: %s, line: %d, NOT for label '%s' line: %d\n",
+ end->data, html->file->data, html->n_lines, obj->key->data, obj->line);
}
- if ('a' <= c2->c && c2->c <= 'z') {
- free(c);
- c = NULL;
- scf_string_free(text);
+ scf_string_free(end);
+ return ret;
+}
+
+static int __html_parse_text(abc_html_t* html, abc_obj_t* obj)
+{
+ scf_string_t* text = scf_string_alloc();
+ if (!text)
+ return -ENOMEM;
+
+ abc_char_t* c = NULL;
- int ret = __html_parse_obj(html, c2);
- if (ret < 0) {
+ while (1) {
+ c = __html_pop_char(html);
+ if (!c) {
scf_loge("\n");
- return ret;
+ scf_string_free(text);
+ return -1;
}
- return __html_parse_text(html, obj);
+ if ('<' == c->c)
+ break;
+
+ if ('\n' == c->c) {
+ html->n_lines++;
+ html->pos = 0;
+ } else {
+ html->pos += c->len;
+ scf_string_cat_cstr_len(text, c->utf8, c->len);
+ }
- } else if ('/' != c2->c) {
free(c);
c = NULL;
- scf_string_free(text);
-
- scf_loge("invalid char '%c:%#x' in HTML attribute, file: %s, line: %d\n",
- c2->c, c2->c, html->file->data, html->n_lines);
-
- free(c2);
- return -1;
}
- html->pos++;
-
- free(c2);
- free(c);
- c2 = NULL;
- c = NULL;
-
if (text->len > 0)
obj->text = text;
else
scf_string_free(text);
text = NULL;
- // check the end label </...>
- scf_string_t* end = scf_string_alloc();
- if (!end)
- return -ENOMEM;
-
- while (1) {
- c = __html_pop_char(html);
- if (!c) {
- scf_loge("\n");
- scf_string_free(end);
- return -1;
- }
-
- html->pos += c->len;
-
- if ('>' == c->c)
- break;
- scf_string_cat_cstr_len(end, c->utf8, c->len);
- free(c);
+ if (ABC_HTML_BR == obj->type) { // single label
+ __html_push_char(html, c);
c = NULL;
+ return 0;
}
html->pos++;
-
free(c);
c = NULL;
- int ret = 0;
- if (scf_string_cmp(obj->key, end)) {
- ret = -1;
- scf_loge("end label '%s' file: %s, line: %d, NOT for label '%s' line: %d\n",
- end->data, html->file->data, html->n_lines, obj->key->data, obj->line);
+ c = __html_pop_char(html);
+ if (!c) {
+ scf_loge("\n");
+ free(c);
+ return -1;
}
- scf_string_free(end);
- end = NULL;
+ if ('/' != c->c) {
+ abc_obj_t* mov = NULL;
+
+ if (ABC_HTML_H1 == obj->type
+ || ABC_HTML_H2 == obj->type
+ || ABC_HTML_H3 == obj->type
+ || ABC_HTML_H4 == obj->type
+ || ABC_HTML_H5 == obj->type
+ || ABC_HTML_H6 == obj->type
+ || ABC_HTML_P == obj->type) {
+
+ if (obj->text) {
+#define HTML_MOV_TEXT() \
+ do { \
+ mov = abc_obj_alloc(NULL, obj->line, obj->pos, obj->type); \
+ if (!mov) \
+ return -ENOMEM; \
+ mov->text = obj->text; \
+ obj->text = NULL; \
+ mov->parent = obj; \
+ scf_list_add_tail(&obj->childs, &mov->list); \
+ scf_logd("--- %s, %s\n", obj->key->data, mov->text->data); \
+ } while (0)
+
+ HTML_MOV_TEXT();
+ }
+ }
- return ret;
+ int ret = __html_parse_obj(html, c);
+ if (ret < 0)
+ return ret;
+
+ ret = __html_parse_text(html, obj);
+ if (ret < 0)
+ return ret;
+
+ if (mov && obj->text)
+ HTML_MOV_TEXT();
+
+ return ret;
+ }
+
+ html->pos++;
+ free(c);
+ c = NULL;
+
+ return __html_parse_end(html, obj);
}
static int __html_parse_value(abc_html_t* html, abc_obj_t* attr)
if (!value)
return -ENOMEM;
- abc_char_t* c = NULL;
+ abc_char_t* c = NULL;
+ abc_char_t* c2 = NULL;
int flag = 0;
html->pos += c->len;
- if ((!flag && ' ' == c->c) || '>' == c->c)
- break;
+ if (!flag) {
+ if (' ' == c->c || '>' == c->c)
+ break;
+
+ if ('/' == c->c) {
+ c2 = __html_pop_char(html);
+
+ __html_push_char(html, c2);
+ if ('>' == c2->c)
+ break;
+ }
+
+ if ('\"' == c->c || '\'' == c->c)
+ flag = c->c;
+ else
+ scf_string_cat_cstr_len(value, c->utf8, c->len);
- if ('\"' == c->c)
- flag = !flag;
+ } else if (flag == c->c)
+ flag = 0;
else
scf_string_cat_cstr_len(value, c->utf8, c->len);
html->pos += c->len;
- if (' ' == c->c || '>' == c->c)
+ if (' ' == c->c || '>' == c->c || '/' == c->c)
break;
if ('\n' == c->c) {
return -ENOMEM;
}
- obj->key = key;
+ obj->flags = label->flags;
+ obj->key = key;
key = NULL;
+ obj->parent = html->current;
+
int ret = __html_load_attrs(obj, label->attrs, label->n_attrs);
if (ret < 0) {
abc_obj_free(obj);
return ret;
}
- ret = 0;
- if (' ' == tmp) {
- ret = __html_parse_attr(html, obj, label->attrs, label->n_attrs);
- if (ret < 0) {
- abc_obj_free(obj);
- return ret;
- }
- }
-
scf_logi("key: %s\n", obj->key->data);
+ switch (tmp) {
+ case ' ':
+ ret = __html_parse_attr(html, obj, label->attrs, label->n_attrs);
+ if (ret < 0) {
+ abc_obj_free(obj);
+ return ret;
+ }
+ break;
+ case '/':
+ ret = tmp;
+ break;
+ default:
+ ret = 0;
+ break;
+ };
+
if (!html->root) {
html->root = obj;
html->current = obj;
scf_list_add_tail(&html->current->childs, &obj->list);
- obj->parent = html->current;
html->current = obj;
}
c = NULL;
if ('>' != tmp) {
- scf_loge("HTML label '%s' not closed, in file: %s, line: %d\n",
- obj->key->data, html->file->data, html->n_lines);
+ scf_loge("HTML label '%s' (%d) not closed, in file: %s, line: %d\n",
+ obj->key->data, tmp, html->file->data, html->n_lines);
return -1;
}
} else
#include"abc.h"
-int abc_layout_html (abc_layout_t* layout, abc_obj_t* root, int width, int height);
-int abc_layout_title(abc_layout_t* layout, abc_obj_t* root, int width, int height);
-int abc_layout_head (abc_layout_t* layout, abc_obj_t* root, int width, int height);
-int abc_layout_body (abc_layout_t* layout, abc_obj_t* root, int width, int height);
+int abc_layout_html (abc_layout_t* layout, abc_obj_t* obj, int width, int height);
+int abc_layout_title(abc_layout_t* layout, abc_obj_t* obj, int width, int height);
+int abc_layout_head (abc_layout_t* layout, abc_obj_t* obj, int width, int height);
+int abc_layout_body (abc_layout_t* layout, abc_obj_t* obj, int width, int height);
-int abc_layout_div (abc_layout_t* layout, abc_obj_t* root, int width, int height);
-int abc_layout_h1 (abc_layout_t* layout, abc_obj_t* root, int width, int height);
-int abc_layout_a (abc_layout_t* layout, abc_obj_t* root, int width, int height);
-int abc_layout_img (abc_layout_t* layout, abc_obj_t* root, int width, int height);
+int abc_layout_div (abc_layout_t* layout, abc_obj_t* obj, int width, int height);
+int abc_layout_h1 (abc_layout_t* layout, abc_obj_t* obj, int width, int height);
+int abc_layout_a (abc_layout_t* layout, abc_obj_t* obj, int width, int height);
+int abc_layout_img (abc_layout_t* layout, abc_obj_t* obj, int width, int height);
static abc_layout_pt abc_layouts[ABC_HTML_NB] =
{
// 4
abc_layout_div,
+ // 5
abc_layout_h1,
abc_layout_h1,
abc_layout_h1,
abc_layout_h1,
// 11
+ abc_layout_h1, // <p>
+ abc_layout_h1, // <br>
abc_layout_a,
NULL,
int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height)
{
- scf_list_t* l;
- abc_obj_t* child;
+ scf_string_t* key;
+ scf_list_t* l;
+ abc_obj_t* child;
if (!root)
return -EINVAL;
int x = 4;
int y = 4;
- int w = 0;
int h = 0;
+ int __w = 0;
+ int __h = 0;
+
for (l = scf_list_head(&root->childs); l != scf_list_sentinel(&root->childs); l = scf_list_next(l)) {
child = scf_list_data(l, abc_obj_t, list);
if (ret < 0)
return ret;
- child->x = x;
- child->y = y;
+ switch (child->type) {
+
+ case ABC_HTML_H1:
+ case ABC_HTML_H2:
+ case ABC_HTML_H3:
+ case ABC_HTML_H4:
+ case ABC_HTML_H5:
+ case ABC_HTML_H6:
+ case ABC_HTML_BR:
+ child->x = 4;
+ child->y = y + h;
+
+ x = 4;
+ y = child->y + child->h;
+ h = 0;
+ break;
+
+ default:
+ if (child->w + x < width) {
+ child->x = x;
+ child->y = y;
- scf_logd("key: %s, x: %d, y: %d, w: %d, h: %d\n\n", child->key->data, child->x, child->y, child->w, child->h);
+ if (h < child->h)
+ h = child->h;
- y = child->y + child->h;
+ x += child->w;
+ } else {
+ y += h;
- if (w < child->x + child->w)
- w = child->x + child->w;
+ child->x = 4;
+ child->y = y;
- if (h < child->y + child->h)
- h = child->y + child->h;
+ h = child->h;
+ x = child->x + child->w;
+ }
+ break;
+ };
+
+ if (child->key)
+ scf_logi("key: %s, x: %d, y: %d, w: %d, h: %d\n\n", child->key->data, child->x, child->y, child->w, child->h);
+
+ if (__w < child->x + child->w)
+ __w = child->x + child->w;
+
+ if (__h < child->y + child->h)
+ __h = child->y + child->h;
}
int ret = abc_layout_obj(NULL, root, width, height);
if (ret < 0)
return ret;
- if (root->w < w)
- root->w = w;
+ if (root->w < __w)
+ root->w = __w;
+
+ if (root->h < __h)
+ root->h = __h;
- if (root->h < h)
- root->h = h;
+ if (root->key)
+ scf_logi("key: %s, x: %d, y: %d, w: %d, h: %d\n", root->key->data, root->x, root->y, root->w, root->h);
- scf_logd("key: %s, x: %d, y: %d, w: %d, h: %d\n", root->key->data, root->x, root->y, root->w, root->h);
return 0;
}