;*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    Make Valid
        SUBTITLE Header
;/*****************************************************************************
;*
;* SOURCE FILE NAME = MKVALID.ASM
;*
;* DESCRIPTIVE NAME = Color and brush validation routines.
;*
;*
;* VERSION      V2.0
;*
;* DATE         11/12/91
;*
;* DESCRIPTION  Color and brush validation routines.
;*
;* FUNCTIONS    MakePassedColorsValid
;*              MakeColorsValid
;*              MakeBrushValid
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   11/12/91                     KEZ  Original
;*   06/18/93              69006  Don't dither patterns on DCs with palette
;*                                loaded or RGBs or Indexes that have exact
;*                                matches in the HW Palette.
;*   05/02/94              81355  Always realize new brush when the color
;*                                changes.
;*   06/22/94              82281  Add special case (hack) for applications
;*                                passing RGB values while in LCT mode.
;*
;*****************************************************************************/


        .386P
        .MODEL FLAT,SYSCALL

        OPTION  OLDSTRUCTS

;/*
;** Included files
;*/

IFDEF PALMGR2
INCL_GPILOGCOLORTABLE   equ                      1
INCL_GRE_PALETTE        equ                      1
ENDIF
INCL_DDIFONTSTRUCS      EQU                      1
INCL_DDIMISC            EQU                      1
INCL_GPIPRIMITIVES      EQU                      1
INCL_NOBASEAPI          EQU                      1
INCL_NOCOMMON           EQU                      1
INCL_SAADEFS            EQU                      1
OS2_NOPMAPI             EQU                      1
        INCLUDE PMGRE.INC

DINCL_BITMAP       EQU                           1
DINCL_CLR_TBL      EQU                           1
DINCL_ENABLE       EQU                           1

        include fontmap.inc

        INCLUDE DRIVER.INC
        INCLUDE EXTERN.INC
        INCLUDE PROTOS.INC
        INCLUDE ASSERT.MAC

ifdef PALMGR2
        INCLUDE PALETTE.INC
ENDIF

;/*
;** Local structures
;*/

FONT_ENTRIES STRUCT
   fe_dBits DWORD ?     ; Offset entry index for prop fonts
   fe_width WORD  ?     ; Width entry index for prop fonts
FONT_ENTRIES ENDS

;/*
;** ABC_FONT_ENTRIES is the format of the individual character records in an
;** ABC spaced font.
;*/


ABC_FONT_ENTRIES STRUCT
   abc_fe_dBits DWORD ?
   abc_a_space  WORD  ?
   abc_b_space  WORD  ?
   abc_c_space  WORD  ?
ABC_FONT_ENTRIES ENDS


        .ERRNZ  (size CSP_INFO) - (size BITBLTATTRS)
        .ERRNZ  CSP_INFO.csp_lBackColor          - BITBLTATTRS.bba_lBackColor
        .ERRNZ  CSP_INFO.csp_lColor              - BITBLTATTRS.bba_lColor

;/*
;** Public functions
;*/

        .CODE

        SUBTITLE MakePassedColorsValid
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = MakePassedColorsValid
;*
;* DESCRIPTION   = MakePassedColorsValid realizes the correct IPC for the
;*                 passed colors The attribute will be marked as needing to be
;*                 re-realized upon exit.
;*
;*                 Registers Preserved:
;*                       BX,CX,SI,DI,DS
;*                 Registers Destroyed:
;*                       AX,DX,ES,FLAGS
;*
;* INPUT         = ESI --> DDC
;*                 EBX --> Basic Attribute structure
;*                 EDI --> Passed attributes (CSP_INFO or BITBLTATTRS)
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = 'S' clear       ( = the sign bit in EAX)
;*
;* RETURN-ERROR  = 'S' set         ( = the sign bit in EAX)
;*                 EAX  = INVALID_IPC
;*                 Error logged
;*
;**************************************************************************/


MakePassedColorsValid PROC SYSCALL PUBLIC

;/*
;** Make sure that the attributes header is correct
;*/


        CMP     WORD ptr [EDI].CSP_INFO.csp_cSize+2,0
        JNE     MPCV_Attrs_struc_bad
        CMP     WORD ptr [EDI].CSP_INFO.csp_cSize,sizeof CSP_INFO
        JE      Attrs_struc_good

MPCV_Attrs_struc_bad:
        MOV     EAX,PMERR_INV_LENGTH_OR_COUNT
        save_error_code
        MOV     EAX,INVALID_IPC_DWORD
        JMP     MPCV_Exit

;/*
;** Since we already have the logic to handle mapping the colors from the DDC,
;** and since we need to have the background color somewhere for correct
;** mapping, we'll stuff the passed colors into the DDC.  We will mark both as
;** invalid, and clear the default bits since you can never have a default
;** color passed in.
;*/


Attrs_struc_good:
        PUSH    [EBX].BASIC_ATTRS.ba_clr
        PUSH    [EBX].BASIC_ATTRS.ba_clrBack
        PUSH    DWORD ptr [EBX].BASIC_ATTRS.ba_bReserved
        .ERRNZ  BASIC_ATTRS.ba_fb-BASIC_ATTRS.ba_bReserved-1

        MOV     EAX,[EDI].CSP_INFO.csp_lColor
        MOV     [EBX].BASIC_ATTRS.ba_clr,EAX
        MOV     EAX,[EDI].CSP_INFO.csp_lBackColor
        MOV     [EBX].BASIC_ATTRS.ba_clrBack,EAX
        MOV     [EBX].BASIC_ATTRS.ba_fb,BA_CLR_INVALID or BA_CLR_BACK_INV

        INVOKE  MakeColorsValid                                  ; He does all the work for us

        POP     DWORD ptr [EBX].BASIC_ATTRS.ba_bReserved
        .ERRNZ  BASIC_ATTRS.ba_fb-BASIC_ATTRS.ba_bReserved-1
        POP     [EBX].BASIC_ATTRS.ba_clrBack
        POP     [EBX].BASIC_ATTRS.ba_clr
        OR      [EBX].BASIC_ATTRS.ba_fb,BA_CLR_INVALID or BA_CLR_BACK_INV or BA_REREALIZE

MPCV_Exit:
        OR      EAX,EAX                         ; Set/clear 'S'
        RET

MakePassedColorsValid ENDP

        SUBTITLE MakeColorsValid
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = MakeColorsValid
;*
;* DESCRIPTION   = MakeColorsValid makes sure the internal device dependent
;*                 color representations in a Basic Attributes structure are
;*                 up to date.
;*
;*                 Registers Preserved:
;*                       BX,CX,SI,DI,DS
;*                 Registers Destroyed:
;*                       AX,DX,ES,FLAGS
;*
;* INPUT         = ESI --> DDC
;*                 EBX --> Basic Attribute structure
;*
;* OUTPUT        = EAX = IPC
;*
;* RETURN-NORMAL = 'S' clear ( = the sign bit in EAX)
;*
;* RETURN-ERROR  = EAX = INVALID_IPC
;*                 'S' set ( = the sign bit in EAX)
;*                 Error logged
;**************************************************************************/


MakeColorsValid PROC SYSCALL PUBLIC

        DebugMsg <MakeColorsValid KEZ, mkvalid.asm>
IFDEF FIREWALLS

        ddc?    ESI
        MOV     CL,[EBX].BASIC_ATTRS.ba_fb
        TEST    CL,BA_CLR_INVALID or BA_CLR_BACK_INV
        JNZ     @F
        rip     text,<ColorsAlreadyValid>

@@:

ENDIF ; FIREWALLS

        MOV     CL,[EBX].BASIC_ATTRS.ba_fb
        OR      CL,CL
        JNS     MCV_Clr_okay
        .ERRNZ  BA_CLR_INVALID - 80h
        MOV     EAX,[EBX].BASIC_ATTRS.ba_clr
        AND     CL,BA_CLR_DEF
        INVOKE  ColorConvert
        ;JS      MCV_Exit
        JS      @f
        MOV     [EBX].BASIC_ATTRS.ba_ipc,AX
        MOV     CL,[EBX].BASIC_ATTRS.ba_fb
        jmp     MCV_Clr_okay
@@:
        MOV     EAX,PMERR_INCOMPAT_COLOR_FORMAT
        save_error_code
        xor     eax,eax

MCV_Clr_okay:
        TEST    CL,BA_CLR_BACK_INV
        JZ      MCV_ClrBack_okay
        MOV     EAX,[EBX].BASIC_ATTRS.ba_clrBack
        AND     CL,BA_CLR_BACK_DEF
        INVOKE  ColorConvert
        ;JS      MCV_Exit
        JS      @f
        MOV     WORD ptr [EBX].BASIC_ATTRS.ba_ipcBack,AX
        jmp     MCV_ClrBack_okay
@@:
        MOV     EAX,PMERR_INCOMPAT_COLOR_FORMAT
        save_error_code
        xor     eax,eax

MCV_ClrBack_okay:
        ; not together
        AND     [EBX].BASIC_ATTRS.ba_fb,not (BA_CLR_BACK_INV or BA_CLR_INVALID or BA_REREALIZE)
MCV_Exit:
        OR      EAX,EAX
        RET

MakeColorsValid ENDP

        SUBTITLE MakeBrushValid
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = MakeBrushValid
;*
;* DESCRIPTION   = MakeBrushValid will process the given DDC's pattern
;*                 attributes and attempt to make them valid.
;*
;* INPUT         = ESI --> DDC
;*                 CL   =  FF if to override color with passed colors
;*                 CL   =  00 if to use colors in pattern attributes
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = S' clear ( = the sign bit in EAX)
;* RETURN-ERROR  = 'S' set ( = the sign bit in EAX)
;*                 Error logged
;**************************************************************************/


;/*
;** Flag values which will be used by this routine.  DH_ is kept in DH,
;** DL_ is kept in DL
;*/


DH_USER_FONT    EQU 80h ; Work copy of CA_USER_FONT
DH_CHANGED      EQU 08h ; Work copy of CA_CHANGED

DL_PASSED_CLRS  EQU 80h ; Colors were passed to this routine
DL_CLRS_CHANGED EQU 40h ; Colors changed
DL_ROTATED      EQU 20h ; We rotated the brush bits
DL_COLOR_TRUTH  EQU 10h ; Local copy of PA_COLOR_TRUTH
DL_BITMAP_SRC   EQU 08h ; Local copy of PA_BITMAP_SRC
DL_DITHER_OK    EQU 04h ; Dithering is ok

MakeBrushValid PROC SYSCALL PUBLIC uses EBX EDI ESI,
                pColors:DWORD

        LOCAL   clrFore:DWORD
        LOCAL   rclTemp:RECTL

        DebugMsg <MakeBrushValid KEZ, MKVALID.ASM>
IFDEF FIREWALLS

        ddc?    ESI
        OR      CL,CL                           ; Make sure param in CL valid
        JZ      @F
        CMP     CL,0FFh
        JZ      @F
        rip     text,<Invalid flags passed to MakeBrushValid>

@@:
        TEST    [ESI].DDC.ddc_pa.pa_fs,CA_VECTOR
        JZ      @F                              ; Vector fonts should have
                                                ; been caught by
                                                ; SetPatternFont

        rip     text,<MakeBrushValid - Symbol Set marked Vector>

@@:
        MOV     AL,[ESI].DDC.ddc_pa.pa_fb       ; Can only show color truth
        TEST    AL,PA_COLOR_TRUTH               ; if pattern came from a
                                                ; bitmap

        JZ      @F
        TEST    AL,PA_BITMAP_SRC
        JNZ     @F
        rip     text,<MakeBrushValid - Pattern marked color but it is not a bitmap>
@@:

ENDIF ; FIREWALLS

;/*
;** If a new font has been selected, it will have been processed by
;** SetPatternFont.  SetPatternFont will have set the following flags:
;**
;**   BA_REREALIZE        To force calling this routine.
;**
;**   PA_BITMAP_SRC       If the source is really a bitmap.
;**
;**   PA_COLOR_TRUTH      If a source bitmap is color.  All other patterns are
;**                       considered a monochrome source.
;**
;**                       When a color bitmap is used, it will have been
;**                       copied into the color portion of the brush.  When a
;**                       monochrome bitmap is used, it will have been copied
;**                       into the transparency mask of the brush.
;**
;**   CA_CHANGED          To show that a new code-point is in use.  This will
;**                       force the rotation of the brush based on the DC
;**                       origin and the pattern origin.  The current rotation
;**                       (BASIC_ATTRS.ba_cRcr) will be ignored.                         |
;**
;** If a new symbol (code point) has been selected, the following flags will
;** have been set:
;**
;**   BA_REREALIZE        To force calling this routine.
;**
;**   CA_CHANGED          To show that a new code-point is in use.  This will
;**                       force the rotation of the brush based on the DC
;**                       origin and the pattern origin.  The current rotation
;**                       (BASIC_ATTRS.ba_cRcr) will be ignored.                         |
;**
;** If the transform has changed, or the DC Origin has changed, the following
;** flags will have been set:
;**
;**   BA_REREALIZE        To force calling this routine.
;**
;** If the foreground/background colors have changed, the following flags will
;** have been set:
;**
;**   BA_REREALIZE        To force calling this routine.
;**
;**   BA_CLR_INVALID      Foreground color changed.  The brush bits must be
;**                       realized.
;**
;**   BA_CLR_BACK_INV     Background color changed.  The brush bits must be
;**                       realized.
;**
;** None of the routines which set the above flags will ever alter pa_cRcr.
;** This will allow us to rotate a new pattern without having to do the
;** transform of pa_ptlOrg.
;*/

        MOV     EDX,[ESI].DDC.ddc_pa.pa_fs       ; Gather flags into EDX
        MOV     DL,[ESI].DDC.ddc_pa.pa_fb
        AND     EDX,CA_USER_FONT or CA_CHANGED or PA_COLOR_TRUTH or PA_BITMAP_SRC
        .ERRNZ  low CA_USER_FONT
        .ERRNZ  low CA_CHANGED
        .ERRNZ  (DH_USER_FONT shl 8)-CA_USER_FONT
        .ERRNZ  (DH_CHANGED   shl 8)-CA_CHANGED
        .ERRNZ  high PA_COLOR_TRUTH
        .ERRNZ  high PA_BITMAP_SRC
        .ERRNZ  DL_COLOR_TRUTH-PA_COLOR_TRUTH
        .ERRNZ  DL_BITMAP_SRC-PA_BITMAP_SRC
        AND     CL,DL_PASSED_CLRS
        OR      DL,CL

        MOV     AL,DL   ; Create a mask for testing BA_CLR_DEF
        NOT     AL      ; If passed colors, ignore DEF bit
        SHR     AL,2
        .ERRNZ  (DL_PASSED_CLRS shr 2) - BA_CLR_DEF
        AND     AL,BA_CLR_DEF

IFDEF PALMGR2
        mov     ebx,DirectDeviceDefaultPalette          ;DMS
        cmp     ebx,offset FullSizeDeviceDefaultPalette ;DMS
        JNZ     Dither_flag_is_set

ENDIF ; PALMGR

;start           
;/*
;**  If we are passed an RGB and we have an exact match for it,
;**  we shouldn't dither.
;*/
        TEST    DL,DL_PASSED_CLRS
        JZ      NotInRGBMode
        TEST    [ESI].DDC.ddc_fbClrTbl,DDC_RGB_MODE
        JZ      NotInRGBMode
        PUSH    EDI
        PUSH    EAX
        MOV     EDI,pColors
        MOV     EAX,[EDI].BITBLTATTRS.bba_lColor
        OR      EAX,EAX                                 ;color negative?
        JNS     @f                                      ;no, see if we have a match
        POP     EAX                                     ;yes, don't try to match
        POP     EDI                                     ;clean up and go on
        JMP     NotInRGBMode
@@:
        PUSH    ECX
        PUSH    EDX
        INVOKE  ExactDefaultPhysicalIndex,ESI,EAX
        POP     EDX
        POP     ECX
        CMP     EAX,PAL_ERROR                           ;did we find it?
        POP     EAX
        POP     EDI
        JNZ     Dither_flag_is_set                      ;yes, no need to dither
NotInRGBMode:
;end             

        TEST    [ESI].DDC.ddc_pa.pa_ba.ba_fb,AL
        JNZ     Dither_flag_is_set
        TEST    EDX,DH_USER_FONT shl 8 or DL_BITMAP_SRC
        JNZ     Dither_flag_is_set
        CMP     [ESI].DDC.ddc_pa.pa_ch,PATSYM_SOLID
        JNE     Dither_flag_is_set
        TEST    [ESI].DDC.ddc_fbClrTbl,DDC_PALETTE      ;           don't dither if
        JNZ     Dither_flag_is_set                      ;           palette loaded
        TEST    [ESI].DDC.ddc_fbClrTbl,DDC_DITHER
        JZ      Dither_flag_is_set
        OR      DL,DL_DITHER_OK

Dither_flag_is_set:

        TEST    DH,DH_CHANGED
        JNZ     @F
        JMP     Check_new_colors                 ; No font or code point change
@@:

;/*
;** The font or code point has changed.  This will require that the new bits
;** making up the pattern be located and moved into the pattern.  If the source
;** is a bitmap, then SetPatternFont will have already copied the bits into the
;** pattern for us.  Any other source will require us to locate the bits and
;** copy them into the pattern.
;*/


        AND     [ESI].DDC.ddc_pa.pa_fb,not (PA_GRAY or PA_SINGLE_CLR)
        AND     [ESI].DDC.ddc_pa.pa_fs, not CA_CHANGED
        TEST    DL,DL_BITMAP_SRC
        JZ      @F
        JMP     Have_new_code_point              ; Already have bits if a bitmap
                                        ; pattern

@@:
        TEST    DH,DH_USER_FONT
        JNZ     Use_user_font
        JMP     Use_default_patterns             ; Using default symbol set in _TEXT

;/*
;** The font is a user font.  We'll have to futz around (that's a technical
;** term!) to get the bits from the font and place them into the pattern
;** If the code point is invalid, we'll use the default code point in the
;** default pattern symbol set.
;*/


;/*
;**   get pointer to font
;**   get the codepoint
;**   map it through the codepage vector
;**   is it a valid codepoint?
;**   if no, go use the default one
;**   if normal font
;**       AH <-- width of glyph in bits (only significant up through 8)
;**       CX <-- number of bytes per scan of bitmap
;**       DX <-- height of bitmap
;**       DI <-- pointer to source bits
;**   else (abc spacing)
;**       AH <-- width of glyph in bits (only significant up through 8)
;**       CX <-- number of bytes per scan of bitmap
;**       DX <-- height of bitmap
;**       DI <-- pointer to source bits
;**   AL <-- 1 (number of color planes)
;**   BX <-- DDC
;**   SI <-- destination (transparency mask)
;*/


Use_user_font:
        MOV     EDI,[ESI].DDC.ddc_pa.pa_pFont
        MOVZX   EBX,[ESI].DDC.ddc_pa.pa_ch
        TEST    [ESI].DDC.ddc_pa.pa_fs,CA_MUST_MAP
        JZ      Chk_char_range
        ADD     EBX,EBX                         ; Make WORD pointer
        XCHG    EAX,EBX                         ; Put codepoint*2 into EAX
        MOV     EBX,[ESI].DDC.ddc_pa.pa_paus     ; Get mapping array
        XCHG    EDI,EAX
        MOVZX   EDI,WORD PTR [EBX][EDI]
        XCHG    EAX,EDI                         ; EDI unchanged
        XCHG    EAX,EBX                         ; Put codepoint into EBX

Chk_char_range:
        SUB     BX,[EDI].FOCAFONT.ff_fmMetrics.foca_usFirstChar
        JB      Use_default_code_point
        CMP     BX,[EDI].FOCAFONT.ff_fmMetrics.foca_usLastChar
        JA      Use_default_code_point
        PUSH    EDX                             ; Save flags
        MOVZX   EDX,[EDI].FOCAFONT.ff_fdDefinitions.fdh_yCellHeight
        TEST    [ESI].DDC.ddc_pa.pa_fs,CA_ABC_SPACE
        JZ      MBV_Setup_normal_font

MBV_Setup_abc_font:

        LEA     EDI,[EDI]+FONTMAP.fsCharOffset+ABC_FONT_ENTRIES.abc_fe_dBits
        ADD     EBX,EBX
        ADD     EDI,EBX
        SHL     EBX,2
        ADD     EDI,EBX
        .ERRNZ  (size ABC_FONT_ENTRIES) - 10
        JMP     MBV_Copy_font_bits

MBV_Setup_normal_font:
        LEA     EDI,[EDI]+FONTMAP.fsCharOffset+FONT_ENTRIES.fe_dBits
        ADD     EBX,EBX
        ADD     EDI,EBX
        ADD     EBX,EBX
        ADD     EDI,EBX
        .ERRNZ  (size FONT_ENTRIES) - 6

MBV_Copy_font_bits:
        MOV     EDI,[EDI]                       ; EDI=OFFSET FROM pFont
        ADD     EDI,[ESI].DDC.ddc_pa.pa_pFont   ; EDI now points to bits

        MOV     EAX,0801h                       ; 
                                                ; constant
        MOV     ECX,1                           ; Ditto
        MOV     EBX,ESI
        LEA     ESI,[EBX].DDC.ddc_pa.pa_abMask
        INVOKE  copy_bits_to_pattern
        POP     EDX                             ; Restore flags
        MOV     ESI,EBX                         ; Restore DDC to ESI
        JMP     Have_new_code_point

;/*
;** We want to use the default symbol set for the pattern.  The defaults are
;** assumed to reside in _TEXT.  Map the code point and copy the bits into the
;** transparency mask.
;*/


Use_default_patterns:

        MOV     BL,[ESI].DDC.ddc_pa.pa_ch

        DEC     BL
        CMP     BL,PATSYM_DIAGHATCH-1
        JBE     Have_valid_code_point
        CMP     BL,PATSYM_BLANK-1
        MOV     BL,PATSYM_NOSHADE-1
        JE      Have_valid_code_point

Use_default_code_point:
        MOV     BL,PATSYM_SOLID-1                        ; Default code point

Have_valid_code_point:
        MOVZX   EBX,BL
        SHL     EBX,3
        .ERRNZ  SIZE_PATTERN-8
        ADD     EBX,offset abBasePatterns
        XCHG    ESI,EBX
        CLD
        LODSD
        MOV     DWORD ptr [EBX].DDC.ddc_pa.pa_abMask,EAX
        LODSD
        MOV     DWORD ptr [EBX].DDC.ddc_pa.pa_abMask[4],EAX
        .ERRNZ  SIZE_PATTERN-8
        XCHG    ESI,EBX

Have_new_code_point:
        MOV     [ESI].DDC.ddc_pa.pa_cRcr,0       ; Have not rotated it yet

;/*
;** The bits of the pattern are now valid.  Process any color change.
;*/


Check_new_colors:
        TEST    DL,DL_PASSED_CLRS
        JZ      No_passed_colors

; The colors for the brush are to be overridden.  This presents us with a
; couple of problems.  If this is the base symbol set (for patterns) and the
; code point is PATSYM_SOLID and DDC_DITHER is set, then we will have to
; dither the color based on the RGB triplet.  That means we'll have to save
; the colors.

        PUSH    EDX                             ; Save flags
        MOV     EDI,pColors
        MOV     EAX,[EDI].BITBLTATTRS.bba_lColor


        MOV     clrFore,EAX                      ; Save for dithering

        LEA     EBX,[ESI].DDC.ddc_pa.pa_ba       ; Attribute bundle in DDC
        INVOKE  MakePassedColorsValid
        POP     EDX
        JNS     New_colors_set
Invalid_brush:
ifdef FIREWALLS
        cmp     eax,INVALID_IPC_DWORD
        je      @F
        assert  EAX,E,INVALID_IPC_DWORD
@@:
endif   ;FIREWALLS
        JMP     Make_brush_error_exit           ; Error logged already,
                                                ; EAX = IPC

;/*
;** We are to use the colors in the DDC for the brush.  If either color is
;** invalid, we'll have to remap it.
;*/


No_passed_colors:
        TEST    [ESI].DDC.ddc_pa.pa_ba.ba_fb,BA_CLR_INVALID or BA_CLR_BACK_INV
        JZ      New_colors_set
        PUSH    EDX
        LEA     EBX,[ESI].DDC.ddc_pa.pa_ba
        INVOKE  MakeColorsValid                                  ; Clears invalid bits
        POP     EDX
        JS      Invalid_brush

New_colors_set:

;----------------------------------------------------------------------------
; The code below *usually* works. However, there are cases
; where the Foreground color is changed to the default just after
; MakePassedColorsValid had used the DDC to create a one-time brush
; and pa_ipcFore is equal to ba_ipc, but the brush is not valid.           
;
;
;;/*
;;** The new IPCs for the brush are stored in pa_ba.ba_ipcClr*.  If these
;;** match the colors for the actual bits of the brush (in pa_ipc*) AND
;;** the font or codepoint did not change, then we may not have to rerealize
;;** the bits.  If dithering could occur, until we come up with a better
;;** solution, *we'll have to blow the cache.
;;*/
;
;
;        TEST    DH,DH_CHANGED
;        JNZ     Colors_are_different
;        MOV     AX,[ESI].DDC.ddc_pa.pa_ba.ba_ipc
;        CMP     AX,[ESI].DDC.ddc_pa.pa_ipcFore
;        JNE     Colors_are_different
;        MOV     AX,[ESI].DDC.ddc_pa.pa_ba.ba_ipcBack
;        CMP     AX,[ESI].DDC.ddc_pa.pa_ipcBack
;        JNE     Colors_are_different
;        TEST    DL,DL_DITHER_OK
;        JNZ     Colors_are_different
;        JMP     All_bits_are_valid
;----------------------------------------------------------------------------

Colors_are_different:
        MOV     AX,[ESI].DDC.ddc_pa.pa_ba.ba_ipc
        MOV     [ESI].DDC.ddc_pa.pa_ipcFore,AX
        MOV     AX,[ESI].DDC.ddc_pa.pa_ba.ba_ipcBack
        MOV     [ESI].DDC.ddc_pa.pa_ipcBack,AX
        OR      DL,DL_CLRS_CHANGED
        AND     [ESI].DDC.ddc_pa.pa_fb,not (PA_GRAY or PA_SINGLE_CLR)

;/*
;** Any new colors have been computed.  If either the foreground or the
;** background color is invalid, it is an internal error.  If either
;** the font, code point, foreground or background color has changed,
;** then pa_abColor and pa_abMono will have to be rerealized.  Might
;** even have to rerealize pa_abMask.
;*/


Have_all_colors:

IFDEF FIREWALLS
ifndef PALMGR2
        MOV     AX,[ESI].DDC.ddc_pa.pa_ba.ba_ipc
        OR      AX,[ESI].DDC.ddc_pa.pa_ba.ba_ipcBack

        JNS     @F
        rip     <text>,<Display - invalid brush colors stored in DDC>

@@:
endif
ENDIF ; FIREWALLS

        TEST    DX,DH_CHANGED shl 8 or DL_CLRS_CHANGED
        JZ      All_bits_are_valid               ; Only brush origin or IPCs were same

;/*
;** Yep, we be realizing the rest of the brush.  This gets real fun!
;** First, lets see if we can dither.  We can dither if PATSYM_SOLID
;** of the base pattern symbol set was set.  We will not dither if
;** PATSYM_SOLID was used by virtue of it being used as the default.
;**
;** If the foreground color for the brush is the "default", then we
;** won't dither as the default is always a solid.  It would also
;** require that an RGB triplet be around somewhere.  The code which
;** expands monochrome patterns into color patterns only requires
;** the IPC, which we have.
;*/


Must_rerealize_colors:
        TEST    DL,DL_DITHER_OK
        JNZ     Will_be_dithering

;/*
;** We cannot dither the brush.  We will have to perform color conversions
;** on the existing bits.  Two conversions can exist.  If the truth is a
;** monochrome source, then we have to expand it into color.  If the truth
;** is a color source, we'll have to create a monochrome part which will
;** also become the transparency mask.
;**
;** Before synthesizing other pattern bits, check to see if we have a
;** font source and the PAYSYM_SOLID codepoint  --  if so, we can set the
;** PA_SINGLE_CLR accelerator bit for fast Bitblts.
;*/


Cannot_dither:
        TEST    DX,DH_USER_FONT shl 8 or DL_BITMAP_SRC
        JNZ     Chk_color_truth
        CMP     [ESI].DDC.ddc_pa.pa_ch,PATSYM_SOLID
        JNE     Chk_color_truth
        OR      [ESI].DDC.ddc_pa.pa_fb,PA_SINGLE_CLR

Chk_color_truth:
        TEST    DL,DL_COLOR_TRUTH
        JZ      Color_from_mono
        INVOKE  fill_pattern_empty_bits
        INVOKE  synthesize_xparent_mask
        JMP     Gen_mono_brush

Color_from_mono:
        INVOKE  synthesize_color_bits

Gen_mono_brush:
        INVOKE  synthesize_mono_bits
        MOV     EDX,DH_CHANGED shl 8                     ; To force new pa_idBrush
        JMP     All_bits_are_valid

;/*
;** Well, we might be able to dither this guy.  Dithering will require
;** the actual RGB triplet used in the color table.  We can find this in
;** one of three places: the special colors table, the default color
;** table, or the user's color table.  If in RGB mode, it's a lot easier
;** since the index is the rgb color.
;*/


Will_be_dithering:
        MOV     AL,[ESI].DDC.ddc_fbClrTbl
        MOV     EBX,clrFore
        TEST    DL,DL_PASSED_CLRS
        JNZ     Have_dither_index
        MOV     EBX,[ESI].DDC.ddc_pa.pa_ba.ba_clr

Have_dither_index:
        OR      EBX,EBX
        JS      Index_is_special                         ; If negative, must be a
                                                         ; special color
        TEST    AL,DDC_RGB_MODE                          ; AL = DDC_fbClrTbl
        JNZ     Have_dither_RGB                          ; Index is RGB

        ;--------------------------------------------------------------------
        ; This check is to account for the case where the user is using
        ; an RGB while the PS is in LCT mode.           
        ;--------------------------------------------------------------------
        cmp     EBX,[ESI].DDC.ddc_ctMax                  ;           
        JG      Have_dither_RGB                          ;           

        SHL     EBX,SHIFT_DWORD                          ; RGBs in color tables are DWORDs
        TEST    AL,DDC_LOG_CLR_TBL
        JZ      Have_def_tbl_clr                         ; Index is in default table

;/*
;** The index is in a user defined logical color table.
;*/


        MOV     EDI,[ESI].DDC.ddc_pClrTbl
ifdef PALMGR2

;/*
;** ebx is dword shifted=*4, we need *8 => use *2
;*/

        mov     EBX,[edi+ebx*2].COLORTABLETYPE.LogRGB
else
        ADD     EBX,[EDI].COLOR_TABLE.ct_npargb  ; --> RGB index we want
        MOV     EBX,DWORD ptr [EBX]
endif
        JMP     Have_dither_RGB

;/*
;** The index is one of the special colors
;*/


Index_is_special:
ifdef PALMGR2
        neg     ebx
        shl     ebx,3
        test    [esi].DDC.ddc_fb,DDC_DEVICE
        mov     eax,offset MemorySpecialColorTable
        jz      @F
        mov     eax,offset DirectSpecialColorTable
@@:
        MOV     EBX,[eax+ebx].COLORTABLETYPE.LogRGB
        jmp     Have_dither_RGB
else
        SUB     EBX,MIN_SPECIAL_COLOR
        SHL     EBX,SHIFT_DWORD
        ADD     EBX,offset adrgbSpecial
        JMP     Get_clr_off_bx
endif

;/*
;** Index is in the default color table
;*/

Have_def_tbl_clr:
ifdef PALMGR2
        MOV     EAX,DefaultMemoryLogicalColorTable
        test    [esi].DDC.ddc_fb,DDC_DEVICE
        jz      its_memory
        MOV     EAX,DefaultDirectLogicalColorTable
its_memory:

;/*
;** ebx is dword shifted=*4, we need *8 => use *2
;*/

        MOV     EBX,[EAX+EBX*2].COLORTABLETYPE.LogRGB
else
        ADD     EBX,ctDefault+COLOR_TABLE.ct_npargb     ; EBX --> RGB index
Get_clr_off_bx:
        MOV     EBX,DWORD ptr [EBX]
endif                                                   ;         we want

;/*
;** Finally, we should have the RGB triplet to use for dithering.
;** Lets turn the dithering code loose with it.  One last thing
;** to do is determine which dithering code to use.  If this is a
;** device DDC, and there is at least one custom palette realized,
;** dither to the restricted default palette.  Otherwise, use the
;** full default palette.
;*/


Have_dither_RGB:
        MOV     EAX,EBX                         ; AX gets Low Word

;start           
;/*
;**  If our RGB is an exact match of what's in the hardware
;**  we shouldn't dither.
;*/
        PUSH    EAX
        PUSH    ECX
        PUSH    EDX
        INVOKE  ExactDefaultPhysicalIndex,ESI,EAX
        POP     EDX
        POP     ECX
        CMP     AX,[ESI].DDC.ddc_pa.pa_ba.ba_ipc     ;did we get our IPC
        POP     EAX
        JZ      Cannot_dither                        ;yes, don't dither
;end             


        MOV     EDX,EAX
        SHR     EDX,16                          ; DX gets High Word
        INVOKE  dither_brush                                     ; May clr/set solid brush bit
        MOV     DX,DH_CHANGED shl 8                      ; To force new pa_idBrush
        MOV     [ESI].DDC.ddc_pa.pa_cRcr,0       ; Not rotated at all

;/*
;** The bits making up the brush are all valid.  Rotate the brush as
;** needed for the current transform and DC origin.
;*/


All_bits_are_valid:
        MOV     ECX,[ESI].DDC.ddc_pa.pa_ptsOrg.ptl_x
        SUB     CL,[ESI].DDC.ddc_pa.pa_cRcr
        AND     CL,SIZE_PATTERN-1
        JZ      Pattern_is_rotated

;/*
;** Rotate the brush by the difference of the old and the new origin.
;** CL is the number of bits to rotate the pattern right.  Since patterns
;** are somewhat device dependant in their format, we'll let the device
;** specific code do it.
;*/


        ADD     [ESI].DDC.ddc_pa.pa_cRcr,CL      ; Save new rotation count
        INVOKE  rotate_brush
        MOV     DL,DL_ROTATED                                    ; To force new pa_idBrush

Pattern_is_rotated:

;/*
;** If anything changed in the brush, then we must update the brush's
;** reference count for caching.
;*/


        TEST    DX,(DH_CHANGED shl 8) or DL_ROTATED or DL_CLRS_CHANGED
        JZ      Brush_count_valid
        XOR     ECX,ECX                         ; Zeros are real handy

        MOV     EAX,idBrush
        ADD     EAX,1                           ; Update reference count
        RCL     ECX,5
        .ERRNZ  PAT_CACHE_FIRST_ID-0010h
        ADC     EAX,ECX
        MOV     idBrush,EAX

        MOV     [ESI].DDC.ddc_pa.pa_idBrush,EAX

Brush_count_valid:

;/*
;** Hey, I actually think we have finished the brush.  Clear all the "invalid"
;** bits.  The invalid bits for the colors will have been cleared by
;** MakeColorsValid.  We will have set the color invalid bits if we overrode
;** the colors.
;*/


        AND     [ESI].DDC.ddc_pa.pa_fs,not CA_CHANGED
        AND     [ESI].DDC.ddc_pa.pa_ba.ba_fb,not BA_REREALIZE
        XOR     EAX,EAX

Make_brush_error_exit:
        OR      EAX,EAX                         ; Set/clear 'S'
        .ERRNZ  BA_CLR_INVALID - 80h

        RET

MakeBrushValid ENDP

        END
