-#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 int repeat_x; \n"
- "uniform int repeat_y; \n"
- "uniform int index_x; \n"
- "uniform int index_y; \n"
- "uniform sampler2D tex_rgba; \n"
- "void main() { \n"
- " vec2 xy = v_texCoord; \n"
- " float i = floor((xy.x - rect.x) / rect.z); \n"
- " float j = floor((xy.y - rect.y) / rect.w); \n"
- " if ((repeat_x > 0 || int(round(i)) == index_x) && (repeat_y > 0 || int(round(j)) == index_y)) { \n"
- " float x = rect.x + i * rect.z; \n"
- " float y = rect.y + j * rect.w; \n"
- " xy.x = (xy.x - x) / rect.z; \n"
- " xy.y = (xy.y - 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 GLuint uniform_repeat_x;
-static GLuint uniform_repeat_y;
-static GLuint uniform_index_x;
-static GLuint uniform_index_y;
-
-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_logd("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;
- }
-
- GLint repeat_x = 1;
- GLint repeat_y = 1;
- GLint index_x = 0;
- GLint index_y = 0;
-
- attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_BG_POSITION);
- if (attr) {
- abc_css_position(&x, &y, w, h, obj, attr->value->data);
-
- scf_logd("background-position: %s, x: %f, y: %f, w: %f, h: %f\n", attr->value->data, x, y, w, h);
-
- if (x + w > 1.0)
- index_x = -1;
-
- if (y + h > 1.0)
- index_y = -1;
- }
-
- attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_BG_REPEAT);
- if (attr) {
- if (!__html_strcmp(attr->value->data, "repeat-x"))
- repeat_y = 0;
-
- else if (!__html_strcmp(attr->value->data, "repeat-y"))
- repeat_x = 0;
-
- else if (!__html_strcmp(attr->value->data, "no-repeat")) {
- repeat_x = 0;
- repeat_y = 0;
- }
- }
-
- scf_logd("repeat_x: %d, repeat_y: %d, index_x: %d, index_y: %d\n", repeat_x, repeat_y, index_x, index_y);
-
- glUseProgram(program);
-
- uniform_mvp = glGetUniformLocation(program, "mvp");
- uniform_rgba = glGetUniformLocation(program, "tex_rgba");
- uniform_rect = glGetUniformLocation(program, "rect");
- uniform_color = glGetUniformLocation(program, "bgColor");
- uniform_repeat_x = glGetUniformLocation(program, "repeat_x");
- uniform_repeat_y = glGetUniformLocation(program, "repeat_y");
- uniform_index_x = glGetUniformLocation(program, "index_x");
- uniform_index_y = glGetUniformLocation(program, "index_y");
-
- 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);
-
- glUniform1i(uniform_repeat_x, repeat_x);
- glUniform1i(uniform_repeat_y, repeat_y);
- glUniform1i(uniform_index_x, index_x);
- glUniform1i(uniform_index_y, index_y);
-
- // 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,
-};