.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