BltCanvas.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. #include "bltcanvas.h"
  2. #include <tataki/bitmap/bitmap.h>
  3. BltCanvas::~BltCanvas()
  4. {
  5. if (hdc == NULL) return ;
  6. // kill the bitmap and its DC
  7. SelectObject(hdc, prevbmp);
  8. if (ourbmp)
  9. {
  10. //GdiFlush();
  11. DeleteObject(hbmp);
  12. }
  13. DeleteDC(hdc);
  14. hdc = NULL;
  15. if (skinbmps)
  16. {
  17. for (int i=0;i<skinbmps->getNumItems();i++)
  18. skinbmps->enumItem(i)->Release();
  19. delete skinbmps;
  20. }
  21. if (envelope)
  22. envelope->Release();
  23. }
  24. BltCanvas::BltCanvas(HBITMAP bmp)
  25. {
  26. prevbmp = NULL;
  27. bits = NULL;
  28. fcoord = TRUE;
  29. ourbmp = FALSE;
  30. skinbmps = NULL;
  31. envelope = NULL;
  32. hbmp = bmp;
  33. ASSERT(hbmp != NULL);
  34. // create tha DC
  35. hdc = CreateCompatibleDC(NULL);
  36. prevbmp = (HBITMAP)SelectObject(hdc, hbmp);
  37. }
  38. BltCanvas::BltCanvas()
  39. {
  40. hbmp = NULL;
  41. prevbmp = NULL;
  42. bits = NULL;
  43. fcoord = TRUE;
  44. ourbmp = FALSE;
  45. bpp = 32; // TODO: benski> pass as parameter?
  46. skinbmps = NULL;
  47. envelope = NULL;
  48. hdc = CreateCompatibleDC(NULL);
  49. }
  50. BltCanvas::BltCanvas(int w, int h, HWND wnd, int nb_bpp/*, unsigned char *pal, int palsize*/)
  51. {
  52. hbmp = NULL;
  53. prevbmp = NULL;
  54. bits = NULL;
  55. fcoord = TRUE;
  56. ourbmp = FALSE;
  57. bpp = nb_bpp;
  58. skinbmps = NULL;
  59. envelope = NULL;
  60. hdc = CreateCompatibleDC(NULL);
  61. AllocBitmap(w,h,nb_bpp);
  62. if (hbmp)
  63. {
  64. // create tha DC
  65. if (!hdc) {
  66. // int x = GetLastError();
  67. }
  68. prevbmp = (HBITMAP)SelectObject(hdc, hbmp);
  69. }
  70. }
  71. void BltCanvas::AllocBitmap(int w, int h, int nb_bpp)
  72. {
  73. ASSERT(!hbmp);
  74. ASSERT(w != 0 && h != 0);
  75. if (w == 0) w = 1;
  76. if (h == 0) h = 1;
  77. BITMAPINFO bmi;
  78. MEMZERO(&bmi, sizeof(BITMAPINFO));
  79. //bmi.bmiHeader.biClrUsed = 0; // we memzero above, no need
  80. //bmi.bmiHeader.biClrImportant = 0; // we memzero above, no need
  81. bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  82. bmi.bmiHeader.biWidth = ABS(w);
  83. bmi.bmiHeader.biHeight = -ABS(h);
  84. bmi.bmiHeader.biPlanes = 1;
  85. bmi.bmiHeader.biBitCount = nb_bpp;
  86. bmi.bmiHeader.biCompression = BI_RGB;
  87. //bmi.bmiHeader.biSizeImage = 0; // we memzero above, no need
  88. //bmi.bmiHeader.biXPelsPerMeter = 0; // we memzero above, no need
  89. //bmi.bmiHeader.biYPelsPerMeter = 0; // we memzero above, no need
  90. //GdiFlush();
  91. hbmp = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &bits, NULL, 0);
  92. if (hbmp == NULL)
  93. {
  94. return ;
  95. }
  96. ourbmp=TRUE;
  97. GetObject(hbmp, sizeof(BITMAP), &bm);
  98. width = bm.bmWidth;
  99. height = ABS(bm.bmHeight);
  100. pitch = bm.bmWidthBytes;
  101. }
  102. void *BltCanvas::getBits()
  103. {
  104. return bits;
  105. }
  106. HBITMAP BltCanvas::getBitmap()
  107. {
  108. return hbmp;
  109. }
  110. SkinBitmap *BltCanvas::getSkinBitmap()
  111. {
  112. // make a SkinBitmap envelope
  113. if (!envelope)
  114. envelope = new SkinBitmap(getBitmap(), getHDC(), 1, getBits());
  115. // do not delete envelope, it's deleted in destructor
  116. return envelope;
  117. }
  118. SkinBitmap *BltCanvas::makeSkinBitmap()
  119. {
  120. // make a clone of the bitmap - JF> what was that crap about envelopes?
  121. SkinBitmap *clone = new SkinBitmap(getBitmap(), getHDC(), 1);
  122. if (!skinbmps)
  123. skinbmps = new PtrList<SkinBitmap>;
  124. skinbmps->addItem(clone);
  125. return clone;
  126. }
  127. void BltCanvas::disposeSkinBitmap(SkinBitmap *b)
  128. {
  129. if (skinbmps->haveItem(b))
  130. {
  131. skinbmps->removeItem(b);
  132. b->Release();
  133. }
  134. else
  135. {
  136. DebugString("disposeSkinBitmap called on unknown pointer, you should call it from the object used to makeSkinBitmap()\n");
  137. }
  138. }
  139. void BltCanvas::fillBits(COLORREF color)
  140. {
  141. if (bpp == 32)
  142. { // clear out the bits
  143. DWORD *dwbits = (DWORD *)bits;
  144. MEMFILL<DWORD>(dwbits, color, bm.bmWidth * bm.bmHeight);
  145. }
  146. }
  147. void BltCanvas::vflip(int vert_cells)
  148. {
  149. ASSERT(bits != NULL);
  150. // BITMAP bm;
  151. // int r = GetObject(hbmp, sizeof(BITMAP), &bm);
  152. // if (r == 0) return;
  153. int w = bm.bmWidth, h = bm.bmHeight;
  154. int bytes = 4 * w;
  155. __int8 *tmpbuf = (__int8 *)MALLOC(bytes);
  156. if (tmpbuf)
  157. {
  158. int cell_h = h / vert_cells;
  159. for (int j = 0; j < vert_cells; j++)
  160. for (int i = 0; i < cell_h / 2; i++)
  161. {
  162. char *p1, *p2;
  163. p1 = (__int8 *)bits + bytes * i + (j * cell_h * bytes);
  164. p2 = (__int8 *)bits + bytes * ((cell_h - 1) - i) + (j * cell_h * bytes);
  165. if (p1 == p2) continue;
  166. MEMCPY(tmpbuf, p1, bytes);
  167. MEMCPY(p1, p2, bytes);
  168. MEMCPY(p2, tmpbuf, bytes);
  169. }
  170. FREE(tmpbuf);
  171. }
  172. }
  173. void BltCanvas::hflip(int hor_cells)
  174. {
  175. ASSERT(bits != NULL);
  176. // todo: optimize
  177. int w = bm.bmWidth, h = bm.bmHeight;
  178. for (int i = 0;i < hor_cells;i++)
  179. for (int x = 0;x < w / 2 / hor_cells;x++)
  180. for (int y = 0;y < h;y++)
  181. {
  182. int *p = ((int *)bits) + x + y * w + (i * w / hor_cells);
  183. int *d = ((int *)bits) + ((w / hor_cells) - x) + y * w + (i * w / hor_cells) - 1;
  184. int t = *p;
  185. *p = *d;
  186. *d = t;
  187. }
  188. }
  189. void BltCanvas::maskColor(COLORREF from, COLORREF to)
  190. {
  191. int n = bm.bmWidth * bm.bmHeight;
  192. //GdiFlush();
  193. DWORD *b = (DWORD *)getBits();
  194. from &= 0xffffff;
  195. while (n--)
  196. {
  197. if ((*b & 0xffffff) == from)
  198. {
  199. *b = to;
  200. }
  201. else *b |= 0xff000000; // force all other pixels non masked
  202. b++;
  203. }
  204. }
  205. void BltCanvas::makeAlpha(int newalpha)
  206. {
  207. int w, h;
  208. getDim(&w, &h, NULL);
  209. premultiply((ARGB32 *)getBits(), w*h, newalpha);
  210. }
  211. #if 0
  212. void BltCanvas::premultiply(ARGB32 *m_pBits, int nwords, int newalpha)
  213. {
  214. if (newalpha == -1)
  215. {
  216. for (; nwords > 0; nwords--, m_pBits++)
  217. {
  218. unsigned char *pixel = (unsigned char *)m_pBits;
  219. unsigned int alpha = pixel[3];
  220. if (alpha == 255) continue;
  221. pixel[0] = (pixel[0] * alpha) >> 8; // blue
  222. pixel[1] = (pixel[1] * alpha) >> 8; // green
  223. pixel[2] = (pixel[2] * alpha) >> 8; // red
  224. }
  225. }
  226. else
  227. {
  228. for (; nwords > 0; nwords--, m_pBits++)
  229. {
  230. unsigned char *pixel = (unsigned char *)m_pBits;
  231. pixel[0] = (pixel[0] * newalpha) >> 8; // blue
  232. pixel[1] = (pixel[1] * newalpha) >> 8; // green
  233. pixel[2] = (pixel[2] * newalpha) >> 8; // red
  234. pixel[3] = (pixel[3] * newalpha) >> 8; // alpha
  235. }
  236. }
  237. }
  238. #endif
  239. // benski> this may not be completely safe. it's meant for skinbitmap::blittorect
  240. // it doesn't take into account skin bitmaps, enveloped bitmaps, or any other things like that
  241. void BltCanvas::DestructiveResize(int w, int h, int nb_bpp)
  242. {
  243. if (hdc != NULL)
  244. {
  245. SelectObject(hdc, prevbmp);
  246. prevbmp=0;
  247. }
  248. if (ourbmp && hbmp)
  249. {
  250. DeleteObject(hbmp);
  251. hbmp=NULL;
  252. ourbmp=FALSE;
  253. }
  254. // create tha DC
  255. if (hdc == NULL)
  256. hdc = CreateCompatibleDC(NULL);
  257. AllocBitmap(w,h,nb_bpp);
  258. prevbmp = (HBITMAP)SelectObject(hdc, hbmp);
  259. if (envelope) envelope->Release();
  260. envelope=0;
  261. }