1
0

fx_dmove.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. #include <precomp.h>
  2. #include <tataki/blending/blending.h>
  3. #include "fx_dmove.h"
  4. #include <api/skin/widgets/layer.h>
  5. #include <math.h>
  6. #define M_PI 3.14159265358979323846
  7. FxDynamicMove::FxDynamicMove()
  8. : fx_canvas(4,4)
  9. {
  10. need_flush=false;
  11. cache_w=cache_h=4;
  12. m_wmul=0;
  13. m_tab=0;
  14. last_m_tab=0;
  15. m_lastxres=m_lastyres=m_lastpitch=0;
  16. m_xres=16;
  17. m_yres=16;
  18. last_w=last_h=-1;
  19. inited=0;
  20. subpixel=1;
  21. rectcoords=0;
  22. blend=0;
  23. wrap=0;
  24. need_alpha = 1;
  25. alpha_table = (double *)MALLOC((m_xres+1)*(m_yres+1)*sizeof(double));
  26. alpha_once= 0;
  27. can_cache = 1;
  28. m_lastw = 0;
  29. m_lasth = 0;
  30. m_tab_size = 0;
  31. }
  32. FxDynamicMove::~FxDynamicMove()
  33. {
  34. FREE(m_wmul);
  35. FREE(m_tab);
  36. FREE(last_m_tab);
  37. FREE(alpha_table);
  38. }
  39. int FxDynamicMove::render(Layer *l, int _w, int _h, int *input, int tw, int th, int twpitch)
  40. {
  41. double var_x;
  42. double var_y;
  43. double var_d;
  44. double var_r;
  45. /*if (fx_canvas) {
  46. HDC dc;
  47. dc = GetDC(NULL);
  48. BitBlt(dc, 0, 0, w, h, fx_canvas->getHDC(),0, 0, SRCCOPY);
  49. ReleaseDC(NULL, dc);
  50. }*/
  51. prepareCanvas(_w, _h);
  52. int w_adj=(tw-2)<<16;
  53. int h_adj=(th-2)<<16;
  54. int dowrap=wrap;
  55. int XRES=m_xres+1;
  56. int YRES=m_yres+1;
  57. int ignore_last_compare=0;
  58. if (XRES > _w) XRES=_w;
  59. if (YRES > _h) YRES=_h;
  60. if (XRES < 2) XRES=2;
  61. if (XRES > 256) XRES=256;
  62. if (YRES < 2) YRES=2;
  63. if (YRES > 256) YRES=256;
  64. if (need_flush || m_lasth != th || m_lastpitch != twpitch || m_lastw != tw || !m_tab || !m_wmul || m_lastxres != XRES || m_lastyres != YRES)
  65. {
  66. int y;
  67. m_lastxres = XRES;
  68. m_lastyres = YRES;
  69. m_lastw=tw;
  70. m_lasth=th;
  71. m_lastpitch=twpitch;
  72. FREE(m_wmul);
  73. m_wmul=(int*)MALLOC(sizeof(int)*th);
  74. for (y = 0; y < th; y ++) m_wmul[y]=y*twpitch;
  75. FREE(m_tab);
  76. FREE(last_m_tab);
  77. m_tab_size = (XRES*YRES*3 + XRES*6 + 6)*sizeof(int);
  78. m_tab=(int*)MALLOC(m_tab_size);
  79. last_m_tab=(int*)MALLOC(m_tab_size);
  80. ignore_last_compare=1;
  81. }
  82. need_flush=false;
  83. int isblend=blend;
  84. int issub=subpixel;
  85. if (!issub)
  86. {
  87. w_adj=(tw-1)<<16;
  88. h_adj=(th-1)<<16;
  89. }
  90. if (w_adj<0) w_adj=0;
  91. if (h_adj<0) h_adj=0;
  92. {
  93. int x;
  94. int y;
  95. int *tabptr=m_tab;
  96. double xsc=2.0/tw,ysc=2.0/th;
  97. double dw2=((double)tw*32768.0);
  98. double dh2=((double)th*32768.0);
  99. double max_screen_d=sqrt((double)(tw*tw+th*th))*0.5;
  100. double divmax_d=1.0/max_screen_d;
  101. max_screen_d *= 65536.0;
  102. double _var_alpha = 0.50;
  103. int yc_pos, yc_dpos, xc_pos, xc_dpos;
  104. yc_pos=0;
  105. xc_dpos = (tw<<16)/(XRES-1);
  106. yc_dpos = (th<<16)/(YRES-1);
  107. for (y = 0; y < YRES; y ++)
  108. {
  109. xc_pos=0;
  110. for (x = 0; x < XRES; x ++)
  111. {
  112. double xd,yd;
  113. xd=((double)xc_pos-dw2)*(1.0/65536.0);
  114. yd=((double)yc_pos-dh2)*(1.0/65536.0);
  115. xc_pos+=xc_dpos;
  116. var_x=xd*xsc;
  117. var_y=yd*ysc;
  118. var_d=sqrt(xd*xd+yd*yd)*divmax_d;
  119. var_r=atan2(yd,xd) + M_PI*0.5;
  120. double _var_r=var_r, _var_d=var_d;
  121. if (isblend && need_alpha) {
  122. _var_alpha = l->fx_onGetPixelA(var_r, var_d, var_x, var_y);
  123. alpha_table[y*YRES+x] = _var_alpha;
  124. } else if (isblend && !need_alpha) {
  125. _var_alpha = alpha_table[y*YRES+x];
  126. }
  127. if (!rectcoords) {
  128. double t_var_r = l->fx_onGetPixelR(var_r, var_d, var_x, var_y);
  129. _var_d = l->fx_onGetPixelD(var_r, var_d, var_x, var_y);
  130. _var_r = t_var_r;
  131. }
  132. double _var_x=var_x, _var_y=var_y;
  133. if (rectcoords) {
  134. double t_var_x = l->fx_onGetPixelX(var_r, var_d, var_x, var_y);
  135. _var_y = l->fx_onGetPixelY(var_r, var_d, var_x, var_y);
  136. _var_x = t_var_x;
  137. }
  138. int tmp1,tmp2,tmp3;
  139. if (!rectcoords)
  140. {
  141. _var_d *= max_screen_d;
  142. _var_r -= M_PI*0.5;
  143. tmp1=(int) (dw2 + cos(_var_r) * _var_d);
  144. tmp2=(int) (dh2 + sin(_var_r) * _var_d);
  145. }
  146. else
  147. {
  148. tmp1=(int) ((_var_x+1.0)*dw2);
  149. tmp2=(int) ((_var_y+1.0)*dh2);
  150. }
  151. if (!dowrap)
  152. {
  153. if (tmp1 < 0) tmp1=0;
  154. if (tmp1 > w_adj) tmp1=w_adj;
  155. if (tmp2 < 0) tmp2=0;
  156. if (tmp2 > h_adj) tmp2=h_adj;
  157. }
  158. *tabptr++ = tmp1;
  159. *tabptr++ = tmp2;
  160. tmp3 = (int)(_var_alpha*65536.0*256.0);
  161. if (tmp3 < 0) tmp3=0;
  162. if (tmp3 > 0xff0000) tmp3=0xff0000;
  163. *tabptr++=tmp3;
  164. }
  165. yc_pos+=yc_dpos;
  166. }
  167. if (alpha_once)
  168. need_alpha=0;
  169. }
  170. if (can_cache && !ignore_last_compare && !MEMCMP(m_tab, last_m_tab, m_tab_size)) {
  171. // cached, do nothing
  172. // DebugString("cache hit!\n");
  173. } else {
  174. MEMCPY(last_m_tab, m_tab, m_tab_size);
  175. // yay, the table is generated. now we do a fixed point
  176. // interpolation of the whole thing and pray.
  177. {
  178. int *interptab=m_tab+XRES*YRES*3;
  179. int *rdtab=m_tab;
  180. unsigned int *in=(unsigned int *)input;
  181. unsigned int *blendin=(unsigned int *)input;
  182. unsigned int *out=(unsigned int *)fx_canvas.getBits();
  183. int yseek=1;
  184. int xc_dpos, yc_pos=0, yc_dpos;
  185. xc_dpos=(tw<<16)/(XRES-1);
  186. yc_dpos=(th<<16)/(YRES-1);
  187. int lypos=0;
  188. int yl=_h;
  189. while (yl>0)
  190. {
  191. yc_pos+=yc_dpos;
  192. yseek=(yc_pos>>16)-lypos;
  193. if (!yseek) return 0;
  194. lypos=yc_pos>>16;
  195. int l=XRES;
  196. int *stab=interptab;
  197. int xr3=XRES*3;
  198. while (l--)
  199. {
  200. int tmp1, tmp2,tmp3;
  201. tmp1=rdtab[0];
  202. tmp2=rdtab[1];
  203. tmp3=rdtab[2];
  204. stab[0]=tmp1;
  205. stab[1]=tmp2;
  206. stab[2]=(rdtab[xr3]-tmp1)/yseek;
  207. stab[3]=(rdtab[xr3+1]-tmp2)/yseek;
  208. stab[4]=tmp3;
  209. stab[5]=(rdtab[xr3+2]-tmp3)/yseek;
  210. rdtab+=3;
  211. stab+=6;
  212. }
  213. if (yseek > yl) yseek=yl;
  214. yl-=yseek;
  215. if (yseek > 0) while (yseek--)
  216. {
  217. int d_x;
  218. int d_y;
  219. int d_a;
  220. int ap;
  221. int seek;
  222. int *seektab=interptab;
  223. int xp,yp;
  224. int l=_w;
  225. int lpos=0;
  226. int xc_pos=0;
  227. while (l>0)
  228. {
  229. xc_pos+=xc_dpos;
  230. seek=(xc_pos>>16)-lpos;
  231. if (!seek)
  232. {
  233. #ifndef NO_MMX
  234. Blenders::BLEND_MMX_END();
  235. #endif
  236. return 0;
  237. }
  238. lpos=xc_pos>>16;
  239. xp=seektab[0];
  240. yp=seektab[1];
  241. ap=seektab[4];
  242. d_a=(seektab[10]-ap)/(seek);
  243. d_x=(seektab[6]-xp)/(seek);
  244. d_y=(seektab[7]-yp)/(seek);
  245. seektab[0] += seektab[2];
  246. seektab[1] += seektab[3];
  247. seektab[4] += seektab[5];
  248. seektab+=6;
  249. if (seek>l) seek=l;
  250. l-=seek;
  251. if (seek>0)
  252. {
  253. // normal loop
  254. #define NORMAL_LOOP(Z) while (seek--) { Z; xp+=d_x; yp+=d_y; }
  255. // wrapping loop
  256. #define WRAPPING_LOOPS(Z) \
  257. if (d_x <= 0 && d_y <= 0) NORMAL_LOOP(if (xp < 0) xp += w_adj; if (yp < 0) yp += h_adj; Z) \
  258. else if (d_x <= 0) NORMAL_LOOP(if (xp < 0) xp += w_adj; if (yp >= h_adj) yp-=h_adj; Z) \
  259. else if (d_y <= 0) NORMAL_LOOP(if (xp >= w_adj) xp-=w_adj; if (yp < 0) yp += h_adj; Z) \
  260. else NORMAL_LOOP(if (xp >= w_adj) xp-=w_adj; if (yp >= h_adj) yp-=h_adj; Z)
  261. // this is uber gay. J1, D4, L or J1_MMX, D4_MMX, L_MMX
  262. #define LOOPS(DO,J1,D4,L) \
  263. 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) \
  264. else if (isblend&2) DO(*out++=Blenders::BLEND_AD##J1(in[(xp>>16)+m_wmul[yp>>16]],*blendin++,ap>>16); ap+=d_a) \
  265. 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) \
  266. else if (isblend) DO(*out++=Blenders::BLEND_MU##L(in[(xp>>16)+m_wmul[yp>>16]],ap>>16); ap+=d_a) \
  267. else if (issub) DO(*out++=Blenders::BLEN##D4(in+(xp>>16)+m_wmul[yp>>16],twpitch,xp,yp)) \
  268. else DO(*out++=in[(xp>>16)+m_wmul[yp>>16]])
  269. if (!dowrap)
  270. {
  271. #ifndef NO_MMX
  272. if (Blenders::MMX_AVAILABLE())
  273. {
  274. LOOPS(NORMAL_LOOP,J1_MMX,D4_MMX,L_MMX)
  275. }
  276. else
  277. #endif
  278. {
  279. LOOPS(NORMAL_LOOP,J1,D4,L)
  280. }
  281. }
  282. else // dowrap
  283. {
  284. xp %= w_adj+1; yp %= h_adj+1;
  285. if (xp < 0) xp+=w_adj; if (yp < 0) yp+=h_adj;
  286. if (d_x < -w_adj || d_x > w_adj) d_x=0; if (d_y < -h_adj || d_y > h_adj) d_y=0;
  287. #ifndef NO_MMX
  288. if (Blenders::MMX_AVAILABLE())
  289. {
  290. LOOPS(WRAPPING_LOOPS,J1_MMX,D4_MMX,L_MMX)
  291. }
  292. else
  293. #endif
  294. {
  295. LOOPS(WRAPPING_LOOPS,J1,D4,L)
  296. }
  297. }
  298. }
  299. }
  300. blendin+=twpitch-_w;
  301. // adjust final (rightmost elem) part of seektab
  302. seektab[0] += seektab[2];
  303. seektab[1] += seektab[3];
  304. seektab[4] += seektab[5];
  305. }
  306. }
  307. }
  308. }
  309. /*HDC dc = GetDC(NULL);
  310. BitBlt(dc, 0, 0, w, h, fx_canvas->getHDC(),0, 0, SRCCOPY);
  311. ReleaseDC(NULL, dc);*/
  312. #ifndef NO_MMX
  313. Blenders::BLEND_MMX_END();
  314. #endif
  315. return 0;
  316. };
  317. void FxDynamicMove::setWrap(int i) {
  318. wrap = i;
  319. }
  320. void FxDynamicMove::setRect(int i) {
  321. rectcoords = i;
  322. }
  323. void FxDynamicMove::setBilinear(int i) {
  324. subpixel = i;
  325. }
  326. void FxDynamicMove::setAlphaMode(int i) {
  327. blend = i;
  328. }
  329. void FxDynamicMove::setAlphaOnce(int i) {
  330. alpha_once = i;
  331. }
  332. void FxDynamicMove::setGridSize(int x, int y) {
  333. m_xres = x;
  334. m_yres = y;
  335. FREE(alpha_table);
  336. alpha_table = (double *)MALLOC((x+1)*(y+1)*sizeof(double));
  337. need_alpha = 1;
  338. }
  339. BltCanvas *FxDynamicMove::getBltCanvas()
  340. {
  341. return &fx_canvas;
  342. }
  343. void FxDynamicMove::prepareCanvas(int w, int h) {
  344. if (w != last_w || h != last_h)
  345. {
  346. if (cache_w < w || cache_h < h)
  347. {
  348. cache_w = max(cache_w, w);
  349. cache_h = max(cache_h, h);
  350. fx_canvas.DestructiveResize(cache_w, cache_h, 32);
  351. }
  352. last_w = w;
  353. last_h = h;
  354. }
  355. }
  356. void FxDynamicMove::setCanCache(int i) {
  357. can_cache = i;
  358. }
  359. void FxDynamicMove::flushCache()
  360. {
  361. need_flush=true;
  362. }