Copyright This Material is Copyright © 1984 Apple Inc. and is made available only for non-commercial use.
This is QuickDraw source code from the Computer History Museum collection.
Copyright This Material is Copyright © 1984 Apple Inc. and is made available only for non-commercial use.
This is QuickDraw source code from the Computer History Museum collection.
| ;----------------------------------------------------------- | |
| ; | |
| ; --> DRAWARC.TEXT | |
| ; | |
| ; Routine to draw solid or hollow Ovals, RoundRects or Arcs. | |
| ; | |
| ;------------------------------------------------------ | |
| ; | |
| ; OFFSETS IN AN OVAL STATE RECORD: | |
| ; | |
| OVALTOP .EQU 0 ;INTEGER | |
| OVALBOT .EQU OVALTOP+2 ;INTEGER | |
| OVALY .EQU OVALBOT+2 ;INTEGER | |
| RSQYSQ .EQU OVALY+2 ;LONGINT | |
| SQUARE .EQU RSQYSQ+4 ;64 BIT LONGFIX | |
| ODDNUM .EQU SQUARE+8 ;64 BIT LONGFIX | |
| ODDBUMP .EQU ODDNUM+8 ;64 BIT LONGFIX | |
| LEFTEDGE .EQU ODDBUMP+8 ;32 BIT FIXED POINT | |
| RIGHTEDGE .EQU LEFTEDGE+4 ;32 BIT FIXED POINT | |
| ONEHALF .EQU RIGHTEDGE+4 ;32 BIT FIXED POINT | |
| OVALSIZE .EQU ONEHALF+4 ;SIZE OF AN OVALREC | |
| .PROC DrawArc,8 | |
| .REF InitOval,BumpOval,SlopeFromAngle | |
| .REF RSect,ShieldCursor,ShowCursor,TrimRect | |
| .REF InitRgn,SeekRgn,PatExpand,ColorMap | |
| .REF XorSlab,DrawSlab,SlabMode,FastSlabMode,MaskTab | |
| ;---------------------------------------------------------------- | |
| ; | |
| ; 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: | |
| ; | |
| EXPAT .EQU -64 ;16 LONGS | |
| MINRECT .EQU EXPAT-8 ;RECT | |
| STATEA .EQU MINRECT-RGNREC ;RGN STATE RECORD | |
| STATEB .EQU STATEA-RGNREC ;RGN STATE RECORD | |
| STATEC .EQU STATEB-RGNREC ;RGN STATE RECORD | |
| SAVESTK .EQU STATEC-4 ;LONG | |
| RECTFLAG .EQU SAVESTK-2 ;WORD | |
| MASKBUF .EQU RECTFLAG-4 ;LONG | |
| BUFLEFT .EQU MASKBUF-2 ;WORD | |
| BUFSIZE .EQU BUFLEFT-2 ;WORD | |
| MODECASE .EQU BUFSIZE-4 ;LONG | |
| DSTLEFT .EQU MODECASE-4 ;LONG | |
| SAVEA5 .EQU DSTLEFT-4 ;LONG | |
| PORT .EQU SAVEA5-4 ;LONG | |
| FASTFLAG .EQU PORT-2 ;BYTE | |
| TEMPRECT .EQU FASTFLAG-8 ;RECT | |
| INNEROVAL .EQU TEMPRECT-OVALSIZE ;OVAL RECORD | |
| OUTEROVAL .EQU INNEROVAL-OVALSIZE ;OVAL RECORD | |
| SKIPTOP .EQU OUTEROVAL-2 ;WORD | |
| SKIPBOT .EQU SKIPTOP-2 ;WORD | |
| ARCFLAG .EQU SKIPBOT-1 ;BYTE FLAG | |
| SKIPFLAG .EQU ARCFLAG-1 ;BYTE FLAG | |
| STOPANGLE .EQU SKIPFLAG-2 ;INTEGER | |
| MIDVERT .EQU STOPANGLE-2 ;INTEGER | |
| MIDHORIZ .EQU MIDVERT-2 ;INTEGER | |
| WIDTH .EQU MIDHORIZ-2 ;INTEGER | |
| HEIGHT .EQU WIDTH-2 ;INTEGER | |
| SLOPE1 .EQU HEIGHT-4 ;LONG, FIXED POINT | |
| SLOPE2 .EQU SLOPE1-4 ;LONG, FIXED POINT | |
| LINE1 .EQU SLOPE2-4 ;LONG, FIXED POINT | |
| LINE2 .EQU LINE1-4 ;LONG, FIXED POINT | |
| FLAG1 .EQU LINE2-2 ;WORD | |
| FLAG2 .EQU FLAG1-2 ;WORD | |
| OUTERLEFT .EQU FLAG2-2 ;WORD | |
| OUTERRIGHT .EQU OUTERLEFT-2 ;WORD | |
| INNERLEFT .EQU OUTERRIGHT-2 ;WORD | |
| INNERRIGHT .EQU INNERLEFT-2 ;WORD | |
| PATINDEX .EQU INNERRIGHT-2 ;WORD | |
| VARSIZE .EQU PATINDEX ;SIZE OF LOCAL VARIABLES | |
| LINK A6,#VARSIZE ;ALLOCATE LOCAL VARS | |
| MOVEM.L D0-D7/A1-A5,-(SP) ;SAVE REGS | |
| MOVE.L SP,SAVESTK(A6) ;REMEMBER STACK FOR LATER | |
| MOVE.L A5,SAVEA5(A6) ;REMEMBER GLOBAL PTR | |
| MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS | |
| MOVE.L THEPORT(A0),A3 ;GET CURRENT GRAFPORT | |
| TST PNVIS(A3) ;IS PNVIS NEG ? | |
| BLT GOHOME ;YES, QUIT | |
| MOVE.L A3,PORT(A6) ;SAVE CURRENT GRAFPORT | |
| ;------------------------------------------------------- | |
| ; | |
| ; QUIT IF MODE NOT IN 8..15 | |
| ; | |
| MOVEQ #-8,D0 ;MASK TO KILL BOTTOM 3 BITS | |
| AND MODE(A6),D0 ;GET ALL BUT 3 BITS OF MODE | |
| CMP #8,D0 ;IS PEN MODE 8..15 ? | |
| BNE GOHOME ;NO, QUIT | |
| ;---------------------------------------------------------------- | |
| ; | |
| ; ADJUST MODE AND PATTERN IF COLOR FILTERING. | |
| ; | |
| TST COLRBIT(A3) ;IS COLORBIT = 0 ? | |
| BEQ.S NOCOLOR ;YES, DON'T MAP | |
| MOVE MODE(A6),-(SP) ;PUSH INPUT MODE | |
| MOVE.L PAT(A6),-(SP) ;PUSH ADDR OF INPUT PATTERN | |
| JSR COLORMAP ;ALTER BY THECOLOR, THEFILTER | |
| MOVE.L (SP)+,PAT(A6) ;GET (ALTERED) PATTERN | |
| MOVE (SP)+,MODE(A6) ;GET (ALTERED) MODE | |
| NOCOLOR MOVE.L A3,A5 ;PUT GRAFPORT IN A5 | |
| ;--------------------------------------------------------- | |
| ; | |
| ; GET CLIPRGN AND VISRGN HANDLES AND DE-REFERENCE THEM | |
| ; | |
| MOVE.L CLIPRGN(A5),A2 ;GET CLIPRGN HANDLE | |
| MOVE.L (A2),A2 ;GET CLIPRGN POINTER | |
| MOVE.L VISRGN(A5),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 PORTBITS+BOUNDS(A5) ;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 | |
| JSR 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(A5),-(SP) ;push rgnHandle | |
| PEA minRect(A6) ;push addr of minRect | |
| JSR TrimRect ;call trimRect | |
| BLT GOHOME ;quit if intersection empty | |
| BGT.S FLAGOK ;continue if non-rectangular | |
| ; | |
| ; CHECK FOR BLACK OR WHITE PATTERN | |
| ; | |
| CKPAT MOVE.L PAT(A6),A0 ;POINT TO PATTERN | |
| 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,MODE(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 MODE(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,MODE(A6) ;UPDATE MODE | |
| BRA.S FLAGOK ;AND CONTINUE | |
| MODEMAP .BYTE 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),D0 | |
| ADD BOTTOM(A0),D0 | |
| ASR #1,D0 | |
| MOVE D0,MIDVERT(A6) ;MID VERT := (DSTBOT+DSTTOP)/2 | |
| MOVE LEFT(A0),D0 | |
| ADD RIGHT(A0),D0 | |
| ASR #1,D0 | |
| 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 | |
| JSR 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 | |
| JSR 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(A5),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,TEMPRECT(A6) ;STORE RESULTS INTO TEMPRECT | |
| LEA TEMPRECT(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. | |
| ; | |
| PEA MINRECT(A6) ;PUSH SHIELDRECT PARAMETER | |
| MOVE.L PORTBITS+BOUNDS+TOPLEFT(A5),-(SP) ;PUSH DELTA TO CONVERT TO GLOBAL | |
| MOVE.L SAVEA5(A6),A5 ;GET GLOBAL PTR | |
| JSR SHIELDCURSOR ;HIDE CURSOR IF IT INTERSECTS | |
| MOVE.L PORT(A6),A5 ;RESTORE GRAFPORT IN A5 | |
| ;------------------------------------ | |
| ; | |
| ; CALC BUFLEFT | |
| ; | |
| MOVE MINRECT+LEFT(A6),D2 ;GET MINRECT LEFT | |
| SUB PORTBITS+BOUNDS+LEFT(A5),D2 ;CONVERT TO GLOBAL COORDS | |
| AND #$FFF0,D2 ;TRUNC TO MULT OF 16 | |
| ADD PORTBITS+BOUNDS+LEFT(A5),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 BUFSIZE | |
| ; | |
| MOVE MINRECT+RIGHT(A6),D0 ;GET MINRECT RIGHT | |
| SUB D2,D0 ;CALC MAXH-BUFLEFT | |
| LSR #5,D0 ;DIV BY 32 FOR LONGS | |
| MOVE D0,BUFSIZE(A6) ;BUFSIZE = # LONGS - 1 | |
| ;------------------------------------------------------------------------- | |
| ; | |
| ; 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,MASKBUF(A6) ;REMEMBER WHERE MASKBUF IS | |
| ;------------------------------------------------------------------------- | |
| ; | |
| ; INIT STATE RECORDS AND ALLOCATE BUFFERS FOR EACH NON-RECTANGULAR REGION | |
| ; | |
| CLR D5 ;INIT BOTH ARE RECT | |
| MOVE #-32767,STATEA+THISV(A6) ;INIT REGION STATEA | |
| MOVE #32767,STATEA+NEXTV(A6) ;TO HARMLESS IN CASE RECT | |
| CMP #10,RGNSIZE(A2) ;IS CLIPRGN RECTANGULAR ? | |
| BEQ.S ARECT ;YES, CONTINUE | |
| ADD #2,D5 ;NO, SET ITS FLAG | |
| MOVE.L A2,A0 ;POINT TO CLIPRGN | |
| LEA STATEA(A6),A1 ;POINT TO STATE RECORD A | |
| BSR.S INITONE ;INIT STATE, ALLOC BUFFER | |
| ARECT | |
| MOVE #-32767,STATEB+THISV(A6) ;INIT REGION STATEB | |
| MOVE #32767,STATEB+NEXTV(A6) ;TO HARMLESS IN CASE RECT | |
| CMP #10,RGNSIZE(A3) ;IS VISRGN RECTANGULAR ? | |
| BEQ.S BRECT ;YES, CONTINUE | |
| ADD #4,D5 ;NO, SET ITS FLAG | |
| MOVE.L A3,A0 ;POINT TO VISRGN | |
| LEA STATEB(A6),A1 ;POINT TO STATE RECORD B | |
| PEA BRECT ;PUSH FAKE RETURN ADDR | |
| INITONE MOVE MINRECT+LEFT(A6),D0 ;GET MINH | |
| MOVE MINRECT+RIGHT(A6),D1 ;GET MAXH | |
| MOVE BUFLEFT(A6),D2 ;GET BUFLEFT | |
| JMP INITRGN ;INIT STATE, ALLOC BUFFER | |
| BRECT | |
| ;-------------------------------------------------------------------- | |
| ; | |
| ; IF BOTH REGIONS ARE RECTANGULAR, THEN DRAW MINRECT INTO MASK BUFFER | |
| ; | |
| MOVE.W D5,RECTFLAG(A6) ;ARE ALL RGNS RECT ? | |
| BNE.S NOTRECT ;NO, CONTNUE | |
| MOVE.L MASKBUF(A6),A0 ;YES, POINT TO MASK BUFFER | |
| MOVE MINRECT+LEFT(A6),D3 ;SET UP LEFT | |
| SUB BUFLEFT(A6),D3 ;MAKE IT BUFFER RELATIVE | |
| MOVE MINRECT+RIGHT(A6),D4 ;SET UP RIGHT | |
| SUB BUFLEFT(A6),D4 ;MAKE IT BUFFER RELATIVE | |
| JSR XorSlab ;AND XOR BETWEEN THEM | |
| NOTRECT | |
| SKIPSETUP | |
| ;------------------------------------ | |
| ; | |
| ; CALC STARTING DSTLEFT | |
| ; | |
| MOVE MINRECT+TOP(A6),D1 ;GET MINRECT TOP | |
| SUB PORTBITS+BOUNDS+TOP(A5),D1 ;CONVERT TO GLOBAL COORDS | |
| MULU PORTBITS+ROWBYTES(A5),D1 ;MULT BY DST ROWBYTES | |
| ADD.L PORTBITS+BASEADDR(A5),D1 ;ADD START OF BITMAP | |
| SUB PORTBITS+BOUNDS+LEFT(A5),D2 ;CONVERT BUFLEFT TO GLOBAL | |
| LSR #3,D2 ;CALC BUFLEFT DIV 8 | |
| 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 | |
| SUB D1,MINRECT+LEFT(A6) | |
| SUB D1,MINRECT+RIGHT(A6) | |
| SUB.W D1,OUTEROVAL+LEFTEDGE(A6) ;ADJUST OUTEROVAL LEFTEDGE.INT | |
| SUB.W D1,OUTEROVAL+RIGHTEDGE(A6) ;ADJUST OUTEROVAL RIGHTEDGE.INT | |
| SUB.W D1,INNEROVAL+LEFTEDGE(A6) ;ADJUST INNEROVAL LEFTEDGE.INT | |
| SUB.W D1,INNEROVAL+RIGHTEDGE(A6) ;ADJUST INNEROVAL RIGHTEDGE.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 MODE(A6),D2 ;GET (ALTERED) PEN MODE | |
| TST.B FastFlag(A6) ;Rect clipoped and black ? | |
| BEQ.S @1 ;no, use slow drawslab loop | |
| JSR FastSlabMode ;yes, get fast modeCase in A4 | |
| MOVE.L A4,MODECASE(A6) ;SAVE FOR LATER | |
| CLR PATINDEX(A6) ;MAKE UNUSED PATINDEX EVEN | |
| BRA GOFORIT ;SKIP PATTERN STUFF | |
| @1 JSR SlabMode ;get slow modeCase in A4 | |
| MOVE.L A4,MODECASE(A6) ;SAVE FOR LATER | |
| ;------------------------------------------------------------------ | |
| ; | |
| ; EXPAND 8 BYTE PATTERN TO 16 LONGS AND INIT PATTERN SELECTOR | |
| ; | |
| CLR.L D7 ;SAY NOT INVERTED | |
| MOVE MODE(A6),D2 ;GET MODE | |
| 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 MOVE PORTBITS+BOUNDS+LEFT(A5),D2 ;GET GLOBAL-LOCAL OFFSET | |
| MOVE.L PAT(A6),A0 ;POINT TO BYTE WIDE PATTERN | |
| LEA EXPAT(A6),A1 ;POINT TO EXPANDED PATTERN | |
| MOVE.L SAVEA5(A6),A5 ;GET GLOBAL PTR | |
| JSR PATEXPAND ;EXPAND 8 BYTE PATTERN TO 16 LONGS | |
| MOVE.L PORT(A6),A5 ;RESTORE GRAFPORT IN A5 | |
| MOVEQ #$F,D0 ;TREAT COORD MOD 16 | |
| AND MINRECT+TOP(A6),D0 ;GET TOP VERT LOCAL COORD | |
| LSL #2,D0 ;QUAD FOR 4 BYTE PATTERNS | |
| MOVE D0,PATINDEX(A6) ;SET UP PATTERN INDEX | |
| ;------------------------------------------------------------ | |
| ; | |
| ; BUMP OVAL STATE RECORDS UNLESS VERT IS BETWEEN SKIPTOP AND SKIPBOT | |
| ; | |
| GOFORIT MOVE OUTEROVAL+OVALTOP(A6),D7 ;START VERT:= OUTER OVAL TOP | |
| 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 | |
| BSR SEEKMASK ;MAKE MASKBUF 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+LEFTEDGE(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+RIGHTEDGE(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+LEFTEDGE(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+RIGHTEDGE(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+LEFTEDGE(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+RIGHTEDGE(A6),D1 ;YES, DRAW A THIRD SLAB | |
| MOVE OUTERRIGHT(A6),D2 | |
| @5 BSR.S ONESLAB | |
| NOT3 | |
| MOVE OUTEROVAL+LEFTEDGE(A6),D1 | |
| MOVE INNERLEFT(A6),D2 | |
| BSR.S ONESLAB | |
| MOVE INNERRIGHT(A6),D1 | |
| MOVE.W OUTEROVAL+RIGHTEDGE(A6),D2 | |
| BRA.S DOSLAB | |
| ;--------------------------------------------------------- | |
| ; | |
| ; LOCAL PROCEDURE TO SET UP AND DRAW ONE SLAB | |
| ; | |
| ONESLAB MOVEQ #$3F,D6 ;GET WRAP-AROUND MASK | |
| AND PATINDEX(A6),D6 ;GET PATINDEX MOD 64 | |
| MOVE.L EXPAT(A6,D6),D6 ;GET THIS ROW'S PATTERN | |
| LEA MaskTab,A0 ;POINT TO MASK TABLE | |
| MOVE.L DSTLEFT(A6),A1 ;INIT DSTPTR TO LEFT | |
| MOVE.L MASKBUF(A6),A2 ;INIT MASKPTR TO LEFT | |
| LEA MINRECT(A6),A3 ;POINT TO MINRECT | |
| MOVE.L MODECASE(A6),A4 ;GET MODE CASE JUMP | |
| JMP DrawSlab | |
| ;---------------------------------------------------- | |
| ; | |
| ; 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+LEFTEDGE(A6),D1 | |
| BSR ONESLAB | |
| MOVE OUTERLEFT(A6),D1 | |
| MOVE.W OUTEROVAL+RIGHTEDGE(A6),D2 | |
| BRA.S DOSLAB | |
| ;-------------------------------------------------- | |
| ; | |
| ; HOLLOW OVAL: DRAW TWO SLABS BETWEEN OUTER AND INNER OVALS | |
| ; | |
| HOVAL MOVE.W OUTEROVAL+LEFTEDGE(A6),D1 ;GET OUTEROVAL LEFTEDGE.INT | |
| MOVE.W INNEROVAL+LEFTEDGE(A6),D2 ;GET INNEROVAL LEFTEDGE.INT | |
| BSR ONESLAB ;DRAW HORIZ SLAB BETWEEN THEM | |
| MOVE.W INNEROVAL+RIGHTEDGE(A6),D1 ;GET OUTEROVAL RIGHTEDGE.INT | |
| MOVE.W OUTEROVAL+RIGHTEDGE(A6),D2 ;GET INNEROVAL RIGHTEDGE.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+LEFTEDGE(A6),D1 ;GET OUTEROVAL LEFTEDGE.INT | |
| MOVE.W OUTEROVAL+RIGHTEDGE(A6),D2 ;GET OUTEROVAL RIGHTEDGE.INT | |
| DOSLAB BSR ONESLAB ;DRAW HORIZ SLAB BETWEEN THEM | |
| ;------------------------------------------------------------------- | |
| ; | |
| ; BUMP DESTINATION VERTICALLY AND LOOP FOR ALL SCAN LINES | |
| ; | |
| NEXTPAT ADD #4,PATINDEX(A6) ;BUMP PATTERN INDEX | |
| MOVE PORTBITS+ROWBYTES(A5),D0 ;GET DST ROWBYTES | |
| EXT.L D0 ;MAKE IT LONG | |
| 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 | |
| CMP MINRECT+BOTTOM(A6),D7 ;HAVE WE REACHED THE BOTTOM YET ? | |
| BLT NEXTROW ;NO, LOOP FOR MORE | |
| DONE MOVE.L SAVEA5(A6),A5 ;GET GLOBAL PTR | |
| JSR SHOWCURSOR ;RESTORE CURSOR | |
| GOHOME MOVE.L SAVESTK(A6),SP ;STRIP BUFFER | |
| MOVEM.L (SP)+,D0-D7/A1-A5 ;RESTORE REGISTERS | |
| UNLINK PARAMSIZE,'DRAWARC ' | |
| ;----------------------------------------------------------------------------- | |
| ; | |
| ; LOCAL ROUTINE TO UPDATE THE MASK BUFFER | |
| ; BASED ON WHICH REGIONS ARE RECTANGULAR | |
| ; | |
| SEEKMASK MOVE D7,D0 ;GET CURRENT VERT COORD | |
| MOVE RECTFLAG(A6),D1 ;GET RECTFLAG = 0,2,4 | |
| MOVE RECTJMP(D1),D1 ;GET OFFSET FROM TABLE | |
| JMP RECTJMP(D1) ;TAKE CASE JUMP | |
| RECTJMP .WORD IGNORE-RECTJMP ;DO NOTHING IF BOTH RECT | |
| .WORD A-RECTJMP | |
| .WORD B-RECTJMP | |
| .WORD AB-RECTJMP | |
| ; | |
| ; ONLY REGION A IS NON RECTANGULAR. UPDATE IT AND USE IT AS THE MASK | |
| ; | |
| A LEA STATEA(A6),A1 | |
| JSRSEEK JSR SEEKRGN | |
| MOVE.L SCANBUF(A1),MASKBUF(A6) | |
| IGNORE RTS | |
| ; | |
| ; ONLY REGION B IS NON RECTANGULAR. UPDATE IT AND USE IT AS THE MASK | |
| ; | |
| B LEA STATEB(A6),A1 | |
| BRA.S JSRSEEK | |
| ; | |
| ; REGIONS A AND B ARE NON-RECTANGULAR. UPDATE EACH, | |
| ; THEN FORM INTERSECTION IN THE MASK BUFFER. | |
| ; | |
| AB LEA STATEA(A6),A1 | |
| JSR SEEKRGN | |
| LEA STATEB(A6),A1 | |
| JSR SEEKRGN | |
| MOVE.L STATEA+SCANBUF(A6),A0 | |
| MOVE.L STATEB+SCANBUF(A6),A1 | |
| MOVE.L MASKBUF(A6),A2 | |
| MOVE BUFSIZE(A6),D1 | |
| ABLOOP MOVE.L (A0)+,D0 | |
| AND.L (A1)+,D0 | |
| MOVE.L D0,(A2)+ | |
| DBRA D1,ABLOOP | |
| RTS | |
| .PROC INITOVAL,4 | |
| ;------------------------------------------------------------ | |
| ; | |
| ; 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),RIGHTEDGE(A1) ;RIGHTEDGE.INT := DSTRECT.RIGHT | |
| CLR.W RIGHTEDGE+2(A1) ;RIGHTEDGE.FRACT := 0 | |
| MOVE.W LEFT(A0),LEFTEDGE(A1) ;LEFTEDGE.INT := DSTRECT.LEFT | |
| CLR.W LEFTEDGE+2(A1) ;LEFTEDGE.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,LEFTEDGE(A1) ;ADD OVALWD/2 TO LEFTEDGE | |
| SUB.L D0,RIGHTEDGE(A1) ;SUBTRACT OVALWD/2 FROM LEFTEDGE | |
| MOVE.L #$00008000,D0 ;GET FIXED POINT 1/2 | |
| MOVE.L D0,ONEHALF(A1) ;SAVE IN OVAL STATE RECORD | |
| ADD.L D0,RIGHTEDGE(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 | |
| .PROC BUMPOVAL,2 | |
| ;------------------------------------------------------------ | |
| ; | |
| ; 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: LEFTEDGE | |
| ; A1: RIGHTEDGE | |
| ; A2: #$00008000 | |
| ; A3: modified oval ptr | |
| ; | |
| ;----------------------------------------------- | |
| ; | |
| ; WHILE SQUARE < RSQYSQ DO MAKE OVAL BIGGER | |
| ; | |
| MORE1 ADD.L A2,A1 ;RIGHTEDGE := RIGHTEDGE + 1/2 | |
| SUB.L A2,A0 ;LEFTEDGE := LEFTEDGE - 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 ;RIGHTEDGE := RIGHTEDGE - 1/2 | |
| ADD.L A2,A0 ;LEFTEDGE := LEFTEDGE + 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 | |
| .END |