home *** CD-ROM | disk | FTP | other *** search
-
- //===========================
- // XBitmap.cpp
- // by SA VanNess
- // 08 Mar 97
- // for the Win32 platform
- //===========================
- // 8-Plane virtual bitmap
- // Class implementation
- //===========================
- // Copyright (C) 1997 SA VanNess
- // <savanness@pipeline.com>
- //
- // For copyright information, see the file gnu_license.txt included
- // with this source code distribution.
- //
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation; either version 2 of the License, or
- // (at your option) any later version.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program; if not, write to the Free Software
- // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- //===========================
-
- #include <afxwin.h>
- #include <afxcmn.h>
- #include <afxres.h>
-
- #include "macros.h"
- #include "xbitmap.h"
-
- //-----------------
- BOOL XBitmap::Create(UINT iWidth, UINT iHeight)
- {
- //Error checking
- if (iWidth <= 0 || iHeight <= 0) return FALSE;
-
- //Init
- m_iWidth = iWidth;
- m_iHeight = iHeight;
- m_iWidth32 = (iWidth/4) + (iWidth%4 > 0);
-
- //Alloc
- m_pBits = (UINT *)calloc((m_iWidth32*m_iHeight),4);
- if (m_pBits == NULL) return FALSE;
-
- return TRUE;
- }
-
- //-----------------
- BOOL XBitmap::Copy(XBitmap &xBmpSrc)
- {
- //Error checking
- if (!m_pBits) return FALSE;
-
- //Create other object, if needed
- if (!xBmpSrc.m_pBits || (m_iWidth != xBmpSrc.m_iWidth) || (m_iHeight != xBmpSrc.m_iHeight))
- if (!xBmpSrc.Create(m_iWidth,m_iHeight)) return FALSE;
-
- //Data copy
- memcpy(m_pBits, xBmpSrc.m_pBits, (4*m_iWidth32*m_iHeight));
-
- return TRUE;
- }
-
- //-----------------
- BOOL XBitmap::Clear()
- {
- //Error checking
- if (!m_pBits) return FALSE;
-
- //Write zeroes
- for(UINT iDWPos=0;iDWPos < (m_iWidth32*m_iHeight);iDWPos++)
- m_pBits[iDWPos] = 0;
-
- return TRUE;
- }
-
- //-----------------
- inline UINT XBitmap::GetPixel(UINT xx, UINT yy)
- {
- //Clipping
- if (xx < 0 || yy < 0 || xx >= m_iWidth || yy >= m_iHeight)
- return 0;
-
- //Position calc
- UINT iDWPos = (yy*m_iWidth32) + (xx>>2);
- UINT iBitPos = (xx&0x0003) << 3;
-
- //Mask out other bytes
- return ((m_pBits[iDWPos] >> iBitPos) & 0x00ff);
- }
-
- //-----------------
- inline BOOL XBitmap::SetPixel(UINT xx, UINT yy, UINT cc, BOOL bVal)
- {
- cc &= 0x00ff;
-
- //Clipping
- if (xx < 0 || yy < 0 || xx >= m_iWidth || yy >= m_iHeight)
- return FALSE;
-
- //Position calc
- UINT iDWPos = (yy*m_iWidth32) + (xx>>2);
- UINT iBitPos = (xx&0x0003) << 3;
- UINT iBitMask = cc << iBitPos;
-
- if (bVal) //mask bit(s) on
- m_pBits[iDWPos] |= iBitMask;
- else //mask bit(s) off
- m_pBits[iDWPos] &= ~iBitMask;
-
- return TRUE;
- }
-
- //-----------------
- void XBitmap::HLine(UINT x0, UINT x1, UINT yy, UINT cc, BOOL bVal)
- {
- UINT i;
- cc &= 0x00ff;
- cc = (cc<<24) | (cc<<16) | (cc<<8) | (cc);
-
- //Normalization
- if (x0 > x1)
- { x0 ^= x1; x1 ^= x0; x0 ^= x1; }
-
- //Clipping
- if (x0 < 0 || yy < 0 || x1 >= m_iWidth || yy >= m_iHeight)
- {
- x0 = MAX(0,x0); x1 = MIN(m_iWidth-1,x1);
- yy = MAX(0,yy); yy = MIN(m_iHeight-1,yy);
- }
-
- //Short line
- if (x1-x0 < 20)
- {
- for(UINT xx=x0;xx <= x1;xx++) SetPixel(xx,yy,cc,bVal);
- return;
- }
-
- //Draw head
- UINT iDWPos0 = (yy*m_iWidth32) + (x0>>2);
- UINT iBitPos = (x0 & 0x0003) << 3;
- UINT iBitMask = (cc) << iBitPos;
- //UINT iBitMaskAND = ~((~cc) << iBitPos);
- if (bVal) //mask bit(s) on
- m_pBits[iDWPos0] |= iBitMask;
- else //mask bit(s) off
- m_pBits[iDWPos0] &= ~iBitMask;
-
- //m_pBits[iDWPos0] |= iBitMaskOR;
- //m_pBits[iDWPos0] &= iBitMaskAND;
-
- //Draw tail
- UINT iDWPos1 = (yy*m_iWidth32) + (x1>>2);
- iBitPos = (3-(x1 & 0x0003L)) << 3;
- iBitMask = (cc) >> iBitPos;
- //iBitMaskAND = ~((~cc) >> iBitPos);
- if (bVal) //mask bit(s) on
- m_pBits[iDWPos1] |= iBitMask;
- else //mask bit(s) off
- m_pBits[iDWPos1] &= ~iBitMask;
-
- //m_pBits[iDWPos1] |= iBitMaskOR;
- //m_pBits[iDWPos1] &= iBitMaskAND;
-
- //Draw body
- for(i = iDWPos0+1;i < (iDWPos1);i++)
- //m_pBits[i] = cc;
- if (bVal) //mask bit(s) on
- m_pBits[i] |= iBitMask;
- else //mask bit(s) off
- m_pBits[i] &= ~iBitMask;
- }
-
- //-----------------
- void XBitmap::VLine(UINT xx, UINT y0, UINT y1, UINT cc, BOOL bVal)
- {
- cc &= 0x00ff;
-
- //Normalization
- if (y0 > y1)
- { y0 ^= y1; y1 ^= y0; y0 ^= y1; }
-
- //Clipping
- if (xx < 0 || y0 < 0 || xx >= m_iWidth || y1 >= m_iHeight)
- {
- xx = MAX(0,xx); xx = MIN(m_iWidth-1,xx);
- y0 = MAX(0,y0); y1 = MIN(m_iHeight-1,y1);
- }
-
- //Draw body
- UINT iDWPos = (y0*m_iWidth32) + (xx>>2);
- UINT iBitPos = (xx&0x0003) << 3;
- UINT iBitMask = (cc) << iBitPos;
-
- for(UINT i=y0;i <= y1;i++,iDWPos+=m_iWidth32)
- if (bVal) //mask bit(s) on
- m_pBits[iDWPos] |= iBitMask;
- else //mask bit(s) off
- m_pBits[iDWPos] &= ~iBitMask;
- }
-
- //-----------------
- void XBitmap::Line(UINT x0, UINT y0, UINT x1, UINT y1, UINT cc, BOOL bVal)
- {
- UINT xx,yy;
- int iSlope,iSlopeDir = 1;
- cc &= 0x00ff;
-
- //Normalization
- if (y0 > y1)
- { iSlopeDir = -iSlopeDir; y0 ^= y1; y1 ^= y0; y0 ^= y1; }
- if (x0 > x1)
- { iSlopeDir = -iSlopeDir; x0 ^= x1; x1 ^= x0; x0 ^= x1; }
-
- //Alignment switch
- if ((x1-x0) < (y1-y0)) //y-based
- {
- //Calc dx/dy
- iSlope = ((x1-x0) << 16)/(MAX(1,(y1-y0)));
-
- //Adjust intercept
- if (iSlopeDir < 0)
- { x0 ^= x1; x1 ^= x0; x0 ^= x1; }
-
- //Draw line
- for(yy=y0;yy <= y1;yy++)
- {
- xx = x0 + iSlopeDir*((iSlope*(yy-y0)) >> 16);
- VLine(xx-1,yy-1,yy+1,cc,bVal);
- VLine(xx,yy-1,yy+1,cc,bVal);
- VLine(xx+1,yy-1,yy+1,cc,bVal);
- }
- }
- else //x-based
- {
- //Calc dy/dx
- iSlope = ((y1-y0) << 16)/(MAX(1,(x1-x0)));
-
- //Adjust intercept
- if (iSlopeDir < 0)
- { y0 ^= y1; y1 ^= y0; y0 ^= y1; }
-
- //Draw line
- for(xx=x0;xx <= x1;xx++)
- {
- yy = y0 + iSlopeDir*((iSlope*(xx-x0)) >> 16);
- VLine(xx-1,yy-1,yy+1,cc,bVal);
- VLine(xx,yy-1,yy+1,cc,bVal);
- VLine(xx+1,yy-1,yy+1,cc,bVal);
- }
- }
- }
-
- //-----------------
- void XBitmap::FillSolidRect(CRect rc, UINT cc, BOOL bVal)
- {
- int x;
- cc &= 0x00ff;
-
- for(x=rc.left;x < rc.right;x++)
- VLine(x,rc.top,rc.bottom-1,cc,bVal);
- return;
- }
-
- //-----------------
- void XBitmap::Wipe(UINT c1, UINT c2)
- {
- c1 &= 0x00ff;
- c2 &= 0x00ff;
- //UINT c1 = ((c1<<24) | (c1<<16) | (c1<<8) | (c1));
- //UINT c2 = ((c2<<24) | (c2<<16) | (c2<<8) | (c2));
-
- for(UINT i=0;i<4;i++)
- {
- for(UINT iDWPos=0;iDWPos < (m_iWidth32*m_iHeight);iDWPos++)
- {
- if (m_pBits[iDWPos]&c1)
- {
- //Mask the c1 bits off and the c2 bits on
- m_pBits[iDWPos] &= ~c1;
- m_pBits[iDWPos] |= c2;
- }
- } //end of iDWPos for-loop
- c1 = c1 << 8;
- c2 = c2 << 8;
- } //end of bitmask-shift for-loop
- }
-
- //-----------------
- void XBitmap::FloodFill(UINT xx, UINT yy, UINT cc)
- {
- UINT x, xl, xr;
- xl = xr = xx;
- cc &= 0x00ff;
-
- while(!(GetPixel(xl,yy)&cc)) xl--;
- while(!(GetPixel(xr,yy)&cc)) xr++;
- HLine(++xl,--xr,yy,cc,TRUE);
-
- for(x = xl;x <= xr;x++)
- {
- if (!(GetPixel(x,yy-1)&cc)) FloodFill(x,yy-1,cc);
- if (!(GetPixel(x,yy+1)&cc)) FloodFill(x,yy+1,cc);
- }
- return;
- }
-
- //-----------------
- BOOL XBitmap::RScan(UINT xx, UINT yy)
- {
- BOOL bRet = FALSE;
- UINT x, xl, xr;
- xl = xr = xx;
-
- while(!GetPixel(xl,yy)) xl--;
- if (GetPixel(xl,yy)&XBC_WHITE) bRet = TRUE;
- while(!GetPixel(xr,yy)) xr++;
- if (GetPixel(xr,yy)&XBC_WHITE) bRet = TRUE;
- xl++; xr--;
- HLine(xl,xr,yy,XBC_GREY,TRUE);
-
- for(x = xl;x <= xr;x++)
- {
- if (!GetPixel(x,yy-1)) if (RScan(x,yy-1)) bRet = TRUE;
- if (!GetPixel(x,yy+1)) if (RScan(x,yy+1)) bRet = TRUE;
- }
- return bRet;
- }
-
- //-----------------
- UINT XBitmap::ExpandTo(CDC &DC)
- {
- UINT x,y,xl;
- UINT cc;
- CPen *pOldPen,gPen1,gPen0;
- UINT nPix = 0;
-
- gPen1.CreatePen(PS_SOLID,1,RGB_BLUEGRN);
- gPen0.CreatePen(PS_SOLID,1,RGB_BLACK);
- pOldPen = DC.SelectObject(&gPen1);
-
- for(y=0; y < m_iHeight; y++)
- {
- x=0;
- DC.MoveTo(x,y);
- do {
- xl = x;
- cc = (GetPixel(x,y)&XBC_BLUEGRN);
- while((GetPixel(++x,y)&XBC_BLUEGRN) == cc && x < m_iWidth);
- if (cc)
- {
- DC.SelectObject(&gPen1);
- nPix += (x-xl);
- }
- else
- DC.SelectObject(&gPen0);
- DC.LineTo(x,y);
- }while(x < m_iWidth);
- }
- DC.SelectObject(pOldPen);
-
- /* Slow-but-certain alternate algorithm
- for(y=0; y < m_iHeight; y++)
- for(x=0; x < m_iWidth; x++)
- {
- cc = (GetPixel(x,y)&XBC_BLUEGRN);
- if (cc) nPix++;
- if (cc) DC.SetPixel(x,y,RGB_BLUEGRN);
- else DC.SetPixel(x,y,RGB_BLACK);
- }*/
-
- return nPix; //number of bluegrn pix detected
- }
-
- //-----------------
- UINT XBitmap::CountFilledPix(UINT iFirstLine, UINT iLastLine)
- {
- UINT x,y;
- UINT iBitPos,iDWPos;
- UINT nPix = 0;
-
- iFirstLine = MAX(iFirstLine,0);
- iLastLine = MIN(iLastLine,m_iHeight);
-
- y = iFirstLine;
- for(x=0; x < m_iWidth; x++)
- {
- iBitPos = (x&0x0003) << 3;
- for(iDWPos=(y*m_iWidth32)+(x>>2); iDWPos < (m_iWidth32*iLastLine); iDWPos+=m_iWidth32)
- if ((m_pBits[iDWPos] >> iBitPos)&XBC_BLUEGRN) nPix++;
- }
-
- return nPix; //number of bluegrn pix detected
- }
-
- //-----------------
- UINT XBitmap::CalcFillFraction(UINT nPix)
- {
- //Convert number of bluegrn pix to FillFraction (1000:100%)
- nPix -= 2*BORDER_THICKNESS*(m_iHeight-BORDER_THICKNESS); //disinclude initial blue boundaries
- nPix -= 2*BORDER_THICKNESS*(m_iWidth-BORDER_THICKNESS);
- if (nPix&0x8000000) nPix = 0; //protect against underflow
- nPix *= 1000; //maintain precision during intdiv
- nPix /= (m_iWidth*m_iHeight); //do the calculation
- nPix += 50; //apply a fudge factor (5%)
-
- return nPix; //fraction of xbitmap filled with bluegrn pix (1000:100%)
- }
-