1 ;-----------------------------------------------------------
\r
3 ; MXLN.ASM - Line function
\r
4 ; Copyright (c) 1993,1994 by Alessandro Scotti
\r
6 ;-----------------------------------------------------------
\r
13 MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'
\r
14 ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING
\r
16 EXTRN mx_BytesPerLine : WORD
\r
17 EXTRN mx_VideoSegment : WORD
\r
19 EXTRN mx_ClipX1 : WORD
\r
20 EXTRN mx_ClipY1 : WORD
\r
21 EXTRN mx_ClipX2 : WORD
\r
22 EXTRN mx_ClipY2 : WORD
\r
24 tblDrawFunc LABEL WORD
\r
30 ;-----------------------------------------------------------
\r
32 ; Draws a line from (X1,Y1) to (X2,Y2) using the Bresenham
\r
36 ; X1, Y1 = start point
\r
37 ; X2, Y2 = end point
\r
38 ; Color = line color
\r
39 ; Op = raster operator
\r
43 ; Note: the end point (X2,Y2) *IS* drawed. I don't like this very much
\r
44 ; but clipping is much simpler.
\r
61 WritePlane:BYTE = AUTO_SIZE
\r
71 jc @@Exit ; Line is full clipped
\r
75 xchg ax, si ; SI = X1, AX = X2
\r
78 ; Swap points, we want X1 < X2
\r
79 xchg si, cx ; Swap X1 and X2
\r
80 xchg bx, dx ; Swap Y1 and Y2
\r
86 mov cx, [mx_BytesPerLine] ; We don't need X2 anymore
\r
90 neg cx ; Move from bottom to top
\r
91 neg ax ; Get absolute value of AX
\r
96 ; Get pixel address and write plane
\r
98 mul [mx_BytesPerLine]
\r
99 mov cx, si ; CX = X1
\r
102 add si, ax ; SI = pixel offset
\r
106 mov [WritePlane], ah
\r
108 out dx, ax ; Set write plane
\r
109 mov ax, [mx_VideoSegment]
\r
110 mov ds, ax ; DS:SI points to (X1,Y1)
\r
112 ; Select the function to handle the drawing loop
\r
114 mov al, BYTE PTR [Op]
\r
124 out dx, ax ; Set logical function
\r
130 ; Horizontal, vertical and diagonal lines are not optimized yet
\r
136 call tblDrawFunc[bx]
\r
138 ; Reset logical function if needed
\r
139 cmp BYTE PTR [Op], OP_MOVE
\r
150 ;-----------------------------------------------------------
\r
152 ; Checks the coordinates of a line against the active
\r
154 ; Uses a variation of the Cohen-Sutherland algorithm developed
\r
155 ; by Victor Duvanenko.
\r
161 ; CF = set if line is full clipped
\r
162 ; AX, BX = clipped X1, Y1
\r
163 ; CX, DX = clipped X2, Y2
\r
167 subClipLine PROC NEAR
\r
168 mov di, ax ; Copy X1 to DI and free AX
\r
169 mov si, dx ; Copy Y2 to SI and free DX
\r
170 ; Compute clip codes for point (X2,Y2)=(CX,SI)
\r
172 @@P2X1: cmp cx, [mx_ClipX1]
\r
175 @@P2X2: cmp cx, [mx_ClipX2]
\r
178 @@P2Y1: cmp si, [mx_ClipY1]
\r
181 @@P2Y2: cmp si, [mx_ClipY2]
\r
184 @@P2XY: mov [P2], al
\r
185 ; Compute clip codes for point (X1,Y1)=(DI,BX)
\r
187 @@P1X1: cmp di, [mx_ClipX1]
\r
190 @@P1X2: cmp di, [mx_ClipX2]
\r
193 @@P1Y1: cmp bx, [mx_ClipY1]
\r
196 @@P1Y2: cmp bx, [mx_ClipY2]
\r
199 @@P1XY: mov [P1], al
\r
200 ; Check codes for trivial cases
\r
202 test al, ah ; Is line invisible?
\r
203 jnz @@FullClip ; Yes, exit
\r
204 or ah, al ; Both points clipped?
\r
205 jz @@Done ; Yes, exit
\r
213 mov al, [P1] ; Init clipping code
\r
216 test al, al ; Is first point clipped?
\r
217 jnz @@ClipX1 ; No, continue
\r
218 xchg cx, di ; Swap points...
\r
220 xchg al, [P2] ; ...and codes
\r
221 ; Clip left: Y1 = Y1 + DeltaY*(mx_ClipX1-X1)/DeltaX
\r
225 mov ax, [mx_ClipX1]
\r
227 mov di, [mx_ClipX1]
\r
229 ; Clip right: Y1 = Y1 + DeltaY*(mx_ClipX2-X1)/DeltaX
\r
233 mov ax, [mx_ClipX2]
\r
235 mov di, [mx_ClipX2]
\r
241 cmp bx, [mx_ClipY2]
\r
244 cmp bx, [mx_ClipY1]
\r
248 ; Clip top: X1 = X1 + DeltaX*(mx_ClipY1-Y1)/DeltaY
\r
252 mov ax, [mx_ClipY1]
\r
254 mov bx, [mx_ClipY1]
\r
256 ; Clip bottom: X1 = X1 + DeltaX*(mx_ClipY2-Y1)/DeltaY
\r
258 mov ax, [mx_ClipY2]
\r
260 mov bx, [mx_ClipY2]
\r
266 cmp di, [mx_ClipX1]
\r
269 cmp di, [mx_ClipX2]
\r
289 ; Called when Width >= Height and Op = OP_MOVE
\r
290 subWidthMove PROC NEAR
\r
292 neg di ; Initialize error term
\r
299 mov ah, [WritePlane]
\r
300 mov bl, BYTE PTR [Color]
\r
319 ; Called when Width < Height and Op = OP_MOVE
\r
320 subHeightMove PROC NEAR
\r
322 neg di ; Initialize error term
\r
328 mov bl, BYTE PTR [Color]
\r
329 mov ah, [WritePlane]
\r
340 rol ah, 1 ; Next write plane
\r
341 adc si, 0 ; Bump video offset if plane overflows
\r
343 sub di, [ErrorSub] ; Adjust error down
\r
349 ; Called when Width >= Height and Op <> OP_MOVE
\r
350 subWidthOp PROC NEAR
\r
352 neg di ; Initialize error term
\r
359 mov ah, [WritePlane]
\r
360 mov bl, BYTE PTR [Color]
\r
364 mov bh, ds:[si] ; Latch data
\r
380 ; Called when Width < Height and Op <> OP_MOVE
\r
381 subHeightOp PROC NEAR
\r
383 neg di ; Initialize error term
\r
389 mov bl, BYTE PTR [Color]
\r
390 mov ah, [WritePlane]
\r
402 rol ah, 1 ; Next write plane
\r
403 adc si, 0 ; Bump video offset if plane overflows
\r
405 sub di, [ErrorSub] ; Adjust error down
\r