QuickDraw/PutOval.a

250 lines
9.9 KiB
Plaintext
Executable File

.INCLUDE GRAFTYPES.TEXT
;-----------------------------------------------------------
;
; --> PUTOVAL.TEXT
;
; Routine to add the inversion points for an oval to a region.
;
;------------------------------------------------------
;
; 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 PUTOVAL,6
.REF INITOVAL,BUMPOVAL,SETSIZE
;----------------------------------------------------------------
;
; PROCEDURE PutOval(dstRect: Rect; ovalWidth,ovalHeight: INTEGER;
; bufHandle: Handle; VAR index,size: INTEGER);
;
; Create region inversion points for an oval or roundRect.
;
;------------------------------------------------
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE .EQU 20 ;TOTAL SIZE OF PARAMETERS
DSTRECT .EQU PARAMSIZE+8-4 ;ADDR OF RECT
OVALWIDTH .EQU DSTRECT-2 ;INTEGER
OVALHEIGHT .EQU OVALWIDTH-2 ;INTEGER
BUFHANDLE .EQU OVALHEIGHT-4 ;LONG, HANDLE
INDEX .EQU BUFHANDLE-4 ;LONG, VAR
SIZE .EQU INDEX-4 ;LONG, VAR
;------------------------------------------------
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
OVAL .EQU -OVALSIZE ;OVAL RECORD
SKIPTOP .EQU OVAL-2 ;WORD
SKIPBOT .EQU SKIPTOP-2 ;WORD
OLDLEFT .EQU SKIPBOT-2 ;WORD
OLDRIGHT .EQU OLDLEFT-2 ;WORD
VARSIZE .EQU OLDRIGHT ;SIZE OF LOCAL VARIABLES
ENTRY LINK A6,#VARSIZE ;ALLOCATE LOCAL VARS
MOVEM.L D0-D7/A1-A5,-(SP) ;SAVE REGS
;---------------------------------------------------------------
;
; INIT AN OVAL RECORD
;
MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
LEA OVAL(A6),A1 ;POINT TO OVAL RECORD
MOVE OVALWIDTH(A6),D2 ;GET OVALWIDTH
MOVE OVALHEIGHT(A6),D1 ;GET OVALHEIGHT
JSR INITOVAL ;INIT OVAL RECORD
MOVE.W OVAL+LEFTEDGE(A6),OLDLEFT(A6)
MOVE.W OVAL+RIGHTEDGE(A6),OLDRIGHT(A6)
MOVE OVALHEIGHT(A6),D0 ;GET OVALHEIGHT
ASR #1,D0 ;CALC OVAL HEIGHT DIV 2
ADD OVAL+OVALTOP(A6),D0 ;ADD OVAL 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
;-----------------------------------------------------------------
;
; GET BUF HANDLE, DE-REFERENCE IT, AND ADD INDEX
;
MOVE.L BUFHANDLE(A6),A3 ;GET HANDLE
MOVE.L (A3),A3 ;DE-REFERENCE IT
MOVE.L A3,A2 ;REMEMBER BUFSTART FOR LATER
MOVE.L INDEX(A6),A0 ;GET ADDR OF INDEX
ADD (A0),A3 ;ADD INDEX TO BUFPTR
;----------------------------------------------------------
;
; BUFLIMIT := BUFSTART + BUFSIZE
;
MOVE.L A2,A1 ;GET BUFSTART
MOVE.L SIZE(A6),A0 ;GET ADDR OF SIZE
ADD (A0),A1 ;LEAVE BUFLIMIT IN A1
;------------------------------------------------
;
; PUT THE TOP EDGE
;
MOVE OVAL+OVALTOP(A6),D6 ;START VERT:= OVAL TOP
MOVE OLDLEFT(A6),D5
JSR PUTPT ;PUTPOINT (OLDLEFT,VERT)
MOVE OLDRIGHT(A6),D5
JSR PUTPT ;PUTPOINT (OLDRIGHT,VERT)
;-----------------------------------------------------
;
; FOR EACH VERTICAL, BUMP LEFTEDGE AND RIGHTEDGE.
; IF THEY DIFFER FROM OLDLEFT AND OLDRIGHT, PUT INVERSION
; POINTS FOR THE DIFFERENCES
;
NXTVERT CMP SKIPTOP(A6),D6 ;IS VERT < SKIPTOP ?
BLT.S YESBUMP ;YES, BUMP OVAL RECORD
CMP SKIPBOT(A6),D6 ;IS VERT >= SKIPBOT ?
BLT.S RIGHTOK ;NO, SKIP BUMPING
YESBUMP MOVEM.L D6/A1-A3,-(SP) ;PRESERVE REGS
LEA OVAL(A6),A3 ;POINT TO OVAL RECORD
MOVE D6,D0 ;GET CURRENT VERT
JSR BUMPOVAL ;BUMP IT TO NEXT SCANLINE
MOVEM.L (SP)+,D6/A1-A3 ;RESTORE REGS
; CHECK LEFT EDGE AND PUT TWO INVERSION POINTS IF IT HAS CHANGED
MOVE.W OVAL+LEFTEDGE(A6),D5 ;GET LEFTEDGE.INT
CMP OLDLEFT(A6),D5 ;SAME AS OLDLEFT ?
BEQ.S LEFTOK ;YES, CONTINUE
JSR PUTPT ;PUTPOINT (NEWLEFT,VERT)
MOVE OLDLEFT(A6),D5
JSR PUTPT ;PUTPOINT(OLDLEFT,VERT)
MOVE OVAL+LEFTEDGE(A6),OLDLEFT(A6) ;UPDATE OLDLEFT
; CHECK RIGHT EDGE AND PUT TWO INVERSION POINTS IF IT HAS CHANGED
LEFTOK MOVE.W OVAL+RIGHTEDGE(A6),D5 ;GET RIGHTEDGE.INT
CMP OLDRIGHT(A6),D5 ;SAME AS OLDRIGHT ?
BEQ.S RIGHTOK ;YES, CONTINUE
JSR PUTPT ;PUTPOINT (NEWRIGHT,VERT)
MOVE OLDRIGHT(A6),D5
JSR PUTPT ;PUTPOINT(OLDRIGHT,VERT)
MOVE OVAL+RIGHTEDGE(A6),OLDRIGHT(A6) ;UPDATE OLDRIGHT
RIGHTOK ADD #1,D6 ;BUMP CURRENT VERT
CMP OVAL+OVALBOT(A6),D6 ;DONE WITH THE OVAL ?
BLT NXTVERT ;LOOP FOR ALL VERTICALS
;------------------------------------------------
;
; PUT THE BOTTOM EDGE
;
MOVE OLDLEFT(A6),D5
JSR PUTPT ;PUTPOINT (OLDLEFT,VERT)
MOVE OLDRIGHT(A6),D5
JSR PUTPT ;PUTPOINT (OLDRIGHT,VERT)
;----------------------------------------------------
;
; UPDATE INDEX TO REFLECT POINTS ADDED, CLEAN UP STACK AND GO HOME.
;
SUB.L A2,A3 ;CALC BUFPTR-BUFSTART
MOVE.L INDEX(A6),A0 ;GET VAR ADDR OF INDEX
MOVE A3,(A0) ;UPDATE INDEX
MOVEM.L (SP)+,D0-D7/A1-A5 ;RESTORE REGISTERS
UNLINK PARAMSIZE,'PUTOVAL '
;-----------------------------------------------------------------------
;
; Local routine to Append a point to the end of the saved points buffer,
; extending buffer if necessary. If pt is a duplicate of the last pt,
; cancel both instead.
;
; INPUTS: D5: HORIZ COORD
; D6: VERT COORD
; A1: BUFLIMIT GETS EXPANDED AND RELOCATED
; A2: BUFSTART GETS RELOCATED
; A3: BUFPTR GETS BUMPED AND RELOCATED
;
; ALTERS: A1,A2,A3, VAR SIZE
;
PUTPT CMP.L A1,A3 ;IS BUFPTR < BUFLIMIT ?
BLT.S SIZEOK ;YES, CONTINUE
;---------------------------------------------------------------------
;
; BUFFER IS FULL, CALL STORAGE ALLOCATOR TO MAKE ROOM FOR 256 MORE POINTS.
; UPDATE BUFPTR, BUFSTART, BUFLIMIT, AND BUFSIZE AFTER RELOCATION.
;
SUB.L A2,A3 ;MAKE BUFPTR RELATIVE
SUB.L A2,A1 ;MAKE BUFLIMIT RELATIVE
ADD #1024,A1 ;MAKE BUFLIMIT BIGGER
MOVEM.L D0-D7/A0-A3,-(SP) ;SAVE REGS
MOVE.L SIZE(A6),A0 ;GET ADDR OF SIZE
MOVE A1,(A0) ;UPDATE BUFFER SIZE
MOVE.L BUFHANDLE(A6),-(SP) ;PUSH HANDLE PARAM
MOVE A1,-(SP) ;PUSH NEW SIZE
JSR SETSIZE ;MAKE THE BUFFER BIGGER
MOVEM.L (SP)+,D0-D7/A0-A3 ;RESTORE REGS
MOVE.L BUFHANDLE(A6),A2 ;GET BUF HANDLE
MOVE.L (A2),A2 ;GET NEW BUFSTART
ADD.L A2,A3 ;MAKE BUFPTR UN-RELATIVE
ADD.L A2,A1 ;MAKE BUFLIMIT UN-RELATIVE
;-------------------------------------------------------------------
;
; ADD NEW POINT TO THE SAVE BUFFER UNLESS IT MATCHED THE PREVIOUS PT.
; DELETE DUPLICATE POINTS SINCE THEY WILL CANCEL EACH OTHER ANYWAY.
;
SIZEOK CMP.L A2,A3 ;IS BUFPTR=STARTPTR ?
BEQ.S APPEND ;BR IF FIRST POINT
CMP -4+H(A3),D5 ;IS PREVIOUS HORIZ SAME ?
BNE.S APPEND ;NO, APPEND NEW POINT
CMP -4+V(A3),D6 ;YES, IS PREVIOUS VERT SAME TOO ?
BNE.S APPEND ;NO, APPEND NEW POINT
SUB #4,A3 ;YES, DELETE OLD INSTEAD
RTS
APPEND MOVE D6,(A3)+ ;PUT VERT COORD
MOVE D5,(A3)+ ;PUT HORIZ COORD
RTS
.END