mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-27 22:51:28 +00:00
2187 lines
66 KiB
Plaintext
2187 lines
66 KiB
Plaintext
|
;
|
|||
|
; File: Regions.a
|
|||
|
;
|
|||
|
; Contains: QuickDraw routines to operate on regions.
|
|||
|
;
|
|||
|
; Copyright: © 1981-1992 by Apple Computer, Inc., all rights reserved.
|
|||
|
;
|
|||
|
; Change History (most recent first):
|
|||
|
;
|
|||
|
; <SM4> 1/25/93 kc Roll in Shannon Holland's alpha channel fix to DrawRgn.
|
|||
|
; <SM3> 6/11/92 stb <sm 6/9/92>stb Synch with QDciPatchROM.a; comments added to
|
|||
|
; StdRgn, MapRgn
|
|||
|
; <SM2> 5/21/92 kc Change the name of QuickDraws wrapper for NewHandle to
|
|||
|
; NewHandleWrapper to avoid name conflict with the glue.
|
|||
|
; <10> 8/22/91 JSM Don’t use TRUE and FALSE as labels.
|
|||
|
; <9> 7/23/91 KON Fix 32-bit clean crimes in BitMapRgn.
|
|||
|
; <8> 10/30/90 KON Forgot to make all the changes before checking in; This updates
|
|||
|
; to the current version on the ci in QDciPatch. [SMC]
|
|||
|
; <7> 10/30/90 KON Make pmVersion=4 pixmaps work and create rgns as large as 64K
|
|||
|
; (not 32K).
|
|||
|
; <6> 9/7/90 KON Fix misleading comment and enter Comment of the Week contest.
|
|||
|
; <5> 9/7/90 KON Don't remap wideopen rectangular regions since maprect will blow
|
|||
|
; up.
|
|||
|
; <4> 8/28/90 KON Remove benign redefinition of pixmapTooDeepErr (-148) which is
|
|||
|
; now defined in SysErr.a.
|
|||
|
; <3> 8/2/90 gbm change TEMPRECT to TEMPRECTANGLE to avoid global conflict
|
|||
|
; <2> 7/24/90 gbm axe duplicate defs
|
|||
|
; <•1.6> 7/14/89 BAL For Aurora: Final CQD
|
|||
|
; <1.5> 6/30/89 BAL Now uses equate for qdStackXtra
|
|||
|
; <•1.4> 5/29/89 BAL Blasting in 32-Bit QuickDraw version 1.0 Final
|
|||
|
; 9/26/88 BAL Provided RectWithinRgn, a variant of TrimRect
|
|||
|
; 9/25/88 BAL Rewrote TrimRect for a better than 5X performance improvement
|
|||
|
; 11/8/87 DAF Fixed pict opcode recorded by StdRgn
|
|||
|
; 6/4/87 CRC set patMode even if user forgets to
|
|||
|
; 1/3/87 CRC pass color param to stretch
|
|||
|
; 10/9/86 EHB Added mask parameters to stretchbits calls
|
|||
|
; 9/5/86 EHB Added FillCRgn
|
|||
|
; 8/16/86 EHB In FillRgn added support for color grafports
|
|||
|
; 6/18/86 EHB Fixed up references to PortBits in DrawRgn for color ports Call
|
|||
|
; StretchBits instead of RgnBlt
|
|||
|
;
|
|||
|
|
|||
|
BLANKS ON
|
|||
|
STRING ASIS
|
|||
|
|
|||
|
;-----------------------------------------------------------
|
|||
|
;
|
|||
|
;
|
|||
|
; **** ***** *** *** *** * * ***
|
|||
|
; * * * * * * * * * * * *
|
|||
|
; * * * * * * * ** * *
|
|||
|
; **** *** * ** * * * * * * ***
|
|||
|
; * * * * * * * * * ** *
|
|||
|
; * * * * * * * * * * * *
|
|||
|
; * * ***** *** *** *** * * ***
|
|||
|
;
|
|||
|
;-----------------------------------------------------------
|
|||
|
|
|||
|
StdRgn PROC EXPORT
|
|||
|
IMPORT PutPicVerb,DPutPicOp,PutPicRgn
|
|||
|
IMPORT PutRgn,FrRgn,PushVerb,DrawRgn,StdDevLoop
|
|||
|
;---------------------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE StdRgn(verb: GrafVerb; rgn: RgnHandle);
|
|||
|
;
|
|||
|
; A6 OFFSETS OF PARAMS AFTER LINK:
|
|||
|
;
|
|||
|
; has fix from QDciPatchROM.a <sm 6/9/92>stb
|
|||
|
|
|||
|
PARAMSIZE EQU 6
|
|||
|
VERB EQU PARAMSIZE+8-2 ;GRAFVERB
|
|||
|
RGN EQU VERB-4 ;LONG, RGNHANDLE
|
|||
|
|
|||
|
LINK A6,#0 ;NO LOCALS
|
|||
|
MOVEM.L D6-D7/A2-A4,-(SP) ;SAVE REGS
|
|||
|
MOVEQ #0,D7 ;CLEAR LOWORD OF PICT OPCODE <C952/08Nov87> DAF
|
|||
|
MOVE.B VERB(A6),D7 ;GET VERB
|
|||
|
_CheckPic ;SET UP A4,A3 AND CHECK PICSAVE
|
|||
|
BLE.S NOTPIC ;BRANCH IF NOT PICSAVE
|
|||
|
|
|||
|
MOVE.B D7,-(SP) ;PUSH VERB
|
|||
|
JSR PutPicVerb ;PUT ADDITONAL PARAMS TO THEPIC
|
|||
|
MOVE #$80,D0 ;PUT RGNNOUN IN HI NIBBLE
|
|||
|
ADD D7,D0 ;PUT VERB IN LO NIBBLE
|
|||
|
JSR DPutPicOp ;PUT OPCODE TO THEPIC
|
|||
|
MOVE.L RGN(A6),-(SP) ;PUSH RGNHANDLE
|
|||
|
JSR PutPicRgn ;PUT REGION TO THEPIC
|
|||
|
|
|||
|
; CALL STANDARD LOOP TO DRAW TO ALL DEVICES
|
|||
|
|
|||
|
NOTPIC PEA StdDraw ;PUSH ADDRESS OF DRAW ROUTINE
|
|||
|
PEA GetRect ;PUSH ADDRESS OF RECT ROUTINE
|
|||
|
_StdDevLoop ;DRAW TO ALL DEVICES
|
|||
|
|
|||
|
GOHOME MOVEM.L (SP)+,D6-D7/A2-A4 ;RESTORE REGS
|
|||
|
UNLINK PARAMSIZE,'STDRGN '
|
|||
|
|
|||
|
|
|||
|
;---------------------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE GetRect(VAR theRect: rect);
|
|||
|
;
|
|||
|
; RETURN THE OBJECT'S RECTANGLE
|
|||
|
;
|
|||
|
GetRect MOVE.L (SP)+,D0 ;GET RETURN ADDRESS
|
|||
|
MOVE.L (SP)+,A1 ;GET DST RECT
|
|||
|
MOVE.L RGN(A6),A0 ;GET REGION
|
|||
|
MOVE.L (A0),A0 ;POINT AT IT
|
|||
|
LEA RGNBBOX(A0),A0 ;POINT TO BOUNDING BOX
|
|||
|
MOVE.L (A0)+,(A1)+ ;SET TOPLEFT
|
|||
|
MOVE.L (A0),(A1) ;SET BOTRIGHT
|
|||
|
MOVE.L D0,A0 ;GET RETURN ADDRESS
|
|||
|
JMP (A0) ;AND RETURN
|
|||
|
|
|||
|
|
|||
|
;---------------------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE StdDraw;
|
|||
|
;
|
|||
|
; DRAW THE OBJECT
|
|||
|
;
|
|||
|
StdDraw MOVE.L RGN(A6),-(SP) ;PUSH RGNHANDLE
|
|||
|
_PushVerb ;PUSH MODE AND PATTERN
|
|||
|
TST.B D7 ;IS VERB FRAME ?
|
|||
|
BNE.S NOTFR ;NO, CONTINUE
|
|||
|
TST.L RGNSAVE(A3) ;YES, IS RGNSAVE TRUE ?
|
|||
|
BEQ.S NOTRGN ;NO, CONTINUE
|
|||
|
MOVE.L RGN(A6),-(SP) ;YES, PUSH RGNHANDLE
|
|||
|
MOVE.L RGNBUF(A4),-(SP) ;PUSH RGNBUF
|
|||
|
PEA RGNINDEX(A4) ;PUSH VAR RGNINDEX
|
|||
|
PEA RGNMAX(A4) ;PUSH VAR RGNMAX
|
|||
|
_PutRgn ;ADD INVERSION PTS TO THERGN
|
|||
|
|
|||
|
NOTRGN JSR FrRgn ;FrRgn(rgn,pnMode,pnPat)
|
|||
|
BRA.S drawDone
|
|||
|
|
|||
|
NOTFR JSR DrawRgn ;DrawRgn(rgn,mode,pat);
|
|||
|
drawDone
|
|||
|
DONE RTS
|
|||
|
|
|||
|
|
|||
|
|
|||
|
FrameRgn PROC EXPORT
|
|||
|
EXPORT CallRgn,PaintRgn,EraseRgn,InvertRgn,FillRgn,FillCRgn
|
|||
|
IMPORT SetFillPat
|
|||
|
;-----------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE FrameRgn(* rgn: RgnHandle *);
|
|||
|
;
|
|||
|
MOVEQ #FRAME,D0 ;VERB = FRAME
|
|||
|
BRA.S CallRgn ;SHARE COMMON CODE
|
|||
|
|
|||
|
|
|||
|
;-----------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE PaintRgn(* rgn: RgnHandle *);
|
|||
|
;
|
|||
|
PaintRgn
|
|||
|
MOVEQ #PAINT,D0 ;VERB = PAINT
|
|||
|
BRA.S CallRgn ;SHARE COMMON CODE
|
|||
|
|
|||
|
|
|||
|
;--------------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE EraseRgn(* rgn: RgnHandle *);
|
|||
|
;
|
|||
|
EraseRgn
|
|||
|
MOVEQ #ERASE,D0 ;VERB = ERASE
|
|||
|
BRA.S CallRgn ;SHARE COMMON CODE
|
|||
|
|
|||
|
|
|||
|
;--------------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE InvertRgn(* rgn: RgnHandle *);
|
|||
|
;
|
|||
|
InvertRgn
|
|||
|
MOVEQ #INVERT,D0 ;VERB = INVERT
|
|||
|
BRA.S CallRgn ;SHARE COMMON CODE
|
|||
|
|
|||
|
|
|||
|
;--------------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE FillRgn(* rgn: RgnHandle; pat: Pattern *);
|
|||
|
;
|
|||
|
FillRgn MOVEQ #0,D0 ;FLAG = FillRgn
|
|||
|
BRA.S SHARE ; => USE COMMON CODE
|
|||
|
|
|||
|
|
|||
|
;----------------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE FillCRgn(rgn: RgnHandle; PPH: PixPatHandle);
|
|||
|
;
|
|||
|
FillCRgn MOVEQ #1,D0 ;FLAG = FillCRgn
|
|||
|
|
|||
|
SHARE 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 A1,-(SP) ;PUSH ADDR OF PATTERN
|
|||
|
_SETFILLPAT ;FILLPAT := PAT
|
|||
|
MOVEQ #FILL,D0 ;VERB = FILL
|
|||
|
; BRA.S CallRgn ;SHARE COMMON CODE
|
|||
|
|
|||
|
|
|||
|
|
|||
|
;---------------------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE CallRgn(rgn: RgnHandle);
|
|||
|
;
|
|||
|
; code shared by FrameRgn, PaintRgn, EraseRgn, InvertRgn, and FillRgn.
|
|||
|
; enter with verb in D0.
|
|||
|
;
|
|||
|
CallRgn
|
|||
|
MOVE.L (SP)+,A0 ;POP RETURN ADDR
|
|||
|
MOVE.L (SP)+,A1 ;POP RGN
|
|||
|
MOVE.B D0,-(SP) ;PUSH VERB
|
|||
|
MOVE.L A1,-(SP) ;PUSH RGN
|
|||
|
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 JStdRgn,A0 ;get piece of trap table
|
|||
|
BEQ.S USESTD ;YES, USE STD PROC
|
|||
|
MOVE.L D0,A0
|
|||
|
MOVE.L RGNPROC(A0),A0 ;NO, GET PROC PTR
|
|||
|
USESTD JMP (A0) ;GO TO IT
|
|||
|
|
|||
|
|
|||
|
DrawRgn PROC EXPORT
|
|||
|
IMPORT STRETCHBITS
|
|||
|
IMPORT PortToMap
|
|||
|
;--------------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE DrawRgn(rgn: RgnHandle; mode: INTEGER; pat: Pattern);
|
|||
|
;
|
|||
|
; A6 OFFSETS OF PARAMS AFTER LINK:
|
|||
|
;
|
|||
|
PARAMSIZE EQU 10
|
|||
|
RGN EQU PARAMSIZE+8-4 ;LONG, RGNHANDLE
|
|||
|
MODE EQU RGN-2 ;WORD
|
|||
|
PAT EQU MODE-4 ;LONG, ADDR OF PATTERN
|
|||
|
|
|||
|
BBOX EQU -8 ;LOCAL COPY OF RGNBBOX
|
|||
|
VARSIZE EQU BBOX ;SIZE OF LOCALS
|
|||
|
|
|||
|
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
|
|||
|
MOVE.L RGN(A6),A0 ;GET THE REGION HANDLE
|
|||
|
MOVE.L (A0),A0 ;POINT TO THE RGN
|
|||
|
MOVE.L RGNBBOX(A0),BBOX(A6) ;COPY RGNBBOX.TOPLEFT
|
|||
|
MOVE.L RGNBBOX+4(A0),BBOX+4(A6) ;COPY RGNBBOX.BOTRIGHT
|
|||
|
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO LISAGRAF GLOBALS
|
|||
|
MOVE.L THEPORT(A0),A0 ;GET CURRENT PORT
|
|||
|
TST PNVIS(A0) ;IS PNVIS NEG ?
|
|||
|
BMI.S DONE ;YES, QUIT
|
|||
|
MOVE.L A0,A1 ;SAVE A COPY
|
|||
|
_PORTTOMAP ;GET BIT/PIXMAP IN A0
|
|||
|
MOVE.L A0,-(SP) ;PUSH SRCBITS
|
|||
|
CLR.L -(SP) ;NO MASKBITS
|
|||
|
MOVE.L A0,-(SP) ;PUSH DSTBITS
|
|||
|
PEA BBOX(A6) ;PUSH SRCRECT
|
|||
|
CLR.L -(SP) ;NO MASKRECT
|
|||
|
PEA BBOX(A6) ;PUSH DSTRECT
|
|||
|
MOVE MODE(A6),D1 ;PUSH MODE ; <SM4>
|
|||
|
OR #$8,D1 ;set the pattern bit in case the user forgot to ; <SM4>
|
|||
|
_GetStreamMode ;strip mode ; <SM4>
|
|||
|
MOVE.W D1,-(SP) ;save stripped mode ; <SM4>
|
|||
|
MOVE.L PAT(A6),-(SP) ;PUSH PAT
|
|||
|
MOVE.L CLIPRGN(A1),-(SP) ;PUSH CLIPRGN
|
|||
|
MOVE.L VISRGN(A1),-(SP) ;PUSH VISRGN
|
|||
|
MOVE.L RGN(A6),-(SP) ;PUSH RGN
|
|||
|
CLR -(SP) ;pass multicolor flag false
|
|||
|
_STRETCHBITS ;CALL STRETCHBITS
|
|||
|
DONE UNLINK PARAMSIZE,'DRAWRGN '
|
|||
|
|
|||
|
|
|||
|
|
|||
|
FrRgn PROC EXPORT
|
|||
|
IMPORT FrmRect,NewRgn,CopyRgn,InsetRgn,DiffRgn,DrawRgn
|
|||
|
;--------------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE FrRgn(rgn: RgnHandle; mode: INTEGER; pat: Pattern);
|
|||
|
;
|
|||
|
; A6 OFFSETS OF PARAMS AFTER LINK:
|
|||
|
;
|
|||
|
PARAMSIZE EQU 10
|
|||
|
RGN EQU PARAMSIZE+8-4 ;LONG, RGNHANDLE
|
|||
|
MODE EQU RGN-2 ;WORD
|
|||
|
PAT EQU MODE-4 ;LONG, ADDR OF PATTERN
|
|||
|
|
|||
|
LINK A6,#0
|
|||
|
MOVEM.L D7/A3-A4,-(SP) ;SAVE REGS
|
|||
|
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO LISAGRAF GLOBALS
|
|||
|
MOVE.L THEPORT(A4),A3 ;GET CURRENT PORT
|
|||
|
TST PNVIS(A3) ;IS PNVIS NEG ?
|
|||
|
BMI.S DONE ;YES, QUIT
|
|||
|
;
|
|||
|
; special case rectangular region for speed.
|
|||
|
;
|
|||
|
MOVE.L RGN(A6),A0 ;GET RGNHANDLE
|
|||
|
MOVE.L (A0),A0 ;DE-REFERENCE IT
|
|||
|
CMP #10,RGNSIZE(A0) ;IS IT RECTANGULAR ?
|
|||
|
BNE.S NOTRECT ;NO, CONTINUE
|
|||
|
PEA RGNBBOX(A0) ;YES, PUSH ADDR OF BBOX
|
|||
|
bsr.l FRMRECT ;FRAME IT
|
|||
|
BRA.S DONE ;AND QUIT
|
|||
|
|
|||
|
NOTRECT CLR.L -(SP) ;MAKE ROOM FOR FCN RESULT
|
|||
|
_NEWRGN ;ALLOCATE TEMPRGN
|
|||
|
MOVE.L (A7)+,D7 ;PUT TEMPRGN IN D7
|
|||
|
MOVE.L RGN(A6),-(SP) ;PUSH RGN
|
|||
|
MOVE.L D7,-(SP) ;PUSH TEMPRGN
|
|||
|
_COPYRGN ;COPY RGN INTO TEMPRGN
|
|||
|
MOVE.L D7,-(SP) ;PUSH TEMPRGN
|
|||
|
MOVE.L PNSIZE(A3),-(SP) ;PUSH PNSIZE
|
|||
|
_INSETRGN ;InsetRgn(tempRgn,pnSize);
|
|||
|
MOVE.L RGN(A6),-(SP) ;PUSH RGN
|
|||
|
MOVE.L D7,-(SP) ;PUSH TEMPRGN
|
|||
|
MOVE.L D7,-(SP) ;PUSH TEMPRGN
|
|||
|
_DIFFRGN ;DiffRgn(rgn,tempRgn,tempRgn);
|
|||
|
MOVE.L D7,-(SP) ;PUSH TEMPRGN
|
|||
|
MOVE MODE(A6),-(SP) ;PUSH MODE
|
|||
|
MOVE.L PAT(A6),-(SP) ;PUSH PAT
|
|||
|
JSR DRAWRGN ;DrawRgn(tempRgn,mode,pat);
|
|||
|
MOVE.L D7,A0 ;GET TEMPRGN
|
|||
|
_DisposHandle ;DISCARD IT
|
|||
|
DONE MOVEM.L (SP)+,D7/A3-A4 ;RESTORE REGS
|
|||
|
UNLINK PARAMSIZE,'FRRGN '
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NewRgn FUNC EXPORT
|
|||
|
IMPORT NewHandleWrapper
|
|||
|
;---------------------------------------------------
|
|||
|
;
|
|||
|
; FUNCTION NewRgn;
|
|||
|
; Allocate a new region and set it to the empty region.
|
|||
|
; Altered not to SysErr; if memerr then return nil. <BAL/dvb/RAJ 03Mar89>
|
|||
|
;
|
|||
|
moveq #10,d0 ;pass BYTECOUNT=10
|
|||
|
_NewHandle ;ALLOCATE A RELOCATABLE OBJECT
|
|||
|
MOVE.L A0,4(SP) ;STORE INTO NEWRGN RESULT
|
|||
|
tst.w d0
|
|||
|
bne.s @retNil ;if couldn't get it, return nil
|
|||
|
MOVE.L (A0),A0 ;DE-REFERENCE HANDLE
|
|||
|
MOVE #10,(A0)+ ;INSTALL RGNSIZE=10
|
|||
|
CLR.L (A0)+ ;INSTALL RGNBBOX=(0,0,0,0)
|
|||
|
CLR.L (A0)+
|
|||
|
@retNil RTS ;RETURN TO CALLER
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DisposeRgn PROC EXPORT
|
|||
|
;---------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE DisposeRgn(rgn: RgnHandle);
|
|||
|
;
|
|||
|
MOVE.L (SP)+,A1 ;pop return addr
|
|||
|
MOVE.L (SP)+,A0 ;pop handle
|
|||
|
_DisposHandle ;discard it
|
|||
|
JMP (A1) ;and return
|
|||
|
|
|||
|
|
|||
|
|
|||
|
OpenRgn PROC EXPORT
|
|||
|
IMPORT NewHandleWrapper,HidePen
|
|||
|
;---------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE OpenRgn;
|
|||
|
;
|
|||
|
MOVEM.L D3/A2-A4,-(SP) ;SAVE REGS
|
|||
|
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
|
|||
|
MOVE.L THEPORT(A4),A0 ;GET CURRENT GRAFPORT
|
|||
|
MOVE.L #1,D0
|
|||
|
MOVE.L D0,RGNSAVE(A0) ;RGNSAVE := TRUE
|
|||
|
CLR RGNINDEX(A4) ;RGNINDEX := 0
|
|||
|
CLR.L -(SP) ;MAKE ROOM FOR FCN RESULT
|
|||
|
MOVE #256,-(SP) ;PUSH BYTE COUNT = 256
|
|||
|
MOVE (SP),RGNMAX(A4) ;RGNMAX := 256 TOO;
|
|||
|
JSR NewHandleWrapper
|
|||
|
MOVE.L (SP)+,RGNBUF(A4) ;RGNBUF := NEWHANDLE(RGNMAX)
|
|||
|
_HidePen
|
|||
|
MOVEM.L (SP)+,D3/A2-A4 ;RESTORE REGS
|
|||
|
RTS ;AND RETURN
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CloseRgn PROC EXPORT
|
|||
|
IMPORT ShowPen,SortPoints,CullPoints,PackRgn
|
|||
|
;---------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE CloseRgn(* dstRgn: RgnHandle *);
|
|||
|
; Sort array of inversion points and pack into region.
|
|||
|
;
|
|||
|
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
|
|||
|
;
|
|||
|
PARAMSIZE EQU 4 ;TOTAL BYTES OF PARAMETERS
|
|||
|
DSTRGN EQU PARAMSIZE+8-4 ;LONG, RGNHANDLE
|
|||
|
PTCOUNT EQU -2 ;WORD
|
|||
|
VARSIZE EQU PTCOUNT ;SIZE OF LOCAL VARS
|
|||
|
|
|||
|
|
|||
|
LINK A6,#VARSIZE
|
|||
|
MOVEM.L D3/A2-A4,-(SP) ;SAVE REGS
|
|||
|
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
|
|||
|
MOVE.L THEPORT(A4),A0 ;GET CURRENT GRAFPORT
|
|||
|
TST.L RGNSAVE(A0) ;IS RGNSAVE TRUE ?
|
|||
|
BEQ.S DONE ;NO, ABORT
|
|||
|
CLR.L RGNSAVE(A0) ;YES, RGNSAVE := FALSE
|
|||
|
_SHOWPEN ;UNDO THE HIDEPEN FROM OPENRGN
|
|||
|
MOVE RGNINDEX(A4),D0 ;GET CURRENT RGNINDEX
|
|||
|
|
|||
|
cmp.w #-147,qderr ;rgnTooBigErr? <BAL 28Apr89>
|
|||
|
bne.s @rgnOK ;no, return the region <BAL 28Apr89>
|
|||
|
moveq #0,d0 ;yes, return an empty region <BAL 28Apr89>
|
|||
|
move d0,qdErr ;clear error so it doesn't bite us. <BAL 28Apr89>
|
|||
|
|
|||
|
@rgnOK LSR #2,D0 ;DIV BY 4
|
|||
|
MOVE D0,PTCOUNT(A6) ;FOR PTCOUNT
|
|||
|
MOVE.L RGNBUF(A4),A3 ;GET RGNBUF HANDLE
|
|||
|
MOVE.L (A3),-(SP) ;PUSH BUF POINTER
|
|||
|
MOVE D0,-(SP) ;PUSH PTCOUNT
|
|||
|
_SORTPOINTS ;QUICKSORT IN VH ORDER
|
|||
|
MOVE.L (A3),-(SP) ;PUSH BUF POINTER
|
|||
|
PEA PTCOUNT(A6) ;PUSH VAR PTCOUNT
|
|||
|
_CULLPOINTS ;CANCEL DUPLICATE PAIRS
|
|||
|
MOVE.L A3,-(SP) ;PUSH RGNBUF HANDLE
|
|||
|
MOVE PTCOUNT(A6),-(SP) ;PUSH (UPDATED) PTCOUNT
|
|||
|
MOVE.L DSTRGN(A6),-(SP) ;PUSH DSTRGN
|
|||
|
_PACKRGN ;PACK POINTS INTO DSTRGN
|
|||
|
MOVE.L A3,A0 ;GET RGNBUF HANDLE
|
|||
|
_DisposHandle ;DISCARD IT
|
|||
|
DONE MOVEM.L (SP)+,D3/A2-A4 ;RESTORE REGS
|
|||
|
UNLINK PARAMSIZE, 'CLOSERGN'
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CopyRgn PROC EXPORT
|
|||
|
IMPORT SetHSize
|
|||
|
;---------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE CopyRgn(* srcRgn,dstRgn: RgnHandle *);
|
|||
|
;
|
|||
|
PARAMSIZE EQU 8
|
|||
|
SRCRGN EQU PARAMSIZE+8-4 ;RGNHANDLE
|
|||
|
DSTRGN EQU SRCRGN-4 ;RGNHANDLE
|
|||
|
|
|||
|
LINK A6,#0 ;ESTABLISH STACK FRAME
|
|||
|
MOVE.L SRCRGN(A6),A0 ;GET SRCRGN HANDLE
|
|||
|
MOVE.L DSTRGN(A6),A1 ;GET DSTRGN HANDLE
|
|||
|
CMP.L A0,A1 ;ARE THEY THE SAME?
|
|||
|
BEQ.S DONE ;YES, QUIT
|
|||
|
|
|||
|
MOVE.L (A0),A0 ;DE-REFERENCE SRCRGN HANDLE
|
|||
|
MOVE.L (A1),A1 ;DE-REFERENCE DSTRGN HANDLE
|
|||
|
MOVE RGNSIZE(A0),D0 ;GET SRC SIZE
|
|||
|
CMP RGNSIZE(A1),D0 ;IS DST SIZE SAME AS SRC ?
|
|||
|
BEQ.S COPY ;YES, CONTINUE
|
|||
|
|
|||
|
MOVEM.L D0/D3/A2,-(SP) ;SAVE REGS AND BYTECOUNT
|
|||
|
MOVE.L DSTRGN(A6),-(SP) ;PUSH DSTRGN HANDLE
|
|||
|
MOVE D0,-(SP) ;PUSH NEWSIZE=SRC SIZE
|
|||
|
JSR SetHSize ;CHANGE SIZE OF DST
|
|||
|
MOVEM.L (SP)+,D0/D3/A2 ;RESTORE REGS AND BYTECOUNT
|
|||
|
MOVE.L SRCRGN(A6),A0 ;GET SRCRGN HANDLE
|
|||
|
MOVE.L DSTRGN(A6),A1 ;GET DSTRGN HANDLE
|
|||
|
MOVE.L (A0),A0 ;DE-REFERENCE SRCRGN HANDLE
|
|||
|
MOVE.L (A1),A1 ;DE-REFERENCE DSTRGN HANDLE
|
|||
|
|
|||
|
COPY LSR #2,D0 ;LONGCOUNT := BYTECOUNT DIV 4
|
|||
|
BCC.S EVEN ;WAS THERE AN ODD WORD ?
|
|||
|
MOVE (A0)+,(A1)+ ;YES, DO IT TO MAKE EVEN
|
|||
|
BRA.S EVEN ;AND CONTINUE
|
|||
|
COPYLP MOVE.L (A0)+,(A1)+ ;COPY A LONG OF SRC TO DST
|
|||
|
EVEN DBRA D0,COPYLP ;LOOP FOR ALL LONGS
|
|||
|
|
|||
|
DONE UNLINK PARAMSIZE,'COPYRGN '
|
|||
|
|
|||
|
|
|||
|
|
|||
|
SetEmptyRgn PROC EXPORT
|
|||
|
IMPORT SetRectRgn
|
|||
|
;---------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE SetEmptyRgn(rgn: RgnHandle);
|
|||
|
;
|
|||
|
MOVE.L (SP)+,A0 ;POP RETURN ADDR
|
|||
|
CLR.L -(SP) ;PUSH LEFT, TOP
|
|||
|
CLR.L -(SP) ;PUSH RIGHT,BOTTOM
|
|||
|
MOVE.L A0,-(SP) ;RESTORE RETURN ADDR
|
|||
|
JMP SETRECTRGN ;DOUBLE UP ON CODE
|
|||
|
|
|||
|
|
|||
|
|
|||
|
SetRectRgn PROC EXPORT
|
|||
|
IMPORT SetHSize
|
|||
|
;---------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE SetRectRgn(rgn: RgnHandle; left,top,right,bottom: INTEGER);
|
|||
|
; make a rectangular region from 4 integers.
|
|||
|
;
|
|||
|
LINK A6,#0 ;ESTABLISH STACK FRAME
|
|||
|
MOVEM.L D3/A2,-(SP) ;SAVE REGS
|
|||
|
MOVE.L 16(A6),A0 ;GET RGN HANDLE
|
|||
|
MOVE.L (A0),A1 ;DE-REFERENCE HANDLE
|
|||
|
MOVEQ #10,D0
|
|||
|
CMP RGNSIZE(A1),D0 ;IS RGNSIZE ALREADY 10 ?
|
|||
|
BEQ.S SIZEOK ;YES, CONTINUE
|
|||
|
MOVE.L A0,-(SP) ;PUSH RGNHANDLE
|
|||
|
MOVE D0,-(SP) ;PUSH SIZE = 10 BYTES
|
|||
|
JSR SetHSize ;CHANGE SIZE OF REGION
|
|||
|
MOVE.L 16(A6),A0 ;GET RGN HANDLE
|
|||
|
MOVE.L (A0),A1 ;DE-REFERENCE HANDLE
|
|||
|
MOVE #10,RGNSIZE(A1) ;INSTALL SIZE = 10
|
|||
|
SIZEOK MOVE.L 12(A6),RGNBBOX+TOPLEFT(A1) ;INSTALL RGNBBOX TOPLEFT
|
|||
|
MOVE.L 8(A6),RGNBBOX+BOTRIGHT(A1) ;INSTALL RGNBBOX BOTRIGHT
|
|||
|
MOVE RGNBBOX+LEFT(A1),D0
|
|||
|
CMP RGNBBOX+RIGHT(A1),D0 ;IS LEFT >= RIGHT ?
|
|||
|
BGE.S EMPTY ;YES, SET TO EMPTY
|
|||
|
|
|||
|
MOVE RGNBBOX+TOP(A1),D0
|
|||
|
CMP RGNBBOX+BOTTOM(A1),D0 ;IS TOP < BOTTOM ?
|
|||
|
BLT.S DONE ;YES, CONTINUE
|
|||
|
|
|||
|
EMPTY CLR.L RGNBBOX+TOPLEFT(A1)
|
|||
|
CLR.L RGNBBOX+BOTRIGHT(A1)
|
|||
|
DONE MOVEM.L (SP)+,D3/A2 ;RESTORE REGS
|
|||
|
UNLINK 12,'SETRECTR'
|
|||
|
|
|||
|
|
|||
|
|
|||
|
RectRgn PROC EXPORT
|
|||
|
IMPORT SetRectRgn
|
|||
|
;---------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE RectRgn(rgn: RgnHandle; r: Rect);
|
|||
|
; make a rectangular region from a rectangle
|
|||
|
;
|
|||
|
MOVE.L (SP)+,A0 ;POP RETURN ADDR
|
|||
|
MOVE.L (SP)+,A1 ;POP ADDR OF RECT
|
|||
|
MOVE.L (A1)+,-(SP) ;PUSH LEFT,TOP
|
|||
|
MOVE.L (A1)+,-(SP) ;PUSH RIGHT,BOTTOM
|
|||
|
MOVE.L A0,-(SP) ;RESTORE RETURN ADDR
|
|||
|
JMP SETRECTRGN ;DOUBLE UP ON CODE
|
|||
|
|
|||
|
|
|||
|
|
|||
|
OffsetRgn PROC EXPORT
|
|||
|
;---------------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE OffsetRgn(rgn: RgnHandle; dh,dv: INTEGER);
|
|||
|
;
|
|||
|
MOVE.L (SP)+,A1 ;POP RETURN ADDR
|
|||
|
MOVE (SP)+,D1 ;POP DV
|
|||
|
MOVE (SP)+,D0 ;POP DH
|
|||
|
MOVE.L (SP)+,A0 ;POP RGN HANDLE
|
|||
|
MOVE.L (A0),A0 ;DE-REFERENCE IT
|
|||
|
ADD #2,A0 ;POINT TO RGNBBOX
|
|||
|
|
|||
|
;------------------------------------------------------
|
|||
|
;
|
|||
|
; OFFSET THE BOUNDING BOX
|
|||
|
;
|
|||
|
ADD D1,(A0)+ ;ADD DV TO TOP
|
|||
|
ADD D0,(A0)+ ;ADD DH TO LEFT
|
|||
|
ADD D1,(A0)+ ;ADD DV TO BOTTOM
|
|||
|
ADD D0,(A0)+ ;ADD DH TO RIGHT
|
|||
|
|
|||
|
|
|||
|
;---------------------------------------------------------------------
|
|||
|
;
|
|||
|
; IF NON-RECTANGULAR REGION, OFFSET THE COORDINATES TOO.
|
|||
|
;
|
|||
|
CMP #10,-10(A0) ;IS REGION RECTANGULAR ?
|
|||
|
BEQ.S DONE ;IF SO, WE'RE ALL DONE
|
|||
|
NXTVERT ADD D1,(A0)+ ;OFFSET VERTICAL COORD DV
|
|||
|
NXTHOR ADD D0,(A0)+ ;OFFSET LEFT COORD DH
|
|||
|
ADD D0,(A0)+ ;OFFSET RIGHT COORD DH
|
|||
|
CMP #32767,(A0) ;HORIZ TERMINATOR ?
|
|||
|
BNE NXTHOR ;NO, LOOP
|
|||
|
ADD #2,A0 ;YES, SKIP OVER TERMINATOR
|
|||
|
CMP #32767,(A0) ;IS NEXT VERT = 32767 ?
|
|||
|
BNE NXTVERT ;NO, LOOP FOR MORE
|
|||
|
DONE JMP (A1) ;RETURN
|
|||
|
|
|||
|
|
|||
|
|
|||
|
InsetRgn PROC EXPORT
|
|||
|
IMPORT InsetRect,SortPoints
|
|||
|
IMPORT NewHandleWrapper,RgnOp,PackRgn
|
|||
|
;---------------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE InsetRgn(rgn: RgnHandle; dh,dv: INTEGER);
|
|||
|
;
|
|||
|
; Inset a region by (dh,dv). Outset if dh or dv neg
|
|||
|
;
|
|||
|
; A6 OFFSETS OF PARAMS AFTER LINK:
|
|||
|
;
|
|||
|
PARAMSIZE EQU 8
|
|||
|
RGN EQU PARAMSIZE+8-4 ;LONG, RGNHANDLE
|
|||
|
DH EQU RGN-2 ;WORD
|
|||
|
DV EQU DH-2 ;WORD
|
|||
|
|
|||
|
|
|||
|
LINK A6,#0 ;NO LOCAL VARS
|
|||
|
MOVEM.L D3-D7/A2-A4,-(SP) ;SAVE REGS
|
|||
|
MOVE.L DV(A6),D6 ;GET DV AND DH BOTH
|
|||
|
BEQ.S JGOHOME ;QUIT IF BOTH ARE ZERO
|
|||
|
MOVE.L RGN(A6),A4 ;GET RGNHANDLE
|
|||
|
MOVE.L (A4),A3 ;DE-REFERENCE IT
|
|||
|
MOVE (A3)+,D7 ;GET RGNSIZE
|
|||
|
|
|||
|
|
|||
|
;--------------------------------------------------------------
|
|||
|
;
|
|||
|
; IF RECTANGULAR REGION, CALL INSETRECT AND CHECK FOR EMPTY.
|
|||
|
;
|
|||
|
CMP #10,D7 ;IS RGN RECTANGULAR ?
|
|||
|
BNE.S NOTRECT ;NO, CONTINUE
|
|||
|
MOVE.L A3,-(SP) ;PUSH ADDR OF RGNBBOX
|
|||
|
MOVE.L D6,-(SP) ;PUSH DH AND DV
|
|||
|
_INSETRECT ;InsetRect(rgn^^.rgnbbox,dh,dv);
|
|||
|
MOVE LEFT(A3),D0 ;GET BBOX LEFT
|
|||
|
CMP RIGHT(A3),D0 ;IS LEFT >= RIGHT ?
|
|||
|
BGE.S EMPTY ;YES, RETURN EMPTY RGN
|
|||
|
MOVE TOP(A3),D0 ;GET BBOX TOP
|
|||
|
CMP BOTTOM(A3),D0 ;IS TOP >= BOTTOM ?
|
|||
|
BLT.S JGOHOME ;NO, CONTINUE
|
|||
|
EMPTY CLR.L (A3)+ ;SET RGNBBOX TO (0,0,0,0) TO
|
|||
|
CLR.L (A3)+ ;RETURN EMPTY REGION
|
|||
|
JGOHOME BRA.S GOHOME ;ALL DONE
|
|||
|
|
|||
|
|
|||
|
;-----------------------------------------------------
|
|||
|
;
|
|||
|
; THE REGION IS NOT RECTANGULAR. ALLOCATE A POINT BUFFER IN THE HEAP.
|
|||
|
;
|
|||
|
NOTRECT ADD D7,D7 ;TRY BYTES NEEDED = RGNSIZE*2
|
|||
|
CLR.L -(SP) ;ROOM FOR FCN RESULT
|
|||
|
MOVE D7,-(SP) ;PUSH BYTESNEEDED
|
|||
|
JSR NewHandleWrapper ;ALLOCATE PTBUF
|
|||
|
MOVE.L (SP)+,A3 ;PUT PTBUF HANDLE IN A3
|
|||
|
BSR.S HINSET ;INSET HORIZ AND FLIP
|
|||
|
SWAP D6 ;GET DV INSTEAD OF DH
|
|||
|
BSR.S HINSET ;INSET VERTICAL AND FLIP BACK
|
|||
|
BRA.S DONE ;ALL DONE
|
|||
|
|
|||
|
|
|||
|
;--------------------------------------------------------------------------
|
|||
|
;
|
|||
|
; LOCAL ROUTINE TO INSET HORIZONTALLY, SWAP H AND V COORDS, AND RE-SORT
|
|||
|
;
|
|||
|
; RgnOp(rgn,rgn,bufHandle,maxBytes,op,dh,TRUE);
|
|||
|
;
|
|||
|
HINSET CLR.W -(SP) ;ROOM FOR FCN RESULT
|
|||
|
MOVE.L A4,-(SP) ;PUSH RGNA = USER RGN
|
|||
|
MOVE.L A4,-(SP) ;PUSG RGNB = USER RGN ALSO
|
|||
|
MOVE.L A3,-(SP) ;PUSH BUFHANDLE
|
|||
|
MOVE D7,-(SP) ;PUSH MAXBYTES
|
|||
|
MOVE #8,-(SP) ;PUSH OP = INSET
|
|||
|
MOVE D6,-(SP) ;PUSH DH
|
|||
|
ST -(SP) ;PUSH OKGROW = TRUE
|
|||
|
_RGNOP
|
|||
|
MOVE.W (SP)+,D5 ;GET PTCOUNT IN D5
|
|||
|
;
|
|||
|
; SWAP VERT AND HORIZ COORDS OF ALL INVERSION POINTS
|
|||
|
;
|
|||
|
MOVE.L (A3),A0 ;DE-REFERENCE PTBUF HANDLE
|
|||
|
MOVE D5,D1 ;COPY PTCOUNT
|
|||
|
BRA.S SWAP2 ;GO TO LOOP START
|
|||
|
SWAPLP MOVE.L (A0),D0 ;GET A POINT
|
|||
|
SWAP D0 ;SWAP ITS COORDINATES
|
|||
|
MOVE.L D0,(A0)+ ;PUT IT BACK INTO ARRAY
|
|||
|
SWAP2 DBRA D1,SWAPLP ;LOOP FOR ALL POINTS
|
|||
|
;
|
|||
|
; RE-SORT THE POINTS IN V.H ORDER
|
|||
|
;
|
|||
|
MOVE.L (A3),-(SP) ;PUSH PTBUF PTR
|
|||
|
MOVE D5,-(SP) ;PUSH PTCOUNT
|
|||
|
_SORTPOINTS ;RE-SORT INTO VH ORDER
|
|||
|
;
|
|||
|
; PACK THE RESULTING POINTS
|
|||
|
;
|
|||
|
MOVE.L A3,-(SP) ;PUSH PTBUF HANDLE
|
|||
|
MOVE D5,-(SP) ;PUSH PTCOUNT
|
|||
|
MOVE.L A4,-(SP) ;PUSH RGN HANDLE
|
|||
|
_PACKRGN ;PackRgn(ptBuf,ptCount,rgn);
|
|||
|
RTS ;RETURN TO LOCAL CALLER
|
|||
|
|
|||
|
|
|||
|
;----------------------------------------------
|
|||
|
;
|
|||
|
; DISCARD POINT BUFFER AND QUIT.
|
|||
|
;
|
|||
|
DONE MOVE.L A3,A0 ;GET PTBUF HANDLE
|
|||
|
_DisposHandle ;DISCARD IT
|
|||
|
|
|||
|
GOHOME MOVEM.L (SP)+,D3-D7/A2-A4 ;RESTORE REGS
|
|||
|
UNLINK PARAMSIZE,'INSETRGN'
|
|||
|
|
|||
|
|
|||
|
|
|||
|
EmptyRgn FUNC EXPORT
|
|||
|
IMPORT EmptyRect
|
|||
|
;---------------------------------------------------
|
|||
|
;
|
|||
|
; FUNCTION EmptyRgn(rgn: RgnHandle): BOOLEAN;
|
|||
|
;
|
|||
|
MOVE.L (SP)+,A0 ;POP RETURN ADDR
|
|||
|
MOVE.L (SP)+,A1 ;POP RGNHANDLE
|
|||
|
MOVE.L (A1),A1 ;DE-REFERENCE HANDLE
|
|||
|
PEA RGNBBOX(A1) ;PUSH RGNBBOX
|
|||
|
MOVE.L A0,-(SP) ;PUSH RETURN ADDR
|
|||
|
JMP ([4*$ae+$e00]) ;USE EMPTYRECT CODE
|
|||
|
|
|||
|
|
|||
|
|
|||
|
EqualRgn FUNC EXPORT
|
|||
|
;-------------------------------------------------------
|
|||
|
;
|
|||
|
; FUNCTION EqualRgn(rgnA,rgnB: RgnHandle): BOOLEAN;
|
|||
|
;
|
|||
|
; RETURNS TRUE IF RGNA AND RGNB DESCRIBE THE SAME AREA
|
|||
|
;
|
|||
|
MOVE.L 4(SP),A0 ;GET RGNA HANDLE
|
|||
|
MOVE.L 8(SP),A1 ;GET RGNB HANDLE
|
|||
|
CMP.L A0,A1 ;ARE THEY THE SAME ?
|
|||
|
BEQ.S RETTRUE ;YES, THE REGIONS ARE THE SAME
|
|||
|
MOVE.L (A0),A0 ;DE-REFERENCE RGN A
|
|||
|
MOVE.L (A1),A1 ;DE-REFERENCE RGN B
|
|||
|
MOVE (A0),D0 ;GET RGNSIZE A
|
|||
|
MOVE D0,D1 ;MAKE AN EXTRA COPY
|
|||
|
LSR #2,D1 ;DIV BY 4 FOR LONG COUNT
|
|||
|
SUB #1,D1 ;INIT DBRA LOOP COUNT
|
|||
|
LOOP CMPM.L (A0)+,(A1)+ ;COMPARE A LONG
|
|||
|
DBNE D1,LOOP ;LOOK TILL DIFFERENT OR COUNT
|
|||
|
BNE.S RETFALSE ;DIFFERENT --> FALSE
|
|||
|
AND #3,D0 ;GET 0..3 FINISH UP BYTES
|
|||
|
BEQ.S RETTRUE ;IF NO MORE, WE MADE IT
|
|||
|
LOOP2 CMPM.B (A0)+,(A1)+ ;COMPARE A BYTE
|
|||
|
BNE.S RETFALSE ;BR IF DIFFERENT
|
|||
|
SUB #1,D0
|
|||
|
BNE.S LOOP2 ;LOOP LAST 1..3 BYTES
|
|||
|
RETTRUE MOVE.L #1,D0 ;TRUE
|
|||
|
BRA.S DONE
|
|||
|
RETFALSE MOVE.L #0,D0 ;FALSE
|
|||
|
DONE MOVE.B D0,12(SP) ;SET RESULT
|
|||
|
MOVE.L (SP)+,A0 ;POP RETURN ADDR
|
|||
|
ADD #8,SP ;STRIP PARAMETERS
|
|||
|
JMP (A0) ;RETURN
|
|||
|
|
|||
|
|
|||
|
|
|||
|
SectRgn PROC EXPORT
|
|||
|
EXPORT DoRgnOp,UnionRgn,DiffRgn,XorRgn
|
|||
|
IMPORT EqualRgn,CopyRgn,RSect,RectRgn,SetEmptyRgn
|
|||
|
IMPORT NewHandleWrapper,RgnOp,PackRgn
|
|||
|
;---------------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE SectRgn(srcRgnA,srcRgnB,dstRgn: RgnHandle);
|
|||
|
; calculate the intersection of two regions.
|
|||
|
;
|
|||
|
MOVEQ #0,D0 ;OP = SECT
|
|||
|
BRA.S DoRgnOp ;SHARE COMMON CODE
|
|||
|
|
|||
|
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE UnionRgn(srcRgnA,srcRgnB,dstRgn: RgnHandle);
|
|||
|
; calculate the union of two regions.
|
|||
|
;
|
|||
|
UnionRgn
|
|||
|
MOVEQ #4,D0 ;OP = UNION
|
|||
|
BRA.S DoRgnOp ;SHARE COMMON CODE
|
|||
|
|
|||
|
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE DiffRgn(srcRgnA,srcRgnB,dstRgn: RgnHandle);
|
|||
|
; calculate the difference A-B of two regions
|
|||
|
;
|
|||
|
DiffRgn MOVEQ #2,D0 ;OP = DIFF
|
|||
|
BRA.S DoRgnOp ;SHARE COMMON CODE
|
|||
|
|
|||
|
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE XorRgn(srcRgnA,srcRgnB,dstRgn: RgnHandle);
|
|||
|
; calculate the exclusive or of two regions
|
|||
|
;
|
|||
|
XorRgn MOVEQ #6,D0 ;OP = DIFF
|
|||
|
;FALL INTO DORGNOP
|
|||
|
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE DoRgnOp(srcRgnA,srcRgnB,dstRgn: RgnHandle);
|
|||
|
;
|
|||
|
; Computes the Intersection, Difference, Union, or Xor of two regions.
|
|||
|
;
|
|||
|
; enter with op in D0.
|
|||
|
; op = 0: SECT
|
|||
|
; 2: DIFF A-B
|
|||
|
; 4: UNION
|
|||
|
; 6: XOR
|
|||
|
;
|
|||
|
;
|
|||
|
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
|
|||
|
;
|
|||
|
PARAMSIZE EQU 12
|
|||
|
RGNA EQU PARAMSIZE+8-4 ;LONG, RGNHANDLE
|
|||
|
RGNB EQU RGNA-4 ;LONG, RGNHANDLE
|
|||
|
DSTRGN EQU RGNB-4 ;LONG, RGNHANDLE
|
|||
|
;
|
|||
|
TEMPRECTANGLE EQU -8 ;RECT
|
|||
|
VARSIZE EQU TEMPRECTANGLE ;TOTAL LOCALS
|
|||
|
;
|
|||
|
DoRgnOp
|
|||
|
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
|
|||
|
MOVEM.L D3-D7/A2-A4,-(SP) ;SAVE REGS
|
|||
|
MOVE D0,D5 ;COPY OP INTO D5
|
|||
|
MOVE.L RGNA(A6),A2 ;GET RGNA
|
|||
|
MOVE.L RGNB(A6),A3 ;GET RGNB
|
|||
|
MOVE.L DSTRGN(A6),A4 ;GET DSTRGN
|
|||
|
MOVE.L #2,D7
|
|||
|
;
|
|||
|
; ARE THE TWO INPUT REGIONS THE SAME ?
|
|||
|
;
|
|||
|
CLR.B -(SP) ;MAKE ROOM FOR FCN RESULT
|
|||
|
MOVE.L A2,-(SP) ;PUSH RGNA
|
|||
|
MOVE.L A3,-(SP) ;PUSH RGNB
|
|||
|
_EQUALRGN ;CALL EQUALRGN
|
|||
|
TST.B (SP)+ ;ARE THEY THE SAME ?
|
|||
|
BEQ.S NOTSAME ;NO, CONTINUE
|
|||
|
;
|
|||
|
; THE TWO REGIONS ARE THE SAME. IF SECT OR UNION
|
|||
|
; THEN COPY RGNA INTO DSTRGN, ELSE ZERO OUT DSTRGN.
|
|||
|
;
|
|||
|
AND D7,D5 ;WAS OP SECT OR UNION ?
|
|||
|
BNE.S ZERO ;NO, ZERO OUT DSTRGN
|
|||
|
COPY MOVE.L A2,-(SP) ;PUSH RGNA
|
|||
|
MOVE.L A4,-(SP) ;PUSH DSTRGN
|
|||
|
_COPYRGN ;COPY RGNA INTO DSTRGN
|
|||
|
BRA.S JDONE ;AND QUIT
|
|||
|
ZERO MOVE.L A4,-(SP) ;PUSH DSTRGN
|
|||
|
_SetEmptyRgn ;SET IT TO EMPTY
|
|||
|
BRA.S JDONE ;AND QUIT
|
|||
|
|
|||
|
;
|
|||
|
; IF OP = DIFF AND RGNB = EMPTY, COPY RGNA INTO DST
|
|||
|
;
|
|||
|
NOTSAME MOVE.L (A2),A0 ;DE-REFERENCE RGNA
|
|||
|
MOVE.L (A3),A1 ;DE-REFERENCE RGNB
|
|||
|
CMP D7,D5 ;IS OP = DIFF ?
|
|||
|
BGT.S UNIXOR ;NO, ITS UNION OR XOR
|
|||
|
BLT.S BBOXES ;NO, IT'S SECT
|
|||
|
MOVE RGNBBOX+LEFT(A1),D0 ;GET BBOX LEFT
|
|||
|
CMP RGNBBOX+RIGHT(A1),D0 ;IS BBOX LEFT >= RIGHT ?
|
|||
|
BGE COPY ;YES, COPY RGNA INTO DST
|
|||
|
|
|||
|
;
|
|||
|
; IF op = SECT OR DIFF, THEN INTERSECT THE BOUNDING BOXES.
|
|||
|
;
|
|||
|
BBOXES PEA RGNBBOX(A0) ;PUSH RGNA^^.RGNBBOX
|
|||
|
PEA RGNBBOX(A1) ;PUSH RGNB^^.RGNBBOX
|
|||
|
MOVE D7,-(SP) ;PUSH NRECTS = 2
|
|||
|
PEA TEMPRECTANGLE(A6) ;PUSH DST = TEMPRECTANGLE
|
|||
|
_RSECT ;CALC INTERSECTION
|
|||
|
BNE.S NOTEMPTY ;BR IF RESULT NOT EMPTY
|
|||
|
;
|
|||
|
; THE BOUNDING BOXES DON'T INTERSECT.
|
|||
|
; IF OP = SECT, THEN RETURN EMPTY.
|
|||
|
; IF OP = DIFF, THEN COPY RGNA INTO DSTRGN.
|
|||
|
;
|
|||
|
TST D5 ;IS OP = SECT ?
|
|||
|
BEQ ZERO ;YES, RETURN EMPTY
|
|||
|
BRA COPY ;NO, COPY SRCA INTO DSTRGN
|
|||
|
|
|||
|
;
|
|||
|
; IF OP = SECT, THEN CHECK FOR BOTH INPUTS RECTANGULAR
|
|||
|
;
|
|||
|
NOTEMPTY MOVE.L (A2),A0 ;DE-REFERENCE RGNA
|
|||
|
MOVE.L (A3),A1 ;DE-REFERENCE RGNB
|
|||
|
TST D5 ;IS OP = SECT ?
|
|||
|
BNE.S NOTEASY ;NO, CONTINUE
|
|||
|
MOVEQ #10,D0
|
|||
|
CMP RGNSIZE(A0),D0 ;IS RGNA RECTANGULAR ?
|
|||
|
BNE.S NOTEASY ;NO, CONTINUE
|
|||
|
CMP RGNSIZE(A1),D0 ;IS RGNB RECTANGULAR ?
|
|||
|
BNE.S NOTEASY ;NO, CONTINUE
|
|||
|
MOVE.L A4,-(SP) ;PUSH DSTRGN
|
|||
|
PEA TEMPRECTANGLE(A6) ;PUSH TEMPRECTANGLE
|
|||
|
_RECTRGN ;RectRgn(dstRgn,tempRect);
|
|||
|
JDONE BRA.S DONE
|
|||
|
|
|||
|
;
|
|||
|
; OP = UNION OR XOR: IF EITHER REGION IS EMPTY, COPY THE OTHER.
|
|||
|
;
|
|||
|
UNIXOR MOVE RGNBBOX+LEFT(A1),D0 ;GET RGNB BBOX LEFT
|
|||
|
CMP RGNBBOX+RIGHT(A1),D0 ;IS RGNB BBOX LEFT >= RIGHT ?
|
|||
|
BGE COPY ;YES, COPY RGNA INTO DST
|
|||
|
|
|||
|
MOVE RGNBBOX+LEFT(A0),D0 ;GET RGNA BBOX LEFT
|
|||
|
CMP RGNBBOX+RIGHT(A0),D0 ;IS RGNA BBOX LEFT >= RIGHT ?
|
|||
|
BLT.S NOTEASY ;NO, CONTINUE
|
|||
|
MOVE.L A3,A2 ;YES, GET RGNB INSTEAD
|
|||
|
BRA COPY ;COPY RGNB INTO DST
|
|||
|
|
|||
|
|
|||
|
NOTEASY MOVE RGNSIZE(A0),D4 ;GET RGNA RGNSIZE
|
|||
|
ADD RGNSIZE(A1),D4 ;ADD RGNB RGNSIZE
|
|||
|
ADD D4,D4 ;TRY DOUBLE FOR BYTECOUNT
|
|||
|
CLR.L -(SP) ;MAKE ROOM FOR FCN RESULT
|
|||
|
MOVE D4,-(SP) ;PUSH BYTECOUNT
|
|||
|
JSR NewHandleWrapper ;ALLOCATE PTBUF
|
|||
|
MOVE.L (SP)+,A3 ;GET PTBUF HANDLE IN A3
|
|||
|
;
|
|||
|
; PtCount := RgnOp(srcA,srcB,bufHandle,maxBytes,op,0,TRUE);
|
|||
|
;
|
|||
|
CLR.W -(SP) ;MAKE ROOM FOR FCN RESULT
|
|||
|
MOVE.L RGNA(A6),-(SP) ;PUSH RGNA
|
|||
|
MOVE.L RGNB(A6),-(SP) ;PUSH RGNB
|
|||
|
MOVE.L A3,-(SP) ;PUSH BUFHANDLE
|
|||
|
MOVE D4,-(SP) ;PUSH MAXBYTES
|
|||
|
MOVE D5,-(SP) ;PUSH OP
|
|||
|
CLR.W -(SP) ;PUSH DH=0
|
|||
|
ST -(SP) ;PUSH OKGROW = TRUE
|
|||
|
_RGNOP
|
|||
|
MOVE (SP)+,D6 ;GET PTCOUNT
|
|||
|
|
|||
|
MOVE.L A3,-(SP) ;PUSH PTBUF HANDLE
|
|||
|
MOVE D6,-(SP) ;PUSH PTCOUNT
|
|||
|
MOVE.L A4,-(SP) ;PUSH DSTRGN
|
|||
|
_PACKRGN ;PackRgn(ptBuf,ptCount,dstRgn);
|
|||
|
|
|||
|
MOVE.L A3,A0 ;GET PTBUF HANDLE
|
|||
|
_DisposHandle ;DISCARD IT
|
|||
|
|
|||
|
DONE MOVEM.L (SP)+,D3-D7/A2-A4 ;RESTORE REGS
|
|||
|
UNLINK PARAMSIZE,'DORGNOP '
|
|||
|
|
|||
|
|
|||
|
|
|||
|
PtInRgn FUNC EXPORT
|
|||
|
;------------------------------------------------------------
|
|||
|
;
|
|||
|
; FUNCTION PtInRgn(pt: Point; rgn: RgnHandle): BOOLEAN;
|
|||
|
;
|
|||
|
; TESTS IF A GIVEN POINT IS INSIDE A REGION.
|
|||
|
;
|
|||
|
; A6 OFFSETS OF PARAMETERS AFTER LINK:
|
|||
|
;
|
|||
|
PARAMSIZE EQU 8 ;SIZE OF PARAMETERS
|
|||
|
RESULT EQU PARAMSIZE+8 ;BOOLEAN
|
|||
|
PT EQU RESULT-4 ;POINT, VALUE
|
|||
|
RGN EQU PT-4 ;LONG, HANDLE
|
|||
|
|
|||
|
|
|||
|
ENTRY LINK A6,#0 ;NO LOCAL VARS
|
|||
|
MOVE.L D3,-(SP) ;SAVE REG
|
|||
|
MOVE PT+H(A6),D1 ;GET TEST HORIZ
|
|||
|
MOVE PT+V(A6),D2 ;GET TEST VERT
|
|||
|
CLR D3 ;INIT INSIDE:=FALSE
|
|||
|
|
|||
|
|
|||
|
;-----------------------------------------------------------
|
|||
|
;
|
|||
|
; FIRST CHECK BOUNDING BOX
|
|||
|
;
|
|||
|
MOVE.L RGN(A6),A0 ;GET RGN HANDLE
|
|||
|
MOVE.L (A0),A0 ;DE-REFERENCE IT
|
|||
|
CMP RGNBBOX+LEFT(A0),D1 ;IS PT.H < BBOX LEFT ?
|
|||
|
BLT.S DONE ;YES, RETURN FALSE
|
|||
|
CMP RGNBBOX+RIGHT(A0),D1 ;IS PT.H >= BBOX RIGHT ?
|
|||
|
BGE.S DONE ;YES, RETURN FALSE
|
|||
|
CMP RGNBBOX+TOP(A0),D2 ;IS PT.V < BBOX TOP ?
|
|||
|
BLT.S DONE ;YES, RETURN FALSE
|
|||
|
CMP RGNBBOX+BOTTOM(A0),D2 ;IS PT.V >= BBOX BOT ?
|
|||
|
BGE.S DONE ;YES, RETURN FALSE
|
|||
|
CMP #10,RGNSIZE(A0) ;IS REGION RECTANGULAR ?
|
|||
|
BNE.S NOTRECT ;NO, CONTINUE
|
|||
|
NOT D3 ;YES, RETURN TRUE
|
|||
|
BRA.S DONE
|
|||
|
|
|||
|
|
|||
|
;------------------------------------------------------------------
|
|||
|
;
|
|||
|
; PT IS INSIDE BOUNDING BOX AND REGION IS NOT RECTANGULAR.
|
|||
|
; LOOK AT THE INVERSION POINTS TO DETERMINE IF PT IN REGION.
|
|||
|
;
|
|||
|
NOTRECT LEA RGNDATA(A0),A0 ;POINT TO FIRST VERT COORD
|
|||
|
NXTVERT CMP (A0)+,D2 ;IS NEXT VERT > PT.V ?
|
|||
|
BLT.S DONE ;YES, QUIT
|
|||
|
NEXTHOR MOVE (A0)+,D0 ;GET HORIZ COORD
|
|||
|
CMP #32767,D0 ;IS IT THE TERMINATOR ?
|
|||
|
BEQ NXTVERT ;YES, GET NEXT VERT COORD
|
|||
|
CMP D1,D0 ;IS HORIZ <= PT.H ?
|
|||
|
BGT NEXTHOR ;NO, IGNORE THIS POINT
|
|||
|
NOT D3 ;YES, TOGGLE INSIDE
|
|||
|
BRA NEXTHOR ;AND GO FOR MORE POINTS
|
|||
|
DONE NEG.B D3 ;BOOLEAN RESULT IS 0 OR 1
|
|||
|
MOVE.B D3,RESULT(A6) ;RETURN BOOLEAN FCN RESULT
|
|||
|
MOVE.L (SP)+,D3 ;RESTORE REG
|
|||
|
UNLINK PARAMSIZE,'PTINRGN '
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
RectInRgn FUNC EXPORT
|
|||
|
;--------------------------------------------------
|
|||
|
;
|
|||
|
; FUNCTION RectInRgn(r: Rect; rgn: RgnHandle): BOOLEAN;
|
|||
|
;
|
|||
|
; Returns TRUE if any part of the rectangle intersects the region.
|
|||
|
;
|
|||
|
;
|
|||
|
; A6 OFFSETS OF PARAMETERS AFTER LINK:
|
|||
|
;
|
|||
|
PARAMSIZE EQU 8 ;TOTAL SIZE OF PARAMETERS
|
|||
|
RESULT EQU PARAMSIZE+8 ;BYTE, BOOLEAN
|
|||
|
RECT EQU RESULT-4 ;LONG, VAR ADDR
|
|||
|
RGN EQU RECT-4 ;LONG, RGNHANDLE
|
|||
|
|
|||
|
|
|||
|
;------------------------------------------------------
|
|||
|
;
|
|||
|
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
|
|||
|
;
|
|||
|
MINRECT EQU -8 ;RECTANGLE
|
|||
|
SAVESTACK EQU MINRECT-4 ;LONG
|
|||
|
STATE EQU SAVESTACK-RGNREC ;REGION STATE RECORD
|
|||
|
VARSIZE EQU STATE ;TOTAL SIZE OF VARIABLES
|
|||
|
|
|||
|
|
|||
|
LINK A6,#VARSIZE ;ALLOCATE LOCAL VARIABLES
|
|||
|
MOVEM.L D0-D7/A1-A5,-(SP) ;SAVE REGISTERS
|
|||
|
MOVE.L SP,SAVESTACK(A6) ;REMEMBER STACK START
|
|||
|
CLR.B RESULT(A6) ;INIT BOOLEAN RESULT TO FALSE
|
|||
|
MOVE.L RGN(A6),A1 ;GET REGION HANDLE
|
|||
|
MOVE.L (A1),A1 ;DE-REFERENCE IT
|
|||
|
|
|||
|
|
|||
|
;--------------------------------------------------------------
|
|||
|
;
|
|||
|
; FIRST CHECK IF RECTANGLE INTERSECTS BOUNDING BOX OF REGION
|
|||
|
;
|
|||
|
MOVE.L RECT(A6),-(SP) ;PUSH POINTER TO RECT
|
|||
|
PEA RGNBBOX(A1) ;PUSH POINTER TO RGN BBOX
|
|||
|
MOVE #2,-(SP) ;PUSH NRECTS=2
|
|||
|
PEA MINRECT(A6) ;PUSH ADDR WHERE TO PUT RESULT
|
|||
|
_RSECT ;CALC INTERSECTION
|
|||
|
BEQ.S GOHOME ;QUIT IF NO INTERSECTION
|
|||
|
CMP #10,RGNSIZE(A1) ;IS REGION RECTANGULAR ?
|
|||
|
BEQ.S RETTRUE ;YES, RETURN TRUE
|
|||
|
|
|||
|
|
|||
|
;------------------------------------------------------------
|
|||
|
;
|
|||
|
; THE REGION IS NON-RECTANGULAR AND THE RECTANGLE INTERSECTS
|
|||
|
; THE REGION'S BOUNDING BOX. WE WILL PLAY BACK THE PORTION OF
|
|||
|
; THE REGION WITHIN MINRECT AND SEE IF ANY PART OF THE REGION
|
|||
|
; IS ACTUALLY INSIDE THE RECTANGLE.
|
|||
|
;
|
|||
|
|
|||
|
|
|||
|
;-------------------------------------------------
|
|||
|
;
|
|||
|
; INITIALIZE RGN STATE RECORD AT TOP.
|
|||
|
;
|
|||
|
MOVE.L A1,A0 ;GET RGNPTR IN A0
|
|||
|
LEA STATE(A6),A1 ;GET STATE RECORD IN A1
|
|||
|
MOVE MINRECT+LEFT(A6),D0 ;MINH IN D0
|
|||
|
MOVE MINRECT+RIGHT(A6),D1 ;MAXH IN D1
|
|||
|
MOVE D0,D2 ;BUFLEFT:=MINH
|
|||
|
_INITRGN ;INIT RECORD, ALLOCATE BUFFER
|
|||
|
|
|||
|
|
|||
|
;------------------------------------------------------------
|
|||
|
;
|
|||
|
; PLAY THE REGION BACK INTO SCAN BUFFER UNTIL IT GETS DOWN TO
|
|||
|
; MINRECT, THEN CHECK EACH SCANLINE FOR NON-ZERO PLAYBACK.
|
|||
|
; QUIT AND RETURN TRUE IF NON-ZERO FOUND BEFORE RGN GOES BEYOND MINRECT.
|
|||
|
;
|
|||
|
MOVE SCANSIZE(A1),D5 ;GET BUFSIZE= # LONGS -1
|
|||
|
MOVE MINRECT+TOP(A6),D0
|
|||
|
_SEEKRGN ;SEEK THE REGION TO MINRECT TOP
|
|||
|
MOVE MINRECT+BOTTOM(A6),D6
|
|||
|
TESTBUF MOVE.L SCANBUF(A1),A0 ;POINT TO BUFFER START
|
|||
|
MOVE D5,D0 ;INIT LOOP COUNT TO BUFSIZE
|
|||
|
NXTLONG TST.L (A0)+ ;IS SCAN BUF NON-ZERO ?
|
|||
|
DBNE D0,NXTLONG ;TEST LONGS TILL NON ZERO OR END
|
|||
|
BNE.S RETTRUE ;WE FOUND A NON-ZERO, RETURN TRUE
|
|||
|
MOVE NEXTV(A1),D0 ;GET NEXT VERTICAL IN RGN
|
|||
|
CMP D0,D6 ;IS NEXT RGN VERT BEYOND BOTTOM ?
|
|||
|
BLE.S GOHOME ;YES, RETURN FALSE
|
|||
|
_SEEKRGN ;NO, SEEK TO NEXT VERT CHANGE
|
|||
|
BRA.S TESTBUF ;AND SEE IF IT IS NON-ZERO
|
|||
|
|
|||
|
RETTRUE ADDQ.B #1,RESULT(A6) ;SET BOOLEAN RESULT TO TRUE
|
|||
|
GOHOME MOVE.L SAVESTACK(A6),SP ;STRIP SCAN BUFFER IF ANY
|
|||
|
MOVEM.L (SP)+,D0-D7/A1-A5 ;RESTORE REGISTERS
|
|||
|
UNLINK PARAMSIZE,'RECTINRG'
|
|||
|
|
|||
|
|
|||
|
IF 0 THEN
|
|||
|
|
|||
|
OldTrimRect FUNC EXPORT
|
|||
|
|
|||
|
IMPORT RgnOp,TrimRgn
|
|||
|
;------------------------------------------------------
|
|||
|
;
|
|||
|
; FUNCTION TrimRect(rgn: RgnHandle; VAR dstRect: Rect): CCR TRISTATE;
|
|||
|
;
|
|||
|
; RESULT IN CONDITION CODES:
|
|||
|
;
|
|||
|
; = RESULT RECTANGULAR, DSTRECT TRIMMED
|
|||
|
; < RESULT EMPTY, DSTRECT NOT MODIFIED
|
|||
|
; > RESULT NON-RECT, DSTRECT NOT MODIFIED
|
|||
|
;
|
|||
|
; If the intersection of rgn and dstRect is rectangular,
|
|||
|
; then return EQUAL and put the intersection into dstRect.
|
|||
|
; If the intersection is empty or not rectangular, then
|
|||
|
; return FALSE and don't modify dstRect.
|
|||
|
;
|
|||
|
; Does not call the storage allocator.
|
|||
|
;
|
|||
|
; 1. Fake up a rect rgn on the stack from dstRect
|
|||
|
; 2. Call RgnOp with max bytes = 24, OKGROW = FALSE
|
|||
|
; 3a. If ptCount = 4 THEN result rect, return TRUE and update dstRect.
|
|||
|
; 3b. If ptCount < 4 THEN result empty, return TRUE and clear dstRect.
|
|||
|
; 3c. If ptCount > 4 THEN result not rect, return FALSE
|
|||
|
;
|
|||
|
PARAMSIZE EQU 8
|
|||
|
RGN EQU PARAMSIZE+8-4 ;LONG, RGNHANDLE
|
|||
|
DSTRECT EQU RGN-4 ;LONG, ADDR OF DSTRECT
|
|||
|
|
|||
|
PTDATA EQU -24 ;ROOM FOR 6 POINTS
|
|||
|
PTMASTER EQU PTDATA-4 ;LONG, FAKE MASTER
|
|||
|
REGION EQU PTMASTER-10 ;ROOM FOR RECT RGN DATA
|
|||
|
RGNMASTER EQU REGION-4 ;LONG
|
|||
|
VARSIZE EQU RGNMASTER
|
|||
|
|
|||
|
bra TrimRgn
|
|||
|
|
|||
|
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
|
|||
|
MOVEM.L D0-D2/A1,-(SP) ;SAVE ALL REGS USED
|
|||
|
LEA PTDATA(A6),A0 ;POINT TO BUFFER
|
|||
|
MOVE.L A0,PTMASTER(A6) ;INSTALL INTO FAKE MASTER
|
|||
|
LEA REGION(A6),A1 ;POINT TO REGION DATA
|
|||
|
MOVE.L A1,RGNMASTER(A6) ;INSTALL INTO FAKE MASTER
|
|||
|
MOVE #10,(A1)+ ;INSTALL RGNSIZE = 10
|
|||
|
MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
|
|||
|
MOVE.L (A0)+,(A1)+ ;COPY DSTRECT TOPLEFT
|
|||
|
MOVE.L (A0)+,(A1)+ ;COPY DSTRECT BOTRIGHT
|
|||
|
;
|
|||
|
; RgnOp(rgn,rectRgn,BufHandle,24,sect,0,FALSE)
|
|||
|
;
|
|||
|
CLR.W -(SP) ;ROOM FOR FCN RESULT
|
|||
|
MOVE.L RGN(A6),-(SP) ;PUSH RGN
|
|||
|
PEA RGNMASTER(A6) ;PUSH FAKE RGNHANDLE
|
|||
|
PEA PTMASTER(A6) ;PUSH BUFHANDLE
|
|||
|
MOVE #24,-(SP) ;PUSH MAXBYTES = 24
|
|||
|
CLR.L -(SP) ;PUSH OP = SECT, DH = 0
|
|||
|
CLR.B -(SP) ;PUSH OKGROW = FALSE
|
|||
|
_RGNOP ;RgnOp(rgn,rectRgn,buf,64,op,dh,FALSE);
|
|||
|
MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
|
|||
|
CMP #4,(SP)+ ;IS PT COUNT = 4 ?
|
|||
|
BNE.S DONE ;NO, RETURN < OR > IN CCR
|
|||
|
MOVE.L PTDATA(A6),(A0)+ ;UPDATE DSTRECT.TOPLEFT
|
|||
|
MOVE.L PTDATA+12(A6),(A0)+ ;UPDATE DSTRECT.BOTRIGHT
|
|||
|
SUB D0,D0 ;SET EQUAL FLAG
|
|||
|
DONE MOVEM.L (SP)+,D0-D2/A1 ;RESTORE ALL REGS
|
|||
|
UNLK A6 ;RELEASE STACK FRAME
|
|||
|
RTD #PARAMSIZE ;STRIP PARAMETERS AND RETURN
|
|||
|
|
|||
|
ENDIF
|
|||
|
|
|||
|
|
|||
|
|
|||
|
TrimRect FUNC EXPORT
|
|||
|
;------------------------------------------------------
|
|||
|
;
|
|||
|
; FUNCTION TrimRgn(rgn: RgnHandle; VAR dstRect: Rect; Trim: integer): CCR TRISTATE;
|
|||
|
;
|
|||
|
; Quickly determine the complexity of the interection of a
|
|||
|
; rectangle and a region. If the intersection is rectangular,
|
|||
|
; return the intersection in dstRect.
|
|||
|
;
|
|||
|
; If Trim is false, dstRect will not be altered:
|
|||
|
; NON-RECT will be returned if intersection ≠ dstRect
|
|||
|
;
|
|||
|
; RESULT IN CONDITION CODES:
|
|||
|
;
|
|||
|
; = RESULT RECTANGULAR
|
|||
|
; < RESULT EMPTY
|
|||
|
; > RESULT NON-RECT
|
|||
|
;
|
|||
|
; CLOBBERS: A0
|
|||
|
;
|
|||
|
; Does not call the storage allocator.
|
|||
|
;
|
|||
|
; 1. Allocate 2 inversion pair buffers on stack
|
|||
|
; 2. Play rgn (trimmed to rect.left, right) into buffers until rect.top reached
|
|||
|
; if more than 2 points in buffer -> NON-RECT result
|
|||
|
; 3. Play rgn until rect.bottom,
|
|||
|
; if pair in buffer changes -> NON-RECT result
|
|||
|
; else if buffer empty then -> EMPTY/FULL result
|
|||
|
; else Trimmed RECT result
|
|||
|
;
|
|||
|
; ASSUMES: RgnBBox completely encloses Rect
|
|||
|
;
|
|||
|
; NOTE: Only the sides of the dstRect are actually trimmed,
|
|||
|
; no top/bottom trimming is performed
|
|||
|
;
|
|||
|
;
|
|||
|
PARAMSIZE EQU 10
|
|||
|
RGN EQU PARAMSIZE+8-4 ;LONG, RGNHANDLE
|
|||
|
DSTRECT EQU RGN-4 ;LONG, ADDR OF DSTRECT
|
|||
|
TRIM EQU DSTRECT-2 ;WORD, SHOULD DST BE TRIMMED?
|
|||
|
|
|||
|
VARSIZE EQU 0
|
|||
|
|
|||
|
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
|
|||
|
MOVEM.L D0-D7/A1-A5,-(SP) ;SAVE ALL REGS USED
|
|||
|
MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
|
|||
|
MOVEM.L (A0),D4/D5 ;D4 = MinRect.Top, Left
|
|||
|
;D5 = MinRect.Bottom, Right
|
|||
|
MOVE.L D4,D6
|
|||
|
SWAP D6 ;D6 = MinRect.Top
|
|||
|
MOVE.L RGN(A6),A3 ;get RgnHandle
|
|||
|
MOVE.L (A3),A3
|
|||
|
MOVE.W RGNSIZE(A3),D2 ;get rgnSize in D2
|
|||
|
CMP #10,D2 ;Rect Rgn?
|
|||
|
BEQ DONE1 ;return with RECT intersect true
|
|||
|
ADD #RGNDATA,A3 ;point at rgnData
|
|||
|
|
|||
|
_StackAvail ;get stack avail in D0.L
|
|||
|
SUB.L #qdStackXtra,D0 ;subtract slop factor <1.5> BAL
|
|||
|
EXT.L D2 ;make it long
|
|||
|
CMP.L D2,D0 ;enough space?
|
|||
|
BGE.S STKOK ;yes, go allocate
|
|||
|
|
|||
|
MOVE.W D5,D2
|
|||
|
SUB.W D4,D2 ;get Right - Left
|
|||
|
EXT.L D2 ;make it long
|
|||
|
LSL.L #2,D2 ;2 max buffers = 2 (width * 2)
|
|||
|
CMP.L D0,D2 ;enough space?
|
|||
|
BLE.S STKOK ;yes, go allocate
|
|||
|
|
|||
|
; _debugger ;I wish I had a better solution here...
|
|||
|
BRA DONE1 ;return with cc = GT => NON-RECT
|
|||
|
|
|||
|
STKOK LSR.L #1,D2 ;
|
|||
|
BCLR #0,D2 ;make bufSize even
|
|||
|
MOVE.L SP,A0 ;Save stack base in A0
|
|||
|
SUB.L D2,SP ;allocate one buffer
|
|||
|
MOVE.L SP,A4 ;remember buffer pointer
|
|||
|
SUB.L D2,SP ;allocate one buffer
|
|||
|
MOVE.L SP,A5 ;remember buffer pointer
|
|||
|
|
|||
|
;-------------------------------------------------------------
|
|||
|
;
|
|||
|
; Seek into region until ThisV >= minRect.Top
|
|||
|
;;
|
|||
|
|
|||
|
MOVEQ #0,D2 ;init parity to out=even
|
|||
|
MOVE.W #32767,D7 ;get a MAXINT for comparisons
|
|||
|
MOVE.L A4,A1 ;set up src1 ptr
|
|||
|
bra.s NXTV
|
|||
|
|
|||
|
EQUAL CMP D7,D0 ;ALL DONE ?
|
|||
|
BNE.S XorScam ;no, go back for more
|
|||
|
|
|||
|
NXTV MOVE.W D7,(A1) ;flag end of buffer
|
|||
|
|
|||
|
CMP.W (A3)+,D6 ;is minRect.Top < thisV?
|
|||
|
BLT.S INRECT ;yes, go check result
|
|||
|
|
|||
|
MOVE.L A4,A2 ;set up src1 ptr
|
|||
|
MOVE.L A5,A1 ;set up dest ptr
|
|||
|
EXG A4,A5 ;swap the point buffers
|
|||
|
|
|||
|
|
|||
|
;-------------------------------------------------------------
|
|||
|
;
|
|||
|
; Each input scan is a sorted array of integers terminated by 32767.
|
|||
|
;
|
|||
|
; Combine region inversion point data (A3) with that in current
|
|||
|
; buffer (A2) and place result in (A1). Discard inversion points not
|
|||
|
; between Left = D4 and Right = D5. Eliminate duplicate points.
|
|||
|
; Maintain count of inversion points to the left of D4 in D2.
|
|||
|
;
|
|||
|
; NOTE: This routine is similar to XorScan except that
|
|||
|
; it trims the inversion pairs to minRect.Left, Right
|
|||
|
;
|
|||
|
|
|||
|
XorScam MOVE (A2)+,D1 ;get next B
|
|||
|
NEXTA MOVE (A3)+,D0 ;get next A
|
|||
|
NEXT CMP D1,D0 ;find the leftmost
|
|||
|
BEQ.S EQUAL ;equal points cancel
|
|||
|
BLT.S ALESS ;A is less
|
|||
|
BLESS MOVE D1,(A1)+ ;B is pre-clipped so put to dst
|
|||
|
MOVE (A2)+,D1 ;get next B
|
|||
|
BRA.S NEXT ;loop for more
|
|||
|
ALESS CMP.W D4,D0 ;is A less than or equal to minRect.Left?
|
|||
|
BLE.S FLIP ;yes, flip parity
|
|||
|
CMP.W D0,D5 ;is A greater than or equal to minRect.Right?
|
|||
|
BLE.S NEXTA ;yes, discard
|
|||
|
MOVE D0,(A1)+ ;PUT A TO DST
|
|||
|
;move.l a0,d0
|
|||
|
;move.l a1,d3
|
|||
|
;chk.l d0,d3 ;have we gone to far?
|
|||
|
BRA.S NEXTA ;loop for more
|
|||
|
FLIP ADDQ #1,D2 ;toggle even/odd state
|
|||
|
BRA.S NEXTA ;loop for more
|
|||
|
|
|||
|
;-------------------------------------------------------------
|
|||
|
;
|
|||
|
; Scan through region pointed to by A3 until
|
|||
|
; 1) Find an odd number of points to the left of D4 -or-
|
|||
|
; 2) Find a point between D4 and D5 -or-
|
|||
|
; 3) Find a MAXINT (D7)
|
|||
|
;
|
|||
|
|
|||
|
Scam MOVE (A3)+,D0 ;get next A
|
|||
|
CMP.W D4,D0 ;is A less than or equal to minRect.Left?
|
|||
|
BLE.S FLIP2 ;yes, flip parity
|
|||
|
CMP.W D0,D7 ;is A MAXINT?
|
|||
|
BEQ.S NXTV2 ;go get next vert
|
|||
|
CMP.W D0,D5 ;is A greater than or equal to minRect.Right?
|
|||
|
BLE.S Scam ;yes, discard
|
|||
|
BRA.S BAIL ;this would alter the result so bail
|
|||
|
FLIP2 MOVE (A3)+,D0 ;get another A
|
|||
|
CMP.W D4,D0 ;is it also less than or equal to minRect.Left?
|
|||
|
BLE.S Scam ;yes, parity preserved
|
|||
|
|
|||
|
BAIL CMP.W #0,D7 ;NON-RECT, set CC GT and return
|
|||
|
BRA.S DONE
|
|||
|
|
|||
|
|
|||
|
;-------------------------------------------------------------
|
|||
|
;
|
|||
|
; If the initial scanline of intersection is rectangular then
|
|||
|
; 'Scam' through the region until ThisV >= minRect.Bottom.
|
|||
|
; Else abort and return a NON-RECT result
|
|||
|
;;
|
|||
|
|
|||
|
INRECT
|
|||
|
SUB.L A4,A1 ;Get pnt count * 2
|
|||
|
MOVE A1,D3 ;make a copy
|
|||
|
CMP #4,D3 ;is pnt count > 2?
|
|||
|
BGT.S DONE ;NON-RECT so bail out
|
|||
|
BLT.S RECT ;less than 2 pnts => rectangular so far
|
|||
|
AND #1,D2 ;2 pnts => must check parity, is parity even?
|
|||
|
BNE.S BAIL ;no, return NON-RECT
|
|||
|
|
|||
|
RECT MOVE.L D5,D6
|
|||
|
SWAP D6 ;D6 = MinRect.Bottom
|
|||
|
SUB #2,A3 ;back up to thisV
|
|||
|
NXTV2 CMP.W (A3)+,D6 ;is thisV < minRect.Bottom?
|
|||
|
BGT.S SCAM ;yes, go scan more of region
|
|||
|
|
|||
|
TST TRIM(A6) ;is trimming allowed?
|
|||
|
BNE.S TRIMOK ;yes, go to it
|
|||
|
TST D3 ;no, there must be zero points
|
|||
|
BEQ.S NOTRIM ;check for empty/full result
|
|||
|
BRA.S BAIL ;return failure
|
|||
|
|
|||
|
;-------------------------------------------------------------
|
|||
|
;
|
|||
|
; The entire intersection is complete and the result is still
|
|||
|
; rectangular. First check for the trivial FULL/EMPTY intersections then
|
|||
|
; process any partial rectangular intersections.
|
|||
|
;
|
|||
|
|
|||
|
TRIMOK MOVE.L DSTRECT(A6),A1 ;point to dstRect
|
|||
|
MOVE D2,D0 ;prepare for DONE2 fall thru
|
|||
|
CMP #2,D3 ;How many words in scan buffer?
|
|||
|
BLT.S NOTRIM ;none, go decide between full/empty
|
|||
|
BGT.S TRIM2 ;two, must trim both left and right
|
|||
|
;one, could be left or right
|
|||
|
BTST #0,D0 ;check parity
|
|||
|
BNE.S TRIMR ;odd, must trim right
|
|||
|
|
|||
|
MOVE (A4),Left(A1) ;even, trim left and return RECT
|
|||
|
BRA.S DONE2
|
|||
|
|
|||
|
TRIM2 MOVE (A4)+,Left(A1) ;trim Left and then Right
|
|||
|
TRIMR MOVE (A4),Right(A1) ;trim right and return RECT
|
|||
|
BRA.S DONE2
|
|||
|
|
|||
|
NOTRIM MOVEQ #1,D0
|
|||
|
AND D0,D2 ;make even/odd count 0/1
|
|||
|
DONE2 CMP D0,D2 ;set cc LT if even, EQ if odd
|
|||
|
DONE MOVE.L A0,SP ;strip buffers, restore stack ptr
|
|||
|
DONE1 MOVEM.L (SP)+,D0-D7/A1-A5 ;RESTORE ALL REGS
|
|||
|
UNLK A6 ;RELEASE STACK FRAME
|
|||
|
RTD #PARAMSIZE ;STRIP PARAMETERS AND RETURN
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
MapRgn PROC EXPORT
|
|||
|
IMPORT MapRect,NewHandleWrapper,PutRgn,MapPt
|
|||
|
IMPORT SortPoints,CullPoints,PackRgn
|
|||
|
;-------------------------------------------------------------
|
|||
|
;
|
|||
|
; PROCEDURE MapRgn(rgn: RgnHandle; fromRect,toRect: Rect);
|
|||
|
;
|
|||
|
; A6 OFFSETS OF PARAMETERS AND LOCALS AFTER LINK:
|
|||
|
;
|
|||
|
; fix from QDciPatchROM.a is in as <7Sept90 KON> <sm 6/9/92>stb
|
|||
|
|
|||
|
PARAMSIZE EQU 12
|
|||
|
RGN EQU PARAMSIZE+8-4 ;LONG, RGNHANDLE
|
|||
|
FROMRECT EQU RGN-4 ;LONG, ADDR OF RECT
|
|||
|
TORECT EQU FROMRECT-4 ;LONG, ADDR OF RECT
|
|||
|
|
|||
|
INDEX EQU -2 ;INTEGER
|
|||
|
SIZE EQU INDEX-2 ;WORD
|
|||
|
PTCOUNT EQU SIZE-2 ;WORD
|
|||
|
VARSIZE EQU PTCOUNT ;TOTAL BYTES
|
|||
|
|
|||
|
|
|||
|
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
|
|||
|
MOVEM.L D3/D6-D7/A2-A4,-(SP) ;SAVE REGS
|
|||
|
;
|
|||
|
; QUIT FAST IF FROMRECT = TORECT
|
|||
|
;
|
|||
|
MOVE.L FROMRECT(A6),A0 ;POINT TO FROMRECT
|
|||
|
MOVE.L TORECT(A6),A1 ;POINT TO TORECT
|
|||
|
CMPM.L (A0)+,(A1)+ ;IS TOPLEFT SAME ?
|
|||
|
BNE.S NOTSAME ;NO, CONTINUE
|
|||
|
CMPM.L (A0)+,(A1)+ ;YES, IS BOTRIGHT SAME TOO ?
|
|||
|
BEQ.S JDONE ;IF SO, JUST QUIT
|
|||
|
;
|
|||
|
; SPECIAL CASE RECTANGULAR RGN <7Sept90 KON>
|
|||
|
;
|
|||
|
NOTSAME MOVE.L RGN(A6),A4 ;GET RGNHANDLE <7Sept90 KON>
|
|||
|
MOVE.L (A4),A0 ;DE-REFERENCE RGN <7Sept90 KON>
|
|||
|
CMP #10,RGNSIZE(A0) ;IS RGN RECTANGULAR ? <7Sept90 KON>
|
|||
|
BNE.S NOTRECT ;NO, CONTINUE <7Sept90 KON>
|
|||
|
;
|
|||
|
; Don't do anything if region is rectangular and wide open since MapRect will choke <7Sept90 KON>
|
|||
|
; a0 points to rgn
|
|||
|
;
|
|||
|
cmp.l #$80018001,2(a0) ; <7Sept90 KON>
|
|||
|
bne.s @notWide ; <7Sept90 KON>
|
|||
|
cmp.l #$7fff7fff,6(a0) ;wide open?; <7Sept90 KON>
|
|||
|
beq.s JDone ;Yes, Don't remap <7Sept90 KON>
|
|||
|
@notWide
|
|||
|
PEA RGNBBOX(A0) ;YES, PUSH RGNBBOX
|
|||
|
MOVE.L FROMRECT(A6),-(SP) ;PUSH FROMRECT
|
|||
|
MOVE.L TORECT(A6),-(SP) ;PUSH TO RECT
|
|||
|
_MAPRECT ;MapRect(rgn^^.rgnBBox,from,to);
|
|||
|
JDONE BRA.S DONE
|
|||
|
|
|||
|
NOTRECT CLR.L -(SP) ;ROOM FOR FCN RESULT
|
|||
|
MOVE #256,-(SP) ;PUSH BYTECOUNT = 256
|
|||
|
MOVE (SP),SIZE(A6) ;SIZE := 256 BYTES
|
|||
|
JSR NewHandleWrapper ;ALLOCATE PTBUF
|
|||
|
MOVE.L (SP)+,A3 ;GET PTBUF HANDLE IN A3
|
|||
|
|
|||
|
CLR INDEX(A6) ;INDEX := 0
|
|||
|
MOVE.L A4,-(SP) ;PUSH RGN
|
|||
|
MOVE.L A3,-(SP) ;PUSH PTBUF HANDLE
|
|||
|
PEA INDEX(A6) ;PUSH VAR INDEX
|
|||
|
PEA SIZE(A6) ;PUSH VAR SIZE
|
|||
|
_PUTRGN ;UNPACK RGN INTO INVERSION PTS
|
|||
|
MOVE INDEX(A6),D7 ;GET INDEX
|
|||
|
LSR #2,D7 ;PTCOUNT := INDEX DIV 4
|
|||
|
;
|
|||
|
; MAP ALL INVERSION POINTS
|
|||
|
;
|
|||
|
MOVE D7,D6 ;COPY PTCOUNT FOR LOOP COUNT
|
|||
|
MOVE.L (A3),A2 ;DE-REFERENCE PTBUF HANDLE
|
|||
|
BRA.S MORE ;GO TO LOOP START
|
|||
|
LOOP MOVE.L A2,-(SP) ;PUSH ADDR OF AN INV PT
|
|||
|
MOVE.L FROMRECT(A6),-(SP) ;PUSH FROMRECT
|
|||
|
MOVE.L TORECT(A6),-(SP) ;PUSH TORECT
|
|||
|
_MAPPT ;MAP THIS POINT
|
|||
|
ADD.L #4,A2 ;BUMP TO NEXT POINT
|
|||
|
MORE DBRA D6,LOOP ;LOOP ALL INVERSION POINTS
|
|||
|
|
|||
|
MOVE.L (A3),-(SP) ;PUSH PTBUF PTR
|
|||
|
MOVE D7,-(SP) ;PUSH PTCOUNT
|
|||
|
_SORTPOINTS ;SortPoints(ptBuf^,ptCount)
|
|||
|
|
|||
|
MOVE.L (A3),-(SP) ;PUSH PTBUF PTR
|
|||
|
MOVE D7,PTCOUNT(A6) ;PUT PTCOUNT IN MEMORY
|
|||
|
PEA PTCOUNT(A6) ;PUSH VAR PTCOUNT
|
|||
|
_CULLPOINTS ;CullPoints(ptBuf^,ptCount)
|
|||
|
|
|||
|
MOVE.L A3,-(SP) ;PUSH PTBUF HANDLE
|
|||
|
MOVE PTCOUNT(A6),-(SP) ;PUSH PTCOUNT
|
|||
|
MOVE.L A4,-(SP) ;PUSH RGN
|
|||
|
_PACKRGN ;PackRgn(ptBuf,ptCount,rgn);
|
|||
|
|
|||
|
MOVE.L A3,A0 ;PUSH PTBUF HANDLE
|
|||
|
_DisposHandle ;DISCARD IT
|
|||
|
|
|||
|
DONE MOVEM.L (SP)+,D3/D6-D7/A2-A4 ;RESTORE REGS
|
|||
|
UNLINK PARAMSIZE,'MAPRGN '
|
|||
|
|
|||
|
|
|||
|
ENDPROC
|
|||
|
|
|||
|
|
|||
|
;________________________________________________________________________________
|
|||
|
;
|
|||
|
|
|||
|
; version of Tuesday, March 28, 1989
|
|||
|
|
|||
|
; Purpose:
|
|||
|
; To convert bitmaps to regions.
|
|||
|
;
|
|||
|
; PRINT PUSH,OFF
|
|||
|
; INCLUDE 'Traps.a'
|
|||
|
; INCLUDE 'ToolEqu.a'
|
|||
|
; INCLUDE 'QuickEqu.a'
|
|||
|
; INCLUDE 'SysEqu.a'
|
|||
|
; PRINT POP
|
|||
|
; LOAD 'AIncludes.d'
|
|||
|
|
|||
|
|
|||
|
;________________________________________________________________________________
|
|||
|
;
|
|||
|
; FUNCTION BitMapRgn(region:RgnHandle; bMap:BitMap): OSErr; INLINE $A8D7;
|
|||
|
;
|
|||
|
; Given a region and bitmap, BitMapRgn makes the region a bounding
|
|||
|
; region for the 'map. If it can't get memory it will return a
|
|||
|
; Memory Manager-type error and an empty region gibbley. Note that
|
|||
|
; the region might also be empty with no error (if the bounds is an
|
|||
|
; empty rectangle or there are no 1 bits in the bitmap). Lastly,
|
|||
|
; if the region would have to exceed 32K it returns a result of
|
|||
|
; -500 (rgnTooBigErr).
|
|||
|
;
|
|||
|
; The bMap parameter may be a pointer to a bitmap, a pointer to a
|
|||
|
; pixmap, or a pointer to a portBits field in a color grafport.
|
|||
|
; In the latter two cases, if the pixmap is not 1-bit deep, an error
|
|||
|
; result of -148 (pixmapTooDeepErr) is returned.
|
|||
|
;
|
|||
|
; (the nibble state machine idea is from the Finder MaskToRgn routine)
|
|||
|
;
|
|||
|
; History
|
|||
|
; 2/19/88 RBB changed to take in washing and handle rect. & empties properly
|
|||
|
; also now finds minimum rectangle to enclose region
|
|||
|
; *** version of 2/22/88 ***
|
|||
|
; 2/23/88 RBB putting in numerous optimizations recommended by Darin
|
|||
|
; 4/4/88 RBB trying to re-do lost work from March
|
|||
|
; DBA
|
|||
|
; 3/28/89 CSD adjusted setup to know about pixmaps and portBits
|
|||
|
;
|
|||
|
;________________________________________________________________________________
|
|||
|
;
|
|||
|
;Theory
|
|||
|
; We scan each line of the bitmap and pump inversion points (ip's) into the region
|
|||
|
; to put the areas with ones in the bitmap into the region and the areas
|
|||
|
; with zeroes outside the region.
|
|||
|
;
|
|||
|
; In order to keep track of where we are in "inversion land" we use two
|
|||
|
; techniques:
|
|||
|
|
|||
|
; The first is a scanline buffer which records the changes
|
|||
|
; (zeroes to ones and vice versa) as we go. Wherever a change occurs (a
|
|||
|
; 1 next to a 0 in the buffer) we need to put out an inversion point.
|
|||
|
|
|||
|
; The second is a togglin' flag which tells us whether we are "inverted" or not.
|
|||
|
; Since we use a state machine in the innermost (nibble) loop to churn out
|
|||
|
; ip's, the input to the state machine must be complemented if the flag is set.
|
|||
|
|
|||
|
; The loop stuff looks like this:
|
|||
|
; outer line loop (grows handle in anticipation of worst case for next line)
|
|||
|
; longword loop for current line (puts out inter-long ip's as needed)
|
|||
|
; loop for 4 nibbles in current long (calls state maching for each nibble)
|
|||
|
;
|
|||
|
;________________________________________________________________________________
|
|||
|
|
|||
|
|
|||
|
BitMapRgn PROC EXPORT
|
|||
|
|
|||
|
BMFrame RECORD {A6Link},DECR
|
|||
|
result DS.W 1
|
|||
|
|
|||
|
paramTop EQU *
|
|||
|
|
|||
|
regionH DS.L 1
|
|||
|
bMapPtr DS.L 1
|
|||
|
|
|||
|
paramSize EQU paramTop-*
|
|||
|
|
|||
|
return DS.L 1
|
|||
|
A6Link DS.L 1
|
|||
|
|
|||
|
rowLongs DS.L 1 ;number of longwords per line
|
|||
|
rightMask DS.L 1 ;mask for rightmost long of each line
|
|||
|
slHandle DS.L 1 ;handle to scanline buffer
|
|||
|
numLines DS.W 1 ;number of lines in bitmap
|
|||
|
rowNumBytes DS.W 1 ;rowbytes from the bitmap
|
|||
|
startSize DS.L 1 ;size of region at start of line
|
|||
|
lastLineH DS.L 1 ;last line (zeroes) handle
|
|||
|
|
|||
|
handSize DS.L 1 ;size of handle (avoid calls to GetHandleSize)
|
|||
|
max2Add DS.L 1 ;worst case for bytes we could add for next line
|
|||
|
MMUSave ds.b 2 ;keep it even!
|
|||
|
SrcPixMap ds.b PMREC+CTREC+20 ;room for pixmap and color table
|
|||
|
|
|||
|
localSize EQU *
|
|||
|
ENDR
|
|||
|
|
|||
|
WITH BMFrame
|
|||
|
LINK A6,#localSize
|
|||
|
MOVEM.L A2-A5/D3-D7,-(SP) ;save work registers
|
|||
|
|
|||
|
CLR.L slHandle(A6) ;no scanline handle, yet
|
|||
|
CLR.W result(A6) ;function result presumed zero at start
|
|||
|
|
|||
|
MOVE.L regionH(A6),A0
|
|||
|
MOVE.L (A0),A2
|
|||
|
MOVEQ #0,D0
|
|||
|
MOVE.W (A2),D0 ;get size of region
|
|||
|
MOVE.L D0,handSize(A6) ;save it long
|
|||
|
;
|
|||
|
; Convert bitmap/pixmap to a pixmap
|
|||
|
;
|
|||
|
move.l bMapPtr(a6),a1
|
|||
|
lea SrcPixMap(a6),a2
|
|||
|
_BitsToPix
|
|||
|
|
|||
|
;get boundary rectangle so we can tell how to process the bitmap
|
|||
|
|
|||
|
lea SrcPixMap(A6),A1 ;get bitmap pointer
|
|||
|
CMP.W #1, pmPixelSize(A1) ;is it 1 bit per pixel deep?
|
|||
|
BEQ.S @1 ;if yes, we're fine
|
|||
|
MOVE.W #pixmapTooDeepErr, D0 ;return an error otherwise
|
|||
|
BRA BMRBadEmpty ;clean up and bail out
|
|||
|
@1
|
|||
|
MOVE.W rowBytes(A1), rowNumBytes(A6) ;get the rowbytes from the bit/pixmap
|
|||
|
ANDI.W #$7FFF, rowNumBytes(A6) ;mask off pixmap flag
|
|||
|
MOVE.L bounds+topLeft(A1),D2 ;get topLeft
|
|||
|
MOVE.W bounds+right(A1),D0 ;get right
|
|||
|
|
|||
|
;figure the number of longs per row (according to width, not rowbytes)
|
|||
|
;so we can get a scanline buffer
|
|||
|
|
|||
|
SUB.W D2,D0 ;right - left
|
|||
|
BLE BMREmptyOut ;if empty rect. then empty region
|
|||
|
EXT.L D0
|
|||
|
MOVE.L D0,D4
|
|||
|
ADD.L D4,D4 ;double width for 2 bytes/ip
|
|||
|
ADDQ.L #4+2,D4 ;add 4 bytes for y value and $7FFF word
|
|||
|
;add 2 more for the $7FFF if the last line
|
|||
|
ADD.L D4,D4 ;double, just 'cause I feel like it!
|
|||
|
MOVE.L D4,max2Add(A6) ;save max. bytes for a given line
|
|||
|
|
|||
|
MOVEQ #32,D7 ;(side effect: clear high word of D7)
|
|||
|
DIVU D7,D0 ;number of longs = width/32
|
|||
|
|
|||
|
;get a mask for the rightmost long into rightMask
|
|||
|
|
|||
|
MOVE.L D0,D3 ;save remainder(hi word)
|
|||
|
SWAP D3 ;get remainder from width/32
|
|||
|
MOVEQ #-1,D1 ;default rightmost long mask
|
|||
|
TST.W D3 ;zero remainder?
|
|||
|
BEQ.S @0 ;yes, $FFFF is a good mask
|
|||
|
ADDQ.W #1,D0 ;we need one more long
|
|||
|
SUB.W D3,D7 ;32 - remainder = zero bits to shift in
|
|||
|
ASL.L D7,D1 ;get proper mask
|
|||
|
@0 MOVE.L D1,rightMask(A6)
|
|||
|
EXT.L D0
|
|||
|
MOVE.L D0,rowLongs(A6) ;save # of longs
|
|||
|
ASL.L #2,D0 ;longs => bytes
|
|||
|
|
|||
|
;get the scanline buffer (D0 = number of bytes per line)
|
|||
|
_NewHandle clear ;get a scanline buffer (of zeroes)
|
|||
|
BNE BMRBadEmpty ;if we failed then return a NIL handle
|
|||
|
|
|||
|
MOVE.L A0,slHandle(A6) ;save buffer handle
|
|||
|
|
|||
|
;figure the number of lines
|
|||
|
|
|||
|
MOVE.L D2,D3
|
|||
|
SWAP D3 ;get top
|
|||
|
MOVE.W bounds+bottom(A1),D0 ;get bottom
|
|||
|
SUB.W D3,D0 ;bottom - top
|
|||
|
BLE BMREmptyOut ;if empty rect. then empty region
|
|||
|
|
|||
|
MOVE.W D0,numLines(A6) ;number of lines
|
|||
|
|
|||
|
MOVE.L baseAddr(A1),a4 ;point to start of map
|
|||
|
MOVE.W #rgnData,D7 ;initial region size
|
|||
|
|
|||
|
;OK, now we start the loops.
|
|||
|
; A1 will point to the bitmap long,
|
|||
|
; A2 to the region.
|
|||
|
; A3 points to the current scanline buffer long.
|
|||
|
; A4 will point to the row in the map.
|
|||
|
; A5 points to the current word (= size + A2)
|
|||
|
; D1 holds the current long (modified).
|
|||
|
; D2 holds the leftmost coordinate of bitmap.bounds.
|
|||
|
; D3 has the y coordinate, and
|
|||
|
; D4 the x coordinate (high word stays clear!).
|
|||
|
; D5 has number of longs remaining for current line.
|
|||
|
; D6 holds the (on or off) value of the "beam" (for the line).
|
|||
|
; D7 holds the size outside the longword loop (used as scratch while nibbling).
|
|||
|
; (we assume at the very end that D7's high word has remained clear)
|
|||
|
|
|||
|
;
|
|||
|
; goto 32-bit mode
|
|||
|
;
|
|||
|
moveq #true32b,d0 ;switch to 32 bit addressing
|
|||
|
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
|
|||
|
move.b d0,MMUsave(a6) ;save previous state for later
|
|||
|
|
|||
|
BMRHScramLine
|
|||
|
MOVE.L regionH(A6),A2
|
|||
|
MOVE.L (A2),d0
|
|||
|
_StripAddress ;clean it up <9>
|
|||
|
move.l d0,a2 ;point to start of region
|
|||
|
|
|||
|
BMRLineLoop
|
|||
|
LEA (A2,D7.L),A5 ;point to new region start + size
|
|||
|
|
|||
|
MOVE.L handSize(A6),D1 ;get handle size
|
|||
|
SUB.l D7,D1 ;handle size - region size
|
|||
|
CMP.L max2Add(A6),D1 ;is there enough for worst case on next line?
|
|||
|
BGE.S @1 ;skippy if so
|
|||
|
|
|||
|
MOVE.L handSize(A6),D0 ;get handle size
|
|||
|
ADD.L max2Add(A6),D0 ;add more than enough for worst case on next line
|
|||
|
MOVE.L D0,handSize(A6) ;save new size
|
|||
|
;
|
|||
|
; go back to previous mode
|
|||
|
;
|
|||
|
move.b MMUsave(a6),d0 ;get previous MMU state in d0
|
|||
|
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
|
|||
|
|
|||
|
MOVE.L handSize(A6),d0 ;save new size
|
|||
|
MOVE.L regionH(A6),A0 ;region handle
|
|||
|
_SetHandleSize
|
|||
|
BNE BMRBadEmpty ;if we failed then return a NIL handle
|
|||
|
;
|
|||
|
; goto 32-bit mode
|
|||
|
;
|
|||
|
moveq #true32b,d0 ;switch to 32 bit addressing
|
|||
|
_rSwapMMUMode
|
|||
|
BRA.S BMRHScramLine ;rederef. handle and recompute current pointer
|
|||
|
@1
|
|||
|
|
|||
|
MOVE.W D2,D4 ;get current x coordinate from left
|
|||
|
MOVEQ #0,D6 ;beam initially off
|
|||
|
MOVE.L A4,A1 ;start of current line into map pointer
|
|||
|
MOVE.L rowLongs(A6),D5 ;longs remaining for current line
|
|||
|
MOVE.L slHandle(A6),A3 ;A3 points to the current "differences" long
|
|||
|
MOVE.L (A3),A3
|
|||
|
|
|||
|
; Note: within this loop we assume that nothing will be done to move the heap
|
|||
|
|
|||
|
MOVE.W D3,D0 ;get y position
|
|||
|
BSR OutputRgnWord ;output y pos to region
|
|||
|
|
|||
|
MOVE.l D7,startSize(A6) ;save size at line start (a la Derwood)
|
|||
|
BRA NextBMRLong ;enter the long loop
|
|||
|
|
|||
|
BMRLongLoop
|
|||
|
MOVE.L (A1)+,D0 ;fetch the next long for this line
|
|||
|
BMRLastLEntry
|
|||
|
MOVE.L (A3),D1 ;get differences long
|
|||
|
|
|||
|
EOR.L D0,D1 ;compute the differences
|
|||
|
BNE BMRDiff ;if not the same, skip ahead
|
|||
|
|
|||
|
BMRSame
|
|||
|
;since we want to skip this long (it matches the previous line) we need to
|
|||
|
;put out an ip if the beam is on
|
|||
|
TST.B D6 ;beam on?
|
|||
|
BEQ.S @1 ;skip if not
|
|||
|
MOVE.W D4,(A5)+ ;pump it out
|
|||
|
MOVEQ #0,D6 ;beam off
|
|||
|
|
|||
|
@1
|
|||
|
ADD.W #32,D4 ;slip to next long's x coordinate
|
|||
|
@2 ADDQ.W #4,A3 ;to next changes buffer long
|
|||
|
BRA NextBMRLong
|
|||
|
|
|||
|
;----------------------------------------------------------------------------------------
|
|||
|
|
|||
|
; Start of State Machine
|
|||
|
|
|||
|
; Handle state 0001
|
|||
|
|
|||
|
BMRState1
|
|||
|
ADDQ.W #3,D4 ;bump x by 3
|
|||
|
State1Common
|
|||
|
MOVE.W D4,(A5)+ ;generate one
|
|||
|
;Tog1StateDone
|
|||
|
ADDQ.W #1,D4 ;bump x by one more
|
|||
|
TogStateDone
|
|||
|
NOT.B D6 ;toggle state
|
|||
|
RTS
|
|||
|
|
|||
|
; Handle state 0010
|
|||
|
|
|||
|
BMRState2
|
|||
|
ADDQ.W #2,D4 ;bump x by 2
|
|||
|
MOVE.W D4,(A5)+ ;generate one
|
|||
|
Gen1BumpBy1
|
|||
|
BSR.S Gen1InvPoint ;and another one
|
|||
|
BumpBy1
|
|||
|
ADDQ.W #1,D4 ;bump once more
|
|||
|
RTS ;state doesn't change
|
|||
|
|
|||
|
; Handle state 0011
|
|||
|
|
|||
|
BMRState3
|
|||
|
ADDQ.W #2,D4 ;bump x by 2
|
|||
|
MOVE.W D4,(A5)+ ;generate one
|
|||
|
ADDQ.W #2,D4 ;bump
|
|||
|
BRA.S TogStateDone ;toggle the state
|
|||
|
|
|||
|
; Handle state 0100
|
|||
|
|
|||
|
BMRState4
|
|||
|
BSR.S Gen1InvPoint
|
|||
|
BSR.S Gen1InvPoint
|
|||
|
BumpBy2
|
|||
|
ADDQ.W #2,D4
|
|||
|
RTS
|
|||
|
|
|||
|
; Handle state 0101
|
|||
|
|
|||
|
BMRState5
|
|||
|
BSR.S BMRState4 ;start out as state 4
|
|||
|
SUBQ #1,D4
|
|||
|
BRA.S State1Common ;use common code
|
|||
|
|
|||
|
; Handle state 0110
|
|||
|
|
|||
|
BMRState6
|
|||
|
BSR.S Gen1InvPoint
|
|||
|
ADDQ.W #1,D4
|
|||
|
BRA.S Gen1BumpBy1
|
|||
|
|
|||
|
; Handle state 0111
|
|||
|
|
|||
|
BMRState7
|
|||
|
BSR.S Gen1InvPoint
|
|||
|
ADDQ.W #3,D4
|
|||
|
BRA.S TogStateDone
|
|||
|
|
|||
|
; Gen1InvPoint bumps x by one and then generates a horizontal inversion point
|
|||
|
|
|||
|
Gen1InvPoint
|
|||
|
ADDQ.W #1,D4 ;bump by 1, first
|
|||
|
MOVE.W D4,(A5)+ ;add x value (ip) to region
|
|||
|
RTS
|
|||
|
|
|||
|
; Handle State 1000
|
|||
|
|
|||
|
BMRState8
|
|||
|
MOVE.W D4,(A5)+
|
|||
|
BSR.S Gen1InvPoint
|
|||
|
ADDQ.W #3,D4
|
|||
|
RTS
|
|||
|
|
|||
|
; Handle State 1001
|
|||
|
|
|||
|
BMRState9
|
|||
|
MOVE.W D4,(A5)+
|
|||
|
BSR.S Gen1InvPoint
|
|||
|
ADDQ.W #2,D4
|
|||
|
BRA.S State1Common
|
|||
|
|
|||
|
; Handle State 1010 (most complicated case)
|
|||
|
|
|||
|
BMRState10
|
|||
|
MOVE.W D4,(A5)+
|
|||
|
BSR.S Gen1InvPoint
|
|||
|
BSR.S Gen1InvPoint
|
|||
|
BRA.S Gen1BumpBy1
|
|||
|
|
|||
|
; Handle State 1011
|
|||
|
|
|||
|
BMRState11
|
|||
|
MOVE.W D4,(A5)+
|
|||
|
BSR.S Gen1InvPoint
|
|||
|
BSR.S Gen1InvPoint
|
|||
|
ADDQ.W #2,D4
|
|||
|
BRA.S TogStateDone
|
|||
|
|
|||
|
; Handle State 1100
|
|||
|
|
|||
|
BMRState12
|
|||
|
MOVE.W D4,(A5)+
|
|||
|
ADDQ.W #2,D4
|
|||
|
MOVE.W D4,(A5)+
|
|||
|
BRA.S BumpBy2
|
|||
|
|
|||
|
; Handle State 1101
|
|||
|
|
|||
|
BMRState13
|
|||
|
BSR.S BMRState12
|
|||
|
SUBQ #1,D4
|
|||
|
BRA.S State1Common
|
|||
|
|
|||
|
; Handle State 1110
|
|||
|
|
|||
|
BMRState14
|
|||
|
MOVE.W D4,(A5)+
|
|||
|
ADDQ.W #3,D4
|
|||
|
MOVE.W D4,(A5)+
|
|||
|
BRA.S BumpBy1
|
|||
|
|
|||
|
; State table
|
|||
|
|
|||
|
BMRHandler
|
|||
|
BRA.S BMRState0
|
|||
|
BRA.S BMRState1
|
|||
|
BRA.S BMRState2
|
|||
|
BRA.S BMRState3
|
|||
|
|
|||
|
BRA.S BMRState4
|
|||
|
BRA.S BMRState5
|
|||
|
BRA.S BMRState6
|
|||
|
BRA.S BMRState7
|
|||
|
|
|||
|
BRA.S BMRState8
|
|||
|
BRA.S BMRState9
|
|||
|
BRA.S BMRState10
|
|||
|
BRA.S BMRState11
|
|||
|
|
|||
|
BRA.S BMRState12
|
|||
|
BRA.S BMRState13
|
|||
|
BRA.S BMRState14
|
|||
|
|
|||
|
; Handle State 15 or 1111
|
|||
|
|
|||
|
BMRState15
|
|||
|
MOVE.W D4,(A5)+ ;generate one now
|
|||
|
NOT.B D6 ;toggle the state
|
|||
|
|
|||
|
; Handle State 0 or 0000
|
|||
|
|
|||
|
BMRState0
|
|||
|
ADDQ.W #4,D4
|
|||
|
RTS
|
|||
|
|
|||
|
; End of the State Guys
|
|||
|
|
|||
|
;----------------------------------------------------------------------------------------
|
|||
|
|
|||
|
BMRDiff
|
|||
|
MOVE.L D0,(A3)+ ;fix up scanline buffer for next time
|
|||
|
|
|||
|
; this long is different from the last one, so output a bunch
|
|||
|
; of inversion points by pumping it through the state machine, a nibble
|
|||
|
; at a time.
|
|||
|
|
|||
|
MOVEQ #3,D7 ;4 bytes to process (D7 high word clear)
|
|||
|
MOVEQ #0,D0 ;prevent need to mask for first nibble
|
|||
|
|
|||
|
; here is the loop where we feed it through a nibble at a time.
|
|||
|
; it's worth it to special case a whole byte of 0
|
|||
|
|
|||
|
BMRByteLoop
|
|||
|
ROL.L #8,D1 ;get next (topmost) byte
|
|||
|
TST.B D1 ;is it zero?
|
|||
|
BNE.S BMRNibble ;if not, 4 bits at a time
|
|||
|
|
|||
|
TST.B D6
|
|||
|
BNE.S BMRNibble ;if beam on, must pass through
|
|||
|
|
|||
|
;the top 8 are zero, so we can save some time
|
|||
|
|
|||
|
ADDQ.W #8,D4 ;bump x
|
|||
|
BRA.S BMRNextByte
|
|||
|
|
|||
|
;take care of the rightmost long for a line
|
|||
|
|
|||
|
BMRLastLong
|
|||
|
MOVE.L (A1),D0 ;fetch the long from the bitmap
|
|||
|
AND.L rightMask(A6),D0 ;mask off right bits that aren't in map
|
|||
|
BRA BMRLastLEntry ;go process this long
|
|||
|
|
|||
|
; handle the first nibble
|
|||
|
|
|||
|
BMRNibble
|
|||
|
MOVE.B D1,D0 ;get byte
|
|||
|
EOR.B D6,D0 ;invert nibble when beam is on
|
|||
|
LSR.B #4,D0 ;get 1st nibble
|
|||
|
ADD.W D0,D0 ;double for word index
|
|||
|
|
|||
|
JSR BMRHandler(D0.W) ;invoke the handler
|
|||
|
|
|||
|
; handle the second nibble
|
|||
|
|
|||
|
MOVE.B D1,D0 ;get byte again
|
|||
|
EOR.B D6,D0 ;invert nibble when beam is on
|
|||
|
AND.W #%1111,D0 ;mask to it
|
|||
|
ADD.W D0,D0 ;double for word index
|
|||
|
|
|||
|
JSR BMRHandler(D0.W) ;invoke the handler
|
|||
|
|
|||
|
BMRNextByte
|
|||
|
DBRA D7,BMRByteLoop ;loop for all 8 nibbles
|
|||
|
|
|||
|
; bump to the next long
|
|||
|
|
|||
|
NextBMRLong
|
|||
|
SUBQ.W #1,D5 ;decrement longword index
|
|||
|
BGT BMRLongLoop ;not at end, loop for whole line
|
|||
|
BEQ.S BMRLastLong ;process last long for this line
|
|||
|
|
|||
|
; we've reached the end of the (this) line
|
|||
|
BMREOL
|
|||
|
MOVE.l A5,D7 ;current region pointer
|
|||
|
SUB.l A2,D7 ;figga region size
|
|||
|
CMP.l startSize(A6),D7 ;did we add inv. pts to this line?
|
|||
|
BEQ.S BMRNoLine ;br = no, so back up
|
|||
|
BLT BMR64KErr ;if the size decreased, we overflowed
|
|||
|
|
|||
|
; if the state is on, generate one last inversion point
|
|||
|
|
|||
|
TST.B D6
|
|||
|
BEQ.S @1
|
|||
|
|
|||
|
MOVE.W D4,(A5)+ ;generate a last one
|
|||
|
ADDQ.l #2,D7 ;keep sizable advantage
|
|||
|
@1
|
|||
|
|
|||
|
; end the scan line with the traditional $7FFF
|
|||
|
|
|||
|
BSR.S OutputLastRgnWord
|
|||
|
|
|||
|
BMREOL2
|
|||
|
ADDQ.W #1,D3 ;bump y position
|
|||
|
MOVE.W D2,D4 ;start x at left again
|
|||
|
ADD.W rowNumBytes(A6),A4 ;bump to next row in map
|
|||
|
SUBQ.W #1,numLines(A6)
|
|||
|
BGT BMRLineLoop ;if we're not done then do next line
|
|||
|
BLT.S BMRFinis ;br if really done
|
|||
|
|
|||
|
; as the last line process an imaginary line of zeroes to end the region…
|
|||
|
move.b MMUsave(a6),d0 ;get previous MMU state in d0 <9>
|
|||
|
_rSwapMMUMode ;(can trash a0/a1/a2, d0/d1/d2) <9>
|
|||
|
|
|||
|
MOVE.L rowLongs(A6),D0
|
|||
|
ASL.L #2,D0 ;longs => bytes
|
|||
|
_NewHandle clear ;get a full line of zero bits
|
|||
|
BNE BMRBadEmpty ;if we failed then return a NIL handle
|
|||
|
MOVE.L A0,lastLineH(A6) ;save handle
|
|||
|
MOVE.L (A0),A4 ;start of current line
|
|||
|
;
|
|||
|
; Since we just allocated this handle, there is no need to strip it since the flags are guaranteed
|
|||
|
; to be zero.
|
|||
|
;
|
|||
|
moveq #true32b,d0 ;switch to 32 bit addressing <9>
|
|||
|
_rSwapMMUMode ; <9>
|
|||
|
BRA BMRHScramLine ;do this last one (and rederef handle)
|
|||
|
|
|||
|
BMRNoLine
|
|||
|
SUBQ.L #2,A5 ;back up pointer
|
|||
|
SUBQ.l #2,D7 ;back down size
|
|||
|
BRA.S BMREOL2 ;go for next line
|
|||
|
|
|||
|
; Append the "end of line" token to the region
|
|||
|
|
|||
|
OutputLastRgnWord
|
|||
|
MOVE.W #$7FFF,D0
|
|||
|
|
|||
|
; OutputRgnWord takes the word in D0, appends it to the region,
|
|||
|
; and leaves the condition codes set for ADDQ.l D7 (which contains the length)
|
|||
|
|
|||
|
OutputRgnWord
|
|||
|
MOVE.W D0,(A5)+ ;put a word to the region
|
|||
|
ADDQ.l #2,D7 ;ink the size
|
|||
|
RTS
|
|||
|
|
|||
|
|
|||
|
; all done: Restore MMU Mode, clean up, and output the final $7FFF
|
|||
|
;
|
|||
|
BMRFinis
|
|||
|
move.b MMUsave(a6),d0 ;get previous MMU state in d0
|
|||
|
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
|
|||
|
|
|||
|
MOVE.L lastLineH(A6),A0
|
|||
|
_DisposHandle ;get rid of that last line of zeroes
|
|||
|
|
|||
|
CMP.l #10,D7 ;is region empty of inversion points?
|
|||
|
BEQ.S BMREmptyOut ;skip if so (it's an empty region)
|
|||
|
|
|||
|
BSR.S OutputLastRgnWord ;put End-O-Region ($7FFF) word
|
|||
|
;
|
|||
|
; check if rgn > 64K
|
|||
|
;
|
|||
|
cmp.l #$0000FFFF,d7
|
|||
|
BGT.S BMR64KErr ;if larger than $FFFF, we overflowed!
|
|||
|
|
|||
|
; find the smallest rectangle that encompasses all the inversion points
|
|||
|
; A0 will point to the current region word, A1 to the start of the line
|
|||
|
; D1 will have the smallest x, D2 the largest x, D4 will contain $7FFF
|
|||
|
; D3 gets the smallest y value (which we know at the start)
|
|||
|
|
|||
|
LEA rgnData(A2),A0 ;point A0 past the rgnBBox
|
|||
|
MOVE.W #$7FFF,D4
|
|||
|
MOVE.W D4,D1 ;smallest x so far = $7FFF
|
|||
|
MOVE.W #$8000,D2 ;largest x so far = -32768
|
|||
|
MOVE.W (A0),D3 ;smallest y there is
|
|||
|
BRA.S BMRPackStart ;enter loop
|
|||
|
|
|||
|
BMRPackY
|
|||
|
MOVE.L A0,A1 ;remember where the y value is (sort of)
|
|||
|
|
|||
|
CMP.W (A0)+,D1 ;less than smallest x so far?
|
|||
|
BLE.S @1 ;skip if not
|
|||
|
MOVE.W -2(A0),D1 ;new smallest x
|
|||
|
|
|||
|
@1 CMP.W (A0)+,D4 ;end of line?
|
|||
|
BNE.S @1 ;if not then keep looking
|
|||
|
|
|||
|
CMP.W -4(A0),D2 ;last x greater than largest x so far?
|
|||
|
BGE.S BMRPackStart ;skip if not
|
|||
|
MOVE.W -4(A0),D2 ;new largest x
|
|||
|
|
|||
|
BMRPackStart
|
|||
|
MOVE.W (A0)+,D0 ;get next word (y value or $7FFF)
|
|||
|
CMP.W D4,D0 ;if $7FFF then we're done
|
|||
|
BNE.S BMRPackY ;otherwise loop
|
|||
|
|
|||
|
SWAP D3 ;top into top word
|
|||
|
MOVE.W D1,D3 ;left into bottom word
|
|||
|
MOVE.W -2(A1),D4 ;bottom (from last y at start of line)
|
|||
|
SWAP D4 ;move bottom to high word
|
|||
|
MOVE.W D2,D4 ;get right
|
|||
|
|
|||
|
CMP.l #28,D7 ;size = 28? (do we have a rect. region?)
|
|||
|
BEQ.S BMRRect ;skip if so
|
|||
|
|
|||
|
BRA.S BMROut ;return complex region
|
|||
|
|
|||
|
;the region would exceed 64K, so we have to error out, man
|
|||
|
BMR64KErr
|
|||
|
move.b MMUsave(a6),d0 ;get previous MMU state in d0
|
|||
|
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
|
|||
|
MOVE.W #rgnTooBigErr,D0 ;if >32K needed return error
|
|||
|
|
|||
|
;we come here after failing a SetHandleSize (or NewHandle)
|
|||
|
BMRBadEmpty
|
|||
|
MOVE.W D0,result(A6) ;OSErr function result
|
|||
|
|
|||
|
; emptify the region on errors (or when it should be empty with no error)
|
|||
|
BMREmptyOut
|
|||
|
MOVE.L regionH(A6),A0 ;handle to region
|
|||
|
MOVE.L (A0),A2 ;point to it
|
|||
|
CLR.L D3 ;(0, 0) to topLeft
|
|||
|
CLR.L D4 ;(0, 0) to botRight
|
|||
|
|
|||
|
BMRRect
|
|||
|
MOVEQ #10,D7 ;the size of the region = 10
|
|||
|
|
|||
|
;output the region with size (longword, high word clear) in D7
|
|||
|
;D3 comes in with topLeft, D4 with botRight
|
|||
|
BMROut
|
|||
|
MOVE.W D7,(A2)+ ;the size of the region
|
|||
|
MOVE.L D3,(A2)+ ;topLeft to rgnBBox
|
|||
|
MOVE.L D4,(A2) ;botRight to rgnBBox
|
|||
|
MOVE.L D7,D0 ;size
|
|||
|
MOVE.L regionH(A6),A0 ;handle to region
|
|||
|
_SetHandleSize
|
|||
|
|
|||
|
BMRDspSL
|
|||
|
MOVE.L slHandle(A6),A0
|
|||
|
_DisposHandle ;get rid of the scanline buffer (even if NIL)
|
|||
|
|
|||
|
BMRDone
|
|||
|
MOVEM.L (SP)+,A2-A5/D3-D7 ;restore work registers
|
|||
|
UNLK A6
|
|||
|
MOVE.L (SP)+,A0 ;pop return address
|
|||
|
ADD #paramSize,SP ;pop params
|
|||
|
JMP (A0)
|
|||
|
ENDWITH
|
|||
|
|
|||
|
ENDPROC
|