/*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.                                */
/*                                                                           */
/*****************************************************************************/
/**********************************************************************/
/*                                                                    */
/*   Module          = FUDGEPAL.C                                     */
/*                                                                    */
/*   Description     = Routines to calculate mappings and reorganise  */
/*                     the 5 default palettes to put the              */
/*                     system colors in the right place for seamless. */
/*                                                                    */
/*   Reference       = Winthorn Functional Specification              */
/*                     Device Driver Interface Specification          */
/*                     Display Device Driver Design Specification     */
/*                                                                    */
/*                                                                    */
/**********************************************************************/
#define INCL_WINSYS
#define INCL_DDIMISC
#define INCL_DOSDEVICES
#define INCL_DOSERRORS
#include <eddinclt.h>

#include <eddccone.h>
#include <edddtypt.h>

#include <eddcextf.h>
#include <eddgextf.h>

#include <fudgepal.h>


extern DDTType          DDT;

extern RGB2             FullSizeDeviceDefaultPalette[256];
extern RGB2             Reduced128DeviceDefaultPalette[128];
extern RGB2             Reduced64DeviceDefaultPalette[64];
extern RGB2             Reduced32DeviceDefaultPalette[32];
extern RGB2             Reduced16DeviceDefaultPalette[16];

extern COLORTABLETYPE   DefaultFourBppTable[DFLT_LOG_COL_TABLE_SIZE];
extern COLORTABLETYPE   DefaultEightBppTable16[DFLT_LOG_COL_TABLE_SIZE];
extern COLORTABLETYPE   DefaultEightBppTable32[DFLT_LOG_COL_TABLE_SIZE];
extern COLORTABLETYPE   DefaultEightBppTable64[DFLT_LOG_COL_TABLE_SIZE];
extern COLORTABLETYPE   DefaultEightBppTable128[DFLT_LOG_COL_TABLE_SIZE];
extern COLORTABLETYPE   DefaultEightBppTable256[DFLT_LOG_COL_TABLE_SIZE];
extern COLORTABLETYPE   DefaultSixteenBppTable[DFLT_LOG_COL_TABLE_SIZE];

extern COLORTABLETYPE   DirectSpecialColorTable[];
extern COLORTABLETYPE   MemorySpecialColorTable[];

extern BYTE             ColorPat[DITHMATRIX_XSIZE][DITHMATRIX_YSIZE];
#ifndef   _8514
extern XGAINSTANCE      InstanceData;
extern MODEDATAINFO     DMQSModesInfo;
extern HFILE            ring0_handle;
#endif

BYTE    PaletteFudgeTable256[256];
BYTE    PaletteFudgeTable128[128];
BYTE    PaletteFudgeTable64[64];
BYTE    PaletteFudgeTable32[32];
BYTE    PaletteFudgeTable16[16];


ULONG   WindowsDefaultSysColors[20]={
        0x80000000,     /* Black   */
        0x80800000,     /* Red     */
        0x80008000,     /* Green   */
        0x80808000,     /* Yellow  */

        0x80000080,     /* Blue    */
        0x80800080,     /* Magenta */
        0x80008080,     /* Cyan    */
        0x80C0C0C0,     /* Grey    */

        0x80C0DCC0,     /* These are the 4 wierd window 3.1 colors */
        0x80A6CAF0,
        0x80FFFBF0,
        0x80A0A0A4,

        0x80808080,
        0x80FF0000,
        0x8000FF00,
        0x80FFFF00,

        0x800000FF,
        0x80FF00FF,
        0x8000FFFF,
        0x80FFFFFF,     /* White   */

        };


ULONG NearestPaletteEntry(RGB2 RGBColor, PRGB2 Palette, ULONG ulSize)
{
    ULONG   i;
    ULONG   ulBestDiff;
    ULONG   ulNearestIndex;
    ULONG   ulThisDiff;

    ulBestDiff=0xFFFFFFFF;

    for (i=0; i<ulSize; i++)
    {
        ulThisDiff = rgb2_diff(RGBColor, Palette[i]);
        if (ulThisDiff < ulBestDiff)
        {
            ulBestDiff = ulThisDiff;
            ulNearestIndex = i;
        }
    }

    return(ulNearestIndex);
}


VOID FudgePaletteAndGenerateTable(PRGB2 Palette, PBYTE Table, ULONG ulSize)
{
    BYTE    InverseTable[256];
    ULONG   i;
    BYTE    bNearestIndex;
    BYTE    bIndexSwap;
    RGB2    RGBSwap;

    /******************************************************************/
    /* First set up a linear mapping table so that we can call our    */
    /* nearest match color routines for the non-fudged palette.       */
    /******************************************************************/
    for (i=0; i<ulSize; i++)
    {
        Table[i] = (BYTE)i;
        InverseTable[i] = (BYTE)i;
    }

    for (i=0; i<8; i++)
    {
        bNearestIndex = (BYTE)(NearestPaletteEntry(
                            *((PRGB2)&WindowsDefaultSysColors[i]),
                            &Palette[i],
                            ulSize-i)+i);

        /**************************************************************/
        /* Convert from 0..256 range to 0..ulSize.                    */
        /**************************************************************/
        if (bNearestIndex>=128)
        {
            bNearestIndex = (BYTE)(bNearestIndex-256+ulSize);
        }

        RGBSwap = Palette[i];
        Palette[i] = Palette[bNearestIndex];
        Palette[bNearestIndex] = RGBSwap;
        bIndexSwap = InverseTable[i];
        InverseTable[i] = InverseTable[bNearestIndex];
        InverseTable[bNearestIndex] = bIndexSwap;
        Table[InverseTable[i]]=(BYTE)i;
        Table[InverseTable[bNearestIndex]]=bNearestIndex;
    }

    for (i=19; i>11; i--)
    {
        bNearestIndex = (BYTE)(NearestPaletteEntry(
                            *((PRGB2)&WindowsDefaultSysColors[i]),
                            &Palette[8],
                            ulSize-27+i)+8);

        /**************************************************************/
        /* Convert from 0..256 range to 0..ulSize.                    */
        /**************************************************************/
        if (bNearestIndex>=128)
        {
            bNearestIndex = (BYTE)(bNearestIndex-256+ulSize);
        }

        RGBSwap = Palette[ulSize-20+i];
        Palette[ulSize-20+i] = Palette[bNearestIndex];
        Palette[bNearestIndex] = RGBSwap;
        bIndexSwap = InverseTable[ulSize-20+i];
        InverseTable[ulSize-20+i] = InverseTable[bNearestIndex];
        InverseTable[bNearestIndex] = bIndexSwap;
        Table[InverseTable[ulSize-20+i]]=(BYTE)(ulSize-20+i);
        Table[InverseTable[bNearestIndex]]=bNearestIndex;
    }

    if (ulSize>16)
    {
        for (i=8; i<10; i++)
        {
            bNearestIndex = (BYTE)(NearestPaletteEntry(
                                *((PRGB2)&WindowsDefaultSysColors[i]),
                                &Palette[i],
                                ulSize-i)+i);

            /**************************************************************/
            /* Convert from 0..256 range to 0..ulSize.                    */
            /**************************************************************/
            if (bNearestIndex>=128)
            {
                bNearestIndex = (BYTE)(bNearestIndex-256+ulSize);
            }

            RGBSwap = Palette[i];
            Palette[i] = Palette[bNearestIndex];
            Palette[bNearestIndex] = RGBSwap;
            bIndexSwap = InverseTable[i];
            InverseTable[i] = InverseTable[bNearestIndex];
            InverseTable[bNearestIndex] = bIndexSwap;
            Table[InverseTable[i]]=(BYTE)i;
            Table[InverseTable[bNearestIndex]]=bNearestIndex;
        }

        for (i=11; i>9; i--)
        {
            bNearestIndex = (BYTE)(NearestPaletteEntry(
                                *((PRGB2)&WindowsDefaultSysColors[i]),
                                &Palette[10],
                                ulSize-27+i)+10);

            /**************************************************************/
            /* Convert from 0..256 range to 0..ulSize.                    */
            /**************************************************************/
            if (bNearestIndex>=128)
            {
                bNearestIndex = (BYTE)(bNearestIndex-256+ulSize);
            }

            RGBSwap = Palette[ulSize-20+i];
            Palette[ulSize-20+i] = Palette[bNearestIndex];
            Palette[bNearestIndex] = RGBSwap;
            bIndexSwap = InverseTable[ulSize-20+i];
            InverseTable[ulSize-20+i] = InverseTable[bNearestIndex];
            InverseTable[bNearestIndex] = bIndexSwap;
            Table[InverseTable[ulSize-20+i]]=(BYTE)(ulSize-20+i);
            Table[InverseTable[bNearestIndex]]=bNearestIndex;
        }
    }
}


VOID FudgeColorTable(COLORTABLETYPE *ColTable, PRGB2 Palette, ULONG ulSize)
{
    ULONG   i;
    ULONG   ulNewIndex;

    for (i=0; i<DFLT_LOG_COL_TABLE_SIZE; i++)
    {
        ulNewIndex = NearestPaletteEntry(ColTable[i].LogRGB, Palette, ulSize);

        /* Defect 53532 - When running at 4 bpp, Flood fills were     */
        /* spilling out to the left. This was caused because we       */
        /* had the       color index for certain colors. The color    */
        /* index fixup logic below should NOT be done when we are     */
        /* running at 4 bpp. Joe Celi (9/22/92)                       */

        if ((DDT.BitCount==8) && (ulNewIndex >= (ulSize/2)))
        {
            ulNewIndex = ulNewIndex+256-ulSize;
        }

        ColTable[i].PhyIndex = ulNewIndex;
    }
}


VOID FudgePalettesAndGenerateTables(VOID)
{
    FudgePaletteAndGenerateTable(FullSizeDeviceDefaultPalette,
                                 PaletteFudgeTable256,
                                 256);

    FudgePaletteAndGenerateTable(Reduced128DeviceDefaultPalette,
                                 PaletteFudgeTable128,
                                 128);

    FudgePaletteAndGenerateTable(Reduced64DeviceDefaultPalette,
                                 PaletteFudgeTable64,
                                 64);

    FudgePaletteAndGenerateTable(Reduced32DeviceDefaultPalette,
                                 PaletteFudgeTable32,
                                 32);

    FudgePaletteAndGenerateTable(Reduced16DeviceDefaultPalette,
                                 PaletteFudgeTable16,
                                 16);

    FudgeColorTable(DefaultEightBppTable256,
                    FullSizeDeviceDefaultPalette,
                    256);

    FudgeColorTable(DefaultEightBppTable128,
                    Reduced128DeviceDefaultPalette,
                    128);

    FudgeColorTable(DefaultEightBppTable64,
                    Reduced64DeviceDefaultPalette,
                    64);

    FudgeColorTable(DefaultEightBppTable32,
                    Reduced32DeviceDefaultPalette,
                    32);

    FudgeColorTable(DefaultEightBppTable16,
                    Reduced16DeviceDefaultPalette,
                    16);

    FudgeColorTable(DefaultFourBppTable,
                    Reduced16DeviceDefaultPalette,
                    16);

}

VOID FudgeDitherPattern(ULONG ulPaletteSize)
{
    PBYTE   TranslateTable;
    BYTE    bOldPhyIndex;
    BYTE    bNewPhyIndex;
    ULONG   x,y;

    switch (ulPaletteSize)
    {
        case 256:
            TranslateTable = PaletteFudgeTable256;
            break;

        case 128:
            TranslateTable = PaletteFudgeTable128;
            break;

        case 64:
            TranslateTable = PaletteFudgeTable64;
            break;

        case 32:
            TranslateTable = PaletteFudgeTable32;
            break;

        case 16:
            TranslateTable = PaletteFudgeTable16;
            break;

#ifdef FIREWALLS
        default:
            haltproc();
            ulPaletteSize = 256;
            TranslateTable = PaletteFudgeTable256;
#endif

    }

    for (y=0; y<DITHMATRIX_YSIZE; y++)
    {
        for (x=0; x<DITHMATRIX_XSIZE; x++)
        {
            /**********************************************************/
            /* Get the existing physical index for this entry in the  */
            /* dither matrix.  (At 8bpp this will be a range from     */
            /* 0 to 255).                                             */
            /**********************************************************/
            bOldPhyIndex = ColorPat[x][y];

            /**********************************************************/
            /* Convert from 0 to 255 range to 0 to ulPaletteSize      */
            /* range and use the translation tables to obtain a new   */
            /* physical index (also in the 0 to ulPaletteSize range). */
            /**********************************************************/
            if (bOldPhyIndex>=128)
            {
                bNewPhyIndex = TranslateTable[bOldPhyIndex-256+ulPaletteSize];
            }
            else
            {
                bNewPhyIndex = TranslateTable[bOldPhyIndex];
            }

            /**********************************************************/
            /* If we are at 8bpp then we must convert our index to    */
            /* the 0 to 256 palette range.                            */
            /**********************************************************/
            if ((DDT.BitCount==8) && (bNewPhyIndex>=(BYTE)(ulPaletteSize/2)))
            {
                bNewPhyIndex += (BYTE)(256-ulPaletteSize);
            }

            /**********************************************************/
            /* Put the new physical index into the dither matrix.     */
            /**********************************************************/
            ColorPat[x][y] = bNewPhyIndex;
        }
    }
}

#ifndef   _8514
/**********************************************************************/
/* Adds the ISO compliant colours to the palettes by replacing the    */
/* nearest colour already in the palette.                             */
/**********************************************************************/

VOID MakePalettesISOCompliant(VOID)

{
  register ULONG i;
  register ULONG nearest_index;


  /**************************************************************/
  /* We should only add the ISO colors in when we are running   */
  /* at 8 bpp.  If there are palette manager apps around they   */
  /* can blow away the ISO colors.  Previously, we were adding  */
  /* the ISO colors to the 4 bpp palette and getting complaints */
  /* about the wierd system colors. At 16 bpp this is not an    */
  /* issue.                                                     */
  /*                                                            */
  /* Joe Celi (12/2/92) -  Defect 57912                         */
  /**************************************************************/

  if (DDT.BitCount == 8)
  {

     /********************************************************************/
     /* Go through each of the ISO colours, find the nearest match in    */
     /* the palettes and replace.                                        */
     /********************************************************************/
     for ( i = 0; i < MAX_ISO_COLOURS; i++ )
     {
       nearest_index = NearestPaletteEntry(InstanceData.aISOColours[i].rgb2,
                                           FullSizeDeviceDefaultPalette,
                                           256);
       FullSizeDeviceDefaultPalette[nearest_index] =
                                            InstanceData.aISOColours[i].rgb2;


       /**************************************************************/
       /* We don't want to add the ISO colors to the reduced         */
       /* palettes.                                                  */
       /*                                                            */
       /* Joe Celi (12/2/92) -  Defect 57912                         */
       /**************************************************************/

//     nearest_index = NearestPaletteEntry(InstanceData.aISOColours[i].rgb2,
//                                         Reduced128DeviceDefaultPalette,
//                                         128);
//     Reduced128DeviceDefaultPalette[nearest_index] =
//                                          InstanceData.aISOColours[i].rgb2;
//
//     nearest_index = NearestPaletteEntry(InstanceData.aISOColours[i].rgb2,
//                                         Reduced64DeviceDefaultPalette,
//                                         64);
//     Reduced64DeviceDefaultPalette[nearest_index] =
//                                          InstanceData.aISOColours[i].rgb2;
//
//     nearest_index = NearestPaletteEntry(InstanceData.aISOColours[i].rgb2,
//                                         Reduced32DeviceDefaultPalette,
//                                         32);
//     Reduced32DeviceDefaultPalette[nearest_index] =
//                                          InstanceData.aISOColours[i].rgb2;
//
//     nearest_index = NearestPaletteEntry(InstanceData.aISOColours[i].rgb2,
//                                         Reduced16DeviceDefaultPalette,
//                                         16);
//     Reduced16DeviceDefaultPalette[nearest_index] =
//                                          InstanceData.aISOColours[i].rgb2;
     }
  }

} /* MakePalettesISOCompliant */
#endif //_8514
