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
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;
|
|
}
|