mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-28 16:31:01 +00:00
0ba83392d4
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.
1412 lines
48 KiB
Plaintext
1412 lines
48 KiB
Plaintext
;EASE$$$ READ ONLY COPY of file ÒPOLYGONS.m.aÓ
|
|
; 1.2 cv 03/23/1989 Adding code corresponding to patch PMA361. It incorporates
|
|
; the routines from QuickPolysClassicPatch.a and speeds up polygons.
|
|
; 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'
|
|
INCLUDE 'traps.a' ;<1.2/15mar89>
|
|
;--------------------------------------------------------------
|
|
;
|
|
;
|
|
; **** *** * * * *** *** * * ***
|
|
; * * * * * * * * * * * * * * *
|
|
; * * * * * * * * * ** * *
|
|
; **** * * * * * ** * * * * * ***
|
|
; * * * * * * * * * * ** *
|
|
; * * * * * * * * * * * * *
|
|
; * *** ***** * *** *** * * ***
|
|
;
|
|
;
|
|
|
|
; <1.2/15mar89> This is the revision history for the old polygons.m.a file prior to rolling
|
|
; in the new code from QuickPolysClassicPatch.a.
|
|
;_______________________________________________________________________________________
|
|
; This code replaces StdPoly with a version that has two important features. It does
|
|
; not use QuickDraw regions, and so does not blow up. In addition, for screen sized
|
|
; polygons it performs about 4 times faster than QuickDraw polygons.
|
|
;_______________________________________________________________________________________
|
|
;
|
|
; modification history
|
|
;
|
|
; <18Jan88> AWC MacPlus/SE rom patch installed this date
|
|
; <24Mar88> PMAB440 AWC Fixed sorting problem to make QuickPolys match Classic QuickDraw
|
|
; <26Mar88> PMAB444 AWC Fixed nil NewHandle bug in QuickPolys; refixed save A0 across _FixRatio
|
|
; <31Mar88> PMAB451 AWC Fixed a bug in PMAB440 above and saved registers across FixRatio
|
|
; <25Jul88> PMAB543 BAL/JDB Implemented fast case for rectangular filled polys.
|
|
;
|
|
|
|
;-------------------------------------------------------------
|
|
;
|
|
; Definition of the VectorRec structure
|
|
;
|
|
YVector Equ 0
|
|
XVector Equ 2
|
|
YDelta Equ 4
|
|
XDelta Equ 6
|
|
VectorSize Equ 8
|
|
|
|
;-------------------------------------------------------------
|
|
;
|
|
; Definition of the EdgeRec structure
|
|
;
|
|
|
|
NextEdge Equ 0 ; pointer to next edge
|
|
PrevEdge Equ NextEdge+4 ; pointer to previous edge
|
|
XValue Equ PrevEdge+4 ; current x position (Fixed)
|
|
XSlope Equ XValue+4 ; slope of the line (Fixed)
|
|
LastY Equ XSlope+4 ; end of the edge
|
|
Sign Equ LastY+2 ; sign of the vector (+1 or -1)
|
|
EdgeRecSize Equ Sign+2 ; size of the EdgeRec structure (20)
|
|
|
|
;-------------------------------------------------------------
|
|
; Flag to switch between the old polygons and new quickpolys rtns
|
|
;
|
|
QuickPolys EQU 1
|
|
|
|
;-------------------------------------------------------------
|
|
;
|
|
|
|
StdPoly PROC EXPORT
|
|
IMPORT CheckPic,PutPicVerb,DPutPicByte,PutPicRgn
|
|
IMPORT PushVerb,FrPoly,RSect,DrawPoly
|
|
|
|
|
|
;---------------------------------------------------------------
|
|
;
|
|
; PROCEDURE StdPoly(verb: GrafVerb; poly: PolyHandle);
|
|
;
|
|
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
|
|
;
|
|
PARAMSIZE EQU 6
|
|
VERB EQU PARAMSIZE+8-2 ;GRAFVERB
|
|
POLY EQU VERB-4 ;LONG, PolyHandle
|
|
|
|
MINRECT EQU -8 ;RECT
|
|
VARSIZE EQU MINRECT ;TOTAL BYTES OF LOCALS
|
|
|
|
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
|
|
MOVEM.L D5-D7/A2-A4,-(SP) ;SAVE REGS
|
|
MOVE.B VERB(A6),D7 ;GET VERB
|
|
JSR CHECKPIC ;SET UP A4,A3 AND CHECK PICSAVE
|
|
BLE.S NOTPIC ;BRANCH IF NOT PICSAVE
|
|
|
|
MOVE.B D7,-(SP)
|
|
JSR PutPicVerb ;PUT ADDIONAL PARAMS TO THEPIC
|
|
MOVEQ #$70,D0 ;PUT POLYNOUN IN HI NIBBLE
|
|
ADD D7,D0 ;PUT VERB IN LO NIBBLE
|
|
JSR DPutPicByte ;PUT OPCODE TO THEPIC
|
|
MOVE.L POLY(A6),-(SP) ;PUSH POLYHANDLE
|
|
JSR PutPicRgn ;TREAT SAME AS A REGION
|
|
|
|
NOTPIC MOVE.L POLY(A6),A2 ;GET POLYHANDLE
|
|
TST.B D7 ;IS VERB FRAME ?
|
|
BNE.S NOTFR ;NO, CONTINUE
|
|
MOVE.L A2,-(SP) ;PUSH POLYHANDLE
|
|
JSR FrPoly ;FrPoly(poly);
|
|
BRA.S GOHOME ;AND QUIT
|
|
|
|
NOTFR MOVE.L (A2),A0 ;DE-REFERANCE POLYHANDLE
|
|
PEA POLYBBOX(A0) ;PUSH POLYBBOX
|
|
MOVE.L VISRGN(A3),A0 ;GET VISRGN HANDLE
|
|
MOVE.L (A0),A0 ;DE-REFERENCE HANDLE
|
|
PEA RGNBBOX(A0) ;PUSH VISRGN BBOX
|
|
MOVE.L CLIPRGN(A3),A0 ;GET CLIPRGN HANDLE
|
|
MOVE.L (A0),A0 ;DE-REFERENCE HANDLE
|
|
PEA RGNBBOX(A0) ;PUSH CLIPRGN BBOX
|
|
MOVE #3,-(SP) ;PUSH NRECTS = 3
|
|
PEA MINRECT(A6) ;PUT RESULT IN MINRECT
|
|
JSR RSECT ;CALC INTERSECTION
|
|
BEQ.S GOHOME ;QUIT IF NO INTERSECT
|
|
|
|
MOVE.L A2,-(SP) ;PUSH POLYHANDLE
|
|
JSR PushVerb ;PUSH MODE AND PATTERN
|
|
JSR DrawPoly ;DrawPoly(poly,mode,pat);
|
|
|
|
GOHOME MOVEM.L (SP)+,D5-D7/A2-A4 ;RESTORE REGS
|
|
UNLINK PARAMSIZE,'STDPOLY '
|
|
|
|
|
|
FramePoly PROC EXPORT
|
|
EXPORT CallPoly,PaintPoly,ErasePoly,InvertPoly,FillPoly
|
|
;-----------------------------------------------------
|
|
;
|
|
; PROCEDURE FramePoly(* poly: PolyHandle *);
|
|
;
|
|
MOVEQ #FRAME,D0 ;VERB = FRAME
|
|
BRA.S CallPoly ;SHARE COMMON CODE
|
|
|
|
|
|
|
|
;-----------------------------------------------------
|
|
;
|
|
; PROCEDURE PaintPoly(* poly: PolyHandle *);
|
|
;
|
|
PaintPoly
|
|
MOVEQ #PAINT,D0 ;VERB = PAINT
|
|
BRA.S CallPoly ;SHARE COMMON CODE
|
|
|
|
|
|
|
|
;--------------------------------------------------------
|
|
;
|
|
; PROCEDURE ErasePoly(* poly: PolyHandle *);
|
|
;
|
|
ErasePoly
|
|
MOVEQ #ERASE,D0 ;VERB = ERASE
|
|
BRA.S CallPoly ;SHARE COMMON CODE
|
|
|
|
|
|
|
|
;--------------------------------------------------------
|
|
;
|
|
; PROCEDURE InvertPoly(* poly: PolyHandle *);
|
|
;
|
|
InvertPoly
|
|
MOVEQ #INVERT,D0 ;VERB = INVERT
|
|
BRA.S CallPoly ;SHARE COMMON CODE
|
|
|
|
|
|
|
|
;--------------------------------------------------------
|
|
;
|
|
; PROCEDURE FillPoly(* poly: PolyHandle; pat: Pattern *);
|
|
;
|
|
FillPoly
|
|
MOVE.L (SP)+,A0 ;POP RETURN ADDR
|
|
MOVE.L (SP)+,A1 ;POP ADDR OF PATTERN
|
|
MOVE.L A0,-(SP) ;PUT RETURN ADDR BACK
|
|
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO LISAGRAF GLOBALS
|
|
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
|
|
LEA FILLPAT(A0),A0 ;POINT TO FILLPAT
|
|
MOVE.L (A1)+,(A0)+ ;COPY PAT INTO FILLPAT
|
|
MOVE.L (A1)+,(A0)+ ;ALL EIGHT BYTES
|
|
MOVEQ #FILL,D0 ;VERB = FILL
|
|
BRA.S CallPoly ;SHARE COMMON CODE
|
|
|
|
|
|
|
|
;---------------------------------------------------------------
|
|
;
|
|
; PROCEDURE CallPoly(poly: PolyHandle);
|
|
;
|
|
; code shared by FramePoly, PaintPoly, ErasePoly, InvertPoly, and FillPoly.
|
|
; enter with verb in D0.
|
|
;
|
|
CallPoly
|
|
MOVE.L (SP)+,A0 ;POP RETURN ADDR
|
|
MOVE.L (SP)+,A1 ;POP POLY
|
|
MOVE.B D0,-(SP) ;PUSH VERB
|
|
MOVE.L A1,-(SP) ;PUSH POLY
|
|
MOVE.L A0,-(SP) ;RESTORE RETURN ADDR
|
|
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO LISAGRAF GLOBALS
|
|
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
|
|
MOVE.L GRAFPROCS(A0),D0 ;IS GRAFPROCS NIL ?
|
|
MOVE.L JStdPoly,A0 ;get piece of trap table
|
|
BEQ.S USESTD ;YES, USE STD PROC
|
|
MOVE.L D0,A0
|
|
MOVE.L POLYPROC(A0),A0 ;NO, GET PROC PTR
|
|
USESTD JMP (A0) ;GO TO IT
|
|
|
|
|
|
|
|
OpenPoly FUNC EXPORT
|
|
IMPORT HidePen,NewHandle
|
|
;---------------------------------------------------------------
|
|
;
|
|
; FUNCTION OpenPoly: PolyHandle;
|
|
;
|
|
STARTSIZE EQU 138 ;ENOUGH FOR 32 POINTS
|
|
|
|
JSR HidePen ;TURN OFF DRAWING
|
|
CLR.L -(SP) ;MAKE ROOM FOR FCN RESULT
|
|
MOVE #STARTSIZE,-(SP) ;PUSH BYTE COUNT = STARTSIZE
|
|
JSR NEWHANDLE ;ALLOCATE NEWHANDLE
|
|
MOVE.L (SP)+,A1 ;POP RESULTING HANDLE
|
|
MOVE.L A1,4(SP) ;PUT HANDLE IN FCN RESULT
|
|
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
|
|
MOVE.L A1,THEPOLY(A0) ;REMEMBER HANDLE IN THEPOLY
|
|
MOVE #STARTSIZE,POLYMAX(A0) ;POLYMAX := STARTSIZE;
|
|
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
|
|
MOVEQ #1,D0
|
|
MOVE.L D0,POLYSAVE(A0) ;POLYSAVE := TRUE
|
|
MOVE.L (A1),A1 ;DE-REFERENCE HANDLE
|
|
MOVE #10,(A1)+ ;INSTALL POLYSIZE = 10
|
|
CLR.L (A1)+ ;ZERO OUT POLYBBOX
|
|
CLR.L (A1)+
|
|
RTS ;RETURN
|
|
|
|
|
|
|
|
ClosePoly PROC EXPORT
|
|
IMPORT SETHSIZE,ShowPen
|
|
;---------------------------------------------------------------
|
|
;
|
|
; PROCEDURE ClosePoly;
|
|
;
|
|
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
|
|
;
|
|
MOVEM.L D3-D7/A4,-(SP) ;SAVE REGS
|
|
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
|
|
MOVE.L THEPORT(A4),A0 ;GET CURRENT GRAFPORT
|
|
CLR.L POLYSAVE(A0) ;POLYSAVE := FALSE
|
|
MOVE.L THEPOLY(A4),A4 ;GET THEPOLY HANDLE
|
|
MOVE.L (A4),A0 ;DE-REFERENCE THEPOLY
|
|
MOVE (A0)+,D7 ;GET POLYSIZE
|
|
CLR.L (A0)+ ;ZERO OUT POLYBBOX
|
|
CLR.L (A0)+
|
|
MOVE D7,D6
|
|
SUB #10,D6
|
|
LSR #2,D6 ;NPOINTS = (SIZE-10) DIV 4
|
|
BEQ.S EMPTY ;QUIT IF NO POINTS
|
|
|
|
|
|
;-----------------------------------------------------
|
|
;
|
|
; SCAN FOR BOUNDING BOX OF POLYGON
|
|
;
|
|
MOVE (A0)+,D1 ;TOP := FIRST POINT VERT
|
|
MOVE D1,D2 ;BOTTOM := FIRST POINT VERT
|
|
MOVE (A0)+,D3 ;LEFT := FIRST POINT HORIZ
|
|
MOVE D3,D4 ;RIGHT := FIRST POINT HORIZ
|
|
SUB #1,D6 ;DECREMENT POINT COUNT
|
|
BRA.S RIGHTOK ;GO TO LOOP START
|
|
NEXTPT MOVE (A0)+,D0 ;GET VERT COORD
|
|
CMP D1,D0 ;IS VERT < BBOX TOP ?
|
|
BGE.S TOPOK ;NO, CONTINUE
|
|
MOVE D0,D1 ;YES, UPDATE BBOX TOP
|
|
TOPOK CMP D2,D0 ;IS VERT > BBOX BOTTOM ?
|
|
BLE.S BOTOK ;NO, CONTINUE
|
|
MOVE D0,D2 ;YES, UPDATE BBOX BOTTOM
|
|
BOTOK MOVE (A0)+,D0 ;GET HORIZ COORD
|
|
CMP D3,D0 ;IS HORIZ < BBOX LEFT ?
|
|
BGE.S LEFTOK ;NO, CONTINUE
|
|
MOVE D0,D3 ;YES, UPDATE BBOX LEFT
|
|
LEFTOK CMP D4,D0 ;IS HORIZ > BBOX RIGHT ?
|
|
BLE.S RIGHTOK ;NO, CONTINUE
|
|
MOVE D0,D4 ;YES, UPDATE BBOX RIGHT
|
|
RIGHTOK DBRA D6,NEXTPT ;LOOP ALL POINTS
|
|
MOVE.L (A4),A0 ;DE-REFERENCE THEPOLY
|
|
LEA POLYBBOX(A0),A0 ;POINT TO POLYBBOX
|
|
MOVE D1,(A0)+ ;INSTALL BBOX TOP
|
|
MOVE D3,(A0)+ ;INSTALL BBOX LEFT
|
|
MOVE D2,(A0)+ ;INSTALL BBOX BOTTOM
|
|
MOVE D4,(A0)+ ;INSTALL BBOX RIGHT
|
|
|
|
|
|
;--------------------------------------------------------
|
|
;
|
|
; TRIM THEPOLY TO FINAL SIZE, SHOW PEN AND QUIT
|
|
;
|
|
EMPTY MOVE.L A4,-(SP) ;PUSH THEPOLY HANDLE
|
|
MOVE D7,-(SP) ;PUSH BYTECOUNT = POLYSIZE
|
|
JSR SETHSIZE ;TRIM TO MINIMUM SIZE
|
|
JSR SHOWPEN ;RESTORE PNVIS
|
|
MOVEM.L (SP)+,D3-D7/A4 ;RESTORE REGS
|
|
RTS ;AND RETURN
|
|
|
|
|
|
|
|
KillPoly PROC EXPORT
|
|
;---------------------------------------------------
|
|
;
|
|
; PROCEDURE KillPoly(poly: PolyHandle);
|
|
;
|
|
MOVE.L (SP)+,A1 ;pop return addr
|
|
MOVE.L (SP)+,A0 ;pop handle
|
|
_DisposHandle ;discard it
|
|
JMP (A1) ;and return
|
|
|
|
|
|
|
|
|
|
OffsetPoly PROC EXPORT
|
|
;---------------------------------------------------
|
|
;
|
|
; PROCEDURE OffsetPoly(poly: PolyHandle; dh,dv: INTEGER);
|
|
;
|
|
MOVE.L (SP)+,A0 ;POP RETURN ADDRESS
|
|
MOVE (SP)+,D0 ;POP DV
|
|
MOVE (SP)+,D1 ;POP DH
|
|
MOVE.L (SP)+,A1 ;POP POLYHANDLE
|
|
MOVE.L (A1),A1 ;DE-REFERENCE POLYHANDLE
|
|
MOVE (A1)+,D2 ;GET POLYSIZE
|
|
SUB #2,D2 ;CALC TOTAL # POINTS, INCL BBOX
|
|
LSR #2,D2 ; # POINTS = (SIZE-2) DIV 4
|
|
SUB #1,D2 ;INIT DBRA COUNT
|
|
NEXTPT ADD D0,(A1)+ ;OFFSET VERT COORD
|
|
ADD D1,(A1)+ ;OFFSET HORIZ COORD
|
|
DBRA D2,NEXTPT ;LOOP FOR ALL POINTS
|
|
JMP (A0) ;AND RETURN
|
|
|
|
|
|
|
|
MapPoly PROC EXPORT
|
|
IMPORT MapPt,MapRect
|
|
;-------------------------------------------------------------
|
|
;
|
|
; PROCEDURE MapPoly(poly: PolyHandle; fromRect,toRect: Rect);
|
|
;
|
|
; A6 OFFSETS OF PARAMETERS AND LOCALS AFTER LINK:
|
|
;
|
|
PARAMSIZE EQU 12
|
|
POLY EQU PARAMSIZE+8-4 ;LONG, RGNHANDLE
|
|
FROMRECT EQU POLY-4 ;LONG, ADDR OF RECT
|
|
TORECT EQU FROMRECT-4 ;LONG, ADDR OF RECT
|
|
|
|
LINK A6,#0 ;ALLOCATE STACK FRAME
|
|
MOVEM.L D7/A2-A4,-(SP) ;SAVE REGS
|
|
;
|
|
; QUIT FAST IF FROMRECT = TORECT
|
|
;
|
|
MOVE.L FROMRECT(A6),A2 ;POINT TO FROMRECT
|
|
MOVE.L TORECT(A6),A3 ;POINT TO TORECT
|
|
MOVE.L (A2),D0
|
|
CMP.L (A3),D0 ;IS TOPLEFT SAME ?
|
|
BNE.S NOTSAME ;NO, CONTINUE
|
|
MOVE.L 4(A2),D0
|
|
CMP.L 4(A3),D0 ;YES, IS BOTRIGHT SAME TOO ?
|
|
BEQ.S DONE ;IF SO, JUST QUIT
|
|
|
|
NOTSAME MOVE.L POLY(A6),A4 ;GET POLYHANDLE
|
|
MOVE.L (A4),A4 ;DE-REFERENCE POLYHANDLE
|
|
PEA POLYBBOX(A4) ;PUSH ADDR OF BBOX
|
|
MOVE.L A2,-(SP) ;PUSH FROMRECT
|
|
MOVE.L A3,-(SP) ;PUSH TORECT
|
|
JSR MAPRECT ;MAP POLYBBOX
|
|
|
|
MOVEQ #10,D0
|
|
MOVE POLYSIZE(A4),D7 ;GET POLYSIZE
|
|
SUB D0,D7
|
|
LSR #2,D7 ;NPOINTS = (POLYSIZE-10) DIV 4
|
|
ADD D0,A4 ;POINT TO FIRST POINT
|
|
BRA.S START ;GO TO LOOP START
|
|
NEXTPT MOVE.L A4,-(SP) ;PUSH ADDR OF POINT
|
|
MOVE.L A2,-(SP) ;PUSH FROMRECT
|
|
MOVE.L A3,-(SP) ;PUSH TORECT
|
|
JSR MAPPT ;MAP THIS POINT
|
|
ADD #4,A4 ;BUMP TO NEXT POINT
|
|
START DBRA D7,NEXTPT ;LOOP ALL POINTS IN POLY
|
|
|
|
DONE MOVEM.L (SP)+,D7/A2-A4 ;RESTORE REGS
|
|
UNLINK PARAMSIZE,'MAPPOLY '
|
|
|
|
|
|
|
|
FrPoly PROC EXPORT
|
|
IMPORT MoveTo,DoLine
|
|
;--------------------------------------------------------
|
|
;
|
|
; PROCEDURE FrPoly(poly: PolyHandle);
|
|
;
|
|
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
|
|
;
|
|
PARAMSIZE EQU 4
|
|
POLY EQU PARAMSIZE+8-4 ;LONG, POLYHANDLE
|
|
|
|
LINK A6,#0 ;ALLOCATE STACK FRAME
|
|
MOVEM.L D6-D7/A4,-(SP) ;SAVE REGS
|
|
MOVE.L POLY(A6),A4 ;GET POLYHANDLE
|
|
MOVE.L (A4),A0 ;DE-REFERENCE IT
|
|
MOVE (A0),D7 ;GET POLYSIZE
|
|
SUB #10,D7
|
|
LSR #2,D7 ;NPOINTS = (SIZE-10) DIV 4
|
|
BEQ.S DONE ;QUIT IF EMPTY POLYGON
|
|
MOVE.L 10(A0),-(SP) ;PUSH FIRST POINT
|
|
JSR MOVETO ;MOVETO(FIRST POINT)
|
|
MOVE.L #14,D6 ;INIT BYTE OFFSET
|
|
SUB #1,D7 ;DECREMENT COUNT
|
|
BRA.S START ;GOT TO LOOP START
|
|
NEXTPT MOVE.L (A4),A0 ;DE-REFERENCE POLYHANDLE
|
|
MOVE.L 0(A0,D6),-(SP) ;PUSH NEXT POINT
|
|
ADD #4,D6 ;BUMP BYTE OFFSET
|
|
JSR DOLINE ;DOLINE(PT)
|
|
START DBRA D7,NEXTPT ;LOOP FOR ALL POINTS
|
|
DONE MOVEM.L (SP)+,D6-D7/A4 ;RESTORE REGS
|
|
UNLINK PARAMSIZE,'FRPOLY '
|
|
|
|
|
|
;-------------------------------------------------------------
|
|
; <1.2/15mar89> This flag is used so that the old code could be
|
|
; kept around in case we need to use it at at later
|
|
; date. Now we always use the new quickpolybw code.
|
|
; A new Drawpoly routine has been developed along
|
|
; with supporting code.
|
|
|
|
IF QuickPolys THEN
|
|
;-------------------------------------------------------------
|
|
;
|
|
; PROCEDURE SortVectors(Vectors: Ptr; VCount: integer);
|
|
;
|
|
; SortVectors performs a non-recursive QuickSort on an array of
|
|
; vectors (y,x,dy,dx). The vectors are sorted first on y and second
|
|
; on x. The differential values are not examined. This code is
|
|
; a modified version of SortPoints, found in the QuickDraw ROM.
|
|
; The vectors are placed in increasing Y.X order. See the source
|
|
; reference "Algorithms + Data Structures = Programs, p. 80"
|
|
|
|
SortVectors PROC EXPORT
|
|
|
|
ParamSize Equ 6
|
|
Vectors Equ ParamSize+8-4
|
|
VCount Equ Vectors-2
|
|
|
|
VarSize Equ 0
|
|
|
|
Link A6,#VarSize ; no local variables
|
|
MoveM.L D3-D4/A2-A4,-(SP) ; save registers
|
|
Move.L Vectors(A6),A3 ; LeftPtr := start of point array
|
|
Move A3,D3 ; set up low bits for sort
|
|
And #7,D3 ; AWC - #3 => #7
|
|
MoveQ #0,D0 ; clear high word
|
|
Move VCount(A6),D0 ; get VCount
|
|
Ble.S GoHome ; do nothing if no vectors
|
|
Lsl.L #3,D0 ; AWC - #2 => #3; LineCount * 8 for bytes
|
|
Move.L A3,A4
|
|
Add.L D0,A4 ; add to DstStart
|
|
SubQ.L #8,A4 ; AWC - #4 => #8; RightPtr := DstEnd - 8
|
|
Move.L SP,D4 ; remember stack marker
|
|
MoveM.L A3/A4,-(SP) ; push LeftPtr and RightPtr
|
|
RePartition MoveM.L (SP)+,A3/A4 ; pop LeftPtr and RightPtr
|
|
Split Move.L A3,A1 ; IPtr := LeftPtr
|
|
Move.L A4,A2 ; JPtr := RightPtr
|
|
|
|
; Calculate MidPtr and MidPt
|
|
|
|
Move.L A3,D0 ; D0 := LeftPtr + RightPtr
|
|
Add.L A4,D0
|
|
RoxR.L #1,D0 ; divide by 2 for MidPtr
|
|
And #$FFF8,D0 ; AWC - #$FFFC => #$FFF8; truncate to multiple of 8 bytes
|
|
Or D3,D0 ; OR in low bits for vector boundary
|
|
Move.L D0,A0 ; put MidPtr into A0
|
|
Move XVector(A0),D1 ; D1 := MidPt.X
|
|
Move YVector(A0),D2 ; D2 := MidPt.Y
|
|
Bra.S IScan
|
|
|
|
; while IPtr^ < MidPt do IPtr := IPtr + 8
|
|
|
|
NextIPtr AddQ.L #8,A1 ; AWC - #4 => #8; bump IPtr to "right"
|
|
IScan Cmp YVector(A1),D2 ; is MidPt.Y > IPtr^.Y?
|
|
Bgt.S NextIPtr ; yes => continue bumping
|
|
Blt.S JScan ; MidPt.Y < IPtr^.Y? yes => done with IPtr
|
|
Cmp XVector(A1),D1 ; sort on X - is MidPt.X > IPtr^.X?
|
|
Bgt.S NextIPtr ; yes => continue bumping
|
|
Bra.S JScan ; go to loop start
|
|
|
|
; while JPtr^ > MidPt do JPtr := JPtr - 8
|
|
|
|
NextJPtr SubQ.L #8,A2 ; AWC - #4 => #8; decrement JPtr
|
|
JScan Cmp YVector(A2),D2 ; is JPtr^.Y > MidPt.Y?
|
|
Blt.S NextJPtr ; yes => look at the next JPtr
|
|
Bgt.S EndScan ; is JPtr^.Y < MidPt.Y? yes => this partition is done
|
|
Cmp XVector(A2),D1 ; is JPtr^.X > MidPt.X?
|
|
Blt.S NextJPtr ; yes => look at the next JPtr
|
|
|
|
; if IPtr <= JPtr then swap IPtr^ and JPtr^, and bump both pointers
|
|
|
|
EndScan Cmp.L A2,A1 ; is IPtr > JPtr?
|
|
Bgt.S NoSwap ; yes => all done
|
|
Move.L (A1),D0 ; D0 := IPtr^
|
|
Move.L (A2),(A1) ; IPtr^ := JPtr^
|
|
Move.L D0,(A2) ; JPtr^ := D0
|
|
Move.L 4(A1),D0 ; D0 := IPtr^.dy
|
|
Move.L 4(A2),4(A1) ; IPtr^.dy := JPtr^.dy
|
|
Move.L D0,4(A2) ; JPtr^.dy := D0
|
|
AddQ.L #8,A1 ; IPtr := IPtr + 8
|
|
SubQ.L #8,A2 ; JPtr := JPtr - 8
|
|
|
|
; repeat until this partitioning is complete, IPtr > JPtr
|
|
|
|
NoSwap CmpA.L A2,A1 ; is IPtr > JPtr
|
|
Bls.S IScan ; no => loop again
|
|
|
|
; if IPtr < RightPtr then stack request to sort right partition
|
|
|
|
CmpA.L A4,A1 ; is IPtr < RightPtr?
|
|
Bhs.S RightOkay ; yes => continue
|
|
MoveM.L A1/A4,-(SP) ; no => PushPartition(IPtr,RightPtr)
|
|
|
|
RightOkay Move.L A2,A4 ; RightPtr := JPtr
|
|
CmpA.L A4,A3 ; is LeftPtr >= RightPtr?
|
|
Blo.S Split ; no => partition again
|
|
CmpA.L D4,SP ; is stack empty yet?
|
|
Bne.S RePartition ; no => loop for more
|
|
|
|
GoHome MoveM.L (SP)+,D3-D4/A2-A4 ; restore registers
|
|
UNLINK PARAMSIZE,'SORTVECT'
|
|
|
|
;---------------------------------------------------
|
|
;
|
|
; PROCEDURE PaintVector(Vector:VectorArray; VCount:integer; EoFill:boolean;
|
|
; VectRect:Rect; Mode:integer; Pat:Pattern);
|
|
;
|
|
|
|
PaintVector PROC EXPORT
|
|
IMPORT ShowCursor,ShieldCursor,MaskTab,PatExpand,ColorMap,XorSlab
|
|
IMPORT DrawSlab,SlabMode,FastSlabMode,RSect,TrimRect
|
|
IMPORT InitRgn,SeekRgn
|
|
|
|
ParamSize Equ 18
|
|
Vector Equ ParamSize+8-4
|
|
VCount Equ Vector-2
|
|
EoFill Equ VCount-2
|
|
VectRect Equ EoFill-4
|
|
Mode Equ VectRect-2
|
|
Pat Equ Mode-4
|
|
|
|
|
|
;-------------------------------------------------
|
|
;
|
|
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
|
|
;
|
|
EXPAT EQU -64 ;16 LONGS
|
|
MINRECT EQU EXPAT-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
|
|
MODECASE EQU BUFSIZE-4 ;LONG
|
|
DSTLEFT EQU MODECASE-4 ;LONG
|
|
SAVEA5 EQU DSTLEFT-4 ;LONG
|
|
PORT EQU SAVEA5-4 ;LONG
|
|
FASTFLAG EQU PORT-2 ;BYTE
|
|
TEMPRECT EQU FASTFLAG-8 ;RECT
|
|
PATINDEX EQU TEMPRECT-2 ;WORD
|
|
|
|
; Stack frame variables used only in DrawPoly
|
|
|
|
FreeList Equ PatIndex-4
|
|
StackLimit Equ FreeList-4
|
|
ActiveList Equ StackLimit-4
|
|
VarSize Equ ActiveList
|
|
|
|
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 THEPORT(A0),A3 ;GET CURRENT GRAFPORT
|
|
TST PNVIS(A3) ;IS PNVIS NEG ?
|
|
BLT GOHOME ;YES, QUIT
|
|
MOVE.L A3,PORT(A6) ;SAVE CURRENT GRAFPORT
|
|
|
|
;-------------------------------------------------------
|
|
;
|
|
; QUIT IF MODE NOT IN 8..15
|
|
;
|
|
MOVEQ #-8,D0 ;MASK TO KILL BOTTOM 3 BITS
|
|
AND MODE(A6),D0 ;GET ALL BUT 3 BITS OF MODE
|
|
CMP #8,D0 ;IS PEN MODE 8..15 ?
|
|
BNE GOHOME ;NO, QUIT
|
|
|
|
|
|
;----------------------------------------------------------------
|
|
;
|
|
; ADJUST MODE AND PATTERN IF COLOR FILTERING.
|
|
;
|
|
TST COLRBIT(A3) ;IS COLORBIT NEG ?
|
|
BMI.S NOCOLOR ;YES, DON'T MAP
|
|
MOVE MODE(A6),-(SP) ;PUSH INPUT MODE
|
|
MOVE.L PAT(A6),-(SP) ;PUSH ADDR OF INPUT PATTERN
|
|
JSR COLORMAP ;ALTER BY THECOLOR, THEFILTER
|
|
MOVE.L (SP)+,PAT(A6) ;GET (ALTERED) PATTERN
|
|
MOVE (SP)+,MODE(A6) ;GET (ALTERED) MODE
|
|
NOCOLOR MOVE.L A3,A5 ;PUT GRAFPORT IN A5
|
|
|
|
|
|
;---------------------------------------------------------
|
|
;
|
|
; GET CLIPRGN AND VISRGN HANDLES AND DE-REFERENCE THEM
|
|
;
|
|
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
|
|
|
|
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; CALC MINRECT, THE INTERSECTION OF DSTRECT, BITMAP BOUNDS,
|
|
; CLIPRGN BBOX, AND VISRGN BBOX. QUIT IF NO INTERSECTION.
|
|
;
|
|
MOVE.L VectRect(A6),-(SP) ;PUSH DSTRECT
|
|
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
|
|
|
|
;
|
|
; 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 GOHOME ;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) ;REMEMBER 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 GOHOME ;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
|
|
|
|
|
|
;----------------------------------------------------------------
|
|
;
|
|
; 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 ;RESTORE GRAFPORT IN A5
|
|
|
|
|
|
;------------------------------------
|
|
;
|
|
; 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 REGION STATEA
|
|
MOVE #32767,STATEA+NEXTV(A6) ;TO HARMLESS IN CASE RECT
|
|
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 REGION STATEB
|
|
MOVE #32767,STATEB+NEXTV(A6) ;TO HARMLESS IN CASE RECT
|
|
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 ALL 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 ;GET MINRECT TOP
|
|
SUB PORTBITS+BOUNDS+TOP(A5),D1 ;CONVERT 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 ALL HORIZONTAL COORDINATES RELATIVE TO BUFFER
|
|
;
|
|
MOVE BUFLEFT(A6),D1
|
|
SUB D1,MINRECT+LEFT(A6)
|
|
SUB D1,MINRECT+RIGHT(A6)
|
|
|
|
;---------------------------------------------------
|
|
;
|
|
; SET UP CASE JUMP BASED ON MODE AND FASTFLAG
|
|
;
|
|
MOVE MODE(A6),D2 ;GET (ALTERED) PEN MODE
|
|
TST.B FastFlag(A6) ;Rect clipoped and black ?
|
|
BEQ.S @1 ;no, use slow drawslab loop
|
|
JSR FastSlabMode ;yes, get fast modeCase in A4
|
|
MOVE.L A4,MODECASE(A6) ;SAVE FOR LATER
|
|
CLR PATINDEX(A6) ;MAKE UNUSED PATINDEX EVEN
|
|
BRA.S GOFORIT ;SKIP PATTERN STUFF
|
|
@1 JSR SlabMode ;get slow modeCase in A4
|
|
MOVE.L A4,MODECASE(A6) ;SAVE FOR LATER
|
|
|
|
|
|
;------------------------------------------------------------------
|
|
;
|
|
; EXPAND 8 BYTE PATTERN TO 16 LONGS AND INIT PATTERN SELECTOR
|
|
;
|
|
CLR.L D7 ;SAY NOT INVERTED
|
|
MOVE MODE(A6),D2 ;GET 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 BYTE PATTERN TO 16 LONGS
|
|
MOVE.L PORT(A6),A5 ;RESTORE GRAFPORT IN A5
|
|
MOVEQ #$F,D0 ;TREAT COORD MOD 16
|
|
AND MINRECT+TOP(A6),D0 ;GET TOP VERT LOCAL COORD
|
|
LSL #2,D0 ;QUAD FOR 4 BYTE PATTERNS
|
|
MOVE D0,PATINDEX(A6) ;SET UP PATTERN INDEX
|
|
|
|
|
|
;;;;; End of sicko code from DrawArc
|
|
|
|
GoForIt Clr.L FreeList(A6) ; FreeList := nil;
|
|
Clr.L ActiveList(A6) ; ActiveList := nil;
|
|
_StackSpace ; how much stack is available
|
|
Move.L SP,D1 ; grab current stack
|
|
Sub.L D0,D1 ; calculate the maximum stack limit
|
|
Add.L #$100,D1 ; give us some spare room
|
|
Move.L D1,StackLimit(A6) ; save it
|
|
Move.L Vector(A6),A3 ; get pointer to VectorArray
|
|
Move (A3),D7 ; get CurrentY
|
|
Move VCount(A6),D3 ; get number of edges
|
|
ActiveLoop MoveQ #Nil,A0 ; NewEdges := nil
|
|
MoveQ #Nil,A1 ; CurrentEdge := nil
|
|
|
|
; while (Vector < VCount) & (CurrentY = Vectors[Vector+1].YVector) do begin
|
|
|
|
Tst D3 ; any new edges left?
|
|
Beq NoNewEdges ; no => don't add any new
|
|
NewEdgeLoop Cmp (A3),D7 ; does CurrentY = NextY?
|
|
Bne NoNewEdges ; no => don't add any at the moment
|
|
Move.L FreeList(A6),A2 ; grab the FreeList
|
|
Move.L A2,D0 ; CmpA #Nil,A2; can we get an edge from the free list?
|
|
Bne.S FreeAndEasy ; yes => good enough
|
|
SubA.L #EdgeRecSize,SP ; make room for daddy
|
|
Move.L SP,A2 ; and create a new edge on the stack (gross)
|
|
CmpA.L StackLimit(A6),A2 ; have we bombed
|
|
Bge.S StackEdge ; no => keep trucking
|
|
Bra NoMorePoly ; yes => get out of here
|
|
|
|
FreeAndEasy Move.L (A2),FreeList(A6) ; FreeList := FreeList^.NextEdge
|
|
StackEdge MoveM.L A0-A1,-(SP) ; save registers across the FixRatio AWC.PMAB451
|
|
Clr.L -(SP) ; FixRatio result AWC.PMAB440
|
|
Move.L YDelta(A3),-(SP) ; push numerator and denominator for FixRatio
|
|
_FixRatio ; calculate it
|
|
|
|
; The following few lines are excerpted from the PutLine code of Quickdraw so we can match
|
|
; the old polygon code precisely in terms of pixels rendered.
|
|
|
|
Move.L (SP)+,D2 ; D2 := slope
|
|
MoveM.L (SP)+,A0-A1 ; restore registers AWC.PMAB451
|
|
Move XVector(A3),D1 ; HiWord(D1) := XVector
|
|
Sub BufLeft(A6),D1 ; adjust to global coordinates
|
|
Swap D1 ; put the coordinate in the high word
|
|
Move #$8000,D1 ; LoWord(XVector) := 1/2
|
|
Move.L D2,D0 ; D0 := slope
|
|
Asr.L #1,D0 ; D0 := slope/2
|
|
Add.L D0,D1 ; XValue := XValue + Slope/2
|
|
Move.L #$10000,D0 ; D0 := 1.0000 fixed
|
|
Tst.L D2 ; is slope negative?
|
|
Bmi.S NegSlope ; yes => continue
|
|
Cmp.L D0,D2 ; is slope < 1.0000?
|
|
Bge.S SlopeOkay ; no => continue
|
|
Add.L D2,D1 ; XValue := XValue + Slope
|
|
Bra.S SlopeOkay ; continue
|
|
|
|
NegSlope Cmp.L #$FFFF0000,D2 ; is slope > -1.0000?
|
|
Bge.S SlopeOkay ; yes => continue
|
|
Add.L D0,D1 ; XValue := XValue + 1.0000
|
|
|
|
SlopeOkay Move.L D1,XValue(A2) ; XValue := D1
|
|
Move.L D2,XSlope(A2) ; XSlope := FixRatio(XVector,YVector)
|
|
MoveQ #1,D1 ; Sign := 1
|
|
Move YDelta(A3),D0 ; D0 := abs(YDelta)
|
|
Bpl.S SignOkay ; don't negate it
|
|
Neg D0 ; abs(YDelta)
|
|
Neg D1 ; Sign := -1
|
|
SignOkay Add D7,D0 ; D0 := CurrentY + abs(YDelta)
|
|
Move D0,LastY(A2) ; Edge^.LastY := CurrentY + abs(YDelta)
|
|
Tst.B EoFill(A6) ; are we EoFill'ing?
|
|
Beq.S Winder ; no => leave sign alone
|
|
MoveQ #0,D1 ; Sign := 0
|
|
Winder Move D1,Sign(A2) ; save Sign
|
|
|
|
Move.L A0,D0 ; CmpA.L #Nil,A0; is NewEdges nil? AWC.PMAB440
|
|
Bne.S InsertMid ; no => insert this new edge in the list AWC.PMAB440
|
|
Move.L A2,A0 ; NewEdges := Edge AWC.PMAB440
|
|
Move.L A2,A1 ; CurrentEdge := Edge AWC.PMAB440
|
|
Clr.L NextEdge(A2) ; end of list AWC.PMAB440
|
|
Clr.L PrevEdge(A2) ; beginning of list, too AWC.PMAB440
|
|
Bra.S InsertDone ; continue AWC.PMAB440
|
|
|
|
InsertMid Move.L A1,A4 ; InsertPt := CurrentEdge AWC.PMAB440
|
|
Move.L XValue(A2),D0 ; grab our compare value AWC.PMAB440
|
|
InsertNext Cmp.L XValue(A4),D0 ; D0 - InsertPt^.XValue AWC.PMAB440
|
|
Bge.S InsertIt ; if greater or equal, insert it AWC.PMAB440
|
|
Move.L PrevEdge(A4),A4 ; InsertPt := InsertPt^.NextEdge AWC.PMAB440
|
|
Move.L A4,D1 ; is the next edge nil? AWC.PMAB440
|
|
Bne.S InsertNext ; no => keep looking AWC.PMAB440
|
|
Move.L A0,NextEdge(A2) ; Edge^.NextEdge := NewEdges AWC.PMAB440
|
|
Move.L A2,PrevEdge(A0) ; NewEdges^.PrevEdge := Edge AWC.PMAB440
|
|
Clr.L PrevEdge(A2) ; Edge^.PrevEdge := nil AWC.PMAB440
|
|
Move.L A2,A0 ; NewEdges := Edge AWC.PMAB440
|
|
Bra.S InsertDone ; continue AWC.PMAB440
|
|
|
|
InsertIt CmpA.L A1,A4 ; at the end of the list? AWC.PMAB440
|
|
Beq.S InsertEnd ; yes => insert this edge at the end of list AWC.PMAB440
|
|
Move.L A4,PrevEdge(A2) ; Edge^.PrevEdge := InsertPt AWC.PMAB440
|
|
Move.L NextEdge(A4),D0 ; save InsertPt^.NextEdge AWC.PMAB440
|
|
Move.L A2,NextEdge(A4) ; InsertPt^.NextEdge := Edge AWC.PMAB451
|
|
Move.L D0,NextEdge(A2) ; Edge^.NextEdge := InsertPt^.NextEdge AWC.PMAB440
|
|
Move.L D0,A4 ; InsertPt := InsertPt^.NextEdge AWC.PMAB440
|
|
Move.L A2,PrevEdge(A4) ; InsertPt^.NextEdge^.PrevEdge := Edge AWC.PMAB440
|
|
Bra.S InsertDone ; continue AWC.PMAB440
|
|
|
|
InsertEnd Move.L A2,NextEdge(A1) ; CurrentEdge^.NextEdge := Edge AWC.PMAB440
|
|
Move.L A1,PrevEdge(A2) ; Edge^.PrevEdge := CurrentEdge AWC.PMAB440
|
|
Clr.L NextEdge(A2) ; Edge^.NextEdge := nil AWC.PMAB440
|
|
Move.L A2,A1 ; CurrentEdge := Edge AWC.PMAB440
|
|
InsertDone AddA.L #VectorSize,A3 ; bump A3 to the next vector AWC.PMAB440
|
|
SubQ #1,D3 ; VCount := VCount - 1
|
|
Bgt NewEdgeLoop ; check for more edges
|
|
|
|
; Merge the NewEdges with the ActiveList
|
|
|
|
NoNewEdges Move.L #Nil,A1 ; CurrentEdge := nil
|
|
Move.L ActiveList(A6),A4 ; NextActive := ActiveList
|
|
MergeLoop Move.L A4,D0 ; CmpA.L #Nil,A4; is NextActive nil?
|
|
Bne.S NextOrMerge ; no => merge edges
|
|
Move.L A0,D0 ; CmpA.L #Nil,A0; is NewEdges nil?
|
|
Beq.S Merged ; yes => don't merge edges
|
|
|
|
; NextActive = nil; NewEdges <> nil
|
|
|
|
Move.L A1,PrevEdge(A0) ; NewEdges^.PrevEdge := CurrentEdge; is CurrentEdge nil?
|
|
Bne.S C1 ; no => fix up CurrentEdge^.NextEdge
|
|
Move.L A0,ActiveList(A6) ; ActiveList := NewEdges
|
|
Bra.S Merged ; continue
|
|
|
|
C1 Move.L A0,NextEdge(A1) ; CurrentEdge^.NextEdge := NewEdges
|
|
Bra.S Merged ; continue
|
|
|
|
; else if NewEdges = nil { and therefore NextActive <> nil } then begin
|
|
|
|
NextOrMerge Move.L A0,D0 ; CmpA.L #Nil,A0; is NewEdges nil?
|
|
Bne.S MergeEdges ; no => merge edges
|
|
Move.L A1,PrevEdge(A4) ; NextActive^.PrevEdge := CurrentEdge; is CurrentEdge nil?
|
|
Bne.S C2 ; no => append NextActive to the list
|
|
Move.L A4,ActiveList(A6) ; ActiveList := NextActive
|
|
Bra.S Merged ; continue
|
|
|
|
C2 Move.L A4,NextEdge(A1) ; CurrentEdge^.NextEdge := NextActive
|
|
Bra.S Merged ; continue
|
|
|
|
; else { both are still active so } begin
|
|
|
|
MergeEdges Move.L XValue(A4),D0 ; get NextActive^.XValue
|
|
Cmp.L XValue(A0),D0 ; is NextActive^.XValue > NewEdges^.XValue?
|
|
Ble.S C3 ; no => select NextActive
|
|
Move.L A0,A2 ; Edge := NewEdges
|
|
Move.L NextEdge(A2),A0 ; NewEdges := Edge^.NextEdge
|
|
Bra.S C4 ; continue
|
|
|
|
C3 Move.L A4,A2 ; Edge := NextActive
|
|
Move.L NextEdge(A2),A4 ; NextActive := Edge^.NextEdge
|
|
C4 Move.L A1,PrevEdge(A2) ; Edge^.PrevEdge := CurrentEdge; is CurrentEdge nil?
|
|
Bne.S C5 ; no => patch CurrentEdge
|
|
Move.L A2,ActiveList(A6) ; ActiveList := Edge
|
|
Bra.S C6 ; continue
|
|
|
|
C5 Move.L A2,NextEdge(A1) ; CurrentEdge^.NextEdge := Edge
|
|
C6 Clr.L NextEdge(A2) ; Edge^.NextEdge := nil
|
|
Move.L A2,A1 ; CurrentEdge := Edge
|
|
Bra.S MergeLoop ; continue
|
|
|
|
Merged
|
|
|
|
;;;;; More DrawArc craziness
|
|
|
|
CMP MINRECT+TOP(A6),D7 ;IS CURRENT VERT < MINV ?
|
|
BLT.S NoMask ;YES, DON'T DRAW
|
|
|
|
; SEEK MASK TO THE CURRENT VERTICAL
|
|
|
|
TST.B FASTFLAG(A6) ;RECT CLIPPED AND BLACK ?
|
|
BNE.S NOMASK ;YES, DON'T BOTHER WITH MASK
|
|
|
|
Jsr SeekMask ; make MaskBuf Current
|
|
|
|
NoMask Move.L ActiveList(A6),A4 ; NextActive := ActiveList
|
|
MoveQ #0,D5 ; LineFlag := false or WrapCount := 0
|
|
SlabLoop Move.L A4,A1 ; CurrentEdge := NextActive
|
|
Move.L NextEdge(A1),A4 ; NextActive := CurrentEdge^.NextEdge
|
|
Cmp LastY(A1),D7 ; is LastY <= CurrentY?
|
|
Bge RemoveEdge ; yes => go remove the edge
|
|
Move Sign(A1),D0 ; grab the sign
|
|
Beq.S DoToggle1 ; if zero then EoFill; toggle the flag
|
|
Tst D5 ; is current wrapcount 0?
|
|
Bne.S NoWrapMove ; no => don't establish WrapMove
|
|
Move XValue(A1),D6 ; save wrapmove
|
|
NoWrapMove Add D0,D5 ; WrapCount += Sign; is it 0?
|
|
Bne.S BumpX ; no => don't draw a line
|
|
NoLineMove Move XValue(A1),D0 ; grab current value
|
|
Cmp D6,D0 ; is line XValue.HiWord > move XValue.HiWord?
|
|
Bgt.S DrawLine ; yes => draw a line
|
|
Bra.S BumpX ; continue
|
|
|
|
DoToggle1 Eor #1,D5 ; toggle D5
|
|
Beq.S NoLineMove ; yes => go draw the line
|
|
Move XValue(A1),D6 ; save line mvoe
|
|
Bra.S BumpX ; continue
|
|
|
|
ONESLAB MOVEQ #$3F,D6 ;GET WRAP-AROUND MASK
|
|
AND PATINDEX(A6),D6 ;GET PATINDEX MOD 64
|
|
MOVE.L EXPAT(A6,D6),D6 ;GET THIS ROW'S PATTERN
|
|
LEA MaskTab,A0 ;POINT TO MASK TABLE
|
|
MOVE.L DSTLEFT(A6),A1 ;INIT DSTPTR TO LEFT
|
|
MOVE.L MASKBUF(A6),A2 ;INIT MASKPTR TO LEFT
|
|
LEA MINRECT(A6),A3 ;POINT TO MINRECT
|
|
MOVE.L MODECASE(A6),A4 ;GET MODE CASE JUMP
|
|
JMP DrawSlab
|
|
|
|
DrawLine CMP MINRECT+TOP(A6),D7 ;IS CURRENT VERT < MINV ?
|
|
Blt.S BumpX ;YES, DON'T DRAW
|
|
Move D6,D1 ; get start of slab
|
|
Move D0,D2 ; get end of slab
|
|
MoveM.L D3-D6/A1-A4,-(SP) ; save everything
|
|
Bsr.S OneSlab ; jump to ROM calling routine
|
|
MoveM.L (SP)+,D3-D6/A1-A4 ; restore everything
|
|
|
|
BumpX Move.L XValue(A1),D0 ; grab current XValue
|
|
Add.L XSlope(A1),D0 ; bump it to the next value
|
|
Move.L D0,XValue(A1) ; XValue := XValue + XSlope
|
|
Move.L PrevEdge(A1),A2 ; Edge := CurrentEdge^.PrevEdge
|
|
Move.L A2,D1 ; CmpA.L #Nil,A2; is Edge = nil?
|
|
Beq.S CheckEdge ; yes => sorting order is okay
|
|
Cmp.L XValue(A2),D0 ; is PrevEdge^.XValue <= CurrentEdge^.XValue?
|
|
Bge.S CheckEdge ; yes => sorting order is okay
|
|
Move.L NextEdge(A1),NextEdge(A2) ; PrevEdge^.NextEdge := CurrentEdge^.NextEdge; nil?
|
|
Beq.S NextIsNil ; yes => don't bother setting backlink
|
|
Move.L NextEdge(A1),A0 ; grab the next edge
|
|
Move.L A2,PrevEdge(A0) ; NextEdge^.PrevEdge := CurrentEdge^.PrevEdge
|
|
|
|
NextIsNil Move.L PrevEdge(A2),A2 ; Edge := Edge^.PrevEdge
|
|
Move.L A2,D1 ; CmpA.L #Nil,A2; is it nil?
|
|
Bne.S CheckCross ; no => check for crossing
|
|
Move.L ActiveList(A6),A2 ; get NextEdge
|
|
Move.L A2,NextEdge(A1) ; CurrentEdge^.NextEdge := ActiveList
|
|
Clr.L PrevEdge(A1) ; PrevEdge := nil
|
|
Move.L A1,PrevEdge(A2) ; NextEdge^.PrevEdge := CurrentEdge
|
|
Move.L A1,ActiveList(A6) ; ActiveList := CurrentEdge
|
|
Bra.S CheckEdge ; continue
|
|
|
|
CheckCross Cmp.L XValue(A2),D0 ; is Edge^.XValue <=CurrentEdge^.XValue?
|
|
Blt.S NextIsNil ; no => continue searching
|
|
Move.L NextEdge(A2),A0 ; grab NextEdge
|
|
Move.L A0,NextEdge(A1) ; CurrentEdge^.NextEdge := Edge^.NextEdge
|
|
Move.L A2,PrevEdge(A1) ; CurrentEdge^.PrevEdge := Edge
|
|
Move.L A1,PrevEdge(A0) ; CurrentEdge^.NextEdge^.PrevEdge := CurrentEdge
|
|
Move.L A1,NextEdge(A2) ; Edge^.NextEdge := CurrentEdge
|
|
Bra.S CheckEdge ; continue
|
|
|
|
RemoveEdge Move.L PrevEdge(A1),A0 ; grab PrevEdge
|
|
Move.L A0,D0 ; CmpA.L #Nil,A0; is PrevEdge nil?
|
|
Bne.S PrevNotNil ; no => remove from middle
|
|
Move.L NextEdge(A1),ActiveList(A6) ; ActiveList := CurrentEdge^.NextEdge
|
|
Bra.S PrevWasNil ; continue
|
|
|
|
PrevNotNil Move.L NextEdge(A1),NextEdge(A0) ; PrevEdge^.NextEdge := CurrentEdge^.NextEdge
|
|
PrevWasNil Beq.S NextWasNil ; if NextEdge is nil, don't patch back pointer
|
|
Move.L NextEdge(A1),A2 ; grab NextEdge
|
|
Move.L A0,PrevEdge(A2) ; NextEdge^.PrevEdge := CurrentEdge^.PrevEdge
|
|
NextWasNil Move.L FreeList(A6),NextEdge(A1) ; CurrentEdge^.NextEdge := FreeList
|
|
Move.L A1,FreeList(A6) ; FreeList := CurrentEdge
|
|
Move.L A0,A1 ; CurrentEdge := CurrentEdge^.PrevEdge
|
|
|
|
CheckEdge Move.L A4,D0 ; CmpA.L #Nil,A4; is NextActive nil?
|
|
Bne SlabLoop ; no => do another edge
|
|
|
|
CMP MINRECT+TOP(A6),D7 ;IS CURRENT VERT < MINV ?
|
|
Blt.S BumpY ;YES, DON'T DRAW
|
|
|
|
;-------------------------------------------------------------------
|
|
;
|
|
; BUMP DESTINATION VERTICALLY AND LOOP FOR ALL SCAN LINES
|
|
;
|
|
NEXTPAT ADD #4,PATINDEX(A6) ;BUMP PATTERN INDEX
|
|
MOVE PORTBITS+ROWBYTES(A5),D0 ;GET DST ROWBYTES
|
|
EXT.L D0 ;MAKE IT LONG
|
|
ADD.L D0,DSTLEFT(A6) ;BUMP DST TO NEXT ROW
|
|
|
|
BumpY AddQ #1,D7 ; CurrentY += 1
|
|
Cmp MinRect+Bottom(A6),D7 ; have we reached the bottom?
|
|
Bge.S NoMorePoly ; yes => shut down ahead of schedule
|
|
|
|
Tst.L ActiveList(A6) ; does the ActiveList contain edges?
|
|
Bne ActiveLoop ; yes => loop
|
|
Tst D3 ; any new edges left?
|
|
Bne ActiveLoop ; yes => loop
|
|
|
|
NoMorePoly _ShowCursor ; restore cursor
|
|
GoHome Move.L SaveStk(A6),SP ; clean up the free list and strip buffer
|
|
MoveM.L (SP)+,D0-D7/A1-A5 ; restore registers
|
|
UNLINK PARAMSIZE,'PAINTVEC'
|
|
|
|
;-----------------------------------------------------------------------------
|
|
; <1.2/15mar89> Seekmask code copied from DrawArc which is what QuickPolys used.
|
|
|
|
;-----------------------------------------------------------------------------
|
|
;
|
|
; LOCAL ROUTINE TO UPDATE THE MASK BUFFER
|
|
; BASED ON WHICH REGIONS ARE RECTANGULAR
|
|
;
|
|
SEEKMASK MOVE D7,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
|
|
|
|
|
|
;---------------------------------------------------
|
|
;
|
|
; PROCEDURE DrawPoly(poly: PolyHandle; mode: integer; VAR pat: Pattern);
|
|
;
|
|
|
|
DrawPoly PROC EXPORT
|
|
IMPORT DrawRect
|
|
|
|
ParamSize Equ 10
|
|
Poly Equ ParamSize+8-4
|
|
Mode Equ Poly-2
|
|
Pat Equ Mode-4
|
|
|
|
PolyRect Equ -8
|
|
VarSize Equ PolyRect
|
|
|
|
; <25Jul88> PMAB543 BAL/JDB Implemented fast case for rectangular filled polys.
|
|
Link A6,#VarSize ; no local variables
|
|
|
|
move.l Poly(a6),a0 ; pick up polyhdl <Begin PMAB543 BAL/JDB>
|
|
move.l (a0),a0 ; deref to polyptr
|
|
move (a0)+,d0 ; pick up byte count
|
|
cmp #4*5+10,d0 ; quadrilateral?
|
|
bne.s @chk4pt ; no, take general case
|
|
move.l 8+4*4(a0),d1 ; pick up last pnt
|
|
cmp.l 8(a0),d1 ; cmpare with first pnt
|
|
bne.s @notRect ;
|
|
bra.s @4Pnts
|
|
|
|
@chk4pt cmp #4*4+10,d0 ; quadrilateral?
|
|
bne.s @notRect ; no, take general case
|
|
@4Pnts moveq #2,d0 ; force to 4 points
|
|
addq #8,a0 ; bump past rect
|
|
lea 4(a0),a1 ; point to next point
|
|
@nxtPnt cmp (a0)+,(a1)+ ; cmp h's
|
|
seq d1 ; remember equality
|
|
cmp (a0)+,(a1)+ ; cmp v's
|
|
seq d2 ; remember equality
|
|
or.b d1,d2 ; compute h1=h2 | v1=v2
|
|
beq.s @notRect ; no, not rect
|
|
dbra d0,@nxtPnt
|
|
|
|
lea -12(a0),a1 ; point to first point
|
|
cmp (a0)+,(a1)+ ; cmp h's
|
|
seq d1 ; remember equality
|
|
cmp (a0)+,(a1)+ ; cmp v's
|
|
seq d2 ; remember equality
|
|
or.b d1,d2 ; compute h1=h2 | v1=v2
|
|
beq.s @notRect ; no, not rect
|
|
lea PolyRect(A6),a0 ; point to rect
|
|
move.l -12(a1),(a0)+ ; save top left
|
|
move.l -8(a1),(a0) ; save bot rght
|
|
pea PolyRect(A6) ; push ptr to rect
|
|
move Mode(A6),-(SP) ; push mode
|
|
move.l Pat(A6),-(SP) ; push pattern
|
|
jsr DrawRect ; go so incredibly blindingly fast <End PMAB543 BAL/JDB>
|
|
bra GoHome2 ; get out of here, undoing the link
|
|
|
|
@notRect
|
|
|
|
MoveM.L D3-D5/A2,-(SP) ; save registers
|
|
Move.L GrafGlobals(A5),A0 ; point to QuickDraw globals
|
|
Move.L ThePort(A0),A0 ; get current port
|
|
Tst PnVis(A0) ; is PnVis neg ?
|
|
Bmi GoHome ; yes, quit AWC.PMAB444
|
|
Move.L Poly(A6),A0 ; get the poly handle
|
|
Move.L A0,D0 ; CmpA.L #Nil,A0; is it real?
|
|
Beq GoHome ; no => punt AWC.PMAB444
|
|
_HLock ; lock it down
|
|
Move.L (A0),A0 ; dereference poly
|
|
Move.L 2(A0),PolyRect(A6) ; move Top.Left
|
|
Move.L 6(A0),PolyRect+4(A6) ; move Bottom.Right
|
|
Move (A0),D4 ; get the length of the data
|
|
Sub #10,D4 ; remove the length word and the bounding box rect
|
|
Lsr #2,D4 ; D4 is temporarily the point count
|
|
MoveQ #0,D0 ; clear the high word
|
|
Move D4,D0 ; copy the number of points
|
|
AddQ.L #1,D0 ; bump it for the closing edge, maybe
|
|
Asl.L #3,D0 ; multiply by 8 bytes per edge
|
|
_NewHandle ; get a new handle
|
|
Tst D0 ; was there an error? AWC.PMAB444
|
|
Bne TempError ; yes => cleanup and get out of here AWC.PMAB444
|
|
Move.L A0,A2 ; copy it
|
|
_HLock ; lock it down
|
|
MoveQ #0,D3 ; clear VCount
|
|
Move.L Poly(A6),A1 ; get the handle again
|
|
Move.L (A1),A1 ; redereference it
|
|
AddA.L #polyPoints,A1 ; bump A1 to the first point
|
|
Move.L (A1)+,D5 ; get h and v for "old" position
|
|
Move D4,D2 ; copy loop counter to D2
|
|
SubQ.L #1,D2 ; remove the first point
|
|
Move.L (A2),A0 ; dereference the sorted edge list
|
|
Bra.S PolyEnd ; jump into the loop
|
|
|
|
PolyLoop Move.L D5,D4 ; copy current to old
|
|
Move.L (A1)+,D5 ; get next point
|
|
Move.L D4,D0 ; get the old point
|
|
Move.L D5,D1 ; copy the new point
|
|
Sub D0,D1 ; calculate XDelta
|
|
Swap D0 ; y1 is in D0.Low
|
|
Swap D1 ; y2 is in D1.Low
|
|
Sub D0,D1 ; calculate YDelta; does dy = 0?
|
|
Beq.S PolyEnd ; yes => ignore horizontal vectors
|
|
Bmi.S Upwards ; negative => save the new point
|
|
Move.L D4,(A0)+ ; save the old point
|
|
Bra.S IncVCount ; and continue
|
|
|
|
Upwards Move.L D5,(A0)+ ; save the new point
|
|
IncVCount AddQ #1,D3 ; bump VCount (D3)
|
|
Swap D1 ; XDelta:YDelta => YDelta:XDelta
|
|
Move.L D1,(A0)+ ; save YDelta:XDelta
|
|
PolyEnd DBra D2,PolyLoop ; loop for another poly point
|
|
|
|
Move.L D5,D4 ; save the new point to old
|
|
Move.L Poly(A6),A1 ; get poly handle again
|
|
Move.L (A1),A1 ; dereference it again
|
|
Move.L polyPoints(A1),D5 ; grab the first point again
|
|
Cmp.L D4,D5 ; did we end where we began?
|
|
Beq.S PolyDone ; yes => don't close it
|
|
|
|
Move.L D4,D0 ; get the old point
|
|
Move.L D5,D1 ; copy the new point
|
|
Sub D0,D1 ; calculate XDelta
|
|
Swap D0 ; y1 is in D0.Low
|
|
Swap D1 ; y2 is in D1.Low
|
|
Sub D0,D1 ; calculate YDelta; does dy = 0?
|
|
Beq.S PolyDone ; yes => ignore horizontal vectors
|
|
Bmi.S Upwards2 ; positive => use the old point
|
|
Move.L D4,(A0)+ ; save the old point
|
|
Bra.S IncVCount2 ; and continue
|
|
|
|
Upwards2 Move.L D5,(A0)+ ; save the new point
|
|
IncVCount2 AddQ #1,D3 ; bump VCount (D4)
|
|
Swap D1 ; XDelta:YDelta => YDelta:XDelta
|
|
Move.L D1,(A0)+ ; save deltas
|
|
PolyDone Move.L Poly(A6),A0 ; grab poly handle
|
|
_HUnlock ; unlock it
|
|
Move.L (A2),-(SP) ; push vectors pointer
|
|
Move D3,-(SP) ; push VCount
|
|
Jsr SortVectors ; sort them vectors
|
|
Move.L (A2),-(SP) ; push vectors pointer
|
|
Move D3,-(SP) ; push VCount
|
|
; Tst.B WnFill(A6) ; are we winding-number filling?
|
|
; Seq -(SP) ; push (not WnFill)
|
|
St -(SP) ; push EoFill
|
|
Pea PolyRect(A6) ; push rect
|
|
Move Mode(A6),-(SP) ; repush mode
|
|
Move.L Pat(A6),-(SP) ; repush pat
|
|
Jsr PaintVector ; go paint it
|
|
Move.L A2,A0 ; grab vectors handle
|
|
_HUnlock ; unlock it
|
|
Move.L A2,A0 ; grab it again
|
|
_DisposHandle ; dump it
|
|
Bra.S GoHome ; continue AWC.PMAB444
|
|
|
|
TempError Move.L Poly(A6),A0 ; grab poly handle AWC.PMAB444
|
|
_HUnlock ; unlock it AWC.PMAB444
|
|
GoHome MoveM.L (SP)+,D3-D5/A2 ; restore registers AWC.PMAB444
|
|
GoHome2 UNLINK PARAMSIZE,'DRAWPOLY'
|
|
|
|
|
|
|
|
|
|
ELSE ; <1.2/15mar89> Use original DrawPoly rtn
|
|
;--------------------------------------------------------
|
|
; <1.2/15mar89> THIS IS THE ORIGINAL DrawPoly CODE
|
|
|
|
DrawPoly PROC EXPORT
|
|
IMPORT OpenRgn,FrPoly,DoLine,NewRgn,CloseRgn,DrawRgn
|
|
;--------------------------------------------------------
|
|
;
|
|
; PROCEDURE DrawPoly(poly: PolyHandle; mode: INTEGER; VAR pat: Pattern);
|
|
;
|
|
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
|
|
;
|
|
PARAMSIZE EQU 10
|
|
POLY EQU PARAMSIZE+8-4 ;LONG, POLYHANDLE
|
|
MODE EQU POLY-2 ;WORD
|
|
PAT EQU MODE-4 ;LONG, ADDR OF PATTERN
|
|
|
|
LINK A6,#0 ;NO LOCAL VARS
|
|
MOVE.L A4,-(SP) ;SAVE REG
|
|
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
|
|
MOVE.L THEPORT(A0),A0 ;GET CURRENT PORT
|
|
TST PNVIS(A0) ;IS PNVIS NEG ?
|
|
BMI.S DONE ;YES, QUIT
|
|
JSR OPENRGN ;OpenRgn
|
|
MOVE.L POLY(A6),-(SP)
|
|
JSR FRPOLY ;FrPoly(poly);
|
|
MOVE.L POLY(A6),A0
|
|
MOVE.L (A0),A0
|
|
MOVE.L 10(A0),-(SP) ;PUSH FIRST POINT
|
|
JSR DOLINE ;MAKE SURE IT CLOSES
|
|
CLR.L -(SP) ;ROOM FOR FCN RESULT
|
|
JSR NEWRGN ;ALLOCATE TEMPRGN
|
|
MOVE.L (SP),A4 ;PUT TEMPRGN IN A4
|
|
JSR CLOSERGN ;CLOSERGN(TEMPRGN)
|
|
MOVE.L A4,-(SP)
|
|
MOVE MODE(A6),-(SP)
|
|
MOVE.L PAT(A6),-(SP)
|
|
JSR DRAWRGN ;DrawRgn(tempRgn,mode,pat);
|
|
MOVE.L A4,A0 ;get tempRgn
|
|
_DisposHandle ;DISCARD IT
|
|
DONE MOVEM.L (SP)+,A4 ;RESTORE REG
|
|
UNLINK PARAMSIZE,'DRAWPOLY'
|
|
|
|
ENDIF ;<1.2/15mar89> QuickPolys
|
|
|
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|