Files
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

2038 lines
53 KiB
C++

#pragma warning (disable:4800)
#include "stdafx.h"
#include "dibsection.hpp"
#include "dibsurf.hpp" //lint !e537
#include <stack>
#include <vector>
//*******************************************************************
//
// DESCRIPTION:Implementation file for CDIBSurface class
//
// AUTHOR: Andrew Farrier
//
// SourceSafe Version: $Revision: 107 $
//
//******************************************************************
std::vector<HDC> *CDIBSurface::m_FreeDC = NULL;
std::vector<DCData> *CDIBSurface::m_AllDCs = NULL;
int CDIBSurface::m_DCStackRefCount = 0;
int g_NumDibSurf = 0;
bool CDIBSurface::Blt (int x,int y,int width,int height,const CDIBSurface *src,int srcx,int srcy,DWORD rop)
{
ASSERT (m_DIBData);
ASSERT (src);
ASSERT (IsValid ());
if(!src)
return false;
if (rop == SRCCOPY && src->GetBitDepth() == GetBitDepth())
{ // use non-GDI versions
if(src->UseMask () && src->Mask())
return MaskBltNonGDI (x,y,width,height,*src,srcx,srcy);
else
return BltNonGDI (x,y,width,height,*src,srcx,srcy);
}
else if(src->UseMask ())
return MaskBlt (x,y,width,height,src,srcx,srcy);
else
{
HDC dc1,dc2;
bool toret;
dc1 = GetDC ();
dc2 = src->GetDC ();
if (!(dc1 && dc2))
{
if (dc1)
ReleaseDC (dc1);
if (dc2)
src->ReleaseDC (dc2);
return false;
}
toret = (::BitBlt (dc1,x,y,width,height,dc2,srcx,srcy,rop) == TRUE);
ReleaseDC (dc1);
src->ReleaseDC (dc2);
return toret;
}
}
void CDIBSurface::UseDC (HDC tempdc)
{
ASSERT (m_DIBData);
if (m_DIBData->m_SelectedDC == tempdc)
{
m_DIBData->m_SelectedDCRefCount++;
return;
}
HBITMAP bmap = GetBitmap();
ASSERT (bmap);
m_DIBData->m_OldBitmap = (HBITMAP) SelectObject (tempdc,bmap);
m_DIBData->m_SelectedDC = tempdc;
m_DIBData->m_SelectedDCRefCount=1;
m_DIBData->m_AllocedDC = false;
return ;
}
HDC CDIBSurface::GetDC (void)
{
HDC tempdc;
HBITMAP tempbits;
ASSERT (m_DIBData);
if (m_DIBData->m_SelectedDC)
{
m_DIBData->m_SelectedDCRefCount++;
return m_DIBData->m_SelectedDC;
}
if (m_FreeDC->size () == 0)
{
tempdc = CreateCompatibleDC (NULL);
ASSERT (tempdc);
tempbits = (HBITMAP) GetCurrentObject (tempdc,OBJ_BITMAP);
SelectObject (tempdc,tempbits);
m_AllDCs->push_back (DCData (tempdc,tempbits));
m_FreeDC->push_back (tempdc);
}
tempdc = m_FreeDC->back ();
m_FreeDC->pop_back ();
// asking for a DC only makes sense if you have a bitmap selected in it
GetBitmap();
ASSERT (m_DIBData->m_BackBits);
if (m_DIBData->m_BackBits)
if (!SelectObject (tempdc,m_DIBData->m_BackBits))
{
m_FreeDC->push_back (tempdc);
return NULL;
}
m_DIBData->m_SelectedDC = tempdc;
m_DIBData->m_SelectedDCRefCount=1;
m_DIBData->m_AllocedDC = true;
return tempdc;
}
HDC CDIBSurface::GetDC (void) const
{
HDC tempdc;
HBITMAP tempbits;
ASSERT (m_DIBData);
if (m_DIBData->m_SelectedDC)
{
m_DIBData->m_SelectedDCRefCount++;
return m_DIBData->m_SelectedDC;
}
if (m_FreeDC->size () == 0)
{
tempdc = CreateCompatibleDC (NULL);
ASSERT (tempdc);
tempbits = (HBITMAP) GetCurrentObject (tempdc,OBJ_BITMAP);
SelectObject (tempdc,tempbits);
m_AllDCs->push_back (DCData (tempdc,tempbits));
m_FreeDC->push_back (tempdc);
}
tempdc = m_FreeDC->back();
m_FreeDC->pop_back ();
// asking for a DC only makes sense if you have a bitmap selected in it
GetBitmap();
ASSERT (m_DIBData->m_BackBits);
if (m_DIBData->m_BackBits)
if (!SelectObject (tempdc,m_DIBData->m_BackBits))
{
m_FreeDC->push_back (tempdc);
return NULL;
}
m_DIBData->m_SelectedDC = tempdc;
m_DIBData->m_SelectedDCRefCount=1;
m_DIBData->m_AllocedDC = true;
return tempdc;
}
void CDIBSurface::ReleaseDC (HDC dc) const
{
std::vector<DCData>::iterator iter;
ASSERT (dc);
ASSERT (m_DIBData);
m_DIBData->m_SelectedDCRefCount--;
if (m_DIBData->m_SelectedDCRefCount)
return;
if (m_DIBData->m_AllocedDC)
{
iter = m_AllDCs->begin ();
while(iter != m_AllDCs->end ())
{
if(iter->thedc == dc)
{
HBITMAP temp = (HBITMAP) GetCurrentObject (dc,OBJ_BITMAP);
if (temp != iter->oldbits)
SelectObject (dc,iter->oldbits);
break;
}
iter++;
}
}
else
{
SelectObject (dc,m_DIBData->m_OldBitmap);
}
m_DIBData->m_SelectedDC = NULL;
if (m_DIBData->m_AllocedDC)
m_FreeDC->push_back (dc);
}
CDIBSurface::~CDIBSurface (void)
{
if(m_RefCount)
{
Release ();
}
m_RefCount = NULL;
m_DIBData = NULL;
}
CDIBSurface::CDIBSurface (const CDIBSurface& p)
{
ASSERT (p.m_RefCount);
ASSERT (p.m_DIBData);
m_RefCount = p.m_RefCount;
m_DIBData = p.m_DIBData;
AddRef ();
}
CDIBSurface& CDIBSurface::operator= (const CDIBSurface& p)
{
ASSERT (p.m_RefCount);
ASSERT (p.m_DIBData);
if(m_DIBData)
{
Release ();
}
m_RefCount = p.m_RefCount;
m_DIBData = p.m_DIBData;
AddRef ();
return *this;
}
bool CDIBSurface::SplitRef (void)
{
DIBData *olddata;
ASSERT (m_DIBData);
ASSERT (m_RefCount);
if(*m_RefCount < 2)
return true;
olddata = m_DIBData;
//m_RefCount--;
Release ();
// *m_RefCount -= 1;
m_RefCount = new UINT;
*m_RefCount = 0;
AddRef ();
m_DIBData = new DIBData;
ClearData ();
if(!Create (olddata->m_Width,olddata->m_Height,olddata->m_BitDepth))
return false;
UINT tocopy;
if(m_DIBData->m_Pitch == olddata->m_Pitch)
{
tocopy = abs (m_DIBData->m_Pitch) * m_DIBData->m_Height;
memcpy (m_DIBData->m_Data,olddata->m_Data,tocopy);
}
else
{
int y;
unsigned char *dest,*src;
dest = m_DIBData->m_UpperLeft;
src = olddata->m_UpperLeft;
for(y=0;y<m_DIBData->m_Height;y++)
{
memcpy (dest,src,m_DIBData->m_Pitch);
dest += m_DIBData->m_Pitch;
src += olddata->m_Pitch;
}
}
if(olddata->m_Mask)
{
if(!CalcMask ())
return false;
HDC dc1,dc2;
dc1 = m_DIBData->m_Mask->GetDC ();
dc2 = olddata->m_Mask->GetDC ();
BitBlt (dc1,0,0,m_DIBData->m_Width,m_DIBData->m_Height,dc2,0,0,SRCCOPY);
m_DIBData->m_Mask->ReleaseDC (dc1);
olddata->m_Mask->ReleaseDC (dc2);
}
m_DIBData->m_UseMask = olddata->m_UseMask;
return true;
}
CDIBSurface::CDIBSurface (void)
{
m_RefCount = new UINT;
ASSERT (m_RefCount);
*m_RefCount = 0;
AddRef ();
m_DIBData = new DIBData;
ClearData ();
}
unsigned char *CDIBSurface::GetMem( int x, int y )
{
ASSERT( m_DIBData );
unsigned char *pBits = NULL;
if( 0 <= x && GetWidth() > x &&
0 <= y && GetHeight() > y &&
m_DIBData->m_Data &&
GdiFlush() )
{
int nPixelSize = GetBitDepth() >> 3;
int nPitch = GetPitch();
pBits = m_DIBData->m_Data;
if( 0 > nPitch )
pBits -= nPitch * (GetHeight() - y - 1);
else
pBits += nPitch * y;
pBits += nPixelSize * x;
}
return( pBits );
}
//****************************************************************
//
// Function Name: CDIBSurface::CDIBSurface
//
// Description: Constructor for CDIBSurface. Empties the fields and calls Create
//
// Returns:nothing
//
//****************************************************************
CDIBSurface::CDIBSurface (UINT Width,UINT Height,UINT BitDepth)
{
if(!m_DCStackRefCount)
{
m_AllDCs = new std::vector<DCData>;
m_FreeDC = new std::vector<HDC>;
}
m_DCStackRefCount++;
m_RefCount = new UINT;
ASSERT (m_RefCount);
*m_RefCount = 0;
AddRef ();
m_DIBData = new DIBData;
ASSERT (m_DIBData);
ClearData ();
if(!Create (Width,Height,BitDepth))
{
throw std::runtime_error ("unable to create a blank CDIBSurface");
}
}
//****************************************************************
//
// Function Name: CDIBSurface::Create
//
// Description: creates a new DIBSection of the specified size
// If already present of the right size then just clear to black
// If wrong size then destroy and create a new one
//
// Returns: true if section was created
//
//****************************************************************
bool CDIBSurface::Create (UINT Width,UINT Height,UINT BitDepth)
{
RECT arect;
ASSERT (m_DIBData);
// if we already have a surface with the current size then just repaint it to black
if((m_DIBData->m_Data) && (Width == m_DIBData->m_Width) && (Height == m_DIBData->m_Height) && (BitDepth == m_DIBData->m_BitDepth))
{
arect.left = 0;
arect.top = 0;
arect.right = (long) m_DIBData->m_Width;
arect.bottom = (long) m_DIBData->m_Height;
HDC dc = GetDC ();
FillRect (dc,&arect,(HBRUSH) GetStockObject (BLACK_BRUSH));
ReleaseDC (dc);
return true;
}
// delete the current surface if we have one
if(m_DIBData->m_Data)
Destroy ();
g_NumDibSurf++;
if((Width == 0) || (Height == 0) || (BitDepth == 0))
return true;
m_DIBData->m_Width = Width;
m_DIBData->m_Height = Height;
m_DIBData->m_BitDepth = BitDepth;
// when we create a DIB section we need to setup a BITMAPINFO structure to pass to CreateDIBSection
// this structure hold all the data about out buffer
switch(m_DIBData->m_BitDepth)
{
case 24:
m_DIBData->m_Pitch = (int) m_DIBData->m_Width*3;
m_DIBData->m_Pitch += ((4-(m_DIBData->m_Pitch&0x03))&0x03);
break;
case 16:
m_DIBData->m_Pitch = (int) m_DIBData->m_Width*2;
m_DIBData->m_Pitch += ((4-(m_DIBData->m_Pitch&0x03))&0x03);
break;
case 8:
m_DIBData->m_Pitch = (int) m_DIBData->m_Width;
m_DIBData->m_Pitch += ((4-(m_DIBData->m_Pitch&0x03))&0x03);
break;
case 4:
m_DIBData->m_Pitch = (int) ((m_DIBData->m_Width+1)>>1);
m_DIBData->m_Pitch += ((4-(m_DIBData->m_Pitch&0x03))&0x03);
break;
case 1:
m_DIBData->m_Pitch = (int) ((m_DIBData->m_Width+7)>>3);
m_DIBData->m_Pitch += ((4-(m_DIBData->m_Pitch&0x03))&0x03);
break;
default:
OutputDebugString ("Unsupported Bitdepth for DibSections");
return false;
}
// create a DC to use the DIB section in
#if 0
m_DIBData->m_BackDC = CreateCompatibleDC (NULL);
ASSERT(NULL != m_DIBData->m_BackDC);
if (NULL == m_DIBData->m_BackDC) {
Destroy ();
return false;
}
#endif
m_DIBData->m_BackBits = NULL;
// select the dib section into the DC from above
// m_DIBData->m_OldBits = (HBITMAP) SelectObject (m_DIBData->m_BackDC,m_DIBData->m_BackBits);
m_DIBData->m_Data = new BYTE [abs (m_DIBData->m_Pitch) * m_DIBData->m_Height];
if (!m_DIBData->m_Data)
{
Destroy();
return false;
}
memset (m_DIBData->m_Data,0,abs (m_DIBData->m_Pitch) * m_DIBData->m_Height);
if(m_DIBData->m_Pitch < 0) // only the case if we have a bottom-up section
m_DIBData->m_UpperLeft = (m_DIBData->m_Data+((-1*m_DIBData->m_Pitch)*(((int)m_DIBData->m_Height)-1)));
else
m_DIBData->m_UpperLeft = m_DIBData->m_Data;
// init the whole surface to black
arect.left = 0;
arect.top = 0;
arect.right = (long) m_DIBData->m_Width;
arect.bottom = (long) m_DIBData->m_Height;
// HDC testdc = CreateCompatibleDC (NULL);
// HBITMAP testbit = (HBITMAP) SelectObject (testdc,m_DIBData->m_BackBits);
// dc = GetDC ();
// FillRect (dc,&arect,(HBRUSH) GetStockObject (BLACK_BRUSH));
// ReleaseDC (dc);
// SelectObject (testdc,testbit);
// DeleteDC (testdc);
return true;
}
//****************************************************************
//
// Function Name: CDIBSurface::Destroy
//
// Description: clean up after ourselves.
//
// Returns: nothing
//
//****************************************************************
void CDIBSurface::Destroy (void)
{
ASSERT (m_DIBData);
if(!m_DIBData->m_Data)
return;
g_NumDibSurf--;
// select the old bitmap back into our DC then delete the DC
// SelectObject (m_DIBData->m_BackDC,m_DIBData->m_OldBits);
// DeleteDC (m_DIBData->m_BackDC);
// m_DIBData->m_BackDC = NULL;
// m_DIBData->m_OldBits = NULL;
if (m_DIBData->m_BackBits) // if you have the bits, then the data is from the dibsection
DeleteObject (m_DIBData->m_BackBits);
else
delete [] m_DIBData->m_Data; // otherwise the data was new'd
m_DIBData->m_BackBits = NULL;
m_DIBData->m_Width = m_DIBData->m_Height = m_DIBData->m_BitDepth = m_DIBData->m_Pitch = 0;
m_DIBData->m_Data = NULL;
m_DIBData->m_UpperLeft = NULL;
// select the old mask bitmap back into our DC then delete the DC
m_DIBData->m_UseMask = false;
delete m_DIBData->m_Mask;
m_DIBData->m_Mask = NULL;
}
//****************************************************************
//
// Function Name: CDIBSurface::Fill
//
// Description: Will fill the rectangle passed in with the color requested
//
// Returns: true is successful
//
//****************************************************************
bool CDIBSurface::Fill (const CRect *therect,const COLORREF colorref)
{
HBRUSH stupid;
HDC dc;
bool fred;
CRect temp;
ASSERT (m_DIBData);
ASSERT (therect);
if(!therect)
return false;
temp = *therect;
temp.right += 1;
temp.bottom += 1;
stupid = CreateSolidBrush (colorref);
dc = GetDC ();
#pragma warning (disable : 4800)
fred = FillRect (dc,therect,stupid);
ReleaseDC (dc);
DeleteObject (stupid);
return fred;
}
//****************************************************************
//
// Function Name: CDIBSurface::FillHatchBrush
//
// Description: Will fill the rectangle passed in with the color requested
//
// Returns: true is successful
//
//****************************************************************
bool CDIBSurface::FillHatchBrush (const CRect *therect,
int stockHatchBrushStyle, const COLORREF colorref)
{
HBRUSH stupid,oldBrush;
HDC dc;
bool fred;
CRect temp;
ASSERT (m_DIBData);
ASSERT (therect);
if(!therect)
return false;
temp = *therect;
temp.right += 1;
temp.bottom += 1;
stupid = CreateHatchBrush (stockHatchBrushStyle,colorref);
dc = GetDC ();
oldBrush = (HBRUSH)SelectObject(dc,stupid);
#pragma warning (disable : 4800)
fred = PatBlt(dc, therect->left, therect->top,therect->right, therect->bottom, 0x00A000C9);
SelectObject(dc,oldBrush);
ReleaseDC (dc);
DeleteObject (stupid);
return fred;
}
//****************************************************************
//
// Function Name: CDIBSurface::GetColor
//
// Description: will get the current color at the location x,y
//
// Returns: current color as a COLORREF
//
//****************************************************************
COLORREF CDIBSurface::GetColor (UINT x,UINT y) const
{
DWORD value;
COLORREF toret;
RGBQUAD temp;
int red,blue,green;
HDC dc;
ASSERT (m_DIBData);
value = GetValue (x,y);
switch(m_DIBData->m_BitDepth)
{
case 1:
case 4:
case 8:
dc = GetDC ();
if(GetDIBColorTable (dc,value,1,&temp) == 0)
{
ReleaseDC (dc);
return RGB (0,0,0);
}
ReleaseDC (dc);
toret = RGBQUADtoCOLORREF (temp);
break;
case 16:
red = value >> 7;
green = value >> 2;
blue = (int) (value << 3);
blue &= 0xf8;
green &= 0xf8;
red &= 0xf8;
toret = (blue<<16) + (green<<8) + red;
break;
case 24:
toret = (value);
break;
default:
ASSERT (false);
toret = false;
break;
}
return toret;
}
void CDIBSurface::SetColor (UINT x,UINT y,COLORREF color)
{
int red,green,blue;
unsigned char *mem;
ASSERT (m_DIBData);
mem = GetMem ();
mem += GetLocation (x,y);
switch(m_DIBData->m_BitDepth)
{
case 16:
unsigned short *mem16;
mem16 = (unsigned short *) mem;
red = color&0xff;
green = (color>>8) & 0xff;
blue = (color>>16) & 0xff;
red >>= 3;
green >>= 3;
blue >>= 3;
(*mem16) = (red<<10)+(green<<5)+blue;
break;
case 24:
red = color&0xff;
green = (color>>8) & 0xff;
blue = (color>>16) & 0xff;
(*mem) = blue;
mem++;
(*mem) = green;
mem++;
(*mem) = red;
break;
default:
ASSERT (false);
break;
}
}
void CDIBSurface::SetColor( COLORREF color )
{
Fill( 0, 0, m_DIBData->m_Width, m_DIBData->m_Height, color );
}
//****************************************************************
//
// Function Name: CDIBSurface::MaskBlt
//
// Description: will use src and mask to perform a mask blt to this DIBSurface
// white is tranparent, black is opaque
//
// Returns: true if successful
//
//****************************************************************
bool CDIBSurface::MaskBlt (const int x,const int y,const int width,const int height,const HDC src,const HDC mask,const int srcx,const int srcy)
{
ASSERT (m_DIBData);
ASSERT (src);
ASSERT (mask);
if(!src)
return false;
if(!mask)
return false;
HDC dc = GetDC ();
SetBkColor(dc, RGB(255, 255, 255)); // 1s --> 0xFFFFFF
SetTextColor(dc, RGB(0, 0, 0)); // 0s --> 0x000000
BitBlt(dc, x, y, width, height, src, srcx, srcy, SRCINVERT);
BitBlt(dc, x, y, width, height, mask, srcx, srcy, SRCAND);
BitBlt(dc, x, y, width, height, src, srcx, srcy, SRCINVERT);
ReleaseDC (dc);
return true;
}
//****************************************************************
//
// Function Name: CDIBSurface::MaskBlt
//
// Description: will perform a mask blt using the data from src
//
// Returns: true if successful
//
//****************************************************************
bool CDIBSurface::MaskBlt (const int x,const int y,const int width,const int height,const CDIBSurface *src,const int srcx,const int srcy)
{
ASSERT (m_DIBData);
ASSERT (src);
ASSERT (src->m_DIBData);
if(src == NULL)
return false;
ASSERT (src->UseMask ());
if(!src->UseMask ())
return false;
HDC dc = GetDC ();
SetBkColor(dc, RGB(255, 255, 255)); // 1s --> 0xFFFFFF
SetTextColor(dc, RGB(0, 0, 0)); // 0s --> 0x000000
// BitBlt(m_BackDC, x, y, width, height, src->m_BackDC, srcx, srcy, SRCINVERT);
HDC dc2,dc3;
dc2 = src->m_DIBData->m_Mask->GetDC ();
dc3 = src->GetDC ();
BitBlt(dc, x, y, width, height, dc2, srcx, srcy, SRCAND);
BitBlt(dc, x, y, width, height, dc3, srcx, srcy, SRCPAINT);
src->m_DIBData->m_Mask->ReleaseDC (dc2);
src->ReleaseDC (dc3);
ReleaseDC (dc);
return true;
}
bool CDIBSurface::RotateBlt( int left, int top, int right, int bottom, const CDIBSurface& src, int x, int y, int ang )
{
#if 1
// This only works between similarly-depth'ed surfaces.
if( GetBitDepth() != src.GetBitDepth() )
return( Blt( CRect( left, top, right, bottom ), src, CPoint( x, y ) ) );
// return( false );
// Degenerate case
if( 0 == ang )
return( Blt( CRect( left, top, right, bottom ), src, CPoint( x, y ) ) );
int nDstW = GetWidth(), nDstH = GetHeight();
if( nDstW <= left || nDstH < top || 0 > right || 0 > bottom )
return( true );
int nSrcW = src.GetWidth(), nSrcH = src.GetHeight();
int nSrcP = src.GetPitch(), nDstP = GetPitch();
if( 0 > left )
{
x -= left;
left = 0;
}
if( 0 > top )
{
y -= top;
top = 0;
}
if( nDstW < right )
right = nDstW;
if( nDstH < bottom )
bottom = nDstH;
nDstW = right - left;
nDstH = bottom - top;
if( x + nDstW > nSrcW )
{
nDstW = nSrcW - x;
right = left + nDstW;
}
if( y + nDstH > nSrcH )
{
nDstH = nSrcH - y;
bottom = top + nDstH;
}
if( nDstW != nDstH )
return( false );
const BYTE *pSBits = src.GetMem();
if( 0 > nSrcP )
pSBits -= nSrcP * (nSrcH - 1);
BYTE *pDBits = GetMem();
if( 0 > nDstP )
pDBits -= nDstP * (nDstH - 1);
int nOffset, nPixelSize = GetBitDepth() >> 3;
int nPixelStride, nSrcStride, nDstStride = nDstP - nPixelSize * nDstW;
switch( ang )
{
#if 0 // Handled by short-circuit case above
case 0:
nPixelStride = nPixelSize;
nSrcStride = nSrcP - nDstW * nPixelSize;
nOffset = 0;
break;
#endif
case 90:
nPixelStride = -nSrcP;
nSrcStride = nDstH * nSrcP + nPixelSize;
nOffset = nSrcP * (nDstH - 1);
break;
case 180:
nPixelStride = -nPixelSize;
nSrcStride = nPixelSize * nDstW - nSrcP;
nOffset = nSrcP * (nDstH - 1) + nPixelSize * (nDstW - 1);
break;
case 270:
nPixelStride = nSrcP;
nSrcStride = -(nSrcP * nDstH) - nPixelSize;
nOffset = (nDstW - 1) * nPixelSize;
break;
default:
return( false );
}
pDBits += nDstP * top + nPixelSize * left;
pSBits += nSrcP * y + nPixelSize * x + nOffset;
while( 0 < nDstH-- )
{
for( int i = 0; i < nDstW; i++ )
{
for( int j = 0; j < nPixelSize; j++ )
*pDBits++ = pSBits[ j ];
pSBits += nPixelStride;
}
pDBits += nDstStride;
pSBits += nSrcStride;
}
return( true );
#else
// FIX implement
return( Blt( loc, src, srcloc ) );
#endif
}
bool CDIBSurface::TransparentBlt( int left, int top, int right, int bottom, const CDIBSurface& src, int x, int y, const COLORREF bgClr )
{
#if 1
// This only works between similarly-depth'ed surfaces.
if( GetBitDepth() != src.GetBitDepth() )
return( Blt( CRect( left, top, right, bottom ), src, CPoint( x, y ) ) );
// return( false );
int nDstW = GetWidth(), nDstH = GetHeight();
if( nDstW <= left || nDstH < top || 0 > right || 0 > bottom )
return( true );
int nSrcW = src.GetWidth(), nSrcH = src.GetHeight();
int nSrcP = src.GetPitch(), nDstP = GetPitch();
if( 0 > left )
{
x -= left;
left = 0;
}
if( 0 > top )
{
y -= top;
top = 0;
}
if( nDstW < right )
right = nDstW;
if( nDstH < bottom )
bottom = nDstH;
nDstW = right - left;
nDstH = bottom - top;
if( x + nDstW > nSrcW )
{
nDstW = nSrcW - x;
right = left + nDstW;
}
if( y + nDstH > nSrcH )
{
nDstH = nSrcH - y;
bottom = top + nDstH;
}
const BYTE *pSBits = src.GetMem();
if( 0 > nSrcP )
pSBits -= nSrcP * (nSrcH - 1);
BYTE *pDBits = GetMem();
if( 0 > nDstP )
pDBits -= nDstP * (nDstH - 1);
switch( GetBitDepth() )
{
case 16:
{
pDBits += nDstP * top + left * sizeof( WORD );
pSBits += nSrcP * y + x * sizeof( WORD );
const WORD *pS = (const WORD *)pSBits;
WORD *pD = (WORD *)pDBits;
WORD crClr = ConvertColorToWord( bgClr );
int nSrcS = (nSrcP - nDstW * sizeof( WORD )) / sizeof( WORD );
int nDstS = (nDstP - nDstW * sizeof( WORD )) / sizeof( WORD );
while( 0 < nDstH-- )
{
for( int i = nDstW; i; i-- )
{
if( *pS != crClr )
*pD = *pS;
pD++;
pS++;
}
pD += nDstS;
pS += nSrcS;
}
break;
}
case 24:
{
pDBits += nDstP * top + left * sizeof( RGBTRIPLE );
pSBits += nSrcP * y + x * sizeof( RGBTRIPLE );
const RGBTRIPLE *pS = (const RGBTRIPLE *)pSBits;
RGBTRIPLE *pD = (RGBTRIPLE *)pDBits;
// RGBTRIPLE crClr = ConvertColorToTriple( bgClr );
int nSrcS = (nSrcP - nDstW * sizeof( RGBTRIPLE )) / sizeof( RGBTRIPLE );
int nDstS = (nDstP - nDstW * sizeof( RGBTRIPLE )) / sizeof( RGBTRIPLE );
while( 0 < nDstH-- )
{
for( int i = nDstW; i; i-- )
{
if( memcmp( pS, pD, 3 ) )
*pD = *pS;
pD++;
pS++;
}
pD += nDstS;
pS += nSrcS;
}
break;
}
case 32:
{
pDBits += nDstP * top + left * sizeof( DWORD );
pSBits += nSrcP * y + x * sizeof( DWORD );
const DWORD *pS = (const DWORD *)pSBits;
DWORD *pD = (DWORD *)pDBits;
DWORD crClr = ConvertColorToLong( bgClr );
int nSrcS = (nSrcP - nDstW * sizeof( DWORD )) / sizeof( DWORD );
int nDstS = (nDstP - nDstW * sizeof( DWORD )) / sizeof( DWORD );
while( 0 < nDstH-- )
{
for( int i = nDstW; i; i-- )
{
if( (0x00ffffff & *pS) != crClr )
*pD = *pS;
pD++;
pS++;
}
pD += nDstS;
pS += nSrcS;
}
break;
}
}
return( true );
#else
// FIX implement
Blt( loc, src, srcloc );
return( true );
#endif
}
//****************************************************************
//
// Function Name: CDIBSurface::CalcMask
//
// Description: will create a mask for the DIBSurface based on the color passed in
// all pixels that are the same color as colorref are considered transparent
//
// Returns: true if successful
//
//****************************************************************
bool CDIBSurface::CalcMask (COLORREF colorref)
{
if(!CalcMask ())
return false;
switch(m_DIBData->m_BitDepth)
{
case 1:
m_DIBData->m_UseMask = Create1BitMask (colorref);
break;
case 4:
m_DIBData->m_UseMask = Create4BitMask (colorref);
break;
case 8:
m_DIBData->m_UseMask = Create8BitMask (colorref);
break;
case 16:
m_DIBData->m_UseMask = Create16BitMask (colorref);
break;
case 24:
m_DIBData->m_UseMask = Create24BitMask (colorref);
break;
default:
ASSERT (false);
break;
}
if(!m_DIBData->m_UseMask)
{
delete m_DIBData->m_Mask;
m_DIBData->m_Mask = NULL;
}
return m_DIBData->m_UseMask;
}
//****************************************************************
//
// Function Name: CDIBSurface::CalcMask
//
// Description: will create a mask for the DIBSurface the initial image is all opaque
//
// Returns: true if successful
//
//****************************************************************
bool CDIBSurface::CalcMask (void)
{
ASSERT (m_DIBData);
delete m_DIBData->m_Mask;
m_DIBData->m_Mask = NULL;
m_DIBData->m_Mask = new CDIBSurface ();
if(!m_DIBData->m_Mask)
return false;
if(!m_DIBData->m_Mask->Create (m_DIBData->m_Width,m_DIBData->m_Height,1)) //lint !e539 huh
{
delete m_DIBData->m_Mask;
m_DIBData->m_Mask = NULL;
return false;
}
m_DIBData->m_UseMask = true;
return true;
}
bool CDIBSurface::DestroyMask (void)
{
ASSERT (m_DIBData);
delete m_DIBData->m_Mask;
m_DIBData->m_Mask = NULL;
m_DIBData->m_UseMask = false;
return true;
}
int CDIBSurface::FloodFill (const CPoint& start,const COLORREF color)
{
COLORREF srccolor,intcolor;
CPoint temp;
std::stack<CPoint> data;
int count=0;
ASSERT (m_DIBData);
if(m_DIBData->m_BitDepth == 24)
return FloodFill24 (start,color);
intcolor = color;
if (m_DIBData->m_BitDepth == 16)
intcolor &= 0x00f8f8f8;
srccolor = GetColor (start.x,start.y);
if(srccolor == intcolor)
return 0;
data.push (start);
while(!data.empty ())
{
temp = data.top ();
data.pop ();
if(GetColor (temp.x,temp.y)==srccolor)
{
SetColor (temp.x,temp.y,color);
count++;
if(temp.y != 0)
data.push (CPoint(temp.x,temp.y-1));
if(temp.y != (m_DIBData->m_Height-1))
data.push (CPoint(temp.x,temp.y+1));
if(temp.x != 0)
data.push (CPoint(temp.x-1,temp.y));
if(temp.x != (m_DIBData->m_Width-1))
data.push (CPoint(temp.x+1,temp.y));
}
}
return count;
}
// assume the alpha is an eight bit surface where the indexs are really the alpha values
// 0 in the alpha means to use leave the dest alone
// 255 in the alpha means to be 100% from the source.
bool CDIBSurface::AlphaBlt (const int x,const int y,const int width,const int height,const CDIBSurface *src,const CDIBSurface *alpha,const int srcx,const int srcy,const int alphasrcx,const int alphasrcy)
{
ASSERT (m_DIBData);
ASSERT (src->m_DIBData);
ASSERT (alpha->m_DIBData);
ASSERT (alpha->GetBitDepth () == 8);
ASSERT ((GetBitDepth()==16)||(GetBitDepth()==24));
ASSERT ((src->GetBitDepth()==16)||(src->GetBitDepth()==24));
ASSERT (GetBitDepth() == src->GetBitDepth ());
ASSERT ((x+width) <= GetWidth ());
ASSERT ((srcx+width) <= src->GetWidth ());
ASSERT ((y+height) <= GetHeight ());
ASSERT ((srcy+height) <= src->GetHeight ());
ASSERT (x >= 0);
ASSERT (y >= 0);
ASSERT (width >= 0);
ASSERT (height >= 0);
ASSERT (srcx >= 0);
ASSERT (srcy >= 0);
int asrcx = (alphasrcx < 0) ? srcx : alphasrcx;
int asrcy = (alphasrcy < 0) ? srcy : alphasrcy;
ASSERT ((asrcx+width) <= alpha->GetWidth ());
ASSERT ((asrcy+height) <= alpha->GetHeight ());
switch(GetBitDepth ())
{
case 16:
return AlphaBlt16 (x,y,width,height,src,alpha,srcx,srcy,asrcx,asrcy);
break;
case 24:
return AlphaBlt24 (x,y,width,height,src,alpha,srcx,srcy,asrcx,asrcy);
break;
default:
ASSERT (false);
break;
}
return false;
}
bool CDIBSurface::ColorBlt (const int x,const int y,const int width,const int height,const CDIBSurface* src,const int srcx,const int srcy,COLORREF color,bool addred,bool addgreen,bool addblue,CDIBSurface *altmask)
{
ASSERT (m_DIBData);
ASSERT (src->m_DIBData);
ASSERT ((GetBitDepth()==16)||(GetBitDepth()==24));
ASSERT (GetBitDepth() == src->GetBitDepth ());
ASSERT ((src!=this) || ((srcx==x) && (srcy==y)));
ASSERT ((x+width) <= GetWidth ());
ASSERT ((srcx+width) <= src->GetWidth ());
ASSERT ((y+height) <= GetHeight ());
ASSERT ((srcy+height) <= src->GetHeight ());
ASSERT (x >= 0);
ASSERT (y >= 0);
ASSERT (width >= 0);
ASSERT (height >= 0);
ASSERT (srcx >= 0);
ASSERT (srcy >= 0);
switch(GetBitDepth ())
{
case 16:
return ColorBlt16 (x,y,width,height,src,srcx,srcy,color,addred,addgreen,addblue,altmask);
break;
case 24:
return ColorBlt24 (x,y,width,height,src,srcx,srcy,color,addred,addgreen,addblue,altmask);
break;
default:
ASSERT (false);
break;
}
return false;
}
bool CDIBSurface::GrayBlt (const int x,const int y,const int width,const int height,const CDIBSurface* src,const int srcx,const int srcy, CDIBSurface *altmask)
{
ASSERT (m_DIBData);
ASSERT (src->m_DIBData);
ASSERT ((GetBitDepth()==16)||(GetBitDepth()==24));
ASSERT (GetBitDepth() == src->GetBitDepth ());
ASSERT ((src!=this) || ((srcx==x) && (srcy==y)));
ASSERT ((x+width) <= GetWidth ());
ASSERT ((srcx+width) <= src->GetWidth ());
ASSERT ((y+height) <= GetHeight ());
ASSERT ((srcy+height) <= src->GetHeight ());
ASSERT (x >= 0);
ASSERT (y >= 0);
ASSERT (width >= 0);
ASSERT (height >= 0);
ASSERT (srcx >= 0);
ASSERT (srcy >= 0);
switch(GetBitDepth ())
{
case 16:
return GrayBlt16 (x,y,width,height,src,srcx,srcy,altmask);
break;
case 24:
return GrayBlt24 (x,y,width,height,src,srcx,srcy,altmask);
break;
default:
ASSERT (false);
break;
}
return false;
}
bool CDIBSurface::MultBlt (const int x,const int y,const int width,const int height,const CDIBSurface* src,const int srcx,const int srcy,const float red,const float green,const float blue,CDIBSurface *altmask)
{
ASSERT (m_DIBData);
ASSERT (src->m_DIBData);
ASSERT ((GetBitDepth()==16)||(GetBitDepth()==24));
ASSERT (GetBitDepth() == src->GetBitDepth ());
ASSERT ((src!=this) || ((srcx==x) && (srcy==y)));
int nWidth = GetWidth(), nHeight = GetHeight();
int l = x, t = y, w = width, h = height;
if( 0 > l )
{
w += l;
l = 0;
}
if( 0 > t )
{
h += t;
t = 0;
}
if( nWidth < l + w )
w = nWidth - l;
if( nHeight < t + h )
h = nHeight - t;
ASSERT (w >= 0);
ASSERT (h >= 0);
ASSERT ((srcx+w) <= src->GetWidth ());
ASSERT ((srcy+h) <= src->GetHeight ());
ASSERT (srcx >= 0);
ASSERT (srcy >= 0);
// ASSERT ((x+width) <= GetWidth ());
// ASSERT ((y+height) <= GetHeight ());
// ASSERT (x >= 0);
// ASSERT (y >= 0);
switch(GetBitDepth ())
{
case 16:
return MultBlt16 (l,t,w,h,src,srcx,srcy,red,green,blue,altmask);
break;
case 24:
return MultBlt24 (l,t,w,h,src,srcx,srcy,red,green,blue,altmask);
break;
default:
ASSERT (false);
break;
}
return false;
}
//****************************************************************
//
// Function Name: MaskBlt
//
// Description: will use src and mask to perform a mask blt to this DIBSurface
// white is tranparent, black is opaque
//
// Returns: true if successful
//
//****************************************************************
bool MaskBlt (HDC dest,const int x,const int y,const int width,const int height,const HDC src,const HDC mask,const int srcx,const int srcy,const int maskx,const int masky)
{
ASSERT (src);
ASSERT (mask);
if((!src) || (!mask))
return false;
SetBkColor(dest, RGB(255, 255, 255)); // 1s --> 0xFFFFFF
SetTextColor(dest, RGB(0, 0, 0)); // 0s --> 0x000000
BitBlt(dest, x, y, width, height, src, srcx, srcy, SRCINVERT);
BitBlt(dest, x, y, width, height, mask, maskx, masky, SRCAND);
BitBlt(dest, x, y, width, height, src, srcx, srcy, SRCINVERT);
return true;
}
bool MaskBlt (HDC dest,const int x,const int y,const int width,const int height,const HDC src,const HDC mask,const int srcx,const int srcy)
{
ASSERT (dest);
ASSERT (src);
ASSERT (mask);
if((!src) || (!mask))
return false;
SetBkColor(dest, RGB(255, 255, 255)); // 1s --> 0xFFFFFF
SetTextColor(dest, RGB(0, 0, 0)); // 0s --> 0x000000
BitBlt(dest, x, y, width, height, src, srcx, srcy, SRCINVERT);
BitBlt(dest, x, y, width, height, mask, srcx, srcy, SRCAND);
BitBlt(dest, x, y, width, height, src, srcx, srcy, SRCINVERT);
return true;
}
//****************************************************************
//
// Function Name: MaskBlt
//
// Description: will perform a mask blt using the data from src
//
// Returns: true if successful
//
//****************************************************************
bool MaskBlt (HDC dest,const int x,const int y,const int width,const int height,const CDIBSurface *src,const int srcx,const int srcy)
{
ASSERT (dest);
ASSERT (src);
// ASSERT (src->UseMask ());
if(!src)
return false;
if (src->UseMask ())
{
SetBkColor(dest, RGB(255, 255, 255)); // 1s --> 0xFFFFFF
SetTextColor(dest, RGB(0, 0, 0)); // 0s --> 0x000000
HDC tmphdc;
/*
tmphdc = src->GetDC ();
BitBlt(dest, x, y, width, height, tmphdc, srcx, srcy, SRCINVERT);
src->ReleaseDC(tmphdc);
*/
tmphdc = src->Mask ()->GetDC ();
BitBlt(dest, x, y, width, height, tmphdc, srcx, srcy, SRCAND);
src->Mask ()->ReleaseDC(tmphdc);
tmphdc = src->GetDC ();
BitBlt(dest, x, y, width, height, tmphdc, srcx, srcy, SRCPAINT);
src->ReleaseDC(tmphdc);
}
else
{
HDC tmphdc;
tmphdc = src->GetDC ();
BitBlt(dest, x, y, width, height, tmphdc, srcx, srcy, SRCCOPY);
src->ReleaseDC(tmphdc);
}
return true;
}
bool CDIBSurface::CalcMask (const std::vector<COLORREF>& colors)
{
std::vector<COLORREF>::const_iterator iter;
UINT x,y;
COLORREF curcolor;
COLORREF curmask;
ASSERT (m_DIBData);
if(!CalcMask ())
return false;
ASSERT (m_DIBData->m_Mask);
if(!m_DIBData->m_Mask)
return false;
iter = colors.begin ();
while(iter != colors.end ())
{
curmask = (*iter);
for(y=0;y<m_DIBData->m_Height;y++)
{
for(x=0;x<m_DIBData->m_Width;x++)
{
curcolor = GetColor (x,y);
if(curcolor == curmask)
m_DIBData->m_Mask->SetColor (x,y,RGB (255,255,255));
}
}
iter++;
}
for(y=0;y<m_DIBData->m_Height;y++)
{
for(x=0;x<m_DIBData->m_Width;x++)
{
curcolor = m_DIBData->m_Mask->GetColor (x,y);
if(curcolor == RGB (255,255,255))
SetColor (x,y,RGB (0,0,0));
}
}
return true;
}
bool CDIBSurface::ConvertBitDepth (int newdepth)
{
CDIBSurface temp;
ASSERT (m_DIBData);
if (m_DIBData->m_BitDepth == newdepth)
return true;
if((m_DIBData->m_BitDepth == 24) && (newdepth == 16))
return Convert24to16 ();
if(!temp.Create (m_DIBData->m_Width,m_DIBData->m_Height,newdepth))
return false;
if (!temp.Blt (0,0,m_DIBData->m_Width,m_DIBData->m_Height,this,0,0))
return false;
if(m_DIBData->m_Mask)
{
if(!temp.CalcMask ())
return false;
HDC dc1,dc2;
dc1 = temp.m_DIBData->m_Mask->GetDC ();
dc2 = m_DIBData->m_Mask->GetDC ();
BitBlt (dc1,0,0,m_DIBData->m_Width,m_DIBData->m_Height,dc2,0,0,SRCCOPY);
temp.m_DIBData->m_Mask->ReleaseDC (dc1);
m_DIBData->m_Mask->ReleaseDC (dc2);
}
// (*temp.m_RefCount)++;
temp.AddRef ();
Destroy ();
memcpy (m_DIBData,temp.m_DIBData,sizeof (DIBData));
delete temp.m_DIBData;
delete temp.m_RefCount;
temp.m_DIBData = NULL;
temp.m_RefCount = NULL;
return true;
}
HBITMAP CDIBSurface::GetBitmap (void) const // actually creates the DIB section (if needed)
{
if (m_DIBData->m_BackBits != NULL)
return m_DIBData->m_BackBits;
BITMAPINFO *bitinfo = AllocBitmapInfo();
unsigned char *olddata = m_DIBData->m_Data;
HDC dc = ::GetDC (NULL);
m_DIBData->m_BackBits = CreateDIBSection (dc,bitinfo,DIB_RGB_COLORS,(void **) &m_DIBData->m_Data,NULL,NULL);
if (m_DIBData->m_BackBits == NULL)
{
DWORD error = GetLastError ();
OutputDebugString ("error code is ");
m_DIBData->m_Data = olddata;
}
else // move data over
{
// ::SetDIBits (dc, m_DIBData->m_BackBits, 0, bitinfo->bmiHeader.biHeight, olddata, bitinfo, DIB_RGB_COLORS);
memcpy (m_DIBData->m_Data, olddata, abs (m_DIBData->m_Pitch) * m_DIBData->m_Height);
delete olddata;
}
::ReleaseDC (NULL, dc);
delete bitinfo;
if(m_DIBData->m_Pitch < 0) // only the case if we have a bottom-up section
m_DIBData->m_UpperLeft = (m_DIBData->m_Data+((-1*m_DIBData->m_Pitch)*(((int)m_DIBData->m_Height)-1)));
else
m_DIBData->m_UpperLeft = m_DIBData->m_Data;
ASSERT(NULL != m_DIBData->m_BackBits);
return m_DIBData->m_BackBits;
}
void CDIBSurface::ReleaseBitmap (void) const // call to free up GDI resources
{
if (m_DIBData->m_BackBits == NULL)
return;
unsigned char *newdata = new unsigned char [abs (m_DIBData->m_Pitch) * m_DIBData->m_Height];
if (!newdata)
return; // GDI resource not freed, but bitmap still works
#if 1
// m_BackBits must not be selected into a DC
ASSERT (m_DIBData->m_SelectedDC == NULL);
// (if that's a problem, release the dc here)
memcpy (newdata, m_DIBData->m_Data, abs (m_DIBData->m_Pitch) * m_DIBData->m_Height);
DeleteObject (m_DIBData->m_BackBits);
m_DIBData->m_BackBits = NULL;
m_DIBData->m_Data = newdata;
if(m_DIBData->m_Pitch < 0) // only the case if we have a bottom-up section
m_DIBData->m_UpperLeft = (m_DIBData->m_Data+((-1*m_DIBData->m_Pitch)*(((int)m_DIBData->m_Height)-1)));
else
m_DIBData->m_UpperLeft = m_DIBData->m_Data;
#else
BITMAPINFO *bitinfo = AllocBitmapInfo();
if (!bitinfo)
delete newdata;
else
{
// m_BackBits must not be selected into a DC
ASSERT (m_DIBData->m_SelectedDC == NULL);
// (if that's a problem, release the dc here)
HDC dc = ::GetDC (NULL);
// move data over
if (GetDIBits (dc, m_DIBData->m_BackBits, 0, bitinfo->bmiHeader.biHeight, newdata, bitinfo, DIB_RGB_COLORS))
{
DeleteObject (m_DIBData->m_BackBits);
m_DIBData->m_BackBits = NULL;
m_DIBData->m_Data = newdata;
if(m_DIBData->m_Pitch < 0) // only the case if we have a bottom-up section
m_DIBData->m_UpperLeft = (m_DIBData->m_Data+((-1*m_DIBData->m_Pitch)*(((int)m_DIBData->m_Height)-1)));
else
m_DIBData->m_UpperLeft = m_DIBData->m_Data;
}
else
{
DWORD err = GetLastError();
DPRINTF ("GetDIBits failed, error 0x%lx\n", err);
delete newdata;
}
::ReleaseDC (NULL, dc);
}
delete bitinfo;
#endif
}
BITMAPINFO *CDIBSurface::AllocBitmapInfo (void) const // delete when done with it
{
short index;
BITMAPINFO *bitinfo;
// when we create a DIB section we need to setup a BITMAPINFO structure to pass to CreateDIBSection
// this structure hold all the data about out buffer
switch(m_DIBData->m_BitDepth)
{
case 24:
bitinfo = (BITMAPINFO *) new BYTE[sizeof (BITMAPINFO)];
if(bitinfo == NULL)
return NULL;
memset (bitinfo,0,sizeof (BITMAPINFO));
bitinfo->bmiHeader.biBitCount = 24;
break;
case 16:
bitinfo = (BITMAPINFO *) new BYTE[sizeof (BITMAPINFO)];
if(bitinfo == NULL)
return NULL;
memset (bitinfo,0,sizeof (BITMAPINFO));
bitinfo->bmiHeader.biBitCount = 16;
break;
case 8:
bitinfo = (BITMAPINFO *) new BYTE[sizeof (BITMAPINFO)+(sizeof (PALETTEENTRY)*256)];
if(bitinfo == NULL)
return NULL; //lint !e525 huh
memset (bitinfo,0,sizeof (BITMAPINFO)+(sizeof (PALETTEENTRY)*256)); //lint !e419 ok size good
for(index = 0;index<256;index++)
{
bitinfo->bmiColors[index].rgbRed = 0; //lint !e662 !e661 ok
bitinfo->bmiColors[index].rgbGreen = 0; //lint !e662 !e661 ok
bitinfo->bmiColors[index].rgbBlue = 0; //lint !e662 !e661 ok
}
bitinfo->bmiHeader.biBitCount = 8;
break;
case 4:
bitinfo = (BITMAPINFO *) new BYTE[sizeof (BITMAPINFO)+(sizeof (PALETTEENTRY)*16)];
if(bitinfo == NULL)
return NULL; //lint !e525 huh
memset (bitinfo,0,sizeof (BITMAPINFO)+(sizeof (PALETTEENTRY)*16)); //lint !e419 size is good
for(index = 0;index<16;index++)
{
bitinfo->bmiColors[index].rgbRed = 0; //lint !e662 !e661 ok
bitinfo->bmiColors[index].rgbGreen = 0; //lint !e662 !e661 ok
bitinfo->bmiColors[index].rgbBlue = 0; //lint !e662 !e661 ok
}
bitinfo->bmiHeader.biBitCount = 4;
break;
case 1:
bitinfo = (BITMAPINFO *) new BYTE[sizeof (BITMAPINFO)+(sizeof (PALETTEENTRY)*2)];
if(bitinfo == NULL)
return NULL; //lint !e525 huh
memset (bitinfo,0,sizeof (BITMAPINFO)+(sizeof (PALETTEENTRY)*2)); //lint !e419 size is good
bitinfo->bmiColors[0].rgbRed = 0; //line !e662 !e661
bitinfo->bmiColors[0].rgbGreen = 0; //line !e662 !e661
bitinfo->bmiColors[0].rgbBlue = 0; //line !e662 !e661
bitinfo->bmiColors[1].rgbRed = 255; //lint !e415 ok
bitinfo->bmiColors[1].rgbGreen = 255; //lint !e415 ok
bitinfo->bmiColors[1].rgbBlue = 255; //lint !e415 ok
bitinfo->bmiHeader.biBitCount = 1;
break;
default:
OutputDebugString ("Unsupported Bitdepth for DibSections");
return NULL;
}
// these are our generic fields for both 8 and 16-bit
bitinfo->bmiHeader.biHeight = (long) (-1*((int) m_DIBData->m_Height)); // we use a negative height to mean a top-down bitmap
bitinfo->bmiHeader.biWidth = (long) m_DIBData->m_Width;
bitinfo->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
bitinfo->bmiHeader.biPlanes = 1;
bitinfo->bmiHeader.biCompression = BI_RGB;
bitinfo->bmiHeader.biSizeImage = 0;
bitinfo->bmiHeader.biXPelsPerMeter = 0;
bitinfo->bmiHeader.biYPelsPerMeter = 0;
bitinfo->bmiHeader.biClrUsed = 0;
bitinfo->bmiHeader.biClrImportant = 0;
return bitinfo;
}
#ifdef USE_FEWER_GDI_RES
using namespace NWarp;
namespace {
bool intersectintervals (int width, int srcx, int srcmax, int destx, int destmax, int& srcoffx, int& destoffx, int& interw)
{
if (destx + width <= 0 || destx >= destmax || srcx + width <= 0 || srcx >= srcmax)
return false;
// clip by minimum dest coord
if (destx < 0)
{
destoffx = 0;
srcoffx = srcx - destx;
interw = width + destx;
}
else
{
destoffx = destx;
srcoffx = srcx;
interw = width;
}
// clip by minimum src coord
if (srcx < 0)
{
destoffx -= srcx;
srcoffx -= srcx;
interw += srcx;
}
// clip by maximum source and dest coords
if (srcoffx + interw > srcmax)
interw = srcmax - srcoffx;
if (destoffx + interw > destmax)
interw = destmax - destoffx;
ASSERT (srcoffx >= 0);
ASSERT (srcoffx < srcmax);
ASSERT (destoffx >= 0);
ASSERT (destoffx < destmax);
ASSERT (interw > 0);
ASSERT (interw <= width);
return true;
}
}
// this version does not have the rop argument, assumes SRC_COPY
template <class PixelHandlerType>
bool BltNonGDI (PixelHandlerType& pixelhandler, const CDIBSurface& dest,const int destx,const int desty,const int width,const int height,const CDIBSurface& src,const int srcx,const int srcy)
{
ASSERT (pixelhandler.Depth() == src.GetBitDepth());
ASSERT (pixelhandler.Depth() == dest.GetBitDepth());
int srcoffx, destoffx, interw;
int srcoffy, destoffy, interh;
if (!intersectintervals (width, srcx, src.GetWidth(), destx, dest.GetWidth(), srcoffx, destoffx, interw))
return true; // nothing to blit
if (!intersectintervals (height, srcy, src.GetHeight(), desty, dest.GetHeight(), srcoffy, destoffy, interh))
return true; // nothing to blit
const unsigned char *srcscanline = src.GetMem() + srcoffy * src.GetPitch();
const unsigned char *destscanline = dest.GetMem() + destoffy * dest.GetPitch();
// can be made much faster by doing larger reads/writes on aligned data
#if 1
if ((pixelhandler.Depth() & 0x7) == 0)
{
const int pixsize = (pixelhandler.Depth() >> 3);
for (int j = 0; j < interh; j++)
{
memcpy ((void*)(destscanline + destoffx * pixsize), (void*)(srcscanline + srcoffx * pixsize), interw * pixsize);
srcscanline += src.GetPitch();
destscanline += dest.GetPitch();
}
}
else
#endif
for (int j = 0; j < interh; j++)
{
CPixelAddress s = pixelhandler.Increment (pixelhandler.PixelAddress ((void*)srcscanline), srcoffx);
CPixelAddress d = pixelhandler.Increment (pixelhandler.PixelAddress ((void*)destscanline), destoffx);
for (int i = 0; i < interw; i++)
{
CPixel pixel = pixelhandler.Get (s);
pixelhandler.Set (d, pixel);
s = pixelhandler.Increment (s);
d = pixelhandler.Increment (d);
}
srcscanline += src.GetPitch();
destscanline += dest.GetPitch();
}
return true;
}
#pragma intrinsic(memcpy)
// this version does not have the rop argument, assumes SRC_COPY
bool BltNonGDI16 (const CDIBSurface& dest,const int destx,const int desty,const int width,const int height,const CDIBSurface& src,const int srcx,const int srcy)
{
ASSERT (16 == src.GetBitDepth());
ASSERT (16 == dest.GetBitDepth());
int srcoffx, destoffx, interw;
int srcoffy, destoffy, interh;
if (!intersectintervals (width, srcx, src.GetWidth(), destx, dest.GetWidth(), srcoffx, destoffx, interw))
return true; // nothing to blit
if (!intersectintervals (height, srcy, src.GetHeight(), desty, dest.GetHeight(), srcoffy, destoffy, interh))
return true; // nothing to blit
const int srcpitch = src.GetPitch();
const int destpitch = dest.GetPitch();
const unsigned char *srcscanline = src.GetMem() + srcoffy * srcpitch;
const unsigned char *destscanline = dest.GetMem() + destoffy * destpitch;
const unsigned char *s = srcscanline + (srcoffx << 1);
const unsigned char *d = destscanline + (destoffx << 1);
const unsigned char *q = s + interh * srcpitch;
ASSERT (((DWORD)s & 0x03) != 3); // these addresses cause stalls, but should not happen
ASSERT (((DWORD)d & 0x03) != 3); // these addresses cause stalls, but should not happen
while (s != q)
{
memcpy ((void*)d, s, interw << 1);
s += srcpitch;
d += destpitch;
}
return true;
}
// this version does not have the rop argument, assumes SRC_COPY
template <class PixelHandlerType>
bool MaskBltNonGDI (PixelHandlerType& pixelhandler, const CDIBSurface& dest,const int destx,const int desty,int width,int height,const CDIBSurface& src,int srcx,int srcy)
{
ASSERT (pixelhandler.Depth() == src.GetBitDepth());
ASSERT (pixelhandler.Depth() == dest.GetBitDepth());
ASSERT (src.UseMask());
if(!src.UseMask ())
return false;
CPixelHandler1 pixelhandler1;
int srcoffx, destoffx, interw;
int srcoffy, destoffy, interh;
if (width <= 0 || !intersectintervals (width, srcx, src.GetWidth(), destx, dest.GetWidth(), srcoffx, destoffx, interw))
return true; // nothing to blit
if (height <= 0 || !intersectintervals (height, srcy, src.GetHeight(), desty, dest.GetHeight(), srcoffy, destoffy, interh))
return true; // nothing to blit
const unsigned char *srcscanline = src.GetMem() + srcoffy * src.GetPitch();
const unsigned char *maskscanline = src.Mask()->GetMem() + srcoffy * src.Mask()->GetPitch();
const unsigned char *destscanline = dest.GetMem() + destoffy * dest.GetPitch();
// can be made much faster by doing larger reads/writes on aligned data
for (int j = 0; j < interh; j++)
{
CPixelAddress m = pixelhandler1.Increment (pixelhandler1.PixelAddress ((void*)maskscanline), srcoffx);
CPixelAddress s = pixelhandler.Increment (pixelhandler.PixelAddress ((void*)srcscanline), srcoffx);
CPixelAddress d = pixelhandler.Increment (pixelhandler.PixelAddress ((void*)destscanline), destoffx);
for (int i = 0; i < interw; i++)
{
if (pixelhandler1.Get (m) == 0)
pixelhandler.Set (d, pixelhandler.Get (s));
m = pixelhandler1.Increment (m);
s = pixelhandler.Increment (s);
d = pixelhandler.Increment (d);
}
maskscanline += src.Mask()->GetPitch();
srcscanline += src.GetPitch();
destscanline += dest.GetPitch();
}
return true;
}
// this version does not have the rop argument, assumes SRC_COPY
bool MaskBltNonGDI16 (const CDIBSurface& dest,const int destx,const int desty,int width,int height,const CDIBSurface& src,int srcx,int srcy)
{
ASSERT (16 == src.GetBitDepth());
ASSERT (16 == dest.GetBitDepth());
ASSERT (src.UseMask());
if(!src.UseMask ())
return false;
int srcoffx, destoffx, interw;
int srcoffy, destoffy, interh;
if (!intersectintervals (width, srcx, src.GetWidth(), destx, dest.GetWidth(), srcoffx, destoffx, interw))
return true; // nothing to blit
if (!intersectintervals (height, srcy, src.GetHeight(), desty, dest.GetHeight(), srcoffy, destoffy, interh))
return true; // nothing to blit
CPixelHandler1 pixelhandler1;
const int srcpitch = src.GetPitch();
const int destpitch = dest.GetPitch();
const int maskpitch = src.Mask()->GetPitch();
const unsigned char *srcscanline = src.GetMem() + srcoffy * srcpitch;
const unsigned char *maskscanline = src.Mask()->GetMem() + srcoffy * maskpitch;
const unsigned char *destscanline = dest.GetMem() + destoffy * destpitch;
const unsigned char *s = srcscanline + (srcoffx << 1);
const unsigned char *d = destscanline + (destoffx << 1);
const unsigned char *q = s + interh * srcpitch;
ASSERT (((DWORD)s & 0x03) != 3); // these addresses cause stalls, but should not happen
ASSERT (((DWORD)d & 0x03) != 3); // these addresses cause stalls, but should not happen
while (s != q)
{
CPixelAddress m = pixelhandler1.Increment (pixelhandler1.PixelAddress ((void*)maskscanline), srcoffx);
const unsigned short *is = (const unsigned short *)s;
const unsigned short *iq = (const unsigned short *)s + interw;
unsigned short *id = (unsigned short *)d;
while (is != iq)
{
if (pixelhandler1.Get (m) == 0)
*id = *is;
m = pixelhandler1.Increment (m);
++is, ++id;
}
s += srcpitch;
d += destpitch;
maskscanline += maskpitch;
}
return true;
}
// this version does not have the rop argument, assumes SRC_COPY
bool CDIBSurface::BltNonGDI (int x,int y,int width,int height,const CDIBSurface& src,int srcx,int srcy)
{
#ifdef _DEBUG
static int doit = 0;
if (doit)
{ // revert back to traditional blit for tests
HDC dc1,dc2;
bool toret;
dc1 = GetDC ();
dc2 = src.GetDC ();
if (!(dc1 && dc2))
{
if (dc1)
ReleaseDC (dc1);
if (dc2)
src.ReleaseDC (dc2);
return false;
}
toret = (::BitBlt (dc1,x,y,width,height,dc2,srcx,srcy,SRCCOPY) == TRUE);
ReleaseDC (dc1);
src.ReleaseDC (dc2);
return toret;
}
#endif
ASSERT (GetBitDepth() == src.GetBitDepth());
switch (GetBitDepth())
{
case 1:
return ::BltNonGDI (CPixelHandler1(), *this,x,y,width,height,src,srcx,srcy);
case 8:
return ::BltNonGDI (CPixelHandler8(), *this,x,y,width,height,src,srcx,srcy);
case 16:
return ::BltNonGDI16 (*this,x,y,width,height,src,srcx,srcy);
case 24:
return ::BltNonGDI (CPixelHandler24(), *this,x,y,width,height,src,srcx,srcy);
case 32:
return ::BltNonGDI (CPixelHandler32(), *this,x,y,width,height,src,srcx,srcy);
default:
ASSERT (0);
return false;
}
}
// this version does not have the rop argument, assumes SRC_COPY
bool CDIBSurface::MaskBltNonGDI (int x,int y,int width,int height,const CDIBSurface& src,int srcx,int srcy)
{
#ifdef _DEBUG
static int doit = 0;
if (doit)
{ // revert back to traditional blit for tests
ASSERT (m_DIBData);
ASSERT (src.m_DIBData);
ASSERT (src.UseMask ());
if(!src.UseMask ())
return false;
HDC dc = GetDC ();
SetBkColor(dc, RGB(255, 255, 255)); // 1s --> 0xFFFFFF
SetTextColor(dc, RGB(0, 0, 0)); // 0s --> 0x000000
// BitBlt(m_BackDC, x, y, width, height, src->m_BackDC, srcx, srcy, SRCINVERT);
HDC dc2,dc3;
dc2 = src.m_DIBData->m_Mask->GetDC ();
dc3 = src.GetDC ();
BitBlt(dc, x, y, width, height, dc2, srcx, srcy, SRCAND);
BitBlt(dc, x, y, width, height, dc3, srcx, srcy, SRCPAINT);
src.m_DIBData->m_Mask->ReleaseDC (dc2);
src.ReleaseDC (dc3);
ReleaseDC (dc);
return true;
}
#endif
ASSERT (GetBitDepth() == src.GetBitDepth());
switch (GetBitDepth())
{
case 1:
return ::MaskBltNonGDI (CPixelHandler1(), *this,x,y,width,height,src,srcx,srcy);
case 8:
return ::MaskBltNonGDI (CPixelHandler8(), *this,x,y,width,height,src,srcx,srcy);
case 16:
return ::MaskBltNonGDI (CPixelHandler16(), *this,x,y,width,height,src,srcx,srcy);
case 24:
return ::MaskBltNonGDI (CPixelHandler24(), *this,x,y,width,height,src,srcx,srcy);
case 32:
return ::MaskBltNonGDI (CPixelHandler32(), *this,x,y,width,height,src,srcx,srcy);
default:
ASSERT (0);
return false;
}
}
#else
bool CDIBSurface::BltNonGDI (int x,int y,int width,int height,const CDIBSurface& src,int srcx,int srcy)
{
HDC dc1,dc2;
bool toret;
dc1 = GetDC ();
dc2 = src.GetDC ();
if (!(dc1 && dc2))
{
if (dc1)
ReleaseDC (dc1);
if (dc2)
src.ReleaseDC (dc2);
return false;
}
toret = (::BitBlt (dc1,x,y,width,height,dc2,srcx,srcy,SRCCOPY) == TRUE);
ReleaseDC (dc1);
src.ReleaseDC (dc2);
return toret;
}
bool CDIBSurface::MaskBltNonGDI (int x,int y,int width,int height,const CDIBSurface& src,int srcx,int srcy)
{
ASSERT (m_DIBData);
ASSERT (src.m_DIBData);
ASSERT (src.UseMask ());
if(!src.UseMask ())
return false;
HDC dc = GetDC ();
SetBkColor(dc, RGB(255, 255, 255)); // 1s --> 0xFFFFFF
SetTextColor(dc, RGB(0, 0, 0)); // 0s --> 0x000000
// BitBlt(m_BackDC, x, y, width, height, src->m_BackDC, srcx, srcy, SRCINVERT);
HDC dc2,dc3;
dc2 = src.m_DIBData->m_Mask->GetDC ();
dc3 = src.GetDC ();
BitBlt(dc, x, y, width, height, dc2, srcx, srcy, SRCAND);
BitBlt(dc, x, y, width, height, dc3, srcx, srcy, SRCPAINT);
src.m_DIBData->m_Mask->ReleaseDC (dc2);
src.ReleaseDC (dc3);
ReleaseDC (dc);
return true;
}
#endif