Enlightenment CVS committal Author : raster Project : e17 Module : apps/e
Dir : e17/apps/e/src/modules/dropshadow Modified Files: e_mod_main.c e_mod_main.h Log Message: heavily optimised shaped window dropshadow handling... MUCH faster for most common cases. =================================================================== RCS file: /cvsroot/enlightenment/e17/apps/e/src/modules/dropshadow/e_mod_main.c,v retrieving revision 1.16 retrieving revision 1.17 diff -u -3 -r1.16 -r1.17 --- e_mod_main.c 14 Apr 2005 11:46:17 -0000 1.16 +++ e_mod_main.c 21 Apr 2005 05:13:46 -0000 1.17 @@ -5,9 +5,6 @@ * * * bug in shadow_x < 0 and shadow_y < 0 needs to be fixed (not urgent though) * * add alpha-pixel only pixel space to image objects in evas and make use of it to save cpu and ram - * * when blurring ALSO cut out the overlayed rect frrom the blur algorithm - * * handle shaped windows efficiently (as possible). - * * share shadow pixels between shadow objects for square shapes if big enough to be split into 1 stretched images * * look into mmx for the blur function... * * handle other shadow pos cases where we cant use 4 objects (3 or 2). */ @@ -37,6 +34,7 @@ static Shadow *_ds_shadow_add(Dropshadow *ds, E_Container_Shape *es); static void _ds_shadow_obj_clear(Shadow *sh); static void _ds_shadow_obj_init(Shadow *sh); +static void _ds_shadow_obj_init_rects(Shadow *sh, Evas_List *rects); static void _ds_shadow_obj_shutdown(Shadow *sh); static void _ds_shadow_del(Shadow *sh); static void _ds_shadow_show(Shadow *sh); @@ -45,6 +43,7 @@ static void _ds_shadow_resize(Shadow *sh, int w, int h); static void _ds_shadow_shaperects(Shadow *sh); static int _ds_shadow_reshape(void *data); +static void _ds_edge_scan(Shpix *sp, Tilebuf *tb, int bsz, int q, int x1, int y1, int x2, int y2); static void _ds_shadow_recalc(Shadow *sh); static void _ds_config_darkness_set(Dropshadow *ds, double v); static void _ds_config_shadow_xy_set(Dropshadow *ds, int x, int y); @@ -57,6 +56,7 @@ static void _ds_shpix_free(Shpix *sp); static void _ds_shpix_fill(Shpix *sp, int x, int y, int w, int h, unsigned char val); static void _ds_shpix_blur(Shpix *sp, int x, int y, int w, int h, unsigned char *blur_lut, int blur_size); +static void _ds_shpix_blur_rects(Shpix *sp, Evas_List *rects, unsigned char *blur_lut, int blur_size); static void _ds_shpix_object_set(Shpix *sp, Evas_Object *o, int x, int y, int w, int h); static void _ds_shared_free(Dropshadow *ds); static void _ds_shared_use(Dropshadow *ds, Shadow *sh); @@ -65,7 +65,21 @@ static void _ds_shstore_free(Shstore *st); static void _ds_shstore_object_set(Shstore *st, Evas_Object *o); static void _ds_object_unset(Evas_Object *o); - +static int _tilebuf_x_intersect(Tilebuf *tb, int x, int w, int *x1, int *x2, int *x1_fill, int *x2_fill); +static int _tilebuf_y_intersect(Tilebuf *tb, int y, int h, int *y1, int *y2, int *y1_fill, int *y2_fill); +static int _tilebuf_intersect(int tsize, int tlen, int tnum, int x, int w, int *x1, int *x2, int *x1_fill, int *x2_fill); +static void _tilebuf_setup(Tilebuf *tb); +static Tilebuf *_tilebuf_new(int w, int h); +static void _tilebuf_free(Tilebuf *tb); +static void _tilebuf_set_tile_size(Tilebuf *tb, int tw, int th); +static void _tilebuf_get_tile_size(Tilebuf *tb, int *tw, int *th); +static int _tilebuf_add_redraw(Tilebuf *tb, int x, int y, int w, int h); +static void _tilebuf_clear(Tilebuf *tb); +static Evas_List *_tilebuf_get_render_rects(Tilebuf *tb); +static void _tilebuf_free_render_rects(Evas_List *rects); + +#define TILE(tb, x, y) ((tb)->tiles.tiles[((y) * (tb)->tiles.w) + (x)]) + /* public module routines. all modules must have these */ void * e_modapi_init(E_Module *m) @@ -607,7 +621,6 @@ sh->ds = ds; sh->shape = es; e_object_ref(E_OBJECT(sh->shape)); - _ds_shadow_obj_init(sh); return sh; } @@ -617,6 +630,8 @@ E_Container *con; int i; + if (sh->initted) return; + sh->initted = 1; con = e_container_shape_container_get(sh->shape); for (i = 0; i < 4; i++) { @@ -628,6 +643,48 @@ evas_object_color_set(sh->object[i], 255, 255, 255, 255 * sh->ds->conf->shadow_darkness); + if (sh->visible) + evas_object_show(sh->object[i]); + } +} + +static void +_ds_shadow_obj_init_rects(Shadow *sh, Evas_List *rects) +{ + E_Container *con; + Evas_List *l; + int i; + + if (sh->initted) return; + sh->initted = 1; + con = e_container_shape_container_get(sh->shape); + for (l = rects; l; l = l->next) + { + E_Rect *r; + Evas_Object *o; + Shadow_Object *so; + + r = l->data; + so = calloc(1, sizeof(Shadow_Object)); + if (so) + { + o = evas_object_image_add(con->bg_evas); + evas_object_layer_set(o, 10); + evas_object_pass_events_set(o, 1); + evas_object_move(o, r->x, r->y); + evas_object_resize(o, r->w, r->h); + evas_object_color_set(o, + 255, 255, 255, + 255 * sh->ds->conf->shadow_darkness); + if (sh->visible) + evas_object_show(o); + so->obj = o; + so->x = r->x; + so->y = r->y; + so->w = r->w; + so->h = r->h; + sh->object_list = evas_list_append(sh->object_list, so); + } } } @@ -635,6 +692,7 @@ _ds_shadow_obj_clear(Shadow *sh) { int i; + Evas_List *l; for (i = 0; i < 4; i++) { @@ -646,6 +704,13 @@ _ds_shared_unuse(sh->ds); sh->use_shared = 0; } + for (l = sh->object_list; l; l = l->next) + { + Shadow_Object *so; + + so = l->data; + _ds_object_unset(so->obj); + } } @@ -654,6 +719,8 @@ { int i; + if (!sh->initted) return; + sh->initted = 0; for (i = 0; i < 4; i++) { if (sh->object[i]) @@ -668,6 +735,15 @@ _ds_shared_unuse(sh->ds); sh->use_shared = 0; } + while (sh->object_list) + { + Shadow_Object *so; + + so = sh->object_list->data; + evas_object_del(so->obj); + free(so); + sh->object_list = evas_list_remove_list(sh->object_list, sh->object_list); + } } static void @@ -687,60 +763,112 @@ static void _ds_shadow_show(Shadow *sh) { - if (sh->square) + Evas_List *l; + + _ds_shadow_obj_init(sh); + if (!sh->object_list) { - int i; - - for (i = 0; i < 4; i++) - evas_object_show(sh->object[i]); + if (sh->square) + { + int i; + + for (i = 0; i < 4; i++) + evas_object_show(sh->object[i]); + } + else + { + evas_object_show(sh->object[0]); + } } else { - evas_object_show(sh->object[0]); + for (l = sh->object_list; l; l = l->next) + { + Shadow_Object *so; + + so = l->data; + evas_object_show(so->obj); + } } + sh->visible = 1; } static void _ds_shadow_hide(Shadow *sh) { - if (sh->square) + Evas_List *l; + + _ds_shadow_obj_init(sh); + if (!sh->object_list) { - int i; - - for (i = 0; i < 4; i++) - evas_object_hide(sh->object[i]); + if (sh->square) + { + int i; + + for (i = 0; i < 4; i++) + evas_object_hide(sh->object[i]); + } + else + { + evas_object_hide(sh->object[0]); + } } else { - evas_object_hide(sh->object[0]); + for (l = sh->object_list; l; l = l->next) + { + Shadow_Object *so; + + so = l->data; + evas_object_hide(so->obj); + } } + sh->visible = 0; } static void _ds_shadow_move(Shadow *sh, int x, int y) { + Evas_List *l; + + _ds_shadow_obj_init(sh); sh->x = x; sh->y = y; - if ((sh->square) && (!sh->toosmall)) + if (!sh->object_list) { - evas_object_move(sh->object[0], - sh->x + sh->ds->conf->shadow_x - sh->ds->conf->blur_size, - sh->y + sh->ds->conf->shadow_y - sh->ds->conf->blur_size); - evas_object_move(sh->object[1], - sh->x + sh->ds->conf->shadow_x - sh->ds->conf->blur_size, - sh->y); - evas_object_move(sh->object[2], - sh->x + sh->w, - sh->y); - evas_object_move(sh->object[3], - sh->x + sh->ds->conf->shadow_x - sh->ds->conf->blur_size, - sh->y + sh->h); + if ((sh->square) && (!sh->toosmall)) + { + evas_object_move(sh->object[0], + sh->x + sh->ds->conf->shadow_x - sh->ds->conf->blur_size, + sh->y + sh->ds->conf->shadow_y - sh->ds->conf->blur_size); + evas_object_move(sh->object[1], + sh->x + sh->ds->conf->shadow_x - sh->ds->conf->blur_size, + sh->y); + evas_object_move(sh->object[2], + sh->x + sh->w, + sh->y); + evas_object_move(sh->object[3], + sh->x + sh->ds->conf->shadow_x - sh->ds->conf->blur_size, + sh->y + sh->h); + } + else + { + evas_object_move(sh->object[0], + sh->x + sh->ds->conf->shadow_x - sh->ds->conf->blur_size, + sh->y + sh->ds->conf->shadow_y - sh->ds->conf->blur_size); + } } else { - evas_object_move(sh->object[0], - sh->x + sh->ds->conf->shadow_x - sh->ds->conf->blur_size, - sh->y + sh->ds->conf->shadow_y - sh->ds->conf->blur_size); + for (l = sh->object_list; l; l = l->next) + { + Shadow_Object *so; + + so = l->data; + evas_object_move(so->obj, + sh->x + so->x + sh->ds->conf->shadow_x - sh->ds->conf->blur_size, + sh->y + so->y + sh->ds->conf->shadow_y - sh->ds->conf->blur_size); + } } } @@ -749,6 +877,7 @@ { unsigned char toosmall = 0; + _ds_shadow_obj_init(sh); if ((w < ((sh->ds->conf->blur_size * 2) + 2)) || (h < ((sh->ds->conf->blur_size * 2) + 2))) toosmall = 1; @@ -758,30 +887,33 @@ sh->reshape = 1; if ((sh->square) && (!sh->toosmall)) { - evas_object_move(sh->object[0], - sh->x + sh->ds->conf->shadow_x - sh->ds->conf->blur_size, - sh->y + sh->ds->conf->shadow_y - sh->ds->conf->blur_size); - evas_object_move(sh->object[1], - sh->x + sh->ds->conf->shadow_x - sh->ds->conf->blur_size, - sh->y); - evas_object_move(sh->object[2], - sh->x + sh->w, - sh->y); - evas_object_move(sh->object[3], - sh->x + sh->ds->conf->shadow_x - sh->ds->conf->blur_size, - sh->y + sh->h); - - evas_object_resize(sh->object[0], sh->w + (sh->ds->conf->blur_size) * 2, sh->ds->conf->blur_size - sh->ds->conf->shadow_y); - evas_object_image_fill_set(sh->object[0], 0, 0, sh->w + (sh->ds->conf->blur_size) * 2, sh->ds->conf->blur_size - sh->ds->conf->shadow_y); - - evas_object_resize(sh->object[1], sh->ds->conf->blur_size - sh->ds->conf->shadow_x, sh->h); - evas_object_image_fill_set(sh->object[1], 0, 0, sh->ds->conf->blur_size - sh->ds->conf->shadow_x, sh->h); - - evas_object_resize(sh->object[2], sh->ds->conf->shadow_x + sh->ds->conf->blur_size, sh->h); - evas_object_image_fill_set(sh->object[2], 0, 0, sh->ds->conf->blur_size + sh->ds->conf->shadow_x, sh->h); - - evas_object_resize(sh->object[3], sh->w + (sh->ds->conf->blur_size * 2), sh->ds->conf->blur_size + sh->ds->conf->shadow_y); - evas_object_image_fill_set(sh->object[3], 0, 0, sh->w + (sh->ds->conf->blur_size * 2), sh->ds->conf->blur_size + sh->ds->conf->shadow_y); + if (!sh->object_list) + { + evas_object_move(sh->object[0], + sh->x + sh->ds->conf->shadow_x - sh->ds->conf->blur_size, + sh->y + sh->ds->conf->shadow_y - sh->ds->conf->blur_size); + evas_object_move(sh->object[1], + sh->x + sh->ds->conf->shadow_x - sh->ds->conf->blur_size, + sh->y); + evas_object_move(sh->object[2], + sh->x + sh->w, + sh->y); + evas_object_move(sh->object[3], + sh->x + sh->ds->conf->shadow_x - sh->ds->conf->blur_size, + sh->y + sh->h); + + evas_object_resize(sh->object[0], sh->w + (sh->ds->conf->blur_size) * 2, sh->ds->conf->blur_size - sh->ds->conf->shadow_y); + evas_object_image_fill_set(sh->object[0], 0, 0, sh->w + (sh->ds->conf->blur_size) * 2, sh->ds->conf->blur_size - sh->ds->conf->shadow_y); + + evas_object_resize(sh->object[1], sh->ds->conf->blur_size - sh->ds->conf->shadow_x, sh->h); + evas_object_image_fill_set(sh->object[1], 0, 0, sh->ds->conf->blur_size - sh->ds->conf->shadow_x, sh->h); + + evas_object_resize(sh->object[2], sh->ds->conf->shadow_x + sh->ds->conf->blur_size, sh->h); + evas_object_image_fill_set(sh->object[2], 0, 0, sh->ds->conf->blur_size + sh->ds->conf->shadow_x, sh->h); + + evas_object_resize(sh->object[3], sh->w + (sh->ds->conf->blur_size * 2), sh->ds->conf->blur_size + sh->ds->conf->shadow_y); + evas_object_image_fill_set(sh->object[3], 0, 0, sh->w + (sh->ds->conf->blur_size * 2), sh->ds->conf->blur_size + sh->ds->conf->shadow_y); + } } else { @@ -820,6 +952,49 @@ } static void +_ds_edge_scan(Shpix *sp, Tilebuf *tb, int bsz, int q, int x1, int y1, int x2, int y2) +{ + int x, y; + unsigned char *ptr, *pptr; + int val; + + if (x1 == x2) /* scan vert */ + { + pptr = sp->pix + ((y1 - 1) * sp->w) + x1; + ptr = sp->pix + (y1 * sp->w) + x1; + for (y = y1; y <= y2; y++) + { + val = ptr[0] + ptr[-1] + pptr[0] + pptr[-1]; + if ((val != 0) && (val != (255 * 4))) + _tilebuf_add_redraw(tb, + x1 - ((bsz + 1) / q), + y - ((bsz + 1) / q), + ((bsz + 1) * 2) / q, + ((bsz + 1) * 2) / q); + ptr += sp->w; + pptr += sp->h; + } + } + else if (y1 == y2) /* scan horiz */ + { + pptr = sp->pix + ((y1 - 1) * sp->w) + x1; + ptr = sp->pix + (y1 * sp->w) + x1; + for (x = x1; x <= x2; x++) + { + val = ptr[0] + ptr[-1] + pptr[0] + pptr[-1]; + if ((val != 0) && (val != (255 * 4))) + _tilebuf_add_redraw(tb, + x - ((bsz + 1) / q), + y1 - ((bsz + 1) / q), + ((bsz + 1) * 2) / q, + ((bsz + 1) * 2) / q); + ptr++; + pptr++; + } + } +} + +static void _ds_shadow_recalc(Shadow *sh) { Evas_List *rects = NULL; @@ -832,7 +1007,7 @@ sh->toosmall = 0; if ((rects) || (sh->toosmall)) { - Evas_List *l; + Evas_List *l, *ll; Shpix *sp; int shw, shh, bsz, shx, shy; int x1, y1, x2, y2; @@ -844,14 +1019,6 @@ else sh->square = 0; - /* FIXME: find "minimum" center of the shape rects - if any */ - /* idea - take rects, run thru list. for each rect start x - * check all rects with a y > than this one. (will come later - * in the list). keep track of the last y point and id this rect x - * spans this line then advance new y point by rect size if it - * immediately joins it... - - */ shx = sh->ds->conf->shadow_x; shy = sh->ds->conf->shadow_y; shw = sh->w; @@ -867,8 +1034,9 @@ sp = _ds_shpix_new((shw + (bsz * 2)) / q, (shh + (bsz * 2)) / q); if (sp) { - int slx, sly, slw, slh; + Tilebuf *tb; + _ds_shadow_obj_shutdown(sh); if (!rects) { /* FIXME; rounding errors - fix as below in else{} */ @@ -894,83 +1062,132 @@ } } - e_container_shape_solid_rect_get(sh->shape, &slx, &sly, &slw, &slh); - slx += bsz; - sly += bsz; - slw -= bsz * 2; - slh -= bsz * 2; - slw = (slw - 1 + slx) / q; - slh = (slh - 1 + sly) / q; - slx /= q; - sly /= q; - slw = slw - slx + 1; - slh = slh - sly + 1; - if ((slw > 0) && (slh > 0)) + tb = _tilebuf_new((shw + (bsz * 2)) / q, (shh + (bsz * 2)) / q); + if (tb) { - /* FIXME: handle as 4 separate shadow obj's - not 1 */ - _ds_shpix_blur(sp, 0, 0, - (shw + (bsz * 2)) / q, - (shh + (bsz * 2)) / q, - sh->ds->table.gauss2, (bsz) / q); - _ds_shpix_object_set(sp, sh->object[0], 0, 0, - (shw + (bsz * 2)) / q, (shh + (bsz * 2)) / q); - - evas_object_move(sh->object[0], - sh->x + shx - bsz, - sh->y + shy - bsz); - evas_object_image_smooth_scale_set(sh->object[0], 1); - evas_object_image_border_set(sh->object[0], - 0, 0, 0, 0); - evas_object_resize(sh->object[0], - sh->w + (bsz * 2), - sh->h + (bsz * 2)); - evas_object_image_fill_set(sh->object[0], 0, 0, - sh->w + (bsz * 2), - sh->h + (bsz * 2)); - _ds_object_unset(sh->object[1]); - _ds_object_unset(sh->object[2]); - _ds_object_unset(sh->object[3]); - _ds_shpix_free(sp); + Evas_List *brects; - if (evas_object_visible_get(sh->object[0])) + _tilebuf_set_tile_size(tb, 16 / q, 16 / q); + /* find edges */ + if (rects) { - evas_object_hide(sh->object[1]); - evas_object_hide(sh->object[2]); - evas_object_hide(sh->object[3]); + for (l = rects; l; l = l->next) + { + E_Rect *r; + + r = l->data; + x1 = (bsz + r->x) / q; + y1 = (bsz + r->y) / q; + x2 = (bsz + r->x + r->w - 1) / q; + y2 = (bsz + r->y + r->h - 1) / q; + if (x1 < 1) x1 = 1; + if (x1 >= (sp->w - 1)) x1 = (sp->w - 1) - 1; + if (x2 < 1) x1 = 1; + if (x2 >= (sp->w - 1)) x2 = (sp->w - 1) - 1; + if (y1 < 1) y1 = 1; + if (y1 >= (sp->h - 1)) y1 = (sp->h - 1) - 1; + if (y2 < 1) y1 = 1; + if (y2 >= (sp->h - 1)) y2 = (sp->h - 1) - 1; + _ds_edge_scan(sp, tb, bsz, q, x1, y1, x2 + 1, y1); + _ds_edge_scan(sp, tb, bsz, q, x1, y2 + 1, x2 + 1, y2 + 1); + _ds_edge_scan(sp, tb, bsz, q, x1, y1, x1, y2 + 1); + _ds_edge_scan(sp, tb, bsz, q, x2 + 1, y1, x2 + 1, y2 + 1); + } } - } - else + /* its a rect - just add the rect outline */ + else + { + _tilebuf_add_redraw(tb, + 0, + 0, + (shw + (bsz * 2)) / q, + ((bsz + 1) * 2) / q); + _tilebuf_add_redraw(tb, + 0, + ((bsz + 1) * 2) / q, + ((bsz + 1) * 2) / q, + sp->h - (2 * (((bsz + 1) * 2) / q))); + _tilebuf_add_redraw(tb, + sp->w - (((bsz + 1) * 2) / q), + ((bsz + 1) * 2) / q, + ((bsz + 1) * 2) / q, + sp->h - (2 * (((bsz + 1) * 2) / q))); + _tilebuf_add_redraw(tb, + 0, + sp->h - (((bsz + 1) * 2) / q), + (shw + (bsz * 2)) / q, + ((bsz + 1) * 2) / q); + } + brects = _tilebuf_get_render_rects(tb); +#if 0 /* enable this to see how dropshadow minimises what it has to go blur */ + printf("BRTECTS:\n"); + for (l = brects; l; l = l->next) + { + E_Rect *r; + r = l->data; + _ds_shpix_fill(sp, r->x, r->y, r->w, r->h, 255); +/* printf(" %i,%i %ix%i\n", r->x, r->y, r->w, r->h);*/ + } + printf("done\n"); +#else + _ds_shpix_blur_rects(sp, brects, + sh->ds->table.gauss2, (bsz) / q); +#endif + _ds_shadow_obj_init_rects(sh, brects); + for (l = brects, ll = sh->object_list; + l && ll; + l = l->next, ll = ll->next) + { + Shadow_Object *so; + E_Rect *r; + int x, y, w, h; + + r = l->data; + so = ll->data; + evas_object_image_smooth_scale_set(so->obj, 1); + evas_object_move(so->obj, + sh->x + so->x + sh->ds->conf->shadow_x - sh->ds->conf->blur_size, + sh->y + so->y + sh->ds->conf->shadow_y - sh->ds->conf->blur_size); + evas_object_resize(so->obj, + r->w, r->h); + evas_object_image_fill_set(so->obj, + 0, 0, + r->w, r->h); + if (sh->visible) + evas_object_show(so->obj); + _ds_shpix_object_set(sp, so->obj, + r->x, r->y, r->w, r->h); + } +#if 0 + _ds_shpix_object_set(sp, sh->object[0], 0, 0, + (shw + (bsz * 2)) / q, (shh + (bsz * 2)) / q); + evas_object_move(sh->object[0], + sh->x + shx - bsz, + sh->y + shy - bsz); + evas_object_image_smooth_scale_set(sh->object[0], 1); + evas_object_image_border_set(sh->object[0], + 0, 0, 0, 0); + evas_object_resize(sh->object[0], + sh->w + (bsz * 2), + sh->h + (bsz * 2)); + evas_object_image_fill_set(sh->object[0], 0, 0, + sh->w + (bsz * 2), + sh->h + (bsz * 2)); + _ds_object_unset(sh->object[1]); + _ds_object_unset(sh->object[2]); + _ds_object_unset(sh->object[3]); + + if (evas_object_visible_get(sh->object[0])) { - _ds_shpix_blur(sp, 0, 0, - (shw + (bsz * 2)) / q, - (shh + (bsz * 2)) / q, - sh->ds->table.gauss2, (bsz) / q); - _ds_shpix_object_set(sp, sh->object[0], 0, 0, - (shw + (bsz * 2)) / q, (shh + (bsz * 2)) / q); - - evas_object_move(sh->object[0], - sh->x + shx - bsz, - sh->y + shy - bsz); - evas_object_image_smooth_scale_set(sh->object[0], 1); - evas_object_image_border_set(sh->object[0], - 0, 0, 0, 0); - evas_object_resize(sh->object[0], - sh->w + (bsz * 2), - sh->h + (bsz * 2)); - evas_object_image_fill_set(sh->object[0], 0, 0, - sh->w + (bsz * 2), - sh->h + (bsz * 2)); - _ds_object_unset(sh->object[1]); - _ds_object_unset(sh->object[2]); - _ds_object_unset(sh->object[3]); + evas_object_hide(sh->object[1]); + evas_object_hide(sh->object[2]); + evas_object_hide(sh->object[3]); + } +#endif _ds_shpix_free(sp); - if (evas_object_visible_get(sh->object[0])) - { - evas_object_hide(sh->object[1]); - evas_object_hide(sh->object[2]); - evas_object_hide(sh->object[3]); - } + _tilebuf_free_render_rects(brects); + _tilebuf_free(tb); } } } @@ -978,6 +1195,7 @@ { int shw, shh, bsz, shx, shy; + _ds_shadow_obj_init(sh); sh->square = 1; shx = sh->ds->conf->shadow_x; @@ -1484,6 +1702,84 @@ } static void +_ds_shpix_blur_rects(Shpix *sp, Evas_List *rects, unsigned char *blur_lut, int blur_size) +{ + Shpix *sp2; + Evas_List *l; + + if (!sp) return; + if (blur_size < 1) return; + + sp2 = _ds_shpix_new(sp->w, sp->h); + if (!sp2) return; + /* FIXME: copy the inverse rects from rects list */ + memcpy(sp2->pix, sp->pix, sp->w * sp->h); + for (l = rects; l; l = l->next) + { + E_Rect *r; + int x, y, w, h; + + r = l->data; + x = r->x; y = r->y; w = r->w; h = r->h; + if ((w < 1) || (h < 1)) continue; + + if (x < 0) + { + w += x; + x = 0; + if (w < 1) continue; + } + if (x >= sp->w) continue; + if ((x + w) > (sp->w)) w = sp->w - x; + + if (y < 0) + { + h += y; + y = 0; + if (h < 1) continue; + } + if (y >= sp->h) continue; + if ((y + h) > (sp->h)) h = sp->h - y; + _ds_gauss_blur_h(sp->pix, sp2->pix, + sp->w, sp->h, + blur_lut, blur_size, + x, y, x + w, y + h); + } + for (l = rects; l; l = l->next) + { + E_Rect *r; + int x, y, w, h; + + r = l->data; + x = r->x; y = r->y; w = r->w; h = r->h; + if ((w < 1) || (h < 1)) continue; + + if (x < 0) + { + w += x; + x = 0; + if (w < 1) continue; + } + if (x >= sp->w) continue; + if ((x + w) > (sp->w)) w = sp->w - x; + + if (y < 0) + { + h += y; + y = 0; + if (h < 1) continue; + } + if (y >= sp->h) continue; + if ((y + h) > (sp->h)) h = sp->h - y; + _ds_gauss_blur_v(sp2->pix, sp->pix, + sp2->w, sp2->h, + blur_lut, blur_size, + x, y, x + w, y + h); + } + _ds_shpix_free(sp2); +} + +static void _ds_shpix_object_set(Shpix *sp, Evas_Object *o, int x, int y, int w, int h) { unsigned char *p; @@ -1726,3 +2022,237 @@ evas_object_image_data_set(o, NULL); evas_object_image_size_set(o, 0, 0); } + +static int +_tilebuf_x_intersect(Tilebuf *tb, int x, int w, int *x1, int *x2, int *x1_fill, int *x2_fill) +{ + return _tilebuf_intersect(tb->tile_size.w, tb->outbuf_w, tb->tiles.w, + x, w, x1, x2, x1_fill, x2_fill); +} + +static int +_tilebuf_y_intersect(Tilebuf *tb, int y, int h, int *y1, int *y2, int *y1_fill, int *y2_fill) +{ + return _tilebuf_intersect(tb->tile_size.h, tb->outbuf_h, tb->tiles.h, + y, h, y1, y2, y1_fill, y2_fill); +} + +static int +_tilebuf_intersect(int tsize, int tlen, int tnum, int x, int w, int *x1, int *x2, int *x1_fill, int *x2_fill) +{ + int p1, p2; + + /* initial clip out of region */ + if ((x + w) <= 0) return 0; + if (x >= tlen) return 0; + + /* adjust x & w so it all fits in region */ + if (x < 0) + { + w += x; + x = 0; + } + if (w < 0) return 0; + if ((x + w) > tlen) w = tlen - x; + + /* now figure if the first edge is fully filling its tile */ + p1 = (x) / tsize; + if ((p1 * tsize) == (x)) *x1_fill = 1; + else *x1_fill = 0; + *x1 = p1; + + /* now figure if the last edge is fully filling its tile */ + p2 = (x + w - 1) / tsize; + if (((p2 + 1) * tsize) == (x + w)) *x2_fill = 1; + else *x2_fill = 0; + *x2 = p2; + + return 1; + tnum = 0; +} + +static void +_tilebuf_setup(Tilebuf *tb) +{ + if (tb->tiles.tiles) free(tb->tiles.tiles); + tb->tiles.tiles = NULL; + + tb->tiles.w = (tb->outbuf_w + (tb->tile_size.w - 1)) / tb->tile_size.w; + tb->tiles.h = (tb->outbuf_h + (tb->tile_size.h - 1)) / tb->tile_size.h; + + tb->tiles.tiles = malloc(tb->tiles.w * tb->tiles.h * sizeof(Tilebuf_Tile)); + + if (!tb->tiles.tiles) + { + tb->tiles.w = 0; + tb->tiles.h = 0; + return; + } + memset(tb->tiles.tiles, 0, tb->tiles.w * tb->tiles.h * sizeof(Tilebuf_Tile)); +} + +static Tilebuf * +_tilebuf_new(int w, int h) +{ + Tilebuf *tb; + + tb = calloc(1, sizeof(Tilebuf)); + if (!tb) return NULL; + + tb->tile_size.w = 16; + tb->tile_size.h = 16; + tb->outbuf_w = w; + tb->outbuf_h = h; + + return tb; +} + +static void +_tilebuf_free(Tilebuf *tb) +{ + if (tb->tiles.tiles) free(tb->tiles.tiles); + free(tb); +} + +static void +_tilebuf_set_tile_size(Tilebuf *tb, int tw, int th) +{ + tb->tile_size.w = tw; + tb->tile_size.h = th; + _tilebuf_setup(tb); +} + +static void +_tilebuf_get_tile_size(Tilebuf *tb, int *tw, int *th) +{ + if (tw) *tw = tb->tile_size.w; + if (th) *th = tb->tile_size.h; +} + +static int +_tilebuf_add_redraw(Tilebuf *tb, int x, int y, int w, int h) +{ + int tx1, tx2, ty1, ty2, tfx1, tfx2, tfy1, tfy2, xx, yy; + int num; + + num = 0; + if (_tilebuf_x_intersect(tb, x, w, &tx1, &tx2, &tfx1, &tfx2) && + _tilebuf_y_intersect(tb, y, h, &ty1, &ty2, &tfy1, &tfy2)) + { + for (yy = ty1; yy <= ty2; yy++) + { + Tilebuf_Tile *tbt; + + tbt = &(TILE(tb, tx1, yy)); + for (xx = tx1; xx <= tx2; xx++) + { + tbt->redraw = 1; + num++; + tbt++; + } + } + } + return num; +} + +static void +_tilebuf_clear(Tilebuf *tb) +{ + if (!tb->tiles.tiles) return; + memset(tb->tiles.tiles, 0, tb->tiles.w * tb->tiles.h * sizeof(Tilebuf_Tile)); +} + +static Evas_List * +_tilebuf_get_render_rects(Tilebuf *tb) +{ + Evas_List *rects = NULL; + int x, y; + + for (y = 0; y < tb->tiles.h; y++) + { + for (x = 0; x < tb->tiles.w; x++) + { + if (TILE(tb, x, y).redraw) + { + int can_expand_x = 1, can_expand_y = 1; + E_Rect *r = NULL; + int xx = 0, yy = 0; + + r = calloc(1, sizeof(E_Rect)); + /* amalgamate tiles */ + while (can_expand_x) + { + xx++; + if ((x + xx) >= tb->tiles.w) + can_expand_x = 0; + else if (!(TILE(tb, x + xx, y).redraw)) + can_expand_x = 0; + if (can_expand_x) + TILE(tb, x + xx, y).redraw = 0; + } + while (can_expand_y) + { + int i; + + yy++; + if ((y + yy) >= tb->tiles.h) + can_expand_y = 0; + if (can_expand_y) + { + for (i = x; i < x + xx; i++) + { + if (!(TILE(tb, i, y + yy).redraw)) + { + can_expand_y = 0; + break; + } + } + } + if (can_expand_y) + { + for (i = x; i < x + xx; i++) + TILE(tb, i, y + yy).redraw = 0; + } + } + TILE(tb, x, y).redraw = 0; + r->x = x * tb->tile_size.w; + r->y = y * tb->tile_size.h; + r->w = (xx) * tb->tile_size.w; + r->h = (yy) * tb->tile_size.h; + if (r->x < 0) + { + r->w += r->x; + r->x = 0; + } + if ((r->x + r->w) > tb->outbuf_w) + r->w = tb->outbuf_w - r->x; + if (r->y < 0) + { + r->h += r->y; + r->y = 0; + } + if ((r->y + r->h) > tb->outbuf_h) + r->h = tb->outbuf_h - r->y; + if ((r->w <= 0) || (r->h <= 0)) + free(r); + else + rects = evas_list_append(rects, r); + x = x + (xx - 1); + } + } + } + return rects; +} + +static void +_tilebuf_free_render_rects(Evas_List *rects) +{ + while (rects) + { + E_Rect *r; + + r = rects->data; + rects = evas_list_remove_list(rects, rects); + free(r); + } +} =================================================================== RCS file: /cvsroot/enlightenment/e17/apps/e/src/modules/dropshadow/e_mod_main.h,v retrieving revision 1.7 retrieving revision 1.8 diff -u -3 -r1.7 -r1.8 --- e_mod_main.h 13 Apr 2005 15:52:34 -0000 1.7 +++ e_mod_main.h 21 Apr 2005 05:13:46 -0000 1.8 @@ -1,11 +1,14 @@ #ifndef E_MOD_MAIN_H #define E_MOD_MAIN_H -typedef struct _Shpix Shpix; -typedef struct _Shstore Shstore; -typedef struct _Config Config; -typedef struct _Dropshadow Dropshadow; -typedef struct _Shadow Shadow; +typedef struct _Shpix Shpix; +typedef struct _Shstore Shstore; +typedef struct _Config Config; +typedef struct _Dropshadow Dropshadow; +typedef struct _Shadow Shadow; +typedef struct _Shadow_Object Shadow_Object; +typedef struct _Tilebuf Tilebuf; +typedef struct _Tilebuf_Tile Tilebuf_Tile; struct _Shpix { @@ -58,10 +61,40 @@ Evas_Object *object[4]; + Evas_List *object_list; + + unsigned char initted : 1; unsigned char reshape : 1; unsigned char square : 1; unsigned char toosmall : 1; unsigned char use_shared : 1; + unsigned char visible : 1; +}; + +struct _Shadow_Object +{ + int x, y, w, h; + Evas_Object *obj; +}; + +struct _Tilebuf +{ + int outbuf_w; + int outbuf_h; + + struct { + int w, h; + } tile_size; + + struct { + int w, h; + Tilebuf_Tile *tiles; + } tiles; +}; + +struct _Tilebuf_Tile +{ + int redraw : 1; }; EAPI void *e_modapi_init (E_Module *m); ------------------------------------------------------- This SF.Net email is sponsored by: New Crystal Reports XI. Version 11 adds new functionality designed to reduce time involved in creating, integrating, and deploying reporting solutions. Free runtime info, new features, or free trial, at: http://www.businessobjects.com/devxi/728 _______________________________________________ enlightenment-cvs mailing list enlightenment-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs