/*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 = NEWBMPS.C
 *
 * DESCRIPTIVE NAME = GLOBALS USED BY THE NEW LAYER FUNCTIONS
 *
 *
 * VERSION = V2.0
 *
 * DATE
 *
 * DESCRIPTION
 *
 *
 * FUNCTIONS      CompDeCompBull
 *                prdn_DeviceCreateBitmap
 *                prdn_GetSetBitmapBits
 *
 * 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_GPIERRORS
#define INCL_GPIPRIMITIVES
#define INCL_WINHEAP
#define INCL_GPIBITMAPS
#define INCL_DOSMEMMGR
#include <os2.h>
#undef INCL_DOSSEMAPHORES
#undef INCL_DOSPROCESS                  /* Convert to C/SET2    CON3201       */
#undef INCL_GPIERRORS
#undef INCL_GPIPRIMITIVES
#undef INCL_WINHEAP
#undef INCL_GPIBITMAPS
#undef INCL_DOSMEMMGR

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

#define INCL_GRE_BITMAPS
#define INCL_GRE_DEVSUPPORT
#include <pmddim.h>
#undef INCL_GRE_DEVSUPPORT
#undef INCL_GRE_BITMAPS

#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 <prdconse.h>

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

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


   typedef struct
   {
      ULONG  cbFix;            /* Length of fixed portion of structure   */
      ULONG  cx;               /* Bit-map width in pels                  */
      ULONG  cy;               /* Bit-map height in pels                 */
      USHORT cPlanes;          /* Number of bit planes                   */
      USHORT cBitCount;        /* Number of bits per pel within a plane  */
      ULONG  ulCompression;    /* Compression scheme used to store bitmap */
      ULONG  cbImage;          /* Length of bit-map storage data in bytes */
      ULONG  cxResolution;     /* x resolution of target device          */
      ULONG  cyResolution;     /* y resolution of target device          */
      ULONG  cclrUsed;         /* Number of color indices used           */
      ULONG  cclrImportant;    /* Number of important color indices      */
      USHORT usUnits;          /* Units of measure                       */
      USHORT usReserved;       /* Reserved                               */
      USHORT usRecording;      /* Recording algorithm                    */
      USHORT usRendering;      /* Halftoning algorithm                   */
      ULONG  cSize1;           /* Size value 1                           */
      ULONG  cSize2;           /* Size value 2                           */
      ULONG  ulColorEncoding;  /* Color encoding                         */
      ULONG  ulIdentifier;     /* Reserved for application use           */
      RGB2   argbColor[256];   /* Color definition record                */
   } BITMAP_INFO2;
   typedef BITMAP_INFO2 *PBITMAP_INFO2;


ULONG CompDeCompBull ( ULONG, PBITMAPINFO2, PBYTE, PBITMAPINFO2 *, PBYTE *,
                       lpDCI, ULONG,        ULONG );


/****************************************************************************
 *
 * FUNCTION NAME = CompDeCompBull
 *
 * DESCRIPTION   = This function handles calls from both createbitmap and
 *                 getsetbitmapbits.  if the call is from prdn_createbitmap or
 *                 Setbitmapbis then allocates memory for bitmap and
 *                 bitmapinfo and calls the convertbitmapdata32.if the call is
 *                 from getbitmapbits it will allocates memory only for
 *                 BITMAPINFO calls Convetbitmapdata32.
 *
 *  Created : 04/18/93  Kranthi Ravi
 *
 *
 * INPUT         = ULONG DcH
 *                 PBITMAPINFO2 lpInitInfo
 *                 PBYTE ArgBits
 *                 PBITMAPINFO2 *tempInfo
 *                 PBYTE * ArgBitmap
 *                 lpDCI DCIData
 *                 ULONG FunN
 *                 ULONG Compression
 *
 *
 * OUTPUT        = ULONG
 *
 * RETURN-NORMAL = NONE
 *
 * RETURN-ERROR  = NONE
 *
 ****************************************************************************/

ULONG CompDeCompBull ( ULONG DcH,PBITMAPINFO2 lpInitInfo,PBYTE ArgBits,
                       PBITMAPINFO2 *tempInfo,PBYTE * ArgBitmap,
                       lpDCI DCIData,ULONG FunN,ULONG Compression)

{

    ULONG   TotalBytes;  /* Bitmap size in bytes                     */
    ULONG   BytesPerRow; /* bytes in one bitmap row                  */
    ULONG   ulReturn;
    ULONG   NEntries;    /* no of rgb2 structures */
    ULONG   InfoSize;    /* size of bitmapinfo with rgb2 structures at end */

    NEntries = 2 << (lpInitInfo->cBitCount - 1);
    InfoSize = sizeof(BITMAPINFOHEADER2) + (NEntries * sizeof(RGB2));
    SafeSSALLOCMEM(tempInfo,InfoSize,0);
    if(LOUSHORT(FunN) == NGreGetBitmapBits)
    {                          /* getbitmapbits */
        PBITMAPINFO2 tinfo;
        prdu_memcpy(*tempInfo,lpInitInfo,InfoSize);
        tinfo = lpInitInfo;
        lpInitInfo = *tempInfo;   /* alternate the infos */
        *tempInfo = lpInitInfo;
    }
    else
    {       /* gre needs us to fill this info */
        (*tempInfo)->cbFix     = sizeof(BITMAPINFOHEADER2);
        (*tempInfo)->cx        = lpInitInfo->cx;
        (*tempInfo)->cy        = lpInitInfo->cy;
        (*tempInfo)->cPlanes   = lpInitInfo->cPlanes;
        (*tempInfo)->cBitCount = lpInitInfo->cBitCount;
        (*tempInfo)->cbImage   = lpInitInfo->cbImage;
    }
                         /* calculate size of bitmap to allocate     */
    if (LOUSHORT(FunN) == NGreDeviceCreateBitmap ||
                     LOUSHORT(FunN) == NGreSetBitmapBits)
    {                              /* create bitmap or setbitmapbits */
        BytesPerRow = ((lpInitInfo->cx *
                         lpInitInfo->cBitCount + 31) / 32) * 4;
        TotalBytes = BytesPerRow * lpInitInfo->cy;
        SafeSSALLOCMEM(ArgBitmap, TotalBytes, 0);
        (*tempInfo)->cbImage = TotalBytes;
        (VOID)prdu_memset(*ArgBitmap, 0, TotalBytes);
    }
    ulReturn = GreConvertBitmapData(DcH,Compression,0L,
                       lpInitInfo,ArgBits,*tempInfo,*ArgBitmap);
    if (LOUSHORT(FunN) == NGreGetBitmapBits)
        SSFREEMEM (lpInitInfo);   /* free the memory we have created */
    return(ulReturn);
}

/****************************************************************************
 *
 * FUNCTION NAME = prdn_DeviceCreateBitmap
 *
 * DESCRIPTION   =
 *
 *
 * INPUT         = hanDC              DcH
 *                 PBITMAPINFOHEADER2 lpInfoHdr
 *                 ULONG              ArgUsage
 *                 PBYTE              ArgBits
 *                 PBITMAPINFO2       lpInitInfo
 *                 lpDCI              DCIData
 *                 ULONG              FunN
 *
 *
 * OUTPUT        = ULONG
 *
 * RETURN-NORMAL = NONE
 *
 * RETURN-ERROR  = NONE
 *
 ****************************************************************************/

ULONG EXPENTRY prdn_DeviceCreateBitmap ( hanDC              DcH,
                                         PBITMAPINFOHEADER2 lpInfoHdr,
                                         ULONG              ArgUsage,
                                         PBYTE              ArgBits,
                                         PBITMAPINFO2       lpInitInfo,
                                         lpDCI              DCIData,
                                         ULONG              FunN )
{
    PBYTE              pbTemp;
    ULONG              ulReturn;

    BITMAPINFOHEADER2  InfoHdr;
    PBITMAPINFOHEADER2 newInfoHdr   = &InfoHdr;
    BITMAP_INFO2        InitInfo;
    PBITMAP_INFO2       newInitInfo = &InitInfo;
    PBITMAPINFOHEADER  oldlpInfoHdr;
    PBITMAPINFO        oldlpInitInfo;

    PBITMAPINFO2       tempInfo;
    SHORT              NEntries; /* # of valid entries in color table */
    SHORT              i;
    ULONG              Compression = FALSE;
    PBYTE              ArgBitmap;

    /*
    ** bitmap should be associated to some device. if not return error
    */
    if (!DcH)
       return(ERROR_ZERO);
    prdz_EnterDriver(DCIData);

    ArgBitmap  = (PBYTE)ArgBits;
    tempInfo   = lpInitInfo;

    /*
    **  If the lpInfoHdr is of type PBITMAPINFOHEADER2 then check if
    **  ArgBits is compressed. If so call gre to decompress ArgBits.
    **  decompressd bits will be in ArgBitmap.
    **  then fall thru to the code used for BITMAPINFO2.
    */


    if (lpInfoHdr->cbFix > sizeof(BITMAPINFOHEADER))
    {
    /*
    **            Adding (ArgUsage & CBM_INIT) && is the fix for our trap
    ** in 1-2-3G
    */
        if ((ArgUsage & CBM_INIT) && lpInfoHdr->cbFix > MIN_BITMAPINFO2
                                    && lpInitInfo->ulCompression)
        {
           Compression = CBD_DECOMPRESSION;
           ulReturn = CompDeCompBull(DcH,lpInitInfo,ArgBits,&tempInfo,&ArgBitmap,
                                              DCIData,FunN,Compression);
           if (ulReturn == GPI_ERROR)
               return(ulReturn);
        }
        /*
        **  It is BITMAPINFO2 with or without compression.
        **  if it is with compression, bitmap is decompressed by now.
        **  so simply call prdb_DeviceCreateBitmap.
        */

        ulReturn = prdb_DeviceCreateBitmap(DcH,lpInfoHdr,ArgUsage,ArgBitmap,
                                                       tempInfo,DCIData,FunN);
        if (Compression)   /* if we called compdecompbull, delete the memory */
            SSFREEMEM(tempInfo);
        prdm_LeaveDriver(DCIData);
        return(ulReturn);

    }
    /*
    **  lpInitInfo is PBITMAPINFO. So copy the values into our
    **  structures and call the function.
    */

    pbTemp = (PBYTE) lpInfoHdr;
    oldlpInfoHdr = (PBITMAPINFOHEADER) pbTemp;

    newInfoHdr->cbFix           = sizeof(BITMAPINFOHEADER2);
    newInfoHdr->cx              = oldlpInfoHdr->cx;
    newInfoHdr->cy              = oldlpInfoHdr->cy;
    newInfoHdr->cPlanes         = oldlpInfoHdr->cPlanes;
    newInfoHdr->cBitCount       = oldlpInfoHdr->cBitCount;

    if (ArgUsage & CBM_INIT)
    {
        pbTemp                 = (PBYTE) lpInitInfo;
        oldlpInitInfo          = (PBITMAPINFO) pbTemp;
        newInitInfo->cbFix     = sizeof(BITMAPINFOHEADER2);
        newInitInfo->cx        = oldlpInitInfo->cx;
        newInitInfo->cy        = oldlpInitInfo->cy;
        newInitInfo->cPlanes   = oldlpInitInfo->cPlanes;
        newInitInfo->cBitCount = oldlpInitInfo->cBitCount;
        if (oldlpInitInfo->cBitCount != 24)
        {
            NEntries = 2 << ((oldlpInitInfo->cBitCount)-1); /* # valid entries    */
            for(i = 0 ; i < NEntries ; i++)
            {
                newInitInfo->argbColor[i].bBlue  = oldlpInitInfo->argbColor[i].bBlue;
                newInitInfo->argbColor[i].bGreen = oldlpInitInfo->argbColor[i].bGreen;
                newInitInfo->argbColor[i].bRed   = oldlpInitInfo->argbColor[i].bRed;
            }
        }
    }
    else
    {
        /*
        **  There is no oldlpInitInfo...  so pass in a null...
        */
        newInitInfo = FNULL;
    }
    ulReturn = prdb_DeviceCreateBitmap(DcH,newInfoHdr,ArgUsage,ArgBits,
                                 (PBITMAPINFO2)newInitInfo,DCIData,FunN);
    prdm_LeaveDriver(DCIData);
    return(ulReturn);
}


/****************************************************************************
 *
 * FUNCTION NAME = prdn_GetSetBitmapBits
 *
 * DESCRIPTION   =
 *
 *
 * INPUT         = hanDC        DcH
 *                 PBYTE        hBitmap
 *                 ULONG        ArgScanStart
 *                 ULONG        ArgScanCount
 *                 PBYTE        ArgAddress
 *                 PBITMAPINFO2 ArgInfo
 *                 lpDCI        DCIData
 *                 ULONG        FunN
 *
 * OUTPUT        = ULONG EXPENTRY
 *
 * RETURN-NORMAL = NONE
 *
 * RETURN-ERROR  = NONE
 *
 ****************************************************************************/

ULONG EXPENTRY prdn_GetSetBitmapBits( hanDC        DcH,
                                      PBYTE        hBitmap,
                                      ULONG        ArgScanStart,
                                      ULONG        ArgScanCount,
                                      PBYTE        ArgAddress,
                                      PBITMAPINFO2 ArgInfo,
                                      lpDCI        DCIData,
                                      ULONG        FunN )
{
    PBYTE              pbTemp;
    ULONG              ulReturn;
    BITMAP_INFO2       InitInfo;
    PBITMAP_INFO2      newInitInfo = &InitInfo;
    PBITMAPINFO        oldArgInfo;
    SHORT              NEntries; /* # of valid entries in color table */
    SHORT              i;

    if (!prdz_EnterDriver(DCIData))
        return(ERROR_NEG);

    /*
    ** If the ArgInfo is of type PBITMAPINFO2 then just call
    ** the function with all the parameters
    */
    if (ArgInfo->cbFix > sizeof(BITMAPINFO))
    {
        ulReturn = prdb_GetSetBitmapBits(DcH,hBitmap,ArgScanStart,ArgScanCount,
                                       ArgAddress,ArgInfo,DCIData,FunN);
        prdm_LeaveDriver(DCIData);
        return(ulReturn);
    }
    /*
    **  No. so copy the values into our structure and call the function
    */
    pbTemp  = (PBYTE)ArgInfo;
    oldArgInfo = (PBITMAPINFO) pbTemp;
    newInitInfo->cbFix          = sizeof(BITMAPINFOHEADER2);
    newInitInfo->cx             = oldArgInfo->cx;
    newInitInfo->cy             = oldArgInfo->cy;
    newInitInfo->cPlanes        = oldArgInfo->cPlanes;
    newInitInfo->cBitCount      = oldArgInfo->cBitCount;
    newInitInfo->ulCompression  = FALSE;

    if (oldArgInfo->cBitCount != 24)
    {
        NEntries = 2 << ((oldArgInfo->cBitCount)-1); /* # valid entries    */
        for(i = 0 ; i < NEntries ; i++)
        {
           newInitInfo->argbColor[i].bBlue  = oldArgInfo->argbColor[i].bBlue;
           newInitInfo->argbColor[i].bGreen = oldArgInfo->argbColor[i].bGreen;
           newInitInfo->argbColor[i].bRed   = oldArgInfo->argbColor[i].bRed;
        }
    }
    ulReturn = prdb_GetSetBitmapBits(DcH,hBitmap,ArgScanStart,ArgScanCount,
                                   ArgAddress,(PBITMAPINFO2)newInitInfo,DCIData,FunN);

    if (ulReturn != ERROR_NEG)
    {
        oldArgInfo->cx             = newInitInfo->cx;
        oldArgInfo->cy             = newInitInfo->cy;
        oldArgInfo->cPlanes        = newInitInfo->cPlanes;
        oldArgInfo->cBitCount      = newInitInfo->cBitCount;
        if (oldArgInfo->cBitCount != 24)
        {
           NEntries = 2 << ((oldArgInfo->cBitCount)-1); /* # valid entries    */
           for(i = 0 ; i < NEntries ; i++)
           {
              oldArgInfo->argbColor[i].bBlue  = newInitInfo->argbColor[i].bBlue;
              oldArgInfo->argbColor[i].bGreen = newInitInfo->argbColor[i].bGreen;
              oldArgInfo->argbColor[i].bRed   = newInitInfo->argbColor[i].bRed;
           }
        }
    }
    prdm_LeaveDriver(DCIData);
    return(ulReturn);
}
