/*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 = PRDBGREY
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS   prdb_GetNextColor
 *
 * 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              /* Convert to C/SET2    CON3201       */
#define INCL_GPIPRIMITIVES
#define INCL_WINHEAP
#define INCL_GPIBITMAPS
#define INCL_GPIERRORS
#define INCL_GPILOGCOLORTABLE
#include <os2.h>
#undef INCL_DOSPROCESS                  /* Convert to C/SET2    CON3201       */
#undef INCL_GPIPRIMITIVES
#undef INCL_WINHEAP
#undef INCL_GPIBITMAPS
#undef INCL_GPIERRORS
#undef INCL_GPILOGCOLORTABLE

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

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

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

#include <prdbtyp1.h>
#include <prdbextf.h>
#include <prdgextf.h>
#include <prdcextf.h>

/******************************************************************************/
/*  A few externals...                                                        */
/******************************************************************************/
extern USHORT  prdd_HugeInc;
extern ULONG   DefaultColorTable[];

/******************************************************************************/
/*  FUNCTION: prdb_GetNextColor                                               */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  PBYTE FAR *  lpSrcPtr    Pointer to the source bitmap                     */
/*  BOOL         fSafe       Flag to indicate whether we'll cross a segment   */
/*  USHORT       usPelsLeft  How many pels are left on the current scan line  */
/*  PUSHORT      pusPels     Pointer to the number of continuous pels found   */
/*  PUSHORT      pusPelPos   Pointer to the source nibble we're working with  */
/*  lpDCI        DCIData     Pointer to current DCIData                       */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This code will read a source color bitmap and determine what the color of */
/*  the first pel it encounters at the current position in the bitmap is as   */
/*  well as the number of continuous pels of the same color.  This will enable*/
/*  us to greyscale as many pels of a specific color at a time as we can.     */
/*  This function returns the current RGB color as well as updating the       */
/*  pointers to the source bitmap, the current pel position and the total     */
/*  number of continuous pels of the current RGB color.                       */
/*                                                                            */
/*  Performance ideas:                                                        */
/*                                                                            */
/*    - Pass in the pointer to the DCIColorTable rather than the pointer to   */
/*      DCIData - we should be able to save precious clocks by not having to  */
/*      dereference the pointer each time.                                    */
/*                                                                            */
/*    - Switch to assembler and make sure the cmp's are done with immediates  */
/*      rather than the register variables - will save one clock per cmp.     */
/*                                                                            */
/*    - Create four separate returns instead of having one single return.     */
/*      Would this make the exit jmp a short jmp and thereby reduce the       */
/*      number of clocks?                                                     */
/******************************************************************************/
ULONG prdb_GetNextColor( PBYTE     *lpSrcPtr,
                         BOOL       fSafe,
                         BOOL       fRGB,
                         USHORT     usPelsLeft,
                         PUSHORT    pusPels,
                         PUSHORT    pusPelPos,
                         lpDCI      DCIData )

{

#define TFUNC "prdb_GetNextColor"

    /**************************************************************************/
    /*  Local variables...                                                    */
    /**************************************************************************/
    ULONG            ulCurrentRGB;
    register USHORT  usPels;
    register USHORT  usPelPos;
    BYTE             bSrcByte;
    BOOL             fColorsMatch;

    /**************************************************************************/
    /*  Initialize a few things...                                            */
    /**************************************************************************/
    fColorsMatch = FALSE;              /* Assume a unique RGB...              */
    usPels       = 0;                  /* # of pels of the same color         */
    usPelPos     = *pusPelPos;         /* Nibble we're currently working with */
    bSrcByte     = **lpSrcPtr;         /* Read the first source byte          */

    /**************************************************************************/
    /*  We have two paths through the following code based on the value of    */
    /*  fRGB, which indicates the color format we're working with.  This is   */
    /*  important because if we're in RGB format there's no color table to    */
    /*  index and we have to use the default color table.  By replicating the */
    /*  following code and changing only the origin of the RGB colors, we'll  */
    /*  save in performance over having to check the color format each time we*/
    /*  get ready to assign the RGB values.                                   */
    /**************************************************************************/
    if (fRGB)
    {

        /**********************************************************************/
        /*  We're in RGB mode, so there's no color table in the DCIData... we */
        /*  need to get the RGB triplets from the default color table...      */
        /*                                                                    */
        /*  We need to replicate the code below into two nearly identical     */
        /*  branches based on the fSafe flag.  fSafe signifies whether or not */
        /*  we need to concern ourselves with huge-incrementing the bitmap.   */
        /*  If we're fSafe, we can ignore all this and just do our thang...   */
        /*  otherwise we need to call POSTINC() to increment the huge bitmap  */
        /*  which will huge increment the bitmap when needed.  This code      */
        /*  duplication is for performance reasons only.                      */
        /**********************************************************************/

/* CON3201 ********************************************************************/
/* Will always be safe in PRDBSUBR.C the second parameter (fSafe) passed to   */
/* to prdb_GetNextColor is always true.  This means that we will never have   */
/* to cross a segment boundary, as is true since we are using 32-bit flat     */
/* model.  Will go ahead and leave this check in but comment out the else     */
/* portion.                                                                   */
/******************************************************************************/
        if (fSafe)
        {

            /******************************************************************/
            /*  We need to be sure we pick up the correct nibble and only     */
            /*  increment the source pointer if we're picking up the last     */
            /*  nibble...                                                     */
            /******************************************************************/
            if (usPelPos++ == 1)
            {
                ulCurrentRGB = DefaultColorTable[(ULONG)(bSrcByte >> 4)];
            }
            else
            {
                ulCurrentRGB = DefaultColorTable[(ULONG)(bSrcByte & 0x0f)];
                (*lpSrcPtr)++;
            }

            /******************************************************************/
            /*  Loop until we find a color differing from the first           */
            /*  encountered or until we've picked up the last of the pels on  */
            /*  this scan line...                                             */
            /******************************************************************/
            do
            {

                /**************************************************************/
                /*  If we have all of the pels we need, then let's bail out...*/
                /**************************************************************/
                if (++usPels == usPelsLeft)
                {
                    break;
                }

                /**************************************************************/
                /*  If we need to read a new source byte, do it here...       */
                /**************************************************************/
                if (usPelPos == 3)
                {
                    bSrcByte = **lpSrcPtr;
                    usPelPos = 1;
                }

                /**************************************************************/
                /*  Check to see if the next color encountered matches the    */
                /*  current color.                                            */
                /**************************************************************/
                fColorsMatch = (ulCurrentRGB == ((usPelPos++ == 1) ?
                                  DefaultColorTable[(ULONG)(bSrcByte >> 4)] :
                                  DefaultColorTable[(ULONG)(bSrcByte & 0x0f)]));

                /**************************************************************/
                /*  Increment the source pointer only if the second nibble is */
                /*  a match...                                                */
                /**************************************************************/
                if (fColorsMatch && (usPelPos == 3))
                {
                    (*lpSrcPtr)++;
                }
            }
            while (fColorsMatch);
        }
/* CON3201 - Start of if'd out code */
#if 0
         else
        {

            /******************************************************************/
            /*  We need to be sure we pick up the correct nibble and only     */
            /*  increment the source pointer if we're picking up the last     */
            /*  nibble...  will increment with POSTINC() macro in this        */
            /*  branch...                                                     */
            /******************************************************************/
            if (usPelPos++ == 1)
            {
                ulCurrentRGB = DefaultColorTable[(ULONG)(bSrcByte >> 4)];
            }
            else
            {
                ulCurrentRGB = DefaultColorTable[(ULONG)(bSrcByte & 0x0f)];
                POSTINC(*lpSrcPtr);
            }

            /******************************************************************/
            /*  Loop until we find a color differing from the first           */
            /*  encountered or until we've picked up the last of the pels on  */
            /*  this scan line...                                             */
            /******************************************************************/
            do
            {

                /**************************************************************/
                /*  If we have all of the pels we need, then let's bail out...*/
                /**************************************************************/
                if (++usPels == usPelsLeft)
                {
                    break;
                }

                /**************************************************************/
                /*  If we need to read a new source byte, do it here...       */
                /**************************************************************/
                if (usPelPos == 3)
                {
                    bSrcByte = **lpSrcPtr;
                    usPelPos = 1;
                }

                /**************************************************************/
                /*  Check to see if the next color encountered matches the    */
                /*  current color.                                            */
                /**************************************************************/
                fColorsMatch = (ulCurrentRGB == ((usPelPos++ == 1) ?
                                  DefaultColorTable[(ULONG)(bSrcByte >> 4)] :
                                  DefaultColorTable[(ULONG)(bSrcByte & 0x0f)]));

                /**************************************************************/
                /*  Set the fColorsMatch and increment the source pointer only*/
                /*  if the second nibble is a match...                        */
                /**************************************************************/
                if (fColorsMatch && (usPelPos == 3))
                {
                    POSTINC(*lpSrcPtr);
                }
            }
            while (fColorsMatch);
        }
/* CON3201 - End of if'd out code */
#endif
    }
    else
    {
        /**********************************************************************/
        /*  We're *not* in RGB mode, so there's a color table in the DCIData  */
        /*  that we need to get the RGB triplets from...                      */
        /*                                                                    */
        /*  We need to replicate the code below into two nearly identical     */
        /*  branches based on the fSafe flag.  fSafe signifies whether or not */
        /*  we need to concern ourselves with huge-incrementing the bitmap.   */
        /*  If we're fSafe, we can ignore all this and just do our thang...   */
        /*  otherwise we need to call POSTINC() (I think) to increment the    */
        /*  huge bitmap which will huge increment the bitmap when needed.     */
        /*  This code duplication is for performance reasons only.            */
        /**********************************************************************/


/* CON3201 ********************************************************************/
/* Will always be safe in PRDBSUBR.C the second parameter (fSafe) passed to   */
/* to prdb_GetNextColor is always true.  This means that we will never have   */
/* to cross a segment boundary, as is true since we are using 32-bit flat     */
/* model.  Will go ahead and leave this check in but comment out the else     */
/* portion.                                                                   */
/******************************************************************************/
        if (fSafe)
        {

            /******************************************************************/
            /*  We need to be sure we pick up the correct nibble and only     */
            /*  increment the source pointer if we're picking up the last     */
            /*  nibble...                                                     */
            /******************************************************************/
            if (usPelPos++ == 1)
            {
                ulCurrentRGB = DCIData->DCIColorTable[(ULONG)(bSrcByte >> 4)].
                                                     LogRGB;
            }
            else
            {
                ulCurrentRGB = DCIData->DCIColorTable[(ULONG)(bSrcByte & 0x0f)].
                                                     LogRGB;
                (*lpSrcPtr)++;
            }

            /******************************************************************/
            /*  Loop until we find a color differing from the first           */
            /*  encountered or until we've picked up the last of the pels on  */
            /*  this scan line...                                             */
            /******************************************************************/
            do
            {

                /**************************************************************/
                /*  If we have all of the pels we need, then let's bail out...*/
                /**************************************************************/
                if (++usPels == usPelsLeft)
                {
                    break;
                }

                /**************************************************************/
                /*  If we need to read a new source byte, do it here...       */
                /**************************************************************/
                if (usPelPos == 3)
                {
                    bSrcByte = **lpSrcPtr;
                    usPelPos = 1;
                }

                /**************************************************************/
                /*  Check to see if the next color encountered matches the    */
                /*  current color.                                            */
                /**************************************************************/
                fColorsMatch = (ulCurrentRGB == ((usPelPos++ == 1) ?
                                  DefaultColorTable[(ULONG)(bSrcByte >> 4)] :
                                  DefaultColorTable[(ULONG)(bSrcByte & 0x0f)]));

                /**************************************************************/
                /*  Set the fColorsMatch and increment the source pointer only*/
                /*  if the second nibble is a match...                        */
                /**************************************************************/
                if (fColorsMatch && (usPelPos == 3))
                {
                    (*lpSrcPtr)++;
                }
            }
            while (fColorsMatch);
        }
/* CON3201 - Start of if'd out code */
#if 0
        else
        {

            /******************************************************************/
            /*  We need to be sure we pick up the correct nibble and only     */
            /*  increment the source pointer if we're picking up the last     */
            /*  nibble...  will increment with POSTINC() macro in this        */
            /*  branch...                                                     */
            /******************************************************************/
            if (usPelPos++ == 1)
            {
                ulCurrentRGB = DCIData->DCIColorTable[(ULONG)(bSrcByte >> 4)].
                                                     LogRGB;
            }
            else
            {
                ulCurrentRGB = DCIData->DCIColorTable[(ULONG)(bSrcByte & 0x0f)].
                                                     LogRGB;
                POSTINC(*lpSrcPtr);
            }

            /******************************************************************/
            /*  Loop until we find a color differing from the first           */
            /*  encountered or until we've picked up the last of the pels on  */
            /*  this scan line...                                             */
            /******************************************************************/
            do
            {

                /**************************************************************/
                /*  If we have all of the pels we need, then let's bail out...*/
                /**************************************************************/
                if (++usPels == usPelsLeft)
                {
                    break;
                }

                /**************************************************************/
                /*  If we need to read a new source byte, do it here...       */
                /**************************************************************/
                if (usPelPos == 3)
                {
                    bSrcByte = **lpSrcPtr;
                    usPelPos = 1;
                }

                /**************************************************************/
                /*  Check to see if the next color encountered matches the    */
                /*  current color.                                            */
                /**************************************************************/
                fColorsMatch = (ulCurrentRGB == ((usPelPos++ == 1) ?
                                  DefaultColorTable[(ULONG)(bSrcByte >> 4)] :
                                  DefaultColorTable[(ULONG)(bSrcByte & 0x0f)]));

                /**************************************************************/
                /*  Set the fColorsMatch and increment the source pointer only*/
                /*  if the second nibble is a match...                        */
                /**************************************************************/
                if (fColorsMatch && (usPelPos == 3))
                {
                    POSTINC(*lpSrcPtr);
                }
            }
            while (fColorsMatch);
        }
/* CON3201 - End of if'd out code */
#endif
    }

    /**************************************************************************/
    /*  Tell the calling routine how many pels we've found of the same color, */
    /*  which nibble in the source bitmap we've ended up on, and return the   */
    /*  current color too...                                                  */
    /**************************************************************************/
    *pusPels   = usPels;
    *pusPelPos = (usPelPos == 3) ? 2 : 1;
    return(ulCurrentRGB);
}
#undef TFUNC
