;*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 = PHYCOLOR.ASM
;*
;* DESCRIPTIVE NAME = Color related functions
;*
;*
;* VERSION      V2.0
;*
;* DATE         03/07/88
;*
;* DESCRIPTION  ColorConvert converts a logical color (an RGB triplet) to a     
;*              physical color (a byte).                                           
;*
;* FUNCTIONS    far_rgb_to_ipc
;*              rgb_to_ipc
;*              synthesize_xparent_mask
;*              synthesize_color_bits
;*              synthesize_mono_bits
;*              do_one_plane
;*              rotate_brush
;*              copy_bits_to_pattern
;*              fill_pattern_empty_bits
;*                                     
;* 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/02/88                     Walt Moore [waltm]
;*                                Return error if raster font selected or font  
;*                                is huge                                       
;*
;*   09/19/88                     Wes Rupel [wesleyr]
;*                                Re-wrote it.  It used to just take the 3      
;*                                highest bits for green and red, and the two   
;*                                highest for blue.  That was not a very good   
;*                                mapping.  For example, In the case of blue we 
;*                                have hardware colors at 00,55,AA, and FF.  We 
;*                                want anything in the range 55 +\- 55/2 to map 
;*                                to 55.  The new method does this correctly.   
;*                                The old method mapped anything between FF/4   
;*                                and FF/2 to 55.                               
;*                                                                      
;*   09/28/88                     Wes Rupel [wesleyr]
;*                                Massive revisions.
;*
;*   10/13/88                     Lee A. Newberg [leen]
;*                                The old method for BLUE was:  take the value,
;*                                add FF/6, and then multiply by 3. The high
;*                                byte is the two bit quantity for RRRGGGBB.  I
;*                                switched the order of the add and multiply for
;*                                better accuracy.  The new method is:  take the
;*                                blue value, multiply by 3 and then add 80h.
;*                                Ideally we should take this new value and
;*                                divide it by 255 to get the two bit blue
;*                                value.  Instead we are merely grabbing the
;*                                high byte, which is equivalent to dividing by 
;*                                256 and which saves a few clocks.  To make up 
;*                                for the     division, we add 01h more to the  
;*                                dividend as a fudge factor.                   
;*                                                                             
;*                                The same tactics are used for GREEN and RED.   
;*                                The fudge factor compensates perfectly except  
;*                                that ED (which is greater than 13/14 of 255    
;*                                gets rounded down to 6/7 (i.e.  110b) rather   
;*                                than up to 7/7 (i.e.  111b).                   
;*
;*                                Equivalent changes have been made in the      
;*                                dither_brush routine.                         
;*
;*   10/13/88                     Lee A. Newberg [leen]
;*                                The old method for BLUE was:  take the value, 
;*                                add FFh/24d, and then multiply by 12d.  The   
;*                                high byte is the 4 bit quantity for blue.  I  
;*                                switched the order of the add and multiply for
;*                                better accuracy.  The new method is:  take the
;*                                blue value, multiply by 12d and then add 80h. 
;*                                Ideally we should take this new value and     
;*                                divide it by 255d to get the four bit blue    
;*                                value.  Instead we are merely grabbing the    
;*                                high byte, which is equivalent to dividing by 
;*                                256d and which saves a few clocks.  To make up
;*                                for the     division, we add more to the      
;*                                dividend as a fudge factor.                   
;*
;*                                The same tactics are used for GREEN and RED.  
;*                                The fudge factor compensates perfectly except 
;*                                ...  BLUE 35h should be rounded down BLUE CAh 
;*                                should be rounded up RED/GREEN 32h should be  
;*                                rounded down RED/GREEN 3Bh should be rounded  
;*                                down RED/GREEN C4h should be rounded up       
;*                                RED/GREEN CDh should be rounded up Equivalent 
;*                                changes have been made in the rgb_to_ipc      
;*                                routine.                                      
;*
;*   04/17/90                     Kate Robinson [krobin]
;*                                Change default palette to add 32 pure greys,  
;*                                by dropping 1 red level.  Change color metric 
;*                                from linear RGB to psychometric (companded)   
;*                                RGB.  Add support for realize color table     
;*                                function.                                     
;*                                                                        
;*   04/17/90                     Kate Robinson [krobin]
;*                                Modifications to support realizable color
;*                                tables.  This change requires keeping the
;*                                original algorithm for the default palette as
;*                                one subroutine and using a search method for
;*                                realizable palettes as another subroutine.
;*                                                                        
;*  03/23/93   @TAK        64227  Terry Kirschner [terryki]
;*                                Fix: Color bitmaps not displayed.
;*                                                                        
;*****************************************************************************/


.286p
        .xlist
        include cmacros.inc
INCL_DDIBUNDLES         equ     1
INCL_FONTFILEFORMAT     equ     1
INCL_DDIMISC            equ     1
INCL_DEV                equ     1
INCL_GRE_DEVMISC1       equ     1
INCL_GRE_FONTS          equ     1
INCL_WINSYS             equ     1
INCL_GPIBITMAPS         equ     1
INCL_GPILOGCOLORTABLE   equ     1
        include pmgre.inc
DINCL_CLR_TBL           equ     1
DINCL_VIO               equ     1
DINCL_BITMAP            equ     1
        include driver.inc
        include display.inc
        include fontseg.inc
        Include 8514.inc
        Include 8514mem.inc
        include palette.inc
        .list

        ??_out  ColorConversion

        errcode <HUGE_FONTS_NOT_SUPPORTED,INV_PATTERN_ATTR>
        errcode <INV_PATTERN_SET_ATTR,INV_PATTERN_SET_FONT>

        externFP GreEntry3

HUGE_FONT       equ     8000h                    
FD_VECTOR       equ     0000000000000001B        


;/*
;** The special colors which correspond to negative indices, and other
;** public data.
;*/

TEMP_CONST equ ( ( SYSCLR_CSYSCOLORS ) - 17 )           ; This is the count of system
                                                        ; colors above the 190 system
                                                        ; color list.

        pubabs  MIN_SPECIAL_COLOR,%(SYSCLR_WINDOWSTATICTEXT-TEMP_CONST)
        pubabs  MIN_SYSTEM_COLOR, %(SYSCLR_WINDOWSTATICTEXT-TEMP_CONST)

        public  ctDefault
        public  ipcSysClrWindow
        public  ipcSysClrWindowText
        public  drgbSysClrWindow
        public  drgbSysClrWindowText
        public  aipcSpecial
        public  adrgbSpecial
        public  adrgbDefault
        public  adrgbIndex
        public  ctRealizableDefault

;/*
;** --------------------------------------------------------------------;
;**  MakeCT Macro 
;** 
;**  index   - suffix index, eg 0 .. 255
;**  lab     - label prefix, eg PHY_COLOR_DATA_
;**  objsize - size of each entry, eg dd or dw
;**  donts   -
;**---------------------------------------------------------------------;
;*/

MakeCT  Macro   index,lab,objsize,donts
gotit   =       0
        Ifnb    <donts>
        Irp     x,<donts>
        Ifidn   <x>,<index>
gotit   =       1
        Exitm
        Endif
        Endm
        Endif
        Ife     gotit
        objsize lab&index
        Endif
        Endm

        page
sBegin  Data

        externW hwFlags                           ; hw state flags
        externW npbmcColor                        ; -> cs-based color bitmap info struct

;/*
;** Warning: this data is interdependant between CopyI8E4,
;**          CreateColorColorTable (both in bmc_ite.asm) and this.
;**          These must be the same values as the first 16 default
;**          color table entries.
;*/


d3      macro   lbl
        dw      lbl AND 0FFFFh
        db      lbl shr 16
        endm

;/*
;** Warning: this data is interdependant between CopyI8E4,
;**          CreateColorColorTable (both in bmc_ite.asm) and this.
;**          These must be the same values as the first 16 default
;**          color table entries.
;*/

;/*
;** This is the color table that will be passed back to the app if it
;** asks for 4 bits/pel.
;*/

        public  argbDefCT16Reorg
argbDefCT16Reorg        label   byte
        d3      PHY_COLOR_DATA_0        ; black
        d3      PHY_COLOR_DATA_2        ; blue
        d3      PHY_COLOR_DATA_16       ; green
        d3      PHY_COLOR_DATA_18       ; cyan
        d3      PHY_COLOR_DATA_160      ; red
        d3      PHY_COLOR_DATA_162      ; magenta
        d3      PHY_COLOR_DATA_144      ; yellow
        d3      PHY_COLOR_DATA_137      ; gray
        d3      PHY_COLOR_DATA_128      ; dark gray ("intense black")
        d3      PHY_COLOR_DATA_3        ; intense blue
        d3      PHY_COLOR_DATA_28       ; intense green
        d3      PHY_COLOR_DATA_31       ; intense cyan
        d3      PHY_COLOR_DATA_224      ; intense red
        d3      PHY_COLOR_DATA_227      ; intense magenta
        d3      PHY_COLOR_DATA_252      ; intense yellow
        d3      PHY_COLOR_DATA_255      ; intense white


;/*
;** The default logical color table.  Colors 0 and 7 may be written
;** over if SYSCLR_WINDOW or SYSCLR_WINDOWTEXT change.
;*/

ctDefault       label   word

        dw      CT_IDENT
        dw      adrgbDefault
        dw      0                               ; Never saved/restored
        dw      0                               ; Minimum loaded index
        dw      DEFAULT_COLOR_TABLE_SIZE - 1    ; Maximum loaded index

;/*
;** The actual physical colors
;*/

;/*
;** -----------------------------------------------------------------------;
;** 
;**  Palette Color Selection:
;** 
;**  Terms:
;**    hwR,hwG,hwB are the Red,Green, and Blue values one puts in the
;**        hardware palette.
;**    R,G,B are the usual PM values which range from 0 to 255.
;** 
;**  We keep 3 bits of Red and 3 bits of Green, but only two bits
;**  of B in our ipc.  This means we divide the R and G ranges into 7ths
;**  and the B range into 3rds (black is included).
;** 
;**  In the actual hardware palette we can put values from 0 to 63 for each
;**  of hwR,hwG and hwB.  Experiment* has shown that the hardware colors do
;**  not vary linearly with the hw value.  For example you might expect
;**  that 32 would be about half as bright as 63, but it is actually less
;**  than 1/7 as bright.  The brightness goes roughly like this:
;** 
;**  Brightness = (hwValue/63)^3     where Brightness ranges from 0 to 1.
;** 
;**  This means that in order to have evenly spaced R,G and B values I
;**  have had to choose very unevenly spaced hwR, hwG and hwB values.
;** 
;**  The numbering scheme you see below works like this:
;** 
;**  For the rest of this comment block R and G range from 0-7 and B from 0-3
;** 
;**  index into hardware palette = 32*R + 4*G + B
;** 
;**  The first 16 colors in the default color table are predefined
;**  for PM drivers.  These colors are shown in the first column below.
;**  The other columns show how we generate them.
;** 
;**   Predefined Color                 index  R G B      R   G  B
;**   ---------------------------      -----  -----     --- --- --
;**   white         SYSCLR_WINDOW       255   7 7 3  =  111 111 11
;**   blue                              3     0 0 3  =  000 000 11
;**   red                               224   7 0 0  =  111 000 00
;**   pink (magenta)                    227   7 0 3  =  111 000 11
;**   green                             28    0 7 0  =  000 111 00
;**   turquoise (cyan)                  31    0 7 3  =  000 111 11
;**   yellow                            252   7 7 0  =  111 111 00
;**   black         SYSCLR_WINDOWTEXT   0     0 0 0  =  000 000 00
;** 
;**   For the dark colors we can choose 1/3 brightness or 2/3.  I choose 1/3.
;** 
;**   gray                              37    1 1 1  =  001 001 01
;**   dark blue                         1     0 0 1  =  000 000 01
;**   dark red                          64    2 0 0  =  010 000 00
;**   purple                            65    2 0 1  =  010 000 01
;**   dark green                        8     0 2 0  =  000 010 00
;**   dark turquoise                    9     0 2 1  =  000 010 01
;**   mustard                           72    2 2 0  =  010 010 00
;**   dark gray                         73    2 2 1  =  010 010 01
;** 
;**  Note that we don't actually have R=G=B in our gray-scales.
;**  It doesn't matter much if blue is different than the others as
;**  long as it is reasonably close.  This is because it is such a dark
;**  color that it has only a small effect (about 10%).
;** 
;**   Mon 26-Sep-1988 18:38:53     -by-    Wes Rupel       [wesleyr]
;**  For convenience I have appended the complete list of index-to-RGB
;**  to the end of this file.
;**  * ask for my pal.exe program if you are interested in the experiment.
;** 
;**   17th April 1990              -by-    Kate Robinson [krobin]
;**  Implement dcr 25074.
;** 
;**  Change default palette to add 32 pure greys, by dropping 1 red level.
;**  We now keep 3 bits for Red but only use 7 levels instead of 8.
;** 
;**  For R in the range 0-6, G in the range 0-7 and B in the range 0-3:
;**      for palette indeces 0-111
;**         index into hardware palette = 32*R + 4*G + B
;**      for palette indeces 112-143
;**         index into hardware palette = pure grey entry number + 112
;**      for palette indeces 144-255
;**         index into hardware palette = (32*R + 4*G + B) + 32
;** 
;**  The color metric has been changed from linear RGB to psychometric (companded)
;**  RGB which means that the the HW values are not as unevenly spaced, they
;**  lie on a 1.3 power law curve with an 8.7 offset instead of on a 3.0 power
;**  law curve.
;** 
;**  The palette entries used for the 16 default colors have been changed to
;**  match as closely as possible the colors previously produced.
;** 
;** -----------------------------------------------------------------------;
;*/

;/*
;** This table is a bunch of ipc's
;*/


;/*
;** WARNING: Do not change these first 16 default colors without
;**          making the coresponding changes to argbDefCT16Reorg,
;**          CopyI8E4, CreateColorColorTable (see in bmc_ite.asm)
;**          and also to the realized form of the table below.
;*/

        .errnz  ($-ctDefault)-ct_aipc
        dw      PHY_COLOR_WORD_255               ; white  SYSCLR_WINDOW
        dw      PHY_COLOR_WORD_3                 ; blue
        dw      PHY_COLOR_WORD_224               ; red
        dw      PHY_COLOR_WORD_227               ; pink (magenta)
        dw      PHY_COLOR_WORD_28                ; green
        dw      PHY_COLOR_WORD_31                ; turquoise (cyan)
        dw      PHY_COLOR_WORD_252               ; yellow
        dw      PHY_COLOR_WORD_0                 ; black  SYSCLR_WINDOWTEXT
        dw      PHY_COLOR_WORD_128               ; dark gray
        dw      PHY_COLOR_WORD_2                 ; dark blue
        dw      PHY_COLOR_WORD_160               ; dark red
        dw      PHY_COLOR_WORD_162               ; purple
        dw      PHY_COLOR_WORD_16                ; dark green
        dw      PHY_COLOR_WORD_18                ; dark turquoise
        dw      PHY_COLOR_WORD_144               ; mustard
        dw      PHY_COLOR_WORD_137               ; gray

;/*
;** This table is a bunch of RGB's
;*/


adrgbDefault    label   byte
        dd      PHY_COLOR_DATA_255      ; white         SYSCLR_WINDOW
        dd      PHY_COLOR_DATA_3        ; blue
        dd      PHY_COLOR_DATA_224      ; red
        dd      PHY_COLOR_DATA_227      ; pink (magenta)
        dd      PHY_COLOR_DATA_28       ; green
        dd      PHY_COLOR_DATA_31       ; turquoise (cyan)
        dd      PHY_COLOR_DATA_252      ; yellow
        dd      PHY_COLOR_DATA_0        ; black         SYSCLR_WINDOWTEXT
        dd      PHY_COLOR_DATA_128      ; dark gray
        dd      PHY_COLOR_DATA_2        ; dark blue
        dd      PHY_COLOR_DATA_160      ; dark red
        dd      PHY_COLOR_DATA_162      ; purple
        dd      PHY_COLOR_DATA_16       ; dark green
        dd      PHY_COLOR_DATA_18       ; dark turquoise
        dd      PHY_COLOR_DATA_144      ; mustard
        dd      PHY_COLOR_DATA_137      ; gray


;/*
;** The default logical color table in realizable form.
;*/

ctRealizableDefault     label   word

        dw      CT_IDENT
        dw      adrgbRealizableDefault
        dw      0                               ; Never saved/restored
        dw      0                               ; Minimum loaded index
        dw      DEFAULT_COLOR_TABLE_SIZE - 1    ; Maximum loaded index

;/*
;** The actual physical colors
;*/

;/*
;** This table is a bunch of ipc's
;*/

;/*
;** WARNING: Do not change these first 16 default colors without
;**          making the coresponding changes to argbDefCT16Reorg,
;**          CopyI8E4, CreateColorColorTable (see in bmc_ite.asm).
;*/

;/*
;** each entry consists of the index into the table (ie 0 to 15)
;** together with the correct mono_bit which is obtained from the entry
;** in the corresponding non realized default color table
;*/

        .errnz  ($-ctRealizableDefault)-ct_aipc
        dw      (PHY_COLOR_WORD_255 and MONO_BIT) or 0 ; white   SYSCLR_WINDOW
        dw      (PHY_COLOR_WORD_3   and MONO_BIT) or 1 ; blue
        dw      (PHY_COLOR_WORD_224 and MONO_BIT) or 2 ; red
        dw      (PHY_COLOR_WORD_227 and MONO_BIT) or 3 ; pink (magenta)
        dw      (PHY_COLOR_WORD_28  and MONO_BIT) or 4 ; green
        dw      (PHY_COLOR_WORD_31  and MONO_BIT) or 5 ; turquoise (cyan)
        dw      (PHY_COLOR_WORD_252 and MONO_BIT) or 6 ; yellow
        dw      (PHY_COLOR_WORD_0   and MONO_BIT) or 7 ; black SYSCLR_WINDOWTEXT
        dw      (PHY_COLOR_WORD_128 and MONO_BIT) or 8 ; dark gray  37 = 25h => R=G=B=1
        dw      (PHY_COLOR_WORD_2   and MONO_BIT) or 9 ; dark blue
        dw      (PHY_COLOR_WORD_160 and MONO_BIT) or 10 ; dark red
        dw      (PHY_COLOR_WORD_162 and MONO_BIT) or 11 ; purple
        dw      (PHY_COLOR_WORD_16  and MONO_BIT) or 12 ; dark green
        dw      (PHY_COLOR_WORD_18  and MONO_BIT) or 13 ; dark turquoise
        dw      (PHY_COLOR_WORD_144 and MONO_BIT) or 14 ; mustard
        dw      (PHY_COLOR_WORD_137 and MONO_BIT) or 15 ; gray      73 = 49h => R=G=2, B=1

;/*
;** we need to fill in the remaining 240 entries with the correct ipcs
;** but mark each of them as invalid as well
;*/

MakeIpcInvalid Macro index
        dw      (PHY_COLOR_WORD_&index and MONO_BIT) or index
Endm

RGBIndex = 16
        Rept 240
        MakeIpcInvalid %RGBIndex
        RGBIndex = RGBIndex + 1
Endm

;/*
;** This table is a bunch of RGB's
;*/

adrgbRealizableDefault  label   byte
        dd      PHY_COLOR_DATA_255      ; white         SYSCLR_WINDOW
        dd      PHY_COLOR_DATA_3        ; blue
        dd      PHY_COLOR_DATA_224      ; red
        dd      PHY_COLOR_DATA_227      ; pink (magenta)
        dd      PHY_COLOR_DATA_28       ; green
        dd      PHY_COLOR_DATA_31       ; turquoise (cyan)
        dd      PHY_COLOR_DATA_252      ; yellow
        dd      PHY_COLOR_DATA_0        ; black         SYSCLR_WINDOWTEXT
        dd      PHY_COLOR_DATA_128      ; dark gray
        dd      PHY_COLOR_DATA_2        ; dark blue
        dd      PHY_COLOR_DATA_160      ; dark red
        dd      PHY_COLOR_DATA_162                ; purple
        dd      PHY_COLOR_DATA_16       ; dark green
        dd      PHY_COLOR_DATA_18       ; dark turquoise
        dd      PHY_COLOR_DATA_144      ; mustard
        dd      PHY_COLOR_DATA_137      ; gray

;/*
;** because this table is realizable, we need to have 256 entries defined
;** in it for use by the code that actually realizes the table.
;** each of these entries needs to be marked as invalid
;*/

MakeRGBInvalid Macro index
        dd      PHY_COLOR_DATA_&index or 8000h
Endm

RGBIndex = 16
        Rept 240
        MakeRGBInvalid %RGBIndex
        RGBIndex = RGBIndex + 1
Endm

;/*
;**  adrgbIndex
;** 
;**  A sorted list of the RGB colors for mapping from an ipc index.
;** 
;**  What this actually generates (thru the MakeCT macro) is a list
;**  of statements like this:
;**        dd      PHY_COLOR_DATA_0
;**        dd      PHY_COLOR_DATA_1
;**        etc
;*/

adrgbIndex      equ     this dword
maketmp         =       0
        Rept    256
        MakeCT  %maketmp,PHY_COLOR_DATA_,dd
maketmp         =       maketmp + 1
        Endm

;/*
;** The system colors ipc table.
;*/


        globalW ipc_index_mask,255

aipcSpecial     equ     this word

        rept TEMP_CONST
        dw      0
        endm

        dw      PHY_COLOR_WORD_3                 ;-26  WINDOWSTATICTEXT
        dw      PHY_COLOR_WORD_73                ;-25  SCROLLBAR
        dw      PHY_COLOR_WORD_31                ;-24  BACKGROUND
        dw      PHY_COLOR_WORD_3                 ;-23  ACTIVETITLE
        dw      PHY_COLOR_WORD_255               ;-22  INACTIVETITLE
        dw      PHY_COLOR_WORD_31                ;-21  MENU
ipcSysClrWindow         equ     this word
        dw      PHY_COLOR_WORD_255               ;-20  WINDOW
        dw      PHY_COLOR_WORD_0                 ;-19  WINDOWFRAME
        dw      PHY_COLOR_WORD_0                 ;-18  MENUTEXT
ipcSysClrWindowText     equ     this word
        dw      PHY_COLOR_WORD_0                 ;-17  WINDOWTEXT
        dw      PHY_COLOR_WORD_255               ;-16  TITLETEXT
        dw      PHY_COLOR_WORD_37                ;-15  ACTIVEBORDER
        dw      PHY_COLOR_WORD_37                ;-14  INACTIVEBORDER
        dw      PHY_COLOR_WORD_9                 ;-13  APPWORKSPACE
        dw      PHY_COLOR_WORD_3                 ;-12  HELPBACKGROUND
        dw      PHY_COLOR_WORD_31                ;-11  HELPTEXT
        dw      PHY_COLOR_WORD_255               ;-10  HELPHILITE
        .errnz  SYSCLR_CSYSCOLORS - ($ - aipcSpecial) / 2
        dw      INVALID_IPC                      ;-9
        dw      INVALID_IPC                      ;-8
        dw      INVALID_IPC                      ;-7
        dw      INVALID_IPC                      ;-6
        dw      PHY_COLOR_WORD_0                 ;-5  All 0s
        dw      PHY_COLOR_WORD_255               ;-4  All 1s
        dw      INVALID_IPC                      ;-3
        dw      PHY_COLOR_WORD_255               ;-2  White
        dw      PHY_COLOR_WORD_0                 ;-1  Black

;/*
;** The rgb triplets corresponding to the system colors
;*/

adrgbSpecial    equ     this dword

        rept TEMP_CONST
        dd      0
        endm

        dd      PHY_COLOR_DATA_3        ;-26            WINDOWSTATICTEXT
        dd      PHY_COLOR_DATA_73       ;-25            SCROLLBAR
        dd      PHY_COLOR_DATA_31       ;-24            BACKGROUND
        dd      PHY_COLOR_DATA_3        ;-23            ACTIVETITLE
        dd      PHY_COLOR_DATA_255      ;-22            INACTIVETITLE
        dd      PHY_COLOR_DATA_31       ;-21            MENU
drgbSysClrWindow        equ     this dword
        dd      PHY_COLOR_DATA_255      ;-20            WINDOW
        dd      PHY_COLOR_DATA_0        ;-19            WINDOWFRAME
        dd      PHY_COLOR_DATA_0        ;-18            MENUTEXT
drgbSysClrWindowText    equ     this dword
        dd      PHY_COLOR_DATA_0        ;-17            WINDOWTEXT
        dd      PHY_COLOR_DATA_255      ;-16            TITLETEXT
        dd      PHY_COLOR_DATA_37       ;-15            ACTIVEBORDER
        dd      PHY_COLOR_DATA_37       ;-14            INACTIVEBORDER
        dd      PHY_COLOR_DATA_9        ;-13            APPWORKSPACE
        dd      PHY_COLOR_DATA_3        ;-12            HELPBACKGROUND
        dd      PHY_COLOR_DATA_31       ;-11            HELPTEXT
        dd      PHY_COLOR_DATA_255      ;-10            HELPHILITE
        .errnz  SYSCLR_CSYSCOLORS - ($ - adrgbSpecial) / 4
        dd      -1                      ;-9
        dd      -1                      ;-8
        dd      -1                      ;-7
        dd      -1                      ;-6
        dd      PHY_COLOR_DATA_0        ;-5             All 0s
        dd      PHY_COLOR_DATA_255      ;-4             All 1s
        dd      -1                      ;-3
        dd      PHY_COLOR_DATA_255      ;-2             White
        dd      PHY_COLOR_DATA_0        ;-1             Black


;/*
;** Global variables required by the 8514 Color Realization Modifications
;*/

        public  RealizedPalette
RealizedPalette label   byte

;/*
;**--- might as well initialize with same data as the default palette ----
;*/

RGBIndex = 0
        irp     CurrHWR,<0,19,27>
        irp     CurrHWG,<0,18,24,31,38,46,54,63>
        irp     CurrHWB,<0,27,44,63>
        db      CurrHWR,CurrHWG,CurrHWB
RGBIndex = RGBIndex + 1
        endm
        endm
        endm
        irp     CurrHWR,<35>
        irp     CurrHWG,<0,18,24,31>
        irp     CurrHWB,<0,27,44,63>
        db      CurrHWR,CurrHWG,CurrHWB
RGBIndex = RGBIndex + 1
        endm
        endm
        endm
        db       0, 0, 0
        db      14,14,14
        db      15,15,15
        db      16,16,16
        db      18,18,18
        db      19,19,19
        db      20,20,20
        db      22,22,22
        db      23,23,23
        db      25,25,25
        db      26,26,26
        db      28,28,28
        db      29,29,29
        db      31,31,31
        db      32,32,32
        db      34,34,34
        db      36,36,36
        db      37,37,37
        db      39,39,39
        db      41,41,41
        db      42,42,42
        db      44,44,44
        db      46,46,46
        db      48,48,48
        db      50,50,50
        db      51,51,51
        db      53,53,53
        db      55,55,55
        db      57,57,57
        db      59,59,59
        db      61,61,61
        db      63,63,63
RGBIndex = RGBIndex + 32
        irp     CurrHWR,<35>
        irp     CurrHWG,<38,46,54,63>
        irp     CurrHWB,<0,27,44,63>
        db      CurrHWR,CurrHWG,CurrHWB
RGBIndex = RGBIndex + 1
        endm
        endm
        endm
        irp     CurrHWR,<44,53,63>
        irp     CurrHWG,<0,18,24,31,38,46,54,63>
        irp     CurrHWB,<0,27,44,63>
        db      CurrHWR,CurrHWG,CurrHWB
RGBIndex = RGBIndex + 1
        endm
        endm
        endm

;/*
;** translate table to map from the 0-255 values for RGB entry at GPI
;** to the 0-63 values for the palette
;** table has been produced by taking the values defined for the original
;** 8514 driver and filling in the inbetween values - this means that it
;** may not be mathematically accurate but its fairly close
;*/

        public  xlate_rgb_to_palette
xlate_rgb_to_palette  equ     this byte
        db       0      ; RGB value 0
        db      11
        db      11
        db      12
        db      13
        db      13
        db      14
        db      14
        db      14
        db      14
        db      14      ; RGB value 10
        db      14
        db      14
        db      15
        db      15
        db      15
        db      15
        db      15
        db      15
        db      15
        db      16      ; RGB value 20
        db      16
        db      16
        db      16
        db      16
        db      16
        db      17
        db      17
        db      17
        db      17
        db      17      ; RGB value 30
        db      17
        db      17
        db      18
        db      18
        db      18
        db      18      ; RGB value 36
        db      18
        db      18
        db      19
        db      19      ; RGB value 40
        db      19
        db      19
        db      19
        db      19
        db      20
        db      20
        db      20
        db      20
        db      20
        db      20      ; RGB value 50
        db      21
        db      21
        db      21
        db      21
        db      21
        db      21
        db      22
        db      22
        db      22
        db      22      ; RGB value 60
        db      22
        db      22
        db      23
        db      23
        db      23
        db      23
        db      23
        db      23
        db      24
        db      24      ; RGB value 70
        db      24
        db      24
        db      24      ; RGB value 73
        db      25
        db      25
        db      25
        db      25
        db      25
        db      25
        db      26      ; RGB value 80
        db      26
        db      26
        db      26
        db      26
        db      27      ; RGB value 85
        db      27
        db      27
        db      27
        db      27
        db      27      ; RGB value 90
        db      28
        db      28
        db      28
        db      28
        db      28
        db      29
        db      29
        db      29
        db      29
        db      29      ; RGB value 100
        db      30
        db      30
        db      30
        db      30
        db      30
        db      30
        db      31
        db      31
        db      31      ; RGB value 109
        db      31      ; RGB value 110
        db      31
        db      32
        db      32
        db      32
        db      32
        db      32
        db      33
        db      33
        db      33
        db      33      ; RGB value 120
        db      33
        db      34
        db      34
        db      34
        db      34
        db      34
        db      35
        db      35
        db      35
        db      35      ; RGB value 130
        db      35
        db      36
        db      36
        db      36
        db      36
        db      36
        db      37
        db      37
        db      37
        db      37      ; RGB value 140
        db      37
        db      38
        db      38
        db      38
        db      38
        db      39      ; RGB value 146
        db      39
        db      39
        db      39
        db      39      ; RGB value 150
        db      40
        db      40
        db      40
        db      40
        db      40
        db      41
        db      41
        db      41
        db      41
        db      41      ; RGB value 160
        db      42
        db      42
        db      42
        db      42
        db      43
        db      43
        db      43
        db      43
        db      43
        db      44      ; RGB value 170
        db      44
        db      44
        db      44
        db      44
        db      45
        db      45
        db      45
        db      45
        db      46
        db      46      ; RGB value 180
        db      46
        db      46      ; RGB value 182
        db      46
        db      47
        db      47
        db      47
        db      47
        db      48
        db      48
        db      48      ; RGB value 190
        db      48
        db      48
        db      49
        db      49
        db      49
        db      49
        db      50
        db      50
        db      50
        db      50      ; RGB value 200
        db      50
        db      51
        db      51
        db      51
        db      51
        db      52
        db      52
        db      52
        db      52
        db      52      ; RGB value 210
        db      53
        db      53
        db      53
        db      53
        db      54
        db      54
        db      54
        db      54
        db      55      ; RGB value 219
        db      55      ; RGB value 220
        db      55
        db      55
        db      55
        db      56
        db      56
        db      56
        db      56
        db      57
        db      57
        db      57      ; RGB value 230
        db      57
        db      58
        db      58
        db      58
        db      58
        db      58
        db      59
        db      59
        db      59
        db      59      ; RGB value 240
        db      60
        db      60
        db      60
        db      60
        db      61
        db      61
        db      61
        db      61
        db      62
        db      62      ; RGB value 250
        db      62
        db      62
        db      63
        db      63
        db      63      ; RGB value 255

;/*
;**  The table xlate_logRGB_to_realRGB is used by the various color query
;**  functions when returning data for realized color tables. For example,
;**  if a logical color table is created with 256 shades of grey in it, then
;**  QueryRealColors, with LCOLOPT_REALIZED, should return the RGB values of
;**  the distinct colors available on the device. It is incorrect to simply
;**  return the RGB values supplied in the logical color table as this would
;**  imply that there were 256 distinct greys available on the device,
;**  whereas there can only be a maximum of less than 64 due to the hardware
;**  limitations and the correction factor. The xlate_logRGB_to_realRGB table
;**  is therefore used to map from any logical RGB to the corresponding
;**  realized RGB.
;*/

        public  xlate_logRGB_to_realRGB
xlate_logRGB_to_realRGB label   byte
        db       0      ; RGB value 0
        db       2
        db       2
        db       3
        db       4
        db       4
        db       9
        db       9
        db       9
        db       9
        db       9      ; RGB value 10
        db       9
        db       9
        db      16
        db      16
        db      16
        db      16
        db      16
        db      16
        db      16
        db      23      ; RGB value 20
        db      23
        db      23
        db      23
        db      23
        db      23
        db      29
        db      29
        db      29
        db      29
        db      29      ; RGB value 30
        db      29
        db      29
        db      36
        db      36
        db      36
        db      36      ; RGB value 36
        db      36
        db      36
        db      42
        db      42      ; RGB value 40
        db      42
        db      42
        db      42
        db      42
        db      48
        db      48
        db      48
        db      48
        db      48
        db      48      ; RGB value 50
        db      54
        db      54
        db      54
        db      54
        db      54
        db      54
        db      60
        db      60
        db      60
        db      60      ; RGB value 60
        db      60
        db      60
        db      66
        db      66
        db      66
        db      66
        db      66
        db      66
        db      71
        db      71      ; RGB value 70
        db      71
        db      71
        db      71      ; RGB value 73
        db      77
        db      77
        db      77
        db      77
        db      77
        db      77
        db      82      ; RGB value 80
        db      82
        db      82
        db      82
        db      82
        db      88      ; RGB value 85
        db      88
        db      88
        db      88
        db      88
        db      88      ; RGB value 90
        db      93
        db      93
        db      93
        db      93
        db      93
        db      98
        db      98
        db      98
        db      98
        db      98      ; RGB value 100
        db     104
        db     104
        db     104
        db     104
        db     104
        db     104
        db     109
        db     109
        db     109      ; RGB value 109
        db     109      ; RGB value 110
        db     109
        db     114
        db     114
        db     114
        db     114
        db     114
        db     119
        db     119
        db     119
        db     119      ; RGB value 120
        db     119
        db     124
        db     124
        db     124
        db     124
        db     124
        db     129
        db     129
        db     129
        db     129      ; RGB value 130
        db     129
        db     134
        db     134
        db     134
        db     134
        db     134
        db     139
        db     139
        db     139
        db     139      ; RGB value 140
        db     139
        db     144
        db     144
        db     144
        db     144
        db     148      ; RGB value 146
        db     148
        db     148
        db     148
        db     148      ; RGB value 150
        db     153
        db     153
        db     153
        db     153
        db     153
        db     158
        db     158
        db     158
        db     158
        db     158      ; RGB value 160
        db     163
        db     163
        db     163
        db     163
        db     167
        db     167
        db     167
        db     167
        db     167
        db     172      ; RGB value 170
        db     172
        db     172
        db     172
        db     172
        db     176
        db     176
        db     176
        db     176
        db     181
        db     181      ; RGB value 180
        db     181
        db     181      ; RGB value 182
        db     181
        db     186
        db     186
        db     186
        db     186
        db     190
        db     190
        db     190      ; RGB value 190
        db     190
        db     190
        db     195
        db     195
        db     195
        db     195
        db     199
        db     199
        db     199
        db     199      ; RGB value 200
        db     199
        db     203
        db     203
        db     203
        db     203
        db     208
        db     208
        db     208
        db     208
        db     208      ; RGB value 210
        db     212
        db     212
        db     212
        db     212
        db     217
        db     217
        db     217
        db     217
        db     221      ; RGB value 219
        db     221      ; RGB value 220
        db     221
        db     221
        db     221
        db     225
        db     225
        db     225
        db     225
        db     230
        db     230
        db     230      ; RGB value 230
        db     230
        db     234
        db     234
        db     234
        db     234
        db     234
        db     238
        db     238
        db     238
        db     238      ; RGB value 240
        db     242
        db     242
        db     242
        db     242
        db     247
        db     247
        db     247
        db     247
        db     251
        db     251      ; RGB value 250
        db     251
        db     251
        db     255
        db     255
        db     255      ; RGB value 255



globalB fpalettetype,DEFAULT_PALETTE    ; start with default palette

globalB saved_fbClrTbl,0                ; flag byte of the realized color table

        public  saved_ClrTbl
        ; this is used to hold a complete saved copy of the realized color
        ; table in a form which can immediately be used by the standard
        ; routines (used when searching for the correct ipc to use for
        ; a system color used when another DC has realized its table)
saved_ClrTbl label   byte
        db      1546 dup (0)
        ; SIZE COLOR_TABLE+LOGICAL_COLOR_TABLE_SIZE*(DRGB_SIZE+SIZE_IPC)

        even

;/*
;** -----------------------------------------------------------------------;
;**             define corresponding constants
;** 
;**  I carefully chose the ipc's above so that the color intensities
;**  would be evenly spaced.  The main reason is that it will make our
;**  dithering algorithm trivial.  However, one might claim that this
;**  is     in that the eye responds logarithmically, so we should have
;**  fewer intense colors and more dim ones.  I don't know if that's true.
;** 
;**  But whatever intensities are choosen, they need be mapped linearly
;**  based on their intensities to our standard 0 to 255 RGB values.
;** 
;**  Given the ipc's we've chosen, we will have evenly spaced RGBs.
;**  So the ipc_to_RGB constants defined below will have 7ths of 255 for
;**  Red and Green, and 3rds of 255 for Blue.
;**------------------------------------------------------------------------;
;*/


MakePal Macro   index,CurrR,CurrG,CurrB
        if      ((CurrR + CurrG + CurrB) GE 384)
PHY_COLOR_WORD_&index = index + MONO_BIT
        else
PHY_COLOR_WORD_&index = index
        endif
PHY_COLOR_DATA_&index   equ     (CurrR Shl 16)+(CurrG Shl 8)+CurrB
        Endm

RGBIndex = 0
        irp     CurrR,<0,43,85>
        irp     CurrG,<0,36,73,109,146,182,219,255>
        irp     CurrB,<0,85,170,255>
        MakePal %RGBIndex,CurrR,CurrG,CurrB
RGBIndex = RGBIndex + 1
        endm
        endm
        endm
        irp     CurrR,<128>
        irp     CurrG,<0,36,73,109>
        irp     CurrB,<0,85,170,255>
        MakePal %RGBIndex,CurrR,CurrG,CurrB
RGBIndex = RGBIndex + 1
        endm
        endm
        endm
        MakePal 112,1,1,1
        MakePal 113,8,8,8
        MakePal 114,16,16,16
        MakePal 115,24,24,24
        MakePal 116,32,32,32
        MakePal 117,41,41,41
        MakePal 118,49,49,49
        MakePal 119,57,57,57
        MakePal 120,65,65,65
        MakePal 121,74,74,74
        MakePal 122,82,82,82
        MakePal 123,90,90,90
        MakePal 124,98,98,98
        MakePal 125,106,106,106
        MakePal 126,115,115,115
        MakePal 127,123,123,123
        MakePal 128,131,131,131
        MakePal 129,139,139,139
        MakePal 130,148,148,148
        MakePal 131,156,156,156
        MakePal 132,164,164,164
        MakePal 133,172,172,172
        MakePal 134,180,180,180
        MakePal 135,189,189,189
        MakePal 136,197,197,197
        MakePal 137,205,205,205
        MakePal 138,213,213,213
        MakePal 139,222,222,222
        MakePal 140,230,230,230
        MakePal 141,238,238,238
        MakePal 142,246,246,246
        MakePal 143,254,254,254
RGBIndex = RGBIndex + 32
        irp     CurrR,<128>
        irp     CurrG,<146,182,219,255>
        irp     CurrB,<0,85,170,255>
        MakePal %RGBIndex,CurrR,CurrG,CurrB
RGBIndex = RGBIndex + 1
        endm
        endm
        endm
        irp     CurrR,<170,213,255>
        irp     CurrG,<0,36,73,109,146,182,219,255>
        irp     CurrB,<0,85,170,255>
        MakePal %RGBIndex,CurrR,CurrG,CurrB
RGBIndex = RGBIndex + 1
        endm
        endm
        endm

PHY_COLOR_WORD_0   = PHY_COLOR_WORD_0            + ONES_OR_ZEROS
PHY_COLOR_WORD_255 = PHY_COLOR_WORD_255 + ONES_OR_ZEROS

;/*
;** MakeIPC
;*/

;/*
;**----------- define high ipc byte --------
;*/

MakeIPC Macro   index,CurrR,CurrG,CurrB
monotmp = CurrR + CurrG + CurrB
ipctmp  = 0
        If      (index EQ 0) Or (index EQ 255)
ipctmp  = ipctmp + ONES_OR_ZEROS
        Endif
        If      (monotmp GE 180h)
ipctmp  = ipctmp + MONO_BIT
        Endif
        db      High ipctmp
        Endm


sEnd    Data
;/*
;**------------------------ end Data, start VioSeg -------------------------;
;*/
        page

sBegin  VioSeg
        assumes cs,VioSeg
        
;/*
;** -----------------------------------------------------------------------;
;**  ColorMap is used by VIO in CellDraw.asm
;** 
;**  The color map below (ColorMap) entries are indices into the 8514's
;**  256-entry color map.  These 8-bit indices can be broken down into
;**  3 bits of RED, 3 bits of GREEN and 2 bits of BLUE.  So, ColorMap
;**  entry 7 (White), being 0b6h can be broken down into the following
;**  bits:
;** 
;**            7  6  5  4   3  2  1  0  --  bit number
;**            ----------   ----------
;**            1  0  1  1   0  1  1  0  --  0B6h
;**            |  |  |  |   |  |  |  |
;**            \  |  /  \   |  /  \  /
;**               |       \ | /    Blue
;**              Red      Green
;** 
;**              101       101      10
;** 
;** 
;**  0      1      2      3      4      5        6       7
;**  Black  Blue   Green  Cyan   Red    Magenta  Brown   White
;** 
;**  8      9      A      B      C      D        E       F
;**  Grey   Light  Light  Light  Light  Light    Yellow  White (High
;**         Blue   Green  Cyan   Red    Magenta          Intensity)
;** 
;**  These are the same colors as in our default color table, but in a
;**  slightly different order.
;** 
;** -----------------------------------------------------------------------;
;*/

        public  ColorMap
ColorMap db      0FFh  AND  PHY_COLOR_WORD_0         ; black
         db      0FFh  AND  PHY_COLOR_WORD_2         ; dark blue
         db      0FFh  AND  PHY_COLOR_WORD_16        ; dark green
         db      0FFh  AND  PHY_COLOR_WORD_18        ; dark turquoise
         db      0FFh  AND  PHY_COLOR_WORD_160       ; dark red
         db      0FFh  AND  PHY_COLOR_WORD_162       ; purple
         db      0FFh  AND  PHY_COLOR_WORD_144       ; mustard
         db      0FFh  AND  PHY_COLOR_WORD_137       ; dark gray

         db      0FFh  AND  PHY_COLOR_WORD_128       ; gray
         db      0FFh  AND  PHY_COLOR_WORD_3         ; blue
         db      0FFh  AND  PHY_COLOR_WORD_28        ; green
         db      0FFh  AND  PHY_COLOR_WORD_31        ; turquoise (cyan)
         db      0FFh  AND  PHY_COLOR_WORD_224       ; red
         db      0FFh  AND  PHY_COLOR_WORD_227       ; pink (magenta)
         db      0FFh  AND  PHY_COLOR_WORD_252       ; yellow
         db      0FFh  AND  PHY_COLOR_WORD_255       ; white

sEnd VioSeg

;/*
;**------------------------ end VioSeg, start Code -------------------------;
;*/
        page

sBegin  Code
        assumes cs,Code
        externW CodeData

        externNP calc_rgb_distance               ;  COLORTBL.ASM

;/*
;** create the IPC flags bytes
;*/

        public  aipcLookup
aipcLookup      label   byte
IPCFlags        label   byte


RGBIndex = 0
        irp     CurrR,<0,43,85>
        irp     CurrG,<0,36,73,109,146,182,219,255>
        irp     CurrB,<0,85,170,255>
        MakeIPC %RGBIndex,CurrR,CurrG,CurrB
RGBIndex = RGBIndex + 1
        endm
        endm
        endm
        irp     CurrR,<128>
        irp     CurrG,<0,36,73,109>
        irp     CurrB,<0,85,170,255>
        MakeIPC %RGBIndex,CurrR,CurrG,CurrB
RGBIndex = RGBIndex + 1
        endm
        endm
        endm
        MakeIPC 112,1,1,1
        MakeIPC 113,8,8,8
        MakeIPC 114,16,16,16
        MakeIPC 115,24,24,24
        MakeIPC 116,32,32,32
        MakeIPC 117,41,41,41
        MakeIPC 118,49,49,49
        MakeIPC 119,57,57,57
        MakeIPC 120,65,65,65
        MakeIPC 121,74,74,74
        MakeIPC 122,82,82,82
        MakeIPC 123,90,90,90
        MakeIPC 124,98,98,98
        MakeIPC 125,106,106,106
        MakeIPC 126,115,115,115
        MakeIPC 127,123,123,123
        MakeIPC 128,131,131,131
        MakeIPC 129,139,139,139
        MakeIPC 130,148,148,148
        MakeIPC 131,156,156,156
        MakeIPC 132,164,164,164
        MakeIPC 133,172,172,172
        MakeIPC 134,180,180,180
        MakeIPC 135,189,189,189
        MakeIPC 136,197,197,197
        MakeIPC 137,205,205,205
        MakeIPC 138,213,213,213
        MakeIPC 139,222,222,222
        MakeIPC 140,230,230,230
        MakeIPC 141,238,238,238
        MakeIPC 142,246,246,246
        MakeIPC 143,254,254,254
RGBIndex = RGBIndex + 32
        irp     CurrR,<128>
        irp     CurrG,<146,182,219,255>
        irp     CurrB,<0,85,170,255>
        MakeIPC %RGBIndex,CurrR,CurrG,CurrB
RGBIndex = RGBIndex + 1
        endm
        endm
        endm
        irp     CurrR,<170,213,255>
        irp     CurrG,<0,36,73,109,146,182,219,255>
        irp     CurrB,<0,85,170,255>
        MakeIPC %RGBIndex,CurrR,CurrG,CurrB
RGBIndex = RGBIndex + 1
        endm
        endm
        endm

        page

;/***************************************************************************
;*
;* FUNCTION NAME = rgb_to_ipc
;*
;* DESCRIPTION   = rgb_to_ipc accepts a logical RGB color value and returns   
;*                 the device dependent, physical representation of bits      
;*                 necessary to display the color closest to the specified    
;*                 color on the device.                                       
;*                 
;*                 Registers Preserved:
;*                       BX,CX,DX,SI,DI,DS,ES
;*                 Registers Destroyed:
;*                       AX,FLAGS
;*                 
;* INPUT         = DX:AX   =  RGB color (AL=blue, AH=green, DL=red) 
;* OUTPUT        = AL      = physical color index 
;*                 AH      = ipcFlags             
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

mult    macro reg,const,scratch         ;; multiplies reg by const
    if const eq 3
        mov     scratch,reg
        add     reg,reg
        add     reg,scratch
    elseif const eq 7
        mov     scratch,reg
        shl     reg,3
        sub     reg,scratch
    elseif const eq 6
        mov     scratch,reg
        shl     reg,3
        sub     reg,scratch
        sub     reg,scratch
    elseif const eq 15
        mov     scratch,reg
        shl     reg,4
        sub     reg,scratch
    elseif const eq 31
        mov     scratch,reg
        shl     reg,5
        sub     reg,scratch
    else
        .errnz  1       ;; undefined use of mult.
    endif
endm

;/***************************************************************************
;*
;* FUNCTION NAME = far_rgb_to_ipc
;*
;* DESCRIPTION   = Calls rgb_to_ipc
;*                                                                          
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   far_rgb_to_ipc,<FAR,PUBLIC,NODATA,NONWIN>
cBegin
        call    rgb_to_ipc
cEnd

cProc   rgb_to_ipc,<NEAR,PUBLIC,NODATA,NONWIN>
cBegin

;/*
;** This is now a routine which decides which of two
;** specialist routines to pass the work on to
;*/

not_realizable:
        call    rgb_to_ipc_default
rgb_to_ipc_exit:
cEnd


cProc   far_rgb_to_ipc_default,<FAR,PUBLIC,NODATA,NONWIN>
cBegin
        call    rgb_to_ipc_default
cEnd

cProc   rgb_to_ipc_default,<NEAR,PUBLIC>,<cx,si> ;!!! is there a free register?

cBegin


;/*
;** Test for true grey.
;*/

        cmp     al,0
        je      not_true_grey
        cmp     al,255
        je      not_true_grey
        cmp     al,ah
        jne     not_true_grey
        cmp     al,dl
        jne     not_true_grey
        jmp     true_grey

not_true_grey:

;/*
;**BLUE
;*/
        mov     cl,ah
        xor     ah,ah
        mult    ax,3,si
        add     ax,81h                  ; half of the interval (80) + fudge factor (01)
        mov     al,ah                   ; AL now has our blue bits: XXXXXXBB

;/*
;**GREEN
;*/
        xor     ch,ch
        mult    cx,7,si                 ; CH now has our green bits
        add     cx,81h                  ; half of the interval (80) + fudge factor (01)
        shl     ch,2
        or      al,ch                   ; AL now has XXXGGGBB

;/*
;**RED
;*/
        xor     ch,ch
        mov     cl,dl
        mult    cx,6,si                 ; CH now has our red bits
        add     cx,81h                  ; half of the interval (80) + fudge factor (01)
        shl     ch,5
        or      al,ch                   ; AL now has RRRGGGBB

        cmp     al,112
        jb      found_index
        add     al,32
        jmp     found_index

true_grey:
        xor     ah,ah
        mult    ax,31,si
        add     ax,81h
        mov     al,ah
        add     al,112

;/*
;** Al = physical color bits
;*/

found_index:
        xchg    ax,bx                   ; save BX
        xor     bh,bh
        mov     bh,IPCFlags[bx]         ; get flag bits to high byte
        xchg    ax,bx                   ; restore BX, ipc to AX

;/*
;** Ah = IPC status flags
;*/

cEnd

cProc   far_rgb_to_ipc_realized,<FAR,PUBLIC,NODATA,NONWIN>
cBegin
        call    rgb_to_ipc_realized
cEnd


cProc   rgb_to_ipc_realized,<NEAR,PUBLIC>,<es,si,di,bx,cx>

        localD  mindifference           ; min difference between two values

cBegin

;/*
;** the following code is very similar to that in QueryColorIndex
;** any improvments here should be reflected there and vice versa
;*/


;/*
;** INPUT dx:ax = 0r:gb
;**       ds:si = ddc
;** OUTPUT ax = IPC of nearest value
;*/

        test    [si].ddc_fbClrTbl,DDC_RGB_MODE
        push    si
        jnz     get_saved_table
        les     si,[si].ddc_pClrTbl     ; es:si -> color table
        jmp     short table_got
get_saved_table:
        push    ds
        pop     es
        mov     si,DataOFFSET saved_ClrTbl
table_got:
        assumes es,nothing
        push    si                      ; we need -> color table again later
        mov     si,es:[si].ct_npargb    ; es:si -> rgb triplets

        mov     cx,256                  ; 256 entries to check
        mov     mindifference.hi,cx     ; max value in here by calculation is 2!
next_color:
        mov     di,cx                   ; save the count

;/*
;** get the rgb value from the LCT
;** this will either hold the value set by the user, or for undefined entries
;** the value will be the appropriate value from the default palette
;*/

        mov     cx,es:[si]              ; get Green and Blue values
        mov     dh,es:[si+2]            ; get Red value
        add     si,4                    ; advance to next LCT entry

;/*
;** compare the two RGBs to see if we have an exact match
;*/

        cmp     ax,cx
        jnz     not_exact_match
        cmp     dh,dl
        jz      exact_match

;/*
;** not an exact match, so must find how close the match was
;*/

not_exact_match:
        push    dx                      ; save the input Red
        push    ax                      ; save the input Green & Blue

        call    calc_rgb_distance       ; find how close the RGBs are

        cmp     dx,mindifference.hi     ; compare the high words
        jb      lower                   ; high word is lower, so whole is lower
        ja      not_lower               ; high word higher, so whole is higher
        ; high words are equal so check the low words
        cmp     ax,mindifference.lo     ; compare the low words
        jae     not_lower
lower:
        mov     mindifference.hi,dx     ; store the new minimum
        mov     mindifference.lo,ax
        mov     bx,di                   ; update the store of the lowest count
                                        ; (di holds the loop count from cx)

not_lower:
        pop     ax                      ; restore initial ax (Green/Blue)
        pop     dx                      ; restore initial dx (Red)
        mov     cx,di                   ; restore the loop count
        loop    next_color
        jmp     short rgb_to_ipc_realized_exit

exact_match:
        mov     bx,di                   ; get the current count into bx

rgb_to_ipc_realized_exit:
        mov     ax,256
        sub     ax,bx                   ; convert count to index

        pop     si                      ; es:si -> color table again
        lea     si,[si].ct_aipc         ; es:si = table of IPCs
        add     si,ax
        add     si,ax                   ; es:si -> IPC in table for index
        mov     ah,es:[si+1]            ; get the appropriate mono_bit
        pop     si
        test    [si].ddc_fbClrTbl,DDC_RGB_MODE
        jz      rgb_to_ipc_realized_end
        and     ax,not INVALID_IPC      ; all IPCs are valid in RGB mode
rgb_to_ipc_realized_end:
cEnd

page
;/***************************************************************************
;*
;* FUNCTION NAME = dither_brush
;*
;* DESCRIPTION   = The given logical solid brush is realized.  Each color for
;*                 the brush (RGB) is dithered for the color bruhses.
;*
;*                 The sum of all the colors is used to determine the dither
;*                 to use for monochrome portion of the brush.
;*                                                                          
;*
;*                 Registers Preserved:
;*                       SI,BP,ES,DS,FLAGS
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,DI,FLAGS
;*
;* INPUT         = DX:AX = rgb color to dither 
;*                 DS:SI --> ddc               
;* OUTPUT        = DL = oem_brush_accel flags 
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

;/*
;** -----------------------------------------------------------------------;
;**  The algoritm:
;** 
;**  We will duplicate a 2 pel by 2 pel square to make our dithered brush.
;**  Thus we seemingly have 4 times as many shades of red, of green and of
;**  blue.  This gives 64*256 = 16K simultaneous colors.
;** 
;**  The method is very similar to the way rgb_to_ipc works.  We start
;**  with the assumption that we have hardware colors 4 times as dense.
;**  So we get 4 bits of color info for Blue, and 5 bits for Green and Red.
;** 
;**  Now we spread this out evenly over the 4 pels.  This means dividing
;**  by four and painted each pel accordingly.  We can do that because
;**  we actually have hardware shades at those values.  Additionally we
;**  must keep track of the remainder (from the division) and increment
;**  (by one) the intensity of that many pels.
;** 
;**  We will follow this pattern:
;** 
;**      ---------    ---------    ---------    ---------     ---------
;**      |   |   |    | R |   |    | R |   |    | R | R |     | R | R |
;**      |   |   |    |   |   |    |   |   |    |   |   |     |   |   |
;**      ---------    ---------    ---------    ---------     ---------
;**      |   |   |    |   |   |    |   | R |    |   | R |     | R | R |
;**      |   |   |    |   |   |    |   |   |    |   |   |     |   |   |
;**      ---------    ---------    ---------    ---------     ---------
;** 
;**  But we'll put the Greens in backwards:
;** 
;**      ---------    ---------    ---------    ---------     ---------
;**      |   |   |    |   |   |    |   | G |    |   | G |     | G | G |
;**      |   |   |    |   |   |    |   |   |    |   |   |     |   |   |
;**      ---------    ---------    ---------    ---------     ---------
;**      |   |   |    | G |   |    | G |   |    | G | G |     | G | G |
;**      |   |   |    |   |   |    |   |   |    |   |   |     |   |   |
;**      ---------    ---------    ---------    ---------     ---------
;** 
;**  Thus if there are 3 green and 1 red, or vice versa, there wont be any
;**  black spots on the screen.  Hopefully this will give a more uniform dither,
;**  but it is likely that this effect will be hard to see.
;** 
;**      ---------------
;**      |      |      |
;**      | ipc1 | ipc2 |      The variables used in the routine below
;**      |      |      |      are intended to be arranged as shown at
;**      ---------------      the left.
;**      |      |      |
;**      | ipc3 | ipc4 |
;**      |      |      |
;**      ---------------
;** 
;**  Another important question:  How many (dithered) colors do we now have?
;**  Let's look at Blue:  In the palette we have 2 bits of blue
;**  giving 4 dividers and 3 intervals:
;** 
;**   |-----------------------|-----------------------|-----------------------|
;**   0                      55h                     AAh                     FFh
;** 
;**  We have two addtional bits of color information because of the 2x2=4
;**  pel dithered pattern.  So now we have 2^(2+2)=16 dividers giving 15
;**  intervals.  The size of each interval is 0FFh/15.
;** 
;**   |---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
;**   0              40h             80h             C0h             FFh
;** 
;**  Wrong!  Our extra bits serve only to break up the existing intervals.
;**  Think of it physically, with the different dithered combos we get.
;**  So we lose a little information at the high end.  The picture looks like:
;** 
;**   |-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|
;**   0                      55h                     AAh                     FFh
;** 
;**  So we have 2^(2+2) - 3 = 13 dividers giving 12 Blue
;**  intervals.  The size of each interval is 0FFh/12.
;** 
;**  For Red and Green there were 7 intervals, so now we have 7*4 = 28 intervals.
;**  The size of each interval is 0FFh/28
;**  We use this below in our calculatons.
;** -----------------------------------------------------------------------;
;*/

        assumes Ds,Data
        assumes Es,nothing

cProc   dither_brush,<NEAR,PUBLIC>,<ES>

ifdef DONT_DITHER
cBegin
        and     [si].ddc_pa.pa_fb,not PA_GRAY
        or      [si].ddc_pa.pa_fb,PA_SINGLE_CLR
cEnd
else ;DONT_DITHER

        localB  ipc1                    ; ipc for one of the 4 pels
        localB  ipc2                    ; ipc for one of the 4 pels  ;use BX
        localB  ipc3                    ; ipc for one of the 4 pels  ;use SI
        localB  ipc4                    ; ipc for one of the 4 pels  ;use DI
cBegin
        mov     bx,dx

;/*
;**Test for true grey.
;*/

        cmp     al,0
        je      dont_dither_grey
        cmp     al,255
        je      dont_dither_grey
        cmp     al,ah
        jne     dont_dither_grey
        cmp     al,bl
        jne     dont_dither_grey
        jmp     dither_grey
dont_dither_grey:

;/*
;**---------- BLUE --------------
;*/

        mov     cx,ax
        xor     ah,ah
        imul    ax,12                   ; Gives AH = blue bits: 0000BBBB
        add     ax,86h                  ; add half an interval (80) + fudge factor (06)
        mov     al,ah
        shr     al,2                    ; AL = intensity per pel
        and     ah,03h                  ; AH = remainder
        mov     bh,ah                   ; accumulate remainders to set flags
        mov     ipc2,al
        sub     ah,3                    ; set CF is remainder != 3
        sbb     al,-1                   ; add one to intensity if remainder = 3
        mov     ipc3,al
        add     ah,1                    ; this will set CF if remainder was 2
        adc     al,0
        mov     ipc1,al
        add     ah,1                    ; this will set CF if remainder was 1
        adc     al,0
        mov     ipc4,al


;/*
;**---------- GREEN --------------
;*/

        mov     al,ch
        xor     ah,ah
        imul    ax,28                   ; Gives AH = green bits: 000GGGGG
        add     ax,8Eh                  ; add half an interval (80) + fudge factor (0E)
        mov     al,ah
        and     al,00011100b            ; AL = intensity per pel 000GGG00
        and     ah,03h                  ; AH = remainder
        add     bh,ah                   ; accumulate remainders to set flags
        or      ipc1,al

        sub     ah,3                    ; set CF is remainder != 3
        jb      @F
        add     al,100b                 ; add one to intensity if remainder = 3
@@:
        or      ipc4,al
        inc     ah
        jnz     @F
        add     al,100b                 ; add one to intensity if remainder = 2
@@:
        or      ipc2,al
        inc     ah
        jnz     @F
        add     al,100b                 ; add one to intensity if remainder = 1
@@:
        or      ipc3,al

;/*
;**---------- RED --------------
;*/

        mov     al,bl
        xor     ah,ah
        imul    ax,24                   ; Gives AH = red bits: 000RRRRR
        add     ax,8Ch                  ; add half an interval (80) + fudge factor (0E)
        mov     al,ah
        and     al,00011100b            ; AL = intensity per pel 000RRR00
        shl     al,3                    ; AL = intensity per pel RRR00000
        and     ah,03h                  ; AH = remainder
        add     bh,ah                   ; accumulate remainders to set flags
        or      ipc3,al

        sub     ah,3                    ; set CF is remainder != 3
        jb      @F
        add     al,100000b              ; increment intensity if remainder = 3
@@:
        or      ipc2,al
        inc     ah
        jnz     @F
        add     al,100000b              ; increment intensity if remainder = 2
@@:
        or      ipc4,al
        inc     ah
        jnz     @F
        add     al,100000b              ; increment intensity if remainder = 1
@@:
        or      ipc1,al

        cmp     ipc1,112
        jb      ipc1_set
        add     ipc1,32
ipc1_set:
        cmp     ipc2,112
        jb      ipc2_set
        add     ipc2,32
ipc2_set:
        cmp     ipc3,112
        jb      ipc3_set
        add     ipc3,32
ipc3_set:
        cmp     ipc4,112
        jb      ipc4_set
        add     ipc4,32
ipc4_set:
        jmp     dithering_done

;/*
;**---------- GREY --------------
;*/

dither_grey:
        mov     ch,al                   ; for mono dithering
        xor     ah,ah
        imul    ax,124
        add     ax,0BEh                 ; add half an interval (80) + fudge factor (1E)
        mov     al,ah
        shr     al,2                    ; AL = intensity per pel
        and     ah,03h                  ; AH = remainder
        mov     bh,ah                   ; accumulate remainders to set flags
        mov     ipc2,al
        add     ipc2,112

        sub     ah,3                    ; set CF is remainder != 3
        sbb     al,-1                   ; add one to intensity if remainder = 3
        mov     ipc3,al
        add     ipc3,112

        add     ah,1                    ; this will set CF if remainder was 2
        adc     al,0
        mov     ipc1,al
        add     ipc1,112

        add     ah,1                    ; this will set CF if remainder was 1
        adc     al,0
        mov     ipc4,al
        add     ipc4,112

;/*
;** if BH is zero then it is a solid color, else not solid.
;*/

dithering_done:
        and     [si].ddc_pa.pa_fb,not PA_GRAY
        or      bh,bh
        jnz     dither_not_solid_color
        or      [si].ddc_pa.pa_fb,PA_SINGLE_CLR
dither_not_solid_color:


;/*
;** write the resulting brush in the DDC
;*/

stuff_the_brush:
        lea     di,[si].ddc_pa.pa_abColor
        mov     es,CodeData
        assumes es,nothing
        cld
        mov     al,ipc1
        mov     ah,ipc2     ; these could be a single word mov
        stosw
        stosw
        stosw
        stosw
        add     di,SIZE_PATTERN
        stosw
        stosw
        stosw
        stosw
        add     di,SIZE_PATTERN
        stosw
        stosw
        stosw
        stosw
        add     di,SIZE_PATTERN
        stosw
        stosw
        stosw
        stosw

        sub     di,(SIZE_PATTERN * 6)
        mov     al,ipc3
        mov     ah,ipc4     ; these could be a single word mov
        stosw
        stosw
        stosw
        stosw
        add     di,SIZE_PATTERN
        stosw
        stosw
        stosw
        stosw
        add     di,SIZE_PATTERN
        stosw
        stosw
        stosw
        stosw
        add     di,SIZE_PATTERN
        stosw
        stosw
        stosw
        stosw

;/*
;** Create the monochrome dither pattern.  Right now we have our
;** original (input) RGBs as BL:CH:CL = R:G:B.  Graphics masters
;** would be happiest if we mixed about 11% Blue with 30% Red and
;** 59% Green to get the Mono Brightness.  For simplicity here we
;** will approximate this as B/8 + 2R/8 + 5G/8,
;** i.e. 12.5%, 25%, 62.5%
;*/

        xor     bh,bh
        xor     ax,ax
        xchg    al,ch

;/*
;** now BX:AX:CX = R:G:B
;** We want to produce
;** 2 parts R
;** 5 parts G
;** 1 parts B
;*/

        mov     dx,cx           ; 1 part Blue
        add     dx,bx           ; 1 part  Red
        add     dx,bx           ; 2 parts Red
        add     dx,ax           ; 1 part Green
        add     ax,ax
        add     ax,ax
        add     dx,ax           ; 4 more parts Green
        add     dx,4
        shr     dx,3            ; Gives (2/8)R + (5/8)G + (1/8)B

        push    si                      ; save DDC
        xor     si,si
        .errnz  pa_abMono - (pa_abColor + (BITS_PEL * SIZE_PATTERN))
        cCall   mono_dither             ; DL = gray level

;/*
;** The mono_dither algorithm may generate an undesirable gray
;** (for 404040 and C0C0C0), so these are
;** special cased to a known grey that will be uniform across the
;** devices, and is known to have a satisfactory appearance.
;*/

        or      si,si                   ;Was this one of the greys?
        jz      mono_plane_dithered     ;  No
        test    si,100b                 ;If black or white, ignore it
        jnz     mono_plane_dithered     ;  Was black or white
        add     si,si                   ;Special case the grey
        mov     ax,cs:greys[si][-2]
        sub     di,SIZE_PATTERN
        stosw
        stosw
        stosw
        stosw
        .errnz  SIZE_PATTERN - 8
mono_plane_dithered:
        pop     si

cEnd

endif ;DONT_DITHER


greys   label   word
        db      088h,022h               ;Dark grey dither
        db      0AAh,055h               ;Grey dither
        db      0DDh,077h               ;Light grey dither


S_HATCH_BR1_0   equ     0FFh and 01110111b      ;Solid Hatched brush 1
S_HATCH_BR1_1   equ     0FFh and 11111111b
S_HATCH_BR1_2   equ     0FFh and 11111111b
S_HATCH_BR1_3   equ     0FFh and 11111111b
S_HATCH_BR1_4   equ     0FFh and 11011101b
S_HATCH_BR1_5   equ     0FFh and 11111111b
S_HATCH_BR1_6   equ     0FFh and 11111111b
S_HATCH_BR1_7   equ     0FFh and 11111111b

S_HATCH_BR2_0   equ     0FFh and 01110111b      ;Solid Hatched brush 2
S_HATCH_BR2_1   equ     0FFh and 11111111b
S_HATCH_BR2_2   equ     0FFh and 11011101b
S_HATCH_BR2_3   equ     0FFh and 11111111b
S_HATCH_BR2_4   equ     0FFh and 01110111b
S_HATCH_BR2_5   equ     0FFh and 11111111b
S_HATCH_BR2_6   equ     0FFh and 11011101b
S_HATCH_BR2_7   equ     0FFh and 11111111b

S_HATCH_BR3_0   equ     0FFh and 01110111b      ;Solid Hatched brush 3
S_HATCH_BR3_1   equ     0FFh and 11011101b
S_HATCH_BR3_2   equ     0FFh and 01110111b
S_HATCH_BR3_3   equ     0FFh and 11011101b
S_HATCH_BR3_4   equ     0FFh and 01110111b
S_HATCH_BR3_5   equ     0FFh and 11011101b
S_HATCH_BR3_6   equ     0FFh and 01110111b
S_HATCH_BR3_7   equ     0FFh and 11011101b

S_HATCH_BR4_0   equ     0FFh and 01110111b      ;Solid Hatched brush 4
S_HATCH_BR4_1   equ     0FFh and 10101010b
S_HATCH_BR4_2   equ     0FFh and 11011101b
S_HATCH_BR4_3   equ     0FFh and 10101010b
S_HATCH_BR4_4   equ     0FFh and 01110111b
S_HATCH_BR4_5   equ     0FFh and 10101010b
S_HATCH_BR4_6   equ     0FFh and 11011101b
S_HATCH_BR4_7   equ     0FFh and 10101010b

S_HATCH_BR5_0   equ     0FFh and 10101010b      ;Solid Hatched brush 5
S_HATCH_BR5_1   equ     0FFh and 01010101b
S_HATCH_BR5_2   equ     0FFh and 10101010b
S_HATCH_BR5_3   equ     0FFh and 01010101b
S_HATCH_BR5_4   equ     0FFh and 10101010b
S_HATCH_BR5_5   equ     0FFh and 01010101b
S_HATCH_BR5_6   equ     0FFh and 10101010b
S_HATCH_BR5_7   equ     0FFh and 01010101b

S_HATCH_BR6_0   equ     0FFh and not S_HATCH_BR4_0      ;Solid Hatched brush 6
S_HATCH_BR6_1   equ     0FFh and not S_HATCH_BR4_1
S_HATCH_BR6_2   equ     0FFh and not S_HATCH_BR4_2
S_HATCH_BR6_3   equ     0FFh and not S_HATCH_BR4_3
S_HATCH_BR6_4   equ     0FFh and not S_HATCH_BR4_4
S_HATCH_BR6_5   equ     0FFh and not S_HATCH_BR4_5
S_HATCH_BR6_6   equ     0FFh and not S_HATCH_BR4_6
S_HATCH_BR6_7   equ     0FFh and not S_HATCH_BR4_7

S_HATCH_BR7_0   equ     0FFh and not S_HATCH_BR3_0      ;Solid Hatched brush 7
S_HATCH_BR7_1   equ     0FFh and not S_HATCH_BR3_1
S_HATCH_BR7_2   equ     0FFh and not S_HATCH_BR3_2
S_HATCH_BR7_3   equ     0FFh and not S_HATCH_BR3_3
S_HATCH_BR7_4   equ     0FFh and not S_HATCH_BR3_4
S_HATCH_BR7_5   equ     0FFh and not S_HATCH_BR3_5
S_HATCH_BR7_6   equ     0FFh and not S_HATCH_BR3_6
S_HATCH_BR7_7   equ     0FFh and not S_HATCH_BR3_7

S_HATCH_BR8_0   equ     0FFh and not S_HATCH_BR2_0      ;Solid Hatched brush 8
S_HATCH_BR8_1   equ     0FFh and not S_HATCH_BR2_1
S_HATCH_BR8_2   equ     0FFh and not S_HATCH_BR2_2
S_HATCH_BR8_3   equ     0FFh and not S_HATCH_BR2_3
S_HATCH_BR8_4   equ     0FFh and not S_HATCH_BR2_4
S_HATCH_BR8_5   equ     0FFh and not S_HATCH_BR2_5
S_HATCH_BR8_6   equ     0FFh and not S_HATCH_BR2_6
S_HATCH_BR8_7   equ     0FFh and not S_HATCH_BR2_7

NS_HATCH_BR_0   equ     0FFh and 00000000b      ;No Shading Hatched brush
NS_HATCH_BR_1   equ     0FFh and 00000000b
NS_HATCH_BR_2   equ     0FFh and 00000000b
NS_HATCH_BR_3   equ     0FFh and 00000000b
NS_HATCH_BR_4   equ     0FFh and 00000000b
NS_HATCH_BR_5   equ     0FFh and 00000000b
NS_HATCH_BR_6   equ     0FFh and 00000000b
NS_HATCH_BR_7   equ     0FFh and 00000000b

A_HATCH_BR_0    equ     0FFh and not S_HATCH_BR5_0      ;Alternating Hatched brush
A_HATCH_BR_1    equ     0FFh and not S_HATCH_BR5_1
A_HATCH_BR_2    equ     0FFh and not S_HATCH_BR5_2
A_HATCH_BR_3    equ     0FFh and not S_HATCH_BR5_3
A_HATCH_BR_4    equ     0FFh and not S_HATCH_BR5_4
A_HATCH_BR_5    equ     0FFh and not S_HATCH_BR5_5
A_HATCH_BR_6    equ     0FFh and not S_HATCH_BR5_6
A_HATCH_BR_7    equ     0FFh and not S_HATCH_BR5_7

H_HATCH_BR_0    equ     0FFh and 11111111b      ;Horizontal Hatched brush colors
H_HATCH_BR_1    equ     0FFh and 00000000b
H_HATCH_BR_2    equ     0FFh and 00000000b
H_HATCH_BR_3    equ     0FFh and 00000000b
H_HATCH_BR_4    equ     0FFh and 11111111b
H_HATCH_BR_5    equ     0FFh and 00000000b
H_HATCH_BR_6    equ     0FFh and 00000000b
H_HATCH_BR_7    equ     0FFh and 00000000b

V_HATCH_BR_0    equ     0FFh and 10001000b      ;Vertical Hatched brush colors
V_HATCH_BR_1    equ     0FFh and 10001000b
V_HATCH_BR_2    equ     0FFh and 10001000b
V_HATCH_BR_3    equ     0FFh and 10001000b
V_HATCH_BR_4    equ     0FFh and 10001000b
V_HATCH_BR_5    equ     0FFh and 10001000b
V_HATCH_BR_6    equ     0FFh and 10001000b
V_HATCH_BR_7    equ     0FFh and 10001000b

if      1                                            ;@KY1

DB_HATCH_BR1_0  equ     0FFh and 00000001b      ;\ diagonal hatched brush 1
DB_HATCH_BR1_1  equ     0FFh and 10000000b
DB_HATCH_BR1_2  equ     0FFh and 01000000b
DB_HATCH_BR1_3  equ     0FFh and 00100000b
DB_HATCH_BR1_4  equ     0FFh and 00010000b
DB_HATCH_BR1_5  equ     0FFh and 00001000b
DB_HATCH_BR1_6  equ     0FFh and 00000100b
DB_HATCH_BR1_7  equ     0FFh and 00000010b

DB_HATCH_BR2_0  equ     0FFh and 10000001b      ;\ diagonal hatched brush 2
DB_HATCH_BR2_1  equ     0FFh and 01100000b
DB_HATCH_BR2_2  equ     0FFh and 00011000b
DB_HATCH_BR2_3  equ     0FFh and 00000110b
DB_HATCH_BR2_4  equ     0FFh and 10000001b
DB_HATCH_BR2_5  equ     0FFh and 01100000b
DB_HATCH_BR2_6  equ     0FFh and 00011000b
DB_HATCH_BR2_7  equ     0FFh and 00000110b

DF_HATCH_BR1_0  equ     0FFh and 10000000b      ;/ diagonal hatched brush 1
DF_HATCH_BR1_1  equ     0FFh and 00000001b
DF_HATCH_BR1_2  equ     0FFh and 00000010b
DF_HATCH_BR1_3  equ     0FFh and 00000100b
DF_HATCH_BR1_4  equ     0FFh and 00001000b
DF_HATCH_BR1_5  equ     0FFh and 00010000b
DF_HATCH_BR1_6  equ     0FFh and 00100000b
DF_HATCH_BR1_7  equ     0FFh and 01000000b

DF_HATCH_BR2_0  equ     0FFh and 10000001b      ;/ diagonal hatched brush 2
DF_HATCH_BR2_1  equ     0FFh and 00000110b
DF_HATCH_BR2_2  equ     0FFh and 00011000b
DF_HATCH_BR2_3  equ     0FFh and 01100000b
DF_HATCH_BR2_4  equ     0FFh and 10000001b
DF_HATCH_BR2_5  equ     0FFh and 00000110b
DF_HATCH_BR2_6  equ     0FFh and 00011000b
DF_HATCH_BR2_7  equ     0FFh and 01100000b

else                                                            ;@KY1

DB_HATCH_BR1_0  equ     0FFh and 00010001b      ;\ diagonal hatched brush 1
DB_HATCH_BR1_1  equ     0FFh and 10001000b
DB_HATCH_BR1_2  equ     0FFh and 01000100b
DB_HATCH_BR1_3  equ     0FFh and 00100010b
DB_HATCH_BR1_4  equ     0FFh and 00010001b
DB_HATCH_BR1_5  equ     0FFh and 10001000b
DB_HATCH_BR1_6  equ     0FFh and 01000100b
DB_HATCH_BR1_7  equ     0FFh and 00100010b

DB_HATCH_BR2_0  equ     0FFh and 10000001b      ;\ diagonal hatched brush 2
DB_HATCH_BR2_1  equ     0FFh and 01100000b
DB_HATCH_BR2_2  equ     0FFh and 00011000b
DB_HATCH_BR2_3  equ     0FFh and 00000110b
DB_HATCH_BR2_4  equ     0FFh and 10000001b
DB_HATCH_BR2_5  equ     0FFh and 01100000b
DB_HATCH_BR2_6  equ     0FFh and 00011000b
DB_HATCH_BR2_7  equ     0FFh and 00000110b

DF_HATCH_BR1_0  equ     0FFh and 10001000b      ;/ diagonal hatched brush 1
DF_HATCH_BR1_1  equ     0FFh and 00010001b
DF_HATCH_BR1_2  equ     0FFh and 00100010b
DF_HATCH_BR1_3  equ     0FFh and 01000100b
DF_HATCH_BR1_4  equ     0FFh and 10001000b
DF_HATCH_BR1_5  equ     0FFh and 00010001b
DF_HATCH_BR1_6  equ     0FFh and 00100010b
DF_HATCH_BR1_7  equ     0FFh and 01000100b

DF_HATCH_BR2_0  equ     0FFh and 10000001b      ;/ diagonal hatched brush 2
DF_HATCH_BR2_1  equ     0FFh and 00000110b
DF_HATCH_BR2_2  equ     0FFh and 00011000b
DF_HATCH_BR2_3  equ     0FFh and 01100000b
DF_HATCH_BR2_4  equ     0FFh and 10000001b
DF_HATCH_BR2_5  equ     0FFh and 00000110b
DF_HATCH_BR2_6  equ     0FFh and 00011000b
DF_HATCH_BR2_7  equ     0FFh and 01100000b

endif                                                           ;@KY1


;/*
;** These are the patterns for the base patterns.  Someday clean this
;** up and put it someplace reasonable.  Should have a pointer in the
;** DS to these so they cpuld change based on resoultion.
;*/

                public  abBasePatterns
abBasePatterns  label   byte

        db      S_HATCH_BR1_0, S_HATCH_BR1_1, S_HATCH_BR1_2, S_HATCH_BR1_3
        db      S_HATCH_BR1_4, S_HATCH_BR1_5, S_HATCH_BR1_6, S_HATCH_BR1_7
        db      S_HATCH_BR2_0, S_HATCH_BR2_1, S_HATCH_BR2_2, S_HATCH_BR2_3
        db      S_HATCH_BR2_4, S_HATCH_BR2_5, S_HATCH_BR2_6, S_HATCH_BR2_7
        db      S_HATCH_BR3_0, S_HATCH_BR3_1, S_HATCH_BR3_2, S_HATCH_BR3_3
        db      S_HATCH_BR3_4, S_HATCH_BR3_5, S_HATCH_BR3_6, S_HATCH_BR3_7
        db      S_HATCH_BR4_0, S_HATCH_BR4_1, S_HATCH_BR4_2, S_HATCH_BR4_3
        db      S_HATCH_BR4_4, S_HATCH_BR4_5, S_HATCH_BR4_6, S_HATCH_BR4_7
        db      S_HATCH_BR5_0, S_HATCH_BR5_1, S_HATCH_BR5_2, S_HATCH_BR5_3
        db      S_HATCH_BR5_4, S_HATCH_BR5_5, S_HATCH_BR5_6, S_HATCH_BR5_7
        db      S_HATCH_BR6_0, S_HATCH_BR6_1, S_HATCH_BR6_2, S_HATCH_BR6_3
        db      S_HATCH_BR6_4, S_HATCH_BR6_5, S_HATCH_BR6_6, S_HATCH_BR6_7
        db      S_HATCH_BR7_0, S_HATCH_BR7_1, S_HATCH_BR7_2, S_HATCH_BR7_3
        db      S_HATCH_BR7_4, S_HATCH_BR7_5, S_HATCH_BR7_6, S_HATCH_BR7_7
        db      S_HATCH_BR8_0, S_HATCH_BR8_1, S_HATCH_BR8_2, S_HATCH_BR8_3
        db      S_HATCH_BR8_4, S_HATCH_BR8_5, S_HATCH_BR8_6, S_HATCH_BR8_7
        db       V_HATCH_BR_0, V_HATCH_BR_1, V_HATCH_BR_2, V_HATCH_BR_3
        db       V_HATCH_BR_4, V_HATCH_BR_5, V_HATCH_BR_6, V_HATCH_BR_7
        db       H_HATCH_BR_0, H_HATCH_BR_1, H_HATCH_BR_2, H_HATCH_BR_3
        db       H_HATCH_BR_4, H_HATCH_BR_5, H_HATCH_BR_6, H_HATCH_BR_7
        db      DF_HATCH_BR1_0,DF_HATCH_BR1_1,DF_HATCH_BR1_2,DF_HATCH_BR1_3
        db      DF_HATCH_BR1_4,DF_HATCH_BR1_5,DF_HATCH_BR1_6,DF_HATCH_BR1_7
        db      DF_HATCH_BR2_0,DF_HATCH_BR2_1,DF_HATCH_BR2_2,DF_HATCH_BR2_3
        db      DF_HATCH_BR2_4,DF_HATCH_BR2_5,DF_HATCH_BR2_6,DF_HATCH_BR2_7
        db      DB_HATCH_BR1_0,DB_HATCH_BR1_1,DB_HATCH_BR1_2,DB_HATCH_BR1_3
        db      DB_HATCH_BR1_4,DB_HATCH_BR1_5,DB_HATCH_BR1_6,DB_HATCH_BR1_7
        db      DB_HATCH_BR2_0,DB_HATCH_BR2_1,DB_HATCH_BR2_2,DB_HATCH_BR2_3
        db      DB_HATCH_BR2_4,DB_HATCH_BR2_5,DB_HATCH_BR2_6,DB_HATCH_BR2_7
        db      NS_HATCH_BR_0, NS_HATCH_BR_1, NS_HATCH_BR_2, NS_HATCH_BR_3
        db      NS_HATCH_BR_4, NS_HATCH_BR_5, NS_HATCH_BR_6, NS_HATCH_BR_7
        db      0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
        db      A_HATCH_BR_0,  A_HATCH_BR_1,  A_HATCH_BR_2,  A_HATCH_BR_3
        db      A_HATCH_BR_4,  A_HATCH_BR_5,  A_HATCH_BR_6,  A_HATCH_BR_7


;/***************************************************************************
;*
;* FUNCTION NAME = mono_dither
;*
;* DESCRIPTION   = 
;*
;*    This function takes value between 0 - 255 and uses it to create
;*    an 8x8 pile of bits that can be used as a brush.  It does this
;*    by reducing the input value to a number between 0 - 64 and then
;*    turns on that many bits in the 8x8 field.  Thus the value 0 leads
;*    to brush of all zeros, a 255 value leads to a brush of all 1's,
;*    and a value of 128 leads to grey.
;*
;*    The algorithm is equivalent to turning on bits based on an array:
;*
;*         0 32  8 40  2 34 10 42
;*        48 16 56 24 50 18 58 26
;*        12 44  4 36 14 46  6 38         This table favors devices like
;*        60 28 52 20 62 30 54 22         the Hercules card where the
;*         3 35 11 43  1 33  9 41         aspect ratio is close to 1:1
;*        51 19 59 27 49 17 57 25
;*        15 47  7 39 13 45  5 37
;*        63 31 55 23 61 29 53 21
;*
;*         0 32 16 48  2 34 18 50
;*        24 56  8 40 26 58 10 42         This table favors devices like
;*         4 36 20 52  6 38 22 54         the CGA card where the aspect
;*        28 60 12 44 30 62 14 46         ratio is close to 2:1
;*         3 35 19 51  1 33 17 49
;*        27 59 11 43 25 57  9 41
;*         7 39 23 55  5 37 21 53
;*        31 63 15 47 29 61 13 45
;*
;*
;*    Where given a value between 0 - 64, turn on the bit if the array
;*    value is less then the desired value.
;*
;*    When dithering for color drivers, where each plane is dither
;*    independantly, this algorithm has a nice side effect in that
;*    for any value n < m, n is a proper subset of m (any bit turned
;*    on in n must have been turned on in m!).
;*
;*    For the 1:1 table, undesirable patterns are generated for light
;*    and dark grey.  These will be flagged when encountered.  For the
;*    2:1 table,  vertical lines are generated for grey, so they will
;*    be flagged when encountered.  The brush realization routines
;*    can then substitute the correct grey (we cannot do it because
;*    we do not know if the other planes of a color brush were the
;*    same pattern).
;*
;*    Reference:  A Survey of Techniques for the Display of Continuous
;*                Tone Pictures on Bilevel Displays,;
;*                Jarvis, Judice, & Ninke;
;*                COMPUTER GRAPHICS AND IMAGE PROCESSING 5, pp 13-40, (1976)
;*
;*                Registers Destroyed:
;*                      AX,BX,CX,DX,FLAGS
;*
;* INPUT         = DL     =  value to dither         
;*                 ES:DI --> destination
;*                 SI     =  previous grey indicator
;*
;* OUTPUT        = ES:DI --> next destination (ES:DI + SIZE_PATTERN)
;*                 DH     =  dither value (0-64)
;*                 SI     =  New grey indicator (SI << 3 || grey_indicator)
;*                             D2:D0 = 001b for dark  grey
;*                             D2:D0 = 010b for grey
;*                             D2:D0 = 011b for light grey
;*                             D2:D0 = 100b for black
;*                             D2:D0 = 101b for white
;*                             D2:D0 = 000b otherwise
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing

cProc   mono_dither,<NEAR,PUBLIC,NODATA>,<ds>
cBegin
        mov     cx,3                    ;Will be usefull
        xor     bx,bx                   ;Need a zero a few times
        xchg    ax,si                   ;Need SI later
        shl     ax,cl                   ;Update old grey flags
        inc     cx                      ;4 will be useful later

        shr     dl,1                    ;Convert value 0-255 into
        adc     dl,bl                   ;  value 0 - 64
        shr     dl,1
        mov     bl,dl                   ;base_pattern index is D6:D2
        mov     dh,dl                   ;Return mapped value to caller in DL
        and     bl,11111100b

        lea     si,abMonoBasePatterns[bx]    ;Copy the base pattern
        cld
        movs    word ptr es:[di],word ptr cs:[si]
        movs    word ptr es:[di],word ptr cs:[si]
        sub     si,cx                   ;Duplicate for second half of brush
        movs    word ptr es:[di],word ptr cs:[si]
        movs    word ptr es:[di],word ptr cs:[si]
        xchg    ax,si                   ;Restore grey flags

        test    dl,00000011b            ;A base pattern?
        jnz     not_base_pattern
        test    dl,00001111b            ;A grey to special case?
        jnz     mono_dither_exit        ;  No, it is not
        shr     bx,cl                   ;D6:D4 is index into grey_flags
        mov     bl,cs:grey_flags[bx]    ;Or in grey flag
        or      si,bx
        jmp     short mono_dither_exit

not_base_pattern:
        shr     bx,1                    ;D5:D2 will index into abRowsMasks
        and     bl,0FEh                 ;Indexing into words, must be 0
        mov     ax,cs:auRowsMasks[bx]   ;AL = base row, AH = base mask
        mov     bl,al                   ;Set base row
        sub     bx,8                    ;Adjust for di pointing past brush
        mov     al,ah                   ;Shift pattern for proper use
        shr     al,cl                   ;AH is base pattern, AL is base >> 4

        and     dl,11b                  ;Dispatch as needed
        cmp     dl,2                    ;CL = 2
        jb      first_bit
        je      second_bit

third_bit:
        or      es:[di][bx][0],al       ;Set third bit

second_bit:
        or      es:[di][bx][4],al       ;Set second bit

first_bit:
        or      es:[di][bx][0],ah       ;Set first bit

mono_dither_exit:
cEnd


page

;/*
;**       The grey_flags table contains the values to OR into the
;**       accumulated grey flag for colors which mapped to the
;**       greys which must be special cased.
;*/


grey_flags      label   byte

                db      100b             ;Black      (00)
                db      001b             ;Dark Grey  (16)
                db      010b             ;Grey       (32)
                db      011b             ;Light Grey (48)
                db      101b             ;White      (64)


;/*
;**     The order in which the rows of the dither are accessed
;**     are as follows:
;**
;**         0,4,0,4,2,6,2,6             ;For low resolution
;**         1,5,1,5,3,7,3,7
;**         0,4,0,4,2,6,2,6
;**         1,5,1,5,3,7,3,7
;**         0,4,0,4,2,6,2,6
;**         1,5,1,5,3,7,3,7
;**         0,4,0,4,2,6,2,6
;**         1,5,1,5,3,7,3,7
;**
;**         0,4,0,4,2,6,2,6             ;For high resolution
;**         0,4,0,4,2,6,2,6
;**         1,5,1,5,3,7,3,7
;**         1,5,1,5,3,7,3,7
;**         0,4,0,4,2,6,2,6
;**         0,4,0,4,2,6,2,6
;**         1,5,1,5,3,7,3,7
;**         1,5,1,5,3,7,3,7
;**
;**
;**     The order in which bits are turned on is as follows:
;**
;**         80,08,08,80,80,08,08,80     ;For low resolutions
;**         20,02,02,20,20,02,02,20
;**         20,02,02,20,20,02,02,20
;**         80,08,08,80,80,08,08,80
;**         40,04,04,40,40,04,04,40
;**         10,01,01,10,10,01,01,10
;**         10,01,01,10,10,01,01,10
;**         40,04,04,40,40,04,04,40
;**
;**         80,08,08,80,20,02,02,20     ;For high resolution
;**         20,02,02,20,80,08,08,80
;**         40,04,04,40,10,01,01,10
;**         10,01,01,10,40,04,04,40
;**         40,04,04,40,10,01,01,10
;**         10,01,01,10,40,04,04,40
;**         80,08,08,80,20,02,02,20
;**         20,02,02,20,80,08,08,80
;**
;**
;**     If you work in groups of four, the following observations
;**     can be made about how the pixels are visited:
;**
;**     The rows are always accessed as follows:
;**
;**             row n
;**             row n+4
;**             row n
;**             row n+4
;**
;**
;**     The bits are always manipulated as follows:
;**
;**             bit n
;**             bit n >> 4
;**             bit n >> 4
;**             bit n
;**
;**
;**     Since base patterns are defined at intervals of four, the
;**     algorithm for turning on the remaining 1, 2, or 3 bits
;**     can be table driven.
;**
;**
;**     The following table will contain the row and the bitmask to
;**     use for turning on the remaining 1, 2, or 3 bits of the pattern.
;**     Bits D5:D2 of the mapped color are used to index into this table.
;**     The format is:
;**
;**             db      base row, base bit
;*/


auRowsMasks label   word

        db      0,80h
        db      2,20h
        db      0,20h
        db      2,80h
        db      1,40h
        db      3,10h
        db      1,10h
        db      3,40h
        db      0,40h
        db      2,10h
        db      0,10h
        db      2,40h
        db      1,80h
        db      3,20h
        db      1,20h
        db      3,80h


abMonoBasePatterns      label   byte

        db      000h,000h,000h,000h
        db      088h,000h,000h,000h
        db      088h,000h,022h,000h
        db      0AAh,000h,022h,000h
        db      0AAh,000h,0AAh,000h
        db      0AAh,044h,0AAh,000h
        db      0AAh,044h,0AAh,011h
        db      0AAh,055h,0AAh,011h
        db      0AAh,055h,0AAh,055h
        db      0EEh,055h,0AAh,055h
        db      0EEh,055h,0BBh,055h
        db      0FFh,055h,0BBh,055h
        db      0FFh,055h,0FFh,055h
        db      0FFh,0DDh,0FFh,055h
        db      0FFh,0DDh,0FFh,077h
        db      0FFh,0FFh,0FFh,077h
        db      0FFh,0FFh,0FFh,0FFh


;/***************************************************************************
;*
;* FUNCTION NAME = synthesize_xparent_mask
;*
;* DESCRIPTION   = The mono bits will be synthesized from the transparency
;*                 mask of the given brush.                                 
;*                                                                          
;*                 Registers Preserved:                                                                
;*                       SI,BP,DS                                                                      
;*                 Registers Destroyed:                                                                
;*                       AX,BX,CX,DX,DI,FLAGS                                                          
;*                                                                          
;* INPUT         = DS:SI --> DDC to use
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes Ds,Data
        assumes Es,nothing

cProc   synthesize_xparent_mask,<NEAR,PUBLIC>,<SI>
cBegin

;/*
;** All colors which match the background color will be set to 0 in the
;** transparency mask.  All other colors will be set to 1 in the mask.
;*/

        Mov     Bl,[Si].ddc_pa.pa_ba.ba_ipcBack
        Mov     Bh,Bl                   ; bg color in upper,lower bytes

        Mov     Cx,Ds
        Mov     Es,Cx
        assumes Es,Data
        Lea     Di,[Si].ddc_pa.pa_abMask; Es:Di -> transparency mask in ddc

        Add     Si,ddc_pa.pa_abColor    ; Ds:Si -> color pattern in ddc

        Mov     Cx,(SIZE_PATTERN*8)/2   ; # words (bytes for 4 bpp) to fetch
        Mov     Dl,00010001b            ; tells when to store a mask byte

ifdef HW4BPP
        Test    hwFlags,HW_8_BPP        ; 8 bpp ?
        .errnz  High HW_8_BPP
        Jz      sxm_4bpp                ; no -- handle 4 bpp case...
endif

;/*
;** create transparency mask from 8 bpp color pattern
;*/

sxm_8bpp_lp:

        Lodsw                           ; fetch 2 color pixels
;       And     Ax,Bx                   ; 0s where bg color ;@TAK: Commented
        Cmp     Al,1                    ; left pixel == bg color ?
        Cmc                             ; 'C'=1 if not
        Rcl     Dh,1                    ; add into building mask byte
        Cmp     Ah,1                    ; right pixel == bg color ?
        Cmc                             ; 'C'=1 if not
        Rcl     Dh,1                    ; add into building mask byte

        Rol     Dl,1                    ; full dest byte accumulated ?
        Jnc     @F                      ; not yet...
        Mov     Al,Dh                   ; yes, so must store it to mask
        Stosb
@@:

        Loop    sxm_8bpp_lp             ; for all words of color brush...

ifdef HW4BPP
        Jmp     sxm_exit                ; we are done...

;/*
;** create transparency mask from 4 bpp color brush
;*/

sxm_4bpp:

        Shl     Bh,4                    ; bg in upper nibble

sxm_4bpp_lp:

        Lodsb                           ; fetch 2 color pixels
        Mov     Ah,Al                   ; clone
        And     Ax,Bx                   ; 0s where bg color
        Cmp     Al,1                    ; left pixel == bg color ?
        Cmc                             ; 'C'=1 if not
        Rcl     Dh,1                    ; add into building mask byte
        Cmp     Ah,10h                  ; right pixel == bg color ?
        Cmc                             ; 'C'=1 if not
        Rcl     Dh,1                    ; add into building mask byte

        Rol     Dl,1                    ; full dest byte accumulated ?
        Jnc     @F                      ; not yet...
        Mov     Al,Dh                   ; yes, so must store it to mask
        Stosb
@@:

        Loop    sxm_4bpp_lp             ; for all words of color brush...

sxm_exit:
endif

cEnd


;/***************************************************************************
;*
;* FUNCTION NAME = synthesize_color_bits
;*
;* DESCRIPTION   = The color bits will be synthesized from the transparency mask
;*                 of the given brush.  The PA_GRAY accelerator is set if the
;*                 ONES_OR_ZEROS accelerator is set in both the foreground and
;*                 background colors, since it would mean the colors were either
;*                 black or white.
;*                                                                          
;*                 Registers Preserved:                                                                
;*                       SI,BP,DS                                                                      
;*                 Registers Destroyed:                                                                
;*                       AX,BX,CX,DX,DI,FLAGS                                                          
;*                                                                          
;* INPUT         = DS:SI --> DDC to use
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes Ds,Data
        assumes Es,nothing

cProc   synthesize_color_bits,<NEAR,PUBLIC>,<SI>
cBegin

        Mov     Bh,[Si].ddc_pa.pa_ba.ba_ipc; fg color
        Mov     Bl,[Si].ddc_pa.pa_ba.ba_ipcBack; bg color

        Mov     Cx,Ds
        Mov     Es,Cx
        assumes Es,Data
        Lea     Di,[Si].ddc_pa.pa_abColor; Es:Di is -> color brush bucket

        Add     Si,ddc_pa.pa_abMask     ; Ds:Si is -> transparency mask

        Mov     Cx,(SIZE_PATTERN * 8)   ; # color brush bytes to store at 8 bpp

ifdef HW4BPP
        Test    hwFlags,HW_8_BPP        ; 8 bpp ?
        .errnz  High HW_8_BPP
        Jz      scb_4bpp                ; no -- handle 4 bpp case...
endif

;/*
;** synthesize 8 bpp color brush from transparency mask
;*/

        Mov     Dl,10000000b            ; fetch mask byte every 8 color bytes

scb_8bpp_lp:

        Rol     Dl,1                    ; need new mask byte ?
        Jnc     @F                      ; not yet...
        Lodsb                           ; fetch new mask byte
        Mov     Ah,Al                   ; save here
@@:

        Mov     Al,Bl                   ; assume bg color
        Shl     Ah,1
        Jnc     @F                      ; it was...
        Mov     Al,Bh                   ; else will store fg color
@@:     Stosb                           ; store new byte to color brush

        Loop    scb_8bpp_lp             ; for all mask pixels...

ifdef HW4BPP
        Jmp     scb_exit                ; we are done...

;/*
;** synthesize 4 bpp color brush from transparency mask
;*/

scb_4bpp:

        Mov     Dl,10001000b            ; fetch mask byte every 4 color bytes
        Shr     Cx,1                    ; 1/2 the # of color brush bytes

scb_4bpp_lp:

        Rol     Dl,1                    ; need new mask byte ?
        Jnc     @F                      ; not yet...
        Lodsb                           ; fetch new mask byte
        Mov     Ah,Al                   ; save here
@@:

        Shl     Ah,1                    ; store bg color ?
        Jc      scb_4bpp_fg_0           ; no, fg...
        Mov     Al,Bl                   ; yes, fetch bg color
        Jmp     Short @F
scb_4bpp_fg_0:
        Mov     Al,Bh                   ; fetch fg color
@@:     Shl     Al,4                    ; to left pixel in byte

        Shl     Ah,1                    ; create next nibble
        Jc      scb_4bpp_fg_1
        Or      Al,Bl                   ; add in bg pixel
        Jmp     Short @F
scb_4bpp_fg_1:
        Or      Al,Bh                   ; add in fg pixel
@@:

        Stosb                           ; store color brush pixels

        Loop    scb_4bpp_lp             ; for all color brush 4bpp pixels...

scb_exit:
endif

cEnd


;/***************************************************************************
;*
;* FUNCTION NAME = mono_brush_from_mask
;*
;* DESCRIPTION   = The mono bits will be synthesized from the transparency
;*                 mask of the given brush.                                 
;*                                                                          
;*                 Registers Preserved:                                                                
;*                       SI,BP,DS                                                                      
;*                 Registers Destroyed:                                                                
;*                       AX,BX,CX,DX,DI,FLAGS                                                          
;*                                                                          
;* INPUT         = DS:SI --> DDC to use
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes Ds,Data
        assumes Es,nothing

cProc   synthesize_mono_bits,<NEAR,PUBLIC>,<SI>
cBegin

;/*
;** Get replicated versions of the mono colors corresponding to the current
;** pattern attribute fg and bg colors.
;*/

        Mov     Bl,[Si].ddc_pa.pa_ba.ba_ipc[1]
        Shr     Bl,1
        .errnz  Low MONO_BIT
        .errnz  High MONO_BIT - 00000001b
        Sbb     Bl,Bl                   ; replicated fg colors

        Mov     Bh,[Si].ddc_pa.pa_ba.ba_ipcBack[1]
        Shr     Bh,1
        .errnz  Low MONO_BIT
        .errnz  High MONO_BIT - 00000001b
        Sbb     Bh,Bh                   ; replicated bg colors

;/*
;** Set up for the main loop. We will be fetching bits from the transparency
;** mask, translating and storing back the mono pixels to the mono brush.
;*/

        Mov     Ax,Ds
        Mov     Es,Ax
        assumes Es,Data
        Lea     Di,[Si].ddc_pa.pa_abMono; Es:Di -> mono brush bits

        Add     Si,ddc_pa.pa_abMask     ; Ds:Si -> transparency mask bits

        Mov     Cx,SIZE_PATTERN         ; # bytes in mono brush

;/*
;**  Our modus operandi:
;** 
;**        1s in the transparency mask correspond to foreground pixels in the
;**        mono brush. Likewise, 0s in the transparency mask correspond to
;**        background pixels in the mono brush. We fetch the transparency bits
;**        8 bits at a time, isolate foreground bits as 1s in a register, and
;**        isolate background bits as 1s in another register (this is just the
;**        inverted value of the original byte). We AND in the actual fg and
;**        bg colors into the corresponding bits, combine into one register, and
;**        finally store the result back.
;*/

smb_lp: Lodsb                           ; fetch mask byte
        Mov     Ah,Al                   ; isolate fg,bg pixels
        Not     Ah                      ; 1s wherever bg pixels
        And     Ax,Bx                   ; Ah=bg colors, Al=fg colors
        Or      Al,Ah                   ; combine into Al
        Stosb                           ; store to mono brush
        Loop    smb_lp                  ; for all mono brush bytes...

cEnd


;/***************************************************************************
;*
;* FUNCTION NAME = rotate_brush     
;*
;* DESCRIPTION   = The brush is rotated right the given amount.             
;*
;*                 Registers Preserved: 
;*                       DI,SI,BP,DS    
;*                 Registers Destroyed: 
;*                       AX,CX,FLAGS    
;*
;* INPUT         = DS:SI --> DDC to use
;*                 CL   =  Amount to rotate right
;*
;* OUTPUT        = DS:SI --> DDC to use
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes Ds,Data
        assumes Es,nothing

cProc   rotate_brush,<NEAR,PUBLIC>,<SI>

        localV  PixelBucket,8           ; place to hold rotating pixels
        localW  RightPixels             ; # pixels to move on right end

cBegin

        Sub     Ch,Ch                   ; zext the rotation count

;/*
;** First we rotate the mono brush and transparency mask
;*/

        Lea     Di,[Si].ddc_pa.pa_abMono; Ds:Di is -> mono brush
        Mov     Bl,16                   ; rotate both brush and mask in loop
        .errnz  SIZE_PATTERN - 8
        .errnz  (pa_abMask-pa_abMono) - SIZE_PATTERN
rb_mono_mask:
        Ror     Byte Ptr [Di],Cl        ; rotate 8 pixels
        Inc     Di                      ; -> next 8 pixels
        Dec     Bl
        Jnz     rb_mono_mask            ; for all mask and brush bytes...

;/*
;** Now we rotate the color pixels in the color brush.
;*/

        Add     Si,ddc_pa.pa_abColor    ; Ds:Si -> color brush pixels
        Mov     Bx,SIZE_PATTERN         ; Bx is # of rows of pattern to process

ifdef HW4BPP
        Test    hwFlags,HW_8_BPP        ; 8 bpp ?
        Jz      rb_4_bpp                ; no...
endif

;/*
;** Rotate the brush made up of 8 bpp pixels
;*/

        Mov     Dx,Cx                   ; is # pixels on left end of rows
        Neg     Cx
        And     Cx,7
        .errnz  SIZE_PATTERN - 8
        xchg    dx,cx
        Mov     RightPixels,Cx          ; is # pixels on right end of rows

rb_8_bpp:

        Mov     Ax,Ss
        Mov     Es,Ax
        assumes Es,nothing
        Lea     Di,PixelBucket          ; Es:Di is -> holding area

        Mov     Cx,Dx                   ; # pixels on left to save off
    Rep Movsb                           ; get left pixels that are overwritten

        Mov     Ax,Ds
        Mov     Es,Ax
        assumes Es,Data
        Mov     Di,Si                   ; Ds:Si -> right pixels
        Sub     Di,Dx                   ; Es:Di -> to start of brush row

        Mov     Cx,RightPixels
    Rep Movsb                           ; move right pixels down

                                        ; Es:Di -> where to put left pixels
        Lea     Si,PixelBucket          ; Ss:Si -> left pixels to move
        Mov     Cx,Dx                   ; # of left pixels to move
    Rep Movs    Es:Byte Ptr [Di],Ss:Byte Ptr [Si]; move left pixels

        Mov     Si,Di                   ; Ds:Si -> next row start
        Dec     Bx                      ; 1 less row to rotate
        Jnz     rb_8_bpp                ; for all rows...

ifdef HW4BPP
        Jmp     Short rb_exit           ; we are done...

;/*
;** Rotate the brush made up of 4 bpp pixels
;*/

rb_4_bpp:

        Mov     Di,Bx                   ; row count kept here
        Mov     Ch,Cl                   ; save rotate count

rb_4_bpp_lp0:

        .errnz  SIZE_PATTERN - 8
        Lodsw                           ; P2|P3|P0|P1
        Mov     Dx,Ax
        Lodsw                           ; P6|P7|P4|P5
        Xchg    Ah,Dh                   ; P6|P7|P0|P1 in Ax, swizzle
                                        ; P2|P3|P4|P5 in Dx, swizzle

        Mov     Cl,Ch                   ; get rotate count

rb_4_bpp_lp1:

        Mov     Bl,Al
        Shl     Bl,4                    ; P1|00
        Mov     Bh,Dl
        Shl     Bh,4                    ; P5|00
        Shr     Ax,4                    ; 00|P6|P7|P0
        Or      Ah,Bh                   ; P5|P6|P7|P0
        Shr     Dx,4                    ; 00|P2|P3|P4
        Or      Dh,Bl                   ; P1|P2|P3|P4
        Dec     Cl                      ; 1 less rotation
        Jnz     rb_4_bpp_lp1            ; for all rotations...

        Xchg    Ah,Dh                   ; undo above swizzle
        Mov     Ds:[Si][-4],Ax          ; store rotated left 4 pixels
        Mov     Ds:[Si][-2],Dx          ; store rotated right 4 pixels

        Dec     Di                      ; drop row count
        Jnz     rb_4_bpp_lp0            ; for all rows...

rb_exit:
endif

cEnd


        page
;/***************************************************************************
;*
;* FUNCTION NAME = SetPatternFont
;*
;* DESCRIPTION   = Deals with font selection/bitmap bits for patterns.  This  
;*                 routine will not be called when the base pattern set is    
;*                 selected.                                                  
;*
;*                 Registers Preserved:
;*                       BX,CX,SI,DI,BP,DS
;*                 Registers Destroyed:
;*                       AX,DX,ES,FLAGS
;*                 Calls:
;*                       copy_bits_to_pattern
;*                 
;* INPUT         = DS:BX --> ddc                                                          
;*                 DX:AX  =  font handle / font pointer / bitmap handle
;*                 BP     =  attr index for characters
;*                 ES:SI --> attribute bundle
;*                                                                                         
;* OUTPUT        = PA_BITMAP_SRC and PA_COLOR_TRUTH bits clear in          
;*                 ddc->ddc_pa.pa_ba.ba_fb
;*
;* RETURN-NORMAL = AX = 1       
;* RETURN-ERROR  = AX = 0       
;*                 error logged 
;**************************************************************************/
 
        assumes ds,Data
        assumes es,nothing

FNT_GENERIC     equ     1

cProc   My_SetPatternFont,<PUBLIC,FAR,NODATA>,<cx,si,di>
cBegin
        ddc?    bx

;/*
;** Check whether we have a bitmap or a font.
;*/

        cmp     es:[si].dabnd_adef.adef_defSet.sel,HDBM_IDENT
        jnz     spf_font
        jmp     spf_bitmap

;/*
;** -----------------------------------------------------------------------;
;**  We have a font.  Set the codepage id, and get the codepage mapping
;**  vector if needed.  Set the following flags if needed (* --> always set):
;** 
;**        CA_MUST_MAP, CA_ABC_SPACING, CA_CHANGED (*), CA_USER_FONT (*)
;**        BA_REREALZE (*)
;** 
;**  Return errors in case of:
;** 
;**        vector font
;**        huge font (> 64K)
;**        failure reading codepage mapping vector
;** 
;**  We need to set the flags to make the brush realization code do
;**  something.  The PA_BITMAP_SRC and PA_COLOR_TRUTH bits have already
;**  been cleared by the caller.
;** 
;**  We can ignore the offset to the font because we FIREWALLed it to be
;**  zero, and all our code would fall apart if it wasn't.
;** -----------------------------------------------------------------------;
;*/

spf_font:
ifdef FIREWALLS
        mov     [bx].ddc_pa.pa_paus.sel,INVALID_SEL
endif

xyzzy   equ     CDEF_STRIKEOUT or CDEF_UNDERSCORE or CDEF_ITALIC or CDEF_BOLD
        test    es:[si].dabnd_adef.adef_fFlags,xyzzy
        jz      @F
        jmp     spf_bad_font_attrs
@@:
        mov     si,es:[si].dabnd_adef.adef_CodePage
        mov     cx,[bx].ddc_pa.pa_fs

        cmp     dx,INVALID_SEL       ;Don't gain access to bogus selectors
        je      spf_bad_font         ; used to be @F ?
        lar     ax,dx
        jz      @F
        cCall   gain_access_to_selector,<dx>
        or      ax,ax
        jnz     spf_bad_font            ; dosgetseg may have failed
@@:
        mov     es,dx
        assumes es,FontSeg
        test    fsMetrics.foca_fsTypeFlags,HUGE_FONT
        jnz     spf_huge_font

        test    fsMetrics.foca_fsDefn,FD_VECTOR
        jnz     spf_bad_font

        cmp     fsDef.fdh_fsChardef,FONTDEFCHAR3
        jne     @F
        or      cx,CA_ABC_SPACE
@@:

;/*
;** If the font is not in the default code page (850), then no mapping
;** is possible.  If the font is the default code page and a different
;** code page is to be used, get the mapping array.  If getting the
;** mapping array fails, return an error.
;*/

        cmp     fsMetrics.foca_usCodePage,DEFAULTVIOCODEPAGE
        jne     spf_font_done
        cmp     si,DEFAULTVIOCODEPAGE
        je      spf_font_done
        or      si,si                   ;0 = use the default in the font
        je      spf_font_done

;/*
;** Get the mapping vector for this code page.  Don't bother to get access
;** now since the access test has to be made at output time.
;*/

        check   QueryCodePageVector,<idCP,hddc,ulFunN>
        save    <bx,cx>
        xor     dx,dx
        farPtr  myCPID,dx,si
        farPtr  myhddc,dx,dx
        cCall   GreEntry3,<myCPID,myhddc,GreQueryCodePageVector>
        mov     [bx].ddc_pa.pa_paus.sel,dx
        mov     [bx].ddc_pa.pa_paus.off,ax
        or      ax,dx
        jz      spf_exit_vect           ;Error, return 0
        or      cx,CA_MUST_MAP

spf_font_done:
        or      [bx].ddc_pa.pa_ba.ba_fb,BA_REREALIZE
        or      cx,CA_CHANGED or CA_USER_FONT
        mov     [bx].ddc_pa.pa_fs,cx
        mov     ax,1
spf_exit_vect:
        jmp     spf_exit


;/*
;** Log the error and exit
;*/

spf_bad_font_attrs:
        mov     ax,PMERR_INV_PATTERN_SET_ATTR
        jmp     short spf_error

spf_bad_font:
        mov     ax,PMERR_INV_PATTERN_SET_FONT
        jmp     short spf_error

spf_huge_font:
        mov     ax,PMERR_HUGE_FONTS_NOT_SUPPORTED
spf_error:
        save_error_code
        xor     ax,ax
        jmp     spf_exit



;/*
;** We have a bitmap to copy into the pattern attributes structure.
;** Before anything else, check that its handle is valid, that the
;** surface is indeed a bitmap, and that it is neither null nor huge.
;** Of all those checks, only null or huge bitmaps are considered
;** errors to be returned to the caller, the others being internal errors
;** worthy of rips.
;*/

spf_bitmap:
        mov     di,ax                   ;move bitmap handle into index reg


ifdef FIREWALLS

;/*
;** Make sure the bitmap belongs to us.  If not, the engine screwed up.
;*/

        cmp     dx,HDBM_IDENT
        jne     spf_bad_handle
        cmp     [di].bm_sd.sd_usId,SURFACE_IDENT
        jne     spf_bad_handle
        test    [di].bm_sd.sd_fb,SD_DEVICE
        jz      spf_bitmap_handle_ok

spf_bad_handle:
        rip     text,<A bad bitmap handle came into SetPatternFont>
        xor     ax,ax
        jmp     short spf_exit

spf_bitmap_handle_ok:
endif


;/*
;** Make sure that we have a handle to bits if the bitmap is non-null.
;** Exit with an error if the bitmap is null or huge.
;*/

        test    [di].bm_sd.sd_fb,SD_NONNULL
        jz      spf_bad_font                ;it's a null bitmap --> no bits
        test    [di].bm_sd.sd_fb,SD_HUGE
        jnz     spf_bad_font                ;it's a huge bitmap --> get out
ifdef FIREWALLS
        cmp     [di].bm_sd.sd_pBits.sel,0   ;must have non-null selector
        jnz     spf_selector_ok

        rip     text,<A null bitmap selector came into SetPatternFont>
        xor     ax,ax
        jmp     short spf_exit
spf_selector_ok:
endif


;/*
;** Now that we believe the bitmap is valid, set up a call to copy the
;** bits based on whether it is in color or is monochrome.
;*/

        test    [di].bm_sd.sd_fb,SD_COLOR
        jz      spf_mono_bitmap

        or      [bx].ddc_pa.pa_fb,PA_BITMAP_SRC or PA_COLOR_TRUTH
        lea     si,[bx].ddc_pa.pa_abColor
        mov     cl,4
        jmp     short spf_copy_bitmap_bits

spf_mono_bitmap:
        or      [bx].ddc_pa.pa_fb,PA_BITMAP_SRC
        lea     si,[bx].ddc_pa.pa_abMask
        mov     cl,1

;/*
;** -----------------------------------------------------------------------;
;**  Set up the registers as follows:
;** 
;**        AL     =  number of color planes
;**        AH     =  width in pels
;**        DS:BX --> DDC
;**        CX     =  number of bytes per scan
;**        DX     =  height in scans
;**        DS:SI --> destination of bits
;**        ES:DI --> source bits
;** 
;**  The width is truncated to 8 pels to make it fit in a byte.  It is only
;**  needed to determine if the bitmap fills the entire pattern bits buffer.
;**  The access macro is called to prevent GP faults (which will happen
;**  without it!!).
;** 
;**  The brush realization code looks at the BA_REREALIZE and CA_CHANGED
;**  bits in the pattern attributes to determine if the brush bits need
;**  to be rerealized, so make sure we set these!
;** -----------------------------------------------------------------------;
;*/

spf_copy_bitmap_bits:
        mov     ax,[di].bm_sd.sd_pBits.sel      ;want ES:DI ptr to source bits
        mov     es,ax
        assumes es,nothing
        mov     ax,[di].bm_sd.sd_cx             ;width of source bitmap
        push    bx                              ;save work register
        mov     bx,PATTERN_WIDTH                ; 
        usmin_ax   bx                           ;make sure width fits in a byte
        pop     bx                              ;restore DDC
        mov     ah,al                           ;copy_bits... wants width here
        mov     al,cl                           ;  and wants plane cnt here
        mov     cx,[di].bm_sd.sd_cbScan         ;get bytes per scan line
        mov     dx,[di].bm_sd.sd_cy             ;height of source bitmap
        mov     di,[di].bm_sd.sd_pBits.off      ;offset of source bits
spf_copy_bits:
        cCall   copy_bits_to_pattern
        or      [bx].ddc_pa.pa_ba.ba_fb,BA_REREALIZE
        or      [bx].ddc_pa.pa_fs,CA_CHANGED
        mov     ax,1

spf_exit:
cEnd


        page
;/***************************************************************************
;*
;* FUNCTION NAME = copy_bits_to_pattern 
;*
;* DESCRIPTION   = Copys the specified bits to a pattern for a DDC
;*                 
;*                  Registers Preserved:        
;*                        BX,BP,DS              
;*                  Registers Destroyed:        
;*                        AX,CX,DX,SI,DI,FLAGS  
;*
;* INPUT         = AL   =  Number of color planes in source bitmap                 
;*                 AH   =  Width of bitmap (numbers only significant up through 8) 
;*                 DS:BX --> DDC
;*                 CX   =  Number of bytes per scan of source bitmap              
;*                 DX   =  Height of bitmap                                       
;*                 DS:SI --> Destination of bits (first BYTE of pattern bits buffer)
;*                 ES:DI --> Source bits (first BYTE of bits buffer)
;*                 
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        missing_code    <copy_bits_to_pattern -- need 4bpp code>

        assumes ds,Data
        assumes es,nothing

;/*
;** This function is public only for debugging.
;*/

cProc   copy_bits_to_pattern,<PUBLIC,NEAR,NODATA>,<>

        localB  SrcWidth        ;width in pels of source
        localW  SrcHeight       ;height in scans of source
        localW  ScanIncr        ;increment to next scan of source
        localB  PlaneCnt        ;number of color planes in source
        localB  InitScanCnt     ;number of scans to copy per plane of source
        localB  BitFillCnt      ;number of empty bits per scan in pattern
        localB  ScanFillCnt     ;number of empty scans in pattern
        localB  BackClr         ;our version of the background color

cBegin
        push    bx              ;save DDC

        xchg    ax,cx
        mov     PlaneCnt,cl     ;save number color planes for loop counter
        mov     SrcWidth,ch     ;save input to make space for calculations
        mov     ScanIncr,ax     ;scan increment always bytes-per-scan
        mov     SrcHeight,dx    ;need this a few times

        dec     dx              ;# scans offset to lower left scan of src
        mul     dx              ;get offset to lower left scan
        add     di,ax           ;ES:DI is -> lower left scan of src

        add     si,PATTERN_HEIGHT-1;assume mono dest, offset to lower left
        cmp     PlaneCnt,1      ;assumption correct?
        je      @F              ;yes...
                                ;no -- add in offset for 8 bpp pattern
        add     si,((PATTERN_HEIGHT-1)*PATTERN_WIDTH)-(PATTERN_HEIGHT-1)
@@:

;/*
;** Create an ipc (internal physical color) to use when padding empty
;** bits with the background color.  If the source is color, take the
;** background color as is.  If the source is monochrome, then background
;** color bits are written as 0, which Bitblt knows to translate into the
;** the current pattern background color.
;*/

        mov     bl,[bx].ddc_pa.pa_ba.ba_ipcBack.ipc_bClr
        cmp     PlaneCnt,2      ;C = 1 if mono source
        sbb     bh,bh           ;BH = 0FFh if mono source, =   0  if color
        not     bh              ;BH =   0  if mono source, = 0FFh if color
        and     bl,bh           ;background color forced to 0 if mono source
        mov     BackClr,bl      ;save background color bits

;/*
;** Determine whether or not the source has enough scans to fill the
;** destination buffer (it needs 8).  Save the number of scans which
;** need to be padded with the background color.  Save the inner loop
;** limit in InitScanCnt.
;*/

        mov     ax,PATTERN_HEIGHT  ;InitScanCnt = min(8, SrcHeight)
        usmin_ax SrcHeight         ; 
        mov     InitScanCnt,al     ;save inner loop limit
        neg     al                 ;ScanFillCnt = 8 - ScanCnt
        add     al,PATTERN_HEIGHT  ; 
        mov     ScanFillCnt,al     ;save for updating DDC, and doing the fill

;/*
;** Determine whether or not the source has enough bits to fill an entire
;** scan of the destination buffer (it needs 8).  Save the number of bits
;** which need to be padded with the background color, and create a mask
;** to clear them out of a byte.  Load up some registers which won't
;** change during the loop.
;*/

        mov     cl,PATTERN_WIDTH-1;destination will be 8 bits wide
        sub     cl,SrcWidth     ;CL = no. bits to fill w/bk color (-1)
        sbb     ch,ch           ;CH = 0FFh if no need to rotate mask, else 0
        not     ch              ;CH =   0  if ..., else 0FFH
        inc     cl              ;in case CL positive, we want to add 1
        and     cl,ch           ;CL = 0 if was negative, else unchanged
        mov     BitFillCnt,cl   ;save for updating DDC

        sub     ch,ch           ;ensure  zero-extended loop counters
        mov     dx,ScanIncr     ;source scan increment, loop invariant

        cmp     PlaneCnt,2      ; color pattern copy ?
        jc      cbp_mono        ; no -- mono copy...

;/*
;** Copy a color source pattern to the destination.                       ;
;*/

        mov     cl,InitScanCnt  ;# of scans to copy
        jcxz    cbp_copy_scan_c_done

        mov     bl,cl           ;keep # of scans to copy here
cbp_copy_scan_c0:
        push    di

        mov     cl,BitFillCnt   ;# bg filled bytes on right
        neg     cl
        add     cl,8            ;now # copied bytes on left
        jcxz    cbp_copy_scan_c_end_fill;no bytes to be copied...
@@:     mov     al,es:[di]      ;get source byte
        mov     [si],al         ;store byte
        inc     si              ;adjust destination pointer
        inc     di              ;adjust source pointer
        loop    @B

        mov     cl,BitFillCnt
        jcxz    cbp_copy_scan_c_end_fill
@@:     mov     [si],bh         ;background fill
        inc     si              ;adjust destination pointer
        loop    @B
cbp_copy_scan_c_end_fill:

        pop     di
        sub     di,dx           ;adjust source pointer to next scan
        sub     si,PATTERN_WIDTH*2;adjust destination pointer to next scan
        dec     bl              ;drop count of # scans to be copied
        jnz     cbp_copy_scan_c0
cbp_copy_scan_c_done:

        mov     cl,ScanFillCnt  ;how many scans to fill w/bk color?
        jcxz    cbp_fill_extra_scan_c_done; none -- we are done...
        mov     bl,cl           ;keep # scans to fill with bg color here
cbp_fill_extra_scan_c0:
        mov     cx,PATTERN_WIDTH;# bytes on this scan to fill
@@:     mov     [si],bh         ;store byte of background color
        inc     si              ;point to next destination scan byte
        loop    @B              ;for all bytes in the scan
        sub     si,(PATTERN_WIDTH*2);adjust destination pointer to next scan
        dec     bl              ;drop count of # scans to background fill
        jnz     cbp_fill_extra_scan_c0;for all background filled scans...
cbp_fill_extra_scan_c_done:

        jmp     short cbp_exit

;/*
;** Copy one plane of the source bitmap into the pattern attributes
;** structure.  The color masks (AH, BL, BH) need to be computed,
;** and the number of scans to copy initialized.  If after copying
;** the whole plane there weren't enough scans to fill the destination
;** buffer, pad out the rest with the background color.
;**
;** NOTE: CL = # pixels to fill in in a byte
;*/

cbp_mono:

        mov     ah,0FFh         ;assume no unused bits to mask off
        shl     ah,cl           ;make mask where used bits are 1's

        shr     BackClr,1       ;shift current color bit into carry
        sbb     bl,bl           ;BL = 0 if color = 0; BL = 0FFh if color = 1
        mov     bh,bl           ;make copy in case unused scans to fill
        not     ah              ;make mask where unused bits are 1's
        and     bl,ah           ;mask off used bits
        not     ah              ;restore mask of used bits

        mov     cl,InitScanCnt  ; # of scans to copy
        jcxz    @F
cbp_copy_scan_m:
        mov     al,es:[di]      ;get source byte
        and     al,ah           ;clear off unused bits
        or      al,bl           ;fill unused bits with background color
        mov     [si],al         ;store byte
        dec     si              ;adjust destination pointer
        sub     di,dx           ;adjust source pointer to next scan
        loop    cbp_copy_scan_m
@@:

        mov     cl,ScanFillCnt  ;how many scans to fill w/bk color?
        jcxz    @F              ; none -- we are done...
cbp_fill_extra_scan_m:
        mov     [si],bh         ;store scan of background color
        dec     si              ;point to next destination scan
        loop    cbp_fill_extra_scan_m
@@:

;/*
;** Get the DDC back and store the number of empty bits per scan and
;** the number of empty scans.  The next time the background color
;** changes, if the brush source was a color bitmap, these empty bits
;** will need to be filled with the new background color.
;*/

cbp_exit:

        pop     bx              ;restore DDC
        mov     al,BitFillCnt
        mov     [bx].ddc_pa.pa_cxFill,al
        mov     al,ScanFillCnt
        mov     [bx].ddc_pa.pa_cyFill,al

cEnd


        page
;/***************************************************************************
;*
;* FUNCTION NAME = fill_pattern_empty_bits
;*
;* DESCRIPTION   = Use the background color to fill in those color pattern   
;*                 bits not taken from a color source bitmap.  This          
;*                 subroutine will only be called when the following are     
;*                 true:  The pattern bits came from a color bitmap not large
;*                 enough to fill 8x8 pels.  The pattern background color    
;*                 changed so that the brush bits were invalidated.  The     
;*                 display driver fills in the empty space in the pattern    
;*                 with the current pattern background color.  When the      
;*                 background color changes, these bits need to be updated.  
;*                 The monochrome bits and transparency mask will be         
;*                 synthesized from the color bits after this subroutine is  
;*                 done.                                                     
;*                                                                           
;*                  Registers Preserved:                                                            
;*                        SI,DI,BP,DS                                                               
;*                  Registers Destroyed:                                                            
;*                        AX,BX,CX,DX,ES                                                            
;*                                                                           
;* INPUT         = DS:SI --> DDC
;* OUTPUT        = direction flag cleared 
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        missing_code    <fill_pattern_empty_bits -- need 4bpp code>

        assumes ds,Data
        assumes es,nothing

cProc   fill_pattern_empty_bits,<PUBLIC,NEAR,NODATA>,<si,di>

cBegin

        mov     cl,[si].ddc_pa.pa_cyFill;get # of scans to fill
        mov     ch,[si].ddc_pa.pa_cxFill;get # of pixels at scan ends to fill
        jcxz    fpeb_exit               ; no work to be done

        cld                             ;lodsb/stosb need this

        mov     bx,ds
        mov     es,bx
        assumes es,Data
        lea     di,[si].ddc_pa.pa_abColor;want ES:DI --> first scan to fill

        or      cl,cl                   ;if no scans to fill
        jz      fpeb_chk_cxfill         ;  check for bits on the right side

;/*
;** Fill in top cyFill scans with background color.
;*/

        mov     al,PATTERN_WIDTH        ;8bpp color pattern width
        mul     cl                      ;# bytes of empty scans to fill
        mov     cx,ax                   ;kept in count register
        mov     al,[si].ddc_pa.pa_ba.ba_ipcBack.ipc_bClr
        rep     stosb                   ;stuff background color

;/*
;** Fill in right sides of lower scans that do have pattern data.
;**
;**       ES:DI points to next color scan whose right side may be altered
;**       AL contains the background color to fill with
;*/

fpeb_chk_cxfill:

        mov     cl,[si].ddc_pa.pa_cxFill;get number of bits to fill
        sub     ch,ch
        jcxz    fpeb_exit               ;no right-side pixels to fill...

;/*
;** Fill in least significant cxFill bits with background color.
;*/

        mov     ax,cx                   ;# right-side pixels to fill
        neg     ax
        add     ax,PATTERN_WIDTH        ;# already filled pixels to ignore
        add     di,ax                   ;ES:DI is -> first pixel to fill

        mov     ah,PATTERN_HEIGHT       ;height of color pattern
        sub     ah,[si].ddc_pa.pa_cyFill;subtract off number of scans filled

        mov     al,[si].ddc_pa.pa_ba.ba_ipcBack.ipc_bClr
        mov     bx,cx                   ;cache inner loop count here

@@:     mov     cx,bx                   ;# pixels on right side to fill
        rep     stosb                   ;background fill rightside pixels
        sub     di,bx                   ;rewind pattern scan offset
        add     di,PATTERN_HEIGHT       ;point to next pattern scan
        dec     ah                      ;drop count of # scans to right fill
        jnz     @B                      ;do all of them...

fpeb_exit:
cEnd


sEnd
        End

;/*
** These are the rgb indicies, listed here simply for reference.
;*/

         IPC          RGB

0       0 0 0        0 0 0
1       0 0 1        0 0 1
2       0 0 2        0 0 2
3       0 0 3        0 0 3
4       0 1 0        0 1 0
5       0 1 1        0 1 1
6       0 1 2        0 1 2
7       0 1 3        0 1 3
8       0 2 0        0 2 0
9       0 2 1        0 2 1
10      0 2 2        0 2 2
11      0 2 3        0 2 3
12      0 3 0        0 3 0
13      0 3 1        0 3 1
14      0 3 2        0 3 2
15      0 3 3        0 3 3
16      0 4 0        0 4 0
17      0 4 1        0 4 1
18      0 4 2        0 4 2
19      0 4 3        0 4 3
20      0 5 0        0 5 0
21      0 5 1        0 5 1
22      0 5 2        0 5 2
23      0 5 3        0 5 3
24      0 6 0        0 6 0
25      0 6 1        0 6 1
26      0 6 2        0 6 2
27      0 6 3        0 6 3
28      0 7 0        0 7 0
29      0 7 1        0 7 1
30      0 7 2        0 7 2
31      0 7 3        0 7 3
32      1 0 0        1 0 0
33      1 0 1        1 0 1
34      1 0 2        1 0 2
35      1 0 3        1 0 3
36      1 1 0        1 1 0
37      1 1 1        1 1 1
38      1 1 2        1 1 2
39      1 1 3        1 1 3
40      1 2 0        1 2 0
41      1 2 1        1 2 1
42      1 2 2        1 2 2
43      1 2 3        1 2 3
44      1 3 0        1 3 0
45      1 3 1        1 3 1
46      1 3 2        1 3 2
47      1 3 3        1 3 3
48      1 4 0        1 4 0
49      1 4 1        1 4 1
50      1 4 2        1 4 2
51      1 4 3        1 4 3
52      1 5 0        1 5 0
53      1 5 1        1 5 1
54      1 5 2        1 5 2
55      1 5 3        1 5 3
56      1 6 0        1 6 0
57      1 6 1        1 6 1
58      1 6 2        1 6 2
59      1 6 3        1 6 3
60      1 7 0        1 7 0
61      1 7 1        1 7 1
62      1 7 2        1 7 2
63      1 7 3        1 7 3
64      2 0 0        2 0 0
65      2 0 1        2 0 1
66      2 0 2        2 0 2
67      2 0 3        2 0 3
68      2 1 0        2 1 0
69      2 1 1        2 1 1
70      2 1 2        2 1 2
71      2 1 3        2 1 3
72      2 2 0        2 2 0
73      2 2 1        2 2 1
74      2 2 2        2 2 2
75      2 2 3        2 2 3
76      2 3 0        2 3 0
77      2 3 1        2 3 1
78      2 3 2        2 3 2
79      2 3 3        2 3 3
80      2 4 0        2 4 0
81      2 4 1        2 4 1
82      2 4 2        2 4 2
83      2 4 3        2 4 3
84      2 5 0        2 5 0
85      2 5 1        2 5 1
86      2 5 2        2 5 2
87      2 5 3        2 5 3
88      2 6 0        2 6 0
89      2 6 1        2 6 1
90      2 6 2        2 6 2
91      2 6 3        2 6 3
92      2 7 0        2 7 0
93      2 7 1        2 7 1
94      2 7 2        2 7 2
95      2 7 3        2 7 3
96      3 0 0        3 0 0
97      3 0 1        3 0 1
98      3 0 2        3 0 2
99      3 0 3        3 0 3
100     3 1 0        3 1 0
101     3 1 1        3 1 1
102     3 1 2        3 1 2
103     3 1 3        3 1 3
104     3 2 0        3 2 0
105     3 2 1        3 2 1
106     3 2 2        3 2 2
107     3 2 3        3 2 3
108     3 3 0        3 3 0
109     3 3 1        3 3 1
110     3 3 2        3 3 2
111     3 3 3        3 3 3

;/*
;** Start of pure greys
;*/

112     3 4 0
113     3 4 1
114     3 4 2
115     3 4 3
116     3 5 0
117     3 5 1
118     3 5 2
119     3 5 3
120     3 6 0
121     3 6 1
122     3 6 2
123     3 6 3
124     3 7 0
125     3 7 1
126     3 7 2
127     3 7 3
128     4 0 0
129     4 0 1
130     4 0 2
131     4 0 3
132     4 1 0
133     4 1 1
134     4 1 2
135     4 1 3
136     4 2 0
137     4 2 1
138     4 2 2
139     4 2 3
140     4 3 0
141     4 3 1
142     4 3 2
143     4 3 3

;/*
;** End of pure greys
;*/

144     4 4 0        3 4 0
145     4 4 1        3 4 1
146     4 4 2        3 4 2
147     4 4 3        3 4 3
148     4 5 0        3 5 0
149     4 5 1        3 5 1
150     4 5 2        3 5 2
151     4 5 3        3 5 3
152     4 6 0        3 6 0
153     4 6 1        3 6 1
154     4 6 2        3 6 2
155     4 6 3        3 6 3
156     4 7 0        3 7 0
157     4 7 1        3 7 1
158     4 7 2        3 7 2
159     4 7 3        3 7 3
160     5 0 0        4 0 0
161     5 0 1        4 0 1
162     5 0 2        4 0 2
163     5 0 3        4 0 3
164     5 1 0        4 1 0
165     5 1 1        4 1 1
166     5 1 2        4 1 2
167     5 1 3        4 1 3
168     5 2 0        4 2 0
169     5 2 1        4 2 1
170     5 2 2        4 2 2
171     5 2 3        4 2 3
172     5 3 0        4 3 0
173     5 3 1        4 3 1
174     5 3 2        4 3 2
175     5 3 3        4 3 3
176     5 4 0        4 4 0
177     5 4 1        4 4 1
178     5 4 2        4 4 2
179     5 4 3        4 4 3
180     5 5 0        4 5 0
181     5 5 1        4 5 1
182     5 5 2        4 5 2
183     5 5 3        4 5 3
184     5 6 0        4 6 0
185     5 6 1        4 6 1
186     5 6 2        4 6 2
187     5 6 3        4 6 3
188     5 7 0        4 7 0
189     5 7 1        4 7 1
190     5 7 2        4 7 2
191     5 7 3        4 7 3
192     6 0 0        5 0 0
193     6 0 1        5 0 1
194     6 0 2        5 0 2
195     6 0 3        5 0 3
196     6 1 0        5 1 0
197     6 1 1        5 1 1
198     6 1 2        5 1 2
199     6 1 3        5 1 3
200     6 2 0        5 2 0
201     6 2 1        5 2 1
202     6 2 2        5 2 2
203     6 2 3        5 2 3
204     6 3 0        5 3 0
205     6 3 1        5 3 1
206     6 3 2        5 3 2
207     6 3 3        5 3 3
208     6 4 0        5 4 0
209     6 4 1        5 4 1
210     6 4 2        5 4 2
211     6 4 3        5 4 3
212     6 5 0        5 5 0
213     6 5 1        5 5 1
214     6 5 2        5 5 2
215     6 5 3        5 5 3
216     6 6 0        5 6 0
217     6 6 1        5 6 1
218     6 6 2        5 6 2
219     6 6 3        5 6 3
220     6 7 0        5 7 0
221     6 7 1        5 7 1
222     6 7 2        5 7 2
223     6 7 3        5 7 3
224     7 0 0        6 0 0
225     7 0 1        6 0 1
226     7 0 2        6 0 2
227     7 0 3        6 0 3
228     7 1 0        6 1 0
229     7 1 1        6 1 1
230     7 1 2        6 1 2
231     7 1 3        6 1 3
232     7 2 0        6 2 0
233     7 2 1        6 2 1
234     7 2 2        6 2 2
235     7 2 3        6 2 3
236     7 3 0        6 3 0
237     7 3 1        6 3 1
238     7 3 2        6 3 2
239     7 3 3        6 3 3
240     7 4 0        6 4 0
241     7 4 1        6 4 1
242     7 4 2        6 4 2
243     7 4 3        6 4 3
244     7 5 0        6 5 0
245     7 5 1        6 5 1
246     7 5 2        6 5 2
247     7 5 3        6 5 3
248     7 6 0        6 6 0
249     7 6 1        6 6 1
250     7 6 2        6 6 2
251     7 6 3        6 6 3
252     7 7 0        6 7 0
253     7 7 1        6 7 1
254     7 7 2        6 7 2
255     7 7 3        6 7 3
