sys7.1-doc-wip/QuickDraw/DrawArc.a
2019-07-27 22:37:48 +08:00

1159 lines
38 KiB
Plaintext

;
; File: DrawArc.a
;
; Contains: xxx put contents here (or delete the whole line) xxx
;
; Written by: xxx put name of writer here (or delete the whole line) xxx
;
; Copyright: © 1981-1990, 1992 by Apple Computer, Inc., all rights reserved.
;
; This file is used in these builds: Mac32 Bigbang Sys606
;
; Change History (most recent first):
;
; <SM2> 6/11/92 stb <sm 6/9/92>stb Add comment from QDciPatchROM.a at SKIPSETUP;
; synched with QDciPatchROM.a.
; <8> 11/26/90 SMC Fixed the way valid pen mode is checked for. With BAL.
; <7> 9/26/90 SMC Avoid overflow problem when calculating arc center by using
; longs instead of words.
; <6> 9/17/90 BG Removed <3>. 040s are now behaving more reliably.
; <5> 8/2/90 gbm change LEFTEDGE and RIGHTEDGE in ovalstate record to avoid
; conflicts with other equates
; <4> 7/20/90 gbm Change some identifier names to resolve conflicts with interface
; files
; <3> 6/25/90 BG Added EclipseNOPs because of flakey 040s.
; <2> 2/13/90 BAL Calculate initial bit offset as a long.
; <•1.6> 7/14/89 BAL For Aurora: Final CQD
; <1.5> 6/30/89 BAL Cleared runBuf(a6) before calling getSeek to specifiy classic
; masking.
; <•1.4> 5/29/89 BAL Blasting in 32-Bit QuickDraw version 1.0 Final
; <•1.3> 4/12/89 BAL Blasting in 32-Bit QuickDraw 1.0B1
; 1/22/89 BAL Made patVPos a long.
; 10/3/88 BAL Added references to DstRow.
; 9/22/88 BAL Moved initialization of region state records into GetSeek.
; 9/19/88 BAL Altered to use common stack frame file 'Drawing Vars.a'
; 9/18/88 BAL Altered to get CRSRFLAG value from _BitsToPix; Removed
; references to PIXSRC;
; 11/8/87 BAL Fixed computation of bufSize for more accurate region clipping
; at at depths greater than 1. <C954>
; 11/7/87 BAL Fixed ChkPat to handle new patterns. <C945>
; 1/3/87 CRC pass color param to stretch
; 12/12/86 CRC added arithmetic mode support
; 7/29/86 EHB Allocate EXPAT buffer on stack so long aligned
; 7/26/86 EHB Added support for expanded patterns
; 7/22/86 EHB Pass mode to patexpand for colorizing
; 7/5/86 EHB Replaced SeekMask and GetXRtn with GetSeek
; 6/22/86 EHB Call new patexpand for depths
; 6/20/86 EHB New params to COLORMAP Added FCOLOR and BCOLOR to stack frame
; 6/15/86 EHB Make sure stack is longword aligned (for fast buffers) If one
; 1-bit region, play directly into RGNBUFFER Convert BitsToPix and
; use pixelSize
; 6/14/86 EHB Call GetXRtn to set expand routine for SeekMask Added DSTPIX to
; stack frame
; 6/13/86 EHB Updated SeekMask to check rgn changed flag Moved SeekMask to
; another file Rearranged stack frame with SeekMask stuff at top
; 6/10/86 EHB Modified to use 32-bit DrawSlab
BLANKS ON
STRING ASIS
MACHINE MC68020
;-----------------------------------------------------------
;
; --> DRAWARC.TEXT
;
; Routine to draw solid or hollow Ovals, RoundRects or Arcs.
;
;------------------------------------------------------------------
DrawArc PROC EXPORT
IMPORT InitOval,BumpOval,SlopeFromAngle,SHFTTBL
;----------------------------------------------------------------
;
; PROCEDURE DrawArc(dstRect: Rect;
; hollow: BOOLEAN;
; ovalWidth,ovalHeight,mode: INTEGER;
; pat: Pattern;
; startAngle,arcAngle: INTEGER);
;
;------------------------------------------------
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE EQU 20 ;TOTAL SIZE OF PARAMETERS
DSTRECT EQU PARAMSIZE+8-4 ;ADDR OF RECT
HOLLOW EQU DSTRECT-2 ;BOOLEAN
OVALWIDTH EQU HOLLOW-2 ;INTEGER
OVALHEIGHT EQU OVALWIDTH-2 ;INTEGER
MODE EQU OVALHEIGHT-2 ;INTEGER
PAT EQU MODE-4 ;LONG, ADDR OF PATTERN
STARTANGLE EQU PAT-2 ;INTEGER
ARCANGLE EQU STARTANGLE-2 ;INTEGER
;-------------------------------------------------
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
; STACK FRAME VARS USED BY SEEKMASK (CALLED BY STRETCHBITS, RGNBLT, DRAWARC, DRAWLINE)
;
&CurFile SETC 'DRAWARC'
INCLUDE 'DrawingVars.a'
;-------------------------------------------------
LINK A6,#VARSIZE ;ALLOCATE LOCAL VARS
MOVEM.L D0-D7/A1-A4,-(SP) ;SAVE REGS
MOVE.L SP,SAVESTK(A6) ;REMEMBER STACK FOR LATER
CLR.L DSTMASKBUF(A6) ;ASSUME NO MASK
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A4 ;GET CURRENT GRAFPORT
TST PNVIS(A4) ;IS PNVIS NEG ?
BLT GOHOME ;YES, QUIT
MOVE.W MODE(A6),D1 ;get pen mode Start of <8>
_GetStreamMode ;strip off alpha bits
BSET #3,D1 ;set the pattern bit in case the user forgot to
MOVEQ #$10,D0 ;1 past normal mode range
BTST #5,D1 ;arithmetic mode?
BEQ.S @noRith
CMP #$3A,D1 ;hilite?
BEQ.S @ok
MOVEQ #$30,D0 ;1 past arithmetic mode range
@noRith CMP D0,D1 ;greater than defined range?
BGT GOHOME
@ok MOVE D1,LOCMODE(A6) ;copy mode for colormap End of <8>
LEA EXPAT(A6),A0 ;DUMMY PATTERN USED IN ONESLAB
MOVE.L A0,(A0) ;POINT IT AT ITSELF
CLR.l PATVPOS(A6) ;INITIALIZE IN CASE NO PATTERN <BAL 22Jan89>
CLR PATVMASK(A6) ;INITIALIZE IN CASE NO PATTERN
MOVE #1,PATROW(A6) ;INITIALIZE IN CASE NO PATTERN
;----------------------------------------------------------------
;
; MAKE SURE THE STACK IS ON A LONGWORD BOUNDARY (FOR FAST BUFFERS)
;
MOVE.L SP,D1 ;GET THE STACK POINTER
AND.B #$FC,D1 ;FORCE LONG ALIGNMENT
MOVE.L D1,SP ;USE IT
;----------------------------------------------------
;
; CONVERT PORTBITS TO A PIXMAP
; (A5 must contain global ptr)
;
LEA PORTBITS(A4),A1 ;PUSH POINTER TO PORTBITS
LEA DSTPIX(A6),A2 ;AND COPY INTO DSTPIX
_BitsToPix ;CONVERT BITMAP
MOVE.L D1,REALBOUNDS(A6) ;SAVE REAL DST BOUNDS.TOPLEFT
MOVE.B D2,CRSRFLAG(A6) ;REMEMBER IF DST IS SCREEN <BAL 18Sep88>
;----------------------------------------------------
;
; CONVERT PIXEL DEPTH TO SHIFT AMOUNT TO AVOID MULTIPLIES
;
LEA SHFTTBL,A0 ;POINT TO SHIFT TABLE
MOVE DSTPIX+PIXELSIZE(A6),D0 ;GET DST PIXEL SIZE
MOVEQ #0,D1 ;DEFAULT SHIFT = 0
MOVE.B 0(A0,D0),D1 ;GET SRC SHIFT
MOVE D1,DSTSHIFT(A6) ;AND SAVE DST SHIFT AMOUNT
;----------------------------------------------------------------
;
; SET UP NEWPATTERN TO INDICATE OLD OR NEW STYLE PATTERN
; ALSO SET UP LOCAL PATTERN POINTER, LOCPAT(A6)
;
MOVE.L PAT(A6),LOCPAT(A6) ;COPY PATTERN POINTER
TST PORTBITS+ROWBYTES(A4) ;IS THE DST OLD OR NEW?
SMI NEWPATTERN(A6) ;FLAG = TRUE IF NEW PATTERN
;----------------------------------------------------------------
;
; ADJUST MODE AND PATTERN IF COLOR FILTERING.
; (A5 must contain global ptr)
;
CLR.B multiColor(A6) ;use fg/bg color
_COLORMAP ;ALTER BY THECOLOR, THEFILTER
;---------------------------------------------------------
;
; GET CLIPRGN AND VISRGN HANDLES AND DE-REFERENCE THEM
;
MOVE.L CLIPRGN(A4),A2 ;GET CLIPRGN HANDLE
MOVE.L (A2),A2 ;GET CLIPRGN POINTER
MOVE.L VISRGN(A4),A3 ;GET VISRGN HANDLE
MOVE.L (A3),A3 ;GET VISRGN POINTER
;-----------------------------------------------------------------------
;
; CALC MINRECT, THE INTERSECTION OF DSTRECT, BITMAP BOUNDS,
; CLIPRGN BBOX, AND VISRGN BBOX. QUIT IF NO INTERSECTION.
;
MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT
PEA DSTPIX+BOUNDS(A6) ;PUSH BITMAP BOUNDS
PEA RGNBBOX(A2) ;PUSH CLIPRGN BBOX
PEA RGNBBOX(A3) ;PUSH VISRGN BBOX
MOVE #4,-(SP) ;PUSH NRECTS=4
PEA MINRECT(A6) ;PUSH DST ADDR
_RSECT ;CALC INTERSECTION
BEQ GOHOME ;QUIT IF NO INTERSECT
;--------------------------------------------------
;
; CHECK FOR BOTH VISRGN AND CLIPRGN RECTANGULAR
;
CLR.B FASTFLAG(A6) ;FASTFLAG := FALSE
CMP #10,RGNSIZE(A2) ;IS CLIPRGN RECTANGULAR ?
BNE.S FLAGOK ;NO, CONTINUE
CMP #10,RGNSIZE(A3) ;IS VISRGN RECTANGULAR ?
BEQ.S CKPAT ;YES, CONTINUE
;--------------------------------------------------
;
; If only visRgn is non-rectangular, then check if
; its intersection with minrect would be rectangular.
; IF TrimRect(visRgn,minRect) then treat as rectangular.
;
MOVE.L visRgn(A4),-(SP) ;push rgnHandle
PEA minRect(A6) ;push addr of minRect
MOVE.W #-1,-(SP) ;pass Trim = True
_TrimRect ;call trimRect
BLT GOHOME ;quit if intersection empty
BGT.S FLAGOK ;continue if non-rectangular
;--------------------------------------------------
;
; CHECK FOR BLACK OR WHITE PATTERN
;
CKPAT BTST #5,LocMode+1(A6) ;an arithmetic mode?
BNE.S FlagOK ;skip fast case if so
MOVE.L LOCPAT(A6),A0 ;POINT TO PATTERN
TST.B NEWPATTERN(A6) ;is it a new pattern? <C945 07Nov87 BAL>
BEQ.S @oldPat ;=>yes, skip pixpat fields <C945 07Nov87 BAL>
MOVE.L (a0),a0 ;get the pixpat handle <C945 07Nov87 BAL>
MOVE.L (a0),a0 ;get the pixpat pointer <C945 07Nov87 BAL>
TST PATTYPE(A0) ;is it an old-style pattern? <C945 07Nov87 BAL>
BNE.S FLAGOK ;=>no, skip fast case <C945 07Nov87 BAL>
MOVE.L patData(a0),a0 ;get handle to pattern data <C945 07Nov87 BAL>
MOVE.L (a0),a0 ;get pattern ptr <C945 07Nov87 BAL>
@oldPat MOVE.L (A0)+,D0 ;GET 1ST HALF OF PATTERN
CMP.L (A0)+,D0 ;IS IT SAME AS 2ND HALF ?
BNE.S FLAGOK ;NO, CONTINUE
NOT.L D0 ;IS PATTERN BLACK ?
BEQ.S YESFLAG ;YES, WE MADE IT
NOT.L D0 ;IS PATTERN WHITE ?
BNE.S FLAGOK ;NO, CONTINUE
EOR #4,LOCMODE(A6) ;YES, ALTER MODE AS IF BLACK
YESFLAG ST FASTFLAG(A6) ;REMEMBER RECT CLIPPED AND BLACK
;--------------------------------------------------
;
; fast case: map mode into black,xor,white, or do-nothing
;
MOVEQ #7,D0 ;GET 3 BIT MASK
AND LOCMODE(A6),D0 ;GET 3 BITS OF MODE
MOVE.B MODEMAP(D0),D0 ;MAP TO BLACK,XOR,WHITE,NOP
BMI GOHOME ;QUIT IF DO-NOTHING MODE
MOVE D0,LOCMODE(A6) ;UPDATE MODE
BRA.S FLAGOK ;AND CONTINUE
MODEMAP DC.B 0,0,1,2,2,255,255,255
FLAGOK
CLR.B SKIPFLAG(A6) ;INIT TO NOT SKIPPING
;--------------------------------------------------
;
; ADJUST IF ARCANGLE NEGATIVE, QUIT IF ARC = 0
; NOTE WHETHER FULL CIRCLE OR ARC
;
MOVE ARCANGLE(A6),D0 ;GET ARC ANGLE
BEQ GOHOME ;QUIT IF ARC ANGLE = 0
BPL.S POSANG ;IS ANGLE NEG ?
ADD D0,STARTANGLE(A6) ;YES, ADJUST START ANGLE
NEG D0 ;AND MAKE ARC ANGLE POSITIVE
MOVE D0,ARCANGLE(A6) ;UPDATE INPUT PARAM
POSANG CMP #360,D0 ;IS ARC ANGLE < 360 ?
SLT ARCFLAG(A6) ;REMEMBER FOR LATER
BGE NOTARC ;NO, SKIP SETUP
;---------------------------------------------------------------
;
; IF ARCANGLE < 360 THEN SET UP ARC STUFF
;
; TREAT STARTANGLE MOD 360
;
MOVE STARTANGLE(A6),D0 ;GET STARTANGLE
EXT.L D0 ;SIGN EXTEND FOR DIVIDE
DIVS #360,D0 ;TREAT STARTANGLE MOD 360
SWAP D0 ;GET THE REMAINDER
TST D0 ;WAS IT NEGATIVE ?
BPL.S STARTOK ;NO, CONTINUE
ADD #360,D0 ;YES, PUT IN RANGE 0..359
STARTOK MOVE D0,STARTANGLE(A6) ;REPLACE INPUT PARAM
ADD ARCANGLE(A6),D0 ;CALC STOPANGLE
CMP #360,D0 ;IS IT >= 360 ?
BLT.S STOPOK ;NO, CONTINUE
SUB #360,D0 ;YES, PUT IN RANGE 0..359
STOPOK MOVE D0,STOPANGLE(A6) ;SAVE STOPANGLE FOR LATER
MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
MOVE TOP(A0),A1 ;<SMC 26SEP90> <7>
ADD BOTTOM(A0),A1 ;<SMC 26SEP90> <7>
MOVE.L A1,D0 ;<SMC 26SEP90> <7>
ASR.L #1,D0 ;<SMC 26SEP90> <7>
MOVE D0,MIDVERT(A6) ;MID VERT := (DSTBOT+DSTTOP)/2
MOVE LEFT(A0),A1 ;<SMC 26SEP90> <7>
ADD RIGHT(A0),A1 ;<SMC 26SEP90> <7>
MOVE.L A1,D0 ;<SMC 26SEP90> <7>
ASR.L #1,D0 ;<SMC 26SEP90> <7>
MOVE D0,MIDHORIZ(A6) ;MID HORIZ := (DSTLEFT+DSTRIGHT)/2
MOVE RIGHT(A0),D0
SUB LEFT(A0),D0
MOVE D0,WIDTH(A6) ;WIDTH := DSTRIGHT - DSTLEFT
MOVE BOTTOM(A0),D0
SUB TOP(A0),D0
MOVE D0,HEIGHT(A6) ;HEIGHT := DSTBOTTOM -DSTTOP
CLR.L -(SP) ;MAKE ROOM FOR FCN RESULT
MOVE WIDTH(A6),-(SP)
MOVE HEIGHT(A6),-(SP)
_FixRatio ;CALC ASPECT RATIO
MOVE.L (SP)+,D7 ;SAVE RESULT IN D7
;--------------------------------------------
;
; CALC SLOPE1 FROM STARTANGLE
;
CLR.L -(SP) ;MAKE ROOM FOR FCN RESULT
MOVE STARTANGLE(A6),-(SP) ;PUSH STARTANG
_SlopeFromAngle ;CALC SLOPE1
MOVE.L (SP)+,D0 ;POP SLOPE1
CLR.L -(SP) ;ROOM FOR FCN RESULT
MOVE.L D0,-(SP) ;PUSH SLOPE1
MOVE.L D7,-(SP) ;PUSH ASPECT RATIO
_FixMul ;scale slope1
MOVE.L (SP)+,SLOPE1(A6) ;SAVE RESULT FOR LATER
;--------------------------------------------
;
; CALC SLOPE2 FROM STOPANGLE
;
CLR.L -(SP) ;MAKE ROOM FOR FCN RESULT
MOVE STOPANGLE(A6),-(SP) ;PUSH STOPANGLE
_SlopeFromAngle ;CALC SLOPE2
MOVE.L (SP)+,D0 ;POP SLOPE2
CLR.L -(SP) ;ROOM FOR FCN RESULT
MOVE.L D0,-(SP) ;PUSH SLOPE
MOVE.L D7,-(SP) ;PUSH ASPECT RATIO
_FixMul ;SCALE SLOPE2
MOVE.L (SP)+,SLOPE2(A6) ;SAVE RESULT FOR LATER
;---------------------------------------------------------
;
; CALC HORIZ COORDS OF LINE1 AND LINE2 AT TOP OF DSTRECT
;
MOVE MIDHORIZ(A6),D6
SWAP D6
CLR.W D6 ;CALC MIDHORIZ*64K
MOVE HEIGHT(A6),D7
LSR #1,D7 ;CALC HEIGHT DIV 2
MOVE SLOPE1+2(A6),D0 ;GET LO WORD OF SLOPE
MULU D7,D0 ;CALC LO PARTIAL PRODUCT
MOVE.L D0,LINE1(A6) ;ACCUMULATE IT
MOVE.W SLOPE1(A6),D0 ;GET HI WORD OF SLOPE
MULS D7,D0 ;CALC HI PARTIAL PRODUCT
ADD.W D0,LINE1(A6) ;ADD TO HI WORD OF ACCUMULATOR
MOVE.L D6,D0 ;COPY MIDHORIZ*64K
SUB.L LINE1(A6),D0 ;CALC MIDH*64K-SLOPE*(HT DIV 2)
MOVE.L D0,LINE1(A6) ;STORE AS LINE1 HORIZ AT TOP
MOVE SLOPE2+2(A6),D0 ;GET LO WORD OF SLOPE
MULU D7,D0 ;CALC LO PARTIAL PRODUCT
MOVE.L D0,LINE2(A6) ;ACCUMULATE IT
MOVE.W SLOPE2(A6),D0 ;GET HI WORD OF SLOPE
MULS D7,D0 ;CALC HI PARTIAL PRODUCT
ADD.W D0,LINE2(A6) ;ADD TO HI WORD OF ACCUMULATOR
SUB.L LINE2(A6),D6 ;CALC MIDH*64K-SLOPE*(HT DIV 2)
MOVE.L D6,LINE2(A6) ;STORE AS LINE2 HORIZ AT TOP
;----------------------------------------------------------
;
; SET UP FLAG1 AND FLAG2 TO TELL WHICH HALF EACH LINE IS ACTIVE IN:
; CODE IS: NEG = ACTIVE IN TOP, POS = ACTIVE IN BOTTOM, 0 = HORIZONTAL
;
MOVE STARTANGLE(A6),D0
CMP #180,D0 ;IS STARTANGLE < 180 ?
BGE.S @1 ;NO, CONTINUE
SUB #90,D0 ;YES, FLAG1:=STARTANGLE-90
BRA.S @2 ;CONTINUE
@1 SUB #270,D0
NEG D0 ;FLAG1 := 270-STARTANGLE
@2 MOVE D0,FLAG1(A6) ;SAVE FOR LATER
MOVE STOPANGLE(A6),D0
CMP #180,D0 ;IS STOPANGLE < 180 ?
BGE.S @3 ;NO, CONTINUE
SUB #90,D0 ;YES, FLAG2:=STOPANGLE-90
BRA.S @4 ;CONTINUE
@3 SUB #270,D0
NEG D0 ;FLAG2 := 270-STOPANGLE
@4 MOVE D0,FLAG2(A6) ;SAVE FOR LATER
;----------------------------------------------------------
;
; SET UP SKIPFLAG TO SKIP OVER UNUSED ARC PORTIONS
;
MOVE ARCANGLE(A6),D0
CMP #180,D0 ;IS ARC ANGLE > 180 ?
BGT.S OBTUSE ;SKIP IF ANGLE > 180
BLT.S ACUTE ;DEAL WITH ACUTE ANGLE
CMP #90,STARTANGLE(A6) ;OTHERWISE ANGLE=180
SEQ SKIPFLAG(A6) ;SO SKIP IF START=90
BRA.S OBTUSE
ACUTE MOVE FLAG1(A6),D0
OR FLAG2(A6),D0
SPL SKIPFLAG(A6) ;SKIP:=FLAG1 AND FLAG2 BOTH >= 0
OBTUSE
NOTARC
;---------------------------------------------------------------
;
; INIT OUTER OVAL STATE RECORD
;
MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
LEA OUTEROVAL(A6),A1 ;POINT TO OUTER OVAL RECORD
MOVE OVALHEIGHT(A6),D1 ;GET OVALHEIGHT
MOVE OVALWIDTH(A6),D2 ;GET OVALWIDTH
JSR INITOVAL ;INITIALIZE OUTER OVAL RECORD
MOVE OVALHEIGHT(A6),D0 ;GET OVALHEIGHT
ASR #1,D0 ;CALC OVAL HEIGHT DIV 2
ADD OUTEROVAL+OVALTOP(A6),D0 ;ADD OUTEROVAL TOP
MOVE D0,SKIPTOP(A6) ;SAVE SKIPTOP
MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
ADD BOTTOM(A0),D0 ;ADD BOTTOM
SUB TOP(A0),D0 ;SUBTRACT TOP
SUB OVALHEIGHT(A6),D0 ;SUBTRACT OVALHEIGHT
MOVE D0,SKIPBOT(A6) ;SAVE SKIPBOT
;---------------------------------------------------
;
; IF THIS IS A HOLLOW OVAL, THEN CALC DSTRECT INSET BY PENSIZE,
; AND INIT INNEROVAL. (IF INNEROVAL EMPTY, SWITCH TO SOLID).
;
MOVE #32767,INNEROVAL+OVALTOP(A6);INIT INNEROVAL NOT USED
TST.B HOLLOW(A6) ;IS HOLLOWFLAG TRUE ?
BEQ.S SOLID ;NO, SKIP INNER OVAL
MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
MOVEM.W (A0),D0-D3 ;GET DSTRECT INTO REGS
MOVE.L PNSIZE(A4),D4 ;GET THEPORT^.PNSIZE
ADD D4,D1 ;LEFT := DSTLEFT + PENWIDTH
SUB D4,D3 ;RIGHT := DSTRIGHT - PENWIDTH
CMP D3,D1 ;IS LEFT >= TOP ?
BGE.S SOLID ;YES, EMPTY RECT
SWAP D4 ;GET PNSIZE.V
ADD D4,D0 ;TOP := DSTTOP + PENHEIGHT
SUB D4,D2 ;BOTTOM := DSTBOTTOM - PENHEIGHT
CMP D2,D0 ;IS TOP >= BOTTOM ?
BGE.S SOLID ;YES, EMPTY RECT
MOVEM.W D0-D3,TEMPRECTANGLE(A6) ;STORE RESULTS INTO TEMPRECTANGLE
LEA TEMPRECTANGLE(A6),A0 ;POINT TO DSTRECT INSET BY PENSIZE
LEA INNEROVAL(A6),A1 ;POINT TO INNER OVAL RECORD
MOVE OVALHEIGHT(A6),D1
SUB D4,D1 ;INNER HEIGHT:=OUTER-2*PENHEIGHT
SUB D4,D1
MOVE OVALWIDTH(A6),D2
SWAP D4 ;GET PEN WIDTH
SUB D4,D2 ;INNER WIDTH:=OUTER-2*PENWIDTH
SUB D4,D2
JSR INITOVAL ;INITIALIZE INNER OVAL RECORD
SOLID
;----------------------------------------------------------------
;
; HIDE CURSOR IF CURSOR INTERSECTS MINRECT AND DST IS SCREEN.
;
TST.B CRSRFLAG(A6) ;IS DST TO A SCREEN? <BAL 19Sep88>
BEQ.S NOTSCREEN ;=>NO
PEA MINRECT(A6) ;PUSH SHIELDRECT PARAMETER
MOVE.L REALBOUNDS(A6),-(SP) ;PUSH DELTA FOR GLOBAL
_SHIELDCURSOR ;HIDE CURSOR IF IT INTERSECTS
NOTSCREEN
;------------------------------------
;
; CALC BUFLEFT
;
MOVE DSTSHIFT(A6),D5 ;GET SHIFT FOR PIXEL DEPTH
MOVE MINRECT+LEFT(A6),D2 ;GET MINRECT LEFT
SUB DSTPIX+BOUNDS+LEFT(A6),D2 ;CONVERT TO GLOBAL COORDS
EXT.L D2 ;MAKE IT A LONG
LSL.L D5,D2 ;CONVERT PIXELS TO BITS
AND.l #~$1f,D2 ;TRUNC TO MULT OF 32 BITS
MOVE.L D2,D0 ;GET FOR PATHPOS CALC
LSR.L #3,D0 ;CONVERT TO BYTES
MOVE D0,PATHPOS(A6) ;SAVE FOR BIG PATTERNS
LSR.L D5,D2 ;CONVERT BITS TO PIXELS
ADD DSTPIX+BOUNDS+LEFT(A6),D2 ;CONVERT BACK TO GLOBAL
MOVE D2,BUFLEFT(A6) ;SAVE AS BUFLEFT
;
; IF FASTFLAG, THEN SKIP REGION SETUP
;
TST.B FASTFLAG(A6) ;RECT CLIPPED AND BLACK ?
BNE SKIPSETUP ;YES, DON'T WASTE TIME WITH SETUP
;
; CALC expansion buffer = [ (minRect.right-minRect.left) div 32 + 1 ] * pixelsize - 1
; CALC bufSize = [ (minRect.right-minRect.left) * pixelsize - 1 ] div 32 <C954> 08Nov87 BAL
;
MOVE MINRECT+RIGHT(A6),D0 ;GET MINRECT RIGHT
SUB D2,D0 ;CALC MAXH-BUFLEFT
move d0,d1 ;save for expansion scanline buffer <C954>
ext.l d1 ;clear out high word <C954>
lsl.l d5,d1 ;convert to bits <C954>
subq.l #1,d1 ;force downward round <C954>
LSR.l #5,D1 ;GET NUMBER OF LONGS IN SCANBUF - 1 <C954>
MOVE D1,BUFSIZE(A6) ;BUFSIZE = # LONGS -1 <C954>
LSR #5,D0 ;get (pixels in scanbuf)/32 <C954>
ADDQ #1,D0 ;MAKE IT ONE BASED
LSL D5,D0 ;CONVERT PIXELS TO BITS
SUBQ #1,D0 ;MAKE 0 BASED AGAIN
;-------------------------------------------------------------------------
;
; ALLOCATE AND CLEAR A SCANLINE BUFFER FOR THE COMPOSITE MASK
;
CLRMASK CLR.L -(SP) ;ALLOCATE AND CLEAR ONE LONG
DBRA D0,CLRMASK ;LOOP TILL DONE
MOVE.L SP,RGNBUFFER(A6) ;REMEMBER WHERE RGNBUFFER IS
;--------------------------------------------------------------------
;
; ALLOCATE BUFFERS AND INIT STATE RECORDS FOR EACH NON-RECT REGION
; GET SEEK ROUTINE INTO SEEKMASK(A6)
; GET EXPAND ROUTINE INTO EXRTN(A6) FOR SEEK ROUTINE
; Clobbers: A0-A3, D0-D4
;
lea Show,a0 ;get go home routine
move.l a0,goShow(a6) ;pass to getSeek <BAL 21Mar89>
move.l maskbc,StackFree(a6) ;pretend lots of stack <BAL 21Mar89>
clr.l DstRow(a6) ;flag as seeking down
clr.l runBuf(a6) ;don't use run clipping <1.5> BAL
MOVE.L VISRGN(A4),-(SP) ;PUSH THEPORT^.VISRGN
MOVE.L CLIPRGN(A4),-(SP) ;PUSH THEPORT^.CLIPRGN
MOVE.L #1,-(SP) ;PUSH HANDLE COUNT - 1
_GETSEEK ;GET EXPAND ROUTINE INTO EXRTN(A6)
;AND SEEK ROUTINE INTO SEEKMASK(A6)
SKIPSETUP
;------------------------------------
;
; CALC STARTING DSTLEFT
;
; as seen in QDciPatchROM.a at TryLineArc <sm 6/9/92>stb
MOVE MINRECT+TOP(A6),D1 ;GET MINRECT TOP
SUB DSTPIX+BOUNDS+TOP(A6),D1 ;CONVERT TO GLOBAL COORDS
MOVE DSTPIX+ROWBYTES(A6),D0 ;GET DST ROWBYTES
AND #nuRBMask,D0 ;CLEAR FLAG BITS
EXT.L D0 ;MAKE IT LONG
MOVE.L D0,DSTROW(A6) ;SAVE FOR LATER
MULS D0,D1 ;MULT BY DST ROWBYTES; BAL 02Dec88
ADD.L DSTPIX+BASEADDR(A6),D1 ;ADD START OF BITMAP
MOVE BUFLEFT(A6),D2 ;GET BUFLEFT
SUB DSTPIX+BOUNDS+LEFT(A6),D2 ;CONVERT BUFLEFT TO GLOBAL
ext.l d2 ;clear out high end <BAL 13Feb90>
MOVE DSTSHIFT(A6),D7 ;GET PIXEL TO BIT SHIFT AMOUNT
LSL.L D7,D2 ;CONVERT PIXELS TO BITS <BAL 13Feb90>
LSR.L #3,D2 ;CONVERT BITS TO BYTES <BAL 13Feb90>
; EXT.L D2 ;CLR HI WORD <BAL 13Feb90>
ADD.L D2,D1 ;ADD HORIZ BYTE OFFSET
MOVE.L D1,DSTLEFT(A6) ;SAVE AS DSTLEFT
;----------------------------------------------------
;
; MAKE ALL HORIZONTAL COORDINATES RELATIVE TO BUFFER
;
MOVE BUFLEFT(A6),D1 ;GET LEFT OF BUFFER
SUB D1,MINRECT+LEFT(A6)
SUB D1,MINRECT+RIGHT(A6)
SUB.W D1,OUTEROVAL+LEFTMOSTEDGE(A6) ;ADJUST OUTEROVAL LEFTMOSTEDGE.INT
SUB.W D1,OUTEROVAL+RIGHTMOSTEDGE(A6) ;ADJUST OUTEROVAL RIGHTMOSTEDGE.INT
SUB.W D1,INNEROVAL+LEFTMOSTEDGE(A6) ;ADJUST INNEROVAL LEFTMOSTEDGE.INT
SUB.W D1,INNEROVAL+RIGHTMOSTEDGE(A6) ;ADJUST INNEROVAL RIGHTMOSTEDGE.INT
SUB.W D1,LINE1(A6) ;ADJUST LINE1
SUB.W D1,LINE2(A6) ;ADJUST LINE2
;---------------------------------------------------
;
; SET UP CASE JUMP BASED ON MODE AND FASTFLAG
;
MOVE LOCMODE(A6),D2 ;GET (ALTERED) PEN MODE
TST.B FastFlag(A6) ;Rect clipped and black ?
BEQ.S @1 ;no, use slow drawslab loop
_FastSlabMode ;yes, get fast modeCase in A4
MOVE.L A4,MODECASE(A6) ;SAVE FOR LATER
BRA.S GOFORIT ;SKIP PATTERN STUFF
@1
;------------------------------------------------------------------
;
; ALLOCATE EXPANDED PATTERN BUFFER.
; EXPAND BYTE PATTERN TO PROPER DEPTH AND INIT PATTERN SELECTOR
;
CLR.L D7 ;SAY NOT INVERTED
MOVE LOCMODE(A6),D2 ;GET MODE
BTST #5,D2 ;a new arithmetic mode? <BAL 17Jan89>
BNE.S NOTINV ;if so, no invert bit to test <BAL 17Jan89>
BCLR #2,D2 ;TEST AND CLR INVERT BIT
BEQ.S NOTINV ;SKIP IF NOT INVERTED
NOT.L D7 ;INVERTED; D7 GETS ALL 1'S
NOTINV _PATEXPAND ;EXPAND 8 BYTE PATTERN TO 16 LONGS
;SET UP PATROW,PATHMASK,PATVMASK
MOVE PATROW(A6),D1 ;BIG PATTERN USED?
BNE.S DONEW ;=>YES, GO USE IT
MOVEQ #$F,D0 ;ELSE 16 ROWS OF PATTERN
MOVEQ #4,D1 ;GET PATTERN ROWBYTES
MOVE D1,PATROW(A6) ;SET PATTERN ROWBYTES
MOVE #3,PATHMASK(A6) ;HORIZONTAL MASK FOR PATTERN
MOVE #$3F,PATVMASK(A6) ;VERTICAL MASK FOR PATTERN
BRA.S DOOLD ;=>GO GET VERTICAL OFFSET
; NEW PATTERN. SET STARTING VERT POSITION, SET FLAG.
DONEW MOVEQ #0,D0 ;CLEAR HIGH WORD
MOVE PATVMASK(A6),D0 ;GET VERTICAL MASK
ADDQ #1,D0 ;CONVERT TO COUNT
DIVU PATROW(A6),D0 ;DIVIDE BY ROWSIZE
SUBQ #1,D0 ;CONVERT TO ROW MASK
DOOLD AND MINRECT+TOP(A6),D0 ;GET TOP VERT LOCAL COORD
MULU D1,D0 ;CALC OFFSET INTO PATTERN
MOVE.l D0,PATVPOS(A6) ;SAVE AS PATVPOS <BAL 22Jan89>
MOVE LOCMODE(A6),D2 ;GET (ALTERED) PEN MODE
_SlabMode ;GET SLOW MODECASE IN A4
;RELIES ON PATROW(A6)
MOVE.L A4,MODECASE(A6) ;SAVE FOR LATER
GOFORIT
;-----------------------------------------------------------
;
; Switch to 32 bit addressing mode
;
moveq #true32b,d0 ;switch to 32 bit addressing
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
move.b d0,MMUsave(a6) ;save previous state for later
;------------------------------------------------------------
;
; BUMP OVAL STATE RECORDS UNLESS VERT IS BETWEEN SKIPTOP AND SKIPBOT
;
MOVE OUTEROVAL+OVALTOP(A6),D7 ;START VERT:= OUTER OVAL TOP
MOVE D7,VERT(A6) ;SET UP FOR SEEKMASK
NEXTROW CMP SKIPTOP(A6),D7 ;IS VERT < SKIPTOP ?
BLT.S YESBUMP ;YES, OK TO BUMP OVALS
CMP SKIPBOT(A6),D7 ;IS VERT >= SKIPBOT ?
BLT.S NOBUMP ;NO, SKIP BUMPING
YESBUMP MOVE D7,-(SP) ;STASH CURRENT VERT
MOVE D7,D0 ;COPY CURRENT VERTICAL
LEA OUTEROVAL(A6),A3 ;POINT TO OUTER OVAL STATE RECORD
JSR BUMPOVAL ;BUMP IT TO NEXT SCANLINE
MOVE (SP),D0 ;COPY CURRENT VERT
LEA INNEROVAL(A6),A3 ;POINT TO INNER OVAL STATE RECORD
JSR BUMPOVAL ;BUMP IT TO NEXT SCANLINE
MOVE (SP)+,D7 ;RECOVER SAVED CURRENT VERT
;--------------------------------------------------
;
; ADJUST ARC STUFF AS WE CROSS THE MIDDLE VERTICALLY
;
NOBUMP CMP MIDVERT(A6),D7 ;IS CURRENT VERT = MIDVERT ?
BNE.S NOTMID ;NO, CONTINUE
TST.B ARCFLAG(A6) ;ARE WE DOING AN ARC ?
BEQ.S NOTMID ;NO, SKIP
NEG FLAG1(A6) ;YES, INVERT FLAGS AS WE CROSS
NEG FLAG2(A6)
;
; RE-CALCULATE SKIPFLAG, AND QUIT IF IT BECOMES TRUE
;
CLR.B SKIPFLAG(A6)
MOVE ARCANGLE(A6),D0
CMP #180,D0 ;IS ARC ANGLE > 180 ?
BGT.S OBTUSE1 ;SKIP IF ANGLE > 180
BLT.S ACUTE1 ;DEAL WITH ACUTE ANGLE
CMP #270,STARTANGLE(A6) ;IS STARTANGLE = 270 ?
BNE.S OBTUSE1 ;NO, CONTINUE
BRA DONE ;YES, WE'RE ALL DONE
ACUTE1 MOVE FLAG1(A6),D0
OR FLAG2(A6),D0
BPL DONE ;QUIT IF BOTH FLAG1 AND FLAG2>=0
OBTUSE1
;
; NOW SWAP THE ROLES OF LINE1 AND LINE2 AS THEY CROSS THE MIDDLE
;
MOVE FLAG1(A6),D0 ;SWAP FLAG1 AND FLAG2
MOVE FLAG2(A6),FLAG1(A6)
MOVE D0,FLAG2(A6)
MOVE.L LINE1(A6),D0 ;SWAP LINE1 AND LINE2
MOVE.L LINE2(A6),LINE1(A6)
MOVE.L D0,LINE2(A6)
MOVE.L SLOPE1(A6),D0 ;SWAP SLOPE1 AND SLOPE2
MOVE.L SLOPE2(A6),SLOPE1(A6)
MOVE.L D0,SLOPE2(A6)
NOTMID CMP MINRECT+TOP(A6),D7 ;IS CURRENT VERT < MINV ?
BLT NODRAW ;YES, DON'T DRAW
TST.B SKIPFLAG(A6) ;ARE WE SKIPPING ?
BNE NEXTPAT ;YES, SKIP
;------------------------------------------------
;
; SEEK MASK TO THE CURRENT VERTICAL, AND
; BRANCH BASED ON SOLID OR HOLLOW OVAL OR ARC.
;
TST.B FASTFLAG(A6) ;RECT CLIPPED AND BLACK ?
BNE.S NOMASK ;YES, DON'T BOTHER WITH MASK
JSR ([SEEKMASK,A6]) ;MAKE RGNBUFFER CURRENT
NOMASK TST.B ARCFLAG(A6) ;ARE WE DOING AN ARC ?
BNE.S DOARC ;YES, GO TO IT
CMP INNEROVAL+OVALTOP(A6),D7 ;IS VERT >= INNEROVAL OVALTOP ?
BLT SOVAL ;NO, TREAT AS SOLID OVAL
CMP INNEROVAL+OVALBOT(A6),D7 ;IS VERT < INNEROVAL OVALTOP ?
BGE SOVAL ;NO, TREAT AS SOLID OVAL
BRA HOVAL ;YES, PROCESS HOLLOW OVAL
;----------------------------------------------
;
; SOLID OR HOLLOW ARC: CALC OUTERLEFT AND OUTERRIGHT
;
DOARC MOVE.W OUTEROVAL+LEFTMOSTEDGE(A6),D1 ;GET HI WORD OF OUTEROVAL LEFT
TST FLAG1(A6) ;IS LINE1 ACTIVE ?
BPL.S @1 ;NO, CONTINUE
CMP.W LINE1(A6),D1 ;YES, CHECK LINE1 HORIZ COORD
BGE.S @1
MOVE.W LINE1(A6),D1 ;CALC MAX(OVALLEFT,LINE1)
@1 MOVE D1,OUTERLEFT(A6) ;SAVE OUTER LEFT
MOVE.W OUTEROVAL+RIGHTMOSTEDGE(A6),D2 ;GET HI WORD OF OUTEROVAL RIGHT
TST FLAG2(A6) ;IS LINE2 ACTIVE ?
BPL.S @2 ;NO, CONTINUE
CMP.W LINE2(A6),D2 ;YES, CHECK LINE2 HORIZ COORD
BLE.S @2
MOVE.W LINE2(A6),D2 ;CALC MIN(OVALRIGHT,LINE2)
@2 MOVE D2,OUTERRIGHT(A6) ;SAVE OUTER RIGHT
CMP INNEROVAL+OVALTOP(A6),D7 ;IS VERT >= INNEROVAL OVALTOP ?
BLT SARC ;NO, PROCESS SOLID ARC
CMP INNEROVAL+OVALBOT(A6),D7 ;IS VERT < INNEROVAL OVALTOP ?
BGE SARC ;NO, PROCESS SOLID ARC
;--------------------------------------------------
;
; HOLLOW ARC: CALC INNERLEFT AND INNERRIGHT
;
HARC MOVE.W INNEROVAL+LEFTMOSTEDGE(A6),D0 ;GET HI WORD OF INNEROVAL LEFT
TST FLAG2(A6) ;IS LINE2 ACTIVE ?
BPL.S @1 ;NO, CONTINUE
CMP.W LINE2(A6),D0 ;YES, CHECK LINE2 HORIZ COORD
BLE.S @1
MOVE.W LINE2(A6),D0 ;CALC MIN(OVALLEFT,LINE2)
@1 MOVE D0,INNERLEFT(A6) ;SAVE INNER LEFT
MOVE.W INNEROVAL+RIGHTMOSTEDGE(A6),D0 ;GET HI WORD OF INNEROVAL RIGHT
TST FLAG1(A6) ;IS LINE1 ACTIVE ?
BPL.S @2 ;NO, CONTINUE
CMP.W LINE1(A6),D0 ;YES, CHECK LINE1 HORIZ COORD
BGE.S @2
MOVE.W LINE1(A6),D0 ;CALC MAX(OVALRIGHT,LINE1)
@2 MOVE D0,INNERRIGHT(A6) ;SAVE INNER RIGHT
;--------------------------------------------------
;
; IF OUTERLEFT < OUTERRIGHT THEN PAINT TWO SLABS
;
CMP D2,D1 ;IS OUTERLEFT < OUTERRIGHT ?
BGE.S @3 ;NO, CONTINUE
MOVE INNERLEFT(A6),D2
BSR.S ONESLAB
MOVE INNERRIGHT(A6),D1
MOVE OUTERRIGHT(A6),D2
BRA DOSLAB
@3
;
; ELSE IF BOTH LINES ACTIVE AND ANGLE > 180 THEN PAINT TWO OR THREE SLABS
;
MOVE FLAG1(A6),D0
AND FLAG2(A6),D0 ;ARE BOTH LINES ACTIVE ?
BPL NEXTPAT ;NO, CONTINUE
CMP #180,ARCANGLE(A6) ;IS THE ANGLE > 180 ?
BLE NEXTPAT ;NO, CONTINUE
CMP INNERLEFT(A6),D2 ;IS INNERLEFT=OUTERRIGHT?
BNE.S @4 ;NO, CONTINUE
MOVE.W INNEROVAL+LEFTMOSTEDGE(A6),D2 ;YES DRAW A THIRD SLAB
BRA.S @5
@4 MOVE OUTERLEFT(A6),D0
CMP INNERRIGHT(A6),D0 ;IS INNERRIGHT=OUTERLEFT ?
BNE.S NOT3 ;NO, CONTINUE
MOVE.W INNEROVAL+RIGHTMOSTEDGE(A6),D1 ;YES, DRAW A THIRD SLAB
MOVE OUTERRIGHT(A6),D2
@5 BSR.S ONESLAB
NOT3
MOVE OUTEROVAL+LEFTMOSTEDGE(A6),D1
MOVE INNERLEFT(A6),D2
BSR.S ONESLAB
MOVE INNERRIGHT(A6),D1
MOVE.W OUTEROVAL+RIGHTMOSTEDGE(A6),D2
BRA.S DOSLAB
;---------------------------------------------------------
;
; LOCAL PROCEDURE TO SET UP AND DRAW ONE SLAB
;
ONESLAB MOVE.l PATVPOS(A6),D6 ;GET VERT POS IN PATTERN <BAL 22Jan89>
LEA ([EXPAT,A6],D6.l),A0 ;GET pointer to THIS ROW'S PATTERN
MOVE.L (A0),D6 ;set up the pattern
MOVE.L DSTLEFT(A6),A1 ;INIT DSTPTR TO LEFT
MOVE.L RGNBUFFER(A6),A2 ;INIT MASKPTR TO LEFT
LEA MINRECT(A6),A3 ;POINT TO MINRECT
; MOVE.L MODECASE(A6),A4 ;GET MODE CASE JUMP (don't need to reload)
MOVE DSTSHIFT(A6),D0 ;GET PIXEL TO BIT SHIFT AMOUNT
MOVE.L FCOLOR(A6),D4 ;PASS FCOLOR
MOVE.L BCOLOR(A6),D5 ;AND BACKCOLOR
_DrawSlab
RTS ;AND RETURN
;----------------------------------------------------
;
; SOLID ARC: IF OUTERLEFT < OUTERRIGHT THEN PAINT ONE SLAB
;
SARC CMP D2,D1 ;IS OUTERLEFT < OUTERRIGHT ?
BLT.S DOSLAB ;YES, DO ONE SLAB BETWEEN THEM
;
; ELSE IF BOTH LINES ACTIVE AND ANGLE > 180 THEN PAINT TWO SLABS
;
MOVE FLAG1(A6),D0
AND FLAG2(A6),D0 ;ARE BOTH LINES ACTIVE ?
BPL.S NEXTPAT ;NO, CONTINUE
CMP #180,ARCANGLE(A6) ;IS THE ANGLE > 180 ?
BLE.S NEXTPAT ;NO, CONTINUE
MOVE OUTEROVAL+LEFTMOSTEDGE(A6),D1
BSR ONESLAB
MOVE OUTERLEFT(A6),D1
MOVE.W OUTEROVAL+RIGHTMOSTEDGE(A6),D2
BRA.S DOSLAB
;--------------------------------------------------
;
; HOLLOW OVAL: DRAW TWO SLABS BETWEEN OUTER AND INNER OVALS
;
HOVAL MOVE.W OUTEROVAL+LEFTMOSTEDGE(A6),D1 ;GET OUTEROVAL LEFTMOSTEDGE.INT
MOVE.W INNEROVAL+LEFTMOSTEDGE(A6),D2 ;GET INNEROVAL LEFTMOSTEDGE.INT
BSR ONESLAB ;DRAW HORIZ SLAB BETWEEN THEM
MOVE.W INNEROVAL+RIGHTMOSTEDGE(A6),D1 ;GET OUTEROVAL RIGHTMOSTEDGE.INT
MOVE.W OUTEROVAL+RIGHTMOSTEDGE(A6),D2 ;GET INNEROVAL RIGHTMOSTEDGE.INT
BSR ONESLAB ;DRAW HORIZ SLAB BETWEEN THEM
BRA.S NEXTPAT
;----------------------------------------------------
;
; SOLID OVAL: DRAW ONE SLAB BETWEEN LEFT AND RIGHT EDGES OF OUTER OVAL
;
SOVAL MOVE.W OUTEROVAL+LEFTMOSTEDGE(A6),D1 ;GET OUTEROVAL LEFTMOSTEDGE.INT
MOVE.W OUTEROVAL+RIGHTMOSTEDGE(A6),D2 ;GET OUTEROVAL RIGHTMOSTEDGE.INT
DOSLAB BSR ONESLAB ;DRAW HORIZ SLAB BETWEEN THEM
;-------------------------------------------------------------------
;
; BUMP DESTINATION VERTICALLY AND LOOP FOR ALL SCAN LINES
;
NEXTPAT MOVE.l PATVPOS(A6),D0 ;GET PATVPOS <BAL 22Jan89>
ADD PATROW(A6),D0 ;BUMP TO NEXT SCAN
AND PATVMASK(A6),D0 ;WRAP AT END OF PATTERN
MOVE.l D0,PATVPOS(A6) ;SAVE PATVPOS <BAL 22Jan89>
MOVE.L DSTROW(A6),D0 ;GET DST ROWBYTES
ADD.L D0,DSTLEFT(A6) ;BUMP DST TO NEXT ROW
NODRAW MOVE.L SLOPE1(A6),D0 ;BUMP LINE1 AND LINE2
ADD.L D0,LINE1(A6)
MOVE.L SLOPE2(A6),D0
ADD.L D0,LINE2(A6)
ADD #1,D7 ;BUMP CURRENT VERT
MOVE D7,VERT(A6) ;AND UPDATE PARM FOR SEEKMASK
CMP MINRECT+BOTTOM(A6),D7 ;HAVE WE REACHED THE BOTTOM YET ?
BLT NEXTROW ;NO, LOOP FOR MORE
DONE move.b MMUsave(a6),d0 ;get previous MMU state in d0
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
SHOW TST.B CRSRFLAG(A6) ;IS SCREEN DST?
BEQ.S GOHOME ;=>NO, DON'T SHOW CURSOR
_SHOWCURSOR ;RESTORE CURSOR
GOHOME BSET #hiliteBit,HiliteMode ;reset hilite override, in case colormap was skipped
MOVE.L SAVESTK(A6),SP ;STRIP BUFFER
MOVEM.L (SP)+,D0-D7/A1-A4 ;RESTORE REGISTERS
UNLINK PARAMSIZE,'DRAWARC '
INITOVAL PROC EXPORT
;------------------------------------------------------------
;
; PROCEDURE InitOval(dstRect: Rect; VAR oval: OvalRec;
; ovalWidth,ovalHeight: INTEGER);
;
; initialize an oval state record to fit the given rectangle.
;
; INPUTS: A0: dstRect
; A1: ovalRec
; D1: ovalHeight
; D2: ovalWidth
;
; CLOBBERS D0,D1,D2
;
;-----------------------------------------------------------
;
; INIT OVAL TOP AND BOTTOM TO DSTRECT TOP AND BOTTOM
;
MOVE TOP(A0),OVALTOP(A1) ;INIT OVAL TOP
MOVE BOTTOM(A0),OVALBOT(A1) ;INIT OVAL BOTTOM
; CHECK OVALWIDTH AND OVALHEIGHT, PIN AT 0
TST D2 ;IS OVALWIDTH NEGATIVE ?
BPL.S OK1 ;NO, CONTINUE
CLR D2 ;YES, PIN IT TO 0
OK1 TST D1 ;IS OVALHEIGHT NEGATIVE ?
BPL.S OK2 ;NO, CONTINUE
CLR D1 ;YES, PIN IT TO 0
OK2
; CHECK OVALWIDTH AND OVALHEIGHT, TRIM IF BIGGER THAN DSTRECT
MOVE RIGHT(A0),D0
SUB LEFT(A0),D0 ;CALC DSTRECT WIDTH
CMP D0,D2 ;IS OVALWIDTH > DSTWIDTH ?
BLE.S OK3 ;NO,CONTINUE
MOVE D0,D2 ;YES, OVALWIDTH:= DSTWIDTH
OK3 MOVE BOTTOM(A0),D0
SUB TOP(A0),D0 ;CALC DSTRECT HEIGHT
CMP D0,D1 ;IS OVALHEIGHT > DSTHEIGHT ?
BLE.S OK4 ;NO,CONTINUE
MOVE D0,D1 ;YES, OVALHEIGHT:= DSTHEIGHT
OK4
; SET UP OVAL LEFT EDGE AND OVAL RIGHT EDGE, FIXED POINT NUMBERS
MOVE.W RIGHT(A0),RIGHTMOSTEDGE(A1) ;RIGHTMOSTEDGE.INT := DSTRECT.RIGHT
CLR.W RIGHTMOSTEDGE+2(A1) ;RIGHTMOSTEDGE.FRACT := 0
MOVE.W LEFT(A0),LEFTMOSTEDGE(A1) ;LEFTMOSTEDGE.INT := DSTRECT.LEFT
CLR.W LEFTMOSTEDGE+2(A1) ;LEFTMOSTEDGE.FRACT := 0
MOVE D2,D0 ;GET OVAL WIDTH
SWAP D0 ;PUT IN HI WORD
CLR D0 ;CLEAR LO WORD FOR FIXED POINT
LSR.L #1,D0 ;CALC OVAL WIDTH DIV 2
ADD.L D0,LEFTMOSTEDGE(A1) ;ADD OVALWD/2 TO LEFTMOSTEDGE
SUB.L D0,RIGHTMOSTEDGE(A1) ;SUBTRACT OVALWD/2 FROM LEFTMOSTEDGE
MOVE.L #$00008000,D0 ;GET FIXED POINT 1/2
MOVE.L D0,ONEHALF(A1) ;SAVE IN OVAL STATE RECORD
ADD.L D0,RIGHTMOSTEDGE(A1) ;BIAS RIGHT EDGE +1/2
; INIT OVALY TO -OVALHEIGHT + 1 (SCALED BY 2, BIASED 1/2 SCANLINE)
MOVEQ #1,D0
SUB D1,D0
MOVE D0,OVALY(A1) ;OVALY:=1-HEIGHT
; INIT RSQYSQ TO 2*OVALHEIGHT-1
MOVE D1,D0 ;GET HEIGHT
EXT.L D0 ;CLEAR OUT HI WORD
ADD.L D0,D0 ;CALC 2*HEIGHT
SUB.L #1,D0 ;CALC 2*HEIGHT - 1
MOVE.L D0,RSQYSQ(A1) ;RSQYSQ:=2*HEIGHT-1
; INIT SQUARE TO 0.0
CLR.L SQUARE(A1) ;SQUARE:=0
CLR.L SQUARE+4(A1) ;FRACT PART := 0 TOO
; ODDNUM:= 1 TIMES ASPECT RATIO SQUARED
CLR.L -(SP) ;GET READY FOR FUNCTION RESULT
MOVE D1,-(SP) ;PUSH NUMERATOR=HEIGHT
MOVE D2,-(SP) ;PUSH DENOMINATOR=WIDTH
_FixRatio ;CALC FIXED POINT HEIGHT/WIDTH
MOVE.L (SP),-(SP) ;DUPLICATE RESULT
PEA ODDNUM(A1) ;PUSH ADDR FOR RESULT
_LongMul ;CALC 64BIT (HEIGHT/WIDTH) SQUARED
; ODDBUMP:= 2 TIMES ASPECT RATIO SQUARED
MOVE.L ODDNUM+4(A1),D0 ;GET LO LONG OF RESULT
ADD.L D0,D0 ;DOUBLE IT
MOVE.L D0,ODDBUMP+4(A1) ;STORE INTO LO LONG OF ODDBUMP
MOVE.L ODDNUM(A1),D0
ADDX.L D0,D0 ;DOUBLE HI LONG WITH CARRY
MOVE.L D0,ODDBUMP(A1)
RTS
BUMPOVAL PROC EXPORT
;------------------------------------------------------------
;
; LOCAL PROCEDURE BumpOval(VAR oval: OvalRec; vert: INTEGER);
;
; bump an oval state record to the next scanline down.
;
; INPUTS: A3 POINTS TO OVAL STATE RECORD
; D0 CONTAINS CURRENT VERT
;
; CLOBBERS D0-D7,A0-A3
;
;
;-------------------------------------------------------
;
; ONLY BUMP IF VERT IS BETWEEN OVALTOP AND OVALBOT
;
CMP (A3)+,D0 ;IS VERT < OVAL TOP ?
BLT.S GOHOME ;YES, IGNORE
CMP (A3)+,D0 ;IS VERT >= OVAL BOTTOM ?
BGE.S GOHOME ;YES, IGNORE
MOVE (A3),D0 ;GET OVALY
ADD #2,(A3)+ ;ADD 2 TO OVALY FOR NEXT TIME
MOVEM.L (A3),D1-D7/A0-A2 ;GET REST OF THE OVAL RECORD
BRA.S WHILE1 ;GO TO LOOP START
;------------------------------------------
;
; register usage:
;
; D0: vert
; D1: RSQYSQ
; D2,D3: SQUARE
; D4,D5: ODDNUM
; D6,D7: ODDBUMP
; A0: LEFTMOSTEDGE
; A1: RIGHTMOSTEDGE
; A2: #$00008000
; A3: modified oval ptr
;
;-----------------------------------------------
;
; WHILE SQUARE < RSQYSQ DO MAKE OVAL BIGGER
;
MORE1 ADD.L A2,A1 ;RIGHTMOSTEDGE := RIGHTMOSTEDGE + 1/2
SUB.L A2,A0 ;LEFTMOSTEDGE := LEFTMOSTEDGE - 1/2
ADD.L D5,D3 ;SQUARE := SQUARE + ODDNUM
ADDX.L D4,D2 ;ALL 64 BITS OF IT
ADD.L D7,D5 ;ODDNUM := ODDNUM + ODDBUMP
ADDX.L D6,D4 ;ALL 64 BITS OF IT
WHILE1 CMP.L D1,D2 ;IS SQUARE < RSQYSQ ?
BLT MORE1 ;YES, LOOP
BRA.S WHILE2 ;NO, GO TO NEXT LOOP START
;-----------------------------------------------
;
; WHILE SQUARE > RSQYSQ DO MAKE OVAL SMALLER
;
MORE2 SUB.L A2,A1 ;RIGHTMOSTEDGE := RIGHTMOSTEDGE - 1/2
ADD.L A2,A0 ;LEFTMOSTEDGE := LEFTMOSTEDGE + 1/2
SUB.L D7,D5 ;ODDNUM := ODDNUM - ODDBUMP
SUBX.L D6,D4 ;ALL 64 BITS OF IT
SUB.L D5,D3 ;SQUARE := SQUARE + ODDNUM
SUBX.L D4,D2 ;ALL 64 BITS OF IT
WHILE2 CMP.L D1,D2 ;IS SQUARE > RSQYSQ ?
BGT MORE2 ;YES, LOOP
ADD #1,D0 ;CALC OVALY+1
EXT.L D0 ;SIGN EXTEND TO A LONG
ASL.L #2,D0 ;CALC 4*(OVALY+1)
SUB.L D0,D1 ;RSQYSQ := RSQYSQ-4*(OVALY+1)
MOVEM.L D1-D7/A0-A2,(A3) ;UPDATE OVAL RECORD
GOHOME RTS
ENDPROC