| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- /*
- ** Command & Conquer Red Alert(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /* $Header: /CounterStrike/ROTBMP.CPP 1 3/03/97 10:25a Joe_bostic $ */
- /***********************************************************************************************
- *** 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 ***
- ***********************************************************************************************
- * *
- * Project Name : Command & Conquer *
- * *
- * File Name : ROTBMP.CPP *
- * *
- * Programmer : Joe L. Bostic *
- * *
- * Start Date : 07/05/96 *
- * *
- * Last Update : July 5, 1996 [JLB] *
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- //#include "function.h"
- #include "watcom.h"
- #include "rotbmp.h"
- #define FILE_H
- #define WWMEM_H
- #include <wwlib32.h>
- int Rotate_Bitmap(GraphicViewPortClass * srcvp, GraphicViewPortClass * destvp, int angle);
- struct WPPOINT {
- int x;
- int y;
- };
- /***************************************************************************
- * Rotate_bitmap -- rotate a bitmap from srcvp to destvp *
- * *
- * INPUT: note that angles are 0 - 255 (best if used in increments of 4!) *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * destvp should be a square. width and height should be equal to : *
- * MAX(srcvp->width,srcvp->height) * 1.7 (square root of 2!!) *
- * *
- * *
- * HISTORY: *
- * 01/02/1996 BP : Created. *
- *=========================================================================*/
- Rotate_Bitmap(GraphicViewPortClass * srcvp, GraphicViewPortClass * destvp, int a)
- {
- int shift = 7;
- int fixpoint1 = 1 << shift; // this is a fixed point 1
- int Deltax;
- int Deltay;
- int sx,sy,dx,dy;
- int Error = 0;
- int Decimal = 0;
- // this is used if I walk in Y
- int buffwidth = srcvp->Get_Width() + srcvp->Get_XAdd();
- int buffwid2 = destvp->Get_Width() + destvp->Get_XAdd();
- char * dest;
- char * src;
- int sa,ca;
- int t;
- int x,y;
- int rx,ry;
- int w,h;
- int dw = destvp->Get_Width();
- int dh = destvp->Get_Height();
- WPPOINT sp[4];
- WPPOINT dp[4];
- sa = Sin256[a];
- ca = Cos256[a];
- // get rectangle size
- x = 0;
- y = 0;
- w = srcvp->Get_Width();
- h = srcvp->Get_Height();
- int halfws = w >> 1;
- int halfhs = h >> 1;
- int halfwd = dw >> 1;
- int halfhd = dh >> 1;
- // make the src rectangle
- sp[0].x = x;
- sp[0].y = y;
- sp[1].x = x + w;
- sp[1].y = y;
- // now calculate the rotated rectangle
- dp[0].x = ( ((sp[0].x - halfws) * ca) - ((sp[0].y - halfhs) * sa) ) >> shift;
- dp[0].x += halfwd;
- dp[0].y = ( ((sp[0].x - halfws) * sa) + ((sp[0].y - halfhs) * ca) ) >> shift;
- dp[0].y += halfhd;
- dp[1].x = ( ((sp[1].x - halfws) * ca) - ((sp[1].y - halfhs) * sa) ) >> shift;
- dp[1].x += halfwd;
- dp[1].y = ( ((sp[1].x - halfws) * sa) + ((sp[1].y - halfhs) * ca) ) >> shift;
- dp[1].y += halfhd;
- rx = dp[0].x;
- ry = dp[0].y;
- // now calculate slope
- // diff from new to old x
- Deltax = (dp[1].x - dp[0].x);
- // diff from new to old y
- Deltay = (dp[1].y - dp[0].y);
- // handle the easy cases
- // no change in x
- int r;
- if (!Deltax) { // must be 90 or 270 degree transpose!
- if (Deltay < 0) {
- // walk across source in the x + dir
- // walk across dest in the y - dir
- x = 0;
- dy = 0;
- dx = 0;
- for (t = 0; t< h; t++) {
- x = 0;
- src = MAKE_PTR(srcvp, x, y);
- dest = MAKE_PTR(destvp, rx + dx, ry - dy);
- for (r = 0; r< w; r++) {
- // transparency
- if (* src)
- *dest = *src;
- src++;
- dest -= buffwid2;
- }
- y++;
- dx++;
- }
- } else {
- // walk across source in the x + dir
- // walk across dest in the y + dir
- x = 0;
- dy = 0;
- dx = 0;
- for (t = 0; t< h; t++) {
- x = 0;
- src = MAKE_PTR(srcvp, x, y);
- dest = MAKE_PTR(destvp, rx - dx, ry + dy);
- for (r = 0; r< w; r++) {
- // transparency
- if (*src)
- *dest = *src;
- src++;
- dest += buffwid2;
- }
- y++;
- dx++;
- }
- }
- return 0;
- }
- // no change in y
- if (!Deltay) { // must be 0 or 180 degree transpose !
- if (Deltax < 0) {
- y = 0;
- for (y = 0; y< h; y++) {
- x = 0;
- src = MAKE_PTR(srcvp, x, y);
- dest = MAKE_PTR(destvp, rx - x , ry - y);
- for (x = 0 ; x< w; x++) {
- // transparency
- if (*src)
- *dest = *src;
- dest--;
- src++;
- }
- }
- } else {
- for (y = 0; y< h; y++) {
- x = 0;
- src = MAKE_PTR(srcvp, x, y);
- dest = MAKE_PTR(destvp, rx + x, ry + y);
- for (x = 0 ; x< w; x++) {
- // transparency
- if (*src)
- *dest = *src;
- dest++;
- src++;
- }
- }
- }
- return 0;
- }
- // ok now the hard part
- // make them 16.16
- if ( ABS(Deltax) < ABS(Deltay)) { // ok this means we want to walk in y
- // walk in + x in the src and
- // walk in + y in the dest
- Error = 0;
- // start at left top corner in src and dest
- sx = 0;
- sy = 0;
- dx = 0;
- dy = 0;
- dest = MAKE_PTR(destvp, rx + dx, ry + dy);
- src = MAKE_PTR(srcvp, x + sx, y + sy);
- // this gets added to error each inc of x
- // when error is > 1 then inc y!
- int xinc = 1;
- if (Deltax < 0) {
- Deltax = -Deltax;
- xinc = -1;
- }
- int yinc = 1;
- int yinc1 = 1;
- if (Deltay < 0) {
- Deltay = - Deltay;
- buffwid2 = - buffwid2;
- }
- Decimal = ( Deltax << shift) / Deltay ;
- // walk in X
- int Deltax2 = Deltax << shift;
- int Deltay2 = Deltay << shift;
- // this is the ratio between the source height and the dest height
- // as the rectangle rotates the height and width change
- int DeltaH = (w << shift) / Deltay;
- int Error2 = 0;
- sy = 0;
- for (int r = 0; r< h ;r++) {
- // now we walk across the top calculating each rotated point
- // along the side
- // the use delta formula to walk in x and y in destination space
- // always walking in the x in the source!
- // figure out rotated location to start in dest
- rx = ( ( (sx - halfws) * ca) - ( (sy - halfhs) * sa) ) >> shift;
- rx += halfwd;
- ry = ( ( (sx - halfws) * sa) + ( (sy - halfhs) * ca) ) >> shift;
- ry += halfhd;
- // this is the end point of the line
- int y2 = ( ( ((w) - halfws) * sa) + ( (sy - halfhs) * ca) ) >> shift;
- y2 += halfhd;
- // length of line
- int diff = ABS(y2 - ry);
- // if walking backwards reveres diff to reflect sign
- src = MAKE_PTR(srcvp, x, y + sy);
- dest = MAKE_PTR(destvp, rx, ry);
- Error = 0;
- Error2 = 0;
- char * baseptr = src;
- // while walking line
- while (diff--) {
- char c = *src;
- // transparency
- if (c)
- *dest = *src;
- Error2 += DeltaH;
- dest += buffwid2;
- Error += Decimal;
- src = baseptr + (Error2 >> shift) ;
- // this is time to inc x in src y in dest
- if (Error >= fixpoint1) {
- Error -= fixpoint1;
- if (*src)
- *dest = *src;
- dest += xinc;
- }
- }
- sy += yinc;
- }
- return 0;
- } else { // else we walk in X
- int lasterror = 0;
- Error = 0;
- // start at left top corner in src and dest
- sx = 0;
- sy = 0;
- dx = 0;
- dy = 0;
- dest = MAKE_PTR(destvp, rx + dx, ry + dy);
- src = MAKE_PTR(srcvp, x + sx, y + sy);
- // this gets added to error each inc of x
- // when error is > 1 then inc y!
- int xinc = 1;
- if (Deltax < 0) {
- Deltax = -Deltax;
- xinc = -1;
- }
- int yinc = 1;
- if (Deltay < 0) {
- Deltay = - Deltay;
- buffwid2 = - buffwid2;
- sy = sy + h - 1;
- yinc = -1;
- }
- Decimal = ( Deltay << shift) / Deltax ;
- // walk in X
- int Deltax2 = Deltax << shift;
- int Deltay2 = Deltay << shift;
- // this is the ratios between the source width and the dest width
- // as the rectangle rotates the actual size changes!
- int DeltaW = (w << shift) / Deltax;
- int Error2 = 0;
- for (int r = 0; r< h ;r++) {
- sx = 0;
- // now we walk across the side calculating each rotated point
- // along the side
- // the use delta formula to walk in x and y in destination space
- // always walking in the x in the source!
- // figure out rotated location to start
- rx = ( ( (sx - halfws) * ca) - ( (sy - halfhs) * sa) ) >> shift;
- rx += halfwd;
- ry = ( ( (sx - halfws) * sa) + ( (sy - halfhs) * ca) ) >> shift;
- ry += halfhd;
- // this is the other side of the box
- int x2 = ( ( ((sx + w) - halfws) * ca) - ( (sy - halfhs) * sa) ) >> shift;
- x2 += halfwd;
- int diff = x2 - rx;
- dx = 0;
- dy = 0;
- if (xinc == -1) {
- diff = -diff;
- }
- src = MAKE_PTR(srcvp, x + sx, y + sy);
- dest = MAKE_PTR(destvp, rx + dx, ry + dy);
- Error = 0;
- Error2 = 0;
- char * baseptr = src;
- while (diff--) {
- char c = *src;
- // transparency
- if (c)
- *dest = *src;
- Error2 += DeltaW;
- rx++;
- dest += xinc;
- Error += Decimal;
- src = baseptr + (Error2 >> shift);
- if (Error >= fixpoint1) {
- Error -= fixpoint1;
- if (*src)
- *dest = *src;
- dest += buffwid2;
- }
- }
- sy += yinc;
- }
- }
- return 0;
- }
|