This repository has been archived by the owner on Nov 29, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
PutLine.a
205 lines (168 loc) · 8.11 KB
/
PutLine.a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
.INCLUDE GRAFTYPES.TEXT
;-----------------------------------------------------------
;
; --> PUTLINE.TEXT
;
; Decompose a line segment into a list of inversion points.
;
;
.PROC PUTLINE,5
.REF SETSIZE
;------------------------------------------------------------------
;
; PROCEDURE PutLine(pt1,pt2: Point; dst: Handle; VAR index,bufMax: INTEGER);
;
; INVERSION POINTS FOR A LINE SEGMENT
;
; SP OFFSETS OF PARAMETERS:
;
PARAMSIZE .EQU 20 ;TOTAL SIZE OF PARAMETERS
PT1 .EQU PARAMSIZE+4-4 ;LONG, POINT (VALUE)
PT2 .EQU PT1-4 ;LONG, POINT (VALUE)
BUF .EQU PT2-4 ;LONG, HANDLE
INDEX .EQU BUF-4 ;LONG, (VAR)
BUFMAX .EQU INDEX-4 ;LONG, (VAR)
MOVEM.L D3-D7/A2-A4,-(SP) ;SAVE REGS, 8*4 ==> 32
;-----------------------------------------------------
;
; IF LINE IS VERTICAL, IGNORE IT.
;
MOVE PT1+H+32(SP),D2 ;GET 1ST POINT'S HORIZ
MOVE PT2+H+32(SP),D4 ;GET 2ND POINT'S HORIZ
CMP D2,D4 ;IS THIS A VERTICAL LINE ?
BEQ GOHOME ;YES, IGNORE IT
;------------------------------------------------------
;
; CALC BYTESNEEDED = 8 * ( Min(ABS(dh),ABS(dv)) + 1)
;
MOVE D2,D0 ;GET H1
SUB D4,D0 ;SUBTRACT H2
BPL.S DHPOS ;BR IF DH POS
NEG D0 ;ELSE TAKE ABSOLUTE VALUE
DHPOS MOVE PT1+V+32(SP),D1 ;GET V1
SUB PT2+V+32(SP),D1 ;SUBTRACT V2
BPL.S DVPOS ;BR IF DV POS
NEG D1 ;ELSE TAKE ABSOLUTE VALUE
DVPOS CMP D1,D0 ;IS DH <= DV ?
BLE.S DHLESS ;YES, CONTINUE
MOVE D1,D0 ;NO, PUT MIN(DH,DV) INTO D0
DHLESS ADD #1,D0 ;CALC MIN(DH,DV)+1
LSL #3,D0 ;TIMES EIGHT FOR BYTESNEEDED
MOVE.L BUF+32(SP),A3 ;GET DSTHANDLE
MOVE.L INDEX+32(SP),A4 ;POINT TO CURRENT INDEX
;-----------------------------------------------------
;
; GROW POINT BUFFER AS NECESSARY TO HOLD BYTESNEEDED
;
ADD (A4),D0 ;NEWSIZE := INDEX + BYTESNEEDED
MOVE.L BUFMAX+32(SP),A0 ;POINT TO BUFMAX
CMP (A0),D0 ;DO WE HAVE TO GROW DSTBUF ?
BLE.S NOGROW ;NO, CONTINUE
ADD #512,D0 ;GROW IN CHUNKS
MOVE D0,(A0) ;UPDATE NEW BUFMAX
MOVE.L A3,-(SP) ;PUSH DSTBUF HANDLE
MOVE D0,-(SP) ;PUSH NEW BUFMAX
JSR SETSIZE ;MAKE THE BUFFER BIGGER
MOVE PT1+H+32(SP),D2 ;RESTORE CLOBBERED REG
NOGROW
MOVE.L (A3),A3 ;DE-REFERENCE DSTHANDLE
ADD (A4),A3 ;ADD INDEX TO BUFPTR
;-----------------------------------------------------
;
; IF LINE IS HORIZONTAL, PUT ITS TWO ENDPOINTS
;
MOVE PT1+V+32(SP),D1 ;GET 1ST POINT'S VERT
MOVE PT2+V+32(SP),D3 ;GET 2ND POINT'S VERT
CMP D1,D3 ;IS THIS A HORIZONTAL LINE ?
BNE.S SLANTED ;NO, BRANCH
MOVE D1,(A3)+ ;PUT V1 VERT COORD
MOVE D2,(A3)+ ;PUT H1 HORIZ COORD
MOVE D3,(A3)+ ;PUT V2 VERT COORD
MOVE D4,(A3)+ ;PUT H2 HORIZ COORD
BRA.S DONE ;UPDATE INDEX AND QUIT
;------------------------------------------------------
;
; LINE IS SLANTED. DIVIDE IT INTO HORIZONTAL SLABS
; AND PUT THE TWO ENDPOINTS OF EACH SLAB.
;
; START BY SORTING POINTS VERTICALLY.
;
SLANTED BGT.S NOSWAP ;SKIP IF ALREADY IN ORDER
EXG D1,D3 ;SORT POINTS BY VERTICAL
EXG D2,D4 ;SWAP HORIZ TO MATCH
NOSWAP MOVE D1,D6 ;INIT V TO TOPV
;------------------------------------------------------------
;
; CALCULATE FIXED POINT SLOPE = FixRatio(dh,dv);
;
CLR.L -(SP) ;MAKE ROOM FOR FCN RESULT
MOVE D4,-(SP) ;PUSH BOTTOM HORIZ
SUB D2,(SP) ;CALC DH
MOVE D3,-(SP) ;PUSH BOTTOM VERT
SUB D1,(SP) ;CALC DV
_FixRatio ;CALC FIXED POINT SLOPE
MOVE.L (SP)+,D7 ;POP RESULT
;---------------------------------------------------------
;
; SET UP STARTING HORIZ FIXED POINT.
;
MOVE.W D2,D1
SWAP D1 ;HORIZ.INT := TOP HORIZ
MOVE.W #$8000,D1 ;HORIZ.FRACT := 1/2
;
; ADJUST HORIZ DEPENDING ON SIGN AND MAGNITUDE OF SLOPE
;
MOVE.L D7,D0 ;COPY SLOPE
ASR.L #1,D0 ;CALC SLOPE/2
ADD.L D0,D1 ;HORIZ := HORIZ + SLOPE/2
MOVE.L #$00010000,D0
TST.L D7 ;IS SLOPE NEG ?
BMI.S NEGSLOPE ;YES, CONTINUE
CMP.L D0,D7 ;IS SLOPE < ONE ?
BGE.S SLOPEOK ;NO, CONTINUE
ADD.L D7,D1 ;ADD SLOPE TO LEFTEDGE
BRA.S SLOPEOK ;CONTINUE
NEGSLOPE CMP.L #$FFFF0000,D7 ;IS SLOPE > -ONE ?
BGE.S SLOPEOK ;YES, CONTINUE
ADD.L D0,D1 ;YES, HORIZ := HORIZ + 1
SLOPEOK
;------------------------------------------------------
;
; FOR VERT:=TOPV TO BOTV-1 ADD SLOPE TO HORIZ AND PUT SLABS
;
MOVE D2,D5 ;H:=TOPH
LOOP SWAP D1 ;GET HORIZ.INT INTO D1 LOWER
CMP D1,D5 ;HAS HORIZ.INT CHANGED ?
BEQ.S NOCHNG ;NO, CONTINUE
MOVE D6,(A3)+ ;YES, PUT VERT COORD
MOVE D5,(A3)+ ;PUT OLD HORIZ COORD
MOVE.W D1,D5 ;OLDH := HORIZ.INT
MOVE D6,(A3)+ ;PUT VERT COORD
MOVE D5,(A3)+ ;PUT NEW HORIZ COORD
NOCHNG SWAP D1 ;PUTBACK HORIZ.INT INTO D1 UPPER
ADD #1,D6 ;VERT:=VERT+1
ADD.L D7,D1 ;ADD SLOPE TO HORIZ
CMP D6,D3 ;IS VERT AT BOTTOM VERT YET ?
BNE LOOP ;NO, GO FOR MORE
;-------------------------------------------------
;
; FINISH UP LAST SLAB
;
CMP D4,D5 ;IS OLDH = BOTTOM H ?
BEQ.S DONE ;YES, CONTINUE
MOVE D6,(A3)+ ;NO, PUT VERT COORD
MOVE D5,(A3)+ ;PUT HORIZ COORD
MOVE D6,(A3)+ ;PUT VERT COORD
MOVE D4,(A3)+ ;PUT BOTTOM H COORD
;---------------------------------------------------
;
; UPDATE INDEX TO REFLECT POINTS ADDED.
;
DONE MOVE.L BUF+32(SP),A0 ;GET DSTHANDLE
SUB.L (A0),A3 ;INDEX := BUFPTR-BUFSTART
MOVE A3,(A4) ;UPDATE INDEX
GOHOME MOVEM.L (SP)+,D3-D7/A2-A4 ;RESTORE REGS
MOVE.L (SP)+,A0
ADD.W #PARAMSIZE,A7
JMP (A0)
.END