matrix.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /*
  2. * File : matrix.c
  3. * This file is part of RT-Thread GUI Engine
  4. * COPYRIGHT (C) 2006 - 2017, 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. * 2009-10-16 Grissiom first version
  23. */
  24. #include <rtgui/rtgui.h>
  25. #include <rtgui/matrix.h>
  26. /* Port from ejoy2d: https://github.com/cloudwu/ejoy2d/blob/master/LICENSE
  27. * Original License:
  28. *
  29. * The MIT License (MIT)
  30. *
  31. * Copyright (c) 2013 Ejoy.com Inc.
  32. *
  33. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  34. * this software and associated documentation files (the "Software"), to deal in
  35. * the Software without restriction, including without limitation the rights to
  36. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  37. * the Software, and to permit persons to whom the Software is furnished to do so,
  38. * subject to the following conditions:
  39. *
  40. * The above copyright notice and this permission notice shall be included in all
  41. * copies or substantial portions of the Software.
  42. *
  43. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  44. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  45. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  46. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  47. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  48. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  49. */
  50. /* Port to RTGUI by Grissiom */
  51. rt_inline int _inverse_scale(const int *m , int *o)
  52. {
  53. if (m[0] == 0 || m[3] == 0)
  54. return 1;
  55. o[0] = _rtgui_matrix_round_div32(RTGUI_MATRIX_FRAC * RTGUI_MATRIX_FRAC, m[0]);
  56. o[1] = 0;
  57. o[2] = 0;
  58. o[3] = _rtgui_matrix_round_div32(RTGUI_MATRIX_FRAC * RTGUI_MATRIX_FRAC, m[3]);
  59. o[4] = _rtgui_matrix_round_div32(-m[4] * o[0], RTGUI_MATRIX_FRAC);
  60. o[5] = _rtgui_matrix_round_div32(-m[5] * o[3], RTGUI_MATRIX_FRAC);
  61. return 0;
  62. }
  63. rt_inline int _inverse_rot(const int *m, int *o)
  64. {
  65. if (m[1] == 0 || m[2] == 0)
  66. return 1;
  67. o[0] = 0;
  68. o[1] = _rtgui_matrix_round_div32(RTGUI_MATRIX_FRAC * RTGUI_MATRIX_FRAC, m[2]);
  69. o[2] = _rtgui_matrix_round_div32(RTGUI_MATRIX_FRAC * RTGUI_MATRIX_FRAC, m[1]);
  70. o[3] = 0;
  71. o[4] = _rtgui_matrix_round_div32(-m[5] * o[2], RTGUI_MATRIX_FRAC);
  72. o[5] = _rtgui_matrix_round_div32(-m[4] * o[1], RTGUI_MATRIX_FRAC);
  73. return 0;
  74. }
  75. int rtgui_matrix_inverse(const struct rtgui_matrix *mm, struct rtgui_matrix *mo)
  76. {
  77. const int *m = mm->m;
  78. int *o = mo->m;
  79. int t;
  80. if (m[1] == 0 && m[2] == 0)
  81. {
  82. return _inverse_scale(m,o);
  83. }
  84. if (m[0] == 0 && m[3] == 0)
  85. {
  86. return _inverse_rot(m,o);
  87. }
  88. t = m[0] * m[3] - m[1] * m[2];
  89. if (t == 0)
  90. return 1;
  91. o[0] = _rtgui_matrix_round_div6432((int64_t)m[3] * (RTGUI_MATRIX_FRAC * RTGUI_MATRIX_FRAC), t);
  92. o[1] = _rtgui_matrix_round_div6432(-(int64_t)m[1] * (RTGUI_MATRIX_FRAC * RTGUI_MATRIX_FRAC), t);
  93. o[2] = _rtgui_matrix_round_div6432(-(int64_t)m[2] * (RTGUI_MATRIX_FRAC * RTGUI_MATRIX_FRAC), t);
  94. o[3] = _rtgui_matrix_round_div6432((int64_t)m[0] * (RTGUI_MATRIX_FRAC * RTGUI_MATRIX_FRAC), t);
  95. o[4] = _rtgui_matrix_round_div6432(-((int64_t)m[4] * o[0] + (int64_t)m[5] * o[2]), RTGUI_MATRIX_FRAC);
  96. o[5] = _rtgui_matrix_round_div6432(-((int64_t)m[4] * o[1] + (int64_t)m[5] * o[3]), RTGUI_MATRIX_FRAC);
  97. return 0;
  98. }
  99. #define COS_TABLE_SZ 512
  100. /* @dd is the degree range in 0~512 */
  101. rt_inline int icost(int dd)
  102. {
  103. static const short t[COS_TABLE_SZ] =
  104. {
  105. 2048, 2048, 2047, 2047, 2046, 2044, 2042, 2040, 2038, 2036, 2033, 2029, 2026,
  106. 2022, 2018, 2013, 2009, 2004, 1998, 1993, 1987, 1980, 1974, 1967, 1960, 1952,
  107. 1945, 1937, 1928, 1920, 1911, 1902, 1892, 1882, 1872, 1862, 1851, 1840, 1829,
  108. 1818, 1806, 1794, 1782, 1769, 1757, 1744, 1730, 1717, 1703, 1689, 1674, 1660,
  109. 1645, 1630, 1615, 1599, 1583, 1567, 1551, 1534, 1517, 1500, 1483, 1466, 1448,
  110. 1430, 1412, 1394, 1375, 1357, 1338, 1319, 1299, 1280, 1260, 1240, 1220, 1200,
  111. 1179, 1159, 1138, 1117, 1096, 1074, 1053, 1031, 1009, 988, 965, 943, 921, 898,
  112. 876, 853, 830, 807, 784, 760, 737, 714, 690, 666, 642, 619, 595, 570, 546, 522,
  113. 498, 473, 449, 424, 400, 375, 350, 325, 301, 276, 251, 226, 201, 176, 151, 126,
  114. 100, 75, 50, 25, 0, -25, -50, -75, -100, -126, -151, -176, -201, -226, -251,
  115. -276, -301, -325, -350, -375, -400, -424, -449, -473, -498, -522, -546, -570,
  116. -595, -619, -642, -666, -690, -714, -737, -760, -784, -807, -830, -853, -876,
  117. -898, -921, -943, -965, -988, -1009, -1031, -1053, -1074, -1096, -1117, -1138,
  118. -1159, -1179, -1200, -1220, -1240, -1260, -1280, -1299, -1319, -1338, -1357,
  119. -1375, -1394, -1412, -1430, -1448, -1466, -1483, -1500, -1517, -1534, -1551,
  120. -1567, -1583, -1599, -1615, -1630, -1645, -1660, -1674, -1689, -1703, -1717,
  121. -1730, -1744, -1757, -1769, -1782, -1794, -1806, -1818, -1829, -1840, -1851,
  122. -1862, -1872, -1882, -1892, -1902, -1911, -1920, -1928, -1937, -1945, -1952,
  123. -1960, -1967, -1974, -1980, -1987, -1993, -1998, -2004, -2009, -2013, -2018,
  124. -2022, -2026, -2029, -2033, -2036, -2038, -2040, -2042, -2044, -2046, -2047,
  125. -2047, -2048, -2048, -2048, -2047, -2047, -2046, -2044, -2042, -2040, -2038,
  126. -2036, -2033, -2029, -2026, -2022, -2018, -2013, -2009, -2004, -1998, -1993,
  127. -1987, -1980, -1974, -1967, -1960, -1952, -1945, -1937, -1928, -1920, -1911,
  128. -1902, -1892, -1882, -1872, -1862, -1851, -1840, -1829, -1818, -1806, -1794,
  129. -1782, -1769, -1757, -1744, -1730, -1717, -1703, -1689, -1674, -1660, -1645,
  130. -1630, -1615, -1599, -1583, -1567, -1551, -1534, -1517, -1500, -1483, -1466,
  131. -1448, -1430, -1412, -1394, -1375, -1357, -1338, -1319, -1299, -1280, -1260,
  132. -1240, -1220, -1200, -1179, -1159, -1138, -1117, -1096, -1074, -1053, -1031,
  133. -1009, -988, -965, -943, -921, -898, -876, -853, -830, -807, -784, -760, -737,
  134. -714, -690, -666, -642, -619, -595, -570, -546, -522, -498, -473, -449, -424,
  135. -400, -375, -350, -325, -301, -276, -251, -226, -201, -176, -151, -126, -100,
  136. -75, -50, -25, 0, 25, 50, 75, 100, 126, 151, 176, 201, 226, 251, 276, 301, 325,
  137. 350, 375, 400, 424, 449, 473, 498, 522, 546, 570, 595, 619, 642, 666, 690, 714,
  138. 737, 760, 784, 807, 830, 853, 876, 898, 921, 943, 965, 988, 1009, 1031, 1053,
  139. 1074, 1096, 1117, 1138, 1159, 1179, 1200, 1220, 1240, 1260, 1280, 1299, 1319,
  140. 1338, 1357, 1375, 1394, 1412, 1430, 1448, 1466, 1483, 1500, 1517, 1534, 1551,
  141. 1567, 1583, 1599, 1615, 1630, 1645, 1660, 1674, 1689, 1703, 1717, 1730, 1744,
  142. 1757, 1769, 1782, 1794, 1806, 1818, 1829, 1840, 1851, 1862, 1872, 1882, 1892,
  143. 1902, 1911, 1920, 1928, 1937, 1945, 1952, 1960, 1967, 1974, 1980, 1987, 1993,
  144. 1998, 2004, 2009, 2013, 2018, 2022, 2026, 2029, 2033, 2036, 2038, 2040, 2042,
  145. 2044, 2046, 2047, 2047, 2048,
  146. };
  147. dd &= COS_TABLE_SZ - 1;
  148. return t[dd];
  149. }
  150. rt_inline int icosd(int d)
  151. {
  152. int dd = d;
  153. return icost(dd);
  154. }
  155. rt_inline int isind(int d)
  156. {
  157. int dd = COS_TABLE_SZ / 4 - d;
  158. return icost(dd);
  159. }
  160. rt_inline void rot_mat(int *m, int d)
  161. {
  162. int cosd = icosd(d);
  163. int sind = isind(d);
  164. int m0_cosd = m[0] * cosd;
  165. int m0_sind = m[0] * sind;
  166. int m1_cosd = m[1] * cosd;
  167. int m1_sind = m[1] * sind;
  168. int m2_cosd = m[2] * cosd;
  169. int m2_sind = m[2] * sind;
  170. int m3_cosd = m[3] * cosd;
  171. int m3_sind = m[3] * sind;
  172. int m4_cosd = m[4] * cosd;
  173. int m4_sind = m[4] * sind;
  174. int m5_cosd = m[5] * cosd;
  175. int m5_sind = m[5] * sind;
  176. m[0] = _rtgui_matrix_round_div32(m0_cosd - m1_sind, RTGUI_MATRIX_FRAC);
  177. m[1] = _rtgui_matrix_round_div32(m0_sind + m1_cosd, RTGUI_MATRIX_FRAC);
  178. m[2] = _rtgui_matrix_round_div32(m2_cosd - m3_sind, RTGUI_MATRIX_FRAC);
  179. m[3] = _rtgui_matrix_round_div32(m2_sind + m3_cosd, RTGUI_MATRIX_FRAC);
  180. m[4] = _rtgui_matrix_round_div32(m4_cosd - m5_sind, RTGUI_MATRIX_FRAC);
  181. m[5] = _rtgui_matrix_round_div32(m4_sind + m5_cosd, RTGUI_MATRIX_FRAC);
  182. }
  183. rt_inline void scale_mat(int *m, int sx, int sy)
  184. {
  185. if (sx != RTGUI_MATRIX_FRAC)
  186. {
  187. m[0] = _rtgui_matrix_round_div32(m[0] * sx, RTGUI_MATRIX_FRAC);
  188. m[2] = _rtgui_matrix_round_div32(m[2] * sx, RTGUI_MATRIX_FRAC);
  189. m[4] = _rtgui_matrix_round_div32(m[4] * sx, RTGUI_MATRIX_FRAC);
  190. }
  191. if (sy != RTGUI_MATRIX_FRAC)
  192. {
  193. m[1] = _rtgui_matrix_round_div32(m[1] * sy, RTGUI_MATRIX_FRAC);
  194. m[3] = _rtgui_matrix_round_div32(m[3] * sy, RTGUI_MATRIX_FRAC);
  195. m[5] = _rtgui_matrix_round_div32(m[5] * sy, RTGUI_MATRIX_FRAC);
  196. }
  197. }
  198. void rtgui_matrix_rotate(struct rtgui_matrix *m, int rot)
  199. {
  200. if (rot)
  201. rot_mat(m->m, rot / (RTGUI_MATRIX_FRAC / COS_TABLE_SZ));
  202. }
  203. RTM_EXPORT(rtgui_matrix_rotate);
  204. void rtgui_matrix_scale(struct rtgui_matrix *m, int sx, int sy)
  205. {
  206. scale_mat(m->m, sx, sy);
  207. }
  208. void rtgui_matrix_move(struct rtgui_matrix *m, int dx, int dy)
  209. {
  210. m->m[4] += dx;
  211. m->m[5] += dy;
  212. }
  213. void rtgui_matrix_dump(const struct rtgui_matrix *m)
  214. {
  215. const int *mm = m->m;
  216. rt_kprintf("|%6d, %6d, %6d|\n", mm[0], mm[1], 0);
  217. rt_kprintf("|%6d, %6d, %6d|\n", mm[2], mm[3], 0);
  218. rt_kprintf("|%6d, %6d, %6d|\n", mm[4], mm[5], 1);
  219. }