+#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,
+};