/*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.                                */
/*                                                                           */
/*****************************************************************************/
/**********************************************************************/
/*                                                                    */
/* bitmaps.c                                                          */
/*                                                                    */
/* Functions for processing bitmaps.                                  */
/**********************************************************************/
#include "eddinclt.h"
#include "bitmaps.h"
#include "errors.h"

#include "eddhcone.h"

#include "memman.h"

#include "edddtypt.h"          // J.C. 16 bpp bmap support

extern    DDTType  DDT;        // J.C. 16 bpp bmap support

/**********************************************************************/
/* SizeOfExternalBMHeader                                             */
/*                                                                    */
/* pInfo  pointer to a bitmap header (PBITMAPINFO2)                   */
/*                                                                    */
/* Returns the minimum amount of memory needed for an external bitmap */
/* header -  this varies depending on whether or not a colour table   */
/* is needed.                                                         */
/* We always use the new form of bitmap header.                       */
/**********************************************************************/
#define SizeOfExternalBMHeader(pInfo)                                  \
   (((pInfo)->cBitCount == 24) ?                                       \
      sizeof(BITMAPINFOHEADER2) :                                      \
      sizeof(BITMAPINFOHEADER2) + (sizeof(RGB2) << (pInfo)->cBitCount))

/**********************************************************************/
/* CreateExternalBitmap                                               */
/*                                                                    */
/* pInfo  pointer to a PM bitmap header (PBITMAPINFO2)                */
/*                                                                    */
/* Allocates the memory needed for an external bitmap and             */
/* its header (which may include a colour table).                     */
/* We always use the BITMAPINFO2 format for the external bitmap.      */
/**********************************************************************/
PBITMAPINFO2 PASCAL CreateExternalBitmap(PBITMAPINFO2  pInfo,
                                         PBYTE *       ppbBits)
{
    PBITMAPINFO2   pExternal;
    ULONG          ulHeaderSize;
    ULONG          ulBitmapSize;

    /******************************************************************/
    /* Get the memory, which we use in the order of                   */
    /*          BITMAPINFO2                                           */
    /*          colour table (not at 24 bpp)                          */
    /*          actual bitmap bits                                    */
    /******************************************************************/
    ulHeaderSize = SizeOfExternalBMHeader(pInfo);
    ulBitmapSize = SizeOfExternalBitmap(pInfo);
    pExternal = AllocateMemory( ulHeaderSize + ulBitmapSize,
                                MT_EXT_BITMAP,
                                MO_SHARED );
    if (pExternal != NULL)
    {
        /**************************************************************/
        /* Allocation suceeded so copy across the bitmap info.        */
        /* First set all fields to 0 (default value)                  */
        /**************************************************************/
        memset(pExternal,0, ulHeaderSize);

        pExternal->cbFix         = sizeof(BITMAPINFOHEADER2);
        pExternal->cx            = pInfo->cx;
        pExternal->cy            = pInfo->cy;
        pExternal->cPlanes       = pInfo->cPlanes;
        pExternal->cBitCount     = pInfo->cBitCount;
        pExternal->cbImage       = ulBitmapSize;


        /**************************************************************/
        /* Return the pointer to the bitmap bits.                     */
        /**************************************************************/
        *ppbBits = (PBYTE)pExternal + ulHeaderSize;
    }

    return (pExternal);
}

/**********************************************************************/
/* CreateInternalBitmap                                               */
/*                                                                    */
/* pInfo  pointer to a BITMAPINFO2 structure which hold bitmap size   */
/*        (only fields cx, cy and cBitCount need be filled in)        */
/*                                                                    */
/* Gets the memory needed for the bitmap specified by pInfo and its   */
/* header.                                                            */
/* The header is initialised and returned (NULL is an error).         */
/**********************************************************************/
pBitmapHeader PASCAL CreateInternalBitmap(PBITMAPINFO2 pInfo)
{
    pBitmapHeader pbhInfo;

    /******************************************************************/
    /* Get the memory, which we use in the order of                   */
    /*          BitmapHeader                                          */
    /*          initial padding                                       */
    /*          actual bitmap bits                                    */
    /*          final padding                                         */
    /* Padding is needed because the software drawing is not always   */
    /* too particular about accesses at the ends of bitmaps.          */
    /******************************************************************/
    pbhInfo = AllocateMemory( sizeof(BitmapHeader) +
                               INITIAL_PAD_SIZE +
                               SizeOfInternalBitmap(pInfo) +
                               FINAL_PAD_SIZE,
                              MT_BITMAP,
                              MO_SHARED );

    if ( pbhInfo != NULL )
    {
        /**************************************************************/
        /* Allocation succeded so set up the internal header values.  */
        /**************************************************************/
        pbhInfo->Info.Width    = (USHORT)pInfo->cx;
        pbhInfo->Info.Height   = (USHORT)pInfo->cy;
        pbhInfo->Info.BitCount = pInfo->cBitCount;
        pbhInfo->Info.HWWidth  = (USHORT)(pInfo->cx - 1);
        pbhInfo->Info.HWHeight = (USHORT)(pInfo->cy - 1);
        switch (pInfo->cBitCount)
        {
            #ifdef   BPP24
            case 24:
                pbhInfo->Info.HWFormat = TWENTYFOUR_BITS_PER_PEL;
                break;
            #endif

            case 16:
                pbhInfo->Info.HWFormat = SIXTEEN_BITS_PER_PEL;
                break;

            case 8:
                pbhInfo->Info.HWFormat = EIGHT_BITS_PER_PEL;
                break;

            case 4:
                pbhInfo->Info.HWFormat = FOUR_BITS_PER_PEL;
                break;

            case 1:
                pbhInfo->Info.HWFormat = ONE_BIT_PER_PEL;
                break;
        }

        /**************************************************************/
        /* Store a count of the bytes per scan line                   */
        /**************************************************************/
        pbhInfo->BytesPerLine = (USHORT)(BytesPerInternalLine(pInfo));

        /**************************************************************/
        /* Finally, the address of the bitmap bits.                   */
        /**************************************************************/
        pbhInfo->BMPhys = FNULL;
        pbhInfo->Bitmap = ((PBYTE)pbhInfo)  +
                           INITIAL_PAD_SIZE +
                           sizeof(BitmapHeader);
    }

    return(pbhInfo);

} /* CreateInternalBitmap */


/**********************************************************************/
/* ValidHeader                                                        */
/*                                                                    */
/* pInfo  pointer to the bitmap header to be validated                */
/*                                                                    */
/* This routine validates the external bitmap header, which may hold  */
/* either BITMAPINFO or BITMAPINFO2 values.                           */
/* Returns TRUE if valid, FALSE otherwise.                            */
/**********************************************************************/
BOOL PASCAL ValidHeader(PBITMAPINFO2 pInfo)
{
    switch ( min(pInfo->cbFix, sizeof(BITMAPINFO2)) )
    {
        case sizeof(BITMAPINFOHEADER):

            /**********************************************************/
            /* Consider the old format header.                        */
            /*                                                        */
            /* If the bitmap is not in a standard PM format then we   */
            /* check to see if it is in device dependent format.      */
            /* We are now supporting 16 bpp bitmaps when running      */
            /* in direct color mode (16 bpp).                         */
            /*                                                        */
            /* Joe Celi (12/2/92) - Defect 58015                      */
            /**********************************************************/

            if ( StandardPlanesBitcount((PBITMAPINFO)pInfo) ||
                 DeviceDependentFormat((PBITMAPINFO)pInfo) )
            {
                return(TRUE);
            }
            break;

        /**************************************************************/
        /* The following cases only do a break if the test fails -    */
        /* if the test is ok then they drop through into the next     */
        /* test.                                                      */
        /**************************************************************/

        case sizeof(BITMAPINFOHEADER2):
            /**********************************************************/
            /* Dont check the ulIdentifier field, it's reserved for   */
            /* application use.                                       */
            /**********************************************************/

            /**********************************************************/
            /* Palette manager uses BCE_PALETTE colour encoding, but  */
            /* it's an error for this to be set if there is no        */
            /* palette selected.                                      */
            /**********************************************************/
            if (pInfo->ulColorEncoding == BCE_PALETTE)
            {
                if (pdc->DCIColFormat != LCOLF_PALETTE)
                {
                    eiErrorToLog = MAKEERRORID(SEVERITY_ERROR,
                                               PMERR_NO_PALETTE_SELECTED);
                    return(FALSE);
                }
            }
            else if (pInfo->ulColorEncoding != BCE_RGB)
            {
                /******************************************************/
                /* The only generally allowed value is BCE_RGB        */
                /******************************************************/
                break;
            }

        case SIZE_BM2_TO_RENDER(pInfo):
            if ( (pInfo->usRendering != BRH_NOTHALFTONED)   &&
                 (pInfo->usRendering != BRH_ERRORDIFFUSION) &&
                 (pInfo->usRendering != BRH_PANDA)          &&
                 (pInfo->usRendering != BRH_SUPERCIRCLE) )
            {
                break;
            }

        case SIZE_BM2_TO_RECORD(pInfo):
            if (pInfo->usRecording != BRA_BOTTOMUP)
            {
                break;
            }

        case SIZE_BM2_TO_RESERVED(pInfo):
            if (pInfo->usReserved != 0)
            {
                break;
            }

        case SIZE_BM2_TO_UNITS(pInfo):
            if (pInfo->usUnits != BRU_METRIC)
            {
                break;
            }

        case SIZE_BM2_TO_IMPORTANT(pInfo):
            /**********************************************************/
            /* Number of important colours cannot be more than total  */
            /* number of colours.                                     */
            /**********************************************************/
            if (pInfo->cclrImportant > (1UL << pInfo->cBitCount))
            {
                break;
            }

        case SIZE_BM2_TO_USED(pInfo):
            /**********************************************************/
            /* Number of used colours cannot be more than total colors*/
            /**********************************************************/
            if (pInfo->cclrUsed > (1UL << pInfo->cBitCount))
            {
                break;
            }

        case SIZE_BM2_TO_COMPRESS(pInfo):
            if ( (pInfo->ulCompression != BCA_UNCOMP)    &&
                 (pInfo->ulCompression != BCA_RLE8)      &&
                 (pInfo->ulCompression != BCA_RLE4)      &&
                 (pInfo->ulCompression != BCA_HUFFMAN1D) &&
                 (pInfo->ulCompression != BCA_RLE24) )
            {
                break;
            }

/*      case SIZE_BM2_MIN(pInfo):  */
        default:
            /**********************************************************/
            /* minimum size of new format header                      */
            /*                                                        */
            /* If the bitmap is not in a standard PM format then we   */
            /* check to see if it is in device dependent format.      */
            /* We are now supporting 16 bpp bitmaps when running      */
            /* in direct color mode (16 bpp).                         */
            /*                                                        */
            /* Joe Celi (12/2/92) - Defect 58015                      */
            /**********************************************************/
            /*                                                        */
            /* made this the default so that we would check other     */
            /* header sizes than those listed in the above case       */
            /* statements.  Because other header sizes may be valid   */
            /* since all fields of the header need not be filled in.  */
            /*                                                        */
            /* VCB (8/3/93) - Defect 72311                            */
            /**********************************************************/

            if ( StandardPlanesBitcount(pInfo) ||
                 DeviceDependentFormat(pInfo) )
            {
                return(TRUE);
            }

    } /* switch size of bitmap header */

    eiErrorToLog = MAKEERRORID(SEVERITY_ERROR, PMERR_INV_INFO_TABLE);
    return(FALSE);

} /* ValidHeader */
