1 ;-----------------------------------------------------------
\r
3 ; MXPG.ASM - Convex polygon fill
\r
4 ; Copyright (c) 1994 by Alessandro Scotti
\r
6 ;-----------------------------------------------------------
\r
13 ;-----------------------------------------------------------
\r
15 ; "Local" definitions
\r
22 ; Do NOT change order!
\r
28 MAXSCANCOLUMNS EQU POLYSCANBUFSIZE / SIZE TSCAN
\r
30 MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'
\r
31 ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING
\r
33 EXTRN mx_VideoSegment : WORD
\r
34 EXTRN mx_CodeSegment : WORD
\r
35 EXTRN mx_BytesPerLine : WORD
\r
36 EXTRN mx_ClipX1 : WORD
\r
37 EXTRN mx_ClipY1 : WORD
\r
38 EXTRN mx_ClipX2 : WORD
\r
39 EXTRN mx_ClipY2 : WORD
\r
40 EXTRN mx_ScanBuffer : NEAR
\r
42 ;-----------------------------------------------------------
\r
44 ; Scans an edge using the DDA (digital differential analyzer) algorithm.
\r
47 ; DS:BX = pointer to start point (X1, Y1)
\r
48 ; DS:SI = pointer to end point (X2, Y2)
\r
49 ; ES:DI = pointer to edge buffer
\r
51 ; ES:DI = updated pointer to edge buffer
\r
53 ; must preserve DS:SI.
\r
57 sub cx, ds:[bx].X ; Get width
\r
65 sub ax, bx ; Get height
\r
66 jg @@T2B ; Scan top to bottom
\r
67 jl @@B2T ; Scan bottom to top
\r
69 ; Special case: vertical line
\r
78 ; Scan top to bottom
\r
85 xchg ax, bx ; BP:BX = fixed 16:16 step
\r
96 ; Scan bottom to top
\r
115 pop bp ; Restore BP
\r
119 ;-----------------------------------------------------------
\r
121 ; Fills a convex polygon with the specified color.
\r
124 ; Count = number of vertexes
\r
125 ; Map = indexes of points and colors (integer)
\r
126 ; Points = array of points (integer X, Y coordinates)
\r
127 ; Color = base color
\r
131 ; vertexes must be in counterclockwise order, arrays are 0-based.
\r
133 mxFillPoly PROC FAR
\r
137 Count:WORD = ARG_SIZE
\r
138 LOCAL WritePlane:BYTE:2, \
\r
139 ScanOffsetT:WORD, \
\r
140 ScanOffsetB:WORD, \
\r
151 BoxY2::WORD = AUTO_SIZE
\r
153 .push ds, si, es, di
\r
156 ; Check that at least three vertexes are specified
\r
161 ;------------------------------
\r
162 ; Find bounding box for polygon
\r
164 lds si, [Points] ; Pointer to vertex array
\r
166 mov [BoxX2], -32768
\r
168 mov [BoxY2], -32768
\r
172 mov bx, es:[di] ; Get index of vertex
\r
173 .shl bx, 2 ; Get offset in point array
\r
178 mov ax, ds:[bx].X ; Get X coordinate
\r
201 ; Repeat thru all points
\r
203 inc di ; Next map entry
\r
210 ;---------------------------------
\r
211 ; Check if polygon is full clipped
\r
213 cmp ax, [mx_ClipX1] ; Is poly full clipped?
\r
216 cmp bx, [mx_ClipX2] ; Is poly full clipped?
\r
218 sub ax, bx ; Get width
\r
219 jle @@Exit ; Exit if not positive
\r
221 cmp ax, [mx_ClipY1] ; Is poly full clipped?
\r
224 cmp bx, [mx_ClipY2] ; Is poly full clipped?
\r
226 sub ax, bx ; Get height
\r
227 jle @@Exit ; Exit if not positive
\r
230 shl [Count], 1 ; We'll work with word offsets
\r
231 mov es, [mx_CodeSegment]
\r
235 mov ax, OFFSET mx_ScanBuffer
\r
236 mov [ScanOffsetT], ax
\r
237 mov si, [MinIdxT] ; Offset of bottom point index
\r
239 lds bx, [Map] ; DS:BX -> map table
\r
240 mov di, ds:[bx+si] ; Index of top point #1
\r
241 dec si ; Next point
\r
247 mov [MinIdxT], si ; Save new index of top point
\r
248 mov si, ds:[bx+si] ; Get index of top point #2
\r
249 .shl di, 2 ; Convert indexes to offsets
\r
251 lds bx, [Points] ; DS:BX -> point array
\r
252 add si, bx ; DS:SI -> top point #2
\r
253 add bx, di ; DS:BX -> top point #1
\r
254 mov di, [ScanOffsetT]
\r
255 call subScan ; Scan edge
\r
256 mov [ScanOffsetT], di
\r
258 cmp si, [MaxIdx] ; End of edge?
\r
259 jne @@STLoop ; No, continue
\r
263 mov ax, OFFSET mx_ScanBuffer + OFFSET Y2
\r
264 mov [ScanOffsetB], ax
\r
265 mov si, [MinIdxB] ; Offset of bottom point index
\r
267 lds bx, [Map] ; DS:BX -> map table
\r
268 mov di, ds:[bx+si] ; Index of bottom point #1
\r
269 inc si ; Next bottom point
\r
275 mov [MinIdxB], si ; Save new index of bottom point
\r
276 mov si, ds:[bx+si] ; Get index of bottom point #2
\r
277 .shl di, 2 ; Convert indexes to offsets
\r
279 lds bx, [Points] ; DS:BX -> point array
\r
280 add si, bx ; DS:SI -> top point #2
\r
281 add bx, di ; DS:BX -> top point #1
\r
282 mov di, [ScanOffsetB]
\r
283 call subScan ; Scan edge
\r
284 mov [ScanOffsetB], di
\r
286 cmp si, [MaxIdx] ; End of edge?
\r
287 jne @@SBLoop ; No, continue
\r
289 ;--------------------
\r
290 ; Clip left and right
\r
291 mov si, OFFSET mx_ScanBuffer
\r
294 sub cx, ax ; CX = bounding box width
\r
295 mov bx, [mx_ClipX1]
\r
297 jle @@ClipL1 ; No need to clip left
\r
298 sub cx, bx ; Update width
\r
299 add ax, bx ; BoxX1 = mx_ClipX1
\r
301 .shl bx, 2 ; Warning!!! This is an hand-coded
\r
302 add si, bx ; multiply by the size of TSCAN
\r
305 add bx, cx ; Last scan column
\r
306 sub bx, [mx_ClipX2]
\r
307 jle @@ClipL2 ; No need to clip right
\r
308 sub cx, bx ; Clip right
\r
310 test cx, cx ; Is clipped width positive?
\r
311 jle @@Exit ; No, exit
\r
312 mov [ScanCount], cx ; Save number of columns to draw
\r
313 mov [ScanOffsetT], si ; Remember offset of (clipped) buffer
\r
314 mov ds, [mx_CodeSegment] ; DS:SI -> scan buffer
\r
316 ;------------------------------
\r
317 ; Check if Y clipping is needed
\r
319 cmp ax, [mx_ClipY1]
\r
320 jl @@ClipTB ; Need to clip top
\r
322 cmp ax, [mx_ClipY2]
\r
323 jg @@ClipTB ; Need to clip bottom
\r
324 jmp @@ClipYExit ; Skip Y clipping
\r
326 ;--------------------
\r
327 ; Clip top and bottom
\r
329 mov di, cx ; DI = scan count
\r
330 inc di ; Increment count for pre-loop test
\r
333 dec di ; Any column left?
\r
334 jz @@ClipYExit ; No, exit
\r
336 mov ax, ds:[si].Y1 ; Y1
\r
337 mov cx, ds:[si].Y2 ; Y2
\r
338 mov dx, [mx_ClipY2]
\r
339 cmp ax, dx ; Full clipped?
\r
340 jg @@ClipYClip ; Yes, skip this column
\r
341 cmp cx, dx ; Need to clip bottom?
\r
342 jle @@ClipY1 ; No, continue
\r
346 sub bx, dx ; Clip distance
\r
347 sub cx, ax ; Height
\r
351 mov dx, [mx_ClipY1]
\r
352 cmp cx, dx ; Full top clipped?
\r
353 jl @@ClipYClip ; Yes, skip
\r
354 sub cx, ax ; Get height
\r
355 jle @@ClipYClip ; Skip if not positive
\r
356 cmp ax, dx ; Need to clip top?
\r
357 jge @@ClipYLoop ; No, continue
\r
359 mov ds:[si].Y1, dx ; Y1 = mx_ClipY1
\r
360 sub dx, ax ; DX = number of pixels clipped
\r
362 ja @@ClipYLoop ; Not clipped, continue
\r
364 mov ds:[si].Y1, -1 ; Mark column as clipped
\r
370 mov es, [mx_VideoSegment]
\r
371 mov si, [ScanOffsetT]
\r
372 mov cl, BYTE PTR [BoxX1] ; Init write plane
\r
376 mov [WritePlane], al
\r
380 test ax, ax ; Was column clipped?
\r
381 js @@DrawNext ; Yes, skip
\r
383 sub cx, ax ; CX = height
\r
385 mul [mx_BytesPerLine] ; Get pixel address
\r
388 mov ah, [WritePlane]
\r
393 mov dx, [mx_BytesPerLine]
\r
407 rol [WritePlane], 1
\r
408 adc [BoxX1], 0 ; Bump pointer to video memory if needed
\r
415 .pop ds, si, es, di
\r