home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 11
/
CD_ASCQ_11_0294.iso
/
maj
/
666
/
xfill.asm
< prev
next >
Wrap
Assembly Source File
|
1993-10-03
|
11KB
|
534 lines
;-----------------------------------------------------------------------
; MODULE XFILL
;
; Point functions all MODE X 256 Color resolutions
;
; Compile with Tasm.
; C callable.
;
;
; ****** XLIB - Mode X graphics library ****************
; ****** ****************
; ****** Written By Themie Gouthas ****************
;
; egg@dstos3.dsto.gov.au
; teg@bart.dsto.gov.au
;-----------------------------------------------------------------------
COMMENT $
This code is my interpretation of a simple "C" flood filling algorithm
titled:
* A Seed Fill Algorithm
* by Paul Heckbert
* from "Graphics Gems", Academic Press, 1990
The original C source is readily available at numerous internet archive
sites.
Its been modified and optimized for tweaked 13h modes (Mode X derrivatives).
The most fundamental change is that it fills a column at a time rather
than a row at a time to minimize the number of plane setting "out"s.
And of course the border fill variant was a logical and useful further
modification.
Both functions return the number of pixels filled..
WARNING: These fill functions make heavy use of the stack and no stack
checking is performed, so caution is advised.
$
include xlib.inc
include xfill.inc
.code
_x_flood_fill proc
ARG X:word,Y:word,PgOfs:word,Color:word
LOCAL len:word,y1:word,y2:word,deltax:word,floodval:word,\
stackptr:word,FillCount:word=STK
push bp
mov bp,sp
sub sp,STK
mov [FillCount],0
push di si
mov si,[Y]
mov ax,[_ScrnLogicalByteWidth]
mul si ;offset of pixel's scan line in page
mov di,[X]
mov bx,di
shr di,2 ;X/4 = offset of pixel in scan line
add di,ax ;offset of pixel in page
add di,[PgOfs] ;offset of pixel in display memory
mov ax,SCREEN_SEG
mov es,ax ;point ES:DI to the pixel's address
;---- Select read plane ------
mov ah,bl
and ah,011b ;AH = pixel's plane
mov al,READ_MAP ;AL = index in GC of the Read Map reg
mov dx,GC_INDEX ;set the Read Map to read the pixel's
out dx,ax ; plane
mov al,es:[di] ;read the pixel's color
cmp al,byte ptr Color ;Is dest pixel the same color as the flood?
je @@Done2 ; if it is abort.
mov cx,_LeftClip ; Is the dest. pixel out of the clipping window?
sal cx,2 ; if not abort.
cmp bx,cx
jl @@Done2
mov cx,_RightClip
sal cx,2
cmp bx,cx
jg @@Done2
mov floodval,ax ; store the color to flood
;-- Push fill segment ---
push bx ; X
push si ; Y
push si ; Y
mov cx,1 ; deltaX (either 1 or -1 indicating direction)
push cx
mov stackptr,1
mov deltax,-1 ; Initialize first column scan
mov y1,si ; then bypass some of the preliminary crap in
mov y2,si ; the main fill loop
jmp short @@entry
@@Done2:mov ax,[FillCount]
pop si di
mov sp,bp
pop bp
ret
@@NextScanCol:
dec stackptr
js @@Done2
@@WhileLoop:
pop cx ; get fill segment from stack
mov deltax,cx ; ie deltaX, Y1, Y2, X
pop ax
mov y2,ax
pop si
mov y1,si
pop bx
sub ax,si ; Acculmulate number of filled pixels
jns @@PositiveY
neg ax
@@PositiveY:
add FillCount,ax
add bx,cx ; move to new column according to deltaX
mov ax,bx ; Make sure the column is within the clipping
sar ax,2 ; rectangle
cmp ax,_LeftClip
jl @@NextScanCol
cmp ax,_RightClip
jg @@NextScanCol
;---- Select read plane ------
mov ah,bl
and ah,011b ;AH = pixel's plane
mov al,READ_MAP ;AL = index in GC of the Read Map reg
mov dx,GC_INDEX ;set the Read Map to read the pixel's
out dx,ax ; plane
@@entry:
;---- Select write plane ------
mov cl,bl
and cl,011b ;CL = pixel's plane
mov ax,0100h + MAP_MASK ;AL = index in SC of Map Mask reg
shl ah,cl ;set only the bit for the pixel's
; plane to 1
mov dx,SC_INDEX ;set the Map Mask to enable only the
out dx,ax ; pixel's plane
mov ax,_ScrnLogicalByteWidth ; store logical width in CX
mov cx,ax ; get offset of scan row
mul si ; set ES:DI ->
mov di,bx ; address of pixel at x,y1
shr di,2
add di,ax
add di,PgOfs ;ES:DI->first pixel of column segment to fill
mov dx,di ; save y1 offset for after upward fill
mov al,byte ptr Color
mov ah,byte ptr floodval
@@FillColUpward:
cmp si,_TopClip ; Dont fill beyond clip boundaries
jl @@UpwardFillDone
cmp es:[di],ah ; if flood pixel color then replace
jne @@UpwardFillDone ; with new color otherwise column is done
mov es:[di],al
sub di,cx
dec si
jmp short @@FillColUpward
@@UpwardFillDone:
cmp si,y1
jge @@Skip
inc si
mov len,si
cmp si,y1
jge @@AtColumnTop
push bx ; queue an upward leak check
push si
mov ax,y1
dec ax
push ax
mov ax,deltax
neg ax
push ax
inc stackptr
@@AtColumnTop:
mov si,y1
mov di,dx
add di,cx
inc si
@@ColumnLoop:
mov ah,byte ptr floodval
mov al,byte ptr Color
@@DownwardFill:
cmp si,_BottomClip
jg @@DownwardFillDone
cmp es:[di],ah
jne @@DownwardFillDone
mov es:[di],al
add di,cx
inc si
jmp short @@DownwardFill
@@DownwardFillDone:
push bx ; queue an upward leak check
mov ax,len
push ax
mov ax,si
dec ax
push ax
mov ax,deltax
push ax
inc stackptr
mov ax,y2
inc ax
cmp si,ax
jle @@Skip
push bx ; queue a downward leak check
push ax
mov ax,si
dec ax
push ax
mov ax,deltax
neg ax
push ax
inc stackptr
@@Skip:
mov ah,byte ptr floodval
mov dx,y2
@@Backtrack:
add di,cx
inc si
cmp si,dx
jg @@BacktrackDone
cmp byte ptr es:[di],ah
jne @@Backtrack
@@BacktrackDone:
mov len,si
cmp si,dx
jle @@ColumnLoop
dec stackptr
js @@Done
jmp @@WhileLoop
@@Done:
mov ax,[FillCount]
pop si di
mov sp,bp
pop bp
ret
_x_flood_fill endp
_x_boundary_fill proc
ARG X:word,Y:word,PgOfs:word,BoundaryColor:word,Color:word
LOCAL len:word,y1:word,y2:word,deltax:word,y1_offs:word,\
stackptr:word,FillCount:word=STK
push bp
mov bp,sp
sub sp,STK
mov [FillCount],0
push di si
mov si,[Y]
mov ax,[_ScrnLogicalByteWidth]
mul si ;offset of pixel's scan line in page
mov di,[X]
mov bx,di
shr di,2 ;X/4 = offset of pixel in scan line
add di,ax ;offset of pixel in page
add di,[PgOfs] ;offset of pixel in display memory
mov ax,SCREEN_SEG
mov es,ax ;point ES:DI to the pixel's address
;---- Select read plane ------
mov ah,bl
and ah,011b ;AH = pixel's plane
mov al,READ_MAP ;AL = index in GC of the Read Map reg
mov dx,GC_INDEX ;set the Read Map to read the pixel's
out dx,ax ; plane
mov al,es:[di] ;read the pixel's color
cmp al,byte ptr Color ;Is dest pixel the same color as the flood?
je @@Done2
cmp al,byte ptr BoundaryColor ;Is dest pixel the same color
je @@Done2 ; as the boundary color?
mov cx,_LeftClip ; Is the dest. pixel out of the clipping window?
sal cx,2
cmp bx,cx
jl @@Done2
mov cx,_RightClip
sal cx,2
cmp bx,cx
jg @@Done2
push bx ; X
push si ; Y
push si ; Y
mov cx,1 ; DX
push cx
mov stackptr,1
mov al,byte ptr BoundaryColor
mov byte ptr [Color+1],al
mov deltax,-1
mov y1,si
mov y2,si
jmp short @@entry
@@Done2:mov ax,[FillCount]
pop si di
mov sp,bp
pop bp
ret
@@NextScanCol:
dec stackptr
js @@Done2
@@WhileLoop:
pop cx
mov deltax,cx
pop ax
mov y2,ax
pop si
mov y1,si
pop bx
add bx,cx ; bx = X
sub ax,si ; Acculmulate number of filled pixels
jns @@PositiveY
neg ax
@@PositiveY:
add FillCount,ax
mov ax,bx ; Make sure the column is within the clipping
sar ax,2 ; rectangle
cmp ax,_LeftClip
jl @@NextScanCol
cmp ax,_RightClip
jg @@NextScanCol
;---- Select read plane ------
mov ah,bl
and ah,011b ;AH = pixel's plane
mov al,READ_MAP ;AL = index in GC of the Read Map reg
mov dx,GC_INDEX ;set the Read Map to read the pixel's
out dx,ax ; plane
@@entry:
;---- Select write plane ------
mov cl,bl
and cl,011b ;CL = pixel's plane
mov ax,0100h + MAP_MASK ;AL = index in SC of Map Mask reg
shl ah,cl ;set only the bit for the pixel's
; plane to 1
mov dx,SC_INDEX ;set the Map Mask to enable only the
out dx,ax ; pixel's plane
mov ax,_ScrnLogicalByteWidth ; store logical width in CX
mov cx,ax ; get offset of scan row
mul si ; set ES:DI ->
mov di,bx ; address of pixel at x,y1
shr di,2
add di,ax
add di,PgOfs
mov y1_offs,di ; save y1 offset for after upward fill
mov ax,Color ; al = Color ah = BoundaryColor
@@FillColUpward:
cmp si,_TopClip ; Dont fill beyond clip boundaries
jl @@UpwardFillDone
mov dl,es:[di]
cmp dl,ah
je @@UpwardFillDone
cmp dl,al
je @@UpwardFillDone
mov es:[di],al
sub di,cx
dec si
jmp short @@FillColUpward
@@UpwardFillDone:
cmp si,y1
jge @@Skip
inc si
mov len,si
cmp si,y1
jge @@AtColumnTop
push bx ; queue an upward leak check
push si
mov ax,y1
dec ax
push ax
mov ax,deltax
neg ax
push ax
inc stackptr
@@AtColumnTop:
mov si,y1
mov di,y1_offs
add di,cx
inc si
@@ColumnLoop:
mov ax,Color ; al = Color ah = BoundaryColor
@@DownwardFill:
cmp si,_BottomClip
jg @@DownwardFillDone
cmp es:[di],ah
je @@DownwardFillDone
cmp es:[di],al
je @@DownwardFillDone
mov es:[di],al
add di,cx
inc si
jmp short @@DownwardFill
@@DownwardFillDone:
push bx ; queue an upward leak check
mov ax,len
push ax
mov ax,si
dec ax
push ax
mov ax,deltax
push ax
inc stackptr
mov ax,y2
inc ax
cmp si,ax
jle @@Skip
push bx ; queue a downward leak check
push ax
mov ax,si
dec ax
push ax
mov ax,deltax
neg ax
push ax
inc stackptr
@@Skip:
mov ax,Color ; al = Color ah = BoundaryColor
@@Backtrack:
add di,cx
inc si
cmp si,y2
jg @@BacktrackDone
mov dl,byte ptr es:[di]
cmp dl,al
je @@Backtrack
cmp dl,ah
je @@Backtrack
@@BacktrackDone:
mov len,si
cmp si,y2
jle @@ColumnLoop
dec stackptr
js @@Done
jmp @@WhileLoop
@@Done:
mov ax,[FillCount]
pop si di
mov sp,bp
pop bp
ret
_x_boundary_fill endp
end