+#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 color; \n"
+ "uniform vec4 bgColor; \n"
+ "uniform float line_width; \n"
+ "\n"
+ "void main() { \n"
+ " float x = v_texCoord.x; \n"
+ " float y = v_texCoord.y; \n"
+ " if (y > 0.5 - line_width && y < 0.5 + line_width) { \n"
+ " outputColor = color; \n"
+ " } else { \n"
+ " outputColor = bgColor; \n"
+ " } \n"
+ "} \n";
+
+
+static GLuint program = 0;
+
+static GLuint vao = 0;
+static GLuint buffers[2] = {0};
+
+static GLuint uniform_mvp;
+static GLuint uniform_color;
+static GLuint uniform_bgColor;
+static GLuint uniform_line_width;
+
+static int __render_fini_hr(abc_render_t* render)
+{
+ return 0;
+}
+
+static int __render_draw_hr(abc_render_t* render, abc_obj_t* obj, int width, int height)
+{
+ abc_obj_t* parent = obj->parent;
+
+ if (0 == program)
+ __init_program(&program, vert_shader, frag_shader);
+
+ if (0 == vao)
+ __init_buffers(&vao, buffers);
+
+ double fgColor[3] = {0.0, 0.0, 0.0};
+ double bgColor[4] = {0.0, 0.0, 0.0, 0.0};
+
+ abc_attr_t* attr = abc_obj_get_attr(obj, ABC_HTML_ATTR_BG_COLOR);
+ if (attr && attr->value->len > 0) {
+ bgColor[3] = 1.0;
+ abc_css_color(bgColor, bgColor + 1, bgColor + 2, attr->value->data, attr->value->len);
+ }
+
+ attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_COLOR);
+ if (attr)
+ abc_css_color(fgColor, fgColor + 1, fgColor + 2, attr->value->data, attr->value->len);
+
+ int x = obj->x + obj->margin_left;
+ int y = obj->y + obj->margin_top;
+ int w = obj->w - obj->margin_left - obj->margin_right;
+ int h = obj->h - obj->margin_top - obj->margin_bottom;
+
+ obj->view_x = x;
+ obj->view_y = y;
+ obj->view_w = w;
+ obj->view_h = h;
+
+ attr = abc_obj_find_attr(obj, ABC_CSS_OVERFLOW);
+ if (attr)
+ obj->overflow_type = abc_css_overflow(attr->value->data);
+
+ switch (obj->overflow_type)
+ {
+ case ABC_OVERFLOW_SCROLL:
+ case ABC_OVERFLOW_AUTO:
+ case ABC_OVERFLOW_HIDDEN:
+ if (parent && (x < parent->view_x
+ || y < parent->view_y
+ || x + w > parent->view_x + parent->view_w
+ || y + h > parent->view_y + parent->view_h)) {
+
+ abc_overflow_show(&obj->view_x, &obj->view_y, &obj->view_w, &obj->view_h,
+ parent->view_x,
+ parent->view_y,
+ parent->view_w - parent->border_right - parent->padding_right,
+ parent->view_h - parent->border_bottom - parent->padding_bottom);
+ }
+ break;
+ default:
+ break;
+ };
+
+ float mvp[16];
+ __compute_mvp(mvp, 0, 0, 0);
+
+ GLfloat vert_update[] =
+ {
+ 2.0 * obj->view_x / (float)width - 1.0,
+ -2.0 * (obj->view_y + obj->view_h) / (float)height + 1.0,
+
+ 2.0 * (obj->view_x + obj->view_w) / (float)width - 1.0,
+ -2.0 * (obj->view_y + obj->view_h) / (float)height + 1.0,
+
+ 2.0 * obj->view_x / (float)width - 1.0,
+ -2.0 * obj->view_y / (float)height + 1.0,
+
+ 2.0 * (obj->view_x + obj->view_w) / (float)width - 1.0,
+ -2.0 * obj->view_y / (float)height + 1.0,
+ };
+
+ GLfloat texture_update[] =
+ {
+ (obj->view_x - x) / (float)w,
+ (obj->view_y + obj->view_h - y) / (float)h,
+
+ (obj->view_x + obj->view_w - x) / (float)w,
+ (obj->view_y + obj->view_h - y) / (float)h,
+
+ (obj->view_x - x) / (float)w,
+ (obj->view_y - y) / (float)h,
+
+ (obj->view_x + obj->view_w - x) / (float)w,
+ (obj->view_y - y) / (float)h,
+ };
+
+ glUseProgram(program);
+ uniform_mvp = glGetUniformLocation(program, "mvp");
+ uniform_color = glGetUniformLocation(program, "color");
+ uniform_bgColor = glGetUniformLocation(program, "bgColor");
+ uniform_line_width = glGetUniformLocation(program, "line_width");
+
+ glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, mvp);
+
+ glUniform4f(uniform_color, fgColor[0], fgColor[1], fgColor[2], 1.0);
+ glUniform4f(uniform_bgColor, bgColor[0], bgColor[1], bgColor[2], bgColor[3]);
+ glUniform1f(uniform_line_width, 1.0 / (float)h);
+
+ // draw
+ glBindBuffer (GL_ARRAY_BUFFER, buffers[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vert_update), vert_update);
+
+ glBindBuffer (GL_ARRAY_BUFFER, buffers[1]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(texture_update), texture_update);
+
+ glBindVertexArray(vao);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glDisable(GL_BLEND);
+
+ glBindVertexArray(0);
+ glUseProgram(0);
+ return 0;
+}
+
+abc_render_t abc_render_hr =
+{
+ .type = ABC_HTML_HR,
+
+ .draw = __render_draw_hr,
+ .fini = __render_fini_hr,
+};