#ifndef __DIBSURFHPP__
#define __DIBSURFHPP__

//*******************************************************************
//
//    DESCRIPTION: Header file for CDIBSurface class
//
//    AUTHOR: Andrew Farrier
//
//    SourceSafe Version: $Revision: 68 $
//
//    HISTORY: Created 11/15/95
//
//*******************************************************************

#include <map>
#include <vector>
#include <stack>

#pragma warning (disable : 4786)

struct DCData
{
	HDC thedc;
	HBITMAP oldbits;
	DCData (void)
	{
		thedc = NULL;
		oldbits = NULL;
	}
	DCData (HDC p1,HBITMAP p2)
	{
		thedc = p1;
		oldbits = p2;
	}
	~DCData (void)
	{
		thedc = NULL;
		oldbits = NULL;
	}
	DCData (const DCData& p1)
	{
		thedc = p1.thedc;
		oldbits = p1.oldbits;
	}
	DCData& operator= (const DCData& p1)
	{
		thedc = p1.thedc;
		oldbits = p1.oldbits;
		return *this;
	}
};

//****************************************************************
//
// Function Name: clamp
//
// Description: Will clamp x to be between min and max exclusive
//
// Returns: clamped value of x
//
//****************************************************************
template<typename type>
inline type clamp (const type& min,const type& x,const type& max)
{
  if (x < min)
    return min;
  if (x>max)
    return max;
  return x;
}

//****************************************************************
//
// Function Name: RGBQUADtoCOLORREF
//
// Description: Will convert from an RGBQUAD to a COLORREF
//
// Returns: the COLORREF equal to the RGBQUAD
//
//****************************************************************
inline COLORREF RGBQUADtoCOLORREF (RGBQUAD value)
{
  int red,green,blue;
  COLORREF toret;

  red = value.rgbRed;
  green = value.rgbGreen;
  blue = value.rgbBlue;
  toret = RGB (red,green,blue);
  return toret;
}

//****************************************************************
//
// Function Name: RGBtoCOLORREF
//
// Description: Will convert from an RGB packed int to a COLORREF
//          int is in the form 0x00RRGGBB
//
// Returns: the COLORREF equal to the packed value
//
//****************************************************************
inline COLORREF RGBtoCOLORREF (int value)
{
  int red,green,blue;
  COLORREF toret;

  red = (value>>16) & 0xff;
  green = (value>>8) & 0xff;
  blue = value&0xff;
  toret = RGB (red,green,blue);
  return toret;
}

//****************************************************************
//
// Function Name: COLORREFtoRGBQUAD
//
// Description: Will convert from a COLORREF value to an RGBQUAD
//
// Returns: the RGBQUAD equal to the COLORREF
//
//****************************************************************
inline RGBQUAD COLORREFtoRGBQUAD (COLORREF value)
{
  RGBQUAD toret;

  toret.rgbRed = (value >> 16) & 0xff;
  toret.rgbGreen = (value >> 8) & 0xff;
  toret.rgbBlue = value & 0xff;
  return toret;
}

class CDIBSurface
{
private:

	static std::vector<HDC> *m_FreeDC;
	static std::vector<DCData> *m_AllDCs;
	static int m_DCStackRefCount;

	struct FloodData
	{
		unsigned char *mem;
		CPoint where;
		FloodData (unsigned char *p1,CPoint p2)
		{mem = p1;where = p2;}
	};

  bool Create1BitMask (COLORREF colorref);
  bool Create4BitMask (COLORREF colorref);
  bool Create8BitMask (COLORREF colorref);
  bool Create16BitMask (COLORREF colorref);
  bool Create24BitMask (COLORREF colorref);
	int FloodFill24 (const CPoint& start,const COLORREF color);
  bool AlphaBlt16 (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);
  bool AlphaBlt24 (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);
	bool ColorBlt16 (const int x,const int y,const int width,const int height,const CDIBSurface* src,const int srcx,const int srcy,const COLORREF color,bool addred=true,bool addgreen=true,bool addblue=true,CDIBSurface *altmask=NULL);
	bool ColorBlt24 (const int x,const int y,const int width,const int height,const CDIBSurface* src,const int srcx,const int srcy,const COLORREF color,bool addred=true,bool addgreen=true,bool addblue=true,CDIBSurface *altmask=NULL);
	bool GrayBlt16 (const int x,const int y,const int width,const int height,const CDIBSurface* srcdib,const int srcx,const int srcy,CDIBSurface *altmask=NULL);
	bool GrayBlt24 (const int x,const int y,const int width,const int height,const CDIBSurface* srcdib,const int srcx,const int srcy,CDIBSurface *altmask=NULL);

	bool MultBlt16 (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=NULL);
	bool MultBlt24 (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=NULL);
	bool Convert24to16 (void);
  bool SetupLoadedBitmap (HBITMAP hbm);
	BITMAPINFO *AllocBitmapInfo (void) const;	// delete when done with it
	void ClearData (void);
	struct DIBData
	{
		CDIBSurface *m_Mask;
	
		HDC m_SelectedDC;
		int m_SelectedDCRefCount;
		bool m_AllocedDC;
		HBITMAP m_OldBitmap;
		HBITMAP m_BackBits;		// may be NULL, call GetBitmap() if you need to create it
//		HBITMAP m_OldBits;
		unsigned char *m_Data;
		unsigned char *m_UpperLeft;
		UINT m_Width,m_Height;
		UINT m_BitDepth;
		int m_Pitch;
	
		bool m_OwnPalette;
	
		bool m_UseMask;
	};

protected:

	UINT *m_RefCount;
	DIBData *m_DIBData;

public:

  CDIBSurface (void);
  CDIBSurface (UINT Width,UINT Height,UINT BitDepth);
  CDIBSurface (const CDIBSurface&);
	CDIBSurface& operator= (const CDIBSurface&);
  ~CDIBSurface (void);

  bool Create (UINT Width,UINT Height,UINT BitDepth=0);
  void Destroy (void);

	bool operator== (const CDIBSurface& param)
	{
		if(!param.IsValid ())
			return false;
		if(!IsValid ())
			return false;
		ASSERT (m_DIBData);
		ASSERT (param.m_DIBData);
		return param.m_DIBData->m_Data == m_DIBData->m_Data;
	}

  HDC  GetDC (void);
  HDC  GetDC (void) const;
  void ReleaseDC (HDC) const;
	void UseDC (HDC);

	// These are not really consts, but behave like that (the state of the object
	// is not the same on return, but it has the same functionality). This was needed
	// to keep GetDC() const happy.
	HBITMAP GetBitmap (void) const;	// actually creates the DIB section (if needed)
	void ReleaseBitmap (void) const;	// call to free up GDI resources

	unsigned char *CDIBSurface::GetMem (void)
	{
		ASSERT (m_DIBData);
		if(!m_DIBData->m_Data)
			return NULL;
		if(!GdiFlush ())
			return NULL;
		return m_DIBData->m_UpperLeft;
	}
	unsigned char *GetMem( int x, int y );
	unsigned char *GetData( void )
	{
		ASSERT( m_DIBData );
		if( !(m_DIBData->m_Data && GdiFlush()) )
			return( NULL );
		return( m_DIBData->m_Data );
	}
	const unsigned char *GetData( void ) const
	{
		ASSERT( m_DIBData );
		if( !(m_DIBData->m_Data && GdiFlush()) )
			return( NULL );
		return( m_DIBData->m_Data );
	}

  bool ReleaseMem (unsigned char *)
  { return (GdiFlush ()==TRUE);}

	const unsigned char *CDIBSurface::GetMem (void) const
	{
		ASSERT (m_DIBData);
		if(!m_DIBData->m_Data)
			return NULL;
		if(!GdiFlush ())
			return NULL;
		return m_DIBData->m_UpperLeft;
	}
  void ReleaseMem (const unsigned char *) const
  {}

  int GetPitch (void) const
  {
		ASSERT (m_DIBData);
    return m_DIBData->m_Pitch;
  }

  int GetLocation (UINT x,UINT y) const
  {
		int tx,ty;
		ASSERT (m_DIBData);
    ASSERT (((UINT) x) < m_DIBData->m_Width);
    ASSERT (((UINT) y) < m_DIBData->m_Height);
    switch(m_DIBData->m_BitDepth)
    {
    case 1:
      x>>=3;
      break;
    case 4:
      x>>=1;
      break;
    case 8:
      break;
    case 16:
      x<<=1;
      break;
    case 24:
      x *= 3;
      break;
    default:
      ASSERT (false);
      break;
    }
		tx = (int) x;
		ty = (int) y;
    return((ty*m_DIBData->m_Pitch)+tx);
  }



  DWORD GetValue (UINT x,UINT y) const
  {
    const unsigned char *mem;
    DWORD toret;

		ASSERT (m_DIBData);
    ASSERT (((UINT) x) < m_DIBData->m_Width);
    ASSERT (((UINT) y) < m_DIBData->m_Height);
    mem = GetMem ();

    mem += GetLocation (x,y);
    toret = 0;
    switch(m_DIBData->m_BitDepth)
    {
    case 1:
      toret = (*mem >> ((~x)&0x07)) & 0x01;		//lint !e504
      break;
    case 4:
      if(x & 0x01)
        toret = *mem & 0x0f;
      else
        toret = *mem>>4;
      break;
    case 8:
      toret = *mem;
      break;
    case 16:
      toret = (*(mem+1)<<8) + *(mem);
      break;
    case 24:
      toret = ((*mem)<<16)+ ((*(mem+1))<<8) + (*(mem+2));
      break;
    default:
      ASSERT (false);
      break;
    }

    ReleaseMem (mem);
    return toret;
  }

  void SetValue (UINT x,UINT y,DWORD value)
  {
    unsigned char *mem;
    DWORD toret;

		ASSERT (m_DIBData);
    ASSERT (((UINT) x) < m_DIBData->m_Width);
    ASSERT (((UINT) y) < m_DIBData->m_Height);
    mem = GetMem ();

    mem += GetLocation (x,y);
    toret = 0;
    switch(m_DIBData->m_BitDepth)
    {
    case 1:
			if (value & 0x01)
				*mem |= (0x01 << ((~x)&0x07));
			else
				*mem &= ~(0x01 << ((~x)&0x07));
      break;
    case 4:
			value &= 0x0f;
      if(x & 0x01)
			{
				*mem &= 0xf0;
				*mem |= value;
			}
      else
			{
				value <<= 4;
				*mem &= 0x0f;
				*mem |= value;
			}
      break;
    case 8:
			value &= 0xff;
			*mem = value;
      break;
    case 16:
			value &= 0xffff;
			*(mem+1) = value&0xff;
			*(mem) = ((value>>8) & 0xff);
      break;
    case 24:
			value &= 0xffffff;
			*(mem+2) = value&0xff;
			*(mem+1) = ((value>>8) & 0xff);
			*(mem) = ((value>>16) & 0xff);
      break;
    default:
      ASSERT (false);
      break;
    }

    ReleaseMem (mem);
  }


  COLORREF GetColor (UINT x,UINT y) const;
	void SetColor (UINT x,UINT y,COLORREF color);
	void SetColor( COLORREF color );

  bool Fill (const CRect *therect,const COLORREF colorref=0);
  bool Fill (const int left,const int top,const int right,const int bottom,const COLORREF colorref=0)
  {return Fill (&CRect(left,top,right,bottom),colorref);}   //lint !e50
  bool Fill (const CPoint& topleft,const CPoint& botright,const COLORREF colorref=0)
  {return Fill (&CRect (topleft,botright),colorref);}   //lint !e50
  bool Fill (const CRect& therect,const COLORREF colorref=0)
  {return Fill (&therect,colorref);}
  bool FillHatchBrush (const CRect *therect,
	  int stockHatchBrushStyle,const COLORREF colorref=0);
  bool FillHatchBrush (const int left,const int top,const int right,
	  const int bottom,int stockHatchBrushStyle,const COLORREF colorref=0)
  {return FillHatchBrush (&CRect(left,top,right,bottom),
			stockHatchBrushStyle, colorref);}   //lint !e50

	bool HighlightFrame (const CRect& therect,bool up);	// light is from upper left
	void HLine( int x1, int x2, int y, COLORREF crColor );

  bool Blt (int x,int y,int width,int height,const CDIBSurface *src,int srcx,int srcy,DWORD rop=SRCCOPY);

  bool Blt (const CPoint& loc,const CSize& size,const CDIBSurface *src,const CPoint& srcloc,DWORD rop=SRCCOPY)
  {return Blt (loc.x,loc.y,size.cx,size.cy,src,srcloc.x,srcloc.y,rop);}
  bool Blt (const CRect& loc,const CDIBSurface *src,const CPoint& srcloc,DWORD rop=SRCCOPY)
  {return Blt (loc.left,loc.top,loc.Width(),loc.Height(),src,srcloc.x,srcloc.y,rop);}

  bool Blt (int x,int y,int width,int height,const CDIBSurface& src,int srcx,int srcy,DWORD rop=SRCCOPY)
  {return Blt (x,y,width,height,&src,srcx,srcy,rop);}
  bool Blt (const CPoint& loc,const CSize& size,const CDIBSurface& src,const CPoint& srcloc,DWORD rop=SRCCOPY)
  {return Blt (loc.x,loc.y,size.cx,size.cy,&src,srcloc.x,srcloc.y,rop);}
  bool Blt (const CRect& loc,const CDIBSurface& src,const CPoint& srcloc,DWORD rop=SRCCOPY)
  {return Blt (loc.left,loc.top,loc.Width(),loc.Height(),&src,srcloc.x,srcloc.y,rop);}


  bool Blt (int x,int y,int width,int height,HDC src,int srcx,int srcy,DWORD rop)
  {
		ASSERT (m_DIBData);
		ASSERT (src);
		ASSERT (IsValid ());
		if((!src) || (!IsValid()))
			return false;
		HDC dc;
		bool toret;
		dc = GetDC ();
		toret = (::BitBlt (dc,x,y,width,height,src,srcx,srcy,rop)==TRUE);
		ReleaseDC (dc);
		return toret;
	}


	// these two are functionally equivalent to their normal versions but do not
	// perform format or palette conversions and do not use any GDI resources
	bool BltNonGDI (int x,int y,int width,int height,const CDIBSurface& src,int srcx,int srcy);
	bool MaskBltNonGDI (int x,int y,int width,int height,const CDIBSurface& src,int srcx,int srcy);

  bool 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);
  bool MaskBlt (const int x,const int y,const int width,const int height,const CDIBSurface *src,const int srcx,const int srcy);

	bool 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=-1,const int alphasrcy=-1);
  bool AlphaBlt (const CRect& loc,const CDIBSurface *src,const CDIBSurface *alpha,const CPoint& srcloc)
	{ return AlphaBlt (loc.left,loc.top,loc.Width (),loc.Height(),src,alpha,srcloc.x,srcloc.y); }
  bool AlphaBlt (const CRect& loc,const CDIBSurface *src,const CDIBSurface *alpha,const CPoint& srcloc,const CPoint& alphaloc)
	{ return AlphaBlt (loc.left,loc.top,loc.Width (),loc.Height(),src,alpha,srcloc.x,srcloc.y,alphaloc.x,alphaloc.y); }
  bool 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=-1,const int alphasrcy=-1)
	{ return AlphaBlt (x,y,width,height,&src,&alpha,srcx,srcy,alphasrcx,alphasrcy); }
  bool AlphaBlt (const CRect& loc,const CDIBSurface& src,const CDIBSurface& alpha,const CPoint& srcloc)
	{ return AlphaBlt (loc.left,loc.top,loc.Width (),loc.Height(),&src,&alpha,srcloc.x,srcloc.y); }
  bool AlphaBlt (const CRect& loc,const CDIBSurface& src,const CDIBSurface& alpha,const CPoint& srcloc,const CPoint& alphaloc)
	{ return AlphaBlt (loc.left,loc.top,loc.Width (),loc.Height(),&src,&alpha,srcloc.x,srcloc.y,alphaloc.x,alphaloc.y); }

  bool RotateBlt( int left, int top, int right, int bottom, const CDIBSurface& src, int x, int y, int ang );
  bool RotateBlt( const CRect& loc, const CDIBSurface& src, const CPoint& srcloc, int ang )
	{ return( RotateBlt( loc.left, loc.top, loc.right, loc.bottom, src, srcloc.x, srcloc.y, ang ) ); }
  bool TransparentBlt( int left, int top, int right, int bottom, const CDIBSurface& src, int x, int y, const COLORREF bgClr );
  bool TransparentBlt( const CRect& loc, const CDIBSurface& src, const CPoint& srcloc, const COLORREF bgClr )
	{ return( TransparentBlt( loc.left, loc.top, loc.right, loc.bottom, src, srcloc.x, srcloc.y, bgClr ) ); }

	bool ColorBlt (const int x,const int y,const int width,const int height,const CDIBSurface* src,const int srcx,const int srcy,const COLORREF color,bool addred=true,bool addgreen=true,bool addblue=true,CDIBSurface *altmask=NULL);
	bool ColorBlt (const CRect& loc,const CDIBSurface* src,const CPoint& srcloc,const COLORREF color,bool addred=true,bool addgreen=true,bool addblue=true,CDIBSurface *altmask=NULL)
	{ return ColorBlt (loc.left,loc.top,loc.Width (),loc.Height (),src,srcloc.x,srcloc.y,color,addred,addgreen,addblue,altmask); }

	bool GrayBlt (const int x,const int y,const int width,const int height,const CDIBSurface* src,const int srcx,const int srcy, CDIBSurface *altmask=NULL);

	bool 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=NULL);
	bool MultBlt (const CRect& loc,const CDIBSurface* src,const CPoint& srcloc,const float red,const float green,const float blue,CDIBSurface *altmask=NULL)
	{ return MultBlt (loc.left,loc.top,loc.Width (),loc.Height (),src,srcloc.x,srcloc.y,red,green,blue,altmask); }

  bool SetClipArea (HRGN newcliparea)
  {	return false; /*	ASSERT (m_DIBData);if(SelectClipRgn (m_DIBData->m_BackDC,newcliparea) == ERROR) return false;return true;*/}




  bool StretchBlt (const CRect& loc,const CDIBSurface *src,const CRect& srcloc,DWORD rop=SRCCOPY)
  {return StretchBlt (loc.left,loc.top,loc.Width(),loc.Height(),src,srcloc.left,srcloc.top,srcloc.Width(),srcloc.Height(),rop);}
  bool StretchBlt (const CRect& loc,const CDIBSurface& src,const CRect& srcloc,DWORD rop=SRCCOPY)
  {return StretchBlt (loc.left,loc.top,loc.Width(),loc.Height(),&src,srcloc.left,srcloc.top,srcloc.Width(),srcloc.Height(),rop);}

  bool StretchBlt (int x,int y,int width,int height,const CDIBSurface *src,int srcx,int srcy,int srcwidth,int srcheight,DWORD rop)
  {
		ASSERT (m_DIBData);
		ASSERT (src);
		ASSERT (IsValid ());
		if((!src) || (!IsValid()))
			return false;
		HDC dc1,dc2;
		bool toret;

		dc1 = GetDC ();
		dc2 = src->GetDC ();
		ASSERT (dc1 && dc2);
		toret = (::StretchBlt (dc1,x,y,width,height,dc2,srcx,srcy,srcwidth,srcheight,rop)==TRUE);
		ReleaseDC (dc1);
		src->ReleaseDC (dc2);
		return toret;
	}

  bool StretchBlt (int x,int y,int width,int height,HDC src,int srcx,int srcy,int srcwidth,int srcheight,DWORD rop)
  {
		ASSERT (m_DIBData);
		ASSERT (src);
		ASSERT (IsValid ());
		if((!src) || (!IsValid()))
			return false;
		HDC dc;
		bool toret;
		dc = GetDC ();
		toret = (::StretchBlt (dc,x,y,width,height,src,srcx,srcy,srcwidth,srcheight,rop)==TRUE);
		ReleaseDC (dc);
		return toret;
	}

	int FloodFill (const CPoint& start,const COLORREF color);

  bool SetSize (UINT cx,UINT cy,UINT BitDepth)
  {		ASSERT (m_DIBData);Destroy (); return Create (cx,cy,BitDepth);}


  UINT GetWidth (void) const
  {		ASSERT (m_DIBData);return m_DIBData->m_Width;}
  UINT GetHeight (void) const
  {		ASSERT (m_DIBData);return m_DIBData->m_Height;}
  UINT GetBitDepth (void) const
  {		ASSERT (m_DIBData);return m_DIBData->m_BitDepth;}
	CSize GetSize( void ) const
	{ ASSERT (m_DIBData); return CSize( m_DIBData->m_Width, m_DIBData->m_Height ); }
  CDIBSurface* Mask (void)
  {		ASSERT (m_DIBData);return m_DIBData->m_Mask;}
  const CDIBSurface* Mask (void) const
  {		ASSERT (m_DIBData);return m_DIBData->m_Mask;}
  bool UseMask (void) const
  {		ASSERT (m_DIBData);return m_DIBData->m_UseMask;}
  void UseMask (bool newflag)
  {		ASSERT (m_DIBData);if((!newflag) || ((m_DIBData->m_Mask) && (m_DIBData->m_Mask->IsValid ()))) m_DIBData->m_UseMask = newflag;}

  bool IsValid (void) const
  {		ASSERT (m_DIBData);return m_DIBData->m_Data != NULL;}

  bool CopyBitmap(HBITMAP hbm,int x,int y,int dx,int dy);

  bool CalcMask (COLORREF colorref);
  bool CalcMask (const std::vector<COLORREF>& colors);
  bool CalcMask (void);
	bool DestroyMask (void);

	bool ConvertBitDepth (int newdepth);
	bool ConvertToGray (void);	// converts contents to 8-bit with gray palette


  //white is transparent

  WORD ConvertColorToWord( COLORREF crColor )
	{ return( WORD( ((0xf80000 & crColor) >> 19) | ((0xf800 & crColor) >> 6) | ((0xf8 & crColor) << 7) ) ); }
  RGBTRIPLE ConvertColorToTriple( COLORREF crColor )
	{ RGBTRIPLE rgb = { (0xff & crColor) >> 16, 0xff & (crColor >> 8), 0xff & crColor }; return( rgb ); }
  DWORD ConvertColorToLong( COLORREF crColor )
	{ return( DWORD( 0x00ffffff & crColor ) ); }

  COLORREF ConvertWordToColor( WORD wColor )
	{ return( RGB( (0x7c00 & wColor) >> 7, (0x03e0 & wColor) >> 2, (0x1f & wColor) << 3 ) ); }
  COLORREF ConvertTripleToColor( RGBTRIPLE rgbColor )
	{ return( RGB( rgbColor.rgbtRed, rgbColor.rgbtGreen, rgbColor.rgbtBlue ) ); }
  COLORREF ConvertLongToColor( DWORD dwColor )
	{ return( RGB( 0xff & dwColor, (0xff00 & dwColor) >> 8, (0xff0000 & dwColor) >> 16 ) ); }

	void ClearOutsideMask (void)	// clears any part of the bitmap that is in the transparent part of the mask
	{	if (Mask())
			Blt (0, 0, GetWidth(), GetHeight(), Mask(), 0, 0, 0x00220326); // DSna
	}

	bool SplitRef (void);

  void AddRef (void)
  {
		ASSERT (m_RefCount);
    (*m_RefCount)++;
		if(!m_DCStackRefCount)
		{
			m_AllDCs = new std::vector<DCData>;
			m_FreeDC = new std::vector<HDC>;
		}
		m_DCStackRefCount++;
  }
	bool Release (void)
  {
		ASSERT (m_RefCount);
		ASSERT (*m_RefCount);
		ASSERT (m_DIBData);
		m_DCStackRefCount--;
		if(!m_DCStackRefCount)
		{
				std::vector<DCData>::iterator iter;
				ASSERT (m_FreeDC->size () == m_AllDCs->size ());
				iter = m_AllDCs->begin ();
				while(iter != m_AllDCs->end ())
				{
					DeleteDC (iter->thedc);
					iter++;
				}
				delete m_FreeDC;
				delete m_AllDCs;
				m_FreeDC = NULL;
				m_AllDCs = NULL;
		}
    (*m_RefCount)--;
    if (!(*m_RefCount))
    {
			Destroy ();
			delete m_RefCount;
			delete m_DIBData;
			m_RefCount = NULL;
			m_DIBData = NULL;
      return false;
    }
    return true;
  }


#if 0
  static void *operator new (size_t size)
  {
    void *temp;

    temp = new BYTE[size];
		if(!temp)
		{
			return NULL;
		}
		memset (temp,0,size);
		((CDIBSurface *) temp)->m_RefCount = 1;
		((CDIBSurface *) temp)->m_Alloced = true;
		return temp;
  }
  static void operator delete (void *,size_t)
	{ }
#endif
};

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

inline bool MaskBlt (HDC dest,const CPoint& loc,const CSize& size,const CDIBSurface *src,const CPoint& srcloc)
{return MaskBlt (dest,loc.x,loc.y,size.cx,size.cy,src,srcloc.x,srcloc.y);}
inline bool MaskBlt (HDC dest,const CRect& loc,const CDIBSurface *src,const CPoint& srcloc)
{return MaskBlt (dest,loc.left,loc.top,loc.Width(),loc.Height(),src,srcloc.x,srcloc.y);}

#endif
