.INCLUDE GRAFTYPES.TEXT ;----------------------------------------------------------- ; ; --> PUTLINE.TEXT ; ; Decompose a line segment into a list of inversion points. ; ; .PROC PUTLINE,5 .REF SETSIZE ;------------------------------------------------------------------ ; ; PROCEDURE PutLine(pt1,pt2: Point; dst: Handle; VAR index,bufMax: INTEGER); ; ; INVERSION POINTS FOR A LINE SEGMENT ; ; SP OFFSETS OF PARAMETERS: ; PARAMSIZE .EQU 20 ;TOTAL SIZE OF PARAMETERS PT1 .EQU PARAMSIZE+4-4 ;LONG, POINT (VALUE) PT2 .EQU PT1-4 ;LONG, POINT (VALUE) BUF .EQU PT2-4 ;LONG, HANDLE INDEX .EQU BUF-4 ;LONG, (VAR) BUFMAX .EQU INDEX-4 ;LONG, (VAR) MOVEM.L D3-D7/A2-A4,-(SP) ;SAVE REGS, 8*4 ==> 32 ;----------------------------------------------------- ; ; IF LINE IS VERTICAL, IGNORE IT. ; MOVE PT1+H+32(SP),D2 ;GET 1ST POINT'S HORIZ MOVE PT2+H+32(SP),D4 ;GET 2ND POINT'S HORIZ CMP D2,D4 ;IS THIS A VERTICAL LINE ? BEQ GOHOME ;YES, IGNORE IT ;------------------------------------------------------ ; ; CALC BYTESNEEDED = 8 * ( Min(ABS(dh),ABS(dv)) + 1) ; MOVE D2,D0 ;GET H1 SUB D4,D0 ;SUBTRACT H2 BPL.S DHPOS ;BR IF DH POS NEG D0 ;ELSE TAKE ABSOLUTE VALUE DHPOS MOVE PT1+V+32(SP),D1 ;GET V1 SUB PT2+V+32(SP),D1 ;SUBTRACT V2 BPL.S DVPOS ;BR IF DV POS NEG D1 ;ELSE TAKE ABSOLUTE VALUE DVPOS CMP D1,D0 ;IS DH <= DV ? BLE.S DHLESS ;YES, CONTINUE MOVE D1,D0 ;NO, PUT MIN(DH,DV) INTO D0 DHLESS ADD #1,D0 ;CALC MIN(DH,DV)+1 LSL #3,D0 ;TIMES EIGHT FOR BYTESNEEDED MOVE.L BUF+32(SP),A3 ;GET DSTHANDLE MOVE.L INDEX+32(SP),A4 ;POINT TO CURRENT INDEX ;----------------------------------------------------- ; ; GROW POINT BUFFER AS NECESSARY TO HOLD BYTESNEEDED ; ADD (A4),D0 ;NEWSIZE := INDEX + BYTESNEEDED MOVE.L BUFMAX+32(SP),A0 ;POINT TO BUFMAX CMP (A0),D0 ;DO WE HAVE TO GROW DSTBUF ? BLE.S NOGROW ;NO, CONTINUE ADD #512,D0 ;GROW IN CHUNKS MOVE D0,(A0) ;UPDATE NEW BUFMAX MOVE.L A3,-(SP) ;PUSH DSTBUF HANDLE MOVE D0,-(SP) ;PUSH NEW BUFMAX JSR SETSIZE ;MAKE THE BUFFER BIGGER MOVE PT1+H+32(SP),D2 ;RESTORE CLOBBERED REG NOGROW MOVE.L (A3),A3 ;DE-REFERENCE DSTHANDLE ADD (A4),A3 ;ADD INDEX TO BUFPTR ;----------------------------------------------------- ; ; IF LINE IS HORIZONTAL, PUT ITS TWO ENDPOINTS ; MOVE PT1+V+32(SP),D1 ;GET 1ST POINT'S VERT MOVE PT2+V+32(SP),D3 ;GET 2ND POINT'S VERT CMP D1,D3 ;IS THIS A HORIZONTAL LINE ? BNE.S SLANTED ;NO, BRANCH MOVE D1,(A3)+ ;PUT V1 VERT COORD MOVE D2,(A3)+ ;PUT H1 HORIZ COORD MOVE D3,(A3)+ ;PUT V2 VERT COORD MOVE D4,(A3)+ ;PUT H2 HORIZ COORD BRA.S DONE ;UPDATE INDEX AND QUIT ;------------------------------------------------------ ; ; LINE IS SLANTED. DIVIDE IT INTO HORIZONTAL SLABS ; AND PUT THE TWO ENDPOINTS OF EACH SLAB. ; ; START BY SORTING POINTS VERTICALLY. ; SLANTED BGT.S NOSWAP ;SKIP IF ALREADY IN ORDER EXG D1,D3 ;SORT POINTS BY VERTICAL EXG D2,D4 ;SWAP HORIZ TO MATCH NOSWAP MOVE D1,D6 ;INIT V TO TOPV ;------------------------------------------------------------ ; ; CALCULATE FIXED POINT SLOPE = FixRatio(dh,dv); ; CLR.L -(SP) ;MAKE ROOM FOR FCN RESULT MOVE D4,-(SP) ;PUSH BOTTOM HORIZ SUB D2,(SP) ;CALC DH MOVE D3,-(SP) ;PUSH BOTTOM VERT SUB D1,(SP) ;CALC DV _FixRatio ;CALC FIXED POINT SLOPE MOVE.L (SP)+,D7 ;POP RESULT ;--------------------------------------------------------- ; ; SET UP STARTING HORIZ FIXED POINT. ; MOVE.W D2,D1 SWAP D1 ;HORIZ.INT := TOP HORIZ MOVE.W #$8000,D1 ;HORIZ.FRACT := 1/2 ; ; ADJUST HORIZ DEPENDING ON SIGN AND MAGNITUDE OF SLOPE ; MOVE.L D7,D0 ;COPY SLOPE ASR.L #1,D0 ;CALC SLOPE/2 ADD.L D0,D1 ;HORIZ := HORIZ + SLOPE/2 MOVE.L #$00010000,D0 TST.L D7 ;IS SLOPE NEG ? BMI.S NEGSLOPE ;YES, CONTINUE CMP.L D0,D7 ;IS SLOPE < ONE ? BGE.S SLOPEOK ;NO, CONTINUE ADD.L D7,D1 ;ADD SLOPE TO LEFTEDGE BRA.S SLOPEOK ;CONTINUE NEGSLOPE CMP.L #$FFFF0000,D7 ;IS SLOPE > -ONE ? BGE.S SLOPEOK ;YES, CONTINUE ADD.L D0,D1 ;YES, HORIZ := HORIZ + 1 SLOPEOK ;------------------------------------------------------ ; ; FOR VERT:=TOPV TO BOTV-1 ADD SLOPE TO HORIZ AND PUT SLABS ; MOVE D2,D5 ;H:=TOPH LOOP SWAP D1 ;GET HORIZ.INT INTO D1 LOWER CMP D1,D5 ;HAS HORIZ.INT CHANGED ? BEQ.S NOCHNG ;NO, CONTINUE MOVE D6,(A3)+ ;YES, PUT VERT COORD MOVE D5,(A3)+ ;PUT OLD HORIZ COORD MOVE.W D1,D5 ;OLDH := HORIZ.INT MOVE D6,(A3)+ ;PUT VERT COORD MOVE D5,(A3)+ ;PUT NEW HORIZ COORD NOCHNG SWAP D1 ;PUTBACK HORIZ.INT INTO D1 UPPER ADD #1,D6 ;VERT:=VERT+1 ADD.L D7,D1 ;ADD SLOPE TO HORIZ CMP D6,D3 ;IS VERT AT BOTTOM VERT YET ? BNE LOOP ;NO, GO FOR MORE ;------------------------------------------------- ; ; FINISH UP LAST SLAB ; CMP D4,D5 ;IS OLDH = BOTTOM H ? BEQ.S DONE ;YES, CONTINUE MOVE D6,(A3)+ ;NO, PUT VERT COORD MOVE D5,(A3)+ ;PUT HORIZ COORD MOVE D6,(A3)+ ;PUT VERT COORD MOVE D4,(A3)+ ;PUT BOTTOM H COORD ;--------------------------------------------------- ; ; UPDATE INDEX TO REFLECT POINTS ADDED. ; DONE MOVE.L BUF+32(SP),A0 ;GET DSTHANDLE SUB.L (A0),A3 ;INDEX := BUFPTR-BUFSTART MOVE A3,(A4) ;UPDATE INDEX GOHOME MOVEM.L (SP)+,D3-D7/A2-A4 ;RESTORE REGS MOVE.L (SP)+,A0 ADD.W #PARAMSIZE,A7 JMP (A0) .END