| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- ;
- ; 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/>.
- ;
- ;***************************************************************************
- ;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
- ;***************************************************************************
- ;* *
- ;* Project Name : Support Library *
- ;* *
- ;* File Name : cliprect.asm *
- ;* *
- ;* Programmer : Julio R Jerez *
- ;* *
- ;* Start Date : Mar, 2 1995 *
- ;* *
- ;* *
- ;*-------------------------------------------------------------------------*
- ;* Functions: *
- ;* int Clip_Rect ( int * x , int * y , int * dw , int * dh , *
- ;* int width , int height ) ; *
- ;* int Confine_Rect ( int * x , int * y , int * dw , int * dh , *
- ;* int width , int height ) ; *
- ;* *
- ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
- IDEAL
- P386
- MODEL USE32 FLAT
- GLOBAL C Clip_Rect :NEAR
- GLOBAL C Confine_Rect :NEAR
- CODESEG
- ;***************************************************************************
- ;* Clip_Rect -- clip a given rectangle against a given window *
- ;* *
- ;* INPUT: &x , &y , &w , &h -> Pointer to rectangle being clipped *
- ;* width , height -> dimension of clipping window *
- ;* *
- ;* OUTPUT: a) Zero if the rectangle is totally contained by the *
- ;* clipping window. *
- ;* b) A negative value if the rectangle is totally outside the *
- ;* the clipping window *
- ;* c) A positive value if the rectangle was clipped against the *
- ;* clipping window, also the values pointed by x, y, w, h will *
- ;* be modified to new clipped values *
- ;* *
- ;* 05/03/1995 JRJ : added comment *
- ;*=========================================================================*
- ; int Clip_Rect (int* x, int* y, int* dw, int* dh, int width, int height); *
- PROC Clip_Rect C near
- uses ebx,ecx,edx,esi,edi
- arg x:dword
- arg y:dword
- arg w:dword
- arg h:dword
- arg width:dword
- arg height:dword
- ;This Clipping algorithm is a derivation of the very well known
- ;Cohen-Sutherland Line-Clipping test. Due to its simplicity and efficiency
- ;it is probably the most commontly implemented algorithm both in software
- ;and hardware for clipping lines, rectangles, and convex polygons against
- ;a rectagular clipping window. For reference see
- ;"COMPUTER GRAPHICS principles and practice by Foley, Vandam, Feiner, Hughes
- ; pages 113 to 177".
- ; Briefly consist in computing the Sutherland code for both end point of
- ; the rectangle to find out if the rectangle is:
- ; - trivially accepted (no further clipping test, return the oroginal data)
- ; - trivially rejected (return with no action, return error code)
- ; - retangle must be iteratively clipped again edges of the clipping window
- ; and return the clipped rectangle
- ; get all four pointer into regisnters
- mov esi,[x] ; esi = pointer to x
- mov edi,[y] ; edi = pointer to x
- mov eax,[w] ; eax = pointer to dw
- mov ebx,[h] ; ebx = pointer to dh
- ; load the actual data into reg
- mov esi,[esi] ; esi = x0
- mov edi,[edi] ; edi = y0
- mov eax,[eax] ; eax = dw
- mov ebx,[ebx] ; ebx = dh
- ; create a wire frame of the type [x0,y0] , [x1,y1]
- add eax,esi ; eax = x1 = x0 + dw
- add ebx,edi ; ebx = y1 = y0 + dh
- ; we start we suthenland code0 and code1 set to zero
- xor ecx,ecx ; cl = sutherland boolean code0
- xor edx,edx ; dl = sutherland boolean code0
- ; now we start computing the to suthenland boolean code for x0 , x1
- shld ecx,esi,1 ; bit3 of code0 = sign bit of (x0 - 0)
- shld edx,eax,1 ; bit3 of code1 = sign bit of (x1 - 0)
- sub esi,[width] ; get the difference (x0 - (width + 1))
- sub eax,[width] ; get the difference (x1 - (width + 1))
- dec esi
- dec eax
- shld ecx,esi,1 ; bit2 of code0 = sign bit of (x0 - (width + 1))
- shld edx,eax,1 ; bit2 of code1 = sign bit of (x0 - (width + 1))
- ; now we start computing the to suthenland boolean code for y0 , y1
- shld ecx,edi,1 ; bit1 of code0 = sign bit of (y0 - 0)
- shld edx,ebx,1 ; bit1 of code1 = sign bit of (y0 - 0)
- sub edi,[height] ; get the difference (y0 - (height + 1))
- sub ebx,[height] ; get the difference (y1 - (height + 1))
- dec edi
- dec ebx
- shld ecx,edi,1 ; bit0 of code0 = sign bit of (y0 - (height + 1))
- shld edx,ebx,1 ; bit0 of code1 = sign bit of (y1 - (height + 1))
- ; Bit 2 and 0 of cl and bl are complemented
- xor cl,5 ; reverse bit2 and bit0 in code0
- xor dl,5 ; reverse bit2 and bit0 in code1
- ; now perform the rejection test
- mov eax,-1 ; set return code to false
- mov bl,cl ; save code0 for future use
- test dl,cl ; if any two pair of bit in code0 and code1 is set
- jnz ??clip_out ; then rectangle is outside the window
- ; now perform the aceptance test
- xor eax,eax ; set return code to true
- or bl,dl ; if all pair of bits in code0 and code1 are reset
- jz ??clip_out ; then rectangle is insize the window. '
- ; we need to clip the rectangle iteratively
- mov eax,-1 ; set return code to false
- test cl,1000b ; if bit3 of code0 is set then the rectangle
- jz ??left_ok ; spill out the left edge of the window
- mov edi,[x] ; edi = a pointer to x0
- mov ebx,[w] ; ebx = a pointer to dw
- mov esi,[edi] ; esi = x0
- mov [dword ptr edi],0 ; set x0 to 0 "this the left edge value"
- add [ebx],esi ; adjust dw by x0, since x0 must be negative
- ??left_ok:
- test cl,0010b ; if bit1 of code0 is set then the rectangle
- jz ??bottom_ok ; spill out the bottom edge of the window
- mov edi,[y] ; edi = a pointer to y0
- mov ebx,[h] ; ebx = a pointer to dh
- mov esi,[edi] ; esi = y0
- mov [dword ptr edi],0 ; set y0 to 0 "this the bottom edge value"
- add [ebx],esi ; adjust dh by y0, since y0 must be negative
- ??bottom_ok:
- test dl,0100b ; if bit2 of code1 is set then the rectangle
- jz ??right_ok ; spill out the right edge of the window
- mov edi,[w] ; edi = a pointer to dw
- mov esi,[x] ; esi = a pointer to x
- mov ebx,[width] ; ebx = the width of the window
- sub ebx,[esi] ; the new dw is the difference (width-x0)
- mov [edi],ebx ; adjust dw to (width - x0)
- jle ??clip_out ; if (width-x0) = 0 then the clipped retangle
- ; has no width we are done
- ??right_ok:
- test dl,0001b ; if bit0 of code1 is set then the rectangle
- jz ??clip_ok ; spill out the top edge of the window
- mov edi,[h] ; edi = a pointer to dh
- mov esi,[y] ; esi = a pointer to y0
- mov ebx,[height] ; ebx = the height of the window
- sub ebx,[esi] ; the new dh is the difference (height-y0)
- mov [edi],ebx ; adjust dh to (height-y0)
- jle ??clip_out ; if (width-x0) = 0 then the clipped retangle
- ; has no width we are done
- ??clip_ok:
- mov eax,1 ; signal the calling program that the rectangle was modify
- ??clip_out:
- ret
- ENDP Clip_Rect
- ;***************************************************************************
- ;* Confine_Rect -- clip a given rectangle against a given window *
- ;* *
- ;* INPUT: &x,&y,w,h -> Pointer to rectangle being clipped *
- ;* width,height -> dimension of clipping window *
- ;* *
- ;* OUTPUT: a) Zero if the rectangle is totally contained by the *
- ;* clipping window. *
- ;* c) A positive value if the rectangle was shifted in position *
- ;* to fix inside the clipping window, also the values pointed *
- ;* by x, y, will adjusted to a new values *
- ;* *
- ;* NOTE: this function make not attempt to verify if the rectangle is *
- ;* bigger than the clipping window and at the same time wrap around*
- ;* it. If that is the case the result is meaningless *
- ;*=========================================================================*
- ; int Confine_Rect (int* x, int* y, int dw, int dh, int width, int height); *
- PROC Confine_Rect C near
- uses ebx, esi,edi
- arg x:dword
- arg y:dword
- arg w:dword
- arg h:dword
- arg width :dword
- arg height:dword
- xor eax,eax
- mov ebx,[x]
- mov edi,[w]
- mov esi,[ebx]
- add edi,[ebx]
- sub edi,[width]
- neg esi
- dec edi
- test esi,edi
- jl ??x_axix_ok
- mov eax,1
- test esi,esi
- jl ??shift_right
- mov [dword ptr ebx],0
- jmp ??x_axix_ok
- ??shift_right:
- inc edi
- sub [ebx],edi
- ??x_axix_ok:
- mov ebx,[y]
- mov edi,[h]
- mov esi,[ebx]
- add edi,[ebx]
- sub edi,[height]
- neg esi
- dec edi
- test esi,edi
- jl ??confi_out
- mov eax,1
- test esi,esi
- jl ??shift_top
- mov [dword ptr ebx],0
- ret
- ??shift_top:
- inc edi
- sub [ebx],edi
- ??confi_out:
- ret
- ENDP Confine_Rect
- END
|