home *** CD-ROM | disk | FTP | other *** search
- ;-----------------------------------------------------------------------
- ; 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
-