/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT (C) Lexmark 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.                                */
/*                                                                           */
/*****************************************************************************/
/**************************************************************************
 *
 * SOURCE FILE NAME = PRDCSUBR
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS  prdc_ColorDifference
 *            prdc_RGBtoPhysIndex
 *            prdc_RGBColorToPelBits
 *            prdc_RGBToColIndex
 *            prdc_RGBColorDiff
 *            prdc_PhysRGBColorToPelBits
 *            prdc_ColourToPelBits
 *            prdc_NegColourToPelBits
 *            prdc_ColorToRGBValue
 *
 * ENTRY POINTS:
 *
 * DEPENDENCIES:
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

#define INCL_32                         /* Convert to C/SET2    CON3201       */
#define INCL_DOSPROCESS                 /* Convert to C/SET2    CON3201       */
#define INCL_DOSSEMAPHORES
#define INCL_GPILOGCOLORTABLE
#define INCL_GPIERRORS
#define INCL_GPIPRIMITIVES
#define INCL_WINHEAP
#define INCL_GPIBITMAPS
#include <os2.h>
#undef INCL_DOSPROCESS                  /* Convert to C/SET2    CON3201       */
#undef INCL_DOSSEMAPHORES
#undef INCL_GPILOGCOLORTABLE
#undef INCL_GPIERRORS
#undef INCL_GPIPRIMITIVES
#undef INCL_WINHEAP
#undef INCL_GPIBITMAPS

#define INCL_DDIBUNDLES
#define INCL_DDIFONTSTRUCS
#define INCL_DDIDEFS
#include <pmddi.h>
#undef INCL_DDIBUNDLES
#undef INCL_DDIFONTSTRUCS
#undef INCL_DDIDEFS

#define INCL_WINP_SELECTIVE
#define INCL_WINP_SEI
#include <pmwinx.h>
#undef INCL_WINP_SELECTIVE
#undef INCL_WINP_SEI
#undef INCL_32                          /* Convert to C/SET2    CON3201       */

#include <prdacone.h>
#include <prdccone.h>
#include <prdconse.h>                   /* Convert to C/SET2    CON3201       */
#include <prddcone.h>

#define NO_SYS
#define NO_CONSTANT_INCL
#include <prdinclt.h>
#undef NO_CONSTANT_INCL
#undef NO_SYS

#include <prdcextf.h>

/******************************************************************************/
/*  A few externals...                                                        */
/******************************************************************************/
extern RGB2                   DVTHardwarePalette[8];               /* CON3201 */
extern DefaultColorTableType  DefaultColorTable[];
extern USHORT                 DRIVER_TYPE;

/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdc_ColorDifference                                   */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   ULONG     RGB1;   The two colours to calculate the difference    */
/*   ULONG     RGB2;   between                                        */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function determines the difference between two RGB values.  */
/*   It determines this as the square of the straight line distance   */
/*   between the two points the colours correspond to in RGB space.   */
/*                                                                    */
/**********************************************************************/
ULONG prdc_ColorDifference ( ULONG RGB_1,
                             ULONG RGB_2 )

{
#define TFUNC "prdc_ColorDifference"
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    USHORT      i;                     /* Loop control variable       */
    ULONG       lcColDiff;             /* Colour difference           */
    ULONG       lcColSum;              /* Colour difference sum       */

    /******************************************************************/
    /* For each of the R, G, and B pairs calculate the square of      */
    /* the difference and then sum.                                   */
    /******************************************************************/
    TRACE4(TFUNC, "First RGB value", &RGB_1, 1);
    TRACE4(TFUNC, "Other RGB value", &RGB_2, 1);

    lcColSum = 0 ;

    for (i = 0; i < 3; i++)
    {
        lcColDiff  = ( ULONG)(((PBYTE)&RGB_1)[i]);
        lcColDiff -= ( ULONG)(((PBYTE)&RGB_2)[i]);
        lcColSum  += lcColDiff * lcColDiff;
    }

    TRACE4(TFUNC, "Color Diff Sum", &lcColSum, 1);

    return(lcColSum);
}
#undef TFUNC



/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdc_RGBToPhysIndex                                    */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   ULONG        LogColor;    The logical colour to be matched       */
/*   lpDCI        DCIData;     Pointer to the DC Instance data        */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function returns the index (into the logical colour table)  */
/*   of the closest match to the given RGB colour which can the       */
/*   device can produce (basing its calculations on the physical      */
/*   colours given for each entry in the logical colour table).       */
/*                                                                    */
/**********************************************************************/
ULONG prdc_RGBToPhysIndex ( ULONG LogColor,
                            lpDCI DCIData )

{
#define TFUNC "prdc_RGBToPhysIndex"

    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    ULONG   lcDiff;                    /* Difference between two RGBs */
    ULONG   lcMinDiff;                 /* Minimum Difference to date  */
    USHORT  i;                         /* Loop variable               */
    ULONG   lcIndex;                   /* Best index to date          */
    ULONG   PhysColor;                 /* Physical colour from device */
                                       /* colour table                */

    /******************************************************************/
    /* Trace the input color ( LogColor is given in RGB terms )       */
    /******************************************************************/
    TRACE4(TFUNC, "Input Color", &LogColor, 1);

    /******************************************************************/
    /* If colour table format is RGB mode then return input RGB colour*/
    /* value.                                                         */
    /******************************************************************/
    if (DCIData->DCIColFormat == LCOLF_RGB)
    {
        TRACE4(TFUNC, "RGB Mode", FNULL, 0);
        return(LogColor);
    }

    /******************************************************************/
    /* Look through the logical colour table for the best match to    */
    /* the colour given.  An index is always found.                   */
    /* Note that the matching is done against the physical RGB colour */
    /* corresponding to each entry in the logical colour table.       */
    /******************************************************************/
    lcMinDiff = 0xFFFFFFFF;

    /******************************************************************/
    /* While there are still more entries in the logical colour table */
    /* and we have not found a perfect match try the next entry.      */
    /******************************************************************/
    for (i = 0; i < DCIData->DCIColTabSize && lcMinDiff != 0; i++)
    {
        if ((PhysColor = DCIData->DCIColorTable[i].PhysRGB) !=
                                                            0xFFFFFFFFL)
        {
            /**********************************************************/
            /* If the colour is a valid one check and see whether it  */
            /* is closer to LogColor than the current closest match.  */
            /**********************************************************/
            lcDiff = prdc_ColorDifference (LogColor, PhysColor);
            if (lcDiff < lcMinDiff)
            {
                lcMinDiff = lcDiff;
                lcIndex   = i;
            }
        }
    }
    /*.. for (i = 0; i < DCIData->DCIColTabSize...haven't found match.*/

    TRACE4(TFUNC, "lcMinDiff", &lcMinDiff, 1);
    TRACE4(TFUNC, "Return Index", &lcIndex, 1);

    /******************************************************************/
    /* Return the index into the logical colour table corresponding   */
    /* to the closest match.                                          */
    /******************************************************************/
    return(lcIndex);
}
#undef TFUNC



/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdc_RGBColorToPelBits                                 */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   ULONG             RGBColor;   RGB value of required colour       */
/*   lpDVTColorTable   DCTab;      Pointer to device colour table to  */
/*                                 use                                */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function returns the index to the entry in the device       */
/*   colour table which is the closest match to RGBColor.             */
/*                                                                    */
/**********************************************************************/
BYTE prdc_RGBColorToPelBits ( ULONG             RGBColor,
                              lpDVTColorTable   DCTab )

{
#define TFUNC "prdc_RGBColorToPelBits"
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    USHORT  i;                         /* Loop variable               */
    ULONG   lcDiff;                    /* Difference between two RGBs */
    ULONG   lcMinDiff;                 /* Minimum Difference to date  */
    ULONG   lcIndex;                   /* Best index to date          */

    /******************************************************************/
    /* Trace the input color ( RGBColor is given in RGB terms )       */
    /******************************************************************/

    TRACE8(TFUNC, "Input Color", &RGBColor, 1);

    /******************************************************************/
    /* Look through DeviceColorTable for best match. A match is       */
    /* always found.                                                  */
    /******************************************************************/
    lcMinDiff = 0xFFFFFFFF;

    /******************************************************************/
    /* While there are still more entries in the the colour table and */
    /* we have not found a perfect match then try the next entry.     */
    /******************************************************************/
    for (i = 0; i < DCTab->ColorNum && lcMinDiff != 0; i++)
    {
        TRACE4(TFUNC, "i", &i, 1);
        /**************************************************************/
        /* Check whether this entry is closest so far to RGBColor.    */
        /* Note that all entries in a device colour table will be     */
        /* valid RGB values.                                          */
        /**************************************************************/
        lcDiff = prdc_ColorDifference (RGBColor, DCTab->Colors[i]);
        if (lcDiff < lcMinDiff)
        {
            lcMinDiff = lcDiff;
            lcIndex   = i;
        }
    }
    /*.. for (i = 0; i < DCTab->ColorNum...haven't found match........*/

    TRACE8(TFUNC, "Return Bit", &lcIndex, 1);

    /******************************************************************/
    /* Return the index into the device colour table of the closest   */
    /* match found.                                                   */
    /******************************************************************/
    return((BYTE) lcIndex);
}
#undef TFUNC

 /**********************************************************************/
 /*                                                                    */
 /*   FUNCTION: prdc_RGBToColIndex                                     */
 /*                                                                    */
 /*   PARAMETERS:                                                      */
 /*                                                                    */
 /*   RGB far *         RGBColor;   RGB value of required colour       */
 /*                                                                    */
 /*   DESCRIPTION:                                                     */
 /*                                                                    */
 /*   This function returns the index to the entry in                  */
 /*   DVTHardwarePalette which is the closest match to RGBColor        */
 /*   This is essentially the same routine as prdc_RGBColorToPelBits   */
 /*   but it deals with PM defined RGB structures, not our internal    */
 /*   ULONG format, and it always uses the same colour table.          */
 /*   Currently only used in bitmap conversions, it might also be      */
 /*   useful in other areas which use RGBs.                            */
 /*                                                                    */
 /**********************************************************************/
 BYTE prdc_RGBToColIndex (RGB2 * RGBColor)                  /* CON3201 */

 {
 #define TFUNC "prdc_RGBToColIndex"
     /******************************************************************/
     /* Local variables                                                */
     /******************************************************************/
     USHORT  i;                         /* Loop variable               */
     ULONG   lcDiff;                    /* Difference between two RGBs */
     ULONG   lcMinDiff;                 /* Minimum Difference to date  */
     ULONG   lcIndex;                   /* Best index to date          */

     /******************************************************************/
     /* Look through DVTHardwarePalette for best match. A match is     */
     /* always found.                                                  */
     /******************************************************************/
     lcMinDiff = 0xFFFFFFFF;

     /******************************************************************/
     /* While there are still more entries in the the colour table and */
     /* we have not found a perfect match then try the next entry.     */
     /******************************************************************/
     for (i = 0; i < 8 && lcMinDiff != 0; i++)
     {
         /**************************************************************/
         /* Check whether this entry is closest so far to RGBColor.    */
         /**************************************************************/
         lcDiff = prdc_RGBColorDiff (RGBColor, &DVTHardwarePalette[i]);
         if (lcDiff < lcMinDiff)
         {
             lcMinDiff = lcDiff;
             lcIndex   = i;
         }
     }
     /*.. for (i = 0; i < DCTab->ColorNum...haven't found match........*/

     /******************************************************************/
     /* Return the index into the device colour table of the closest   */
     /* match found.                                                   */
     /******************************************************************/
     return((BYTE) lcIndex);
 }
 #undef TFUNC


/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdc_RGBColorDiff                                      */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   RGB far * RGB1;   The two colours to calculate the difference    */
/*   RGB far * RGB2;   between                                        */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function determines the difference between two RGB values.  */
/*   It determines this as the square of the straight line distance   */
/*   between the two points the colours correspond to in RGB space.   */
/*   This routine is basically identical to prdc_ColorDifference      */
/*   except that is uses PM defined RGB structures instead of internal*/
/*   format ULONG RGBs.                                               */
/*                                                                    */
/**********************************************************************/
ULONG prdc_RGBColorDiff( RGB2 *RGB_1,                       /* CON3201 */
                         RGB2 *RGB_2 )                      /* CON3201 */

{
#define TFUNC "prdc_RGBColorDiff"
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    USHORT      i;                     /* Loop control variable       */
    ULONG       lcColDiff;             /* Colour difference           */
    ULONG       lcColSum;              /* Colour difference sum       */

    /******************************************************************/
    /* For each of the R, G, and B pairs calculate the square of      */
    /* the difference and then sum. The bytes are stored in order     */
    /* B, G , R in an RGB struct.                                     */
    /******************************************************************/
    TRACE4(TFUNC, "First RGB value", RGB_1, 1);
    TRACE4(TFUNC, "Other RGB value", RGB_2, 1);

    lcColSum = 0 ;

    for (i = 0; i < 3; i++)
    {
        lcColDiff  = (ULONG) (((PBYTE) RGB_1)[i]);
        lcColDiff -= (ULONG) (((PBYTE) RGB_2)[i]);
        lcColSum  += lcColDiff * lcColDiff;
    }

    TRACE4(TFUNC, "Color Diff Sum", &lcColSum, 1);

    return(lcColSum);
}
#undef TFUNC

/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdc_PhysRGBColorToPelBits                             */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   ULONG             PhysRGBColor;   RGB value of required colour   */
/*   lpDVTColorTable   DCTab;          Pointer to device colour table */
/*                                     to use                         */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function searches the colour table for an exact match to    */
/*   PhysRGBColor and returns the index if a match is found.  If no   */
/*   match is found then it returns ERROR_NEG.                        */
/*                                                                    */
/**********************************************************************/
BYTE prdc_PhysRGBColorToPelBits ( ULONG             PhysRGBColor,
                                  lpDVTColorTable   DCTab )

{
#define TFUNC "prdc_PhysRGBColorToPelBits"

    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    USHORT  i;                         /* Loop variable               */
    BYTE    DCTabIndex;                /* Best index to date          */

    /******************************************************************/
    /* Trace the input color                                          */
    /******************************************************************/
    TRACE8(TFUNC, "Input Color", &PhysRGBColor, 1);


    /******************************************************************/
    /* Assume no match                                                */
    /******************************************************************/
    DCTabIndex = (BYTE)ERROR_NEG;

    /******************************************************************/
    /* For each entry in the device colour table.                     */
    /******************************************************************/
    for ( i = 0; i < DCTab->ColorNum; i++ )
    {
        /**************************************************************/
        /* If a match has been found then return it.                  */
        /**************************************************************/
        if ( PhysRGBColor == DCTab->Colors[i] )
        {
            DCTabIndex = (BYTE)i;
            break;
        }
    }

    /******************************************************************/
    /* Return the index into the device colour table                  */
    /******************************************************************/
    return (DCTabIndex);

}
#undef TFUNC






/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdc_ColorToPelBits                                    */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   ULONG            Color;   RGB value, index to logical colour     */
/*                             table or negative colour index         */
/*   lpDCI            DCIData; Pointer to DC Instance data            */
/*   lpDVTColorTable  DCTab;   Pointer to device colour table to use  */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function returns an index to the device colour table for    */
/*   the entry which corresponds (or is closest) to the input colour  */
/*   which may be an RGB value, a positive index into a logical       */
/*   colour table or a negative index (dealt with by                  */
/*   prdc_NegColorToPelBits).                                         */
/*                                                                    */
/*   CHANGES:                                                         */
/*                                                                    */
/*   For colour devices the mapping here will have to be changed. In  */
/*   the case where an RGB colour is provided a nearest match will    */
/*   have to be found allowing for the fact that we do not want to    */
/*   map two distinct colours to the background (index 0) colour.     */
/*   The same will have to be done for indexes into the logical colour*/
/*   table.                                                           */
/*                                                                    */
/**********************************************************************/
BYTE prdc_ColorToPelBits ( ULONG           Color,
                           lpDCI           DCIData,
                           lpDVTColorTable DCTab )

{
#define TFUNC "prdc_ColorToPelBits"

    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    BYTE             DCTabIndex;       /* Index to Device Color Table */
    lpDDTType        pDDT;             /* DDT Pointer                 */

    /******************************************************************/
    /* Trace Arguments                                                */
    /******************************************************************/
    TRACE8(TFUNC, "ENTRY: Color", &Color, 1);

    /******************************************************************/
    /* Find DDT                                                       */
    /******************************************************************/
    pDDT = &DCIData->DCIPdbInstance->DDT;

    /**************************************************************************/
    /*  PD00567 : If this is our special driver, let's go somewhere else      */
    /*  instead...                                                            */
    /**************************************************************************/
    if (!((DRIVER_TYPE == DDT_IBM42XX_DRV) &&
          (DCIData->DCIPdbInstance->PrinterType == IBM_4224_COLOR)))
    {
        return(prdc_GreyColorToPelBits(Color, DCIData, DCTab));
    }

    /******************************************************************/
    /* If the Color is a negative index then pass the call to         */
    /* prdc_NegColorToPelBits for processing.                         */
    /******************************************************************/
    if ( (LONG)Color < (LONG)0 )
    {
        TRACE6(TFUNC, "Neg Color Mode", FNULL, 0);

        DCTabIndex = prdc_NegColorToPelBits( (LONG)Color,
                                              DCIData,
                                              DCTab );
    }

    /******************************************************************/
    /* Else if Colour Format is RGB mode then look up nearest colour  */
    /* in Device Color Table                                          */
    /******************************************************************/
    else if ( DCIData->DCIColFormat == LCOLF_RGB )
    {
        TRACE6(TFUNC, "RGB Mode", FNULL, 0);

        if( pDDT->DDTMaxColors == DDT_TWO_COLORS )
        {
            /**********************************************************/
            /* If the RGB value matches white (i.e. CLR_BACKGROUND)   */
            /* use white; else use black.                             */
            /**********************************************************/
            if ( Color == DCTab->Colors[PRD_BACKGROUND] )   /* white  */
                DCTabIndex = PRD_BACKGROUND;                /*   1    */
            else
                DCTabIndex = PRD_FOREGROUND;                /*   0    */
        }
        else if ( pDDT->DDTMaxColors == DDT_EIGHT_COLORS )
        {
           DCTabIndex = prdc_RGBColorToPelBits(Color, DCTab);
        }
    }
    /*.. else if ( DCIData->DCIColFormat == LCOLF_RGB ) ..............*/

    /******************************************************************/
    /* The color must be an index into a loadable (or the default)    */
    /* color table.  Check first that the index is valid.             */
    /******************************************************************/
    else
    {
        if ( (Color >= DCIData->DCIColTabSize) ||
             (DCIData->DCIColorTable[Color].LogRGB == 0xFFFFFFFF) )
        {
            LOGERR(TFUNC, "Invalid Index Color", &Color,
                                           1, PMERR_INV_COLOR_INDEX);
            return ((BYTE)ERROR_NEG);
        }

        if ( pDDT->DDTMaxColors == DDT_TWO_COLORS )
        {
            /**********************************************************/
            /* If the RGB value matches white (i.e. CLR_BACKGROUND)   */
            /* use white; else use black.                             */
            /**********************************************************/
            if ( DCIData->DCIColorTable[Color].LogRGB == 0x00FFFFFF )
                DCTabIndex = PRD_BACKGROUND;                /*   1    */
            else
                DCTabIndex = PRD_FOREGROUND;                /*   0    */
        }
        else if ( pDDT->DDTMaxColors == DDT_EIGHT_COLORS )
        {
           DCTabIndex = prdc_PhysRGBColorToPelBits(
                                DCIData->DCIColorTable[Color].PhysRGB,
                                DCTab );
        }
    }
    /*.. else else ! ( DCIData->DCIColFormat == LCOLF_RGB ) ..........*/

    /******************************************************************/
    /* Return Index into Device Color Table corresponding to Color    */
    /******************************************************************/
    return (DCTabIndex);
}
#undef TFUNC





/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdc_NegColorToPelBits                                 */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   LONG             NegColor;    Negative colour index              */
/*   lpDCI            DCIData;     Pointer to DC Instance data        */
/*   lpDVTColorTable  DCTab;       Pointer to device colour table to  */
/*                                 use                                */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function handles negative colour indexes which have special */
/*   meanings.                                                        */
/*                                                                    */
/*   CHANGES:                                                         */
/*                                                                    */
/*   For a colour printer this function will have to be altered so    */
/*   that -7 and -8 map to black and white physical colours           */
/*   respectively.                                                    */
/*                                                                    */
/**********************************************************************/
BYTE prdc_NegColorToPelBits ( LONG            NegColor,
                              lpDCI           DCIData,
                              lpDVTColorTable DCTab )

{
#define TFUNC "prdc_NegColorToPelBits"

    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    BYTE             DCTabIndex;       /* Index to Device Color Table */


    /******************************************************************/
    /* Trace Arguments                                                */
    /******************************************************************/
    TRACE8(TFUNC, "Color", &NegColor, 1);

    /******************************************************************/
    /* If this is one of the special negative default indices then    */
    /* interpret it as one of the negative indices known to the       */
    /* system.                                                        */
    /******************************************************************/
    switch ( (SHORT)NegColor )
    {
        case (SHORT)DEFAULT_FOREGROUND_COL:
        case (SHORT)DEFAULT_BACKGROUND_COL:
            NegColor = prdc_InterpretDfltColor(NegColor, DCIData);
            break;

        default :
            break;
    }
    /*.. switch (NegColor) ...........................................*/


    /******************************************************************/
    /* OK now establish index into device colour table for the given  */
    /* negative colour index.                                         */
    /******************************************************************/
    switch ( (SHORT)NegColor )
    {
        case (SHORT)CLR_BLACK:
            DCTabIndex = prdc_PhysRGBColorToPelBits(RGB_BLACK, DCTab);
            break;

        case (SHORT)CLR_WHITE:
            DCTabIndex = prdc_PhysRGBColorToPelBits(RGB_WHITE, DCTab);
            break;

        case (SHORT)CLR_TRUE:
            /**********************************************************/
            /* All pel bits are one - i.e. color is last device       */
            /* color.                                                 */
            /**********************************************************/
            DCTabIndex = (BYTE)(DCTab->ColorNum - 1);
            break;

        case (SHORT)CLR_FALSE:
            /**********************************************************/
            /* All pel bits are zero - i.e. color is first device     */
            /* color.                                                 */
            /**********************************************************/
            DCTabIndex = (BYTE)0;
            break;

        default :
            /**********************************************************/
            /* Log an error.                                          */
            /**********************************************************/
            LOGERR(TFUNC, "Invalid Neg Color", FNULL, 0,
                                                PMERR_INV_COLOR_INDEX);
            return ((BYTE)ERROR_NEG);
            break;
    }
    /*.. switch (NegColor) ...........................................*/


    /******************************************************************/
    /* Return the index to the device colour table                    */
    /******************************************************************/
    return (DCTabIndex);

}
#undef TFUNC






/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdc_InterpretDfltColor                                */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   LONG             NegColor;    Negative colour index              */
/*   lpDCI            DCIData;     Pointer to DC Instance data        */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function handles the special default negative colour        */
/*   indices.  It should only be called with NegColor set to either   */
/*   DEFAULT_FOREGROUND_COL or DEFAULT_BACKGROUND_COL.                */
/*                                                                    */
/*   Foreground is black; background is white.                        */
/*                                                                    */
/**********************************************************************/
LONG prdc_InterpretDfltColor ( LONG  NegColor,
                               lpDCI DCIData )

{
#define TFUNC "prdc_IntDfltCol"

    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    lpDDTType        pDDT;             /* DDT Pointer                 */
    pBMListEntry     ListEntry;        /* Bitmap list entry pointer   */
    LONG             ReturnColor;


    /******************************************************************/
    /* Check whether we've got a Monochrome Memory Bitmap/DC or not.  */
    /******************************************************************/
    ListEntry = (pBMListEntry)DCIData->DCISelBitmap;
    pDDT      = &DCIData->DCIPdbInstance->DDT;

    /******************************************************************/
    /* Set up the color to return.                                    */
    /******************************************************************/
    switch ( (SHORT)NegColor )
    {
        case (SHORT)DEFAULT_FOREGROUND_COL:
            ReturnColor = CLR_BLACK;
            break;

        case (SHORT)DEFAULT_BACKGROUND_COL:
            ReturnColor = CLR_WHITE;
            break;
    }
    /*.. switch (NegColor) ...........................................*/


    return (ReturnColor);

}
#undef TFUNC






/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdc_GetSystemColor                                    */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   LONG          DriverColor;    Color from attribute bundle        */
/*   lpDCI         DCIData;        Pointer to DC Instance data        */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function handles the special default negative colour        */
/*   indices.  If the driver color is DEFAULT_FOREGROUND_COL          */
/*   or DEFAULT_BACKGROUND_COL (which are special values              */
/*   known only to the driver) they are interpretted and returned     */
/*   as negative color indices known to the system.                   */
/*                                                                    */
/*   This is function is called from prda_DeviceGetAttributes.        */
/*                                                                    */
/**********************************************************************/
LONG prdc_GetSystemColor ( LONG  DriverColor,
                           lpDCI DCIData )

{
#define TFUNC "prdc_GetSysCol"

    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    LONG             SystemColor;

    if ( (DriverColor == DEFAULT_FOREGROUND_COL) ||
         (DriverColor == DEFAULT_BACKGROUND_COL) )
    {
        SystemColor = prdc_InterpretDfltColor( DriverColor,
                                               DCIData );
    }
    else
    {
        SystemColor = DriverColor;
    }

    return (SystemColor);

}
#undef TFUNC

/******************************************************************************/
/*  FUNCTION: prdc_ColorToRGBValue                                            */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  ULONG  Color;    RGB value, index to logical color table or negative      */
/*                   color index                                              */
/*  lpDCI  DCIData;  Pointer to DC Instance data                              */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function returns an RGB value based upon the color parameter, which  */
/*  may be itself an RGB value, a system negative value or a positive index   */
/*  into a logical color table.                                               */
/******************************************************************************/
ULONG prdc_ColorToRGBValue ( ULONG  Color,
                             lpDCI  DCIData )

{

    /**************************************************************************/
    /*  Local variables                                                       */
    /**************************************************************************/
    ULONG  RGBValue;                   /* RGB return value                    */
    LONG   NegColor;                   /* Negative color                      */

    /**************************************************************************/
    /*  If the Color is a negative index then let's handle it here.           */
    /**************************************************************************/
    if ((LONG)Color < (LONG)0)
    {
        NegColor = Color;
        switch ((SHORT)NegColor)
        {
            case (SHORT)DEFAULT_FOREGROUND_COL : NegColor = CLR_BLACK;
                                                 break;
            case (SHORT)DEFAULT_BACKGROUND_COL : NegColor = CLR_WHITE;
                                                 break;
            default                            : break;
        }

        /**********************************************************************/
        /*  OK, now that the negative index has been resolved to a 'real'     */
        /*  color, let's convert to an RGB value.                             */
        /**********************************************************************/
        switch ((SHORT)NegColor)
        {
            case (SHORT)CLR_BLACK :
            case (SHORT)CLR_FALSE : RGBValue = RGB_BLACK;
                                    break;
            case (SHORT)CLR_TRUE  :
            case (SHORT)CLR_WHITE : RGBValue = RGB_WHITE;
                                    break;
            default               : break;
        }
    }
    else
    {

        /**********************************************************************/
        /*  Else if Color Format is RGB mode then we have the RGB value.      */
        /**********************************************************************/
        if (DCIData->DCIColFormat == LCOLF_RGB)
            RGBValue = Color;
        else

            /******************************************************************/
            /*  The color must be an index into a loadable (or the default)   */
            /*  color table.                                                  */
            /******************************************************************/
            RGBValue = DCIData->DCIColorTable[Color].LogRGB;
    }

    /**************************************************************************/
    /*  Return the RGB value                                                  */
    /**************************************************************************/
    return(RGBValue);
}

/******************************************************************************/
/*  FUNCTION: prdc_RGBToCLRIndex                                              */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  RGB far *  RGBColor;  RGB value of required color                         */
/*  lpDCI      DCIData;   Pointer to DC Instance data                         */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function returns the index to the entry in DefaultColorTable which   */
/*  is the closest match to RGBColor.  This is essentially the same routine   */
/*  as prdc_RGBToColIndex but it deals with PM defined RGB structures, not    */
/*  our internal ULONG format, and it always uses the same colour table.      */
/*  Currently only used in bitmap conversions, it might also be useful in     */
/*  other areas which use RGBs.                                               */
/******************************************************************************/
ULONG prdc_RGBToCLRIndex ( RGB2  *RGBColor,                         /* CON3201 */
                           lpDCI  DCIData )

{
#define TFUNC "prdc_RGBToCLRIndex"

    /**************************************************************************/
    /*  Local variables                                                       */
    /**************************************************************************/
    USHORT     i;                      /* Loop variable                       */
    ULONG      lcDiff;                 /* Difference between two RGBs         */
    ULONG      lcMinDiff;              /* Minimum Difference to date          */
    ULONG      lcIndex;                /* Best index to date                  */

    /**************************************************************************/
    /*  First let's see if we're in RGB mode - if we are, then the index they */
    /*  just gave us is indeed an RGB value.                                  */
    /**************************************************************************/
    if (DCIData->DCIColFormat == LCOLF_RGB)
    {
        lcIndex = RGBTOUL(RGBColor);
    }
    else
    {

        /**********************************************************************/
        /*  We've got a logical color table (perhaps the default) floating    */
        /*  about that we need to look at.  First, initialize the minimum     */
        /*  difference variable to a huge value so we can whittle the value   */
        /*  to the least difference, which will indicate we've found the      */
        /*  closest match for the value passed in.                            */
        /**********************************************************************/
        lcMinDiff = 0xFFFFFFFF;

        /**********************************************************************/
        /*  While there are still more entries in the color table and we have */
        /*  not found a perfect match then try the next entry.                */
        /**********************************************************************/
        for (i = DCIData->DCILowIndex; i <= DCIData->DCIHighIndex &&
                                       lcMinDiff != 0; i++)
        {

            /******************************************************************/
            /*  Check whether this entry is closest so far to RGBColor.       */
            /******************************************************************/
            lcDiff = prdc_RGBColorDiff(RGBColor,
                                     ULTORGB(DCIData->DCIColorTable[i].LogRGB));
            if (lcDiff < lcMinDiff)
            {
                lcMinDiff = lcDiff;
                lcIndex   = i;
            }
        }
    }

    /**************************************************************************/
    /*  Return the index into the device color table of the closest match     */
    /*  found.                                                                */
    /**************************************************************************/
    return(lcIndex);
}
#undef TFUNC

/******************************************************************************/
/*  FUNCTION: prdc_GreyColorToPelBits                                         */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  ULONG            Color    RGB value, index to logical color               */
/*                            table or negative color index                   */
/*  lpDCI            DCIData  Pointer to DC Instance data                     */
/*  lpDVTColorTable  DCTab    Pointer to device color table to use            */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function returns an index to the device color table for the entry    */
/*  which corresponds (or is closest) to the input color which may be an RGB  */
/*  value, a positive index into a logical color table or a negative index    */
/*  (dealt with by prdc_NegColorToPelBits).                                   */
/*                                                                            */
/*  Note that the difference between this function and prdc_ColorToPelBits()  */
/*  above is that the assumption here is that the printer driver is capable of*/
/*  greyscaling source bitmaps.  This fouls things up when we attempt to use  */
/*  the existing color functions as the existing functions assume that the    */
/*  pDDT->DDTMaxColors value must be used to differentiate between the color  */
/*  tables that we need to access.  In the case of the drivers capable of     */
/*  greyscaling source bitmaps, we must report internally a value of 8 rather */
/*  than 2 for this DDT value, though we require the color table information  */
/*  as if we reported a value of 2.  So, we have to fudge things a bit here to*/
/*  get things like the pattern copy mode correct within the polyscanline     */
/*  code.                                                                     */
/******************************************************************************/
BYTE prdc_GreyColorToPelBits( ULONG            Color,
                              lpDCI            DCIData,
                              lpDVTColorTable  DCTab )

{

#define TFUNC "prdc_GreyColorToPelBits"

    /**************************************************************************/
    /*  Local variables                                                       */
    /**************************************************************************/
    BYTE       DCTabIndex;             /* Index to Device Color Table         */
    lpDDTType  pDDT;                   /* DDT Pointer                         */

    /**************************************************************************/
    /*  Trace Arguments                                                       */
    /**************************************************************************/
    TRACE8(TFUNC, "ENTRY: Color", &Color, 1);

    /**************************************************************************/
    /*  Find DDT                                                              */
    /**************************************************************************/
    pDDT = &DCIData->DCIPdbInstance->DDT;

    /**************************************************************************/
    /*  If Color is negative then pass the call to prdc_NegColorToPelBits for */
    /*  processing.                                                           */
    /**************************************************************************/
    if ((LONG)Color < (LONG)0)
    {
        TRACE6(TFUNC, "Neg Color Mode", FNULL, 0);
        DCTabIndex = prdc_NegColorToPelBits((LONG)Color, DCIData, DCTab);
    }
    else
    {

        /**********************************************************************/
        /*  if color format is RGB mode then look up nearest color in Device  */
        /*  Color Table                                                       */
        /**********************************************************************/
        if (DCIData->DCIColFormat == LCOLF_RGB)
        {
            TRACE6(TFUNC, "RGB Mode", FNULL, 0);

            /******************************************************************/
            /*  If the RGB value matches white (i.e. CLR_BACKGROUND) use      */
            /*  white; else use black.                                        */
            /******************************************************************/
            if (Color == DCTab->Colors[PRD_BACKGROUND])
            {
                DCTabIndex = PRD_BACKGROUND;
            }
            else
            {
                DCTabIndex = PRD_FOREGROUND;
            }
        }
        else
        {

            /******************************************************************/
            /*  The color must be an index into a loadable (or the default)   */
            /*  color table.  Check first that the index is valid.            */
            /******************************************************************/
            if ((Color >= DCIData->DCIColTabSize) ||
                (DCIData->DCIColorTable[Color].LogRGB == 0xFFFFFFFF))
            {
                LOGERR(TFUNC, "Invalid Index Color", &Color, 1,
                       PMERR_INV_COLOR_INDEX);
                return((BYTE)ERROR_NEG);
            }

            /******************************************************************/
            /*  If the RGB value matches white (i.e.  CLR_BACKGROUND) use     */
            /*  white; else use black.                                        */
            /******************************************************************/
            if (DCIData->DCIColorTable[Color].LogRGB == 0x00FFFFFF)
            {
                DCTabIndex = PRD_BACKGROUND;
            }
            else
            {
                DCTabIndex = PRD_FOREGROUND;
            }
        }
    }

    /**************************************************************************/
    /*  Return Index into Device Color Table corresponding to Color           */
    /**************************************************************************/
    return(DCTabIndex);
}
#undef TFUNC
