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

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 09:52:23 +08:00

1155 lines
35 KiB
Plaintext

;
; File: DrawArc.m.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: © 1988-1990 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <3> 10/10/90 JL Change FixRatio to MFixRatio to avoid conflict with Traps.a
; <2> 7/20/90 gbm Move stackframe definition inside procs, to avoid global symbol
; collisions
; <1.1> 11/11/88 CCH Fixed Header.
; <1.0> 11/9/88 CCH Adding to EASE.
; <1.2> 10/12/88 CCH Changed Òm.GrafType.aÓ to ÒGrafType.m.aÓ.
; <1.1> 5/18/88 MSH Changed inclides to use m.GRAPHTYPES to work under EASE.
; <1.0> 2/11/88 BBM Adding file for the first time into EASEÉ
;
; To Do:
;
;EASE$$$ READ ONLY COPY of file ÒDRAWARC.m.aÓ
; 1.1 CCH 11/11/1988 Fixed Header.
; 1.0 CCH 11/ 9/1988 Adding to EASE.
; OLD REVISIONS BELOW
; 1.2 CCH 10/12/1988 Changed Òm.GrafType.aÓ to ÒGrafType.m.aÓ.
; 1.1 MSH 5/18/88 Changed inclides to use m.GRAPHTYPES to work under EASE.
; 1.0 BBM 2/11/88 Adding file for the first time into EASEÉ
; END EASE MODIFICATION HISTORY
BLANKS ON
STRING ASIS
INCLUDE 'GRAFTYPES.m.a'
;-----------------------------------------------------------
;
; --> DRAWARC.TEXT
;
; Routine to draw solid or hollow Ovals, RoundRects or Arcs.
;
DrawArc PROC EXPORT
IMPORT InitOval,BumpOval,SlopeFromAngle
IMPORT RSect,ShieldCursor,ShowCursor,TrimRect
IMPORT InitRgn,SeekRgn,PatExpand,ColorMap
IMPORT XorSlab,DrawSlab,SlabMode,FastSlabMode,MaskTab
;----------------------------------------------------------------
;
; PROCEDURE DrawArc(dstRect: Rect;
; hollow: BOOLEAN;
; ovalWidth,ovalHeight,mode: INTEGER;
; pat: Pattern;
; startAngle,arcAngle: INTEGER);
;
;------------------------------------------------------
;
; 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
;------------------------------------------------
;
; 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 NEG ?
BMI.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 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),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)
_MFixRatio ;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
_MFixMul ;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
_MFixMul ;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 DC.W IGNORE-RECTJMP ;DO NOTHING IF BOTH RECT
DC.W A-RECTJMP
DC.W B-RECTJMP
DC.W 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
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
;
;------------------------------------------------------
;
; 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
;-----------------------------------------------------------
;
; 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
_MFixRatio ;CALC FIXED POINT HEIGHT/WIDTH
MOVE.L (SP),-(SP) ;DUPLICATE RESULT
PEA ODDNUM(A1) ;PUSH ADDR FOR RESULT
_MLongMul ;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
;
;
;------------------------------------------------------
;
; 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
;-------------------------------------------------------
;
; 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