;*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     55,132
        TITLE    Physical Colors
        SUBTITLE Header

;/*****************************************************************************
;*
;* SOURCE FILE NAME = PHYCOLOR.ASM
;*
;* DESCRIPTIVE NAME = Color related functions
;*
;*
;* VERSION      V2.0
;*
;* DATE         11/08/91
;*
;* DESCRIPTION  Color related functions
;*
;* FUNCTIONS    synthesize_xparent_mask
;*              synthesize_color_bits
;*              synthesize_mono_bits
;*              rotate_brush
;*              copy_bits_to_pattern
;*              fill_pattern_empty_bits
;*              alloc_brush
;*              free_brush
;*              copy_brush
;*              check_brush
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   05/10/91                     The special colors which correspond to
;*                                negative indices, was changed from a
;*                                constant of 15 per request of David Kerr
;*                                -Paul King
;*   03/17/93              63989  Transparency mask set incorrectly for
;*                                color bitmap patterns.
;*   06/20/94              85689  Upper portion of ECX not cleared causing
;*                                loop to trap.
;*
;*****************************************************************************/


        .386P
        .MODEL FLAT,SYSCALL

;/*
;** Included files
;*/

INCL_GPIPRIMITIVES EQU 1
INCL_NOBASEAPI     EQU 1
INCL_NOCOMMON      EQU 1
INCL_SAADEFS       EQU 1
INCL_WINSYS        EQU 1
OS2_NOPMAPI        EQU 1
        INCLUDE PMGRE.INC
        INCLUDE DISPLAY.INC
DINCL_BITMAP       EQU 1
DINCL_CLR_TBL      EQU 1
DINCL_ENABLE       EQU 1
        INCLUDE DRIVER.INC
        INCLUDE PROTOS.INC
DIN_PHYCOLOR       EQU 1
        INCLUDE EXTERN.INC

;/*
;** Equates
;*/

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



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


;/*
;** The following equates define the various brush patterns.
;*/


if SCAN_CNT eq 600
USE_HI_RES_PATTERN equ 1
endif

if SCAN_CNT eq 768
USE_HI_RES_PATTERN equ 1
endif

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

HV_HATCH_BR_0  EQU H_HATCH_BR_0 or V_HATCH_BR_0  ; Cross hatch
HV_HATCH_BR_1  EQU H_HATCH_BR_1 or V_HATCH_BR_1
HV_HATCH_BR_2  EQU H_HATCH_BR_2 or V_HATCH_BR_2
HV_HATCH_BR_3  EQU H_HATCH_BR_3 or V_HATCH_BR_3
HV_HATCH_BR_4  EQU H_HATCH_BR_4 or V_HATCH_BR_4
HV_HATCH_BR_5  EQU H_HATCH_BR_5 or V_HATCH_BR_5
HV_HATCH_BR_6  EQU H_HATCH_BR_6 or V_HATCH_BR_6
HV_HATCH_BR_7  EQU H_HATCH_BR_7 or V_HATCH_BR_7

ifndef USE_HI_RES_PATTERN

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

else

DB_HATCH_BR1_0  equ     0FFh and 00010001b      ;\ diagonal hatched brush 1
DB_HATCH_BR1_1  equ     0FFh and 10001000b      ;Lo Res
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

endif

DB_HATCH_BR2_0  equ     0FFh and 10000001b      ;\ diagonal hatched brush 2
DB_HATCH_BR2_1  equ     0FFh and 01100000b      ;Hi Res
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

ifndef USE_HI_RES_PATTERN

DF_HATCH_BR1_0  equ     0FFh and 10000000b      ;/ diagonal hatched brush 1
DF_HATCH_BR1_1  equ     0FFh and 00000001b      ;Lo Res
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

else

DF_HATCH_BR1_0  equ     0FFh and 10001000b      ;/ diagonal hatched brush 1
DF_HATCH_BR1_1  equ     0FFh and 00010001b      ;Hi Res
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

endif

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


DBF_HATCH_BR_0 EQU DF_HATCH_BR1_1 or DB_HATCH_BR1_0 ; Diagonal cross hatch
DBF_HATCH_BR_1 EQU DF_HATCH_BR1_2 or DB_HATCH_BR1_1
DBF_HATCH_BR_2 EQU DF_HATCH_BR1_3 or DB_HATCH_BR1_2
DBF_HATCH_BR_3 EQU DF_HATCH_BR1_4 or DB_HATCH_BR1_3
DBF_HATCH_BR_4 EQU DF_HATCH_BR1_5 or DB_HATCH_BR1_4
DBF_HATCH_BR_5 EQU DF_HATCH_BR1_6 or DB_HATCH_BR1_5
DBF_HATCH_BR_6 EQU DF_HATCH_BR1_7 or DB_HATCH_BR1_6
DBF_HATCH_BR_7 EQU DF_HATCH_BR1_0 or DB_HATCH_BR1_7


;/*
;** Data
;*/

        .DATA

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

DEFINED_ELSEWHERE EQU 1

        public  PalColor
PalColor        label   byte

;/*
;** ----------- data for the hardware 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

;/*
;**            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_BYTE_&index = index + (MONO_BIT SHL 8)
        else
PHY_COLOR_BYTE_&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,0,0,0
        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
;        MakePal 143,255,255,255
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_BYTE_0   = PHY_COLOR_BYTE_0   + (ONES_OR_ZEROS SHL 8)
PHY_COLOR_BYTE_255 = PHY_COLOR_BYTE_255 + (ONES_OR_ZEROS SHL 8)


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


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



;/*
;** 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_BYTE_0        ; black
         db      0FFh  AND  PHY_COLOR_BYTE_2        ; dark blue
         db      0FFh  AND  PHY_COLOR_BYTE_16       ; dark green
         db      0FFh  AND  PHY_COLOR_BYTE_18       ; dark turquoise
         db      0FFh  AND  PHY_COLOR_BYTE_160      ; dark red
         db      0FFh  AND  PHY_COLOR_BYTE_162      ; purple
         db      0FFh  AND  PHY_COLOR_BYTE_144      ; mustard
         db      0FFh  AND  PHY_COLOR_BYTE_137      ; dark gray

         db      0FFh  AND  PHY_COLOR_BYTE_128      ; gray
         db      0FFh  AND  PHY_COLOR_BYTE_3        ; blue
         db      0FFh  AND  PHY_COLOR_BYTE_28       ; green
         db      0FFh  AND  PHY_COLOR_BYTE_31       ; turquoise (cyan)
         db      0FFh  AND  PHY_COLOR_BYTE_224      ; red
         db      0FFh  AND  PHY_COLOR_BYTE_227      ; pink (magenta)
         db      0FFh  AND  PHY_COLOR_BYTE_252      ; yellow
         db      0FFh  AND  PHY_COLOR_BYTE_255      ; white

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

aipcLookup      label   word
IPCFlags        label   word
        public  aipcLookup

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

;/*
;** These are fast lookup dither patterns for the above default colors.
;*/

PUBLIC adDitherPatterns
adDitherPatterns LABEL DWORD

;/*
;**             IIRRGGBB
;*/


        DWORD  0FFFFFFFFh                        ; white
        DWORD  0FF0000FFh                        ; blue
        DWORD  0FFFF0000h                        ; red
        DWORD  0FFFF00FFh                        ; pink (magenta)
        DWORD  0FF00FF00h                        ; green
        DWORD  0FF00FFFFh                        ; turquoise (cyan)
        DWORD  0FFFFFF00h                        ; yellow
        DWORD  000000000h                        ; black
        DWORD  000FFFFFFh                        ; dark gray
        DWORD  0000000FFh                        ; dark blue
        DWORD  000FF0000h                        ; dark red
        DWORD  000FF00FFh                        ; purple
        DWORD  00000FF00h                        ; dark green
        DWORD  00000FFFFh                        ; dark turquoise
        DWORD  000FFFF00h                        ; mustard
        DWORD  0FF000000h                        ; gray



;/*
;** 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 could change based on resoultion.
;*/

        ALIGN  4

abBasePatterns LABEL BYTE                        ; Used in MKVALID.ASM
        BYTE    S_HATCH_BR1_0, S_HATCH_BR1_1, S_HATCH_BR1_2, S_HATCH_BR1_3
        BYTE    S_HATCH_BR1_4, S_HATCH_BR1_5, S_HATCH_BR1_6, S_HATCH_BR1_7

        BYTE    S_HATCH_BR2_0, S_HATCH_BR2_1, S_HATCH_BR2_2, S_HATCH_BR2_3
        BYTE    S_HATCH_BR2_4, S_HATCH_BR2_5, S_HATCH_BR2_6, S_HATCH_BR2_7

        BYTE    S_HATCH_BR3_0, S_HATCH_BR3_1, S_HATCH_BR3_2, S_HATCH_BR3_3
        BYTE    S_HATCH_BR3_4, S_HATCH_BR3_5, S_HATCH_BR3_6, S_HATCH_BR3_7

        BYTE    S_HATCH_BR4_0, S_HATCH_BR4_1, S_HATCH_BR4_2, S_HATCH_BR4_3
        BYTE    S_HATCH_BR4_4, S_HATCH_BR4_5, S_HATCH_BR4_6, S_HATCH_BR4_7

        BYTE    S_HATCH_BR5_0, S_HATCH_BR5_1, S_HATCH_BR5_2, S_HATCH_BR5_3
        BYTE    S_HATCH_BR5_4, S_HATCH_BR5_5, S_HATCH_BR5_6, S_HATCH_BR5_7

        BYTE    S_HATCH_BR6_0, S_HATCH_BR6_1, S_HATCH_BR6_2, S_HATCH_BR6_3
        BYTE    S_HATCH_BR6_4, S_HATCH_BR6_5, S_HATCH_BR6_6, S_HATCH_BR6_7
        BYTE    S_HATCH_BR7_0, S_HATCH_BR7_1, S_HATCH_BR7_2, S_HATCH_BR7_3
        BYTE    S_HATCH_BR7_4, S_HATCH_BR7_5, S_HATCH_BR7_6, S_HATCH_BR7_7
        BYTE    S_HATCH_BR8_0, S_HATCH_BR8_1, S_HATCH_BR8_2, S_HATCH_BR8_3
        BYTE    S_HATCH_BR8_4, S_HATCH_BR8_5, S_HATCH_BR8_6, S_HATCH_BR8_7
        BYTE    V_HATCH_BR_0,  V_HATCH_BR_1,  V_HATCH_BR_2,  V_HATCH_BR_3
        BYTE    V_HATCH_BR_4,  V_HATCH_BR_5,  V_HATCH_BR_6,  V_HATCH_BR_7
        BYTE    H_HATCH_BR_0,  H_HATCH_BR_1,  H_HATCH_BR_2,  H_HATCH_BR_3
        BYTE    H_HATCH_BR_4,  H_HATCH_BR_5,  H_HATCH_BR_6,  H_HATCH_BR_7
        BYTE    DF_HATCH_BR1_0,DF_HATCH_BR1_1,DF_HATCH_BR1_2,DF_HATCH_BR1_3
        BYTE    DF_HATCH_BR1_4,DF_HATCH_BR1_5,DF_HATCH_BR1_6,DF_HATCH_BR1_7
        BYTE    DF_HATCH_BR2_0,DF_HATCH_BR2_1,DF_HATCH_BR2_2,DF_HATCH_BR2_3
        BYTE    DF_HATCH_BR2_4,DF_HATCH_BR2_5,DF_HATCH_BR2_6,DF_HATCH_BR2_7
        BYTE    DB_HATCH_BR1_0,DB_HATCH_BR1_1,DB_HATCH_BR1_2,DB_HATCH_BR1_3
        BYTE    DB_HATCH_BR1_4,DB_HATCH_BR1_5,DB_HATCH_BR1_6,DB_HATCH_BR1_7
        BYTE    DB_HATCH_BR2_0,DB_HATCH_BR2_1,DB_HATCH_BR2_2,DB_HATCH_BR2_3
        BYTE    DB_HATCH_BR2_4,DB_HATCH_BR2_5,DB_HATCH_BR2_6,DB_HATCH_BR2_7
        BYTE    NS_HATCH_BR_0, NS_HATCH_BR_1, NS_HATCH_BR_2, NS_HATCH_BR_3
        BYTE    NS_HATCH_BR_4, NS_HATCH_BR_5, NS_HATCH_BR_6, NS_HATCH_BR_7
        BYTE    0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
        BYTE    A_HATCH_BR_0,  A_HATCH_BR_1,  A_HATCH_BR_2,  A_HATCH_BR_3
        BYTE    A_HATCH_BR_4,  A_HATCH_BR_5,  A_HATCH_BR_6,  A_HATCH_BR_7
        BYTE    HV_HATCH_BR_0, HV_HATCH_BR_1, HV_HATCH_BR_2, HV_HATCH_BR_3
        BYTE    HV_HATCH_BR_4, HV_HATCH_BR_5, HV_HATCH_BR_6, HV_HATCH_BR_7
        BYTE    DBF_HATCH_BR_0,DBF_HATCH_BR_1,DBF_HATCH_BR_2,DBF_HATCH_BR_3
        BYTE    DBF_HATCH_BR_4,DBF_HATCH_BR_5,DBF_HATCH_BR_6,DBF_HATCH_BR_7




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

        page

        .CODE

;/*
;** Public functions
;*/


        SUBTITLE synthesize_xparent_mask
        PAGE +


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

synthesize_xparent_mask PROC SYSCALL PUBLIC uses EBX ESI EDI


;/*
;** 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     al,BYTE ptr [ESI].DDC.ddc_pa.pa_ba.ba_ipcBack
        Mov     ah,al                   ; bg color in upper,lower bytes
        mov     bx,ax
        shl     ebx,16                            ;bg color in all 4 bytes of ebx
        mov     bx,ax


        mov     edi,esi                           ;point edi to DDC also
        Mov     ecx,(SIZE_PATTERN*8)/4   ; # dwords to fetch
        Mov     Dl,01010101b            ; tells when to store a mask byte

        mov     esi,[ESI].DDC.ddc_pa.pa_abColor  ;get ptr to pixels

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


sxm_8bpp_lp:

        mov     eax,[ESI]                              ; fetch 4 color pixels
;V2.1EKF00 And     eax,ebx              ; 0s where bg color
        XOR     eax,ebx                 ; V2.1EKF00 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,1                    ; right pixel == bg color ?
        Cmc                             ; 'C'=1 if not
        Rcl     Dh,1                    ; add into building mask byte
;V2.1EKF00 shl     eax,16
        shr     eax,16                  ; V2.1EKF00 do next two bytes
        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     [EDI].DDC.ddc_pa.pa_abMask,Dh  ; yes, so must store it to mask
        inc     edi
@@:
        add     esi,4
        Loop    sxm_8bpp_lp             ; for all words of color brush...


        RET

synthesize_xparent_mask ENDP

        SUBTITLE synthesize_color_bits
        PAGE +


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


synthesize_color_bits PROC SYSCALL PUBLIC uses ESI EDI BX
        Mov     Bh,byte ptr [ESI].DDC.ddc_pa.pa_ba.ba_ipc; fg color
        Mov     Bl,byte ptr [ESI].DDC.ddc_pa.pa_ba.ba_ipcBack; bg color

;/*
;** check high byte of ipc for black or white
;*/

        mov     ax,word ptr [ESI].DDC.ddc_pa.pa_ba.ba_ipc
        and     ax,word ptr [ESI].DDC.ddc_pa.pa_ba.ba_ipcBack
        TEST    AX,(ONES_OR_ZEROS SHL 8)
        JZ      SCB_Process_bits
        OR      [ESI].DDC.ddc_pa.pa_fb,PA_GRAY

SCB_Process_bits:

        mov     EDI,[ESI].DDC.ddc_pa.pa_abColor  ; EDI --> Destination
        Mov     ecx,(SIZE_PATTERN * SIZE_PATTERN) ; # color brush bytes to store at 8 bpp

;/*
;** 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...
        mov     al,[ESI].DDC.ddc_pa.pa_abMask     ; Ds:Si is -> transparency mask
        Mov     Ah,Al                   ; save here
        inc     esi
@@:

        Mov     Al,Bl                   ; assume bg color
        Shl     Ah,1
        Jnc     @F                      ; it was...
        Mov     Al,Bh                   ; else will store fg color
@@:     mov     [edi],al                ; store new byte to color brush
        inc     edi

        Loop    scb_8bpp_lp             ; for all mask pixels...

        ret

synthesize_color_bits ENDP


        SUBTITLE synthesize_mono_bits
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = synthesize_mono_bits
;*
;* DESCRIPTION   = The mono bits will be synthsized from the transparency
;*                 mask of the given brush.
;*
;*                 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.
;*
;*                 Registers Preserved:
;*                       ESI,EDI,BX
;*                 Registers Destroyed:
;*                       AX,CX,FLAGS
;*
;* INPUT         = ESI --> DDC to use
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

synthesize_mono_bits PROC SYSCALL PUBLIC USES ESI EDI BX

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


        Mov     Bl,byte ptr [ESI].DDC.ddc_pa.pa_ba.ba_ipc
        Shr     Bl,1
        Sbb     Bl,Bl                   ; replicated fg colors

        Mov     Bh,byte ptr [ESI].DDC.ddc_pa.pa_ba.ba_ipcBack
        Shr     Bh,1
        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     Cx,SIZE_PATTERN         ; # bytes in mono brush
        mov     edi,esi

smb_lp: mov     al,[ESI].DDC.ddc_pa.pa_abMask       ; 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
        mov     [EDI].DDC.ddc_pa.pa_abMono,al       ; store to mono brush
        inc     esi
        inc     edi
        Loop    smb_lp                  ; for all mono brush bytes...

        RET

synthesize_mono_bits ENDP

;/***************************************************************************
;*
;* 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         = ESI --> DDC to use
;*                 CL   =  Amount to rotate right
;*
;* OUTPUT        = ESI --> DDC to use
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


rotate_brush PROC SYSCALL PUBLIC uses ESI EDI EDX BX
        Local  PixelBucket[8]:BYTE,     ; place to hold rotating pixels
               RightPixels:WORD         ; # pixels to move on right end

        Sub     Ch,Ch                   ; zext the rotation count
        movzx   edx,dx
        movzx   ecx,cx

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

        Lea     eDi,[eSi].DDC.ddc_pa.pa_abMono; Ds:Di is -> mono brush
        Mov     Bl,16                   ; rotate both brush and mask in loop
        .errnz  SIZE_PATTERN - 8

rb_mono_mask:
        Ror     Byte Ptr [eDi],Cl        ; rotate 8 pixels
        Inc     eDi                      ; -> 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.
;*/


        mov     ESI,[esi].DDC.ddc_pa.pa_abColor    ; Ds:Si -> color brush pixels
        Mov     Bx,SIZE_PATTERN         ; Bx is # of rows of pattern to process

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

        Lea     eDi,PixelBucket          ; Es:Di is -> holding area

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

        Mov     eDi,eSi                   ; Ds:Si -> right pixels
        Sub     eDi,eDx                   ; Es:Di -> to start of brush row

        Mov     Cx,RightPixels
    Rep Movsb                           ; move right pixels down

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

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

        RET

rotate_brush ENDP

        SUBTITLE copy_bits_to_pattern
        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)
;*                 EBX --> DDC
;*                 ECX   =  Number of bytes per scan of source bitmap
;*                 EDX   =  Height of bitmap
;*                 ESI --> Destination of bits (first BYTE of pattern bits buffer)
;*                 EDI --> Source bits (first BYTE of bits buffer)
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


copy_bits_to_pattern PROC SYSCALL PUBLIC uses EDI ESI

        LOCAL   SrcWidth   :BYTE                 ; Width in pels of source
        LOCAL   SrcHeight  :DWORD                ; Height in scans of source
        LOCAL   ScanIncr   :DWORD                ; Increment to next scan of source
        LOCAL   PlaneCnt   :BYTE                 ; Number of color planes in source
        LOCAL   InitScanCnt:BYTE                 ; No. scans to copy per plane of src
        LOCAL   BitFillCnt :BYTE                 ; No. empty bits per scan in pattern
        LOCAL   ScanFillCnt:BYTE                 ; Number of empty scans in pattern
        LOCAL   BackClr    :BYTE                 ; Our version of the background color


        PUSH    EBX                     ; save DDC

        xchg    eax,ecx
        MOV     PlaneCnt,cl                      ; Save number color planes for loop counter
        cmp     cl,0ffh                          ;device dependent ?
        jne     @f
        MOV     PlaneCnt,8
@@:
        MOV     SrcWidth,ch                      ; Save input to make space for calculations
        MOV     ScanIncr,EAX                     ; Plane increment always bytes-per-scan
        MOV     SrcHeight,EDX                    ; Need this a few times

        dec     edx              ;# scans offset to lower left scan of src
        mul     edx              ;get offset to lower left scan
        add     edi,eax           ;ES:DI is -> lower left scan of src

        add     esi,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     esi,((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,byte ptr [ebx].DDC.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     eax,PATTERN_HEIGHT  ;InitScanCnt = min(8, SrcHeight)
        CMP     EAX,SrcHeight
        JB      @F
        MOV     EAX,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     edx,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    edi

        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,[edi]      ;get source byte
        mov     [esi],al         ;store byte
        inc     esi              ;adjust destination pointer
        inc     edi              ;adjust source pointer
        loop    @B

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

        pop     edi
        sub     edi,edx           ;adjust source pointer to next scan
        sub     esi,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     [esi],bh         ;store byte of background color
        inc     esi              ;point to next destination scan byte
        loop    @B              ;for all bytes in the scan
        sub     esi,(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,[edi]      ;get source byte
        and     al,ah           ;clear off unused bits
        or      al,bl           ;fill unused bits with background color
        mov     [esi],al         ;store byte
        dec     esi              ;adjust destination pointer
        sub     edi,edx           ;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     [esi],bh         ;store scan of background color
        dec     esi              ;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     EBX             ; Restore DDC
        MOV     AL,BitFillCnt
        MOV     [EBX].DDC.ddc_pa.pa_cxFill,AL
        MOV     AL,ScanFillCnt
        MOV     [EBX].DDC.ddc_pa.pa_cyFill,AL

        RET

copy_bits_to_pattern ENDP

        SUBTITLE fill_pattern_empty_bits
        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         = ESI --> DDC
;* OUTPUT        = direction flag cleared
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

fill_pattern_empty_bits PROC SYSCALL PUBLIC USES EDI ESI EBX

        mov     cl,[esi].DDC.ddc_pa.pa_cyFill;get # of scans to fill
        mov     ch,[esi].DDC.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     edi,[esi].DDC.ddc_pa.pa_abColor;want EDI --> 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
        movzx   ecx,ax                   ;kept in count register        ;          
        mov     al,byte ptr [esi].DDC.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.
;**
;**       EDI points to next color scan whose right side may be altered
;**       AL contains the background color to fill with
;*/


fpeb_chk_cxfill:

        mov     cl,[esi].DDC.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
        movzx   eax,ax
        add     edi,eax                   ;EDI is -> first pixel to fill

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

        mov     al,byte ptr [esi].DDC.ddc_pa.pa_ba.ba_ipcBack.ipc_bClr
        mov     bx,cx                   ;cache inner loop count here
        movzx   ebx,bx

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

fpeb_exit:
        RET

fill_pattern_empty_bits ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = alloc_brush
;*
;* DESCRIPTION   = Allocate storage for a brush
;*
;* INPUT         = EAX = size of block to allocate
;* OUTPUT        = EAX = pointer to brush
;*
;* RETURN-NORMAL = EAX <> 0
;* RETURN-ERROR  = EAX = 0
;*
;**************************************************************************/

alloc_brush PROC SYSCALL USES EBX
        LOCAL   pBrush:DWORD

        mov     eax,SIZE_PATTERN*BITS_PEL
                ;entry eax = size of block to allocate
        lea     ebx,pBrush
        INVOKE  private_alloc
        mov     eax,pBrush
        or      ecx,ecx
        jz      alloc_ok
        mov     eax,PMERR_INSUFFICIENT_MEMORY
        save_error_code
        xor eax,eax
alloc_ok:
        ret
alloc_brush endp

;/***************************************************************************
;*
;* FUNCTION NAME = free_brush
;*
;* DESCRIPTION   = Frees allocated storage for a brush
;*
;* INPUT         = EAX - pointer to the storage
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

free_brush PROC SYSCALL
        mov     ecx,eax
        INVOKE  private_free
        ret
free_brush endp


;/***************************************************************************
;*
;* FUNCTION NAME = copy_brush
;*
;* DESCRIPTION   = copies a brush
;*
;* INPUT         = DS:SI - brush to copy from
;*                 ES:DI - brush to copy to
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

copy_brush PROC SYSCALL USES ECX ESI EDI
        mov     ecx,SIZE_PATTERN*BITS_PEL
        rep     movsb
        ret
copy_brush endp

        END

