dc_trans.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866
  1. /*
  2. * File : dc_trans.c
  3. * This file is part of RT-Thread GUI
  4. * COPYRIGHT (C) 2006 - 2014, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2014-03-15 Grissom The first version
  23. */
  24. #include <rtgui/rtgui.h>
  25. #include <rtgui/rtgui_system.h>
  26. #include <rtgui/dc.h>
  27. #include <rtgui/dc_trans.h>
  28. struct rtgui_dc_trans
  29. {
  30. struct rtgui_matrix m;
  31. struct rtgui_dc *owner;
  32. int use_aa;
  33. };
  34. struct rtgui_dc_trans* rtgui_dc_trans_create(struct rtgui_dc *owner)
  35. {
  36. struct rtgui_dc_trans *dct;
  37. dct = (struct rtgui_dc_trans*)rtgui_malloc(sizeof(*dct));
  38. if (!dct)
  39. return RT_NULL;
  40. rtgu_matrix_identity(&dct->m);
  41. dct->owner = owner;
  42. dct->use_aa = 0;
  43. return dct;
  44. }
  45. RTM_EXPORT(rtgui_dc_trans_create);
  46. void rtgui_dc_trans_destroy(struct rtgui_dc_trans *dct)
  47. {
  48. rtgui_free(dct);
  49. }
  50. RTM_EXPORT(rtgui_dc_trans_destroy);
  51. void rtgui_dc_trans_set_aa(struct rtgui_dc_trans *dct, int use_aa)
  52. {
  53. RT_ASSERT(dct);
  54. dct->use_aa = use_aa;
  55. }
  56. RTM_EXPORT(rtgui_dc_trans_set_aa);
  57. void rtgui_dc_trans_rotate(struct rtgui_dc_trans *dct, double degree)
  58. {
  59. RT_ASSERT(dct);
  60. rtgui_matrix_rotate(&dct->m, degree * RTGUI_MATRIX_FRAC / 360.0);
  61. }
  62. RTM_EXPORT(rtgui_dc_trans_rotate);
  63. void rtgui_dc_trans_scale(struct rtgui_dc_trans *dct,
  64. double sx,
  65. double sy)
  66. {
  67. RT_ASSERT(dct);
  68. rtgui_matrix_scale(&dct->m, sx * RTGUI_MATRIX_FRAC, sy * RTGUI_MATRIX_FRAC);
  69. }
  70. RTM_EXPORT(rtgui_dc_trans_scale);
  71. void rtgui_dc_trans_move(struct rtgui_dc_trans *dct,
  72. int dx,
  73. int dy)
  74. {
  75. RT_ASSERT(dct);
  76. rtgui_matrix_move(&dct->m, dx, dy);
  77. }
  78. RTM_EXPORT(rtgui_dc_trans_move);
  79. void rtgui_dc_trans_get_new_wh(struct rtgui_dc_trans *dct,
  80. int *new_wp,
  81. int *new_hp)
  82. {
  83. struct rtgui_rect rect;
  84. struct rtgui_point topleft, topright, bottomright;
  85. RT_ASSERT(dct);
  86. if (!new_wp && !new_hp)
  87. return;
  88. rtgui_dc_get_rect(dct->owner, &rect);
  89. /* We ignore the movement components in the matrix. */
  90. /* Transform result of (0, h). */
  91. rtgui_matrix_mul_point_nomove(&topleft, 0, rect.y2,
  92. &dct->m);
  93. /* Transform result of (w, h). */
  94. rtgui_matrix_mul_point_nomove(&topright, rect.x2, rect.y2,
  95. &dct->m);
  96. /* Transform result of (w, 0). */
  97. rtgui_matrix_mul_point_nomove(&bottomright,
  98. rect.x2, 0, &dct->m);
  99. /* Transform result of (0, 0) is always (0, 0). */
  100. #define NORMALIZE(x) do { if (x < 0) x = 0; } while (0)
  101. if (new_wp)
  102. {
  103. int neww;
  104. /* Ignore the nagtive parts. */
  105. NORMALIZE(topright.x);
  106. NORMALIZE(topleft.x);
  107. NORMALIZE(bottomright.x);
  108. neww = _UI_MAX(topright.x, _UI_ABS(topleft.x - bottomright.x))
  109. + dct->m.m[4];
  110. NORMALIZE(neww);
  111. *new_wp = neww;
  112. }
  113. if (new_hp)
  114. {
  115. int newh;
  116. NORMALIZE(topright.y);
  117. NORMALIZE(topleft.y);
  118. NORMALIZE(bottomright.y);
  119. newh = _UI_MAX(topright.y, _UI_ABS(topleft.y - bottomright.y))
  120. + dct->m.m[5];
  121. NORMALIZE(newh);
  122. *new_hp = newh;
  123. }
  124. #undef NORMALIZE
  125. }
  126. RTM_EXPORT(rtgui_dc_trans_get_new_wh);
  127. struct _fb_rect
  128. {
  129. void *fb;
  130. /* unit: pixel */
  131. rt_uint16_t width, height;
  132. /* unit: pixel */
  133. rt_uint16_t skip;
  134. };
  135. /* FrameRect to FrameRect, same format, 2 Bytes/pixel. */
  136. static void _blit_rotate_FR2FR_SF2B(struct _fb_rect* RTGUI_RESTRICT src,
  137. const struct rtgui_point *dc_point,
  138. struct _fb_rect* RTGUI_RESTRICT dst,
  139. const struct rtgui_matrix *invm)
  140. {
  141. rt_uint16_t* RTGUI_RESTRICT srcp = (rt_uint16_t*)src->fb;
  142. rt_uint16_t* RTGUI_RESTRICT dstp = (rt_uint16_t*)dst->fb;
  143. int neww = dst->width;
  144. int newh = dst->height;
  145. int oriw = src->width;
  146. int orih = src->height;
  147. int nx, ny;
  148. int dx, dy;
  149. /* Delta of bx/by when nx++. */
  150. dx = invm->m[0];
  151. dy = invm->m[1];
  152. for (ny = dc_point->y; ny < newh; ny++)
  153. {
  154. /* Base x, y. */
  155. int bx, by;
  156. bx = dc_point->x * dx + ny * invm->m[2] + RTGUI_MATRIX_FRAC * invm->m[4];
  157. by = dc_point->x * dy + ny * invm->m[3] + RTGUI_MATRIX_FRAC * invm->m[5];
  158. for (nx = dc_point->x; nx < neww; nx++, dstp++)
  159. {
  160. /* The coordinate in the source frame. */
  161. int rx, ry;
  162. bx += dx;
  163. by += dy;
  164. if (bx < 0 || by < 0)
  165. continue;
  166. rx = bx / RTGUI_MATRIX_FRAC;
  167. ry = by / RTGUI_MATRIX_FRAC;
  168. if (oriw <= rx || orih <= ry)
  169. continue;
  170. /* We take the source as a whole and ignore the src->skip. */
  171. *dstp = srcp[ry * oriw + rx];
  172. }
  173. dstp += dst->skip - neww;
  174. }
  175. }
  176. /* FrameRect to FrameRect, same format, 2 Bytes/pixel, with AA. */
  177. static void _blit_rotate_FR2FR_SF2B_AA(struct _fb_rect* RTGUI_RESTRICT src,
  178. const struct rtgui_point *dc_point,
  179. struct _fb_rect* RTGUI_RESTRICT dst,
  180. const struct rtgui_matrix *invm)
  181. {
  182. rt_uint16_t* RTGUI_RESTRICT srcp = (rt_uint16_t*)src->fb;
  183. rt_uint16_t* RTGUI_RESTRICT dstp = (rt_uint16_t*)dst->fb;
  184. int neww = dst->width;
  185. int newh = dst->height;
  186. int oriw = src->width;
  187. int orih = src->height;
  188. int nx, ny;
  189. int dx, dy;
  190. dx = invm->m[0];
  191. dy = invm->m[1];
  192. for (ny = dc_point->y; ny < newh; ny++)
  193. {
  194. /* Base x, y. */
  195. int bx, by;
  196. bx = dc_point->x * dx + ny * invm->m[2] + RTGUI_MATRIX_FRAC * invm->m[4];
  197. by = dc_point->x * dy + ny * invm->m[3] + RTGUI_MATRIX_FRAC * invm->m[5];
  198. for (nx = dc_point->x; nx < neww; nx++, dstp++)
  199. {
  200. /* Color of pixels:
  201. * c00 c01
  202. * c10 c11 */
  203. rt_uint32_t c00, c01, c10, c11;
  204. int rx, ry, sx, sy;
  205. bx += dx;
  206. by += dy;
  207. if (bx < 0 || by < 0)
  208. continue;
  209. rx = bx / RTGUI_MATRIX_FRAC;
  210. ry = by / RTGUI_MATRIX_FRAC;
  211. if (oriw - 1 <= rx || orih - 1 <= ry)
  212. continue;
  213. c00 = srcp[ry * oriw + rx];
  214. c01 = srcp[ry * oriw + rx + 1];
  215. c10 = srcp[(ry + 1) * oriw + rx];
  216. c11 = srcp[(ry + 1) * oriw + rx + 1];
  217. c00 = (c00 | c00 << 16) & 0x07e0f81f;
  218. c01 = (c01 | c01 << 16) & 0x07e0f81f;
  219. c10 = (c10 | c10 << 16) & 0x07e0f81f;
  220. c11 = (c11 | c11 << 16) & 0x07e0f81f;
  221. /* We down scale the interpolate factor to 5 bits to avoid color
  222. * corruption. */
  223. sx = ((unsigned int)bx % RTGUI_MATRIX_FRAC) >> (RTGUI_MATRIX_FRAC_BITS - 5);
  224. sy = ((unsigned int)by % RTGUI_MATRIX_FRAC) >> (RTGUI_MATRIX_FRAC_BITS - 5);
  225. if (sx)
  226. c00 = ((c01 - c00) * sx / 32 + c00) & 0x07e0f81f;
  227. if (sx && sy)
  228. c10 = ((c11 - c10) * sx / 32 + c10) & 0x07e0f81f;
  229. if (sy)
  230. c00 = ((c10 - c00) * sy / 32 + c00) & 0x07e0f81f;
  231. /* We take the source as a whole and ignore the src->skip. */
  232. *dstp = c00 | (c00 >> 16);
  233. }
  234. dstp += dst->skip - neww;
  235. }
  236. }
  237. union _rgba
  238. {
  239. rt_uint32_t blk;
  240. struct
  241. {
  242. rt_uint8_t r, g, b, a;
  243. } d;
  244. };
  245. /* FrameRect to FrameRect, same format, 4 Bytes/pixel. */
  246. static void _blit_rotate_FR2FR_SF4B(struct _fb_rect* RTGUI_RESTRICT src,
  247. const struct rtgui_point *dc_point,
  248. struct _fb_rect* RTGUI_RESTRICT dst,
  249. const struct rtgui_matrix *invm)
  250. {
  251. rt_uint32_t* RTGUI_RESTRICT srcp = (rt_uint32_t*)src->fb;
  252. rt_uint32_t* RTGUI_RESTRICT dstp = (rt_uint32_t*)dst->fb;
  253. int neww = dst->width;
  254. int newh = dst->height;
  255. int oriw = src->width;
  256. int orih = src->height;
  257. int nx, ny;
  258. int dx, dy;
  259. dx = invm->m[0];
  260. dy = invm->m[1];
  261. for (ny = dc_point->y; ny < newh; ny++)
  262. {
  263. /* Base x, y. */
  264. int bx, by;
  265. bx = dc_point->x * dx + ny * invm->m[2] + RTGUI_MATRIX_FRAC * invm->m[4];
  266. by = dc_point->x * dy + ny * invm->m[3] + RTGUI_MATRIX_FRAC * invm->m[5];
  267. for (nx = dc_point->x; nx < neww; nx++, dstp++)
  268. {
  269. union _rgba spix, dpix;
  270. int rx, ry, a;
  271. bx += dx;
  272. by += dy;
  273. if (bx < 0 || by < 0)
  274. continue;
  275. rx = bx / RTGUI_MATRIX_FRAC;
  276. ry = by / RTGUI_MATRIX_FRAC;
  277. if (oriw <= rx || orih <= ry)
  278. continue;
  279. spix.blk = srcp[ry * oriw + rx];
  280. /* Down scale the alpha to 5 bits. */
  281. a = spix.d.a >> 3;
  282. if (a == 0)
  283. continue;
  284. if (a == 31)
  285. {
  286. *dstp = spix.blk;
  287. continue;
  288. }
  289. dpix.blk = *dstp;
  290. dpix.d.r = (spix.d.r - dpix.d.r) * a / 32 + dpix.d.r;
  291. dpix.d.g = (spix.d.g - dpix.d.g) * a / 32 + dpix.d.g;
  292. dpix.d.b = (spix.d.b - dpix.d.b) * a / 32 + dpix.d.b;
  293. *dstp = dpix.blk;
  294. }
  295. dstp += dst->skip - neww;
  296. }
  297. }
  298. /* FrameRect to FrameRect, same format, 4 Bytes/pixel, with AA. */
  299. static void _blit_rotate_FR2FR_SF4B_AA(struct _fb_rect* RTGUI_RESTRICT src,
  300. const struct rtgui_point *dc_point,
  301. struct _fb_rect* RTGUI_RESTRICT dst,
  302. const struct rtgui_matrix *invm)
  303. {
  304. rt_uint32_t* RTGUI_RESTRICT srcp = (rt_uint32_t*)src->fb;
  305. rt_uint32_t* RTGUI_RESTRICT dstp = (rt_uint32_t*)dst->fb;
  306. int neww = dst->width;
  307. int newh = dst->height;
  308. int oriw = src->width;
  309. int orih = src->height;
  310. int nx, ny;
  311. int dx, dy;
  312. dx = invm->m[0];
  313. dy = invm->m[1];
  314. for (ny = dc_point->y; ny < newh; ny++)
  315. {
  316. /* Base x, y. */
  317. int bx, by;
  318. bx = dc_point->x * dx + ny * invm->m[2] + RTGUI_MATRIX_FRAC * invm->m[4];
  319. by = dc_point->x * dy + ny * invm->m[3] + RTGUI_MATRIX_FRAC * invm->m[5];
  320. for (nx = dc_point->x; nx < neww; nx++, dstp++)
  321. {
  322. union _rgba spix00, spix01, spix10, spix11, dpix;
  323. int rx, ry, a, sx, sy;
  324. bx += dx;
  325. by += dy;
  326. if (bx < 0 || by < 0)
  327. continue;
  328. rx = bx / RTGUI_MATRIX_FRAC;
  329. ry = by / RTGUI_MATRIX_FRAC;
  330. if (oriw - 1 <= rx || orih - 1 <= ry)
  331. continue;
  332. spix00.blk = srcp[ry * oriw + rx];
  333. /* Down scale the interpolate factor to 5 bits. */
  334. sx = ((unsigned int)bx % RTGUI_MATRIX_FRAC) >> (RTGUI_MATRIX_FRAC_BITS - 5);
  335. sy = ((unsigned int)by % RTGUI_MATRIX_FRAC) >> (RTGUI_MATRIX_FRAC_BITS - 5);
  336. spix01.blk = srcp[ry * oriw + rx + 1];
  337. spix10.blk = srcp[(ry + 1) * oriw + rx];
  338. spix11.blk = srcp[(ry + 1) * oriw + rx + 1];
  339. if (sx)
  340. spix00.d.a = (spix01.d.a - spix00.d.a) * sx / 32 + spix00.d.a;
  341. if (sx && sy)
  342. spix10.d.a = (spix11.d.a - spix10.d.a) * sx / 32 + spix10.d.a;
  343. if (sy)
  344. spix00.d.a = (spix10.d.a - spix00.d.a) * sy / 32 + spix00.d.a;
  345. a = spix00.d.a >> 3;
  346. if (a == 0)
  347. continue;
  348. if (sx)
  349. {
  350. spix00.d.r = (spix01.d.r - spix00.d.r) * sx / 32 + spix00.d.r;
  351. spix00.d.g = (spix01.d.g - spix00.d.g) * sx / 32 + spix00.d.g;
  352. spix00.d.b = (spix01.d.b - spix00.d.b) * sx / 32 + spix00.d.b;
  353. }
  354. if (sx && sy)
  355. {
  356. spix10.d.r = (spix11.d.r - spix10.d.r) * sx / 32 + spix10.d.r;
  357. spix10.d.g = (spix11.d.g - spix10.d.g) * sx / 32 + spix10.d.g;
  358. spix10.d.b = (spix11.d.b - spix10.d.b) * sx / 32 + spix10.d.b;
  359. }
  360. if (sy)
  361. {
  362. spix00.d.r = (spix10.d.r - spix00.d.r) * sy / 32 + spix00.d.r;
  363. spix00.d.g = (spix10.d.g - spix00.d.g) * sy / 32 + spix00.d.g;
  364. spix00.d.b = (spix10.d.b - spix00.d.b) * sy / 32 + spix00.d.b;
  365. }
  366. if (a == (255 >> 3))
  367. {
  368. *dstp = spix00.blk;
  369. continue;
  370. }
  371. dpix.blk = *dstp;
  372. dpix.d.r = (spix00.d.r - dpix.d.r) * a / 32 + dpix.d.r;
  373. dpix.d.g = (spix00.d.g - dpix.d.g) * a / 32 + dpix.d.g;
  374. dpix.d.b = (spix00.d.b - dpix.d.b) * a / 32 + dpix.d.b;
  375. *dstp = dpix.blk;
  376. }
  377. dstp += dst->skip - neww;
  378. }
  379. }
  380. /* FrameRect to FrameRect, from ARGB8888 to RGB565. */
  381. static void _blit_rotate_FR2FR_ARGB2RGB565(struct _fb_rect* RTGUI_RESTRICT src,
  382. const struct rtgui_point *dc_point,
  383. struct _fb_rect* RTGUI_RESTRICT dst,
  384. const struct rtgui_matrix *invm)
  385. {
  386. rt_uint32_t* RTGUI_RESTRICT srcp = (rt_uint32_t*)src->fb;
  387. rt_uint16_t* RTGUI_RESTRICT dstp = (rt_uint16_t*)dst->fb;
  388. int neww = dst->width;
  389. int newh = dst->height;
  390. int oriw = src->width;
  391. int orih = src->height;
  392. int nx, ny;
  393. int dx, dy;
  394. dx = invm->m[0];
  395. dy = invm->m[1];
  396. for (ny = dc_point->y; ny < newh; ny++)
  397. {
  398. /* Base x, y. */
  399. int bx, by;
  400. bx = dc_point->x * dx + ny * invm->m[2] + RTGUI_MATRIX_FRAC * invm->m[4];
  401. by = dc_point->x * dy + ny * invm->m[3] + RTGUI_MATRIX_FRAC * invm->m[5];
  402. for (nx = dc_point->x; nx < neww; nx++, dstp++)
  403. {
  404. int rx, ry;
  405. int alpha;
  406. rt_uint32_t op;
  407. bx += dx;
  408. by += dy;
  409. if (bx < 0 || by < 0)
  410. continue;
  411. rx = bx / RTGUI_MATRIX_FRAC;
  412. ry = by / RTGUI_MATRIX_FRAC;
  413. if (oriw <= rx || orih <= ry)
  414. continue;
  415. /* We take the source as a whole and ignore the src->skip. */
  416. op = srcp[ry * oriw + rx];
  417. /* downscale alpha to 5 bits */
  418. alpha = op >> 27;
  419. if (alpha == (255 >> 3))
  420. {
  421. *dstp = (rt_uint16_t)((op >> 8 & 0xf800) +
  422. (op >> 5 & 0x7e0) +
  423. (op >> 3 & 0x1f));
  424. }
  425. else if (alpha != 0)
  426. {
  427. /* We take the source as a whole and ignore the src->skip. */
  428. rt_uint32_t d = *dstp;
  429. /*
  430. * convert source and destination to G0RAB65565
  431. * and blend all components at the same time
  432. */
  433. op = ((op & 0xfc00) << 11) + (op >> 8 & 0xf800)
  434. + (op >> 3 & 0x1f);
  435. d = (d | d << 16) & 0x07e0f81f;
  436. d += (op - d) * alpha >> 5;
  437. d &= 0x07e0f81f;
  438. *dstp = (rt_uint16_t)(d | d >> 16);
  439. }
  440. }
  441. dstp += dst->skip - neww;
  442. }
  443. }
  444. /* FrameRect to FrameRect, from ARGB8888 to RGB565. */
  445. static void _blit_rotate_FR2FR_ARGB2RGB565_AA(struct _fb_rect* RTGUI_RESTRICT src,
  446. const struct rtgui_point *dc_point,
  447. struct _fb_rect* RTGUI_RESTRICT dst,
  448. const struct rtgui_matrix *invm)
  449. {
  450. rt_uint32_t* RTGUI_RESTRICT srcp = (rt_uint32_t*)src->fb;
  451. rt_uint16_t* RTGUI_RESTRICT dstp = (rt_uint16_t*)dst->fb;
  452. int neww = dst->width;
  453. int newh = dst->height;
  454. int oriw = src->width;
  455. int orih = src->height;
  456. int nx, ny;
  457. int dx, dy;
  458. dx = invm->m[0];
  459. dy = invm->m[1];
  460. for (ny = dc_point->y; ny < newh; ny++)
  461. {
  462. /* Base x, y. */
  463. int bx, by;
  464. bx = dc_point->x * dx + ny * invm->m[2] + RTGUI_MATRIX_FRAC * invm->m[4];
  465. by = dc_point->x * dy + ny * invm->m[3] + RTGUI_MATRIX_FRAC * invm->m[5];
  466. for (nx = dc_point->x; nx < neww; nx++, dstp++)
  467. {
  468. rt_uint32_t op00, op01, op10, op11;
  469. rt_uint8_t a00, a01, a10, a11;
  470. int rx, ry, sx, sy;
  471. bx += dx;
  472. by += dy;
  473. if (bx < 0 || by < 0)
  474. continue;
  475. rx = bx / RTGUI_MATRIX_FRAC;
  476. ry = by / RTGUI_MATRIX_FRAC;
  477. if (oriw - 1 <= rx || orih - 1 <= ry)
  478. continue;
  479. op00 = srcp[ry * oriw + rx];
  480. op01 = srcp[ry * oriw + rx + 1];
  481. op10 = srcp[(ry + 1) * oriw + rx];
  482. op11 = srcp[(ry + 1) * oriw + rx + 1];
  483. /* Down scale the interpolate factor to 5 bits. */
  484. sx = ((unsigned int)bx % RTGUI_MATRIX_FRAC) >> (RTGUI_MATRIX_FRAC_BITS - 5);
  485. sy = ((unsigned int)by % RTGUI_MATRIX_FRAC) >> (RTGUI_MATRIX_FRAC_BITS - 5);
  486. a00 = op00 >> 27;
  487. a01 = op01 >> 27;
  488. a11 = op11 >> 27;
  489. a10 = op10 >> 27;
  490. if (sx)
  491. a00 = (a01 - a00) * sx / 32 + a00;
  492. if (sx && sy)
  493. a10 = (a11 - a10) * sx / 32 + a10;
  494. if (sy)
  495. a00 = (a10 - a00) * sy / 32 + a00;
  496. if (a00 == 0)
  497. continue;
  498. op00 = (((op00 >> 10) & 0x3f) << 21) | (((op00 >> 19) & 0x1f) << 11) | (op00 >> 3 & 0x1f);
  499. op10 = (((op10 >> 10) & 0x3f) << 21) | (((op10 >> 19) & 0x1f) << 11) | (op10 >> 3 & 0x1f);
  500. op01 = (((op01 >> 10) & 0x3f) << 21) | (((op01 >> 19) & 0x1f) << 11) | (op01 >> 3 & 0x1f);
  501. op11 = (((op11 >> 10) & 0x3f) << 21) | (((op11 >> 19) & 0x1f) << 11) | (op11 >> 3 & 0x1f);
  502. if (sx)
  503. {
  504. op00 = ((op01 - op00) * sx / 32 + op00) & 0x07e0f81f;
  505. }
  506. if (sx && sy)
  507. {
  508. op10 = ((op11 - op10) * sx / 32 + op10) & 0x07e0f81f;
  509. }
  510. if (sy)
  511. {
  512. op00 = ((op10 - op00) * sy / 32 + op00) & 0x07e0f81f;
  513. }
  514. if (a00 == (255 >> 3))
  515. {
  516. *dstp = op00 | (op00 >> 16);
  517. }
  518. else if (a00 != 0)
  519. {
  520. rt_uint32_t d = *dstp;
  521. d = (d | d << 16) & 0x07e0f81f;
  522. d += (op00 - d) * a00 >> 5;
  523. d &= 0x07e0f81f;
  524. *dstp = (rt_uint16_t)(d | d >> 16);
  525. }
  526. }
  527. dstp += dst->skip - neww;
  528. }
  529. }
  530. static void _blit_rotate_B2B(struct rtgui_dc_trans *dct,
  531. const struct rtgui_point *dc_point,
  532. struct rtgui_dc_buffer* RTGUI_RESTRICT dest,
  533. struct rtgui_rect *rect,
  534. const struct rtgui_matrix *invm,
  535. int neww, int newh)
  536. {
  537. struct rtgui_rect srcrect;
  538. struct rtgui_dc_buffer *dc = (struct rtgui_dc_buffer*)dct->owner;
  539. struct _fb_rect srcfb, dstfb;
  540. rtgui_dc_get_rect(dct->owner, &srcrect);
  541. srcfb.fb = ((struct rtgui_dc_buffer*)dct->owner)->pixel;
  542. srcfb.width = srcrect.x2;
  543. srcfb.height = srcrect.y2;
  544. srcfb.skip = 0;
  545. dstfb.fb = dest->pixel + rtgui_color_get_bpp(dest->pixel_format) * (rect->x1 + rect->y1 * dest->width);
  546. dstfb.width = neww;
  547. dstfb.height = newh;
  548. dstfb.skip = dest->width;
  549. if (dc->pixel_format == dest->pixel_format)
  550. {
  551. switch (rtgui_color_get_bpp(dest->pixel_format))
  552. {
  553. case 2:
  554. if (dct->use_aa)
  555. _blit_rotate_FR2FR_SF2B_AA(&srcfb, dc_point,
  556. &dstfb, invm);
  557. else
  558. _blit_rotate_FR2FR_SF2B(&srcfb, dc_point,
  559. &dstfb, invm);
  560. break;
  561. case 4:
  562. if (dct->use_aa)
  563. _blit_rotate_FR2FR_SF4B_AA(&srcfb, dc_point,
  564. &dstfb, invm);
  565. else
  566. _blit_rotate_FR2FR_SF4B(&srcfb, dc_point,
  567. &dstfb, invm);
  568. break;
  569. default:
  570. rt_kprintf("could not handle bpp: %d\n",
  571. rtgui_color_get_bpp(dest->pixel_format));
  572. return;
  573. }
  574. }
  575. else if (dc->pixel_format == RTGRAPHIC_PIXEL_FORMAT_ARGB888 &&
  576. dest->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565)
  577. {
  578. if (dct->use_aa)
  579. _blit_rotate_FR2FR_ARGB2RGB565_AA(&srcfb, dc_point,
  580. &dstfb, invm);
  581. else
  582. _blit_rotate_FR2FR_ARGB2RGB565(&srcfb, dc_point,
  583. &dstfb, invm);
  584. }
  585. else
  586. {
  587. rt_kprintf("not implemented yet\n");
  588. return;
  589. }
  590. }
  591. static void _blit_rotate_B2H(struct rtgui_dc_trans *dct,
  592. const struct rtgui_point *dc_point,
  593. struct rtgui_dc_hw* dest,
  594. struct rtgui_rect *rect,
  595. const struct rtgui_matrix *invm,
  596. int neww, int newh)
  597. {
  598. struct rtgui_rect srcrect;
  599. int start_pix;
  600. struct _fb_rect srcfb, dstfb;
  601. struct rtgui_dc_buffer *dc = (struct rtgui_dc_buffer*)dct->owner;
  602. if (dest->hw_driver->framebuffer == RT_NULL)
  603. {
  604. rt_kprintf("Only support framebuffer hw dc\n");
  605. return;
  606. }
  607. rtgui_dc_get_rect(dct->owner, &srcrect);
  608. srcfb.fb = ((struct rtgui_dc_buffer*)dct->owner)->pixel;
  609. srcfb.width = srcrect.x2;
  610. srcfb.height = srcrect.y2;
  611. srcfb.skip = 0;
  612. /* Start point of the widget. */
  613. start_pix = dest->owner->extent.x1 + dest->owner->extent.y1 * dest->hw_driver->width;
  614. /* Start point of the inner rect. */
  615. start_pix += rect->x1 + rect->y1 * dest->hw_driver->width;
  616. dstfb.fb = (void*)(dest->hw_driver->framebuffer
  617. + rtgui_color_get_bpp(dest->hw_driver->pixel_format) * start_pix);
  618. dstfb.width = neww;
  619. dstfb.height = newh;
  620. dstfb.skip = dest->hw_driver->width;
  621. if (dc->pixel_format == dest->hw_driver->pixel_format)
  622. {
  623. switch (rtgui_color_get_bpp(dest->hw_driver->pixel_format))
  624. {
  625. case 2:
  626. if (dct->use_aa)
  627. _blit_rotate_FR2FR_SF2B_AA(&srcfb, dc_point,
  628. &dstfb, invm);
  629. else
  630. _blit_rotate_FR2FR_SF2B(&srcfb, dc_point,
  631. &dstfb, invm);
  632. break;
  633. case 4:
  634. if (dct->use_aa)
  635. _blit_rotate_FR2FR_SF4B_AA(&srcfb, dc_point,
  636. &dstfb, invm);
  637. else
  638. _blit_rotate_FR2FR_SF4B(&srcfb, dc_point,
  639. &dstfb, invm);
  640. break;
  641. default:
  642. rt_kprintf("could not handle bpp: %d\n",
  643. rtgui_color_get_bpp(dest->hw_driver->pixel_format));
  644. return;
  645. }
  646. }
  647. else if (dc->pixel_format == RTGRAPHIC_PIXEL_FORMAT_ARGB888 &&
  648. dest->hw_driver->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565)
  649. {
  650. if (dct->use_aa)
  651. _blit_rotate_FR2FR_ARGB2RGB565_AA(&srcfb, dc_point,
  652. &dstfb, invm);
  653. else
  654. _blit_rotate_FR2FR_ARGB2RGB565(&srcfb, dc_point,
  655. &dstfb, invm);
  656. }
  657. else
  658. {
  659. rt_kprintf("not implemented yet\n");
  660. return;
  661. }
  662. }
  663. void rtgui_dc_trans_blit(struct rtgui_dc_trans *dct,
  664. struct rtgui_point *dc_point,
  665. struct rtgui_dc *dest,
  666. struct rtgui_rect *rect)
  667. {
  668. struct rtgui_rect bkrect;
  669. struct rtgui_matrix invm;
  670. struct rtgui_point dp;
  671. int neww, newh;
  672. RT_ASSERT(dct);
  673. RT_ASSERT(dest);
  674. if (dc_point == RT_NULL)
  675. {
  676. dp.x = dp.y = 0;
  677. dc_point = &dp;
  678. }
  679. if (rect == RT_NULL)
  680. {
  681. rtgui_dc_get_rect(dest, &bkrect);
  682. rect = &bkrect;
  683. }
  684. rtgui_dc_trans_get_new_wh(dct, &neww, &newh);
  685. if (dc_point->x < 0)
  686. {
  687. neww -= dc_point->x;
  688. if (neww < 0)
  689. return;
  690. dc_point->x = 0;
  691. }
  692. else if (dc_point->x > neww)
  693. return;
  694. if (dc_point->y < 0)
  695. {
  696. newh -= dc_point->y;
  697. if (newh < 0)
  698. return;
  699. dc_point->y = 0;
  700. }
  701. else if (dc_point->y > newh)
  702. return;
  703. if (rtgui_matrix_inverse(&dct->m, &invm))
  704. return;
  705. if (rtgui_rect_width(*rect) < neww - dc_point->x)
  706. neww = dc_point->x + rtgui_rect_width(*rect);
  707. if (rtgui_rect_height(*rect) < newh - dc_point->y)
  708. newh = dc_point->y + rtgui_rect_height(*rect);
  709. /* Route to different optimized routines. */
  710. if (dct->owner->type == RTGUI_DC_BUFFER)
  711. {
  712. if (dest->type == RTGUI_DC_BUFFER)
  713. _blit_rotate_B2B(dct, dc_point,
  714. (struct rtgui_dc_buffer*)dest,
  715. rect, &invm, neww, newh);
  716. else if (dest->type == RTGUI_DC_HW)
  717. _blit_rotate_B2H(dct, dc_point,
  718. (struct rtgui_dc_hw*)dest,
  719. rect, &invm, neww, newh);
  720. else if (dest->type == RTGUI_DC_CLIENT)
  721. // TODO:
  722. ;
  723. else
  724. rt_kprintf("unknown dc for dc_trans\n");
  725. }
  726. else
  727. rt_kprintf("not implemented yet\n");
  728. }
  729. RTM_EXPORT(rtgui_dc_trans_blit);