mac-rom/QuickDraw/Classic/DrawLine.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

784 lines
25 KiB
Plaintext

;
; File: DrawLine.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):
;
; <2> 10/10/90 JL Change FixRatio to MFixRatio to avoid conflict with Traps.a
; <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 ÒDRAWLINE.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'
;-----------------------------------------------------------------
;
; --> DRAWLINE.TEXT
;
DrawLine PROC EXPORT
IMPORT RgnBlt,RSect,ShieldCursor,ShowCursor,TrimRect
IMPORT InitRgn,SeekRgn,PatExpand,ColorMap
IMPORT 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 NEG ?
BMI.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 DC.B 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
_MFixRatio ;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
_MFixMul ;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 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
;-------------------------------------------------------
;
; 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