ROTBMP.CPP 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. /*
  2. ** Command & Conquer Red Alert(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /* $Header: /CounterStrike/ROTBMP.CPP 1 3/03/97 10:25a Joe_bostic $ */
  19. /***********************************************************************************************
  20. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : Command & Conquer *
  24. * *
  25. * File Name : ROTBMP.CPP *
  26. * *
  27. * Programmer : Joe L. Bostic *
  28. * *
  29. * Start Date : 07/05/96 *
  30. * *
  31. * Last Update : July 5, 1996 [JLB] *
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  36. //#include "function.h"
  37. #include "watcom.h"
  38. #include "rotbmp.h"
  39. #define FILE_H
  40. #define WWMEM_H
  41. #include <wwlib32.h>
  42. int Rotate_Bitmap(GraphicViewPortClass * srcvp, GraphicViewPortClass * destvp, int angle);
  43. struct WPPOINT {
  44. int x;
  45. int y;
  46. };
  47. /***************************************************************************
  48. * Rotate_bitmap -- rotate a bitmap from srcvp to destvp *
  49. * *
  50. * INPUT: note that angles are 0 - 255 (best if used in increments of 4!) *
  51. * *
  52. * OUTPUT: *
  53. * *
  54. * WARNINGS: *
  55. * destvp should be a square. width and height should be equal to : *
  56. * MAX(srcvp->width,srcvp->height) * 1.7 (square root of 2!!) *
  57. * *
  58. * *
  59. * HISTORY: *
  60. * 01/02/1996 BP : Created. *
  61. *=========================================================================*/
  62. Rotate_Bitmap(GraphicViewPortClass * srcvp, GraphicViewPortClass * destvp, int a)
  63. {
  64. int shift = 7;
  65. int fixpoint1 = 1 << shift; // this is a fixed point 1
  66. int Deltax;
  67. int Deltay;
  68. int sx,sy,dx,dy;
  69. int Error = 0;
  70. int Decimal = 0;
  71. // this is used if I walk in Y
  72. int buffwidth = srcvp->Get_Width() + srcvp->Get_XAdd();
  73. int buffwid2 = destvp->Get_Width() + destvp->Get_XAdd();
  74. char * dest;
  75. char * src;
  76. int sa,ca;
  77. int t;
  78. int x,y;
  79. int rx,ry;
  80. int w,h;
  81. int dw = destvp->Get_Width();
  82. int dh = destvp->Get_Height();
  83. WPPOINT sp[4];
  84. WPPOINT dp[4];
  85. sa = Sin256[a];
  86. ca = Cos256[a];
  87. // get rectangle size
  88. x = 0;
  89. y = 0;
  90. w = srcvp->Get_Width();
  91. h = srcvp->Get_Height();
  92. int halfws = w >> 1;
  93. int halfhs = h >> 1;
  94. int halfwd = dw >> 1;
  95. int halfhd = dh >> 1;
  96. // make the src rectangle
  97. sp[0].x = x;
  98. sp[0].y = y;
  99. sp[1].x = x + w;
  100. sp[1].y = y;
  101. // now calculate the rotated rectangle
  102. dp[0].x = ( ((sp[0].x - halfws) * ca) - ((sp[0].y - halfhs) * sa) ) >> shift;
  103. dp[0].x += halfwd;
  104. dp[0].y = ( ((sp[0].x - halfws) * sa) + ((sp[0].y - halfhs) * ca) ) >> shift;
  105. dp[0].y += halfhd;
  106. dp[1].x = ( ((sp[1].x - halfws) * ca) - ((sp[1].y - halfhs) * sa) ) >> shift;
  107. dp[1].x += halfwd;
  108. dp[1].y = ( ((sp[1].x - halfws) * sa) + ((sp[1].y - halfhs) * ca) ) >> shift;
  109. dp[1].y += halfhd;
  110. rx = dp[0].x;
  111. ry = dp[0].y;
  112. // now calculate slope
  113. // diff from new to old x
  114. Deltax = (dp[1].x - dp[0].x);
  115. // diff from new to old y
  116. Deltay = (dp[1].y - dp[0].y);
  117. // handle the easy cases
  118. // no change in x
  119. int r;
  120. if (!Deltax) { // must be 90 or 270 degree transpose!
  121. if (Deltay < 0) {
  122. // walk across source in the x + dir
  123. // walk across dest in the y - dir
  124. x = 0;
  125. dy = 0;
  126. dx = 0;
  127. for (t = 0; t< h; t++) {
  128. x = 0;
  129. src = MAKE_PTR(srcvp, x, y);
  130. dest = MAKE_PTR(destvp, rx + dx, ry - dy);
  131. for (r = 0; r< w; r++) {
  132. // transparency
  133. if (* src)
  134. *dest = *src;
  135. src++;
  136. dest -= buffwid2;
  137. }
  138. y++;
  139. dx++;
  140. }
  141. } else {
  142. // walk across source in the x + dir
  143. // walk across dest in the y + dir
  144. x = 0;
  145. dy = 0;
  146. dx = 0;
  147. for (t = 0; t< h; t++) {
  148. x = 0;
  149. src = MAKE_PTR(srcvp, x, y);
  150. dest = MAKE_PTR(destvp, rx - dx, ry + dy);
  151. for (r = 0; r< w; r++) {
  152. // transparency
  153. if (*src)
  154. *dest = *src;
  155. src++;
  156. dest += buffwid2;
  157. }
  158. y++;
  159. dx++;
  160. }
  161. }
  162. return 0;
  163. }
  164. // no change in y
  165. if (!Deltay) { // must be 0 or 180 degree transpose !
  166. if (Deltax < 0) {
  167. y = 0;
  168. for (y = 0; y< h; y++) {
  169. x = 0;
  170. src = MAKE_PTR(srcvp, x, y);
  171. dest = MAKE_PTR(destvp, rx - x , ry - y);
  172. for (x = 0 ; x< w; x++) {
  173. // transparency
  174. if (*src)
  175. *dest = *src;
  176. dest--;
  177. src++;
  178. }
  179. }
  180. } else {
  181. for (y = 0; y< h; y++) {
  182. x = 0;
  183. src = MAKE_PTR(srcvp, x, y);
  184. dest = MAKE_PTR(destvp, rx + x, ry + y);
  185. for (x = 0 ; x< w; x++) {
  186. // transparency
  187. if (*src)
  188. *dest = *src;
  189. dest++;
  190. src++;
  191. }
  192. }
  193. }
  194. return 0;
  195. }
  196. // ok now the hard part
  197. // make them 16.16
  198. if ( ABS(Deltax) < ABS(Deltay)) { // ok this means we want to walk in y
  199. // walk in + x in the src and
  200. // walk in + y in the dest
  201. Error = 0;
  202. // start at left top corner in src and dest
  203. sx = 0;
  204. sy = 0;
  205. dx = 0;
  206. dy = 0;
  207. dest = MAKE_PTR(destvp, rx + dx, ry + dy);
  208. src = MAKE_PTR(srcvp, x + sx, y + sy);
  209. // this gets added to error each inc of x
  210. // when error is > 1 then inc y!
  211. int xinc = 1;
  212. if (Deltax < 0) {
  213. Deltax = -Deltax;
  214. xinc = -1;
  215. }
  216. int yinc = 1;
  217. int yinc1 = 1;
  218. if (Deltay < 0) {
  219. Deltay = - Deltay;
  220. buffwid2 = - buffwid2;
  221. }
  222. Decimal = ( Deltax << shift) / Deltay ;
  223. // walk in X
  224. int Deltax2 = Deltax << shift;
  225. int Deltay2 = Deltay << shift;
  226. // this is the ratio between the source height and the dest height
  227. // as the rectangle rotates the height and width change
  228. int DeltaH = (w << shift) / Deltay;
  229. int Error2 = 0;
  230. sy = 0;
  231. for (int r = 0; r< h ;r++) {
  232. // now we walk across the top calculating each rotated point
  233. // along the side
  234. // the use delta formula to walk in x and y in destination space
  235. // always walking in the x in the source!
  236. // figure out rotated location to start in dest
  237. rx = ( ( (sx - halfws) * ca) - ( (sy - halfhs) * sa) ) >> shift;
  238. rx += halfwd;
  239. ry = ( ( (sx - halfws) * sa) + ( (sy - halfhs) * ca) ) >> shift;
  240. ry += halfhd;
  241. // this is the end point of the line
  242. int y2 = ( ( ((w) - halfws) * sa) + ( (sy - halfhs) * ca) ) >> shift;
  243. y2 += halfhd;
  244. // length of line
  245. int diff = ABS(y2 - ry);
  246. // if walking backwards reveres diff to reflect sign
  247. src = MAKE_PTR(srcvp, x, y + sy);
  248. dest = MAKE_PTR(destvp, rx, ry);
  249. Error = 0;
  250. Error2 = 0;
  251. char * baseptr = src;
  252. // while walking line
  253. while (diff--) {
  254. char c = *src;
  255. // transparency
  256. if (c)
  257. *dest = *src;
  258. Error2 += DeltaH;
  259. dest += buffwid2;
  260. Error += Decimal;
  261. src = baseptr + (Error2 >> shift) ;
  262. // this is time to inc x in src y in dest
  263. if (Error >= fixpoint1) {
  264. Error -= fixpoint1;
  265. if (*src)
  266. *dest = *src;
  267. dest += xinc;
  268. }
  269. }
  270. sy += yinc;
  271. }
  272. return 0;
  273. } else { // else we walk in X
  274. int lasterror = 0;
  275. Error = 0;
  276. // start at left top corner in src and dest
  277. sx = 0;
  278. sy = 0;
  279. dx = 0;
  280. dy = 0;
  281. dest = MAKE_PTR(destvp, rx + dx, ry + dy);
  282. src = MAKE_PTR(srcvp, x + sx, y + sy);
  283. // this gets added to error each inc of x
  284. // when error is > 1 then inc y!
  285. int xinc = 1;
  286. if (Deltax < 0) {
  287. Deltax = -Deltax;
  288. xinc = -1;
  289. }
  290. int yinc = 1;
  291. if (Deltay < 0) {
  292. Deltay = - Deltay;
  293. buffwid2 = - buffwid2;
  294. sy = sy + h - 1;
  295. yinc = -1;
  296. }
  297. Decimal = ( Deltay << shift) / Deltax ;
  298. // walk in X
  299. int Deltax2 = Deltax << shift;
  300. int Deltay2 = Deltay << shift;
  301. // this is the ratios between the source width and the dest width
  302. // as the rectangle rotates the actual size changes!
  303. int DeltaW = (w << shift) / Deltax;
  304. int Error2 = 0;
  305. for (int r = 0; r< h ;r++) {
  306. sx = 0;
  307. // now we walk across the side calculating each rotated point
  308. // along the side
  309. // the use delta formula to walk in x and y in destination space
  310. // always walking in the x in the source!
  311. // figure out rotated location to start
  312. rx = ( ( (sx - halfws) * ca) - ( (sy - halfhs) * sa) ) >> shift;
  313. rx += halfwd;
  314. ry = ( ( (sx - halfws) * sa) + ( (sy - halfhs) * ca) ) >> shift;
  315. ry += halfhd;
  316. // this is the other side of the box
  317. int x2 = ( ( ((sx + w) - halfws) * ca) - ( (sy - halfhs) * sa) ) >> shift;
  318. x2 += halfwd;
  319. int diff = x2 - rx;
  320. dx = 0;
  321. dy = 0;
  322. if (xinc == -1) {
  323. diff = -diff;
  324. }
  325. src = MAKE_PTR(srcvp, x + sx, y + sy);
  326. dest = MAKE_PTR(destvp, rx + dx, ry + dy);
  327. Error = 0;
  328. Error2 = 0;
  329. char * baseptr = src;
  330. while (diff--) {
  331. char c = *src;
  332. // transparency
  333. if (c)
  334. *dest = *src;
  335. Error2 += DeltaW;
  336. rx++;
  337. dest += xinc;
  338. Error += Decimal;
  339. src = baseptr + (Error2 >> shift);
  340. if (Error >= fixpoint1) {
  341. Error -= fixpoint1;
  342. if (*src)
  343. *dest = *src;
  344. dest += buffwid2;
  345. }
  346. }
  347. sy += yinc;
  348. }
  349. }
  350. return 0;
  351. }