html/css: support css for <ol>, <ul>, <li> master
authoryu.dongliang <18588496441@163.com>
Sun, 19 Apr 2026 05:56:36 +0000 (13:56 +0800)
committeryu.dongliang <18588496441@163.com>
Sun, 19 Apr 2026 05:56:36 +0000 (13:56 +0800)
examples/list.html
examples/sqpurple.gif [new file with mode: 0644]
html/abc_html.c
html/abc_obj.c
html/abc_obj.h
ui/abc.h
ui/abc_layout.c
ui/abc_layout_h1.c
ui/abc_render_h1.c
ui/abc_render_li.c

index 6e12ce1fe5f4945df7781b02c8c9a5ffafa0c898..a08662b99c58a33d61e30c3e63fdfe92c2c63432 100644 (file)
@@ -2,8 +2,13 @@
 <html>
 <head>
 <style>
 <html>
 <head>
 <style>
-ul.a {list-style-type:circle;}
-ul.b {list-style-type:square;}
+ul.a {
+       list-style-type:circle;
+}
+ul.b {
+       list-style-type:square;
+       list-style-image:url('sqpurple.gif');
+}
 ol.c {list-style-type:upper-roman;}
 ol.d {list-style-type:lower-alpha;}
 </style>
 ol.c {list-style-type:upper-roman;}
 ol.d {list-style-type:lower-alpha;}
 </style>
diff --git a/examples/sqpurple.gif b/examples/sqpurple.gif
new file mode 100644 (file)
index 0000000..7300882
Binary files /dev/null and b/examples/sqpurple.gif differ
index 10cf7edf2926934d246ea2a12a7cc031e0094694..60eaa47783d87c1a94f4e6ce6d4956f9f5525743 100644 (file)
@@ -1350,6 +1350,7 @@ static int __html_parse_obj(abc_html_t* html, abc_char_t* c)
 
                scf_list_add_tail(&html->current->childs, &obj->list);
 
 
                scf_list_add_tail(&html->current->childs, &obj->list);
 
+               obj ->index   = html->current->n_childs++;
                html->current = obj;
        }
 
                html->current = obj;
        }
 
@@ -1373,7 +1374,8 @@ static int __html_parse_obj(abc_html_t* html, abc_char_t* c)
        } else
                ret = __html_parse_text(html, obj);
 
        } else
                ret = __html_parse_text(html, obj);
 
-       switch (obj->type) {
+       switch (obj->type)
+       {
                case ABC_HTML_SCRIPT:
                        if (__html_run_js(html, obj) < 0)
                                return -1;
                case ABC_HTML_SCRIPT:
                        if (__html_run_js(html, obj) < 0)
                                return -1;
index 147cba0a72bffbdb145dbf591ecf41232c6bf5e7..ac1beafed2e678dba5727ed8ea27188b6537d142 100644 (file)
@@ -129,22 +129,6 @@ int abc_obj_set_attr(abc_obj_t* obj, int key, const char* value, size_t len)
        return -EINVAL;
 }
 
        return -EINVAL;
 }
 
-int abc_recursive_set_attr(abc_obj_t* obj, int key, const char* value, size_t len)
-{
-       scf_list_t*  l;
-       abc_obj_t*   child;
-
-       abc_obj_set_attr(obj, key, value, len);
-
-       for (l    = scf_list_head(&obj->childs); l != scf_list_sentinel(&obj->childs); l = scf_list_next(l)) {
-               child = scf_list_data(l, abc_obj_t, list);
-
-               abc_recursive_set_attr(child, key, value, len);
-       }
-
-       return 0;
-}
-
 abc_obj_t* abc_obj_get_attr(abc_obj_t* obj, int key)
 {
        scf_list_t*   l;
 abc_obj_t* abc_obj_get_attr(abc_obj_t* obj, int key)
 {
        scf_list_t*   l;
@@ -344,3 +328,111 @@ scf_string_t* abc_obj_to_string(abc_obj_t* obj)
        scf_logi("%s\n", s->data);
        return s;
 }
        scf_logi("%s\n", s->data);
        return s;
 }
+
+static scf_string_t* __li_style_roman(int num, const char** roman)
+{
+       scf_string_t* s = scf_string_alloc();
+       if (!s)
+               return NULL;
+
+       uint32_t data[] = {1000,900,  500,400,  100,90,  50,40,  10,9,  5,4,  1};
+
+       if (num < 0) {
+               num = -num;
+
+               if (scf_string_cat_cstr_len(s, "-", 1) < 0) {
+                       scf_string_free(s);
+                       return NULL;
+               }
+       }
+
+       int i;
+       for (i = 0; i < sizeof(data) / sizeof(data[0]); i++)
+       {
+               while (num >= data[i])
+               {
+                       int k = (i & 0x1) + 1;
+
+                       if (scf_string_cat_cstr_len(s, roman[i], k) < 0) {
+                               scf_string_free(s);
+                               return NULL;
+                       }
+
+                       num -= data[i];
+               }
+       }
+
+       if (scf_string_cat_cstr_len(s, ". ", 2) < 0) {
+               scf_string_free(s);
+               return NULL;
+       }
+
+       return s;
+}
+
+static scf_string_t* __li_style_number(int num, uint32_t base, const char c0)
+{
+       scf_string_t* s = scf_string_alloc();
+       if (!s)
+               return NULL;
+
+       if (num < 0) {
+               num = -num;
+
+               if (scf_string_cat_cstr_len(s, "-", 1) < 0) {
+                       scf_string_free(s);
+                       return NULL;
+               }
+       }
+
+       int i = s->len;
+       do {
+               uint8_t c = num % base + c0;
+
+               if (scf_string_cat_cstr_len(s, &c, 1) < 0) {
+                       scf_string_free(s);
+                       return NULL;
+               }
+
+               num /= base;
+       } while (num > 0);
+
+       int j = s->len - 1;
+       while (i < j) {
+               SCF_XCHG(s->data[i], s->data[j]);
+               i++;
+               j--;
+       }
+
+       if (scf_string_cat_cstr_len(s, ". ", 2) < 0) {
+               scf_string_free(s);
+               return NULL;
+       }
+
+       return s;
+}
+
+static const char* ROMAN[] = {"M","CM", "D","CD", "C","XC", "L","XL","X","IX","V","IV","I"};
+static const char* roman[] = {"m","cm", "d","cd", "c","xc", "l","xl","x","ix","v","iv","i"};
+
+scf_string_t* abc_ol_list_style(abc_obj_t* obj, int num)
+{
+       abc_obj_t* attr = abc_obj_find_attr(obj, ABC_CSS_LIST_STYLE_TYPE);
+       if (attr) {
+               const char* p = attr->value->data;
+
+               if (!__html_strcmp(p, "upper-roman"))
+                       return __li_style_roman(num + 1, ROMAN);
+
+               else if (!__html_strcmp(p, "lower-roman"))
+                       return __li_style_roman(num + 1, roman);
+
+               else if (!__html_strcmp(p, "upper-alpha"))
+                       return __li_style_number(num, 26, 'A');
+
+               else if (!__html_strcmp(p, "lower-alpha"))
+                       return __li_style_number(num, 26, 'a');
+       }
+
+       return __li_style_number(num, 10, '0');
+}
index 8f2733402ce3f0cecec244264c32c6692d3e99cc..523ba5116d3dc1cc2667f7ab4511659ffd0b25da 100644 (file)
@@ -139,6 +139,8 @@ struct abc_obj_s
 
        scf_list_t      attrs;
        scf_list_t      childs;
 
        scf_list_t      attrs;
        scf_list_t      childs;
+       int             n_childs;
+       int             index;
 
        abc_obj_t*      parent;
 
 
        abc_obj_t*      parent;
 
@@ -159,6 +161,10 @@ struct abc_obj_s
        int             w;
        int             h;
 
        int             w;
        int             h;
 
+       double          y_bearing;
+       int             margin;
+       int             padding;
+
        int             progress;
        uint32_t        jiffies; // timeout numbers of sys timer
 
        int             progress;
        uint32_t        jiffies; // timeout numbers of sys timer
 
@@ -200,6 +206,6 @@ abc_obj_t*     abc_obj_find_type(abc_obj_t* root, int type);
 
 scf_string_t*  abc_obj_to_string(abc_obj_t* obj);
 
 
 scf_string_t*  abc_obj_to_string(abc_obj_t* obj);
 
-int            abc_recursive_set_attr(abc_obj_t* obj, int key, const char* value, size_t len);
+scf_string_t*  abc_ol_list_style(abc_obj_t* obj, int num);
 
 #endif
 
 #endif
index 6c85004d1ae607cf8ff3bf76e169067dcd44e8c8..ff3b339d8d1c09e1d9589ee60517f0a2aa8661b5 100644 (file)
--- a/ui/abc.h
+++ b/ui/abc.h
@@ -76,6 +76,6 @@ int  __init_program(GLuint* pprog, const char* vert_shader, const char* frag_sha
 
 int  __init_buffers(GLuint* vao, GLuint buffers[2]);
 
 
 int  __init_buffers(GLuint* vao, GLuint buffers[2]);
 
-int __init_text(cairo_t* cr, abc_obj_t* obj, double dx);
+int __init_text(cairo_t* cr, abc_obj_t* obj, int num_flag);
 
 #endif
 
 #endif
index 84882f40ea0051e5665dbf662a1c626507ccc618..818668cfe295bdf2a88e1d59731c368781ab5ab5 100644 (file)
@@ -190,9 +190,6 @@ int abc_layout_root(abc_ctx_t* abc, abc_obj_t* root, int width, int height)
                                if (ret < 0)
                                        return ret;
 
                                if (ret < 0)
                                        return ret;
 
-                               if (ABC_HTML_UL == root->type || ABC_HTML_OL == root->type)
-                                       child->w    += 16;
-
                                x = root->x  + 4;
                                y = child->y + child->h;
                                h = 0;
                                x = root->x  + 4;
                                y = child->y + child->h;
                                h = 0;
index a4ade871f4f3b2db8dedd674fec7212bdee43a31..2e869abee78a419713ee0b6b5ad44ab8325b263b 100644 (file)
@@ -5,6 +5,7 @@ int abc_layout_h1(abc_layout_t* layout, abc_obj_t* obj, int width, int height)
        abc_obj_t*            attr;
        abc_obj_t*            style;
        cairo_text_extents_t  extents;
        abc_obj_t*            attr;
        abc_obj_t*            style;
        cairo_text_extents_t  extents;
+       cairo_text_extents_t  extents2;
        cairo_surface_t*      surface;
        cairo_t*              cr;
 
        cairo_surface_t*      surface;
        cairo_t*              cr;
 
@@ -31,9 +32,12 @@ int abc_layout_h1(abc_layout_t* layout, abc_obj_t* obj, int width, int height)
                cairo_select_font_face(cr, attr->value->data, italic, bold);
        }
 
                cairo_select_font_face(cr, attr->value->data, italic, bold);
        }
 
+       int size = 16;
        attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE);
        attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE);
-       if (attr)
-               cairo_set_font_size(cr, atoi(attr->value->data));
+       if (attr) {
+               size = atoi(attr->value->data);
+               cairo_set_font_size(cr, size);
+       }
 
        cairo_font_options_t *options = cairo_font_options_create();
        cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_SUBPIXEL);
 
        cairo_font_options_t *options = cairo_font_options_create();
        cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_SUBPIXEL);
@@ -43,13 +47,36 @@ int abc_layout_h1(abc_layout_t* layout, abc_obj_t* obj, int width, int height)
        cairo_font_options_destroy(options);
 
        cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
        cairo_font_options_destroy(options);
 
        cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+
        cairo_text_extents(cr, obj->text->data, &extents);
 
        cairo_text_extents(cr, obj->text->data, &extents);
 
-//     obj->x = 4;
-//     obj->y = 4;
-       obj->w = extents.width  + extents.x_bearing;
-       obj->h = extents.height + extents.height / 2;
+       int w = 0;
+       if (ABC_HTML_OL == obj->parent->type)
+       {
+               if (0 == obj->parent->padding) {
+                       scf_string_t* s = abc_ol_list_style(obj->parent, obj->parent->n_childs);
+                       if (s) {
+                               cairo_text_extents(cr, s->data, &extents2);
+
+                               obj->parent->padding = extents2.width + extents2.x_bearing + size / 2;
+
+                               scf_string_free(s);
+                               s = NULL;
+                       }
+               }
+
+               obj->y_bearing = extents.y_bearing;
+
+               w = obj->parent->padding;
+       } else if (ABC_HTML_UL == obj->parent->type) {
+               w = size;
+               obj->parent->padding = size;
+       }
+
+       w += extents.width + extents.x_bearing;
 
 
+       obj->w = w;
+       obj->h = extents.height + extents.height / 2;
        obj->w = (obj->w + 3) & ~0x3;
        obj->h = (obj->h + 3) & ~0x3;
 
        obj->w = (obj->w + 3) & ~0x3;
        obj->h = (obj->h + 3) & ~0x3;
 
index e6d90cd42fd6f07bdaa96196670d7be5643a998f..461f2596b8e7e381c51f2e49455d2cfa1ff78765 100644 (file)
@@ -38,7 +38,7 @@ static int _render_fini_h1(abc_render_t* render)
        return 0;
 }
 
        return 0;
 }
 
-int __init_text(cairo_t* cr, abc_obj_t* obj, double dx)
+int __init_text(cairo_t* cr, abc_obj_t* obj, int num_flag)
 {
        abc_obj_t* attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT);
        if (attr) {
 {
        abc_obj_t* attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT);
        if (attr) {
@@ -69,6 +69,13 @@ int __init_text(cairo_t* cr, abc_obj_t* obj, double dx)
                cairo_set_font_size(cr, size);
        }
 
                cairo_set_font_size(cr, size);
        }
 
+       cairo_font_options_t *options = cairo_font_options_create();
+       cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_SUBPIXEL);
+       cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_FULL);
+       cairo_font_options_set_hint_metrics(options, CAIRO_HINT_METRICS_ON);
+       cairo_set_font_options(cr, options);
+       cairo_font_options_destroy(options);
+
        attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_COLOR);
        if (attr)
                abc_css_color(&r, &g, &b, attr->value->data);
        attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_COLOR);
        if (attr)
                abc_css_color(&r, &g, &b, attr->value->data);
@@ -76,7 +83,19 @@ int __init_text(cairo_t* cr, abc_obj_t* obj, double dx)
        cairo_set_source_rgba(cr, r, g, b, 1.0);
        cairo_text_extents   (cr, obj->text->data, &extents);
 
        cairo_set_source_rgba(cr, r, g, b, 1.0);
        cairo_text_extents   (cr, obj->text->data, &extents);
 
-       cairo_move_to  (cr, extents.x_bearing + dx, -extents.y_bearing);
+       switch (obj->parent->type)
+       {
+               case ABC_HTML_OL:
+                       if (num_flag)
+                               cairo_move_to(cr, obj->parent->padding - (extents.x_bearing + extents.width + size / 2), -obj->y_bearing);
+                       else
+                               cairo_move_to(cr, extents.x_bearing + obj->parent->padding, -extents.y_bearing);
+                       break;
+               default:
+                       cairo_move_to(cr, extents.x_bearing + obj->parent->padding, -extents.y_bearing);
+                       break;
+       };
+
        cairo_show_text(cr, obj->text->data);
        cairo_stroke(cr);
 
        cairo_show_text(cr, obj->text->data);
        cairo_stroke(cr);
 
@@ -139,7 +158,7 @@ static int _render_draw_h1(abc_render_t* render, abc_obj_t* obj, int width, int
        cairo_stroke(cr);
 
        if (obj->text)
        cairo_stroke(cr);
 
        if (obj->text)
-               __init_text(cr, obj, 0.0);
+               __init_text(cr, obj, 0);
 //     cairo_surface_write_to_png(surface, "tmp.png");
 
        cairo_destroy(cr);
 //     cairo_surface_write_to_png(surface, "tmp.png");
 
        cairo_destroy(cr);
index 9349b6bb01b05452dd2db334cb3beeb662b64642..138f4af11fa444a7b58417ef47026fbef449c225 100644 (file)
@@ -63,6 +63,12 @@ static int _render_draw_li(abc_render_t* render, abc_obj_t* obj, int width, int
        double r = 0.0;
        double g = 0.0;
        double b = 0.0;
        double r = 0.0;
        double g = 0.0;
        double b = 0.0;
+       int    size = 16;
+
+       attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE);
+       if (attr)
+               size = atoi(attr->value->data);
+
        attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_BG_COLOR);
        if (attr)
                abc_css_color(&r, &g, &b, attr->value->data);
        attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_BG_COLOR);
        if (attr)
                abc_css_color(&r, &g, &b, attr->value->data);
@@ -76,40 +82,9 @@ static int _render_draw_li(abc_render_t* render, abc_obj_t* obj, int width, int
        cairo_fill(cr);
        cairo_stroke(cr);
 
        cairo_fill(cr);
        cairo_stroke(cr);
 
+       int offset = obj->parent->padding;
        if (obj->text)
        if (obj->text)
-               __init_text(cr, obj, 16);
-
-       if (ABC_HTML_UL == obj->parent->type) {
-               r = 0.0;
-               g = 0.0;
-               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_set_source_rgb(cr, r, g, b);
-
-               attr = abc_obj_find_attr(obj, ABC_CSS_LIST_STYLE_TYPE);
-               if (attr) {
-                       if (!strcmp(attr->value->data, "circle"))
-                               cairo_arc (cr, 8, 8, 3, 0, 2 * M_PI);
-
-                       else if (!strcmp(attr->value->data, "square")) {
-                               cairo_rectangle(cr, 5, 5, 6, 6);
-                               cairo_fill(cr);
-
-                       } else if (!strcmp(attr->value->data, "disc")) {
-                               cairo_arc (cr, 8, 8, 3, 0, 2 * M_PI);
-                               cairo_fill(cr);
-                       }
-               } else {
-                       cairo_arc (cr, 8, 8, 3, 0, 2 * M_PI);
-                       cairo_fill(cr);
-               }
-
-               cairo_stroke(cr);
-       }
-//     cairo_surface_write_to_png(surface, "tmp.png");
+               __init_text(cr, obj, 0);
 
        cairo_destroy(cr);
        cairo_surface_destroy(surface);
 
        cairo_destroy(cr);
        cairo_surface_destroy(surface);
@@ -121,13 +96,79 @@ static int _render_draw_li(abc_render_t* render, abc_obj_t* obj, int width, int
 
        GLfloat  x = 0.0;
        GLfloat  y = 0.0;
 
        GLfloat  x = 0.0;
        GLfloat  y = 0.0;
-       GLfloat  w = 0.0;
-       GLfloat  h = 0.0;
+       GLfloat  w = offset / (float)obj->w;
+       GLfloat  h = size   / (float)obj->h;
 
        attr = abc_obj_find_attr(obj, ABC_CSS_LIST_STYLE_IMAGE);
 
 
        attr = abc_obj_find_attr(obj, ABC_CSS_LIST_STYLE_IMAGE);
 
-       if (attr && attr->value && attr->value->len > 0)
+       if (ABC_HTML_OL == obj->parent->type || !attr || !attr->value || attr->value->len <= 0)
        {
        {
+               bgra1 = calloc(1, offset * size * 4);
+               if (!bgra1) {
+                       free(bgra);
+                       return -ENOMEM;
+               }
+
+               surface = cairo_image_surface_create_for_data(bgra1, CAIRO_FORMAT_ARGB32, offset, size, offset * 4);
+               cr      = cairo_create(surface);
+
+               cairo_set_line_width(cr, 1);
+               cairo_set_source_rgb(cr, r, g, b);
+               cairo_rectangle(cr, 0, 0, offset, size);
+               cairo_fill(cr);
+               cairo_stroke(cr);
+
+               if (ABC_HTML_OL == obj->parent->type)
+               {
+                       scf_string_t* s = abc_ol_list_style(obj, obj->index);
+                       if (!s) {
+                               free(bgra1);
+                               free(bgra);
+                               return -ENOMEM;
+                       }
+
+                       SCF_XCHG(obj->text, s);
+                       __init_text(cr, obj, 1);
+                       SCF_XCHG(obj->text, s);
+
+                       scf_string_free(s);
+                       s = NULL;
+               } else {
+                       r = 0.0;
+                       g = 0.0;
+                       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_set_source_rgb(cr, r, g, b);
+
+                       attr = abc_obj_find_attr(obj, ABC_CSS_LIST_STYLE_TYPE);
+                       if (attr) {
+                               if (!strcmp(attr->value->data, "circle"))
+                                       cairo_arc (cr, offset / 2, size / 2, size / 4, 0, 2 * M_PI);
+
+                               else if (!strcmp(attr->value->data, "square")) {
+                                       cairo_rectangle(cr, offset / 4, size / 4, size / 2, size / 2);
+                                       cairo_fill(cr);
+
+                               } else if (!strcmp(attr->value->data, "disc")) {
+                                       cairo_arc (cr, offset / 2, size / 2, size / 4, 0, 2 * M_PI);
+                                       cairo_fill(cr);
+                               }
+                       } else {
+                               cairo_arc (cr, offset / 2, size / 2, size / 4, 0, 2 * M_PI);
+                               cairo_fill(cr);
+                       }
+
+                       cairo_stroke(cr);
+               }
+
+               cairo_destroy(cr);
+               cairo_surface_destroy(surface);
+               surface = NULL;
+               cr = NULL;
+       } else {
                scf_string_t* spath = NULL;
                abc_io_t*     io    = NULL;
 
                scf_string_t* spath = NULL;
                abc_io_t*     io    = NULL;
 
@@ -163,13 +204,10 @@ static int _render_draw_li(abc_render_t* render, abc_obj_t* obj, int width, int
                        return ret;
                }
 
                        return ret;
                }
 
-               x = obj->h * 0.333 / (float)obj->w;
-               y = 0.333;
-               w = x;
-               h = y;
-
-               if (0 == texture_img)
-                       __init_texture(&texture_img, GL_RGBA, img->width, img->height, NULL);
+               x = size / 4 / (float)obj->w;
+               y = size / 4 / (float)obj->h;
+               w = x * 2;
+               h = y * 2;
        }
 
        if (0 == program)
        }
 
        if (0 == program)
@@ -181,6 +219,9 @@ static int _render_draw_li(abc_render_t* render, abc_obj_t* obj, int width, int
        if (0 == texture_rgba)
                __init_texture(&texture_rgba, GL_RGBA, obj->w, obj->h, NULL);
 
        if (0 == texture_rgba)
                __init_texture(&texture_rgba, GL_RGBA, obj->w, obj->h, NULL);
 
+       if (0 == texture_img)
+               __init_texture(&texture_img, GL_RGBA, offset, size, NULL);
+
        float mvp[16];
        __compute_mvp(mvp, 0, 0, 0);
 
        float mvp[16];
        __compute_mvp(mvp, 0, 0, 0);
 
@@ -213,14 +254,15 @@ static int _render_draw_li(abc_render_t* render, abc_obj_t* obj, int width, int
        glActiveTexture(GL_TEXTURE0);
        glBindTexture  (GL_TEXTURE_2D, texture_rgba);
        glTexImage2D   (GL_TEXTURE_2D, 0, GL_RGBA, obj->w, obj->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, bgra);
        glActiveTexture(GL_TEXTURE0);
        glBindTexture  (GL_TEXTURE_2D, texture_rgba);
        glTexImage2D   (GL_TEXTURE_2D, 0, GL_RGBA, obj->w, obj->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, bgra);
-       glUniform1i(uniform_rgba,  0);
-
-       if (img) {
-               glActiveTexture(GL_TEXTURE1);
-               glBindTexture  (GL_TEXTURE_2D, texture_img);
-               glTexImage2D   (GL_TEXTURE_2D, 0, GL_RGBA, img->width, img->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bgra1);
-               glUniform1i(uniform_img,  1);
-       }
+       glUniform1i(uniform_rgba, 0);
+
+       glActiveTexture(GL_TEXTURE1);
+       glBindTexture  (GL_TEXTURE_2D, texture_img);
+       if (img)
+               glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img->width, img->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bgra1);
+       else
+               glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, offset, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, bgra1);
+       glUniform1i(uniform_img, 1);
 
        glUniform4f(uniform_rect, x, y, w, h);
 
 
        glUniform4f(uniform_rect, x, y, w, h);