;*DDK*************************************************************************/
;
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
        page    ,132
;/*****************************************************************************
;*
;* SOURCE FILE NAME = polybitm.asm 
;*
;* DESCRIPTIVE NAME = Polyline bitmap line drawing device driver. 
;*
;*
;* VERSION      V2.0
;*
;* DATE         03/30/87
;*
;* DESCRIPTION  
;*
;*     This module contains all of the routines called by POLYLINE.ASM
;*     to draw solid polylines in memory bitmaps.  The routines are basically 
;*     broken into six different cases.  Lines are categorized as x major,
;*     y major or diagonal.  They are also broken down into simple and 
;*     non-simple, or standard, cases; where simple means horizontal, vertical
;*     or on a diagonal.  These simple cases can be drawn much faster than
;*     the standard cases, and are therefore broken out from the rest.
;*    
;*     There are similar routines in PLYSOLID.ASM for solid lines to the EGA,
;*     and POLYSTYL.ASM for styled lines to EGA or bitmaps.  While these 
;*     routines are all quite similar, they are separated purely for speed
;*     considerations.  POLYLINE.ASM is the dispatching module for all of 
;*     these routines, and the run length slice algorithm DDA, which all of
;*     these routines are based on, is explained in that module.
;*    
;*     Near the end of this module, there are three output routines. 
;*     bm_set_to_zero sets masked bits in the destination byte to zeros.
;*     bm_set_to_one sets masked bits in the destination byte to ones.
;*     bm_not_dest inverts the masked bits in the destination byte.  The
;*     address of one of these routines, or zero, in the case where we want
;*     to do nothing, is loaded into BitmapProc.  Then when drawing lines in
;*     a bitmap, BitmapProc is called to output each byte to the bitmap.
;*    
;*     At the end of this module, there are two routines, check_segment_overflow
;*     and dont_check_overflow.  The address of check_segment_overflow is loaded
;*     into OverflowProc if the destination is a huge bitmap and the line being
;*     drawn is in multiple segments.  Otherwise dont_check_overflow is loaded
;*     into OverflowProc.  The first routine checks and corrects for segment
;*     overflow.  The second routine simply does a near return.  Such a 
;*     complicated routine as this might seem strange, but it allows us to us
;*     the same code for huge and small bitmaps, with minimal speed change.
;*    
;*     Huge bitmaps are stored on a scan line basis.  For example, if we have
;*     three color planes, the the bitmap is stored as a red scan line, a green
;*     scan line, a blue scan line, a red scan line, and so on.  Because of this
;*     format, there will most likely be some left over bytes at the end of the
;*     segment.  These will have to be accounted for when crossing segment
;*     boundaries.  
;*              
;*              
;* FUNCTIONS    setup_poly_frame_1
;*              
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   03/30/87                     Written by Kent Settle   (kentse)
;*
;*****************************************************************************/


        .xlist
        include cmacros.inc
INCL_DDIPATHS   equ     1
        include pmgre.inc
        include driver.inc
        include display.inc
        include polyline.inc
        .list

sBegin  Code
        assumes cs,Code

cProc   setup_poly_frame_1,<FAR,NODATA>
        include plylocal.inc                      
cBegin  nogen
cEnd    nogen

        public  bitmap_solid_horizontal

;/***************************************************************************
;*
;* PUBLIC ROUTINE  bitmap_solid_horizontal 
;*
;* DESCRIPTION   = Draws a solid horizontal line into a bitmap.
;*
;*                  Registers Destroyed: 
;*                        CX,SI          
;*                  Registers Preserved: 
;*                        DX,BP,ES       
;*
;* INPUT         = DS:DI = bitmap address      
;*                 BL = rotating bit mask      
;*                 CX = number of bits to draw 
;*
;* OUTPUT        = DS:DI = new bitmap address 
;*                 BL = new rotating bit mask 
;*                 
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing

bitmap_solid_horizontal    proc    near
        mov     si,wBitmapROP

;/*
;** calculate the start mask, end mask, and byte count
;*/

        dec     cx                                ; CX = number of bits to move over
        mov     ax,cx                             ; AX = ending bit number
        shr     ax,3                              ; AX = number of bytes to move
        and     cx,7                              ; CX = number of bits to rotate
        mov     bh,bl                             ; BH = initial bit
        ror     bl,cl                             ; BL = ending bit
        mov     cx,ax                             ; CX = number of bytes to move
        cmp     bh,bl                             ; adjust the count for byte wrap
        adc     cx,0                              ; CX = bytes to touch - 1
        mov     al,bh                             ; AL = initial bit
        mov     bh,bl                             ; BH = ending bit
        neg     bh                                ; BH = ending mask
        add     al,al
        dec     al                                ; AL = initial mask
        jcxz    just_do_the_last

;/*
;** put out the first byte
;*/

        mov     ah,al
        and     ax,si
        not     al
        and     [di],al
        xor     [di],ah
        inc     di

;/*
;** do any intermediate bytes
;*/

        dec     cx
        jz      finish_up
        mov     ax,si
        not     al
output_loop:
        and     [di],al
        xor     [di],ah
        inc     di
        loop    output_loop

;/*
;** do the last byte (combine end mask and previous mask)
;*/

finish_up:
        mov     al,0FFh
just_do_the_last:
        and     al,bh
        mov     ah,al
        and     ax,si
        not     al
        and     [di],al
        xor     [di],ah
        ret
bitmap_solid_horizontal    endp

        public  bitmap_solid_vertical

;/***************************************************************************
;*
;* PUBLIC ROUTINE  bitmap_solid_vertical
;*
;* DESCRIPTION   = Draws a solid vertical line into a bitmap. 
;*
;*                 Registers Destroyed:  
;*                       CX,SI,DX        
;*                 Registers Preserved:  
;*                       BP,ES           
;*
;* INPUT         = DS:DI = bitmap address      
;*                 BL = rotating bit mask      
;*                 CX = number of bits to draw 
;*
;* OUTPUT        = DS:DI = new bitmap address   
;*                 BL = new rotating bit mask   
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing

bitmap_solid_vertical    proc                     near
        mov     si,cbScanAddressDelta
        mov     dx,wScan
        mov     al,bl                             ; get rotating bit mask
        mov     ah,al
        and     ax,wBitmapROP
        not     al
        dec     cx
        jz      bv_last_pixel
bv_loop:

;/*
;** output a pel
;*/

        and     [di],al
        xor     [di],ah

;/*
;** move to the next scan
;*/

        add     di,si
        dec     dx                                ; check for huge overflow
        loopnz  bv_loop
        jnz     bv_last_pixel

;/*
;** move to next huge scan
;*/

        mov     dx,ds                             ; advance the segment
        add     dx,selHugeDelta
        mov     ds,dx
        assumes ds,nothing
        add     di,cbHugeScanDelta               ; wrap the surface address
        mov     dx,cScansPerSegment              ; reset wScan
        or      cx,cx
        jnz     bv_loop

;/*
;** do the last pel
;*/

bv_last_pixel:
        and     [di],al
        xor     [di],ah
        mov     wScan,dx
        ret
bitmap_solid_vertical    endp

        public  bitmap_solid_diagonal

;/***************************************************************************
;*
;* PUBLIC ROUTINE  bitmap_solid_diagonal
;*
;* DESCRIPTION   = Draws a solid diagonal line into a bitmap. 
;*
;*                 Registers Destroyed: 
;*                       CX,DX,SI       
;*                 Registers Preserved: 
;*                       BP,ES          
;*
;* INPUT         = DS:DI = bitmap address       
;*                 BL = rotating bit mask       
;*                 CX = number of bits to draw  
;*                 
;* OUTPUT        = DS:DI = new EGA address    
;*                 BL = new rotating bit mask 
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;*                       ----Pseudo-Code----
;* bitmap_solid_diagonal
;* {
;*    // this routine draws BitCount diagonal bits.  since we are drawing
;*    // a diagonal segment, x and y coordinates will change with each
;*    // bit drawn.
;*
;*    while (BitCount--)
;*    {
;*        output byte to bitmap memory;
;*        rotate bit mask;
;*        increment DI if done with byte;
;*        DI += AddVertStep;                 // jump to next scan line.
;*    }
;*
;*    BL = rotating bit mask;
;*                                           // return with BL = rotating bitmask,
;*    return();                              // DS:DI => current destination byte.
;* }
;*
;***************************************************************************/

        assumes ds,nothing
        assumes es,nothing

bitmap_solid_diagonal    proc                     near
        mov     si,cbScanAddressDelta
        mov     dx,wScan
        mov     al,bl                             ; get rotating bit mask
        mov     ah,al
        and     ax,wBitmapROP
        not     al
        dec     cx
        jz      bd_last_pixel
bd_loop:

;/*
;** output a pel
;*/

        and     [di],al
        xor     [di],ah

;/*
;** move to the next scan
;*/

        ror     al,1
        ror     ah,1
        ror     bl,1
        adc     di,si
        dec     dx                                ; check for huge overflow
        loopnz  bd_loop
        jnz     bd_last_pixel

;/*
;** move to next huge scan
;*/

        mov     dx,ds                             ; advance the segment
        add     dx,selHugeDelta
        mov     ds,dx
        assumes ds,nothing
        add     di,cbHugeScanDelta                ; wrap the surface address
        mov     dx,cScansPerSegment               ; reset wScan
        or      cx,cx
        jnz     bd_loop

;/*
;** do the last pel
;*/

bd_last_pixel:
        and     [di],al
        xor     [di],ah
        mov     wScan,dx
        ret
bitmap_solid_diagonal    endp

        public  bitmap_styled_horizontal

;/***************************************************************************
;*
;* PUBLIC ROUTINE   bitmap_styled_horizontal  
;*
;* DESCRIPTION   =  Draws a styled horizontal line into a bitmap. 
;*
;*                  Registers Destroyed:
;*                        CX,SI         
;*                  Registers Preserved:
;*                        DX,BP,ES      
;*
;* INPUT         = DS:DI = bitmap address        
;*                 BL = rotating bit mask        
;*                 CX = number of bits to draw   
;*                 
;* OUTPUT        = DS:DI = new bitmap address
;*                 BL = new rotating bit mask
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing

bitmap_styled_horizontal    proc    near


;/*
;** load all quantities into registers
;*/

        mov     al,bl                             ; AL = rotating bit mask
        mov     ah,al
        and     ax,wBitmapROP
        not     al                                ; AX = AND mask, XOR mask
        mov     dl,bActiveStyleCounter            ; DL = style error
        mov     bh,bActiveStyleMask               ; BH = style mask
        mov     si,wStyleStepHorz                 ; SI = style step

;/*
;** run the loop
;*/

        dec     cx
        jz      bsh_last_byte
bsh_loop:

;/*
;** draw the pixel if the mask says so
;*/

        or      bh,bh
        jns     @F
        and     [di],al
        xor     [di],ah
@@:

;/*
;** advance to the next pixel
;*/

        ror     al,1
        ror     ah,1
        ror     bl,1
        adc     di,0

;/*
;** advance the style mask
;*/

        xor     dh,dh
        add     dx,si
        xchg    cl,dh
        rol     bh,cl
        mov     cl,dh
        loop    bsh_loop

;/*
;** draw the last pixel if the mask says so
;*/

bsh_last_byte:
        or      bh,bh
        jns     @F
        and     [di],al
        xor     [di],ah
@@:

;/*
;** unload all registers
;*/

        mov     bActiveStyleCounter,dl
        mov     bActiveStyleMask,bh
        ret
bitmap_styled_horizontal    endp

        public  bitmap_styled_vertical

;/***************************************************************************
;*
;* PUBLIC ROUTINE   bitmap_styled_vertical  
;*
;* DESCRIPTION   =  Draws a styled vertical line into a bitmap.  
;*
;*                  Registers Destroyed:    
;*                        CX,SI,DX          
;*                  Registers Preserved:    
;*                        BP,ES             
;*
;* INPUT         = DS:DI = bitmap address      
;*                 BL = rotating bit mask      
;*                 CX = number of bits to draw 
;*                 
;* OUTPUT        = DS:DI = new bitmap address   
;*                 BL = new rotating bit mask   
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing

bitmap_styled_vertical    proc                     near
        mov     si,wScan
        mov     dl,bActiveStyleCounter            ; DL = style error
        mov     bh,bActiveStyleMask               ; BH = style mask
        mov     al,bl                             ; get rotating bit mask
        mov     ah,al
        and     ax,wBitmapROP
        not     al
        dec     cx
        jz      bsv_last_pixel
bsv_loop:

;/*
;** output a pel
;*/

        or      bh,bh
        jns     @F
        and     [di],al
        xor     [di],ah
@@:

;/*
;** advance the style mask
;*/

        xor     dh,dh
        add     dx,wStyleStepVert
        xchg    cl,dh
        rol     bh,cl
        mov     cl,dh

;/*
;** move to the next scan
;*/

        add     di,cbScanAddressDelta
        dec     si
        loopnz  bsv_loop
        jnz     bsv_last_pixel

;/*
;** move to next huge scan
;*/

        mov     si,ds                            ; advance the segment
        add     si,selHugeDelta
        mov     ds,si
        assumes ds,nothing
        add     di,cbHugeScanDelta               ; wrap the surface address
        mov     si,cScansPerSegment              ; reset wScan
        or      cx,cx
        jnz     bsv_loop

;/*
;** do the last pel
;*/

bsv_last_pixel:
        or      bh,bh
        jns     @F
        and     [di],al
        xor     [di],ah
@@:     mov     bActiveStyleCounter,dl
        mov     bActiveStyleMask,bh
        mov     wScan,si
        ret
bitmap_styled_vertical    endp

        public  bitmap_styled_diagonal

;/***************************************************************************
;*
;* PUBLIC ROUTINE   bitmap_styled_diagonal  
;*
;* DESCRIPTION   =  Draws a styled diagonal line into a bitmap.                     
;*
;*                   Registers Destroyed:     
;*                         CX,DX,SI           
;*                   Registers Preserved:     
;*                         BP,ES              
;*
;* INPUT         = DS:DI = bitmap address      
;*                 BL = rotating bit mask      
;*                 CX = number of bits to draw 
;*                 
;* OUTPUT        = DS:DI = new EGA address      
;*                 BL = new rotating bit mask   
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;*                      -----Pseudo-Code--
;* bitmap_styled_diagonal
;* {
;*    // this routine draws BitCount diagonal bits.  since we are drawing
;*    // a diagonal segment, x and y coordinates will change with each
;*    // bit drawn.
;*
;*    while (BitCount--)
;*    {
;*        output byte to bitmap memory;
;*        rotate bit mask;
;*        increment DI if done with byte;
;*        DI += AddVertStep;                 // jump to next scan line.
;*    }
;*
;*    BL = rotating bit mask;
;*                                           // return with BL = rotating bitmask,
;*    return();                              // DS:DI => current destination byte.
;* }
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing

bitmap_styled_diagonal    proc                     near
        mov     si,wScan
        mov     dl,bActiveStyleCounter            ; DL = style error
        mov     bh,bActiveStyleMask               ; BH = style mask
        mov     al,bl                             ; get rotating bit mask
        mov     ah,al
        and     ax,wBitmapROP
        not     al
        dec     cx
        jz      bsd_last_pixel
bsd_loop:

;/*
;** output a pel
;*/

        or      bh,bh
        jns     @F
        and     [di],al
        xor     [di],ah
@@:

;/*
;** advance the style mask
;*/

        xor     dh,dh
        add     dx,wStyleStepDiag
        xchg    cl,dh
        rol     bh,cl
        mov     cl,dh

;/*
;** move to the next scan
;*/

        ror     ah,1
        ror     al,1
        ror     bl,1
        adc     di,cbScanAddressDelta
        dec     si
        loopnz  bsd_loop
        jnz     bsd_last_pixel

;/*
;** move to next huge scan
;*/

        mov     si,ds                            ; advance the segment
        add     si,selHugeDelta
        mov     ds,si
        assumes ds,nothing
        add     di,cbHugeScanDelta               ; wrap the surface address
        mov     si,cScansPerSegment              ; reset wScan
        or      cx,cx
        jnz     bsd_loop

;/*
;** do the last pel
;*/

bsd_last_pixel:
        or      bh,bh
        jns     @F
        and     [di],al
        xor     [di],ah
@@:     mov     bActiveStyleCounter,dl
        mov     bActiveStyleMask,bh
        mov     wScan,si
        ret
bitmap_styled_diagonal    endp

sEnd    Code

        end
