123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409 |
- #include <precomp.h>
- #include <tataki/blending/blending.h>
- #include "fx_dmove.h"
- #include <api/skin/widgets/layer.h>
- #include <math.h>
- #define M_PI 3.14159265358979323846
- FxDynamicMove::FxDynamicMove()
- : fx_canvas(4,4)
- {
- need_flush=false;
- cache_w=cache_h=4;
- m_wmul=0;
- m_tab=0;
- last_m_tab=0;
- m_lastxres=m_lastyres=m_lastpitch=0;
- m_xres=16;
- m_yres=16;
- last_w=last_h=-1;
- inited=0;
- subpixel=1;
- rectcoords=0;
- blend=0;
- wrap=0;
- need_alpha = 1;
- alpha_table = (double *)MALLOC((m_xres+1)*(m_yres+1)*sizeof(double));
- alpha_once= 0;
- can_cache = 1;
- m_lastw = 0;
- m_lasth = 0;
- m_tab_size = 0;
- }
- FxDynamicMove::~FxDynamicMove()
- {
- FREE(m_wmul);
- FREE(m_tab);
- FREE(last_m_tab);
- FREE(alpha_table);
- }
- int FxDynamicMove::render(Layer *l, int _w, int _h, int *input, int tw, int th, int twpitch)
- {
- double var_x;
- double var_y;
- double var_d;
- double var_r;
- /*if (fx_canvas) {
- HDC dc;
- dc = GetDC(NULL);
- BitBlt(dc, 0, 0, w, h, fx_canvas->getHDC(),0, 0, SRCCOPY);
- ReleaseDC(NULL, dc);
- }*/
- prepareCanvas(_w, _h);
- int w_adj=(tw-2)<<16;
- int h_adj=(th-2)<<16;
- int dowrap=wrap;
- int XRES=m_xres+1;
- int YRES=m_yres+1;
- int ignore_last_compare=0;
- if (XRES > _w) XRES=_w;
- if (YRES > _h) YRES=_h;
- if (XRES < 2) XRES=2;
- if (XRES > 256) XRES=256;
- if (YRES < 2) YRES=2;
- if (YRES > 256) YRES=256;
- if (need_flush || m_lasth != th || m_lastpitch != twpitch || m_lastw != tw || !m_tab || !m_wmul || m_lastxres != XRES || m_lastyres != YRES)
- {
- int y;
- m_lastxres = XRES;
- m_lastyres = YRES;
- m_lastw=tw;
- m_lasth=th;
- m_lastpitch=twpitch;
- FREE(m_wmul);
- m_wmul=(int*)MALLOC(sizeof(int)*th);
- for (y = 0; y < th; y ++) m_wmul[y]=y*twpitch;
- FREE(m_tab);
- FREE(last_m_tab);
- m_tab_size = (XRES*YRES*3 + XRES*6 + 6)*sizeof(int);
- m_tab=(int*)MALLOC(m_tab_size);
- last_m_tab=(int*)MALLOC(m_tab_size);
- ignore_last_compare=1;
- }
- need_flush=false;
- int isblend=blend;
- int issub=subpixel;
- if (!issub)
- {
- w_adj=(tw-1)<<16;
- h_adj=(th-1)<<16;
- }
- if (w_adj<0) w_adj=0;
- if (h_adj<0) h_adj=0;
- {
- int x;
- int y;
- int *tabptr=m_tab;
- double xsc=2.0/tw,ysc=2.0/th;
- double dw2=((double)tw*32768.0);
- double dh2=((double)th*32768.0);
- double max_screen_d=sqrt((double)(tw*tw+th*th))*0.5;
-
- double divmax_d=1.0/max_screen_d;
- max_screen_d *= 65536.0;
- double _var_alpha = 0.50;
- int yc_pos, yc_dpos, xc_pos, xc_dpos;
- yc_pos=0;
- xc_dpos = (tw<<16)/(XRES-1);
- yc_dpos = (th<<16)/(YRES-1);
- for (y = 0; y < YRES; y ++)
- {
- xc_pos=0;
- for (x = 0; x < XRES; x ++)
- {
- double xd,yd;
-
- xd=((double)xc_pos-dw2)*(1.0/65536.0);
- yd=((double)yc_pos-dh2)*(1.0/65536.0);
- xc_pos+=xc_dpos;
- var_x=xd*xsc;
- var_y=yd*ysc;
- var_d=sqrt(xd*xd+yd*yd)*divmax_d;
- var_r=atan2(yd,xd) + M_PI*0.5;
- double _var_r=var_r, _var_d=var_d;
- if (isblend && need_alpha) {
- _var_alpha = l->fx_onGetPixelA(var_r, var_d, var_x, var_y);
- alpha_table[y*YRES+x] = _var_alpha;
- } else if (isblend && !need_alpha) {
- _var_alpha = alpha_table[y*YRES+x];
- }
- if (!rectcoords) {
- double t_var_r = l->fx_onGetPixelR(var_r, var_d, var_x, var_y);
- _var_d = l->fx_onGetPixelD(var_r, var_d, var_x, var_y);
- _var_r = t_var_r;
- }
- double _var_x=var_x, _var_y=var_y;
- if (rectcoords) {
- double t_var_x = l->fx_onGetPixelX(var_r, var_d, var_x, var_y);
- _var_y = l->fx_onGetPixelY(var_r, var_d, var_x, var_y);
- _var_x = t_var_x;
- }
- int tmp1,tmp2,tmp3;
- if (!rectcoords)
- {
- _var_d *= max_screen_d;
- _var_r -= M_PI*0.5;
- tmp1=(int) (dw2 + cos(_var_r) * _var_d);
- tmp2=(int) (dh2 + sin(_var_r) * _var_d);
- }
- else
- {
- tmp1=(int) ((_var_x+1.0)*dw2);
- tmp2=(int) ((_var_y+1.0)*dh2);
- }
- if (!dowrap)
- {
- if (tmp1 < 0) tmp1=0;
- if (tmp1 > w_adj) tmp1=w_adj;
- if (tmp2 < 0) tmp2=0;
- if (tmp2 > h_adj) tmp2=h_adj;
- }
- *tabptr++ = tmp1;
- *tabptr++ = tmp2;
- tmp3 = (int)(_var_alpha*65536.0*256.0);
- if (tmp3 < 0) tmp3=0;
- if (tmp3 > 0xff0000) tmp3=0xff0000;
- *tabptr++=tmp3;
- }
- yc_pos+=yc_dpos;
- }
- if (alpha_once)
- need_alpha=0;
- }
- if (can_cache && !ignore_last_compare && !MEMCMP(m_tab, last_m_tab, m_tab_size)) {
- // cached, do nothing
- // DebugString("cache hit!\n");
- } else {
- MEMCPY(last_m_tab, m_tab, m_tab_size);
- // yay, the table is generated. now we do a fixed point
- // interpolation of the whole thing and pray.
- {
- int *interptab=m_tab+XRES*YRES*3;
- int *rdtab=m_tab;
- unsigned int *in=(unsigned int *)input;
- unsigned int *blendin=(unsigned int *)input;
- unsigned int *out=(unsigned int *)fx_canvas.getBits();
- int yseek=1;
- int xc_dpos, yc_pos=0, yc_dpos;
- xc_dpos=(tw<<16)/(XRES-1);
- yc_dpos=(th<<16)/(YRES-1);
- int lypos=0;
- int yl=_h;
- while (yl>0)
- {
- yc_pos+=yc_dpos;
- yseek=(yc_pos>>16)-lypos;
- if (!yseek) return 0;
- lypos=yc_pos>>16;
- int l=XRES;
- int *stab=interptab;
- int xr3=XRES*3;
- while (l--)
- {
- int tmp1, tmp2,tmp3;
- tmp1=rdtab[0];
- tmp2=rdtab[1];
- tmp3=rdtab[2];
- stab[0]=tmp1;
- stab[1]=tmp2;
- stab[2]=(rdtab[xr3]-tmp1)/yseek;
- stab[3]=(rdtab[xr3+1]-tmp2)/yseek;
- stab[4]=tmp3;
- stab[5]=(rdtab[xr3+2]-tmp3)/yseek;
- rdtab+=3;
- stab+=6;
- }
- if (yseek > yl) yseek=yl;
- yl-=yseek;
- if (yseek > 0) while (yseek--)
- {
- int d_x;
- int d_y;
- int d_a;
- int ap;
- int seek;
- int *seektab=interptab;
- int xp,yp;
- int l=_w;
- int lpos=0;
- int xc_pos=0;
- while (l>0)
- {
- xc_pos+=xc_dpos;
- seek=(xc_pos>>16)-lpos;
- if (!seek)
- {
- #ifndef NO_MMX
- Blenders::BLEND_MMX_END();
- #endif
- return 0;
- }
- lpos=xc_pos>>16;
- xp=seektab[0];
- yp=seektab[1];
- ap=seektab[4];
- d_a=(seektab[10]-ap)/(seek);
- d_x=(seektab[6]-xp)/(seek);
- d_y=(seektab[7]-yp)/(seek);
- seektab[0] += seektab[2];
- seektab[1] += seektab[3];
- seektab[4] += seektab[5];
- seektab+=6;
-
- if (seek>l) seek=l;
- l-=seek;
- if (seek>0)
- {
- // normal loop
- #define NORMAL_LOOP(Z) while (seek--) { Z; xp+=d_x; yp+=d_y; }
- // wrapping loop
- #define WRAPPING_LOOPS(Z) \
- if (d_x <= 0 && d_y <= 0) NORMAL_LOOP(if (xp < 0) xp += w_adj; if (yp < 0) yp += h_adj; Z) \
- else if (d_x <= 0) NORMAL_LOOP(if (xp < 0) xp += w_adj; if (yp >= h_adj) yp-=h_adj; Z) \
- else if (d_y <= 0) NORMAL_LOOP(if (xp >= w_adj) xp-=w_adj; if (yp < 0) yp += h_adj; Z) \
- else NORMAL_LOOP(if (xp >= w_adj) xp-=w_adj; if (yp >= h_adj) yp-=h_adj; Z)
- // this is uber gay. J1, D4, L or J1_MMX, D4_MMX, L_MMX
- #define LOOPS(DO,J1,D4,L) \
- if ((isblend&2) && issub) DO(*out++=Blenders::BLEND_AD##J1(Blenders::BLEN##D4(in+(xp>>16)+m_wmul[yp>>16],twpitch,xp,yp),*blendin++,ap>>16); ap+=d_a) \
- else if (isblend&2) DO(*out++=Blenders::BLEND_AD##J1(in[(xp>>16)+m_wmul[yp>>16]],*blendin++,ap>>16); ap+=d_a) \
- else if (isblend && issub) DO(*out++=Blenders::BLEND_MU##L(Blenders::BLEN##D4(in+(xp>>16)+m_wmul[yp>>16],twpitch,xp,yp),ap>>16); ap+=d_a) \
- else if (isblend) DO(*out++=Blenders::BLEND_MU##L(in[(xp>>16)+m_wmul[yp>>16]],ap>>16); ap+=d_a) \
- else if (issub) DO(*out++=Blenders::BLEN##D4(in+(xp>>16)+m_wmul[yp>>16],twpitch,xp,yp)) \
- else DO(*out++=in[(xp>>16)+m_wmul[yp>>16]])
- if (!dowrap)
- {
- #ifndef NO_MMX
- if (Blenders::MMX_AVAILABLE())
- {
- LOOPS(NORMAL_LOOP,J1_MMX,D4_MMX,L_MMX)
- }
- else
- #endif
- {
- LOOPS(NORMAL_LOOP,J1,D4,L)
- }
- }
- else // dowrap
- {
- xp %= w_adj+1; yp %= h_adj+1;
- if (xp < 0) xp+=w_adj; if (yp < 0) yp+=h_adj;
- if (d_x < -w_adj || d_x > w_adj) d_x=0; if (d_y < -h_adj || d_y > h_adj) d_y=0;
- #ifndef NO_MMX
- if (Blenders::MMX_AVAILABLE())
- {
- LOOPS(WRAPPING_LOOPS,J1_MMX,D4_MMX,L_MMX)
- }
- else
- #endif
- {
- LOOPS(WRAPPING_LOOPS,J1,D4,L)
- }
- }
- }
- }
- blendin+=twpitch-_w;
- // adjust final (rightmost elem) part of seektab
- seektab[0] += seektab[2];
- seektab[1] += seektab[3];
- seektab[4] += seektab[5];
- }
- }
- }
- }
- /*HDC dc = GetDC(NULL);
- BitBlt(dc, 0, 0, w, h, fx_canvas->getHDC(),0, 0, SRCCOPY);
- ReleaseDC(NULL, dc);*/
- #ifndef NO_MMX
- Blenders::BLEND_MMX_END();
- #endif
- return 0;
- };
- void FxDynamicMove::setWrap(int i) {
- wrap = i;
- }
- void FxDynamicMove::setRect(int i) {
- rectcoords = i;
-
- }
- void FxDynamicMove::setBilinear(int i) {
- subpixel = i;
- }
- void FxDynamicMove::setAlphaMode(int i) {
- blend = i;
- }
- void FxDynamicMove::setAlphaOnce(int i) {
- alpha_once = i;
- }
- void FxDynamicMove::setGridSize(int x, int y) {
- m_xres = x;
- m_yres = y;
- FREE(alpha_table);
- alpha_table = (double *)MALLOC((x+1)*(y+1)*sizeof(double));
- need_alpha = 1;
- }
- BltCanvas *FxDynamicMove::getBltCanvas()
- {
- return &fx_canvas;
- }
- void FxDynamicMove::prepareCanvas(int w, int h) {
- if (w != last_w || h != last_h)
- {
- if (cache_w < w || cache_h < h)
- {
- cache_w = max(cache_w, w);
- cache_h = max(cache_h, h);
- fx_canvas.DestructiveResize(cache_w, cache_h, 32);
- }
- last_w = w;
- last_h = h;
- }
- }
- void FxDynamicMove::setCanCache(int i) {
- can_cache = i;
- }
- void FxDynamicMove::flushCache()
- {
- need_flush=true;
- }
|