| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 | #include "bltcanvas.h"#include <tataki/bitmap/bitmap.h>BltCanvas::~BltCanvas(){	if (hdc == NULL) return ;	// kill the bitmap and its DC	SelectObject(hdc, prevbmp);	if (ourbmp)	{		//GdiFlush();		DeleteObject(hbmp);	}	DeleteDC(hdc);	hdc = NULL;	if (skinbmps)	{		for (int i=0;i<skinbmps->getNumItems();i++)			skinbmps->enumItem(i)->Release();		delete skinbmps;	}	if (envelope)		envelope->Release();}BltCanvas::BltCanvas(HBITMAP bmp){	prevbmp = NULL;	bits = NULL;	fcoord = TRUE;	ourbmp = FALSE;	skinbmps = NULL;	envelope = NULL;	hbmp = bmp;	ASSERT(hbmp != NULL);	// create tha DC	hdc = CreateCompatibleDC(NULL);	prevbmp = (HBITMAP)SelectObject(hdc, hbmp);}BltCanvas::BltCanvas(){	hbmp = NULL;	prevbmp = NULL;	bits = NULL;	fcoord = TRUE;	ourbmp = FALSE;	bpp = 32; // TODO: benski> pass as parameter?	skinbmps = NULL;	envelope = NULL;	hdc = CreateCompatibleDC(NULL);	}BltCanvas::BltCanvas(int w, int h, HWND wnd, int nb_bpp/*, unsigned char *pal, int palsize*/){	hbmp = NULL;	prevbmp = NULL;	bits = NULL;	fcoord = TRUE;	ourbmp = FALSE;	bpp = nb_bpp;	skinbmps = NULL;	envelope = NULL;	hdc = CreateCompatibleDC(NULL);	AllocBitmap(w,h,nb_bpp);	if (hbmp)	{		// create tha DC				if (!hdc) {//			int x = GetLastError();		}		prevbmp = (HBITMAP)SelectObject(hdc, hbmp);	}}void BltCanvas::AllocBitmap(int w, int h, int nb_bpp){	ASSERT(!hbmp);	ASSERT(w != 0 && h != 0);	if (w == 0) w = 1;	if (h == 0) h = 1;	BITMAPINFO bmi;	MEMZERO(&bmi, sizeof(BITMAPINFO));	//bmi.bmiHeader.biClrUsed = 0; // we memzero above, no need	//bmi.bmiHeader.biClrImportant = 0; // we memzero above, no need	bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);	bmi.bmiHeader.biWidth = ABS(w);	bmi.bmiHeader.biHeight = -ABS(h);	bmi.bmiHeader.biPlanes = 1;	bmi.bmiHeader.biBitCount = nb_bpp;	bmi.bmiHeader.biCompression = BI_RGB;	//bmi.bmiHeader.biSizeImage = 0; // we memzero above, no need	//bmi.bmiHeader.biXPelsPerMeter = 0; // we memzero above, no need	//bmi.bmiHeader.biYPelsPerMeter = 0; // we memzero above, no need	//GdiFlush();	hbmp = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &bits, NULL, 0);		if (hbmp == NULL)	{		return ;	}		ourbmp=TRUE;	GetObject(hbmp, sizeof(BITMAP), &bm);	width = bm.bmWidth;	height = ABS(bm.bmHeight);	pitch = bm.bmWidthBytes;}void *BltCanvas::getBits(){	return bits;}HBITMAP BltCanvas::getBitmap(){	return hbmp;}SkinBitmap *BltCanvas::getSkinBitmap(){	// make a SkinBitmap envelope	if (!envelope)		envelope = new SkinBitmap(getBitmap(), getHDC(), 1, getBits());	// do not delete envelope, it's deleted in destructor	return envelope;}SkinBitmap *BltCanvas::makeSkinBitmap(){	// make a clone of the bitmap - JF> what was that crap about envelopes?	SkinBitmap *clone = new SkinBitmap(getBitmap(), getHDC(), 1);	if (!skinbmps)		skinbmps = new PtrList<SkinBitmap>;	skinbmps->addItem(clone);	return clone;}void BltCanvas::disposeSkinBitmap(SkinBitmap *b){	if (skinbmps->haveItem(b))	{		skinbmps->removeItem(b);		b->Release();	}	else	{		DebugString("disposeSkinBitmap called on unknown pointer, you should call it from the object used to makeSkinBitmap()\n");	}}void BltCanvas::fillBits(COLORREF color){	if (bpp == 32)	{	// clear out the bits		DWORD *dwbits = (DWORD *)bits;		MEMFILL<DWORD>(dwbits, color, bm.bmWidth * bm.bmHeight);	}}void BltCanvas::vflip(int vert_cells){	ASSERT(bits != NULL);	//  BITMAP bm;	//  int r = GetObject(hbmp, sizeof(BITMAP), &bm);	//  if (r == 0) return;	int w = bm.bmWidth, h = bm.bmHeight;	int bytes = 4 * w;	__int8 *tmpbuf = (__int8 *)MALLOC(bytes);	if (tmpbuf)	{		int cell_h = h / vert_cells;		for (int j = 0; j < vert_cells; j++)			for (int i = 0; i < cell_h / 2; i++)			{				char *p1, *p2;				p1 = (__int8 *)bits + bytes * i + (j * cell_h * bytes);				p2 = (__int8 *)bits + bytes * ((cell_h - 1) - i) + (j * cell_h * bytes);				if (p1 == p2) continue;				MEMCPY(tmpbuf, p1, bytes);				MEMCPY(p1, p2, bytes);				MEMCPY(p2, tmpbuf, bytes);			}		FREE(tmpbuf);	}}void BltCanvas::hflip(int hor_cells){	ASSERT(bits != NULL);	// todo: optimize	int w = bm.bmWidth, h = bm.bmHeight;	for (int i = 0;i < hor_cells;i++)		for (int x = 0;x < w / 2 / hor_cells;x++)			for (int y = 0;y < h;y++)			{				int *p = ((int *)bits) + x + y * w + (i * w / hor_cells);				int *d = ((int *)bits) + ((w / hor_cells) - x) + y * w + (i * w / hor_cells) - 1;				int t = *p;				*p = *d;				*d = t;			}}void BltCanvas::maskColor(COLORREF from, COLORREF to){	int n = bm.bmWidth * bm.bmHeight;	//GdiFlush();	DWORD *b = (DWORD *)getBits();	from &= 0xffffff;	while (n--)	{		if ((*b & 0xffffff) == from)		{			*b = to;		}		else *b |= 0xff000000;	// force all other pixels non masked		b++;	}}void BltCanvas::makeAlpha(int newalpha){	int w, h;	getDim(&w, &h, NULL);	premultiply((ARGB32 *)getBits(), w*h, newalpha);}#if 0void BltCanvas::premultiply(ARGB32 *m_pBits, int nwords, int newalpha){	if (newalpha == -1)	{		for (; nwords > 0; nwords--, m_pBits++)		{			unsigned char *pixel = (unsigned char *)m_pBits;			unsigned int alpha = pixel[3];			if (alpha == 255) continue;			pixel[0] = (pixel[0] * alpha) >> 8;	// blue			pixel[1] = (pixel[1] * alpha) >> 8;	// green			pixel[2] = (pixel[2] * alpha) >> 8;	// red		}	}	else	{		for (; nwords > 0; nwords--, m_pBits++)		{			unsigned char *pixel = (unsigned char *)m_pBits;			pixel[0] = (pixel[0] * newalpha) >> 8;	// blue			pixel[1] = (pixel[1] * newalpha) >> 8;	// green			pixel[2] = (pixel[2] * newalpha) >> 8;	// red			pixel[3] = (pixel[3] * newalpha) >> 8;	// alpha		}	}}#endif// benski> this may not be completely safe.  it's meant for skinbitmap::blittorect// it doesn't take into account skin bitmaps, enveloped bitmaps, or any other things like thatvoid BltCanvas::DestructiveResize(int w, int h, int nb_bpp){	if (hdc != NULL) 	{		SelectObject(hdc, prevbmp);		prevbmp=0;	}	if (ourbmp && hbmp)	{			DeleteObject(hbmp);			hbmp=NULL;			ourbmp=FALSE;	}	// create tha DC	if (hdc == NULL)		hdc = CreateCompatibleDC(NULL);	AllocBitmap(w,h,nb_bpp);	prevbmp = (HBITMAP)SelectObject(hdc, hbmp);	if (envelope) envelope->Release();	envelope=0;}
 |