#include "bltcanvas.h" #include 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;igetNumItems();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; 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(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 0 void 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 that void 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; }