;*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    Color Conversions
        SUBTITLE Header
;/*****************************************************************************
;*
;* SOURCE FILE NAME = CLRCONV.ASM
;*
;* DESCRIPTIVE NAME = Color convesion routines. 
;*
;*
;* VERSION      V2.0
;*
;* DATE         11/10/91
;*
;* DESCRIPTION  Color convesion routines.
;*              
;*
;* FUNCTIONS    ColorConvert
;*              ipc_to_index
;*                          
;* 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/10/91                     KEZ  Original
;*****************************************************************************/

        .386P
        .MODEL FLAT,SYSCALL

;/*
;** Included files
;*/

INCL_NOBASEAPI     EQU 1
INCL_GPIPRIMITIVES EQU 1
OS2_NOPMAPI        EQU 1
INCL_SAADEFS       EQU 1
        INCLUDE PMGRE.INC

DINCL_BITMAP       EQU 1
DINCL_CLR_TBL      EQU 1
DINCL_ENABLE       EQU 1
        INCLUDE DRIVER.INC
        INCLUDE DISPLAY.INC
        INCLUDE EXTERN.INC
        INCLUDE PROTOS.INC

EXTERNDEF ctDefault                     :DWORD

;/*
;** Data
;*/

        .DATA

;/*
;** anpfnClrMap contains the address of the processors which will be called to
;** perform the specific color mapping, based on the color mode currently set
;** in the DDC.
;*/

anpfnClrMap LABEL DWORD  
        DWORD   Def_clr_tbl_to_IPC
        DWORD   User_clr_tbl_to_IPC
        DWORD   My_RGB_to_IPC
        DWORD   My_RGB_to_IPC
        .ERRNZ  DDC_RGB_MODE-00000100b
        .ERRNZ  DDC_LOG_CLR_TBL-00000010b

;/*
;** Public functions
;*/

        .CODE    

        SUBTITLE ColorConvert
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = ColorConvert 
;*
;* DESCRIPTION   = ColorConvert accepts a logical color and returns the device
;*                 dependent, physical representation of bits necessary to    
;*                 display the color closest to the specified color on the    
;*                 device.  This information will be used later by other      
;*                 driver routines.                                           
;*                                                                            
;*                 Registers Preserved:                                                             
;*                       BX,CX,SI,DI,DS                                                             
;*                 Registers Destroyed:                                                             
;*                       AX,DX,ES,FLAGS                                                             
;*                                                                            
;* INPUT         = ESI --> DDC                                      
;*                 EAX  =  Logical color (special, index, or rgb)                                                              
;*                 CL   =  BA_CLR_DEF or BA_CLR_BACK_DEF from ba_fb                                                            
;*                           (only one may be set)                                                                             
;*                                                                            
;* OUTPUT        = EAX  = IPC          
;*                 'S' clear                                                                      
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  = EAX = INVALID_IPC 
;*                 'S' set           
;*                 Error logged      
;*
;**************************************************************************/

        ALIGN   4

ColorConvert PROC SYSCALL PUBLIC USES EBX

IFDEF FIREWALLS

        ddc?    ESI
        NOT     CL                      ; Can have one flag at most set
        TEST    CL,BA_CLR_DEF or BA_CLR_BACK_DEF  
        NOT     CL                      ; Not doesn't alter flags
        JNZ     @F       
        rip     text,<ColorConvert called with more than one _DEF flag>
@@:

ENDIF ; FIREWALLS

        TEST    CL,BA_CLR_DEF or BA_CLR_BACK_DEF  
        JNZ     Have_a_def_color                  
        OR      EAX,EAX                 ; Possibly special color?
        JNS     Not_special_color       ;  Nope
        SUB     EAX,MIN_SPECIAL_COLOR            ; Special color within range?
        JC      Invalid_color_index              ; No, error

;/*
;** The color is a SPECIAL color.  Look it up in aipcSpecial.
;*/

Look_up_special_color:
        ADD     EAX,EAX  
        .ERRNZ  SIZE_IPC-2
        XCHG    EAX,EBX
        MOVSX   EAX,aipcSpecial[EBX]              
        JMP     Color_convert_chk_clr             

        ALIGN   4


;/*
;** The color is a default color.  We can skip all the mapping stuff and just
;** return the correct default to the caller.  The defaults can not be in
;** error.
;*/

Have_a_def_color:
        MOVSX   EAX,ipcSysClrWindowText           
        TEST    CL,BA_CLR_DEF                     
        JNZ     Color_convert_good_color          
        MOVSX   EAX,ipcSysClrWindow               
        JMP     Color_convert_good_color          

        ALIGN   4

;/*
;** These errnz's are very important.  Since we take the good exit, we rely on
;** the "test" operation to clear 'S'.  Since we only allow these two values as
;** arguments, there should be no problem with this.
;*/

        .ERRNZ  BA_CLR_DEF-00100000b
        .ERRNZ  BA_CLR_BACK_DEF-00010000b

;/*
;** The color was not a special color.  Call the color conversion routine to  
;** map the color into an IPC.                                                
;*/

Not_special_color:
        MOVZX   EBX,[ESI].DDC.ddc_fbClrTbl        
        AND     EBX,DDC_RGB_MODE or DDC_LOG_CLR_TBL  
        .ERRNZ  DDC_RGB_MODE-00000100b
        .ERRNZ  DDC_LOG_CLR_TBL-00000010b
        JMP     anpfnClrMap[2*EBX]               ; To the real handler

        ALIGN   4


;/*
;** Process a convert call for the default color table
;*/

Def_clr_tbl_to_IPC::
        CMP     EAX,ctDefault+COLOR_TABLE.ct_iMax  
        JA      Invalid_color_index              ; To big,     color index

Look_up_def_clr_tbl:
        ADD     EAX,EAX  
        .ERRNZ  SIZE_IPC-2
        XCHG    EAX,EBX  
        MOVSX   EAX,WORD ptr ctDefault+ct_aipc[EBX]  
        JMP     Color_convert_chk_clr             

        ALIGN   4


;/*
;** Process a convert call for a user-defined logical color table.
;*/

User_clr_tbl_to_IPC::
        CMP     EAX,DEVCAPS_COLOR_INDEX           
        JA      Invalid_color_index              ; To big,     color index
        MOV     EBX,[ESI].DDC.ddc_pClrTbl         
        ADD     EAX,EAX  
        .ERRNZ  SIZE_IPC-2
        XCHG    EAX,ESI  
        MOVZX   ESI,WORD ptr [EBX]+ct_aipc[ESI]   
        XCHG    EAX,ESI  
        JMP     Color_convert_chk_clr             

        ALIGN   4


;/*
;** Process a convert call for RGB mode.
;*/

My_RGB_to_IPC::
        TEST    EAX,0FF000000h
        JS      Invalid_color_index              ; Special index was too negative
        JNZ     Invalid_color_data               ; RGB is bad
        MOV     EDX,EAX
        SHR     EDX,16
        INVOKE  rgb_to_ipc                       ; Map EAX to an IPC, cannot fail

;/*
;** We could get an invalid IPC from a color table.  If so, we want to log an
;** error.
;*/

Color_convert_chk_clr:
        OR      EAX,EAX                 ; Set/clear 'S'
        JNS     Color_convert_good_color          

Invalid_color_index:
        MOV     EAX,PMERR_INV_COLOR_INDEX         
        JMP     CC_Log_error                      

        ALIGN   4


Invalid_color_data:
        MOV     EAX,PMERR_INV_COLOR_DATA          

CC_Log_error:
        PUSH    EBX                     ; This function preserves these
        PUSH    ECX                     ; registers
        save_error_code
        POP     ECX      
        POP     EBX      
        MOV     EAX,INVALID_IPC_DWORD   ; Invalid color
        OR      EAX,EAX                 ; Set 'S' to show invalid color

Color_convert_good_color:

        RET

ColorConvert ENDP
        SUBTITLE ipc_to_index
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = ipc_to_index  
;*
;* DESCRIPTION   = Converts an IPC to a valid color index.  Scans color     
;*                 tables to find the index if needed.                      
;*                                                                          
;*                 Registers modified: 
;*                   ECX EDX           
;*                                                                          
;* INPUT         = EBX --> DDC 
;*                 EAX  =  IPC 
;* OUTPUT        = EAX = Color index  
;*
;* RETURN-NORMAL = EAX = Color index
;* RETURN-ERROR  = EAX = CLR_NOINDEX if no index exists 
;*
;**************************************************************************/

        ALIGN   4

ipc_to_index PROC SYSCALL PUBLIC uses EBX EDI ESI

        DebugMsg <ipc_to_index,KEZ>

        TEST    [EBX].DDC.ddc_fbClrTbl,DDC_RGB_MODE  
        JZ      Not_RGB_mode                      
        AND     EAX,MM_ALL                                       ; The EGA has accel. bits
        SHL     EAX,2                           ; EAX = 4 * IPC
        MOV     EDI,EAX                         ; EDI = 4 * IPC
        MOV     EAX,adrgbIndex[EDI]                      ; EAX = RBG color 
                                                ;       corresponding to IPC
        JMP     Return_this_index                 

        ALIGN   4


Not_RGB_mode:

;/*
;** Locate the logical color table.
;*/

        MOV     ESI,[EBX].DDC.ddc_pClrTbl       ; ESI --> Color table
        TEST    BYTE ptr [EBX].DDC.ddc_fbClrTbl,DDC_LOG_CLR_TBL
        JZ      Dont_validate                     
        PUSH    EAX      
        MOV     EAX,[EBX].DDC.ddc_iSysClr                ; EAX = Index of current 
                                                ;       system color
        CMP     EAX,ddcInit.ddc_iSysClr           
        JE      @F       
        XCHG    EBX,ESI                         ; EBX --> Color table,
                                                ; ESI --> DDC
        INVOKE  PropagateSysClrChange             
        XCHG    EBX,ESI                         ; EBX --> DDC
                                                ; ESI --> Color table
@@:
        POP     EAX                             ; EAX = RGB color for IPC

Dont_validate:

;/*
;** Locate the IPC in the table.
;*/

        MOV     ECX,[ESI].COLOR_TABLE.ct_iMax
        INC     ECX                             ; ECX = Size of table
        LEA     EDI,[ESI]+ct_aipc                        ; EDI --> IPC array
        CLD      
  REPNZ SCASW    
        JZ      Found_a_match                     

;/*
;** Check for MONO bit match, if monochrome.
;*/

        MOV     EDI,[EBX].DDC.ddc_npsd                   ; EDI --> Surface definition
ifndef JFIX        ;IBMJ
        TEST    [EDI].SURFACE.sd_fb,SD_COLOR     ; No match if color
        JNZ     No_match_at_all                   
else  ;JFIX        ;IBMJ
;/*
;**            It is possible to come here without preparing bitmap handle.
;*/
 CMP EDI,INVALID_ADDRESS
 JE @F
        TEST    [EDI].SURFACE.sd_fb,SD_COLOR     ; No match if color
        JNZ     No_match_at_all                   
@@:
endif ;JFIX        ;IBMJ

;/*
;** Look for an ON bit.
;*/

        MOV     ECX,[ESI].COLOR_TABLE.ct_iMax     
        INC     ECX                             ; ECX = Size of table
        LEA     EDI,[ESI]+ct_aipc                        ; EDI --> IPC array
        MOV     EDX,EDI                         ; EDX --> IPC array
        TEST    EAX,MONO_BIT                      
        JZ      Look_for_OFF_loop                 

Look_for_ON_loop:
        ADD     EDX,2    
        TEST    WORD ptr [EDI],MONO_BIT
        MOV     EDI,EDX                         ; EDI --> Element in IPC array
        LOOPZ   Look_for_ON_loop                  
        JNZ     Found_a_match                     

No_match_at_all:
        MOV     EAX,CLR_NOINDEX                                  ; Indicate no index found
        JMP     Return_this_index                 

        ALIGN   4


;/*
;** Look for an OFF bit.
;*/

Look_for_OFF_loop:
        ADD     EDX,2    
        TEST    WORD ptr [EDI],MONO_BIT
        MOV     EDI,EDX  
        LOOPNZ  Look_for_OFF_loop                 
        JNZ     No_match_at_all                   

;/*
;** Calculate the index.
;*/

Found_a_match:
        SUB     EDI,ESI  
        SUB     EDI,ct_aipc + 2
        MOV     EAX,EDI                         ; EDI = 2 * index
        SHR     EAX,1                           ; EAX = Index

Return_this_index:

        RET

ipc_to_index ENDP

        END
