dirty redraw and SDL framebuffer example
[windtk] / src / windtk.c
index c34dc42..69ad9fa 100644 (file)
@@ -124,19 +124,76 @@ void wt_draw_tree(wt_widget *tree)
        int i;
 
        if(tree->draw) {
-               tree->draw(tree, &wt->gfx);
+               if(wt->gfx.flags & WT_GFX_NODIRTY) {
+                       tree->draw(tree, &wt->gfx);
+               } else {
+                       if(tree->dirty) {
+                               tree->draw(tree, &wt->gfx);
+
+                               if(!tree->parent || !tree->parent->dirty) {
+                                       /* topmost dirty widget should update rects */
+                                       if(tree->type == WT_TYPE_WINDOW) {
+                                               struct wt_rect r;
+                                               calc_window_rect(&r, tree);
+                                               wt_add_upd_rect(&r);
+                                       } else {
+                                               wt_add_upd_rect(&tree->rect);
+                                       }
+                               }
+                       }
+               }
        }
 
        for(i=0; i<tree->num_child; i++) {
                wt_draw_tree(tree->child[i]);
        }
+
+       tree->dirty = 0;
 }
 
 void wt_draw(void)
 {
+       wt->num_upd = 0;
        wt_draw_tree(wt->root);
 }
 
+int wt_num_upd(void)
+{
+       return wt->num_upd;
+}
+
+struct wt_rect *wt_upd_rect(int idx)
+{
+       if(idx < 0 || idx >= wt->num_upd) {
+               return 0;
+       }
+       return wt->upd + idx;
+}
+
+void wt_add_upd_rect(struct wt_rect *r)
+{
+       int i;
+       struct wt_rect rect;
+
+       for(i=0; i<wt->num_upd; i++) {
+               if(wt_rect_overlap(wt->upd + i, r)) {
+                       rect = wt->upd[i];
+                       wt->upd[i] = wt->upd[--wt->num_upd];
+                       wt_rect_union(&rect, r);
+                       wt_add_upd_rect(&rect);
+                       return;
+               }
+       }
+
+       /* no overlaps found, add it if there is space, or union with existing if not */
+       if(wt->num_upd >= MAX_UPD_RECTS) {
+               wt_rect_union(wt->upd, r);
+       } else {
+               wt->upd[wt->num_upd++] = *r;
+       }
+}
+
+
 void wt_gfx_color(int cidx)
 {
        wt->gfx.color(wt->colors[cidx]);
@@ -161,11 +218,11 @@ void wt_gfx_frame(struct wt_rect *r, int style, int basecol)
                wt_gfx_fillrect(r);
        }
        wt_gfx_color(FRMSTYLE(style) == FRM_OUT ? basecol + 2 : basecol + 1);
-       wt_gfx_fillrect4i(r->x + 1, r->y + r->height - 1, r->width - 2, 1);
-       wt_gfx_fillrect4i(r->x + r->width - 1, r->y, 1, r->height);
+       wt_gfx_fillrect4i(r->x + 1, r->y + r->h - 1, r->w - 2, 1);
+       wt_gfx_fillrect4i(r->x + r->w - 1, r->y, 1, r->h);
        wt_gfx_color(FRMSTYLE(style) == FRM_OUT ? basecol + 1 : basecol + 2);
-       wt_gfx_fillrect4i(r->x + 1, r->y, r->width - 2, 1);
-       wt_gfx_fillrect4i(r->x, r->y, 1, r->height);
+       wt_gfx_fillrect4i(r->x + 1, r->y, r->w - 2, 1);
+       wt_gfx_fillrect4i(r->x, r->y, 1, r->h);
 }
 
 void wt_gfx_line(int x0, int y0, int x1, int y1)
@@ -177,6 +234,31 @@ void wt_rect(struct wt_rect *r, int x, int y, int w, int h)
 {
        r->x = x;
        r->y = y;
-       r->width = w;
-       r->height = h;
+       r->w = w;
+       r->h = h;
+}
+
+void wt_rect_union(struct wt_rect *a, struct wt_rect *b)
+{
+       int x1, y1;
+
+       x1 = a->x + a->w;
+       y1 = a->y + a->h;
+
+       if(b->x < a->x) a->x = b->x;
+       if(b->y < a->y) a->y = b->y;
+       if(b->x + b->w > x1) x1 = b->x + b->w;
+       if(b->y + b->h > y1) y1 = b->y + b->h;
+
+       a->w = x1 - a->x;
+       a->h = y1 - a->y;
+}
+
+int wt_rect_overlap(struct wt_rect *a, struct wt_rect *b)
+{
+       if(a->x > b->x + b->w) return 0;
+       if(b->x > a->x + a->w) return 0;
+       if(a->y > b->y + b->h) return 0;
+       if(b->y > a->x + a->h) return 0;
+       return 1;
 }