;*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)
;*
;*****************************************************************************/
        
        .386

        .xlist

INCL_DDIPATHS   equ     1
DINCL_ENABLE            equ     1
DINCL_BITMAP            equ     1

        include pmgre.inc
        include driver.inc
        include display.inc
        include polyline.inc
        include extern.inc
        include protos.inc

        .list

        .MODEL FLAT
    
        ASSUME  CS:FLAT,SS:FLAT,DS:FLAT,ES:FLAT

        .DATA

        .CODE
        
        OPTION PROLOGUE:None

        OPTION EPILOGUE:None

        ALIGN   4

;/***************************************************************************
;*
;* FUNCTION NAME = setup_poly_frame_1
;*
;* DESCRIPTION   = This function is just a grouping of the following 
;*                 public labels:
;*
;*                      bitmap_solid_horizontal
;*                      bitmap_solid_vertical
;*                      bitmap_solid_diagonal
;*                      bitmap_styled_horizontal
;*                      bitmap_styled_vertical
;*                      bitmap_styled_diagonal
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

setup_poly_frame_1  PROC SYSCALL
LOCAL   returnvalue:DWORD,
        dwStyleCounter:DWORD,
        Flags:DWORD,
        Count:DWORD,
        Points:DWORD
LOCAL   npddc:DWORD,
        dwStyleMask:DWORD, 
        npfnUnSetup:DWORD,
        CurLineColor:DWORD,
        DrawModeIndex:DWORD,
        cPlanes:DWORD
LOCAL   cbNextPlane:DWORD,
        dwBitmapROP:DWORD,
        dwStyleStepHorz:DWORD,
        dwStyleStepVert:DWORD,
        dwStyleStepDiag:DWORD
LOCAL   dwStyleStepHorzTmp:DWORD,
        dwStyleStepVertTmp:DWORD,
        offNextLine:DWORD,
        cbScanSize:DWORD,
        cbHugeScanWrap:DWORD,
        cySurface:DWORD   
LOCAL   cScansPerSegment:DWORD, 
        pSurfaceStart:DWORD,
        anpfnRunRoutines:DWORD,
        LineStyle:DWORD,  
        npfnPassSetup:DWORD,
        cPasses:DWORD,
        lsg:LINESEGMENT
LOCAL   dwStyleStepRun:DWORD,
        dwStyleStepSide:DWORD,
        dwActiveStyleCounter:DWORD,
        dwActiveStyleMask:DWORD,
        yA:DWORD,
        cScans:DWORD,      
        cA:DWORD,         
        cB:DWORD,
        cm:DWORD
LOCAL   npfnRunRoutine:DWORD,
        iWhichDDA:DWORD,
        dwError:DWORD,
        dwFracS:DWORD,
        dwRotBitMask:DWORD, 
        cbScanAddressDelta:DWORD, 
        cbSideStepAddressDelta:DWORD,
        cbHugeScanDelta:DWORD,          
        selHugeDelta:DWORD,  
        dwScan:DWORD       
LOCAL   pSurfaceAddress:DWORD,
        cTmpScans:DWORD,          
        dwTmpError:DWORD,
        dwTmpScan:DWORD,          
        dwTmpRotBitMask:DWORD,  
        dwTmpActiveStyleCounter:DWORD,
        dwTmpActiveStyleMask:DWORD,
        cTmpPasses:DWORD,
        TmpCurLineColor:DWORD

        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
;*
;**************************************************************************/


        ALIGN   4

bitmap_solid_horizontal::


        DebugMsg<bitmap_solid_horizontal, polbitm, CLIFFL>

        mov     esi,dwBitmapROP

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

        dec     ecx                               ; CX = number of bits to move over
        mov     eax,ecx                           ; AX = ending bit number
        shr     eax,3                             ; AX = number of bytes to move
        and     ecx,7                             ; CX = number of bits to rotate
        mov     bh,bl                             ; BH = initial bit
        ror     bl,cl                             ; BL = ending bit
        mov     ecx,eax                           ; CX = number of bytes to move
        cmp     bh,bl                             ; adjust the count for byte wrap
        adc     ecx,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
        
        jecxz   just_do_the_last

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

        mov     ah,al
        and     ax,si
        not     al
        and     BYTE PTR [edi],al
        xor     BYTE PTR [edi],ah
        inc     edi

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

        dec     ecx
        jz      finish_up
        mov     eax,esi
        not     al

output_loop:

        and     BYTE PTR [edi],al
        xor     BYTE PTR [edi],ah
        inc     edi
        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     eax,esi
        not     al
        and     BYTE PTR [edi],al
        xor     BYTE PTR [edi],ah
        ret

        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
;*
;**************************************************************************/


        ALIGN   4

bitmap_solid_vertical::


        DebugMsg<bitmap_solid_vertical, polbitm, CLIFFL>

        mov     esi,cbScanAddressDelta
        mov     edx,dwScan
        mov     al,bl                             ; get rotating bit mask
        mov     ah,al
        and     eax,dwBitmapROP
        not     al
        dec     ecx
        jz      bv_last_pixel

bv_loop:

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

        and     BYTE PTR [edi],al
        xor     BYTE PTR [edi],ah

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

        add     edi,esi
        dec     edx                               ; check for huge overflow
        loopnz  bv_loop
        jnz     bv_last_pixel

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

        add     edi,cbHugeScanDelta              ; wrap the surface address
        mov     edx,cScansPerSegment             ; reset wScan
        or      ecx,ecx
        jnz     bv_loop

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

bv_last_pixel:

        and     BYTE PTR [edi],al
        xor     BYTE PTR [edi],ah
        mov     dwScan,edx
        ret

        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.
;* }
;*
;***************************************************************************/


        ALIGN   4

bitmap_solid_diagonal::


        DebugMsg<bitmap_solid_diagonal, polbitm, CLIFFL>

        mov     esi,cbScanAddressDelta
        mov     edx,dwScan
        mov     al,bl                             ; get rotating bit mask
        mov     ah,al
        and     eax,dwBitmapROP
        not     al
        dec     ecx
        jz      bd_last_pixel

bd_loop:

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

        and     BYTE PTR [edi],al
        xor     BYTE PTR [edi],ah

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

        ror     al,1
        ror     ah,1
        ror     bl,1
        adc     edi,esi
        dec     edx                               ; check for huge overflow
        loopnz  bd_loop
        jnz     bd_last_pixel

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

        add     edi,cbHugeScanDelta              ; wrap the surface address
        mov     edx,cScansPerSegment             ; reset wScan
        or      ecx,ecx
        jnz     bd_loop

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

bd_last_pixel:
        and     BYTE PTR [edi],al
        xor     BYTE PTR [edi],ah
        mov     dwScan,edx
        ret

        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
;*
;**************************************************************************/


        ALIGN   4

bitmap_styled_horizontal::


        DebugMsg<bitmap_styled_horizontal, polbitm, CLIFFL>


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

        mov     al,bl                             ; AL = rotating bit mask
        mov     ah,al
        and     eax,dwBitmapROP
        not     al                                ; AX = AND mask, XOR mask
        mov     dl,BYTE PTR dwActiveStyleCounter ; DL = style error
        mov     bh,BYTE PTR dwActiveStyleMask  ; BH = style mask
        mov     esi,dwStyleStepHorz              ; SI = style step

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

        dec     ecx
        jz      bsh_last_byte

bsh_loop:

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

        or      bh,bh
        jns     @F
        and     BYTE PTR [edi],al
        xor     BYTE PTR [edi],ah
@@:

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

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

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

        movzx   edx,dl
        add     edx,esi
        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     BYTE PTR [edi],al
        xor     BYTE PTR [edi],ah
@@:

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

        mov     BYTE PTR dwActiveStyleCounter,dl
        mov     BYTE PTR dwActiveStyleMask,bh
        ret

        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
;*
;**************************************************************************/


        ALIGN   4

bitmap_styled_vertical::


        DebugMsg<bitmap_Styled_vertical, polbitm, CLIFFL>

        mov     esi,dwScan
        mov     dl,BYTE PTR dwActiveStyleCounter ; DL = style error
        mov     bh,BYTE PTR dwActiveStyleMask  ; BH = style mask
        mov     al,bl                             ; get rotating bit mask
        mov     ah,al
        and     eax,dwBitmapROP
        not     al
        dec     ecx
        jz      bsv_last_pixel

bsv_loop:

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

        or      bh,bh
        jns     @F
        and     BYTE PTR [edi],al
        xor     BYTE PTR [edi],ah
@@:

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

        movzx   edx,dl
        add     edx,dwStyleStepVert
        xchg    cl,dh
        rol     bh,cl
        mov     cl,dh

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

        add     edi,cbScanAddressDelta
        dec     esi
        loopnz  bsv_loop
        jnz     bsv_last_pixel

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

        add     edi,cbHugeScanDelta              ; wrap the surface address
        mov     esi,cScansPerSegment             ; reset wScan
        or      ecx,ecx
        jnz     bsv_loop

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

bsv_last_pixel:

        or      bh,bh
        jns     @F
        and     BYTE PTR [edi],al
        xor     BYTE PTR [edi],ah
@@:     mov     BYTE PTR dwActiveStyleCounter,dl
        mov     BYTE PTR dwActiveStyleMask,bh
        mov     dwScan,esi
        ret

        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.
;* }
;*
;**************************************************************************/


        ALIGN   4

bitmap_styled_diagonal::


        DebugMsg<bitmap_Styled_diagonal, polbitm, CLIFFL>

        mov     esi,dwScan
        mov     dl,BYTE PTR dwActiveStyleCounter ; DL = style error
        mov     bh,BYTE PTR dwActiveStyleMask  ; BH = style mask
        mov     al,bl                             ; get rotating bit mask
        mov     ah,al
        and     eax,dwBitmapROP
        not     al
        dec     ecx
        jz      bsd_last_pixel

bsd_loop:

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

        or      bh,bh
        jns     @F
        and     BYTE PTR [edi],al
        xor     BYTE PTR [edi],ah
@@:

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

        movzx   edx,dl
        add     edx,dwStyleStepDiag
        xchg    cl,dh
        rol     bh,cl
        mov     cl,dh

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

        ror     ah,1
        ror     al,1
        ror     bl,1
        adc     edi,cbScanAddressDelta
        dec     esi
        loopnz  bsd_loop
        jnz     bsd_last_pixel

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

        add     edi,cbHugeScanDelta              ; wrap the surface address
        mov     esi,cScansPerSegment             ; reset wScan
        or      ecx,ecx
        jnz     bsd_loop

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

bsd_last_pixel:

        or      bh,bh
        jns     @F
        and     BYTE PTR [edi],al
        xor     BYTE PTR [edi],ah
@@:     mov     BYTE PTR dwActiveStyleCounter,dl
        mov     BYTE PTR dwActiveStyleMask,bh
        mov     dwScan,esi
        ret

setup_poly_frame_1  ENDP

        end
