|
|
/*++
Copyright (c) 1996-1999 Microsoft Corporation
Module Name
Abstract:
Lingyun Wang
Author:
Enviornment:
User Mode
Revision History:
--*/
#include "precomp.hxx"
#include <ddraw.h>
#include <ddrawp.h>
#include <ddrawi.h>
#pragma hdrstop
extern PFNTRANSBLT gpfnTransparentImage; extern PFNTRANSDIB gpfnTransparentDIBImage;
BOOL gbddrawSet = FALSE;
#if (_WIN32_WINNT == 0x400)
extern HMODULE ghddrawlib; extern BOOL gbddraw; extern PFN_GETSURFACEFROMDC pfnGetSurfaceFromDC; PFN_GETSURFACEFROMDC pfnGetSurfaceDesc;
PALETTEENTRY gapeVgaPalette[16] = { { 0, 0, 0, 0 }, { 0x80,0, 0, 0 }, { 0, 0x80,0, 0 }, { 0x80,0x80,0, 0 }, { 0, 0, 0x80, 0 }, { 0x80,0, 0x80, 0 }, { 0, 0x80,0x80, 0 }, { 0x80,0x80,0x80, 0 }, { 0xC0,0xC0,0xC0, 0 }, { 0xFF,0, 0, 0 }, { 0, 0xFF,0, 0 }, { 0xFF,0xFF,0, 0 }, { 0, 0, 0xFF, 0 }, { 0xFF,0, 0xFF, 0 }, { 0, 0xFF,0xFF, 0 }, { 0xFF,0xFF,0xFF, 0 } };
/**************************************************************************\
* Dprintf * * * Arguments: * * szFmt - format string and argrs * * Return Value: * * none * * History: * * \**************************************************************************/
#if DBG
VOID Dprintf( LPSTR szFmt, ... ) { TCHAR szMsg[80]; DWORD cb; va_list marker;
va_start( marker, szFmt ); wvsprintf( szMsg, szFmt, marker ); cb = lstrlen(szMsg); szMsg[cb++] = '\r'; szMsg[cb++] = '\n'; WriteFile( GetStdHandle( STD_OUTPUT_HANDLE ), szMsg, sizeof(TCHAR) * cb, &cb, NULL );
va_end( marker );
return; } #else
VOID Dprintf (LPSTR szFmt, ...) { return; } #endif
/******************************Public*Routine******************************\
* MyGetSystemPaletteEntries * * Internal version of GetSystemPaletteEntries. * * GetSystemPaletteEntries fails on some 4bpp devices. This version * will detect the 4bpp case and supply the hardcoded 16-color VGA palette. * Otherwise, it will pass the call on to GDI's GetSystemPaletteEntries. * * It is expected that this call will only be called in the 4bpp and 8bpp * cases as it is not necessary for OpenGL to query the system palette * for > 8bpp devices. * * History: * 17-Aug-1995 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
static UINT MyGetSystemPaletteEntries(HDC hdc, UINT iStartIndex, UINT nEntries, LPPALETTEENTRY lppe) { int nDeviceBits;
nDeviceBits = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
//
// Some 4bpp displays will fail the GetSystemPaletteEntries call.
// So if detected, return the hardcoded table.
//
if ( nDeviceBits == 4 ) { if ( lppe ) { nEntries = min(nEntries, (16 - iStartIndex));
memcpy(lppe, &gapeVgaPalette[iStartIndex], nEntries * sizeof(PALETTEENTRY)); } else nEntries = 16;
return nEntries; } else { return GetSystemPaletteEntries(hdc, iStartIndex, nEntries, lppe); } }
/******************************Public*Routine******************************\
* bFillColorTable * * Initialize the color table of the BITMAPINFO pointed to by pbmi. Colors * are set to the current system palette. * * Note: call only valid for displays of 8bpp or less. * * Returns: * TRUE if successful, FALSE otherwise. * * History: * 23-Jan-1996 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
static BOOL bFillColorTable(HDC hdc, HPALETTE hpal, BITMAPINFO *pbmi) { BOOL bRet = FALSE; BYTE aj[sizeof(PALETTEENTRY) * 256]; LPPALETTEENTRY lppe = (LPPALETTEENTRY) aj; RGBQUAD *prgb = (RGBQUAD *) &pbmi->bmiColors[0]; ULONG cColors;
cColors = 1 << pbmi->bmiHeader.biBitCount;
if ( cColors <= 256 ) { if ( hpal ? GetPaletteEntries(hpal, 0, cColors, lppe) : MyGetSystemPaletteEntries(hdc, 0, cColors, lppe) ) { UINT i;
for (i = 0; i < cColors; i++) { prgb[i].rgbRed = lppe[i].peRed; prgb[i].rgbGreen = lppe[i].peGreen; prgb[i].rgbBlue = lppe[i].peBlue; prgb[i].rgbReserved = 0; }
bRet = TRUE; } else { //WARNING ("bFillColorTable: MyGetSystemPaletteEntries failed\n");
} }
return bRet; }
/******************************Public*Routine******************************\
* bFillBitmapInfoDirect * * Fills in the fields of a BITMAPINFO so that we can create a bitmap * that matches the format of the display. * * This is done by creating a compatible bitmap and calling GetDIBits * to return the color masks. This is done with two calls. The first * call passes in biBitCount = 0 to GetDIBits which will fill in the * base BITMAPINFOHEADER data. The second call to GetDIBits (passing * in the BITMAPINFO filled in by the first call) will return the color * table or bitmasks, as appropriate. * * Returns: * TRUE if successful, FALSE otherwise. * * History: * 07-Jun-1995 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
BOOL bFillBitmapInfoDirect(HDC hdc, HPALETTE hpal, BITMAPINFO *pbmi) { HBITMAP hbm; BOOL bRet = FALSE;
//
// Create a dummy bitmap from which we can query color format info
// about the device surface.
//
if ((hbm = CreateCompatibleBitmap(hdc, 1, 1)) != NULL) { pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
//
// Call first time to fill in BITMAPINFO header.
//
GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS);
if (( pbmi->bmiHeader.biBitCount <= 8 ) || ( pbmi->bmiHeader.biCompression == BI_BITFIELDS )) { //
// Call a second time to get the color masks.
// It's a GetDIBits Win32 "feature".
//
GetDIBits(hdc, hbm, 0, pbmi->bmiHeader.biHeight, NULL, pbmi, DIB_RGB_COLORS); }
bRet = TRUE;
DeleteObject(hbm); } else { WARNING("bFillBitmapInfoDirect: CreateCompatibleBitmap failed\n"); }
return bRet; }
/******************************Public*Routine******************************\
* bFillBitmapInfoMemory * * Fills in the fields of a BITMAPINFO so that we can create a bitmap * that matches the format of a memory DC. * * * Returns: * TRUE if successful, FALSE otherwise. * * History: * 05-Dec-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/ BOOL bFillBitmapInfoMemory(HDC hdc, HPALETTE hpal, BITMAPINFO *pbmi) { HBITMAP hbm; BOOL bRet = FALSE;
if ( (hbm = (HBITMAP)GetCurrentObject(hdc, OBJ_BITMAP)) != NULL ) { pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
//
// Call first time to fill in BITMAPINFO header.
//
GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS);
if (( pbmi->bmiHeader.biBitCount <= 8 ) || ( pbmi->bmiHeader.biCompression == BI_BITFIELDS )) { //
// Call a second time to get the color masks.
// It's a GetDIBits Win32 "feature".
//
GetDIBits(hdc, hbm, 0, pbmi->bmiHeader.biHeight, NULL, pbmi, DIB_RGB_COLORS); }
bRet = TRUE; } else { WARNING("bFillBitmapInfoMemory: CreateCompatibleBitmap failed\n"); }
return bRet; }
/******************************Public*Routine******************************\
* bFillDIBSection * * Fill in the DIBSection structure for a memory dc * Fills in the fields of a BITMAPINFO so that we can create a bitmap * that matches the format of a memory DC. * * * Returns: * TRUE if successful, FALSE otherwise. * * History: * 05-Dec-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/ BOOL bFillDIBSection( PDIBINFO pDibInfo) { HBITMAP hbm; BOOL bRet = FALSE; BOOL bddraw = FALSE; DIBSECTION dib;
if ( (hbm = (HBITMAP)GetCurrentObject(pDibInfo->hdc, OBJ_BITMAP)) != NULL ) { GetObject (hbm, sizeof(DIBSECTION), &dib);
#if 0
Dprintf ("DIBSECTION is:\n");
Dprintf("bmType=%x dsBm.bmBits = %x\n", dib.dsBm.bmType, dib.dsBm.bmBits);
Dprintf("bmWidth = %x, bmHeight = %x, bmWidthBytes = %x \n", dib.dsBm.bmWidth, dib.dsBm.bmHeight, dib.dsBm.bmWidthBytes);
Dprintf("bmPlanes = %x, bmBitsPixel = %x\n",dib.dsBm.bmPlanes, dib.dsBm.bmBitsPixel);
Dprintf("dsBmh.biSize=%x, biWidth = %x, biHeight = %x\n", dib.dsBmih.biSize, dib.dsBmih.biWidth, dib.dsBmih.biHeight);
Dprintf("dsBmh.biPlanes = %x, biBitCount = %x, biCompression = %x, biSizeImage = %x\n", dib.dsBmih.biPlanes, dib.dsBmih.biBitCount, dib.dsBmih.biSizeImage); #endif
//
// it is a DIBSECTION
//
if ((pDibInfo->pvBits = dib.dsBm.bmBits) != NULL) { //
// it is a DIBSection, now see if it might be a DD Surface (on WIn95)
//
// gbddraw is set at msimg32.dll's dll init time
// gbddrawSet is set by ddraw.dll at its init time
//
if (gbddraw || gbddrawSet) { //
// if this is the first time we call in here
//
if (!ghddrawlib) { //
// increment handle count for ddraw.dll
//
ghddrawlib = LoadLibrary (TEXT("ddraw.dll"));
//Dprintf("LoadLibrary returns %x", hddrawlib);
if (ghddrawlib) pfnGetSurfaceFromDC = (PFN_GETSURFACEFROMDC)GetProcAddress( ghddrawlib, "GetSurfaceFromDC"); }
HDC hdcDevice;
HRESULT ddVal;
if (pfnGetSurfaceFromDC && ((ddVal = pfnGetSurfaceFromDC(pDibInfo->hdc, &pDibInfo->pdds, &hdcDevice)) == DD_OK)) { bddraw = TRUE;
ddVal = pDibInfo->pdds->GetSurfaceDesc(&pDibInfo->ddsd);
//
// !!we DON'T need to lock the surface here, GetDC will do an internal lock
// until dc is release!!
//
if (ddVal == DD_OK) { Dprintf("pfnGetSurfaceFromDC succeed\n");
// printout ddsurface
Dprintf ("ddsd.lpSurface = %x\n", pDibInfo->ddsd.lpSurface); Dprintf ("ddsd.lPitch = %x\n", pDibInfo->ddsd.lPitch); Dprintf ("ddsd.dwWidth = %x, ddsd.dwHight = %x\n", pDibInfo->ddsd.dwWidth, pDibInfo->ddsd.dwHeight); Dprintf ("ddsd.ddpfPixelFormat.dwRGBBitCount=%x\n", pDibInfo->ddsd.ddpfPixelFormat.dwRGBBitCount);
//
// correct the stride
//
dib.dsBm.bmWidthBytes = pDibInfo->ddsd.lPitch;
#if 0
pDibInfo->stride = pDibInfo->ddsd.lPitch;
pDibInfo->pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pDibInfo->pbmi->bmiHeader.biCompression = BI_RGB; pDibInfo->pbmi->bmiHeader.biPlanes = 1;
pDibInfo->pbmi->bmiHeader.biWidth = pDibInfo->ddsd.dwWidth; pDibInfo->pbmi->bmiHeader.biHeight = pDibInfo->ddsd.dwHeight;
switch (pDibInfo->ddsd.ddpfPixelFormat.dwRGBBitCount) { case DDBD_1: pDibInfo->pbmi->bmiHeader.biBitCount = 1; break;
case DDBD_4: pDibInfo->pbmi->bmiHeader.biBitCount = 4; break;
case DDBD_8: pDibInfo->pbmi->bmiHeader.biBitCount = 8; bFillColorTable (pDibInfo->hdc, 0, pDibInfo->pbmi); break;
case DDBD_16: pDibInfo->pbmi->bmiHeader.biBitCount = 16; *(DWORD *)&pDibInfo->pbmi->bmiColors[0] = pDibInfo->ddsd.ddpfPixelFormat.dwRBitMask; *(DWORD *)&pDibInfo->pbmi->bmiColors[1] = pDibInfo->ddsd.ddpfPixelFormat.dwGBitMask; *(DWORD *)&pDibInfo->pbmi->bmiColors[2] = pDibInfo->ddsd.ddpfPixelFormat.dwBBitMask; break;
case DDBD_24: pDibInfo->pbmi->bmiHeader.biBitCount = 24; break;
case DDBD_32: pDibInfo->pbmi->bmiHeader.biBitCount = 32; break; default: WARNING("bad bitformat for ddraw surface\n"); }
pDibInfo->rclClipDC.left = 0; pDibInfo->rclClipDC.top =0; pDibInfo->rclClipDC.right = pDibInfo->ddsd.dwWidth; pDibInfo->rclClipDC.bottom = pDibInfo->ddsd.dwHeight; #endif
bRet = TRUE; } else { Dprintf("fail to GET the surface, ddVal = %x\n", ddVal); } } else { Dprintf("fail GetSurfaceFromDC, ddVal = %x\n", ddVal); } }
Dprintf ("bddraw = %x\n", gbddraw);
//
// continue with dibsection
//
{ //
// If biHeight is positive, then the bitmap is a bottom-up DIB.
// If biHeight is negative, then the bitmap is a top-down DIB.
//
{ // WINBUG #365315 4-10-2001 jasonha Bug in bFillDIBSection
//
// Old Comment:
// GDI Bug 19374: bmWidthBytes returns pitch assuming
// that DIB scanlines are WORD aligned (as they
// are in Win95). But NT DIBs are DWORD aligned.
// When bug if corrected, we can remove this block of
// code.
OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof(osvi); if (GetVersionEx(&osvi)) { if ( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT ) { dib.dsBm.bmWidthBytes = (dib.dsBm.bmWidthBytes + 3) & ~3; } } else { return bRet; } }
if ( dib.dsBmih.biHeight > 0 ) { pDibInfo->pvBase = (PVOID) (((int) dib.dsBm.bmBits) + (dib.dsBm.bmWidthBytes * (dib.dsBm.bmHeight - 1)));
pDibInfo->stride = (ULONG) (-dib.dsBm.bmWidthBytes); } else { pDibInfo->pvBase = dib.dsBm.bmBits;
pDibInfo->stride = dib.dsBm.bmWidthBytes; }
//
// fill up the BITMAPINFOHEADER
//
pDibInfo->pbmi->bmiHeader = dib.dsBmih;
//
// fill up the color table
//
if ((pDibInfo->pbmi->bmiHeader.biBitCount <= 8) || ( pDibInfo->pbmi->bmiHeader.biCompression == BI_BITFIELDS )) { ULONG count = 1 << pDibInfo->pbmi->bmiHeader.biBitCount;
GetDIBits(pDibInfo->hdc, hbm, 0, pDibInfo->pbmi->bmiHeader.biHeight, NULL, pDibInfo->pbmi, DIB_RGB_COLORS);
}
//
// fill prcl
//
pDibInfo->rclClipDC.left = 0; pDibInfo->rclClipDC.top = 0; pDibInfo->rclClipDC.right = dib.dsBm.bmWidth; pDibInfo->rclClipDC.bottom = dib.dsBm.bmHeight;
if (pDibInfo->rclClipDC.bottom < 0) { pDibInfo->rclClipDC.bottom = -pDibInfo->rclClipDC.bottom; }
bRet = TRUE; }
} else { Dprintf("not a dibseciton"); } } return(bRet); }
/******************************Public*Routine******************************\
* bFillBimapInfo * * Fill up the BITMAPINFO structure based on the hdc passed in * and fill up the window(if direct dc) or surface (if memory dc) * rectangle. * * if it's a dibsection, convert DIBSECTION to BITMAPINFO * * Returns: * BOOLEAN * * History: * 09-Dec-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/ BOOL bFillBitmapInfo( PDIBINFO pDibInfo ) { BOOL bRet = FALSE;
//
// if it is printer surface, return TRUE
//
if (GetDeviceCaps(pDibInfo->hdc, TECHNOLOGY) == DT_RASPRINTER) { pDibInfo->flag |= PRINTER_DC; pDibInfo->rclClipDC.left = 0; pDibInfo->rclClipDC.right = GetDeviceCaps(pDibInfo->hdc, HORZRES); pDibInfo->rclClipDC.top = 0; pDibInfo->rclClipDC.bottom = GetDeviceCaps(pDibInfo->hdc, VERTRES);
pDibInfo->rclDIB = pDibInfo->rclClipDC;
return (TRUE); }
{ //
// fill up a BITMAPINFO structure compatible with the
// Destination DC and reduce ulWidth and ulHeight if
// possible
//
if (GetObjectType(pDibInfo->hdc) == OBJ_DC) { //
// get the destination bitmapinfo struct
//
if (bRet = bFillBitmapInfoDirect(pDibInfo->hdc, 0, pDibInfo->pbmi)) { HWND hwnd = WindowFromDC(pDibInfo->hdc);
if (hwnd) { GetClientRect(hwnd,(RECT *)&pDibInfo->rclClipDC); } } } else if (GetObjectType(pDibInfo->hdc) == OBJ_MEMDC) { if (!(bRet = bFillDIBSection (pDibInfo))) { //
// if the bitmap selected in the memory dc is NOT
// a DIBSECTION, call bFillBitmapInfoMemory
//
if (bRet = bFillBitmapInfoMemory(pDibInfo->hdc, 0, pDibInfo->pbmi)) { pDibInfo->rclClipDC.left = 0; pDibInfo->rclClipDC.top = 0; pDibInfo->rclClipDC.right = pDibInfo->pbmi->bmiHeader.biWidth; pDibInfo->rclClipDC.bottom = pDibInfo->pbmi->bmiHeader.biHeight;
if (pDibInfo->rclClipDC.bottom < 0) { pDibInfo->rclClipDC.bottom = -pDibInfo->rclClipDC.bottom; } } }
} }
return(bRet); }
/******************************Public*Routine******************************\
* bSameDIBformat * * Given two BITMAPINFO structs and compare if they are the same * * Returns: * VOID * * History: * 09-Dec-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/ BOOL bSameDIBformat ( PBITMAPINFO pbmiDst, PBITMAPINFO pbmiSrc) { BOOL bRet = FALSE;
if ((pbmiDst->bmiHeader.biBitCount == pbmiSrc->bmiHeader.biBitCount) && (pbmiDst->bmiHeader.biCompression == pbmiSrc->bmiHeader.biCompression)) { bRet = TRUE;
//
// compare bit Bitfields masks
//
if (pbmiDst->bmiHeader.biCompression == BI_BITFIELDS) { if ((*(DWORD *)&pbmiDst->bmiColors[0] != *(DWORD *)&pbmiSrc->bmiColors[0]) || (*(DWORD *)&pbmiDst->bmiColors[1] != *(DWORD *)&pbmiSrc->bmiColors[1]) || (*(DWORD *)&pbmiDst->bmiColors[2] != *(DWORD *)&pbmiSrc->bmiColors[2])) { bRet = FALSE; } }
//
// compare color table
//
if (pbmiDst->bmiHeader.biBitCount <= 8) { ULONG cColors = 1 << pbmiDst->bmiHeader.biBitCount; ULONG i;
for (i = 0; i < cColors; i++) { if ((pbmiDst->bmiColors[i].rgbBlue != pbmiSrc->bmiColors[i].rgbBlue) || (pbmiDst->bmiColors[i].rgbGreen != pbmiSrc->bmiColors[i].rgbGreen) || (pbmiDst->bmiColors[i].rgbRed != pbmiSrc->bmiColors[i].rgbRed))
{ return (FALSE); } } } } return (bRet); } /******************************Public*Routine******************************\
* CreateCompatibleDIB * * Create a DIB_RGB_COLORS dib section based on the given width/height and pbmi * * Returns: * Bitmap handle * * History: * 09-Dec-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/ HBITMAP CreateCompatibleDIB ( HDC hdc, ULONG ulWidth, ULONG ulHeight, PVOID *ppvBits, PBITMAPINFO pbmi) { HBITMAP hbm;
//
// Change bitmap size to match specified dimensions.
//
pbmi->bmiHeader.biWidth = ulWidth; pbmi->bmiHeader.biHeight = ulHeight;
if (pbmi->bmiHeader.biCompression == BI_RGB) { pbmi->bmiHeader.biSizeImage = 0; } else { if ( pbmi->bmiHeader.biBitCount == 16 ) pbmi->bmiHeader.biSizeImage = ulWidth * ulHeight * 2; else if ( pbmi->bmiHeader.biBitCount == 32 ) pbmi->bmiHeader.biSizeImage = ulWidth * ulHeight * 4; else pbmi->bmiHeader.biSizeImage = 0; }
pbmi->bmiHeader.biClrUsed = 0; pbmi->bmiHeader.biClrImportant = 0;
hbm = CreateDIBSection(hdc, (PBITMAPINFO)pbmi, DIB_RGB_COLORS, ppvBits, NULL, 0);
return (hbm); }
/******************************Public*Routine******************************\
* GetCompatibleDIBInfo * * Copies pointer to bitmap origin to ppvBase and bitmap stride to plStride. * Win32 DIBs can be created bottom-up (the default) with the origin at the * lower left corner or top-down with the origin at the upper left corner. * If the bitmap is top-down, *plStride is positive; if bottom-up, *plStride * us negative. * * Also, because of restrictions on the alignment of scan lines the width * the bitmap is often not the same as the stride (stride is the number of * bytes between vertically adjacent pixels). * * The ppvBase and plStride value returned will allow you to address any * given pixel (x, y) in the bitmap as follows: * * PIXEL *ppix; * * ppix = (PIXEL *) (((BYTE *)*ppvBase) + (y * *plStride) + (x * sizeof(PIXEL))); * * Returns: * TRUE if successful, FALSE otherwise. * * History: * 02-Feb-1996 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
BOOL GetCompatibleDIBInfo(HBITMAP hbm, PVOID *ppvBase, LONG *plStride) { BOOL bRet = FALSE; DIBSECTION ds;
//
// Call GetObject to return a DIBSECTION. If successful, the
// bitmap is a DIB section and we can retrieve the pointer to
// the bitmap bits and other parameters.
//
if ( (GetObject(hbm, sizeof(ds), &ds) == sizeof(ds)) && ds.dsBm.bmBits ) { // WINBUG #365315 4-10-2001 jasonha Bug in GetCompatibleDIBInfo
//
// Old Comment:
// GDI Bug 19374: bmWidthBytes returns pitch assuming
// that DIB scanlines are WORD aligned (as they
// are in Win95). But NT DIBs are DWORD aligned.
// When bug if corrected, we can remove this block of
// code.
{ OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(osvi); if (GetVersionEx(&osvi)) { if ( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT ) { ds.dsBm.bmWidthBytes = (ds.dsBm.bmWidthBytes + 3) & ~3; } } else { return bRet; } }
//
// If biHeight is positive, then the bitmap is a bottom-up DIB.
// If biHeight is negative, then the bitmap is a top-down DIB.
//
if ( ds.dsBmih.biHeight > 0 ) { *ppvBase = (PVOID) (((int) ds.dsBm.bmBits) + (ds.dsBm.bmWidthBytes * (ds.dsBm.bmHeight - 1))); *plStride = (ULONG) (-ds.dsBm.bmWidthBytes); } else { *ppvBase = ds.dsBm.bmBits; *plStride = ds.dsBm.bmWidthBytes; }
bRet = TRUE; } else { WARNING("GetCompatibleDIBInfo: cannot get pointer to DIBSECTION bmBits\n"); }
return bRet; }
/******************************************************
* bSetupBitmapInfos * * Calls bFillBitmapInfo to fill the Dst and Src DIBINFO * * 4/4/97 -- by Lingyun Wang [lingyunw] *******************************************************/ BOOL bSetupBitmapInfos( PDIBINFO pDibInfoDst, PDIBINFO pDibInfoSrc ) { BOOL bRet;
bRet = bFillBitmapInfo (pDibInfoDst);
//
// fill up bitmapinfo if it is not coming from TransparentDIBits
//
if (bRet && (pDibInfoSrc != NULL)) { if (pDibInfoSrc->hdc != NULL) { bRet = bFillBitmapInfo (pDibInfoSrc); } else { //
// src is DIB
//
pDibInfoSrc->rclClipDC.left = 0; pDibInfoSrc->rclClipDC.right = pDibInfoSrc->pbmi->bmiHeader.biWidth; pDibInfoSrc->rclClipDC.top = 0; pDibInfoSrc->rclClipDC.bottom = pDibInfoSrc->pbmi->bmiHeader.biHeight;
if (pDibInfoSrc->rclClipDC.bottom < 0) { pDibInfoSrc->rclClipDC.bottom = -pDibInfoSrc->rclClipDC.bottom; }
} }
return (bRet);
}
/******************************Public*Routine******************************\
* vCopyBitmapInfo * * Copy a BITMAPINFO stucture along with its bit masks or colortable * * Returns: * VOID. * * History: * 16-Dec-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/ VOID vCopyBitmapInfo ( PBITMAPINFO pbmiTo, PBITMAPINFO pbmiFrom ) { *pbmiTo = *pbmiFrom;
//
// copy BitFields masks
//
if (pbmiFrom->bmiHeader.biCompression == BI_BITFIELDS) { pbmiTo->bmiColors[0] = pbmiFrom->bmiColors[0]; pbmiTo->bmiColors[1] = pbmiFrom->bmiColors[1]; pbmiTo->bmiColors[2] = pbmiFrom->bmiColors[2]; } else { //
// copy color table
//
ULONG cMaxColors = 1 << pbmiFrom->bmiHeader.biBitCount; ULONG cColors = pbmiFrom->bmiHeader.biClrUsed;
//
// validate number of colors
//
if ((cColors == 0) || (cColors > cMaxColors)) { cColors = cMaxColors; }
if (cColors <= 256) { UINT i;
for (i = 0; i < cColors; i++) { pbmiTo->bmiColors[i] = pbmiFrom->bmiColors[i]; } } }
return; }
/**************************************************************************\
* vIndexToRGB * * * Arguments: * * * * Return Value: * * * * History: * * 4/16/1997 -by- Lingyun Wang [lingyunw] * \**************************************************************************/
VOID vIndexToRGB ( RGBQUAD *pIndex, RGBQUAD *pColors, ULONG count) { ULONG i;
if (count > 256) { WARNING ("vIndexToRGB -- bad count\n"); return; }
for (i=0; i < count; i++) { pIndex[i] = pColors[((ULONG *)pIndex)[i]]; } return; }
#if 1
/******************************Public*Routine******************************\
* vMapPALtoRGB * * Given a DIB_PAL_COLORS iusage bmiColors table, convert the indices into RGB * colors, the bmiColors table will be a DIB_RGB_COLORS table after the convertion. * * Returns: * VOID. * * History: * 16-Dec-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/
VOID vMapPALtoRGB( PDIBINFO pDibInfoDst, PDIBINFO pDibInfoSrc, ULONG TransColor) { //
// only called in DIB API case
//
if (pDibInfoSrc->hdc == NULL) { PBITMAPINFO pbmi = (PBITMAPINFO)LOCALALLOC(sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255);
if (pbmi) { ZeroMemory (pbmi,sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255); vCopyBitmapInfo(pbmi, pDibInfoSrc->pbmi);
HPALETTE hpalDC = (HPALETTE)GetCurrentObject(pDibInfoDst->hdc,OBJ_PAL);
if (hpalDC) { USHORT usNumPaletteEntries = 0; DWORD numColors; DWORD bmiClrUsed = pDibInfoSrc->pbmi->bmiHeader.biClrUsed;
int iRet = GetObject(hpalDC,2,&usNumPaletteEntries);
if ((iRet != 0) && (usNumPaletteEntries != 0)) { switch (pDibInfoSrc->pbmi->bmiHeader.biBitCount) { case 1: numColors = 2; break;
case 4: numColors = 16; if ((bmiClrUsed > 0) && (bmiClrUsed < 16) ) { numColors = bmiClrUsed; } break;
case 8: numColors = 256; if ((bmiClrUsed > 0) && (bmiClrUsed < 256) ) { numColors = bmiClrUsed; } break; default: numColors = 0; }
if (numColors != 0) { PALETTEENTRY *ppal = (PALETTEENTRY *)LOCALALLOC(sizeof(PALETTEENTRY) * usNumPaletteEntries);
if (ppal) { iRet = GetPaletteEntries(hpalDC,0,usNumPaletteEntries,ppal);
if (iRet == (int)usNumPaletteEntries) { ULONG Index;
RGBQUAD *pRGB = (RGBQUAD *)&pbmi->bmiColors[0]; PUSHORT pPalIndex = (PUSHORT)&pDibInfoSrc->pbmi->bmiColors[0];
//
// map PALETTEENTRY to RGBQUAD
//
for (Index=0;Index<numColors;Index++) { ULONG CurIndex = pPalIndex[Index];
if (CurIndex > usNumPaletteEntries) { CurIndex = CurIndex % usNumPaletteEntries; }
pRGB[Index].rgbRed = ppal[CurIndex].peRed; pRGB[Index].rgbGreen = ppal[CurIndex].peGreen; pRGB[Index].rgbBlue = ppal[CurIndex].peBlue; pRGB[Index].rgbReserved = ppal[CurIndex].peFlags; }
//
// swap pbmi in pDibInfoSrc
//
LOCALFREE(pDibInfoSrc->pbmi);
pDibInfoSrc->pbmi = pbmi; }
LOCALFREE(ppal); } } } } } }
}
#else
/******************************Public*Routine******************************\
* vMapPALtoRGB * * Given a DIB_PAL_COLORS iusage bmiColors table, convert the indices into RGB * colors, the bmiColors table will be a DIB_RGB_COLORS table after the convertion. * * Returns: * VOID. * * History: * 16-Dec-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/
VOID vMapPALtoRGB( PDIBINFO pDibInfoDst, PDIBINFO pDibInfoSrc, ULONG TransColor) { HDC hdc = pDibInfoDst->hdc; HDC hdcMem; ULONG cx = 1 << pDibInfoSrc->pbmi->bmiHeader.biBitCount; HBITMAP hbm; PULONG pBits; ULONG cBytes = sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 2; PBITMAPINFO pbmi; ULONG i; BYTE pBytes[256]; ULONG ulWidthDst, ulHeightDst, ulWidthSrc, ulHeightSrc; HPALETTE hpalDC;
pbmi = (PBITMAPINFO)LOCALALLOC(cBytes);
if (pbmi == NULL) { WARNING("MapCopy fail to alloc mem\n"); return ; }
hdcMem = CreateCompatibleDC (hdc);
if (hdcMem != NULL) { HPALETTE hpalDC = (HPALETTE)GetCurrentObject(hdc,OBJ_PAL);
SelectPalette(hdcMem,hpalDC,TRUE); RealizePalette(hdcMem);
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pbmi->bmiHeader.biWidth = 256; pbmi->bmiHeader.biHeight = 1; pbmi->bmiHeader.biPlanes = 1; pbmi->bmiHeader.biBitCount = 32; pbmi->bmiHeader.biCompression = BI_RGB; pbmi->bmiHeader.biSizeImage = 0; pbmi->bmiHeader.biXPelsPerMeter = 0; pbmi->bmiHeader.biYPelsPerMeter = 0; pbmi->bmiHeader.biClrUsed = 0; pbmi->bmiHeader.biClrImportant = 0;
//
// save the original width/height
//
ulWidthDst = pDibInfoDst->pbmi->bmiHeader.biWidth; ulHeightDst = pDibInfoDst->pbmi->bmiHeader.biHeight;
pDibInfoDst->pbmi->bmiHeader.biWidth = 256; pDibInfoDst->pbmi->bmiHeader.biHeight = 1;
//
// create a dib using 32 format
//
hbm = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (PVOID *)&pBits, NULL, 0);
if ((hbm != NULL) && (SelectObject(hdcMem,hbm) != NULL)) { //
// init pBytes to array of each pixel
//
switch (cx) { case 256: for (i=0; i < cx; i++) { pBytes[i] = (BYTE)i; } break;
case 16: pBytes[0] = 0x01; pBytes[1] = 0x23; pBytes[2] = 0x45; pBytes[3] = 0x67; pBytes[4] = 0x89; pBytes[5] = 0xab; pBytes[6] = 0xcd; pBytes[7] = 0xef; break;
case 2: pBytes[0] = 0x40; break; }
ulWidthSrc = pDibInfoSrc->pbmi->bmiHeader.biWidth; ulHeightSrc = pDibInfoSrc->pbmi->bmiHeader.biHeight;
pDibInfoSrc->pbmi->bmiHeader.biWidth = cx; pDibInfoSrc->pbmi->bmiHeader.biHeight = 1;
if (!SetDIBitsToDevice (hdcMem, 0, 0, cx, 1, 0, 0, 0, 1, pBytes, pDibInfoSrc->pbmi, DIB_PAL_COLORS)) { //Dprintf("fail to SetDIBitsTodevice HDC=%x\n",hdcMem);
}
for (i=0; i < cx; i++) { pDibInfoSrc->pbmi->bmiColors[i] = ((RGBQUAD *)pBits)[i]; //Dprintf("i=%x, pBits[i]=%x", i, pBits[i]);
}
pDibInfoSrc->pbmi->bmiHeader.biWidth = ulWidthSrc; pDibInfoSrc->pbmi->bmiHeader.biHeight = ulHeightSrc;
pDibInfoDst->pbmi->bmiHeader.biWidth = ulWidthDst; pDibInfoDst->pbmi->bmiHeader.biHeight = ulHeightDst;
pDibInfoSrc->iUsage = DIB_RGB_COLORS; }
DeleteDC (hdcMem);
if (hbm != NULL) { DeleteObject(hbm); } } }
#endif
/**************************************************************************\
* bGetSrcDIBits: * * Setup SRC DIB surface and retrieve the dibits. * Ported from kernel mode * * Arguments: * * pDibInfoDst - information on dest surface * pDibInfoSrc - information on src surfcace * ulSourceType - type of src surface needed * ulTranColor - transparent color for TransparentBlt * * Return Value: * * Status * * History: * * 4/16/1997 - by Lingyun Wang [lingyunw] * \**************************************************************************/
BOOL bGetSrcDIBits( PDIBINFO pDibInfoDst, PDIBINFO pDibInfoSrc, ULONG ulSourceType, ULONG ulTranColor ) { BOOL bRet = TRUE; LONG DstCx = pDibInfoDst->rclBounds.right - pDibInfoDst->rclBounds.left; LONG DstCy = pDibInfoDst->rclBounds.bottom - pDibInfoDst->rclBounds.top;
LONG SrcCx = pDibInfoSrc->rclBounds.right - pDibInfoSrc->rclBounds.left; LONG SrcCy = pDibInfoSrc->rclBounds.bottom - pDibInfoSrc->rclBounds.top;
PVOID pvBits = pDibInfoSrc->pvBits; PBITMAPINFO pbmi = NULL; HDC hdcTemp = NULL; HBITMAP hbm;
LONG SrcTrimLeft; LONG SrcTrimRight; LONG SrcTrimTop; LONG SrcTrimBottom;
BOOL bStretch = ((DstCx != SrcCx) || (DstCy != SrcCy));
SrcTrimLeft = 0; SrcTrimRight = 0; SrcTrimTop = 0; SrcTrimBottom = 0;
//
// trim destination bounds rect to surface bounds. Src rect must also
// be trimmed by same amount (in src space)
//
if (pDibInfoDst->rclBoundsTrim.left < pDibInfoDst->rclClipDC.left) { SrcTrimLeft = pDibInfoDst->rclClipDC.left - pDibInfoDst->rclBoundsTrim.left; pDibInfoDst->rclBoundsTrim.left = pDibInfoDst->rclClipDC.left; }
if (pDibInfoDst->rclBoundsTrim.top < pDibInfoDst->rclClipDC.top) { SrcTrimTop = pDibInfoDst->rclClipDC.top - pDibInfoDst->rclBoundsTrim.top; pDibInfoDst->rclBoundsTrim.top = pDibInfoDst->rclClipDC.top; }
if (pDibInfoDst->rclBoundsTrim.right > pDibInfoDst->rclClipDC.right) { SrcTrimRight = pDibInfoDst->rclBoundsTrim.right - pDibInfoDst->rclClipDC.right; pDibInfoDst->rclBoundsTrim.right = pDibInfoDst->rclClipDC.right; }
if (pDibInfoDst->rclBoundsTrim.bottom > pDibInfoDst->rclClipDC.bottom) { SrcTrimBottom = pDibInfoDst->rclBoundsTrim.bottom - pDibInfoDst->rclClipDC.bottom; pDibInfoDst->rclBoundsTrim.bottom = pDibInfoDst->rclClipDC.bottom; }
//
// does src need to be reduced because of dst
//
if (bStretch) { //
// convert dst trim to src space and reduce src rect
//
// WARNING: ROUNDING
//
if ((SrcTrimLeft != 0) || (SrcTrimRight != 0)) { double fDstToSrcX = (double)SrcCx / (double)DstCx;
//
// convert dst trim amound to src
//
SrcTrimLeft = (LONG)((double)SrcTrimLeft * fDstToSrcX); SrcTrimRight = (LONG)((double)SrcTrimRight * fDstToSrcX);
pDibInfoSrc->rclBoundsTrim.left += SrcTrimLeft; pDibInfoSrc->rclBoundsTrim.right -= SrcTrimRight; }
if ((SrcTrimTop != 0) || (SrcTrimBottom != 0)) { double fDstToSrcY = (double)SrcCy / (double)DstCy;
//
// convert dst trim amound to src
//
SrcTrimTop = (LONG)((double)SrcTrimTop * fDstToSrcY); SrcTrimBottom = (LONG)((double)SrcTrimBottom * fDstToSrcY);
pDibInfoSrc->rclBoundsTrim.top += SrcTrimTop; pDibInfoSrc->rclBoundsTrim.bottom -= SrcTrimBottom; } } else { //
// reduce src rect
//
if (SrcTrimLeft != 0) { pDibInfoSrc->rclBoundsTrim.left += SrcTrimLeft; }
if (SrcTrimRight != 0) { pDibInfoSrc->rclBoundsTrim.right -= SrcTrimRight; }
if (SrcTrimTop != 0) { pDibInfoSrc->rclBoundsTrim.top += SrcTrimTop; }
if (SrcTrimBottom != 0) { pDibInfoSrc->rclBoundsTrim.bottom -= SrcTrimBottom; } }
//
// Does src still exceed bounds
//
SrcTrimLeft = 0; SrcTrimRight = 0; SrcTrimTop = 0; SrcTrimBottom = 0;
//
// trim destination bounds rect to surface bounds. Src rect must also
// be trimmed by same amount (in src space)
//
if (pDibInfoSrc->rclBoundsTrim.left < pDibInfoSrc->rclClipDC.left) { SrcTrimLeft = pDibInfoSrc->rclClipDC.left - pDibInfoSrc->rclBoundsTrim.left; pDibInfoSrc->rclBoundsTrim.left = pDibInfoSrc->rclClipDC.left; }
if (pDibInfoSrc->rclBoundsTrim.top < pDibInfoSrc->rclClipDC.top) { SrcTrimTop = pDibInfoSrc->rclClipDC.top - pDibInfoSrc->rclBoundsTrim.top; pDibInfoSrc->rclBoundsTrim.top = pDibInfoSrc->rclClipDC.top; }
if (pDibInfoSrc->rclBoundsTrim.right > pDibInfoSrc->rclClipDC.right) { SrcTrimRight = pDibInfoSrc->rclBoundsTrim.right - pDibInfoSrc->rclClipDC.right; pDibInfoSrc->rclBoundsTrim.right = pDibInfoSrc->rclClipDC.right; }
if (pDibInfoSrc->rclBoundsTrim.bottom > pDibInfoSrc->rclClipDC.bottom) { SrcTrimBottom = pDibInfoSrc->rclBoundsTrim.bottom - pDibInfoSrc->rclClipDC.bottom; pDibInfoSrc->rclBoundsTrim.bottom = pDibInfoSrc->rclClipDC.bottom; }
//
// Src rectangle is not allowed to exceed src surface bounds (same
// behavior as NT)
//
if (SrcTrimLeft || SrcTrimRight || SrcTrimTop || SrcTrimBottom) { WARNING("Error in dib.cxx: source rectangle exceeds source surface bounds"); return FALSE; } //
// does Dst need to be reduced because of Src
//
if (bStretch) { //
// WARNING: ROUNDING
//
if ((SrcTrimLeft != 0) || (SrcTrimRight != 0)) { double fSrcToDstX = (double)DstCx / (double)SrcCx;
//
// convert dst trim amound to src
//
SrcTrimLeft = (LONG)((double)SrcTrimLeft * fSrcToDstX); SrcTrimRight = (LONG)((double)SrcTrimRight * fSrcToDstX);
pDibInfoDst->rclBoundsTrim.left += SrcTrimLeft; pDibInfoDst->rclBoundsTrim.right -= SrcTrimRight; }
if ((SrcTrimTop != 0) || (SrcTrimBottom != 0)) { double fSrcToDstY = (double)DstCy / (double)SrcCy;
//
// convert dst trim amound to src
//
SrcTrimTop = (LONG)((double)SrcTrimTop * fSrcToDstY); SrcTrimBottom = (LONG)((double)SrcTrimBottom * fSrcToDstY);
pDibInfoDst->rclBoundsTrim.top += SrcTrimTop; pDibInfoDst->rclBoundsTrim.bottom -= SrcTrimBottom; } } else { //
// reduce dst rect
//
if (SrcTrimLeft != 0) { pDibInfoDst->rclBoundsTrim.left += SrcTrimLeft; }
if (SrcTrimRight != 0) { pDibInfoDst->rclBoundsTrim.right -= SrcTrimRight; }
if (SrcTrimTop != 0) { pDibInfoDst->rclBoundsTrim.top += SrcTrimTop; }
if (SrcTrimBottom != 0) { pDibInfoDst->rclBoundsTrim.bottom -= SrcTrimBottom; } }
//
// check for clipped out Dst and Src
//
if ( (pDibInfoDst->rclBoundsTrim.left < pDibInfoDst->rclBoundsTrim.right) && (pDibInfoDst->rclBoundsTrim.top < pDibInfoDst->rclBoundsTrim.bottom) && (pDibInfoSrc->rclBoundsTrim.left < pDibInfoSrc->rclBoundsTrim.right) && (pDibInfoSrc->rclBoundsTrim.top < pDibInfoSrc->rclBoundsTrim.bottom) ) {
if ((bStretch) || (pDibInfoSrc->pvBits == NULL)) { //
// allocate compatible DC and surface
//
hdcTemp = CreateCompatibleDC(pDibInfoSrc->hdc);
if (hdcTemp) { //
// copy pDibInfoSrc->pbmi into pbmi
//
if (!pDibInfoSrc->hdc) { ULONG cBytes = sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255; pbmi = (PBITMAPINFO)LOCALALLOC(cBytes);
if (pbmi != NULL) { ZeroMemory (pbmi,cBytes); vCopyBitmapInfo (pbmi, pDibInfoSrc->pbmi); } else { WARNING("bGetSrcDIBits fail to alloc mem\n"); bRet = FALSE; } }
if (bRet) { //
// create temp DIB size of dst rect
//
RECTL rclDstCopy = { 0, 0, pDibInfoDst->rclBoundsTrim.right - pDibInfoDst->rclBoundsTrim.left, pDibInfoDst->rclBoundsTrim.bottom - pDibInfoDst->rclBoundsTrim.top };
hbm = CreateCompatibleDIB(hdcTemp, rclDstCopy.right, rclDstCopy.bottom, &pDibInfoSrc->pvBits, pDibInfoSrc->pbmi);
if (hbm) { pDibInfoSrc->hDIB = hbm;
GetCompatibleDIBInfo (hbm, &pDibInfoSrc->pvBase, &pDibInfoSrc->stride);
HBITMAP hbmDefault = (HBITMAP)SelectObject (hdcTemp, hbm);
ULONG OldMode = SetStretchBltMode(hdcTemp,COLORONCOLOR);
//
// Stretch data into source temp DIB
//
//
// Blt data into source temp DIB
//
if (pDibInfoSrc->hdc) { StretchBlt (hdcTemp, 0, 0, rclDstCopy.right, rclDstCopy.bottom, pDibInfoSrc->hdc, pDibInfoSrc->rclBoundsTrim.left, pDibInfoSrc->rclBoundsTrim.top, pDibInfoSrc->rclBoundsTrim.right - pDibInfoSrc->rclBoundsTrim.left, pDibInfoSrc->rclBoundsTrim.bottom - pDibInfoSrc->rclBoundsTrim.top, SRCCOPY); } else {
//
// adjust ySrc to be compatible
//
LONG cySrc = pDibInfoSrc->rclBoundsTrim.bottom-pDibInfoSrc->rclBoundsTrim.top; LONG ySrc = pDibInfoSrc->rclClipDC.bottom - pDibInfoSrc->rclBoundsTrim.top - cySrc;
StretchDIBits (hdcTemp, 0, 0, rclDstCopy.right, rclDstCopy.bottom, pDibInfoSrc->rclBoundsTrim.left, ySrc, pDibInfoSrc->rclBoundsTrim.right-pDibInfoSrc->rclBoundsTrim.left, cySrc, pvBits, pbmi, DIB_RGB_COLORS, SRCCOPY); }
SetStretchBltMode(hdcTemp,OldMode);
SelectObject (hdcTemp, hbmDefault);
pDibInfoSrc->rclDIB = rclDstCopy; } else { WARNING ("bGetSrcDIBits -- fail to createcompatibleDIB\n"); bRet = FALSE; } } } else { WARNING ("bGetSrcDIBits -- fail to createcompatibledc\n"); bRet = FALSE; } } else { pDibInfoSrc->rclDIB = pDibInfoSrc->rclBoundsTrim; } } else { //
// clipped out
//
pDibInfoDst->rclBoundsTrim.left = pDibInfoDst->rclBoundsTrim.right = 0; pDibInfoDst->rclBoundsTrim.top = pDibInfoDst->rclBoundsTrim.bottom = 0; pDibInfoSrc->rclBoundsTrim.left = pDibInfoSrc->rclBoundsTrim.right = 0; pDibInfoSrc->rclBoundsTrim.top = pDibInfoSrc->rclBoundsTrim.bottom = 0; bRet = FALSE; }
if (pbmi) { LOCALFREE (pbmi); }
if (hdcTemp) { DeleteDC(hdcTemp); }
return(bRet); }
/******************************Public*Routine******************************\
* bGetDstDIBits * * Setup the destination DIB surface and retrieve the bits * * Ported from psSetupDstSurface * * * * Return Value: * * * * History: * * 4-April-1997 -by- Lingyun Wang [lingyunw] * \**************************************************************************/
BOOL bGetDstDIBits ( PDIBINFO pDibInfoDst, BOOL *pbReadable, FLONG flCopyMode ) { HDC hdc = pDibInfoDst->hdc; BOOL bRet = TRUE; int iRegionComplexity; RECT rclClipBox;
*pbReadable = TRUE;
//
// read clipping of dst surface. Clipping complexity must not be
// more than SIMPLEREGION, and bounding box must fill drawing
// rect or a temp DIB is created.
//
iRegionComplexity = GetClipBox(pDibInfoDst->hdc,&rclClipBox);
//
// try to clip to dst surface, dst should be clipped in all cases except
// gradient fill
//
if (flCopyMode & (SOURCE_GRADIENT_RECT | SOURCE_GRADIENT_TRI)) { //
// trim destination bounds rect to surface bounds. Src rect must also
// be trimmed by same amount (in src space)
//
if (pDibInfoDst->rclBoundsTrim.left < pDibInfoDst->rclClipDC.left) { pDibInfoDst->rclBoundsTrim.left = pDibInfoDst->rclClipDC.left; }
if (pDibInfoDst->rclBoundsTrim.top < pDibInfoDst->rclClipDC.top) { pDibInfoDst->rclBoundsTrim.top = pDibInfoDst->rclClipDC.top; }
if (pDibInfoDst->rclBoundsTrim.right > pDibInfoDst->rclClipDC.right) { pDibInfoDst->rclBoundsTrim.right = pDibInfoDst->rclClipDC.right; }
if (pDibInfoDst->rclBoundsTrim.bottom > pDibInfoDst->rclClipDC.bottom) { pDibInfoDst->rclBoundsTrim.bottom = pDibInfoDst->rclClipDC.bottom; }
//
// set offset for gradient fill
//
pDibInfoDst->ptlGradOffset.x = 0; pDibInfoDst->ptlGradOffset.y = 0;
//
// don't allocate surface for triangles at 8,4,1
// Must use internal palette routines
//
if ( (pDibInfoDst->pbmi->bmiHeader.biBitCount == 8) || (pDibInfoDst->pbmi->bmiHeader.biBitCount == 4) || (pDibInfoDst->pbmi->bmiHeader.biBitCount == 1) ) { *pbReadable = FALSE; } }
LONG DstCx = pDibInfoDst->rclBoundsTrim.right - pDibInfoDst->rclBoundsTrim.left; LONG DstCy = pDibInfoDst->rclBoundsTrim.bottom - pDibInfoDst->rclBoundsTrim.top;
//
// make sure draswing rect lies within clip box
//
if (iRegionComplexity != NULLREGION) { //
// convert to NULLREGION if drawing rect inside clip box
//
if (iRegionComplexity == SIMPLEREGION) { if ( (pDibInfoDst->rclBoundsTrim.left >= rclClipBox.left) && (pDibInfoDst->rclBoundsTrim.top >= rclClipBox.top) && (pDibInfoDst->rclBoundsTrim.right <= rclClipBox.right) && (pDibInfoDst->rclBoundsTrim.bottom <= rclClipBox.bottom) ) { iRegionComplexity = NULLREGION; } } }
//
// check for need to allocate temp dst surface
//
if ((*pbReadable == TRUE) && ((pDibInfoDst->pvBits == NULL) || (iRegionComplexity != NULLREGION))) { if (pDibInfoDst->rclBounds.left > 0) { pDibInfoDst->ptlGradOffset.x = pDibInfoDst->rclBounds.left; }
if (pDibInfoDst->rclBounds.top > 0) { pDibInfoDst->ptlGradOffset.y = pDibInfoDst->rclBounds.top; }
//
// allocate surface
//
HDC hdcTemp = CreateCompatibleDC (hdc);
if (hdcTemp) { HBITMAP hbm = CreateCompatibleDIB (hdcTemp, DstCx, DstCy, &pDibInfoDst->pvBits, pDibInfoDst->pbmi);
if (hbm != NULL) { pDibInfoDst->hDIB = hbm; GetCompatibleDIBInfo (hbm, &pDibInfoDst->pvBase, &pDibInfoDst->stride);
HGDIOBJ hret = SelectObject(hdcTemp, hbm);
if (hret != NULL) { RECTL rclCopy;
rclCopy.left = 0; rclCopy.right = DstCx; rclCopy.top = 0; rclCopy.bottom = DstCy;
//
// gradient rect does not need source bitmap data
//
if (flCopyMode != SOURCE_GRADIENT_RECT) { bRet = BitBlt(hdcTemp, 0, 0, DstCx, DstCy, pDibInfoDst->hdc, pDibInfoDst->rclBoundsTrim.left, pDibInfoDst->rclBoundsTrim.top, SRCCOPY); }
//
// adjust dst rect
//
if (bRet) { pDibInfoDst->rclDIB = rclCopy; } } else { bRet = NULL; WARNING ("bGetDstDIBits -- fail to select compatible DIB\n"); }
*pbReadable = bRet; } else { bRet = FALSE; }
DeleteDC (hdcTemp); } else { WARNING ("bGetDstDIBits -- fail to createcompatibledc\n"); bRet = FALSE; } } else { pDibInfoDst->rclDIB = pDibInfoDst->rclBoundsTrim; }
return(bRet); }
/******************************Public*Routine******************************\
* bDIBGetSrcDIBits * * Create or get the source dib bits * * Returns: * VOID. * * History: * 09-Dec-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/ BOOL bDIBGetSrcDIBits ( PDIBINFO pDibInfoDst, PDIBINFO pDibInfoSrc, FLONG flSourceMode, ULONG TransColor ) {
if (pDibInfoSrc->iUsage == DIB_PAL_COLORS) { vMapPALtoRGB (pDibInfoDst, pDibInfoSrc, 0); }
//pDibInfoSrc->rclDIB = pDibInfoSrc->rclClipDC;
return (bGetSrcDIBits(pDibInfoDst,pDibInfoSrc,flSourceMode, TransColor));
}
/******************************Public*Routine******************************\
* bDIBInitDIBINFO * * Returns: * BOOLEAN. * * History: * 09-Dec-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/ BOOL bDIBInitDIBINFO( PBITMAPINFO pbmi, CONST VOID * pvBits, int x, int y, int cx, int cy, PDIBINFO pDibInfo) { PVOID p; ULONG cBytes = sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255; int bmWidthBytes; POINT lpPoints[2];
p = LOCALALLOC(cBytes);
if (!p) { WARNING("fail to alloc mem\n"); return (FALSE); }
ZeroMemory (p,cBytes);
//
// copy the input pbmi
//
vCopyBitmapInfo ((PBITMAPINFO)p, pbmi);
pDibInfo->pbmi = (PBITMAPINFO)p; pDibInfo->hdc = NULL;
pDibInfo->rclBounds.left = x; pDibInfo->rclBounds.top = y; pDibInfo->rclBounds.right = x+cx; pDibInfo->rclBounds.bottom = y+cy;
pDibInfo->rclBoundsTrim = pDibInfo->rclBounds;
pDibInfo->pvBits = (PVOID)pvBits; pDibInfo->iUsage = DIB_RGB_COLORS;
//
// align width to WORD boundary
//
bmWidthBytes = ((pbmi->bmiHeader.biWidth*pbmi->bmiHeader.biBitCount + 15)>>4)<<1;
if (pbmi->bmiHeader.biHeight > 0) { pDibInfo->pvBase = (PBYTE)pDibInfo->pvBits + bmWidthBytes * (pbmi->bmiHeader.biHeight - 1); pDibInfo->stride = (ULONG) (-bmWidthBytes); } else { pDibInfo->pvBase = pDibInfo->pvBits; pDibInfo->stride = bmWidthBytes; }
pDibInfo->hDIB = NULL;
pDibInfo->pdds = NULL; pDibInfo->ddsd.dwSize = sizeof(DDSURFACEDESC);
return(TRUE); }
/******************************Public*Routine******************************\
* bInitDIBINFO * * Returns: * BOOLEAN. * * History: * 09-Dec-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/ BOOL bInitDIBINFO( HDC hdc, int x, int y, int cx, int cy, PDIBINFO pDibInfo) { ULONG cBytes; PVOID p; POINT lpPoints[2];
pDibInfo->hdc = hdc;
pDibInfo->rclBounds.left = x; pDibInfo->rclBounds.top = y; pDibInfo->rclBounds.right = x+cx; pDibInfo->rclBounds.bottom = y+cy;
//
// setup rclBounds in device space
//
LPtoDP (hdc, (POINT *)&pDibInfo->rclBounds, 2);
//
// order rect
//
if (pDibInfo->rclBounds.left > pDibInfo->rclBounds.right) { LONG lTemp = pDibInfo->rclBounds.left; pDibInfo->rclBounds.left = pDibInfo->rclBounds.right; pDibInfo->rclBounds.right = lTemp; }
if (pDibInfo->rclBounds.top > pDibInfo->rclBounds.bottom) { LONG lTemp = pDibInfo->rclBounds.top; pDibInfo->rclBounds.top = pDibInfo->rclBounds.bottom; pDibInfo->rclBounds.bottom = lTemp; }
pDibInfo->rclBoundsTrim = pDibInfo->rclBounds;
//
// Now operate in MM_TEXT mode
//
SetViewportOrgEx(hdc, 0, 0, &pDibInfo->ViewportOrg); SetViewportExtEx(hdc, 1, 1, &pDibInfo->ViewportExt); SetWindowOrgEx(hdc, 0, 0, &pDibInfo->WindowOrg); SetWindowExtEx(hdc, 1, 1, &pDibInfo->WindowExt); pDibInfo->Mapmode = SetMapMode(hdc,MM_TEXT);
pDibInfo->pvBits = NULL; pDibInfo->pvBase = NULL; pDibInfo->hDIB = NULL; pDibInfo->iUsage = DIB_RGB_COLORS; pDibInfo->flag = 0;
cBytes = sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255;
p = LOCALALLOC(cBytes);
if (!p) { WARNING("fail to alloc mem\n"); return (FALSE); }
ZeroMemory (p,cBytes);
pDibInfo->pbmi = (PBITMAPINFO)p;
pDibInfo->pdds = NULL; pDibInfo->ddsd.dwSize = sizeof(DDSURFACEDESC);
return(TRUE); }
/******************************Public*Routine******************************\
* bSendDIBInfo * * Returns: * BOOLEAN. * * History: * 09-Dec-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/ BOOL bSendDIBINFO( HDC hdcDst, PDIBINFO pDibInfo ) { BOOL bRet = TRUE;
if (pDibInfo->hDIB) { bRet = SetDIBitsToDevice(hdcDst, pDibInfo->rclBoundsTrim.left, pDibInfo->rclBoundsTrim.top, pDibInfo->rclBoundsTrim.right - pDibInfo->rclBoundsTrim.left, pDibInfo->rclBoundsTrim.bottom - pDibInfo->rclBoundsTrim.top, 0, 0, 0, pDibInfo->rclDIB.bottom - pDibInfo->rclDIB.top, pDibInfo->pvBits, pDibInfo->pbmi, DIB_RGB_COLORS);
} return (bRet); }
/******************************Public*Routine******************************\
* vCleanupDIBInfo * * Returns: * VOID. * * History: * 09-Dec-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/ VOID vCleanupDIBINFO( PDIBINFO pDibInfo) { //
// restore DC map modes
//
if (pDibInfo->hdc != NULL) { SetMapMode(pDibInfo->hdc,pDibInfo->Mapmode);
SetViewportOrgEx(pDibInfo->hdc, pDibInfo->ViewportOrg.x, pDibInfo->ViewportOrg.y, NULL); SetViewportExtEx(pDibInfo->hdc, pDibInfo->ViewportExt.cx, pDibInfo->ViewportExt.cy, NULL);
SetWindowOrgEx(pDibInfo->hdc, pDibInfo->WindowOrg.x, pDibInfo->WindowOrg.y, NULL); SetWindowExtEx(pDibInfo->hdc, pDibInfo->WindowExt.cx, pDibInfo->WindowExt.cy, NULL); }
//
// free allocated DIB and memory buffers
//
if (pDibInfo->hDIB) { DeleteObject (pDibInfo->hDIB); }
if (pDibInfo->pbmi) { LOCALFREE ((PVOID)pDibInfo->pbmi); }
if (pDibInfo->pdds) { pDibInfo->pdds->Unlock(pDibInfo->ddsd.lpSurface); } } #endif
/******************************Public*Routine******************************\
* VOID vSetDdrawflag * * Returns: * private call by ddraw to set a flag to indicate it has loaded * * History: * 29-April-1997 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/ VOID vSetDdrawflag () { gbddrawSet = TRUE; return; }
|