home *** CD-ROM | disk | FTP | other *** search
/ Speelhal Klassiekers - Hits des Salles de Jeux / Arcade.bin / games / Xonix32 / SRC / XBITMAP.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-13  |  9.8 KB  |  418 lines

  1.  
  2. //===========================
  3. // XBitmap.cpp
  4. // by SA VanNess
  5. // 08 Mar 97
  6. // for the Win32 platform
  7. //===========================
  8. // 8-Plane virtual bitmap
  9. // Class implementation
  10. //===========================
  11. // Copyright (C) 1997  SA VanNess
  12. // <savanness@pipeline.com>
  13. //
  14. // For copyright information, see the file gnu_license.txt included
  15. // with this source code distribution.
  16. //
  17. // This program is free software; you can redistribute it and/or modify
  18. // it under the terms of the GNU General Public License as published by
  19. // the Free Software Foundation; either version 2 of the License, or
  20. // (at your option) any later version.
  21. //
  22. // This program is distributed in the hope that it will be useful,
  23. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  25. // GNU General Public License for more details.
  26. //
  27. // You should have received a copy of the GNU General Public License
  28. // along with this program; if not, write to the Free Software
  29. // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  30. //===========================
  31.  
  32. #include <afxwin.h>
  33. #include <afxcmn.h>
  34. #include <afxres.h>
  35.  
  36. #include "macros.h"
  37. #include "xbitmap.h"
  38.  
  39. //-----------------
  40. BOOL XBitmap::Create(UINT iWidth, UINT iHeight)
  41. {
  42. //Error checking
  43. if (iWidth <= 0 || iHeight <= 0) return FALSE;
  44.  
  45. //Init
  46. m_iWidth = iWidth;
  47. m_iHeight = iHeight;
  48. m_iWidth32 = (iWidth/4) + (iWidth%4 > 0);
  49.  
  50. //Alloc
  51. m_pBits = (UINT *)calloc((m_iWidth32*m_iHeight),4);
  52. if (m_pBits == NULL) return FALSE;
  53.  
  54. return TRUE;
  55. }
  56.  
  57. //-----------------
  58. BOOL XBitmap::Copy(XBitmap &xBmpSrc)
  59. {
  60. //Error checking
  61. if (!m_pBits) return FALSE;
  62.  
  63. //Create other object, if needed
  64. if (!xBmpSrc.m_pBits || (m_iWidth != xBmpSrc.m_iWidth) || (m_iHeight != xBmpSrc.m_iHeight))
  65. if (!xBmpSrc.Create(m_iWidth,m_iHeight)) return FALSE;
  66.  
  67. //Data copy
  68. memcpy(m_pBits, xBmpSrc.m_pBits, (4*m_iWidth32*m_iHeight));
  69.  
  70. return TRUE;
  71. }
  72.  
  73. //-----------------
  74. BOOL XBitmap::Clear()
  75. {
  76. //Error checking
  77. if (!m_pBits) return FALSE;
  78.  
  79. //Write zeroes
  80. for(UINT iDWPos=0;iDWPos < (m_iWidth32*m_iHeight);iDWPos++)
  81.    m_pBits[iDWPos] = 0;
  82.  
  83. return TRUE;
  84. }
  85.  
  86. //-----------------
  87. inline UINT XBitmap::GetPixel(UINT xx, UINT yy)
  88. {
  89. //Clipping
  90. if (xx < 0 || yy < 0 || xx >= m_iWidth || yy >= m_iHeight)
  91.    return 0;
  92.  
  93. //Position calc
  94. UINT iDWPos = (yy*m_iWidth32) + (xx>>2);
  95. UINT iBitPos = (xx&0x0003) << 3;
  96.  
  97. //Mask out other bytes
  98. return ((m_pBits[iDWPos] >> iBitPos) & 0x00ff);
  99. }
  100.  
  101. //-----------------
  102. inline BOOL XBitmap::SetPixel(UINT xx, UINT yy, UINT cc, BOOL bVal)
  103. {
  104. cc &= 0x00ff;
  105.  
  106. //Clipping
  107. if (xx < 0 || yy < 0 || xx >= m_iWidth || yy >= m_iHeight)
  108.    return FALSE;
  109.  
  110. //Position calc
  111. UINT iDWPos = (yy*m_iWidth32) + (xx>>2);
  112. UINT iBitPos = (xx&0x0003) << 3;
  113. UINT iBitMask = cc << iBitPos;
  114.  
  115. if (bVal) //mask bit(s) on
  116.    m_pBits[iDWPos] |= iBitMask;
  117. else //mask bit(s) off
  118.    m_pBits[iDWPos] &= ~iBitMask;
  119.  
  120. return TRUE;
  121. }
  122.  
  123. //-----------------
  124. void XBitmap::HLine(UINT x0, UINT x1, UINT yy, UINT cc, BOOL bVal)
  125. {
  126. UINT i;
  127. cc &= 0x00ff;
  128. cc = (cc<<24) | (cc<<16) | (cc<<8) | (cc);
  129.  
  130. //Normalization
  131. if (x0 > x1)
  132.    { x0 ^= x1; x1 ^= x0; x0 ^= x1; }
  133.  
  134. //Clipping
  135. if (x0 < 0 || yy < 0 || x1 >= m_iWidth || yy >= m_iHeight)
  136.    {
  137.    x0 = MAX(0,x0); x1 = MIN(m_iWidth-1,x1);
  138.    yy = MAX(0,yy); yy = MIN(m_iHeight-1,yy);
  139.    }
  140.  
  141. //Short line
  142. if (x1-x0 < 20)
  143.    {
  144.    for(UINT xx=x0;xx <= x1;xx++) SetPixel(xx,yy,cc,bVal);
  145.    return;
  146.    }
  147.  
  148. //Draw head
  149. UINT iDWPos0 = (yy*m_iWidth32) + (x0>>2);
  150. UINT iBitPos = (x0 & 0x0003) << 3;
  151. UINT iBitMask = (cc) << iBitPos;
  152. //UINT iBitMaskAND = ~((~cc) << iBitPos);
  153. if (bVal) //mask bit(s) on
  154.    m_pBits[iDWPos0] |= iBitMask;
  155. else //mask bit(s) off
  156.    m_pBits[iDWPos0] &= ~iBitMask;
  157.  
  158. //m_pBits[iDWPos0] |= iBitMaskOR;
  159. //m_pBits[iDWPos0] &= iBitMaskAND;
  160.  
  161. //Draw tail
  162. UINT iDWPos1 = (yy*m_iWidth32) + (x1>>2);
  163. iBitPos = (3-(x1 & 0x0003L)) << 3;
  164. iBitMask = (cc) >> iBitPos;
  165. //iBitMaskAND = ~((~cc) >> iBitPos);
  166. if (bVal) //mask bit(s) on
  167.    m_pBits[iDWPos1] |= iBitMask;
  168. else //mask bit(s) off
  169.    m_pBits[iDWPos1] &= ~iBitMask;
  170.  
  171. //m_pBits[iDWPos1] |= iBitMaskOR;
  172. //m_pBits[iDWPos1] &= iBitMaskAND;
  173.  
  174. //Draw body
  175. for(i = iDWPos0+1;i < (iDWPos1);i++)
  176.    //m_pBits[i] = cc;
  177.    if (bVal) //mask bit(s) on
  178.       m_pBits[i] |= iBitMask;
  179.    else //mask bit(s) off
  180.       m_pBits[i] &= ~iBitMask;
  181. }
  182.  
  183. //-----------------
  184. void XBitmap::VLine(UINT xx, UINT y0, UINT y1, UINT cc, BOOL bVal)
  185. {
  186. cc &= 0x00ff;
  187.  
  188. //Normalization
  189. if (y0 > y1)
  190.    { y0 ^= y1; y1 ^= y0; y0 ^= y1; }
  191.  
  192. //Clipping
  193. if (xx < 0 || y0 < 0 || xx >= m_iWidth || y1 >= m_iHeight)
  194.    {
  195.    xx = MAX(0,xx); xx = MIN(m_iWidth-1,xx);
  196.    y0 = MAX(0,y0); y1 = MIN(m_iHeight-1,y1);
  197.    }
  198.  
  199. //Draw body
  200. UINT iDWPos = (y0*m_iWidth32) + (xx>>2);
  201. UINT iBitPos = (xx&0x0003) << 3;
  202. UINT iBitMask = (cc) << iBitPos;
  203.  
  204. for(UINT i=y0;i <= y1;i++,iDWPos+=m_iWidth32)
  205.    if (bVal) //mask bit(s) on
  206.       m_pBits[iDWPos] |= iBitMask;
  207.    else //mask bit(s) off
  208.       m_pBits[iDWPos] &= ~iBitMask;
  209. }
  210.  
  211. //-----------------
  212. void XBitmap::Line(UINT x0, UINT y0, UINT x1, UINT y1, UINT cc, BOOL bVal)
  213. {
  214. UINT xx,yy;
  215. int iSlope,iSlopeDir = 1;
  216. cc &= 0x00ff;
  217.  
  218. //Normalization
  219. if (y0 > y1)
  220.    { iSlopeDir = -iSlopeDir; y0 ^= y1; y1 ^= y0; y0 ^= y1; }
  221. if (x0 > x1)
  222.    { iSlopeDir = -iSlopeDir; x0 ^= x1; x1 ^= x0; x0 ^= x1; }
  223.  
  224. //Alignment switch
  225. if ((x1-x0) < (y1-y0)) //y-based
  226.    {
  227.    //Calc dx/dy
  228.    iSlope = ((x1-x0) << 16)/(MAX(1,(y1-y0)));
  229.  
  230.    //Adjust intercept
  231.    if (iSlopeDir < 0)
  232.       { x0 ^= x1; x1 ^= x0; x0 ^= x1; }
  233.    
  234.    //Draw line
  235.    for(yy=y0;yy <= y1;yy++)
  236.       {
  237.       xx = x0 + iSlopeDir*((iSlope*(yy-y0)) >> 16);
  238.       VLine(xx-1,yy-1,yy+1,cc,bVal);
  239.       VLine(xx,yy-1,yy+1,cc,bVal);
  240.       VLine(xx+1,yy-1,yy+1,cc,bVal);
  241.       }
  242.    }
  243. else //x-based
  244.    {
  245.    //Calc dy/dx
  246.    iSlope = ((y1-y0) << 16)/(MAX(1,(x1-x0)));
  247.    
  248.    //Adjust intercept
  249.    if (iSlopeDir < 0)
  250.       { y0 ^= y1; y1 ^= y0; y0 ^= y1; }
  251.    
  252.    //Draw line
  253.    for(xx=x0;xx <= x1;xx++)
  254.       {
  255.       yy = y0 + iSlopeDir*((iSlope*(xx-x0)) >> 16);
  256.       VLine(xx-1,yy-1,yy+1,cc,bVal);
  257.       VLine(xx,yy-1,yy+1,cc,bVal);
  258.       VLine(xx+1,yy-1,yy+1,cc,bVal);
  259.       }
  260.    }
  261. }
  262.  
  263. //-----------------
  264. void XBitmap::FillSolidRect(CRect rc, UINT cc, BOOL bVal)
  265. {
  266. int x;
  267. cc &= 0x00ff;
  268.  
  269. for(x=rc.left;x < rc.right;x++)
  270.    VLine(x,rc.top,rc.bottom-1,cc,bVal);
  271. return;
  272. }
  273.  
  274. //-----------------
  275. void XBitmap::Wipe(UINT c1, UINT c2)
  276. {
  277. c1 &= 0x00ff;
  278. c2 &= 0x00ff;
  279. //UINT c1 = ((c1<<24) | (c1<<16) | (c1<<8) | (c1));
  280. //UINT c2 = ((c2<<24) | (c2<<16) | (c2<<8) | (c2));
  281.  
  282. for(UINT i=0;i<4;i++)
  283.    {
  284.    for(UINT iDWPos=0;iDWPos < (m_iWidth32*m_iHeight);iDWPos++)
  285.       {
  286.       if (m_pBits[iDWPos]&c1)
  287.          {
  288.          //Mask the c1 bits off and the c2 bits on
  289.          m_pBits[iDWPos] &= ~c1;
  290.          m_pBits[iDWPos] |= c2;
  291.          }
  292.       } //end of iDWPos for-loop
  293.    c1 = c1 << 8;
  294.    c2 = c2 << 8;
  295.    } //end of bitmask-shift for-loop
  296. }
  297.  
  298. //-----------------
  299. void XBitmap::FloodFill(UINT xx, UINT yy, UINT cc)
  300. {
  301. UINT x, xl, xr;
  302. xl = xr = xx;
  303. cc &= 0x00ff;
  304.  
  305. while(!(GetPixel(xl,yy)&cc)) xl--;
  306. while(!(GetPixel(xr,yy)&cc)) xr++;
  307. HLine(++xl,--xr,yy,cc,TRUE);
  308.  
  309. for(x = xl;x <= xr;x++)
  310.    {
  311.    if (!(GetPixel(x,yy-1)&cc)) FloodFill(x,yy-1,cc);
  312.    if (!(GetPixel(x,yy+1)&cc)) FloodFill(x,yy+1,cc);
  313.    }
  314. return;
  315. }
  316.  
  317. //-----------------
  318. BOOL XBitmap::RScan(UINT xx, UINT yy)
  319. {
  320. BOOL bRet = FALSE;
  321. UINT x, xl, xr;
  322. xl = xr = xx;
  323.  
  324. while(!GetPixel(xl,yy)) xl--;
  325. if (GetPixel(xl,yy)&XBC_WHITE) bRet = TRUE;
  326. while(!GetPixel(xr,yy)) xr++;
  327. if (GetPixel(xr,yy)&XBC_WHITE) bRet = TRUE;
  328. xl++; xr--;
  329. HLine(xl,xr,yy,XBC_GREY,TRUE);
  330.  
  331. for(x = xl;x <= xr;x++)
  332.    {
  333.    if (!GetPixel(x,yy-1)) if (RScan(x,yy-1)) bRet = TRUE;
  334.    if (!GetPixel(x,yy+1)) if (RScan(x,yy+1)) bRet = TRUE;
  335.    }
  336. return bRet;
  337. }
  338.  
  339. //-----------------
  340. UINT XBitmap::ExpandTo(CDC &DC)
  341. {
  342. UINT x,y,xl;
  343. UINT cc;
  344. CPen *pOldPen,gPen1,gPen0;
  345. UINT nPix = 0;
  346.  
  347. gPen1.CreatePen(PS_SOLID,1,RGB_BLUEGRN);
  348. gPen0.CreatePen(PS_SOLID,1,RGB_BLACK);
  349. pOldPen = DC.SelectObject(&gPen1);
  350.  
  351. for(y=0; y < m_iHeight; y++)
  352.    {
  353.    x=0;
  354.    DC.MoveTo(x,y);
  355.    do {
  356.       xl = x;
  357.       cc = (GetPixel(x,y)&XBC_BLUEGRN);
  358.       while((GetPixel(++x,y)&XBC_BLUEGRN) == cc && x < m_iWidth);
  359.       if (cc)
  360.          {
  361.          DC.SelectObject(&gPen1);
  362.          nPix += (x-xl);
  363.          }
  364.       else
  365.          DC.SelectObject(&gPen0);
  366.       DC.LineTo(x,y);
  367.       }while(x < m_iWidth);
  368.    }
  369. DC.SelectObject(pOldPen);
  370.  
  371. /* Slow-but-certain alternate algorithm
  372. for(y=0; y < m_iHeight; y++)
  373. for(x=0; x < m_iWidth; x++)
  374.    {
  375.    cc = (GetPixel(x,y)&XBC_BLUEGRN);
  376.    if (cc) nPix++;
  377.    if (cc) DC.SetPixel(x,y,RGB_BLUEGRN);
  378.    else DC.SetPixel(x,y,RGB_BLACK);
  379.    }*/
  380.  
  381. return nPix; //number of bluegrn pix detected
  382. }
  383.  
  384. //-----------------
  385. UINT XBitmap::CountFilledPix(UINT iFirstLine, UINT iLastLine)
  386. {
  387. UINT x,y;
  388. UINT iBitPos,iDWPos;
  389. UINT nPix = 0;
  390.  
  391. iFirstLine = MAX(iFirstLine,0);
  392. iLastLine = MIN(iLastLine,m_iHeight);
  393.  
  394. y = iFirstLine;
  395. for(x=0; x < m_iWidth; x++)
  396.    {
  397.    iBitPos = (x&0x0003) << 3;
  398.    for(iDWPos=(y*m_iWidth32)+(x>>2); iDWPos < (m_iWidth32*iLastLine); iDWPos+=m_iWidth32)
  399.       if ((m_pBits[iDWPos] >> iBitPos)&XBC_BLUEGRN) nPix++;
  400.    }
  401.  
  402. return nPix; //number of bluegrn pix detected
  403. }
  404.  
  405. //-----------------
  406. UINT XBitmap::CalcFillFraction(UINT nPix)
  407. {
  408. //Convert number of bluegrn pix to FillFraction (1000:100%)
  409. nPix -= 2*BORDER_THICKNESS*(m_iHeight-BORDER_THICKNESS); //disinclude initial blue boundaries
  410. nPix -= 2*BORDER_THICKNESS*(m_iWidth-BORDER_THICKNESS);
  411. if (nPix&0x8000000) nPix = 0; //protect against underflow
  412. nPix *= 1000; //maintain precision during intdiv
  413. nPix /= (m_iWidth*m_iHeight); //do the calculation
  414. nPix += 50; //apply a fudge factor (5%)
  415.  
  416. return nPix; //fraction of xbitmap filled with bluegrn pix (1000:100%)
  417. }
  418.