;*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    ,132
;/*****************************************************************************
;*
;* SOURCE FILE NAME = MKVALID.ASM
;*
;* DESCRIPTIVE NAME = Color and brush validation routines. 
;*
;*
;* VERSION      V2.0
;*
;* DATE         
;*
;* 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
;*   02/04/88                     Steve Wood [stevewo]
;*                                Wrote MakeColorsValid
;*   02/07/88                     Walt Moore [waltm]
;*                                The big rewrite.  Now trashes ES.
;*   03/01/88                     Wes Rupel [wesleyr]
;*                                Added check for     colors, and error
;*                                return conditions.
;*   04/03/88                     Walt Moore [waltm]
;*                                ColorConvert now logs the error for us.
;*   04/13/88                     Bob Grudem [bobgru]
;*                                Now saves brush rotation count (pa_cRcr)
;*                                when the brush is rotated.
;*   06/16/88                     Walt Moore [waltm]
;*                                Wrote xform_pattern_origin
;*   06/17/88                     Walt Moore [waltm]
;*                                Removed BA_XFORM_CHANGE test and conversion
;*                                of pa_ptlOrg.  Now done when attribute is set,
;*                                so pa_ptsOrg is always valid.
;*   09/19/88                     Walt Moore [waltm]
;*                                Only clear PA_GRAY and PA_SINGLE_CLR if
;*                                they change
;*   09/21/88                     Lee A. Newberg [leen]
;*                                Installed farMakeColorsValid
;*                                Walt Moore [waltm]
;*                                Implemented brush caching logic.
;*   10/10/88                     Walt Moore [waltm]
;*                                Wrote MakeColorsValid
;*   
;*****************************************************************************/
     
     
        .286p
        .xlist
        include cmacros.inc
INCL_GPIPRIMITIVES      equ                      1
INCL_FONTFILEFORMAT     equ                      1
INCL_DDIMISC            equ                      1
INCL_GRE_XFORMS         equ                      1
INCL_GPITRANSFORMS      equ                      1
        include pmgre.inc
DINCL_CLR_TBL           equ                      1
DINCL_PAT_CACHE_DEFS    equ                      1
        include driver.inc
        include fontseg.inc
        include assert.mac
        include njmp.mac
        .list

        ??_out  mkvalid

        errcode <INV_PATTERN_REF_PT_ATTR,INV_LENGTH_OR_COUNT>

        externA MIN_SPECIAL_COLOR


FONT_ENTRIES    struc
fe_dBits        dd      ?                         ;Offset entry index for prop fonts
fe_width        dw      ?                         ;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 struc
abc_fe_dBits     dd     ?
abc_a_space      dw     ?
abc_b_space      dw     ?
abc_c_space      dw     ?
ABC_FONT_ENTRIES ends

sBegin  Data
        externB ctDefault
        externD adrgbSpecial
        externW ipcSysClrWindowText
        externW ipcSysClrWindow
        externD pfnDefConvert
        externD idBrush
sEnd    Data

sBegin  Code
        assumes cs,Code

        externB abBasePatterns

        externNP rgb_to_ipc
        externNP rotate_brush
        externNP fill_pattern_empty_bits
        externNP synthesize_xparent_mask
        externNP synthesize_color_bits
        externNP synthesize_mono_bits
        externNP dither_brush
        externNP copy_bits_to_pattern
        externNP ColorConvert
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         = DS:SI   = DDC
;*                 DS:BX   = Basic Attribute structure offset                                                                    
;*                 ES:DI --> Passed attributes (CSP_INFO or BITBLTATTRS)                                                         
;*                 Calls: MakeColorsValid (saves CX,BX for us)
;*                                                                            
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = 'S' clear       ( = the sign bit in AX) 
;*                                                                            
;* RETURN-ERROR  = 'S' set         ( = the sign bit in AX)                                                              
;*                 AX  = INVALID_IPC                                                                                    
;*                 Error logged
;*
;**************************************************************************/

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

cProc MakePassedColorsValid,<NEAR,PUBLIC,NONWIN>
cBegin

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

        cmp     es:[di].csp_cSize.hi,0
        jne     mpcv_attrs_struc_bad
        cmp     es:[di].csp_cSize.lo,size CSP_INFO
        je      attrs_struc_good

mpcv_attrs_struc_bad:
        mov     ax,PMERR_INV_LENGTH_OR_COUNT
        save_error_code
        mov     ax,INVALID_IPC
        jmp     short 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    [bx].ba_clr.lo
        push    [bx].ba_clr.hi
        push    [bx].ba_clrBack.lo
        push    [bx].ba_clrBack.hi
        push    word ptr [bx].ba_bReserved
        .errnz  ba_fb-ba_bReserved-1

        mov     ax,es:[di].csp_lColor.lo
        mov     [bx].ba_clr.lo,ax
        mov     ax,es:[di].csp_lColor.hi
        mov     [bx].ba_clr.hi,ax
        mov     ax,es:[di].csp_lBackColor.lo
        mov     [bx].ba_clrBack.lo,ax
        mov     ax,es:[di].csp_lBackColor.hi
        mov     [bx].ba_clrBack.hi,ax
        mov     [bx].ba_fb,BA_CLR_INVALID or BA_CLR_BACK_INV

        call    MakeColorsValid                  ;He does all the work for us

        pop     word ptr [bx].ba_bReserved
        .errnz  ba_fb-ba_bReserved-1
        pop     [bx].ba_clrBack.hi
        pop     [bx].ba_clrBack.lo
        pop     [bx].ba_clr.hi
        pop     [bx].ba_clr.lo
        or      [bx].ba_fb,BA_CLR_INVALID or BA_CLR_BACK_INV or BA_REREALIZE

mpcv_exit:
        or      ax,ax                             ;Set/clear 'S'
cEnd
page

;/***************************************************************************
;*
;* FUNCTION NAME = farMakeColorsValid
;*
;* DESCRIPTION   = Calls MakeColorsValid 
;*                                                                          
;* INPUT         = None
;* OUTPUT        = None
;*                  
;* RETURN-NORMAL = None
;* RETURN-ERROR  = None
;*
;**************************************************************************/

cProc   far_MakeColorsValid,<FAR,PUBLIC,NONWIN,NODATA>
cBegin
        cCall   MakeColorsValid
cEnd
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                                                          
;*                 Calls:
;*                       ColorConvert
;*                                                                          
;* INPUT         = DS:SI   = DDC                       
;*                 DS:BX   = Basic Attribute structure                                                        
;*                                                                          
;* OUTPUT        = AX = IPC                          
;*                  
;* RETURN-NORMAL = 'S' clear ( = the sign bit in AX)
;*                                                                          
;* RETURN-ERROR  = AX = INVALID_IPC               
;*                 'S' set ( = the sign bit in AX)                                                         
;*                 Error logged                    
;**************************************************************************/

cProc   MakeColorsValid,<NEAR,PUBLIC,NONWIN>,<cx>
cBegin
ifdef FIREWALLS
        ddc?    si
        mov     cl,[bx].ba_fb
        test    cl,BA_CLR_INVALID or BA_CLR_BACK_INV
        jnz     @F
        rip     text,<ColorsAlreadyValid>
@@:
endif
        mov     cl,[bx].ba_fb
        or      cl,cl
        jns     mcv_clr_okay
        .errnz  BA_CLR_INVALID - 80h
        mov     ax,[bx].ba_clr.lo
        mov     dx,[bx].ba_clr.hi
        and     cl,BA_CLR_DEF
        call    ColorConvert
        js      mcv_exit
        mov     word ptr [bx].ba_ipc,ax
        mov     cl,[bx].ba_fb
mcv_clr_okay:
        test    cl,BA_CLR_BACK_INV
        jz      mcv_clrBack_okay
        mov     ax,[bx].ba_clrBack.lo
        mov     dx,[bx].ba_clrBack.hi
        and     cl,BA_CLR_BACK_DEF
        call    ColorConvert
        js      mcv_exit
        mov     word ptr [bx].ba_ipcBack,ax
mcv_clrBack_okay:
        and     [bx].ba_fb,not (BA_CLR_BACK_INV or BA_CLR_INVALID or BA_REREALIZE)
mcv_exit:
        or      ax,ax
cEnd
page

;/***************************************************************************
;*
;* FUNCTION NAME = MakeBrushValid 
;*
;* DESCRIPTION   = MakeBrushValid will process the given DDC's pattern      
;*                 attributes and attempt to make them valid.               
;*                                                                          
;* INPUT         = DS:SI --> 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 AX) 
;* RETURN-ERROR  = 'S' set ( = the sign bit in AX) 
;*                 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

        assumes ds,Data
        assumes es,nothing

cProc   MakeBrushValid,<NEAR,PUBLIC>,<di>
        parmD   pColors
        localD  clrFore
        localV  rclTemp,%(size RECTL)
cBegin

ifdef FIREWALLS
        ddc?    si
        or      cl,cl
        jz      @F
        cmp     cl,0FFh
        jz      @F
        rip     text,<Invalid flags passed to MakeBrushValid>
@@:
        test    [si].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,[si].ddc_pa.pa_fb              ;Can only show color truth if
        test    al,PA_COLOR_TRUTH                 ;  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

;/*
;** If a new font has been selected, it will have been processed by
;** SetPatternFont.  Set PatternFont 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 (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 (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     dx,[si].ddc_pa.pa_fs             ;  Gather flags into DX
        mov     dl,[si].ddc_pa.pa_fb
        and     dx,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 PALMGR
        test    [si].ddc_fbBelow,DDC_PALETTE
        jnz     dither_flag_is_set
endif
        test    [si].ddc_pa.pa_ba.ba_fb,al
        jnz     dither_flag_is_set
        test    dx,DH_USER_FONT shl 8 or DL_BITMAP_SRC
        jnz     dither_flag_is_set
        cmp     [si].ddc_pa.pa_ch,PATSYM_SOLID
        jne     dither_flag_is_set
        test    [si].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     [si].ddc_pa.pa_fb,not (PA_GRAY or PA_SINGLE_CLR)
        and     [si].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:
        access  ax,[si].ddc_pa.pa_pFont.sel
        les     di,[si].ddc_pa.pa_pFont
        assumes es,FontSeg
        mov     bl,[si].ddc_pa.pa_ch
        xor     bh,bh


        test    [si].ddc_pa.pa_fs,CA_MUST_MAP
        jz      chk_char_range

        add     bx,bx                             ;make word pointer
        access  ax,[si].ddc_pa.pa_paus.sel
        xchg    ax,bx                             ;put codepoint*2 into AX
        les     bx,[si].ddc_pa.pa_paus            ;Get mapping array
        assumes es,nothing
        xchg    di,ax
        mov     di,es:[bx][di]
        xchg    ax,di
        mov     es,[si].ddc_pa.pa_pFont.sel
        assumes es,FontSeg
        xchg    ax,bx                             ;put codepoint into BX

chk_char_range:
        sub     bx,[di].fsMetrics.foca_usFirstChar
        jc      use_default_code_point
        cmp     bx,[di].fsMetrics.foca_usLastChar
        ja      use_default_code_point

        push    dx                                ;save flags
        mov     dx,[di].fsDef.fdCellHeight

        test    [si].ddc_pa.pa_fs,CA_ABC_SPACE
        jz      mbv_setup_normal_font

mbv_setup_abc_font:
        lea     di,[di].fsCharOffset.abc_fe_dBits.lo
        add     bx,bx
        add     di,bx
        add     bx,bx
        add     bx,bx
        add     di,bx
        .errnz  (size ABC_FONT_ENTRIES) - 10
        jmp     short mbv_copy_font_bits

mbv_setup_normal_font:
        lea     di,[di].fsCharOffset.fe_dBits.lo
        add     bx,bx
        add     di,bx
        add     bx,bx
        add     di,bx
        .errnz  (size FONT_ENTRIES) - 6

mbv_copy_font_bits:
        mov     di,es:[di]                        ;DI now points to bits
        mov     al,1                              ;text always from mono bitmap
        mov     ah,8                              ;font format makes this constant
        mov     cx,1                              ; ditto
        mov     bx,si
        lea     si,[bx].ddc_pa.pa_abMask
        cCall   copy_bits_to_pattern
        pop     dx                                ;restore flags

        mov     si,bx                             ;restore DDC to SI
        jmp     short   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,[si].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:

        xor     bh,bh
        shl     bx,3
        .errnz  SIZE_PATTERN-8
        add     bx,CodeOFFSET abBasePatterns
        xchg    si,bx
        cld
        lods    word ptr cs:[si]
        mov     word ptr [bx].ddc_pa.pa_abMask[0],ax
        lods    word ptr cs:[si]
        mov     word ptr [bx].ddc_pa.pa_abMask[2],ax
        lods    word ptr cs:[si]
        mov     word ptr [bx].ddc_pa.pa_abMask[4],ax
        lods    word ptr cs:[si]
        mov     word ptr [bx].ddc_pa.pa_abMask[6],ax
        .errnz  SIZE_PATTERN-8
        xchg    si,bx
have_new_code_point:
        mov     [si].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    dx                                ;Save flags
        les     di,pColors
        assumes es,nothing
        mov     ax,es:[di].bba_lColor.lo
        mov     dx,es:[di].bba_lColor.hi
        mov     clrFore.lo,ax                     ;Save for dithering
        mov     clrFore.hi,dx
        lea     bx,[si].ddc_pa.pa_ba              ;Attribute bundle in ddc
        call    MakePassedColorsValid
        pop     dx
        jns     new_colors_set

invalid_brush:
        assert  ax,E,INVALID_IPC
        jmp     make_brush_error_exit             ;Error logged already, AX = 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    [si].ddc_pa.pa_ba.ba_fb,BA_CLR_INVALID or BA_CLR_BACK_INV
        jz      new_colors_set
        push    dx
        lea     bx,[si].ddc_pa.pa_ba
        call    MakeColorsValid                  ;Clears invalid bits
        pop     dx
        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,word ptr [si].ddc_pa.pa_ba.ba_ipc
        cmp     ax,word ptr [si].ddc_pa.pa_ipcFore
        jne     colors_are_different
        mov     ax,word ptr [si].ddc_pa.pa_ba.ba_ipcBack
        cmp     ax,word ptr [si].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,word ptr [si].ddc_pa.pa_ba.ba_ipc
        mov     word ptr [si].ddc_pa.pa_ipcFore,ax
        mov     ax,word ptr [si].ddc_pa.pa_ba.ba_ipcBack
        mov     word ptr [si].ddc_pa.pa_ipcBack,ax
        or      dl,DL_CLRS_CHANGED
        and     [si].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,word ptr [si].ddc_pa.pa_ba.ba_ipc
        or      ax,word ptr [si].ddc_pa.pa_ba.ba_ipcBack
        jns     @F
        rip     <text>,<Display - invalid brush colors stored in ddc>
@@:
endif
        test    dx,DH_CHANGED shl 8 or DL_CLRS_CHANGED
        jnz     must_rerealize_colors

all_bits_are_valid_relay:
        jmp     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     [si].ddc_pa.pa_ch,PATSYM_SOLID
        jne     chk_color_truth
        or      [si].ddc_pa.pa_fb,PA_SINGLE_CLR
chk_color_truth:
        test    dl,DL_COLOR_TRUTH
        jz      color_from_mono
        call    fill_pattern_empty_bits
        call    synthesize_xparent_mask
        jmp     short gen_mono_brush
color_from_mono:
        call    synthesize_color_bits
gen_mono_brush:
        call    synthesize_mono_bits
        mov     dx,DH_CHANGED shl 8              ;To force new pa_idBrush
        jmp     short 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,[si].ddc_fbClrTbl
        mov     bx,clrFore.lo
        mov     cx,clrFore.hi
        test    dl,DL_PASSED_CLRS
        jnz     have_dither_index
        mov     bx,[si].ddc_pa.pa_ba.ba_clr.lo
        mov     cx,[si].ddc_pa.pa_ba.ba_clr.hi

have_dither_index:
        inc     ch                                ;If negative, must be a
        jz      index_is_special                  ; special color
        dec     ch
        test    al,DDC_RGB_MODE                   ; AL = ddc_fbClrTbl
        jnz     have_dither_rgb                   ;Index is RGB
        shl     bx,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.
;*/

        les     di,[si].ddc_pClrTbl
        assumes es,nothing
        add     bx,es:[di].ct_npargb             ;--> rgb index we want
        mov     cx,es:[di][bx].hi
        mov     bx,es:[di][bx].lo
        jmp     short have_dither_rgb

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

index_is_special:
        sub     bx,MIN_SPECIAL_COLOR
        shl     bx,SHIFT_DWORD
        add     bx,DataOFFSET adrgbSpecial
        jmp     short get_clr_off_bx

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

have_def_tbl_clr:
        add     bx,ctDefault.ct_npargb           ;--> rgb index we want
get_clr_off_bx:
        mov     cx,[bx].hi
        mov     bx,[bx].lo

;/*
;** 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:
        xchg    ax,bx
        mov     dx,cx
        call    dither_brush                      ;May clear/set solid brush bit
        mov     dx,DH_CHANGED shl 8               ;To force new pa_idBrush
        mov     [si].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     cx,[si].ddc_pa.pa_ptsOrg.pts_x
        sub     cl,[si].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     [si].ddc_pa.pa_cRcr,cl            ;save new rotation count
        call    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 brushes
;** reference count for caching.
;*/

        test    dx,(DH_CHANGED shl 8) or DL_ROTATED or DL_CLRS_CHANGED
        jz      brush_count_valid
        xor     cx,cx                             ;Zeros are real handy
        mov     ax,idBrush.lo
        mov     dx,idBrush.hi
        add     ax,1                              ;Update reference count
        adc     dx,cx
        rcl     cx,5
        .errnz  PAT_CACHE_FIRST_ID-0010h
        adc     ax,cx
        mov     idBrush.lo,ax
        mov     idBrush.hi,dx
        mov     [si].ddc_pa.pa_idBrush.lo,ax
        mov     [si].ddc_pa.pa_idBrush.hi,dx
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     [si].ddc_pa.pa_fs,not CA_CHANGED
        and     [si].ddc_pa.pa_ba.ba_fb,not BA_REREALIZE

        xor     ax,ax

make_brush_error_exit:
        or      ax,ax                             ; Set/clear 'S'
        .errnz  BA_CLR_INVALID - 80h

make_brush_out:
cEnd
page

;/***************************************************************************
;*
;* FUNCTION NAME = xform_pattern_origin
;*
;* DESCRIPTION   = The pattern reference point is transformed into device             
;*                 coordinates.  If overflow occurs, an error is returned,
;*                 else the reference point is stored in the ddc with the dc
;*                 origin added in.
;*               Registers Preserved:
;*                     SI,DI,DS,BP
;*               Registers Destroyed:
;*                     AX,BX,CX,DX,ES,Flags
;*               Calls:
;*                     convert_world_device
;*
;* INPUT         = DS:SI --> DDC
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = 1 if OK 
;* RETURN-ERROR  = AX = 0 if error, error logged 
;*                 Error logged 
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   xform_pattern_origin,<NEAR,PUBLIC>
cBegin
        push    [si].ddc_pa.pa_ptlOrg.ptl_y.hi
        push    [si].ddc_pa.pa_ptlOrg.ptl_y.lo
        push    [si].ddc_pa.pa_ptlOrg.ptl_x.hi
        push    [si].ddc_pa.pa_ptlOrg.ptl_x.lo
        mov     cx,sp
        xor     ax,ax
        farPtr  lp_point,ss,cx
        farPtr  myhdc,[si].ddc_hdc.sel,[si].ddc_hdc.off
        farPtr  world,ax,CVTC_WORLD
        farPtr  device,ax,CVTC_DEVICE
        farPtr  count,ax,1
        farPtr  hddcNull,ax,ax
        check   Convert,<hdc,lSrc,lTarg,pptl,cptl,hddc,ulFunN>
        cCall   pfnDefConvert,<myhdc,world,device,lp_point,count,hddcNull,GreConvert>
        or      ax,ax
        jnz     xpo_valid_origin
        add     sp,size POINTL                    ;Remove POINTL from stack
        mov     ax,PMERR_INV_PATTERN_REF_PT_ATTR
        save_error_code
        xor     ax,ax
        jmp     short xpo_exit

;/*
;**  We don't care about overflow from adding in the dc origin since we'll
;**  be taking the entire mess MOD SIZE_PATTERN-1
;*/

xpo_valid_origin:
        pop     ax
        les     bx,[si].ddc_prddc                ; ES:BX = RDDC
        assumes es,nothing
        rddc?   es,bx
        add     ax,es:[bx].rddc_ptsOrg.pts_x
        mov     [si].ddc_pa.pa_ptsOrg.pts_x,ax
        add     sp,2
        pop     ax
        add     ax,es:[bx].rddc_ptsOrg.pts_y
        mov     [si].ddc_pa.pa_ptsOrg.pts_y,ax
        add     sp,2
        mov     ax,1
        fw_zero <es>
xpo_exit:
cEnd
sEnd

ifdef FIREWALLS
        public  mpcv_attrs_struc_bad
        public  attrs_struc_good
        public  mpcv_exit
        public  mcv_clr_okay
        public  mcv_clrBack_okay
        public  mcv_exit
        public  dither_flag_is_set
        public  use_user_font
        public  chk_char_range
        public  mbv_setup_abc_font
        public  mbv_setup_normal_font
        public  mbv_copy_font_bits
        public  use_default_patterns
        public  use_default_code_point
        public  have_valid_code_point
        public  have_new_code_point
        public  check_new_colors
        public  invalid_brush
        public  no_passed_colors
        public  new_colors_set
        public  colors_are_different
        public  have_all_colors
        public  all_bits_are_valid_relay
        public  must_rerealize_colors
        public  cannot_dither
        public  chk_color_truth
        public  color_from_mono
        public  gen_mono_brush
        public  will_be_dithering
        public  have_dither_index
        public  index_is_special
        public  have_def_tbl_clr
        public  get_clr_off_bx
        public  have_dither_rgb
        public  all_bits_are_valid
        public  pattern_is_rotated
        public  brush_count_valid
        public  make_brush_error_exit
        public  make_brush_out
        public  xpo_valid_origin
        public  xpo_exit
endif

end
