<h1 class="red">这个段落采用CSS样式化。</h1>
<p id="a">Hello World!</p>
<p class="red">这个段落<b>采用</b>CSS样式化。</p>
+<p style="color:green">这个段落采用CSS样式化。</p>
</body>
</html>
+body
+{
+ background-color:#b0c4de;
+ background-image:url('img.png');
+}
+h1 {background-color:#6495ed;}
+
#a /*css comment*/
{
color:blue;
css->text_pos = 0;
}
- if (';' == c->c)
+ if (';' == c->c || EOF == c->c)
break;
else
scf_string_cat_cstr_len(value, c->utf8, c->len);
css->text_pos += c->len;
- if ('}' == c->c) {
+ if ('}' == c->c || EOF == c->c) {
free(c);
scf_string_free(key);
return '}';
if (ret < 0)
return ret;
- if ('}' == ret)
+ if ('}' == ret || EOF == ret)
break;
}
if (!href)
return 0;
- n = __io_url_path(&io, &spath, css->file->data, href->value->data);
+ n = __io_url_path(&io, &spath, css->file->data, href->value->data, href->value->len);
if (n < 0)
return n;
while (1) {
c = __io_pop_char(&css->io);
- if (!c)
- return -1;
+ if (!c) {
+ ret = -1;
+ break;
+ }
if (EOF == c->c) {
free(c);
- return 0;
+ ret = 0;
+ break;
}
if ('\n' == c->c) {
ret = __css_parse_obj(css, c);
if (ret < 0) {
scf_loge("css->text_line: %d, css->text_pos: %d\n", css->text_line, css->text_pos);
- return ret;
+ break;
}
} else {
scf_loge("'%c'(%#x), css->text_line: %d, css->text_pos: %d\n", c->c, c->c, css->text_line, css->text_pos);
free(c);
- return -1;
+ ret = -1;
+ break;
}
}
- return -1;
+ io->close(&css->io);
+ return ret;
+}
+
+static void __css_set_attr(abc_obj_t* obj, abc_obj_t* attr)
+{
+ switch (attr->type)
+ {
+ case ABC_HTML_ATTR_BG_COLOR:
+ abc_obj_set_attr(obj, attr->type, attr->value->data);
+ break;
+ default:
+ abc_recursive_set_attr(obj, attr->type, attr->value->data);
+ break;
+ };
}
int abc_css_use(abc_html_t* html, abc_obj_t* obj)
scf_list_t* l3;
abc_obj_t* head;
abc_obj_t* css;
- abc_obj_t* label;
+ abc_obj_t* style;
abc_obj_t* attr;
+ // for css in HTML <head>
head = abc_obj_find_type(html->root, ABC_HTML_HEAD);
- if (!head)
- return 0;
+ if (head) {
+ for (l = scf_list_head(&head->childs); l != scf_list_sentinel(&head->childs); l = scf_list_next(l)) {
+ css = scf_list_data(l, abc_obj_t, list);
- for (l = scf_list_head(&head->childs); l != scf_list_sentinel(&head->childs); l = scf_list_next(l)) {
- css = scf_list_data(l, abc_obj_t, list);
+ if (ABC_HTML_LINK == css->type)
+ {
+ attr = abc_obj_get_attr(css, ABC_HTML_ATTR_TYPE);
+ if (!attr)
+ continue;
- if (ABC_HTML_LINK == css->type)
- {
- attr = abc_obj_get_attr(css, ABC_HTML_ATTR_TYPE);
- if (!attr)
- continue;
+ if (strcmp(attr->value->data, "text/css"))
+ continue;
- if (strcmp(attr->value->data, "text/css"))
+ } else if (ABC_HTML_STYLE != css->type)
continue;
- } else if (ABC_HTML_STYLE != css->type)
- continue;
+ for (l2 = scf_list_head(&css->childs); l2 != scf_list_sentinel(&css->childs); l2 = scf_list_next(l2)) {
+ style = scf_list_data(l2, abc_obj_t, list);
- for (l2 = scf_list_head(&css->childs); l2 != scf_list_sentinel(&css->childs); l2 = scf_list_next(l2)) {
- label = scf_list_data(l2, abc_obj_t, list);
+ if (ABC_CSS_ID == style->type || ABC_CSS_CLASS == style->type)
+ {
+ attr = abc_obj_get_attr(obj, style->type);
+ if (!attr)
+ continue;
- if (ABC_CSS_ID == label->type || ABC_CSS_CLASS == label->type)
- {
- attr = abc_obj_get_attr(obj, label->type);
- if (!attr)
- continue;
+ if (strcmp(attr->value->data, style->text->data + style->css_dot + 1))
+ continue;
- if (strcmp(attr->value->data, label->text->data + label->css_dot + 1))
+ if (style->css_dot > 0) {
+ if (strncmp(obj->keys[0], style->text->data, style->css_dot))
+ continue;
+ }
+
+ } else if (style->type != obj->type)
continue;
- if (label->css_dot > 0) {
- if (strncmp(obj->keys[0], label->text->data, label->css_dot))
- continue;
+ for (l3 = scf_list_head(&style->attrs); l3 != scf_list_sentinel(&style->attrs); l3 = scf_list_next(l3)) {
+ attr = scf_list_data(l3, abc_obj_t, list);
+
+ __css_set_attr(obj, attr);
}
+ }
+ }
+ }
- } else if (label->type != obj->type)
- continue;
+ // for inline css below
+ css = abc_obj_get_attr(obj, ABC_HTML_ATTR_STYLE);
- for (l3 = scf_list_head(&label->attrs); l3 != scf_list_sentinel(&label->attrs); l3 = scf_list_next(l3)) {
- attr = scf_list_data(l3, abc_obj_t, list);
+ if (css && css->value && css->value->len > 0)
+ {
+ html_label_t* label = __html_find_label2(obj->type);
+ abc_io_t* io = abc_io_array[ABC_PROTO_STR];
- abc_recursive_set_attr(obj, attr->type, attr->value->data);
- }
+ css->io.proto = io->proto;
+ css->io.priv = NULL;
+ css->io.open = io->open;
+ css->io.close = io->close;
+ css->io.popc = io->popc;
+ css->io.post = io->post;
+
+ css->text_line = 1;
+ css->text_pos = 0;
+
+ int ret = io->open(&css->io, css->value->data);
+ if (ret < 0)
+ return ret;
+
+ ret = __css_parse_attr(css, css, label->attrs, label->n_attrs);
+ io->close(&css->io);
+ if (ret < 0 && EOF != ret)
+ return ret;
+
+ for (l = scf_list_head(&css->attrs); l != scf_list_sentinel(&css->attrs); ) {
+ attr = scf_list_data(l, abc_obj_t, list);
+ l = scf_list_next(l);
+
+ __css_set_attr(obj, attr);
+
+ scf_list_del(&attr->list);
+ abc_obj_free(attr);
+ attr = 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* class_keys[] = {"class", "类名", NULL};
static char* type_keys[] = {"type", "类型", NULL};
static char* name_keys[] = {"name", "名字", NULL};
static html_attr_t body_attrs[] =
{
- {font_keys, "SimSong", ABC_HTML_ATTR_FONT, 0},
- {font_size_keys, "16", ABC_HTML_ATTR_FONT_SIZE, 0},
+ {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},
};
static html_attr_t h1_attrs[] =
{
{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},
- {font_keys, "SimHei", ABC_HTML_ATTR_FONT, 0},
- {font_size_keys, "40", ABC_HTML_ATTR_FONT_SIZE, 0},
+ {font_keys, "SimHei", ABC_HTML_ATTR_FONT, 0},
+ {font_size_keys, "40", ABC_HTML_ATTR_FONT_SIZE, 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},
+
+ {bg_color_keys, "", ABC_HTML_ATTR_BG_COLOR, ABC_HTML_FLAG_SHOW},
};
static html_attr_t h2_attrs[] =
{
{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},
- {font_keys, "SimHei", ABC_HTML_ATTR_FONT, 0},
- {font_size_keys, "32", ABC_HTML_ATTR_FONT_SIZE, 0},
+ {font_keys, "SimHei", ABC_HTML_ATTR_FONT, 0},
+ {font_size_keys, "32", ABC_HTML_ATTR_FONT_SIZE, 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},
+
+ {bg_color_keys, "", ABC_HTML_ATTR_BG_COLOR, ABC_HTML_FLAG_SHOW},
};
static html_attr_t h3_attrs[] =
{
{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},
- {font_keys, "SimHei", ABC_HTML_ATTR_FONT, 0},
- {font_size_keys, "28", ABC_HTML_ATTR_FONT_SIZE, 0},
+ {font_keys, "SimHei", ABC_HTML_ATTR_FONT, 0},
+ {font_size_keys, "28", ABC_HTML_ATTR_FONT_SIZE, 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},
+
+ {bg_color_keys, "", ABC_HTML_ATTR_BG_COLOR, ABC_HTML_FLAG_SHOW},
};
static html_attr_t h4_attrs[] =
{
{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},
- {font_keys, "SimHei", ABC_HTML_ATTR_FONT, 0},
- {font_size_keys, "24", ABC_HTML_ATTR_FONT_SIZE, 0},
+ {font_keys, "SimHei", ABC_HTML_ATTR_FONT, 0},
+ {font_size_keys, "24", ABC_HTML_ATTR_FONT_SIZE, 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},
+
+ {bg_color_keys, "", ABC_HTML_ATTR_BG_COLOR, ABC_HTML_FLAG_SHOW},
};
static html_attr_t h5_attrs[] =
{
{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},
- {font_keys, "SimHei", ABC_HTML_ATTR_FONT, 0},
- {font_size_keys, "20", ABC_HTML_ATTR_FONT_SIZE, 0},
+ {font_keys, "SimHei", ABC_HTML_ATTR_FONT, 0},
+ {font_size_keys, "20", ABC_HTML_ATTR_FONT_SIZE, 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},
+
+ {bg_color_keys, "", ABC_HTML_ATTR_BG_COLOR, ABC_HTML_FLAG_SHOW},
};
static html_attr_t h6_attrs[] =
{
{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},
- {font_keys, "SimHei", ABC_HTML_ATTR_FONT, 0},
- {font_size_keys, "16", ABC_HTML_ATTR_FONT_SIZE, 0},
+ {font_keys, "SimHei", ABC_HTML_ATTR_FONT, 0},
+ {font_size_keys, "16", ABC_HTML_ATTR_FONT_SIZE, 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},
+
+ {bg_color_keys, "", ABC_HTML_ATTR_BG_COLOR, ABC_HTML_FLAG_SHOW},
};
static html_attr_t p_attrs[] =
{
{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},
{font_keys, "SimSong", ABC_HTML_ATTR_FONT, 0},
{font_size_keys, "16", ABC_HTML_ATTR_FONT_SIZE, 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},
+
+ {bg_color_keys, "", ABC_HTML_ATTR_BG_COLOR, ABC_HTML_FLAG_SHOW},
};
static html_attr_t css_id_attrs[] =
{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},
+
+ {bg_color_keys, "", ABC_HTML_ATTR_BG_COLOR, ABC_HTML_FLAG_SHOW},
};
static html_attr_t i_attrs[] =
{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},
+
+ {bg_color_keys, "", ABC_HTML_ATTR_BG_COLOR, ABC_HTML_FLAG_SHOW},
};
static html_attr_t a_attrs[] =
abc_char_t* __io_pop_char (abc_io_t* io);
void __io_push_char(abc_io_t* io, abc_char_t* c);
-int __io_url_path (abc_io_t** io, scf_string_t** spath, const char* main, const char* current);
+int __io_url_path (abc_io_t** io, scf_string_t** spath, const char* main, const char* current, size_t current_len);
+int __io_url_css (abc_io_t** io, scf_string_t** spath, const char* main, const char* current);
#endif
io->tmp_list = c;
}
-int __io_url_path(abc_io_t** io, scf_string_t** spath, const char* main, const char* current)
+int __io_url_path(abc_io_t** io, scf_string_t** spath, const char* main, const char* current, size_t current_len)
{
scf_string_t* path = scf_string_alloc();
if (!path)
prefix = 7;
proto = ABC_PROTO_FILE;
- ret = scf_string_copy_cstr(path, current);
+ ret = scf_string_copy_cstr_len(path, current, current_len);
} else if (!strncmp(current, "http://", 7)) {
prefix = 7;
proto = ABC_PROTO_HTTP;
- ret = scf_string_copy_cstr(path, current);
+ ret = scf_string_copy_cstr_len(path, current, current_len);
} else {
if (prefix < 0) {
prefix = 0;
}
}
- ret = scf_string_cat_cstr(path, current);
+ ret = scf_string_cat_cstr_len(path, current, current_len);
}
if (ret < 0) {
*spath = path;
return prefix;
}
+
+int __io_url_css(abc_io_t** io, scf_string_t** spath, const char* main, const char* current)
+{
+ if (strncmp(current, "url('", 5))
+ return -EINVAL;
+
+ const char* p0 = current + 5;
+ const char* p = p0;
+
+ while (*p && '\'' != *p)
+ p++;
+
+ return __io_url_path(io, spath, main, p0, (size_t)(p - p0));
+}
while (obj) {
attr = abc_obj_get_attr(obj, key);
- if (attr)
+
+ if (attr && attr->value && attr->value->len > 0)
return attr;
obj = obj->parent;
} else if (obj->keys)
printf("<%s", obj->keys[0]);
-
for (l = scf_list_head(&obj->attrs); l != scf_list_sentinel(&obj->attrs); l = scf_list_next(l)) {
attr = scf_list_data(l, abc_obj_t, list);
ABC_HTML_ATTR_NAME,
ABC_HTML_ATTR_VALUE,
ABC_HTML_ATTR_CLASS,
+ ABC_HTML_ATTR_STYLE,
ABC_HTML_ATTR_HREF,
ABC_HTML_ATTR_SRC,
ABC_HTML_ATTR_TEXT_ALIGN,
+ ABC_HTML_ATTR_BG_COLOR,
+ ABC_HTML_ATTR_BG_IMAGE,
+
ABC_HTML_ATTR_WIDTH,
ABC_HTML_ATTR_HEIGHT,
CFILES += abc_render_body.c
CFILES += abc_render_div.c
+CFILES += abc_render_bg_color.c
+CFILES += abc_render_bg_image.c
+
CFILES += abc_render_empty.c
CFILES += abc_render_h1.c
[ABC_HTML] = abc_layout_html,
[ABC_HTML_TITLE] = abc_layout_title,
[ABC_HTML_HEAD] = abc_layout_head,
- [ABC_HTML_BODY] = abc_layout_h1,
+ [ABC_HTML_BODY] = abc_layout_body,
[ABC_HTML_DIV] = abc_layout_div,
[ABC_HTML_META] = abc_layout_empty,
switch (root->type)
{
+ case ABC_HTML_SCRIPT:
+ case ABC_HTML_STYLE:
+ case ABC_HTML_LINK:
+ return 0;
+ break;
+
case ABC_HTML_BODY:
root->w = width;
root->h = height;
{
[ABC_HTML] = &abc_render_empty,
[ABC_HTML_HEAD] = &abc_render_empty,
- [ABC_HTML_BODY] = &abc_render_h1,
+ [ABC_HTML_BODY] = &abc_render_body,
[ABC_HTML_META] = &abc_render_empty,
[ABC_HTML_TITLE] = &abc_render_title,
[ABC_HTML_DIV] = &abc_render_div,
static int __render_root(abc_ctx_t* ctx, abc_obj_t* root, int width, int height)
{
+ switch (root->type)
+ {
+ case ABC_HTML_SCRIPT:
+ case ABC_HTML_STYLE:
+ case ABC_HTML_LINK:
+ return 0;
+ break;
+ default:
+ break;
+ };
+
scf_list_t* l;
abc_obj_t* child;
--- /dev/null
+#include"abc.h"
+
+static const char* vert_shader =
+ "#version 330 core\n"
+ "layout(location = 0) in vec4 position; \n"
+ "layout(location = 1) in vec2 a_texCoord; \n"
+ "out vec2 v_texCoord; \n"
+ "uniform mat4 mvp; \n"
+ "void main() { \n"
+ "gl_Position = mvp * position; \n"
+ "v_texCoord = a_texCoord; \n"
+ "} \n";
+
+static const char* frag_shader =
+ "#version 330 core\n"
+ "in vec2 v_texCoord; \n"
+ "out vec4 outputColor; \n"
+ "uniform vec4 bgColor; \n"
+ "void main() { \n"
+ " vec2 xy = v_texCoord; \n"
+ " outputColor = bgColor; \n"
+ "} \n";
+
+
+static GLuint program = 0;
+
+static GLuint vao = 0;
+static GLuint buffers[2] = {0};
+
+static GLuint uniform_mvp;
+static GLuint uniform_bgColor;
+
+
+static int _render_fini_bg_color(abc_render_t* render)
+{
+ return 0;
+}
+
+static int _render_draw_bg_color(abc_render_t* render, abc_obj_t* obj, int width, int height)
+{
+ if (0 == program)
+ __init_program(&program, vert_shader, frag_shader);
+
+ if (0 == vao)
+ __init_buffers(&vao, buffers);
+
+ double r = 0.0;
+ double g = 0.0;
+ double b = 0.0;
+
+ abc_obj_t* attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_BG_COLOR);
+ if (attr)
+ abc_css_color(&r, &g, &b, attr->value->data);
+
+ float mvp[16];
+ __compute_mvp(mvp, 0, 0, 0);
+
+ scf_logd("%s, x: %d, y: %d, w: %d, h: %d\n", obj->text->data, obj->x, obj->y, obj->w, obj->h);
+
+ GLfloat vert_update[] =
+ {
+ 2.0 * obj->x / (float)width - 1.0,
+ -2.0 * (obj->y + obj->h) / (float)height + 1.0,
+
+ 2.0 * (obj->x + obj->w) / (float)width - 1.0,
+ -2.0 * (obj->y + obj->h) / (float)height + 1.0,
+
+ 2.0 * obj->x / (float)width - 1.0,
+ -2.0 * obj->y / (float)height + 1.0,
+
+ 2.0 * (obj->x + obj->w) / (float)width - 1.0,
+ -2.0 * obj->y / (float)height + 1.0,
+ };
+
+ glUseProgram(program);
+ uniform_bgColor = glGetUniformLocation(program, "bgColor");
+ uniform_mvp = glGetUniformLocation(program, "mvp");
+
+ glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, mvp);
+ glUniform4f (uniform_bgColor, r, g, b, 1.0);
+
+ // draw
+ glBindBuffer (GL_ARRAY_BUFFER, buffers[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vert_update), vert_update);
+
+ glBindVertexArray(vao);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ glBindVertexArray(0);
+ glUseProgram(0);
+ return 0;
+}
+
+abc_render_t abc_render_bg_color =
+{
+ .type = ABC_HTML_ATTR_BG_COLOR,
+
+ .draw = _render_draw_bg_color,
+ .fini = _render_fini_bg_color,
+};
--- /dev/null
+#include"abc.h"
+
+static const char* vert_shader =
+ "#version 330 core\n"
+ "layout(location = 0) in vec4 position; \n"
+ "layout(location = 1) in vec2 a_texCoord; \n"
+ "out vec2 v_texCoord; \n"
+ "uniform mat4 mvp; \n"
+ "void main() { \n"
+ "gl_Position = mvp * position; \n"
+ "v_texCoord = a_texCoord; \n"
+ "} \n";
+
+static const char* frag_shader =
+ "#version 330 core\n"
+ "in vec2 v_texCoord; \n"
+ "out vec4 outputColor; \n"
+ "uniform vec4 bgColor; \n"
+ "uniform vec4 rect; \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"
+ " vec4 v = texture2D(tex_rgba, xy).rgba; \n"
+ " outputColor = vec4(v.b, v.g, v.r, 1.0); \n"
+ " } else { \n"
+ " outputColor = bgColor; \n"
+ " } \n"
+ "} \n";
+
+
+static GLuint program = 0;
+
+static GLuint vao = 0;
+static GLuint buffers[2] = {0};
+static GLuint texture_rgba = 0;
+
+static GLuint uniform_mvp;
+static GLuint uniform_rgba;
+static GLuint uniform_rect;
+static GLuint uniform_color;
+
+static int _render_fini_bg_image(abc_render_t* render)
+{
+ return 0;
+}
+
+static int _render_draw_bg_image(abc_render_t* render, abc_obj_t* obj, int width, int height)
+{
+ abc_obj_t* attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_BG_IMAGE);
+ if (!attr)
+ return 0;
+ if (!attr->value || attr->value->len <= 0)
+ return 0;
+
+ scf_string_t* spath = NULL;
+ abc_io_t* io = NULL;
+ abc_img_t* img = NULL;
+
+ int ret = __io_url_css(&io, &spath, obj->file->data, attr->value->data);
+ if (ret < 0)
+ return ret;
+
+ scf_logi("background-image: %s\n", spath->data);
+
+ ret = abc_img_open(&img, spath->data);
+
+ scf_string_free(spath);
+ spath = NULL;
+ if (ret < 0)
+ return ret;
+
+ uint8_t* bgra = calloc(1, img->width * img->height * 4);
+ if (!bgra) {
+ abc_img_close(img);
+ return -ENOMEM;
+ }
+
+ ret = abc_img_read(img, bgra, img->width * img->height * 4);
+ if (ret < 0) {
+ abc_img_close(img);
+ free(bgra);
+ return ret;
+ }
+
+ double r = 0.0;
+ double g = 0.0;
+ double b = 0.0;
+ attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_BG_COLOR);
+ if (attr)
+ abc_css_color(&r, &g, &b, attr->value->data);
+
+ if (0 == program)
+ __init_program(&program, vert_shader, frag_shader);
+
+ if (0 == vao)
+ __init_buffers(&vao, buffers);
+
+ if (0 == texture_rgba)
+ __init_texture(&texture_rgba, GL_RGBA, img->width, img->height, NULL);
+
+ float mvp[16];
+ __compute_mvp(mvp, 0, 0, 0);
+
+ scf_logd("%s, x: %d, y: %d, w: %d, h: %d\n", obj->text->data, obj->x, obj->y, obj->w, obj->h);
+
+ GLfloat vert_update[] =
+ {
+ 2.0 * obj->x / (float)width - 1.0,
+ -2.0 * (obj->y + obj->h) / (float)height + 1.0,
+
+ 2.0 * (obj->x + obj->w) / (float)width - 1.0,
+ -2.0 * (obj->y + obj->h) / (float)height + 1.0,
+
+ 2.0 * obj->x / (float)width - 1.0,
+ -2.0 * obj->y / (float)height + 1.0,
+
+ 2.0 * (obj->x + obj->w) / (float)width - 1.0,
+ -2.0 * obj->y / (float)height + 1.0,
+ };
+
+ GLfloat x = 0.0;
+ GLfloat y = 0.0;
+ GLfloat w = img->width / (float)obj->w;
+ GLfloat h = img->height / (float)obj->h;
+
+ if (w > 1.0 || h > 1.0)
+ {
+ GLfloat max = w > h ? w : h;
+
+ w /= max;
+ h /= max;
+ }
+
+ glUseProgram(program);
+ uniform_color = glGetUniformLocation(program, "bgColor");
+ uniform_rgba = glGetUniformLocation(program, "tex_rgba");
+ uniform_rect = glGetUniformLocation(program, "rect");
+ uniform_mvp = glGetUniformLocation(program, "mvp");
+
+ glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, mvp);
+
+ glActiveTexture(GL_TEXTURE0);
+ 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);
+
+ // draw
+ glBindBuffer (GL_ARRAY_BUFFER, buffers[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vert_update), vert_update);
+
+ glBindVertexArray(vao);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ glBindVertexArray(0);
+ glUseProgram(0);
+
+ abc_img_close(img);
+ free(bgra);
+ return 0;
+}
+
+abc_render_t abc_render_bg_image =
+{
+ .type = ABC_HTML_ATTR_BG_IMAGE,
+
+ .draw = _render_draw_bg_image,
+ .fini = _render_fini_bg_image,
+};
#include"abc.h"
+extern abc_render_t abc_render_h1;
+extern abc_render_t abc_render_bg_color;
+extern abc_render_t abc_render_bg_image;
+
static int _render_fini_body(abc_render_t* render)
{
return 0;
static int _render_draw_body(abc_render_t* render, abc_obj_t* obj, int width, int height)
{
+ abc_obj_t* attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_BG_IMAGE);
+
+ if (attr && attr->value && attr->value->len > 0)
+ {
+ abc_render_bg_image.draw(&abc_render_bg_image, obj, width, height);
+ } else
+ abc_render_bg_color.draw(&abc_render_bg_color, obj, width, height);
+
+ if (obj->text)
+ abc_render_h1.draw(&abc_render_h1, obj, width, height);
+
return 0;
}
abc_render_t abc_render_body =
{
- .type = ABC_HTML_H1,
+ .type = ABC_HTML_BODY,
.draw = _render_draw_body,
.fini = _render_fini_body,
return 0;
}
-static int _render_draw_h1(abc_render_t* render, abc_obj_t* obj, int width, int height)
+static int __init_text(cairo_t* cr, abc_obj_t* obj)
{
- if (!obj->text)
- return 0;
-
- if (0 == program)
- __init_program(&program, vert_shader, frag_shader);
-
- if (0 == vao)
- __init_buffers(&vao, buffers);
-
- if (0 == texture_rgba)
- __init_texture(&texture_rgba, GL_RGBA, obj->w, obj->h, NULL);
-
- abc_obj_t* attr;
- cairo_text_extents_t extents;
- cairo_surface_t* surface;
- cairo_t* cr;
-
- uint8_t* bgra = calloc(1, obj->w * obj->h * 4);
- if (!bgra)
- return -ENOMEM;
-
- surface = cairo_image_surface_create_for_data(bgra, CAIRO_FORMAT_ARGB32, obj->w, obj->h, obj->w * 4);
- cr = cairo_create(surface);
-
- cairo_set_line_width(cr, 1);
- cairo_set_source_rgb(cr, 1, 1, 1);
- cairo_rectangle(cr, 0, 0, obj->w, obj->h);
- cairo_fill(cr);
- cairo_stroke(cr);
-
- attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT);
+ abc_obj_t* attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT);
if (attr) {
int bold = CAIRO_FONT_WEIGHT_NORMAL;
int italic = CAIRO_FONT_SLANT_NORMAL;
if (attr)
cairo_set_font_size(cr, atoi(attr->value->data));
+ cairo_text_extents_t extents;
double r = 0.0;
double g = 0.0;
double 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_move_to (cr, extents.x_bearing, -extents.y_bearing);
cairo_show_text(cr, obj->text->data);
+ return 0;
+}
+
+static int _render_draw_h1(abc_render_t* render, abc_obj_t* obj, int width, int height)
+{
+ if (0 == program)
+ __init_program(&program, vert_shader, frag_shader);
+
+ if (0 == vao)
+ __init_buffers(&vao, buffers);
+
+ if (0 == texture_rgba)
+ __init_texture(&texture_rgba, GL_RGBA, obj->w, obj->h, NULL);
+
+ abc_obj_t* attr;
+ cairo_surface_t* surface;
+ cairo_t* cr;
+
+ uint8_t* bgra = calloc(1, obj->w * obj->h * 4);
+ if (!bgra)
+ return -ENOMEM;
+
+ double r = 0.0;
+ double g = 0.0;
+ double b = 0.0;
+ attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_BG_COLOR);
+ if (attr)
+ abc_css_color(&r, &g, &b, attr->value->data);
+
+ surface = cairo_image_surface_create_for_data(bgra, CAIRO_FORMAT_ARGB32, obj->w, obj->h, obj->w * 4);
+ cr = cairo_create(surface);
+
+ cairo_set_line_width(cr, 1);
+ cairo_set_source_rgb(cr, r, g, b);
+ cairo_rectangle(cr, 0, 0, obj->w, obj->h);
+ cairo_fill(cr);
+ cairo_stroke(cr);
+ if (obj->text)
+ __init_text(cr, obj);
// cairo_surface_write_to_png(surface, "tmp.png");
cairo_destroy(cr);
static int _render_draw_img(abc_render_t* render, abc_obj_t* obj, int width, int height)
{
- scf_list_t* l;
- abc_obj_t* attr;
- abc_img_t* img = NULL;
+ abc_obj_t* attr;
+ abc_img_t* img = NULL;
- for (l = scf_list_head(&obj->attrs); l != scf_list_sentinel(&obj->attrs); l = scf_list_next(l)) {
- attr = scf_list_data(l, abc_obj_t, list);
-
- if (ABC_HTML_ATTR_SRC == attr->type)
- break;
- }
-
- if (l == scf_list_sentinel(&obj->attrs)) {
+ attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_SRC);
+ if (!attr) {
scf_loge("src image of '%s' not found\n", obj->keys[0]);
return -1;
}
glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, mvp);
- // board
glActiveTexture(GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, texture_rgba);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, img->width, img->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bgra);