; ; 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): ; ; 6/11/92 stb 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. ; 11/7/87 BAL Fixed ChkPat to handle new patterns. ; 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 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 ;---------------------------------------------------- ; ; 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? BEQ.S @oldPat ;=>yes, skip pixpat fields MOVE.L (a0),a0 ;get the pixpat handle MOVE.L (a0),a0 ;get the pixpat pointer TST PATTYPE(A0) ;is it an old-style pattern? BNE.S FLAGOK ;=>no, skip fast case MOVE.L patData(a0),a0 ;get handle to pattern data MOVE.L (a0),a0 ;get pattern ptr @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 ; <7> ADD BOTTOM(A0),A1 ; <7> MOVE.L A1,D0 ; <7> ASR.L #1,D0 ; <7> MOVE D0,MIDVERT(A6) ;MID VERT := (DSTBOT+DSTTOP)/2 MOVE LEFT(A0),A1 ; <7> ADD RIGHT(A0),A1 ; <7> MOVE.L A1,D0 ; <7> ASR.L #1,D0 ; <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? 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 08Nov87 BAL ; MOVE MINRECT+RIGHT(A6),D0 ;GET MINRECT RIGHT SUB D2,D0 ;CALC MAXH-BUFLEFT move d0,d1 ;save for expansion scanline buffer ext.l d1 ;clear out high word lsl.l d5,d1 ;convert to bits subq.l #1,d1 ;force downward round LSR.l #5,D1 ;GET NUMBER OF LONGS IN SCANBUF - 1 MOVE D1,BUFSIZE(A6) ;BUFSIZE = # LONGS -1 LSR #5,D0 ;get (pixels in scanbuf)/32 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 move.l maskbc,StackFree(a6) ;pretend lots of stack 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 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 MOVE DSTSHIFT(A6),D7 ;GET PIXEL TO BIT SHIFT AMOUNT LSL.L D7,D2 ;CONVERT PIXELS TO BITS LSR.L #3,D2 ;CONVERT BITS TO BYTES ; EXT.L D2 ;CLR HI WORD 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? BNE.S NOTINV ;if so, no invert bit to test 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 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 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 ADD PATROW(A6),D0 ;BUMP TO NEXT SCAN AND PATVMASK(A6),D0 ;WRAP AT END OF PATTERN MOVE.l D0,PATVPOS(A6) ;SAVE PATVPOS 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