Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2278 lines
65 KiB

/*++
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;
}