.INCLUDE GRAFTYPES.TEXT ;----------------------------------------------------------------- ; ; --> DRAWLINE.TEXT ; .PROC DrawLine .REF RgnBlt,RSect,ShieldCursor,ShowCursor,TrimRect .REF InitRgn,SeekRgn,PatExpand,ColorMap .REF XorSlab,DrawSlab,SlabMode,FastSlabMode,MaskTab ;---------------------------------------------------------------- ; ; PROCEDURE DRAWLINE(P1,P2: POINT); ; ; DRAWS A LINE CLIPPED TO CURRENT PORT'S CLIPRGN AND VISRGN ; ; P1 AND P2 ARE GIVEN IN LOCAL COORDINATES OF THEPORT. ; ;------------------------------------------------ ; ; A6 OFFSETS OF PARAMETERS AFTER LINK: ; PARAMSIZE .EQU 8 ;SIZE OF PARAMETERS P1 .EQU PARAMSIZE+8-4 ;POINT P2 .EQU P1-4 ;POINT ;------------------------------------------------- ; ; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK: ; EXPAT .EQU -64 ;16 LONGS LINERECT .EQU EXPAT-8 ;RECT MINRECT .EQU LINERECT-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 VERT .EQU BUFSIZE-2 ;WORD MODECASE .EQU VERT-4 ;LONG PAT .EQU MODECASE-4 ;LONG, ADDR OF PAT LEFTEDGE .EQU PAT-4 ;LONG, FIXED POINT RIGHTEDGE .EQU LEFTEDGE-4 ;LONG, FIXED POINT SLOPE .EQU RIGHTEDGE-4 ;LONG, FIXED POINT DSTLEFT .EQU SLOPE-4 ;LONG SAVEA5 .EQU DSTLEFT-4 ;LONG PORT .EQU SAVEA5-4 ;LONG MODE .EQU PORT-2 ;WORD FASTFLAG .EQU MODE-2 ;BYTE BIGRGN .EQU FASTFLAG-4 ;LONG, RgnHandle VARSIZE .EQU BIGRGN ;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 WIDEOPEN(A0),BIGRGN(A6) ;STASH WIDEOPEN IN BIGRGN MOVE.L THEPORT(A0),A3 ;POINT TO CURRENT GRAFPORT TST PNVIS(A3) ;IS PNVIS NEGATIVE ? BLT GOHOME ;YES, QUIT MOVE.L A3,PORT(A6) ;SAVE PORT FOR LATER ;------------------------------------------------------- ; ; QUIT IF PEN MODE NOT IN 8..15 ; MOVEQ #-8,D0 AND PNMODE(A3),D0 ;GET ALL BUT 3 BITS OF PEN MODE CMP #8,D0 ;IS PEN MODE 8..15 ? BNE GOHOME ;NO, QUIT ;------------------------------------------------------- ; ; Check for color filtering. Alter mode and pattern accordingly. ; MOVE PNMODE(A3),-(SP) ;PUSH PEN MODE PEA PNPAT(A3) ;PUSH ADDR OF PEN PATTERN TST COLRBIT(A3) ;IS COLORBIT = 0 ? BEQ.S NOCOLOR ;YES, DON'T MAP JSR COLORMAP ;CHECK AGAINST THECOLOR, THEFILTER NOCOLOR MOVE.L (SP)+,PAT(A6) ;GET (ALTERED) PATTERN MOVE (SP)+,MODE(A6) ;AND (ALTERED) MODE ;--------------------------------------------------------- ; ; GET CLIPRGN AND VISRGN HANDLES AND DE-REFERENCE THEM ; MOVE.L A3,A5 ;PUT GRAFPTR IN A5 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 ;------------------------------------------------------------- ; ; SET UP LINERECT, THE RECTANGLE BOUNDING THE LINE AND PEN ; MOVEM.W P2(A6),D1/D2/D3/D4 ;GET D1=V1, D2=H1, D3=V2, D4=H2 CMP D3,D1 ;IS V1 > V2 ? BLE.S VOK2 ;NO, CONTINUE EXG D1,D3 ;YES, SWAP VERT VOK2 CMP D4,D2 ;IS H1 > H2 ? BLE.S HOK2 ;NO, CONTINUE EXG D2,D4 ;NO SWAP HORIZ HOK2 ADD PNSIZE+H(A5),D4 ;ADD PEN WIDTH TO RIGHT ADD PNSIZE+V(A5),D3 ;ADD PEN HEIGHT TO BOTTOM MOVEM.W D1/D2/D3/D4,LINERECT(A6) ;STORE TOP, LEFT, BOTTOM, RIGHT ;----------------------------------------------------------------------- ; ; CALC MINRECT, THE INTERSECTION OF LINERECT, BITMAP BOUNDS, ; CLIPRGN BBOX, AND VISRGN BBOX. QUIT IF NO INTERSECTION. ; PEA LINERECT(A6) ;PUSH LINE RECT 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 ; ; 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 ;GET BACK THEPORT ; ; 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 DONE ;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) ;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 DONE ;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 ; ; GET THE TWO LINE ENDPOINTS INTO REGISTERS ; AND CHECK FOR HORIZONTAL OR VERTICAL LINE ; MOVEM.W P2(A6),D1/D2/D3/D4 ;GET D1=V2, D2=H2, D3=V1, D4=H1 CMP D2,D4 ;H1=H2 ? BEQ.S HVLINE ;YES, DO VERTICAL LINE CMP D1,D3 ;NO, IS V2 > V1 ? BGT.S SLANTED ;YES, DRAW SLANTED LINE BLT.S VSWAP ;SWAP POINTS AND DRAW SLANTED ;ELSE V1=V2, DO HORIZONTAL ;----------------------------------------------------------- ; ; LINE IS EITHER HORIZONTAL OR VERTICAL. ; CHECK FOR ONE DOT LINE, BLACK OR WHITE PATTERN, AND ; CLIPRGN AND VISRGN BOTH RECTANGULAR. IF SO, OPTIMIZE FAST LINES. ; HVLINE TST.B FASTFLAG(A6) ;RECT CLIPPED AND BLACK ? BEQ.S NOTFAST ;NO, CONTINUE CMP.L #$00010001,PNSIZE(A5) ;IS PEN 1 BY 1 ? BEQ FASTLINE ;YES, DO IT FAST ! ;-------------------------------------------------------------------- ; ; NOT FASTLINE. PUSH PARAMS AND CALL RGNBLT FOR HORIZ OR VERT LINE. ; NOTFAST PEA PORTBITS(A5) ;PUSH SRCBITS = DSTBITS MOVE.L (SP),-(SP) ;PUSH DSTBITS PEA MINRECT(A6) ;PUSH SRCRECT = DSTRECT MOVE.L (SP),-(SP) ;PUSH DSTRECT MOVE PNMODE(A5),-(SP) ;PUSH MODE PEA PNPAT(A5) ;PUSH PATTERN MOVE.L CLIPRGN(A5),-(SP) ;PUSH CLIPRGN HANDLE MOVE.L VISRGN(A5),-(SP) ;PUSH VISRGN HANDLE MOVE.L BIGRGN(A6),-(SP) ;PUSH SAVED WIDEOPEN MOVE.L SAVEA5(A6),A5 ;GET GLOBAL PTR JSR RGNBLT ;DRAW THE HORIZ OR VERT LINE BRA DONE ;RESTORE CURSOR AND QUIT ;------------------------------------------------------------- ; ; THE LINE IS SLANTED. SORT VERTICALLY ; AND DRAW TOP TO BOTTOM AS HORIZONTAL SLABS. ; VSWAP EXG D1,D3 ;SORT POINTS BY VERTICAL EXG D2,D4 ;SWAP HORIZ TO MATCH SLANTED MOVE D3,D0 ;COPY LINE BOTTOM ADD PNSIZE+V(A5),D0 ;ADD PEN HEIGHT CMP RGNBBOX+TOP(A2),D0 ;IS RESULT <= CLIP TOP ? BLE DONE ;YES, RESTORE CURSOR AND QUIT CMP RGNBBOX+BOTTOM(A2),D1 ;IS TOP >= CLIP BOTTOM ? BGE DONE ;YES, RESTORE CURSOR AND QUIT ;------------------------------------------------------------- ; ; SET UP INITIAL FIXED POINT LEFTEDGE AND RIGHTEDGE ; AND CHECK FOR ZERO PENSIZE. ; MOVE.W D2,LEFTEDGE(A6) ;LEFTEDGE.INT := TOP HORIZ MOVE.W #$8000,LEFTEDGE+2(A6) ;LEFTEDGE.FRACT := 1/2 MOVE.L LEFTEDGE(A6),RIGHTEDGE(A6) ;RIGHTEDGE:=LEFTEDGE MOVE PNSIZE+H(A5),D0 ;GET PEN WIDTH BLE DONE ;QUIT IF PENWIDTH <= 0 ADD.W D0,RIGHTEDGE(A6) ;ADD TO RIGHTEDGE.INT MOVE PNSIZE+V(A5),D6 ;GET PEN HEIGHT BLE DONE ;QUIT IF PEN HEIGHT <= 0 ;---------------------------------------------------- ; ; CALC 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 DH/DV MOVE.L (SP)+,D7 ;POP RESULT MOVE.L D7,SLOPE(A6) ;SAVE FOR LATER ; ; CALC adjust := pen height * slope ; CLR.L -(SP) ;PUSH ROOM FOR FCN RESULT CLR.W -(SP) ;PUSH LOWORD = 0 MOVE.W D6,-(SP) ;PUSH HIWORD = PEN HEIGHT MOVE.L D7,-(SP) ;PUSH SLOPE _FixMul ;CALC FixMul(pnSize.v,slope) MOVE.L (SP)+,D6 ;POP ANSWER INTO D6 ; ; ADJUST LEFTEDGE AND RIGHTEDGE DEPENDING ON SIGN AND MAGNITUDE OF SLOPE ; MOVE.L D7,D0 ;COPY SLOPE ASR.L #1,D0 ;CALC SLOPE/2 ADD.L D0,LEFTEDGE(A6) ;ADD SLOPE/2 TO LEFT EDGE ADD.L D0,RIGHTEDGE(A6) ;ADD SLOPE/2 TO RIGHT EDGE TST.L D7 ;IS SLOPE NEGATIVE ? BMI.S NEGSLOPE ;YES, CONTINUE SUB.L D6,LEFTEDGE(A6) ;SUBTRACT ADJUST FROM LEFTEDGE CMP.L #$00010000,D7 ;IS SLOPE < ONE ? BGE.S LESSV1 ;NO, BRANCH MOREV1 ADD.L D7,LEFTEDGE(A6) ;ADD SLOPE TO LEFTEDGE BRA.S SLOPEOK ;CONTINUE LESSV1 SUB.W #1,RIGHTEDGE(A6) ;RIGHTEDGE := RIGHTEDGE - 1 BRA.S SLOPEOK ;CONTINUE ;---------------------------------------------------- ; ; SLOPE IS NEGATIVE ; NEGSLOPE SUB.L D6,RIGHTEDGE(A6) ;SUBTRACT ADJUST FROM RIGHTEDGE CMP.L #$FFFF0000,D7 ;IS SLOPE > -ONE ? BLT.S LESSV2 ;NO, CONTINUE MOREV2 ADD.L D7,RIGHTEDGE(A6) ;ADD SLOPE TO RIGHTEDGE BRA.S SLOPEOK LESSV2 ADD.W #1,LEFTEDGE(A6) ;LEFTEDGE := LEFTEDGE + 1 SLOPEOK MOVEM.W MINRECT(A6),D1/D2/D3/D4 ;GET MINRECT TOP,LEFT,BOTTOM,RIGHT ; ; ADJUST LEFTEDGE AND RIGHTEDGE IF LINE WAS CLIPPED VERTICALLY ; CMP LINERECT+TOP(A6),D1 ;DID TOP GET CLIPPED ? BEQ.S TOPOK ;NO, CONTINUE MOVE D1,D0 SUB LINERECT+TOP(A6),D0 ;CALC DISCARD AMMOUNT MOVE.L D7,D5 ;GET 32 BIT SLOPE SWAP D5 ;GET HI WORD OF SLOPE MULS D0,D5 ;MULT TIMES DISCARD SWAP D5 ;PUT RESULT IN HI WORD CLR.W D5 ;CLEAR LO WORD MOVE.L D7,D6 ;GET NEW COPY OF SLOPE MULU D0,D6 ;MULT LO WORD TIMES DISCARD ADD.L D6,D5 ;CALC 32BIT SLOPE*DISCARD ADD.L D5,LEFTEDGE(A6) ;BUMP LEFTEDGE TO NEW TOP ADD.L D5,RIGHTEDGE(A6) ;BUMP RIGHTEDGE TO NEW TOP TOPOK ; ; 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 HARMLESS STATE MOVE #32767,STATEA+NEXTV(A6) ;IN CASE RECTANGULAR 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 HARMLESS STATE MOVE #32767,STATEB+NEXTV(A6) ;IN CASE RECTANGULAR 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 BOTH 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 SUB PORTBITS+BOUNDS+TOP(A5),D1 ;CONVERT MINV 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 LEFTEDGE,RIGHTEDGE,MINRECT RELATIVE TO BUFFER LEFT ; MOVE BUFLEFT(A6),D1 SUB.W D1,LEFTEDGE(A6) ;ADJUST LEFTEDGE.INT SUB.W D1,RIGHTEDGE(A6) ;ADJUST RIGHTEDGE.INT SUB D1,MINRECT+LEFT(A6) SUB D1,MINRECT+RIGHT(A6) ;------------------------------------------------------------ ; ; TAKE FAST OR SLOW OUTER CONTROL LOOP FOR SLANTED LINES: ; TST.B fastFlag(A6) ;ARE WE RECT CLIPPED BLACK ? BEQ.S GOSLOW ;NO, CONTINUE MOVE MODE(A6),D2 ;GET (ALTERED) PEN MODE JSR FastSlabMode ;Get fast case jump in A4 LEA MaskTab,A0 ;point to mask table LEA MINRECT(A6),A3 ;POINT TO MINRECT MOVE.L SLOPE(A6),D7 ;GET FIXED POINT SLOPE MOVE PORTBITS+ROWBYTES(A5),D6 ;GET DST ROWBYTES MOVE.L DSTLEFT(A6),A5 ;GET DSTLEFT MOVE MINRECT+BOTTOM(A6),D5 ;GET MINRECT BOTTOM SUB MINRECT+TOP(A6),D5 ;CALC HEIGHT SUB #1,D5 ;MINUS 1 FOR DBRA COUNT NXTFAST MOVE.W LEFTEDGE(A6),D1 ;GET LEFTEDGE.INT MOVE.W RIGHTEDGE(A6),D2 ;GET RIGHTEDGE.INT MOVE.L A5,A1 ;INIT DSTPTR TO LEFT JSR DrawSlab ;DRAW ONE SLAB IN PENMODE ADD D6,A5 ;BUMP DST TO NEXT ROW ADD.L D7,LEFTEDGE(A6) ;ADD SLOPE TO LEFT EDGE ADD.L D7,RIGHTEDGE(A6) ;ADD SLOPE TO RIGHT EDGE DBRA D5,NXTFAST ;LOOP FOR ALL SCANLINES BRA DONE ;AND QUIT GOSLOW MOVE MODE(A6),D2 ;GET (ALTERED) PEN MODE JSR SlabMode ;GET DrawSlab CASE JUMP IN A4 ;------------------------------------------------------------------ ; ; EXPAND 8 BYTE PATTERN TO 16 LONGS AND INIT PATTERN SELECTOR ; CLR.L D7 ;SAY NOT INVERTED MOVE MODE(A6),D2 ;GET (ALTERED) PEN 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 BYTES TO 16 LONGS MOVE.L PORT(A6),A5 ;RESTORE GRAFPTR IN A5 MOVEQ #$F,D7 ;TREAT COORD MOD 16 AND MINRECT+TOP(A6),D7 ;GET TOP VERT LOCAL COORD LSL #2,D7 ;QUAD FOR LONG INDEX ; ; FOR EACH SLAB, MAKE MASK BUFFER CURRENT AND DRAW SLAB ; LEA MINRECT(A6),A3 ;POINT TO MINRECT MOVE PORTBITS+ROWBYTES(A5),D5 ;GET DST ROWBYTES MOVE.L DSTLEFT(A6),A5 ;GET DSTLEFT MOVE.L SLOPE(A6),D4 ;GET FIXED POINT SLOPE MOVE MINRECT+TOP(A6),VERT(A6) ;INIT CURRENT VERT:=MINV NXTMASK BSR.S SEEKMASK ;MAKE MASK BUFFER CURRENT MOVE.L EXPAT(A6,D7),D6 ;GET PATTERN DATA MOVE.W LEFTEDGE(A6),D1 ;GET LEFTEDGE.INT MOVE.W RIGHTEDGE(A6),D2 ;GET RIGHTEDGE.INT LEA MaskTab,A0 ;point to mask table MOVE.L A5,A1 ;INIT DSTPTR TO LEFT MOVE.L MASKBUF(A6),A2 ;INIT MASKPTR TO LEFT JSR DrawSlab ;DRAW ONE SLAB IN PENMODE ADD #4,D7 ;BUMP PATTERN SELECTOR AND #$3F,D7 ;MOD 64 FOR 16 LONG REPEAT ADD D5,A5 ;BUMP DST TO NEXT ROW ADD.L D4,LEFTEDGE(A6) ;ADD SLOPE TO LEFT EDGE ADD.L D4,RIGHTEDGE(A6) ;ADD SLOPE TO RIGHT EDGE ADD #1,VERT(A6) ;BUMP CURRENT VERT MOVE VERT(A6),D0 ;GET CURRENT VERT CMP MINRECT+BOTTOM(A6),D0 ;ARE WE AT BOTTOM YET ? BLT NXTMASK ;NO, LOOP ALL SCAN LINES 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,'DRAWLINE' ;----------------------------------------------------------------------------- ; ; LOCAL ROUTINE TO UPDATE THE MASK BUFFER ; BASED ON WHICH REGIONS ARE RECTANGULAR ; SEEKMASK MOVE VERT(A6),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 ;------------------------------------------------------- ; ; SET UP AND DRAW A FAST HORIZONTAL OR VERTICAL LINE. ; FASTLINE CMP D1,D3 ;IS LINE HORIZONTAL ? BNE VLINE ;NO, MUST BE VERTICAL BSR HVSETUP ;GET DSTPTR,ROWBYTES,HGLOBAL MOVE 32(A0,D0),D6 ;GET LEFTMASK IN D6 MOVE MINRECT+RIGHT(A6),D2 ;GET MINRECT RIGHT SUB PORTBITS+BOUNDS+LEFT(A5),D2 ;CONVERT TO GLOBAL MOVE D2,D0 ;MAKE A COPY OF RIGHT AND #$F,D0 ;TREAT RIGHT MOD 16 ADD D0,D0 ;DOUBLE FOR TABLE MOVE 0(A0,D0),D3 ;GET RIGHTMASK IN D3 LSR #4,D2 ;CONVERT DOTS TO WORDS CMP #1,MODE(A6) ;WHICH MODIFIED MODE ? BLT.S HSET ;BR IF BLACK BEQ.S HTOGL ;BR IF XOR ;ELSE WHITE ;------------------------------------------------------ ; ; DRAW A WHITE HORIZONTAL LINE ; NOT D6 ;MAKE NOT LEFTMASK NOT D3 ;MAKE NOT RIGHTMASK SUB D1,D2 ;CALC WORDCOUNT BEQ.S ENDCLR ;BR IF ALL IN ONE WORD AND D6,(A4)+ ;DO LEFT WORD WITH MASK CLR.L D6 ;FLUSH LEFTMASK FOR END SUB #1,D2 ;DEC WORD COUNT BEQ.S ENDCLR ;BR IF NO UNMASKED WORDS LSR #1,D2 ;HALVE WORDCOUNT FOR LONGCOUNT BCC.S CLRONE ;BR IF EVEN # WORDS LEFT MOVE D6,(A4)+ ;ELSE MAKE EVEN BY DOING A WORD SUB #1,D2 ;ADJUST LONGCOUNT BRA.S CLRMORE ;SEE IF ANY LONGS LEFT TO DO CLRTWO MOVE.L D6,(A4)+ ;FILL A LONG WITH BLACK CLRONE MOVE.L D6,(A4)+ ;FILL ANOTHER LONG SUB #2,D2 ;ANY UNMASKED LONGS LEFT ? CLRMORE BGT CLRTWO ;YES, AT LEAST TWO LONGS BEQ CLRONE ;YES, FINISH UP LAST LONG ENDCLR OR D3,D6 ;COMBINE LEFT AND RIGHT MASK AND D6,(A4) ;DRAW LINE BRA.S DONE ;RESTORE CURSOR AND QUIT ;-------------------------------------------------- ; ; DRAW AN XOR HORIZONTAL LINE ; HTOGL SUB D1,D2 ;CALC WORDCOUNT BEQ.S ENDTOGL ;BR IF ALL IN ONE WORD EOR D6,(A4)+ ;DO LEFT WORD WITH MASK MOVEQ #-1,D6 ;FLUSH LEFTMASK FOR END SUB #1,D2 ;DEC WORD COUNT BEQ.S ENDTOGL ;BR IF NO UNMASKED WORDS LSR #1,D2 ;HALVE WORDCOUNT FOR LONGCOUNT BCC.S TOGLONE ;BR IF EVEN # WORDS LEFT EOR D6,(A4)+ ;ELSE MAKE EVEN BY DOING A WORD SUB #1,D2 ;ADJUST LONGCOUNT BRA.S TOGLMORE ;SEE IF ANY LONGS LEFT TO DO TOGLTWO NOT.L (A4)+ ;INVERT A LONG TOGLONE NOT.L (A4)+ ;INVERT ANOTHER LONG SUB #2,D2 ;ANY UNMASKED LONGS LEFT ? TOGLMORE BGT TOGLTWO ;YES, AT LEAST TWO LONGS BEQ TOGLONE ;YES, FINISH UP LAST LONG ENDTOGL AND D3,D6 ;COMBINE LEFT AND RIGHT MASK EOR D6,(A4) ;DRAW LINE BRA.S DONE ;RESTORE CURSOR AND QUIT ;-------------------------------------------- ; ; DRAW A BLACK HORIZONTAL LINE ; HSET SUB D1,D2 ;CALC WORDCOUNT BEQ.S ENDSET ;BR IF ALL IN ONE WORD OR D6,(A4)+ ;DO LEFT WORD WITH MASK MOVEQ #-1,D6 ;FLUSH LEFTMASK FOR END SUB #1,D2 ;DEC WORD COUNT BEQ.S ENDSET ;BR IF NO UNMASKED WORDS LSR #1,D2 ;HALVE WORDCOUNT FOR LONGCOUNT BCC.S SETONE ;BR IF EVEN # WORDS LEFT MOVE D6,(A4)+ ;ELSE MAKE EVEN BY DOING A WORD SUB #1,D2 ;ADJUST LONGCOUNT BRA.S SETMORE ;SEE IF ANY LONGS LEFT TO DO SETTWO MOVE.L D6,(A4)+ ;FILL A LONG WITH BLACK SETONE MOVE.L D6,(A4)+ ;FILL ANOTHER LONG SUB #2,D2 ;ANY UNMASKED LONGS LEFT ? SETMORE BGT SETTWO ;YES, AT LEAST TWO LONGS BEQ SETONE ;YES, FINISH UP LAST LONG ENDSET AND D3,D6 ;COMBINE LEFT AND RIGHT MASK OR D6,(A4) ;DRAW LINE BRA.S DONE ;RESTORE CURSOR AND QUIT ;------------------------------------------------------- ; ; DRAW A VERTICAL LINE. ; VLINE BSR.S HVSETUP ;GET DSTPTR,ROWBYTES,HGLOBAL MOVE 64(A0,D0),D0 ;GET BITMASK IN D0 MOVE MINRECT+BOTTOM(A6),D1 ;GET BOTTOM SUB MINRECT+TOP(A6),D1 ;CALC HEIGHT SUB #1,D1 ;INIT HEIGHT COUNT CMP #1,MODE(A6) ;WHICH MODIFIED MODE ? BLT.S VSET ;BR IF BLACK BEQ.S VTOGL ;BR IF XOR ;ELSE WHITE NOT D0 ;MAKE NOTMASK VCLR AND D0,(A4) ;CLEAR ONE DOT ADD D7,A4 ;BUMP TO NEXT ROW DBRA D1,VCLR ;LOOP ALL DOTS BRA.S DONE ;RESTORE CURSOR AND QUIT VTOGL EOR D0,(A4) ;TOGGLE ONE DOT ADD D7,A4 ;BUMP TO NEXT ROW DBRA D1,VTOGL ;LOOP ALL DOTS BRA.S DONE ;RESTORE CURSOR AND QUIT VSET OR D0,(A4) ;SET ONE DOT ADD D7,A4 ;BUMP TO NEXT ROW DBRA D1,VSET ;LOOP ALL DOTS BRA.S DONE ;RESTORE CURSOR AND QUIT ;------------------------------------------------------------------------ ; ; LOCAL ROUTINE TO SET UP POINTER TO FIRST WORD, BIT INDEX, AND ROWBYTES ; ; INPUTS: MINRECT ; A5: thePort ; ; OUTPUTS: D0: STARTING HORIZ GLOBAL COORDS ; D1: STARTING HORIZ GLOBAL DIV 16 ; D7: ROWBYTES ; A0: MaskTab ; A4: POINTER TO FIRST WORD ; ; CLOBBERS: D0,D1,D7,A0,A4 ; HVSETUP MOVE.L PORTBITS+BASEADDR(A5),A4 ;GET BITMAP START MOVE MINRECT+TOP(A6),D0 ;GET STARTING VERT SUB PORTBITS+BOUNDS+TOP(A5),D0 ;CONVERT TO GLOBAL MOVE PORTBITS+ROWBYTES(A5),D7 ;GET ROWBYTES MULU D7,D0 ;MULT TOP BY ROWBYTES ADD.L D0,A4 ;ADD TO BASEADDR MOVE MINRECT+LEFT(A6),D0 ;GET STARTING HORIZ SUB PORTBITS+BOUNDS+LEFT(A5),D0 ;CONVERT TO GLOBAL MOVE D0,D1 ;MAKE A COPY LSR #4,D1 ;CONVERT BITS TO WORDS ADD D1,A4 ;ADD TO RUNNING TOTAL ADD D1,A4 ;TWICE FOR BYTES LEA MaskTab,A0 ;return with masktab in A0 AND #$F,D0 ;TREAT LEFT MOD 16 ADD D0,D0 ;DOUBLE FOR TABLE RTS .END