;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; 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 = plmonobm.asm
;*
;* DESCRIPTIVE NAME = Polyline monochrome bitmap line drawing device driver. 
;*
;*
;* VERSION      V2.0
;*
;* DATE         06/14/88
;*
;* DESCRIPTION  
;*
;*      This module contains all of the routines called by POLYLINE.ASM
;*      to draw polylines in monochrome memory bitmaps.  There is a separate
;*      routine for each of the 6 cases.  The 6 cases come from the fact
;*      that lines can be styled or not, and the runs can be horizontal,
;*      vertical, or diagonal.
;*     
;*      These routines only draw a small part of a line.  This small part is
;*      called a "run".  It is a straight piece of a line that is either
;*      purely vertical, purely horizontal, or purely diagonal.  All lines
;*      are represented as a series of one of these cases.
;*     
;*      The details of this algorithm are explained in POLYLINE.ASM
;*
;* FUNCTIONS    setup_poly_frame_bm
;*              mono_bitmap_solid_horizontal 
;*              mono_bitmap_solid_vertical   
;*              mono_bitmap_solid_diagonal   
;*              mono_bitmap_styled_horizontal
;*              mono_bitmap_styled_vertical  
;*              mono_bitmap_styled_diagonal  
;*                                           
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   06/14/88                     Author: Wes Rupel   (wesleyr)
;*   09/16/88                     Bob Grudem [bobgru Separated from other                                                                
;*   09/16/88                     routines to form module of code common to                                                              
;*   09/16/88                     all display drivers.                                                                                   
;  Mon 20-Jun-1988 14:31:48                      -by- Wes Rupel [wesleyr]
; The EGA general case routine becomes the 256-color driver's mono
; bitmap routine.
;  Mon 20-Jun-1988 12:34:27                      -by- Wes Rupel [wesleyr]
; The EGA general case routine becomes the 256-color driver's mono
; bitmap routine.
;  Mon 20-Jun-1988 12:34:27                      -by- Wes Rupel [wesleyr]
; The EGA general case routine becomes the 256-color driver's mono
; bitmap routine.
;  Tue 21-Jun-1988 17:40:14                      -by- Wes Rupel [wesleyr]
; The EGA general case routine becomes the 256-color driver's mono
; bitmap routine.
;  Tue 21-Jun-1988 17:40:14                      -by- Wes Rupel [wesleyr]
; The EGA general case routine becomes the 256-color driver's mono
; bitmap routine.
;  Tue 21-Jun-1988 17:40:14                      -by- Wes Rupel [wesleyr]
; The EGA general case routine becomes the 256-color driver's mono
; bitmap routine.
;
;*****************************************************************************/


        .xlist
        include cmacros.inc
INCL_DDIPATHS   equ     1
        include pmgre.inc
DINCL_ROPS      equ     1
        include driver.inc
        include polyline.inc
        include assert.mac
        .list

        public  mono_bitmap_styled_table
        public  mono_bitmap_solid_table
        public  monoBM_ROPmask_table

        public  mono_bitmap_solid_horizontal
        public  mono_bitmap_solid_vertical
        public  mono_bitmap_solid_diagonal
        public  mono_bitmap_styled_horizontal
        public  mono_bitmap_styled_vertical
        public  mono_bitmap_styled_diagonal


sBegin  Code
        assumes cs,Code

;/*
;**  the various line rendering routines
;*/

mono_bitmap_styled_table                         equ this word
        dw      mono_bitmap_styled_horizontal
        dw      mono_bitmap_styled_vertical
        dw      mono_bitmap_styled_diagonal
        dw      mono_bitmap_styled_diagonal

mono_bitmap_solid_table                          equ this word
        dw      mono_bitmap_solid_horizontal
        dw      mono_bitmap_solid_vertical
        dw      mono_bitmap_solid_diagonal
        dw      mono_bitmap_solid_diagonal

;/*
;** Mono Bitmap Masks
;**
;** The monoBM_ROPmask_table contains and-masks and xor-masks for
;** setting pels to one of four possible values.   The and-masks
;** have been inverted, and are stored in the low byte of each word.
;** The xor-masks are stored in the high bytes.
;**
;**       ROP     XOR    ~AND
;**       -------------------
;**       DDx     00      FF                        set to zero
;**       Dn      FF      00                        not dest
;**       D       00      00                        leave alone
;**       DDxn    FF      FF                        set to one
;*/

monoBM_ROPmask_table        equ     this word
        dw      000FFh                            ; set to zero
        dw      0FF00h                            ; not dest
        dw      00000h                            ; leave alone
        dw      0FFFFh                            ; set to one


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



;/***************************************************************************
;*
;* FUNCTION NAME = mono_bitmap_solid_horizontal
;*
;* DESCRIPTION   = Draws a solid horizontal line into a MONOCHROME 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        = NONE
;*
;* RETURN-NORMAL = DS:DI = new bitmap address
;*                 BL = new rotating bit mask
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing

mono_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
mono_bitmap_solid_horizontal                     endp


;/***************************************************************************
;*
;* FUNCTION NAME = mono_bitmap_solid_vertical
;*
;* DESCRIPTION   = Draws a solid vertical line into a bitmap. 
;*
;*                 Registers Destroyed:
;*                       CX,SI,DX
;*                 Registers Preserv
;*                       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

mono_bitmap_solid_vertical    proc    near
        mov     si,cbScanAddressDelta
        mov     dx,cScansLeftInSeg
        mov     al,bl                             ; get rotating bit mask
        mov     ah,al
        and     ax,wBitmapROP
        not     al
        dec     cx
        jz      mbv_last_pixel
mbv_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  mbv_loop
        jnz     mbv_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 cScansLeftInSeg
        or      cx,cx
        jnz     mbv_loop

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


mbv_last_pixel:
        and     [di],al
        xor     [di],ah
        mov     cScansLeftInSeg,dx
        ret
mono_bitmap_solid_vertical    endp


;/***************************************************************************
;*
;* FUNCTION NAME = mono_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   =
;*    mono_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

mono_bitmap_solid_diagonal    proc    near
        mov     si,cbScanAddressDelta
        mov     dx,cScansLeftInSeg
        mov     al,bl                             ; get rotating bit mask
        mov     ah,al
        and     ax,wBitmapROP
        not     al
        dec     cx
        jz      mbd_last_pixel
mbd_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  mbd_loop
        jnz     mbd_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 cScansLeftInSeg
        or      cx,cx
        jnz     mbd_loop

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


mbd_last_pixel:
        and     [di],al
        xor     [di],ah
        mov     cScansLeftInSeg,dx
        ret
mono_bitmap_solid_diagonal    endp


;/***************************************************************************
;*
;* FUNCTION NAME = mono_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 EGA address
;*                 BL = new rotating bit mask
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


        assumes ds,nothing
        assumes es,nothing

mono_bitmap_styled_horizontal                     proc  near

;/*
;**!!! special case LINETYPE_ALTERNATE for extra speed !!!
;*/


;/*
;** 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      mbsh_last_byte
mbsh_loop:

;/*
;** draw the pixel if the mask's high bit is "1"
;*/


        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    mbsh_loop

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


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

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


        mov     bActiveStyleCounter,dl
        mov     bActiveStyleMask,bh
        ret
mono_bitmap_styled_horizontal                     endp


;/***************************************************************************
;*
;* FUNCTION NAME = mono_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 EGA address
;*                 BL = new rotating bit mask
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing

mono_bitmap_styled_vertical    proc    near
        mov     si,cScansLeftInSeg
        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      mbsv_last_pixel
mbsv_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  mbsv_loop
        jnz     mbsv_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 cScansLeftInSeg
        or      cx,cx
        jnz     mbsv_loop

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


mbsv_last_pixel:
        or      bh,bh
        jns     @F
        and     [di],al
        xor     [di],ah
@@:     mov     bActiveStyleCounter,dl
        mov     bActiveStyleMask,bh
        mov     cScansLeftInSeg,si
        ret
mono_bitmap_styled_vertical    endp


;/***************************************************************************
;*
;* FUNCTION NAME = mono_bitmap_styled_diagonal
;*
;* 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 EGA address
;*                 BL = new rotating bit mask
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;* PSEUDO-CODE   =
;*
;*     mono_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

mono_bitmap_styled_diagonal    proc    near
        mov     si,cScansLeftInSeg
        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      mbsd_last_pixel
mbsd_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  mbsd_loop
        jnz     mbsd_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 cScansLeftInSeg
        or      cx,cx
        jnz     mbsd_loop

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


mbsd_last_pixel:
        or      bh,bh
        jns     @F
        and     [di],al
        xor     [di],ah
@@:     mov     bActiveStyleCounter,dl
        mov     bActiveStyleMask,bh
        mov     cScansLeftInSeg,si
        ret
mono_bitmap_styled_diagonal    endp



sEnd    Code

        end
