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 |