ROTBMP.CPP (11107B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 16 /* $Header: /CounterStrike/ROTBMP.CPP 1 3/03/97 10:25a Joe_bostic $ */ 17 /*********************************************************************************************** 18 *** 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 *** 19 *********************************************************************************************** 20 * * 21 * Project Name : Command & Conquer * 22 * * 23 * File Name : ROTBMP.CPP * 24 * * 25 * Programmer : Joe L. Bostic * 26 * * 27 * Start Date : 07/05/96 * 28 * * 29 * Last Update : July 5, 1996 [JLB] * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * Functions: * 33 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 34 35 #if (0)//PG 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 43 44 int Rotate_Bitmap(GraphicViewPortClass * srcvp, GraphicViewPortClass * destvp, int angle); 45 46 struct WPPOINT { 47 int x; 48 int y; 49 }; 50 51 /*************************************************************************** 52 * Rotate_bitmap -- rotate a bitmap from srcvp to destvp * 53 * * 54 * INPUT: note that angles are 0 - 255 (best if used in increments of 4!) * 55 * * 56 * OUTPUT: * 57 * * 58 * WARNINGS: * 59 * destvp should be a square. width and height should be equal to : * 60 * MAX(srcvp->width,srcvp->height) * 1.7 (square root of 2!!) * 61 * * 62 * * 63 * HISTORY: * 64 * 01/02/1996 BP : Created. * 65 *=========================================================================*/ 66 Rotate_Bitmap(GraphicViewPortClass * srcvp, GraphicViewPortClass * destvp, int a) 67 { 68 int shift = 7; 69 int fixpoint1 = 1 << shift; // this is a fixed point 1 70 int Deltax; 71 int Deltay; 72 int sx,sy,dx,dy; 73 int Error = 0; 74 int Decimal = 0; 75 // this is used if I walk in Y 76 int buffwidth = srcvp->Get_Width() + srcvp->Get_XAdd(); 77 int buffwid2 = destvp->Get_Width() + destvp->Get_XAdd(); 78 char * dest; 79 char * src; 80 int sa,ca; 81 int t; 82 int x,y; 83 int rx,ry; 84 int w,h; 85 int dw = destvp->Get_Width(); 86 int dh = destvp->Get_Height(); 87 WPPOINT sp[4]; 88 WPPOINT dp[4]; 89 sa = Sin256[a]; 90 ca = Cos256[a]; 91 // get rectangle size 92 x = 0; 93 y = 0; 94 w = srcvp->Get_Width(); 95 h = srcvp->Get_Height(); 96 97 int halfws = w >> 1; 98 int halfhs = h >> 1; 99 int halfwd = dw >> 1; 100 int halfhd = dh >> 1; 101 102 103 // make the src rectangle 104 sp[0].x = x; 105 sp[0].y = y; 106 107 sp[1].x = x + w; 108 sp[1].y = y; 109 110 // now calculate the rotated rectangle 111 dp[0].x = ( ((sp[0].x - halfws) * ca) - ((sp[0].y - halfhs) * sa) ) >> shift; 112 dp[0].x += halfwd; 113 114 dp[0].y = ( ((sp[0].x - halfws) * sa) + ((sp[0].y - halfhs) * ca) ) >> shift; 115 dp[0].y += halfhd; 116 117 dp[1].x = ( ((sp[1].x - halfws) * ca) - ((sp[1].y - halfhs) * sa) ) >> shift; 118 dp[1].x += halfwd; 119 120 dp[1].y = ( ((sp[1].x - halfws) * sa) + ((sp[1].y - halfhs) * ca) ) >> shift; 121 dp[1].y += halfhd; 122 123 rx = dp[0].x; 124 ry = dp[0].y; 125 // now calculate slope 126 127 // diff from new to old x 128 129 Deltax = (dp[1].x - dp[0].x); 130 131 // diff from new to old y 132 133 Deltay = (dp[1].y - dp[0].y); 134 135 // handle the easy cases 136 137 // no change in x 138 int r; 139 if (!Deltax) { // must be 90 or 270 degree transpose! 140 if (Deltay < 0) { 141 // walk across source in the x + dir 142 // walk across dest in the y - dir 143 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 } else { 162 // walk across source in the x + dir 163 // walk across dest in the y + dir 164 165 x = 0; 166 dy = 0; 167 dx = 0; 168 for (t = 0; t< h; t++) { 169 x = 0; 170 src = MAKE_PTR(srcvp, x, y); 171 dest = MAKE_PTR(destvp, rx - dx, ry + dy); 172 for (r = 0; r< w; r++) { 173 // transparency 174 if (*src) 175 *dest = *src; 176 src++; 177 dest += buffwid2; 178 } 179 y++; 180 dx++; 181 } 182 } 183 return 0; 184 } 185 // no change in y 186 187 if (!Deltay) { // must be 0 or 180 degree transpose ! 188 if (Deltax < 0) { 189 y = 0; 190 for (y = 0; y< h; y++) { 191 x = 0; 192 src = MAKE_PTR(srcvp, x, y); 193 dest = MAKE_PTR(destvp, rx - x , ry - y); 194 for (x = 0 ; x< w; x++) { 195 // transparency 196 if (*src) 197 *dest = *src; 198 dest--; 199 src++; 200 } 201 } 202 } else { 203 for (y = 0; y< h; y++) { 204 x = 0; 205 src = MAKE_PTR(srcvp, x, y); 206 dest = MAKE_PTR(destvp, rx + x, ry + y); 207 for (x = 0 ; x< w; x++) { 208 // transparency 209 if (*src) 210 *dest = *src; 211 dest++; 212 src++; 213 } 214 } 215 } 216 return 0; 217 } 218 219 220 // ok now the hard part 221 222 // make them 16.16 223 if ( ABS(Deltax) < ABS(Deltay)) { // ok this means we want to walk in y 224 225 // walk in + x in the src and 226 // walk in + y in the dest 227 Error = 0; 228 // start at left top corner in src and dest 229 230 sx = 0; 231 sy = 0; 232 233 dx = 0; 234 dy = 0; 235 236 dest = MAKE_PTR(destvp, rx + dx, ry + dy); 237 238 src = MAKE_PTR(srcvp, x + sx, y + sy); 239 240 // this gets added to error each inc of x 241 // when error is > 1 then inc y! 242 int xinc = 1; 243 if (Deltax < 0) { 244 Deltax = -Deltax; 245 xinc = -1; 246 } 247 int yinc = 1; 248 int yinc1 = 1; 249 if (Deltay < 0) { 250 Deltay = - Deltay; 251 buffwid2 = - buffwid2; 252 } 253 Decimal = ( Deltax << shift) / Deltay ; 254 // walk in X 255 256 int Deltax2 = Deltax << shift; 257 int Deltay2 = Deltay << shift; 258 259 // this is the ratio between the source height and the dest height 260 // as the rectangle rotates the height and width change 261 int DeltaH = (w << shift) / Deltay; 262 int Error2 = 0; 263 sy = 0; 264 for (int r = 0; r< h ;r++) { 265 // now we walk across the top calculating each rotated point 266 // along the side 267 // the use delta formula to walk in x and y in destination space 268 // always walking in the x in the source! 269 // figure out rotated location to start in dest 270 rx = ( ( (sx - halfws) * ca) - ( (sy - halfhs) * sa) ) >> shift; 271 rx += halfwd; 272 ry = ( ( (sx - halfws) * sa) + ( (sy - halfhs) * ca) ) >> shift; 273 ry += halfhd; 274 275 // this is the end point of the line 276 277 int y2 = ( ( ((w) - halfws) * sa) + ( (sy - halfhs) * ca) ) >> shift; 278 y2 += halfhd; 279 280 // length of line 281 282 int diff = ABS(y2 - ry); 283 284 // if walking backwards reveres diff to reflect sign 285 286 src = MAKE_PTR(srcvp, x, y + sy); 287 288 dest = MAKE_PTR(destvp, rx, ry); 289 290 Error = 0; 291 Error2 = 0; 292 char * baseptr = src; 293 // while walking line 294 while (diff--) { 295 char c = *src; 296 // transparency 297 if (c) 298 *dest = *src; 299 Error2 += DeltaH; 300 dest += buffwid2; 301 Error += Decimal; 302 src = baseptr + (Error2 >> shift) ; 303 // this is time to inc x in src y in dest 304 if (Error >= fixpoint1) { 305 Error -= fixpoint1; 306 if (*src) 307 *dest = *src; 308 dest += xinc; 309 } 310 } 311 sy += yinc; 312 } 313 return 0; 314 } else { // else we walk in X 315 int lasterror = 0; 316 Error = 0; 317 // start at left top corner in src and dest 318 319 sx = 0; 320 sy = 0; 321 322 dx = 0; 323 dy = 0; 324 325 dest = MAKE_PTR(destvp, rx + dx, ry + dy); 326 327 src = MAKE_PTR(srcvp, x + sx, y + sy); 328 329 // this gets added to error each inc of x 330 // when error is > 1 then inc y! 331 int xinc = 1; 332 if (Deltax < 0) { 333 Deltax = -Deltax; 334 xinc = -1; 335 } 336 int yinc = 1; 337 if (Deltay < 0) { 338 Deltay = - Deltay; 339 buffwid2 = - buffwid2; 340 sy = sy + h - 1; 341 yinc = -1; 342 } 343 344 345 Decimal = ( Deltay << shift) / Deltax ; 346 // walk in X 347 348 int Deltax2 = Deltax << shift; 349 int Deltay2 = Deltay << shift; 350 351 // this is the ratios between the source width and the dest width 352 // as the rectangle rotates the actual size changes! 353 354 int DeltaW = (w << shift) / Deltax; 355 int Error2 = 0; 356 for (int r = 0; r< h ;r++) { 357 sx = 0; 358 359 // now we walk across the side calculating each rotated point 360 // along the side 361 // the use delta formula to walk in x and y in destination space 362 // always walking in the x in the source! 363 // figure out rotated location to start 364 365 rx = ( ( (sx - halfws) * ca) - ( (sy - halfhs) * sa) ) >> shift; 366 rx += halfwd; 367 ry = ( ( (sx - halfws) * sa) + ( (sy - halfhs) * ca) ) >> shift; 368 ry += halfhd; 369 // this is the other side of the box 370 371 int x2 = ( ( ((sx + w) - halfws) * ca) - ( (sy - halfhs) * sa) ) >> shift; 372 373 x2 += halfwd; 374 375 int diff = x2 - rx; 376 377 378 dx = 0; 379 dy = 0; 380 381 if (xinc == -1) { 382 diff = -diff; 383 } 384 385 src = MAKE_PTR(srcvp, x + sx, y + sy); 386 387 dest = MAKE_PTR(destvp, rx + dx, ry + dy); 388 Error = 0; 389 Error2 = 0; 390 char * baseptr = src; 391 392 while (diff--) { 393 char c = *src; 394 // transparency 395 if (c) 396 *dest = *src; 397 Error2 += DeltaW; 398 rx++; 399 dest += xinc; 400 Error += Decimal; 401 src = baseptr + (Error2 >> shift); 402 if (Error >= fixpoint1) { 403 Error -= fixpoint1; 404 if (*src) 405 *dest = *src; 406 dest += buffwid2; 407 } 408 } 409 sy += yinc; 410 } 411 } 412 return 0; 413 } 414 #endif