;*DDK*************************************************************************/
;
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
        PAGE     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
;* ifdef  TMP        ;IBMJ
;*   01/13/94  @MU1               Trap-D occured on some of EXCEL function.
;* endif ;TMP        ;IBMJ
;*****************************************************************************/

        .386P
        .MODEL FLAT,SYSCALL

;/*
;** Included files       
;*/

INCL_DDIFONTSTRUCS EQU 1
INCL_DDIMISC       EQU 1
INCL_GPIPRIMITIVES EQU 1
INCL_GPITRANSFORMS EQU 1
INCL_GRE_XFORMS    EQU 1
INCL_NOBASEAPI     EQU 1
INCL_NOCOMMON      EQU 1
INCL_SAADEFS       EQU 1
OS2_NOPMAPI        EQU 1

        OPTION  OLDSTRUCTS

        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
        INCLUDE STRBLT.INC

;/*
;** Local structures  
;*/

EXTERNDEF ctDefault                     :DWORD

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

ALIGN 4
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
ALIGN 4

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

ALIGN 4
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
        MOV     [EBX].BASIC_ATTRS.ba_ipc,AX
        MOV     CL,[EBX].BASIC_ATTRS.ba_fb

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
        MOV     WORD ptr [EBX].BASIC_ATTRS.ba_ipcBack,AX

MCV_ClrBack_okay:
        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

ALIGN 4
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


        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_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
ALIGN 4
@@:

;/*
;** 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 
ALIGN 4
                                                 ; pattern

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

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

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
ALIGN 4

;/*
;** 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:
        MOVZX   EBX,[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:
ifndef TMP        ;IBMJ
        SHL     EBX,3
        .ERRNZ  SIZE_PATTERN-8
        ADD     EBX,offset abBasePatterns
else  ;TMP        ;IBMJ
 movzx ebx,bl    ;It is strange, but @MU1
 .errnz SIZE_PATTERN-8   ;sometimes garbage value@MU1
 lea ebx,abBasePatterns[ebx*8] ;was found in BH. @MU1
endif ;TMP        ;IBMJ
        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:
        assert  EAX,E,INVALID_IPC_DWORD
        JMP     Make_brush_error_exit                    ; Error logged already, 
ALIGN 4
                                                ; 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 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
ALIGN 4

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

        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 ; 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
ALIGN 4

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
ALIGN 4

;/*
;** 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
        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
        ADD     EBX,[EDI].COLOR_TABLE.ct_npargb  ; --> RGB index we want
        MOV     EBX,DWORD ptr [EBX]
        JMP     Have_dither_RGB
ALIGN 4

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

Index_is_special:
        SUB     EBX,MIN_SPECIAL_COLOR
        SHL     EBX,SHIFT_DWORD
        ADD     EBX,offset adrgbSpecial
        JMP     Get_clr_off_bx
ALIGN 4

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

Have_def_tbl_clr:
        ADD     EBX,ctDefault+COLOR_TABLE.ct_npargb     ; EBX --> RGB index 
                                                        ;         we want
Get_clr_off_bx:
        MOV     EBX,DWORD ptr [EBX]

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