mac-rom/QuickDraw/DrawArc.a
Elliot Nunn 4325cdcc78 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 09:52:23 +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