www.pudn.com > mmxswarm.zip > Surface.cpp
// Surface.cpp : implementation of the CSurface class
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
//
#include "stdafx.h"
#include "Surface.h"
void CSurface::Create(CWnd *pWnd, int nBitDepth)
{
// no palettes
ASSERT(nBitDepth == 24 || nBitDepth == 16 || nBitDepth == 32);
CRect clientRect;
pWnd->GetClientRect(clientRect);
int height = clientRect.Height();
int width = clientRect.Width();
if (!height || !width)
return;
Destroy();
m_nBitDepth = nBitDepth;
m_nByteDepth = nBitDepth/8;
m_wndHeight = height;
m_wndWidth = width;
m_hDestDC = ::GetDC(pWnd->GetSafeHwnd());
m_pSrcWnd = pWnd;
ASSERT(m_hDestDC);
width = m_wndWidth + m_kDeltaX; // not *2 because we don't need it on the left side.
// Allow derived classes a shot at updating if they need more alignment
AdjustWidth(&width);
// pass Negative Height to make it Top Down.
VERIFY(m_image.Create(width, -(m_wndHeight + m_kDeltaY*2), m_nBitDepth, 0));
ASSERT((DWORD_PTR(m_image.GetBits()) & 0xf) == 0); // make sure we are at least 128 bit aligned.(SSE2)
ASSERT(m_image.GetPitch() > 0); // Verify top down DIB
VERIFY(m_image.GetDC() != NULL); // Prefer the DC to exist for life of object
OnCreated();
}
void CSurface::Destroy()
{
if (IsNull())
return;
m_image.ReleaseDC();
m_image.Destroy();
::ReleaseDC(m_pSrcWnd->GetSafeHwnd(), m_hDestDC);
m_wndHeight = 0;
m_wndWidth = 0;
}
void CSurface::Import(const CImage &image)
{
image.BitBlt(m_image.GetDC(), 0, m_kDeltaY,
GetVisibleWidth(), GetVisibleHeight(), 0, 0);
m_image.ReleaseDC();
BlitBits();
}
void CSurface::ClearBits()
{
int size = m_image.GetPitch() * m_image.GetHeight();
memset(m_image.GetBits(), 0x00, size);
}
void CSurface::StripeBits()
{
int count = 0x880000;
for (int i = 0; i < m_wndHeight; i++) {
COLORREF color = count++; // RAND();
for (int j = 0; j < m_wndWidth; j++) {
PointColor(j, i, color);
}
}
}
void CSurface::RandomBits()
{
for (int i = 0; i < m_wndHeight; i++) {
for (int j = 0; j < m_wndWidth; j++) {
PointColor(j, i, RGB(Random(), Random(), Random()));
}
}
}
void CSurface::ShiftBits()
{
BYTE *pBits = (BYTE*)m_image.GetBits();
int nPitch = GetPitch();
for (int i = 0; i < m_wndHeight; i++) {
memcpy_s(pBits, nPitch, pBits+nPitch, nPitch);
pBits += nPitch;
}
}
void CSurface::BlurBits()
{
COLORREF cLeft = 0, cCur = PointColor(0,0), cRight, cUp, cDown;
BYTE r, g, b;
for (int i = 0; i < m_wndHeight; i++) {
cLeft = 0;
for (int j = 0; j < m_wndWidth; j++) {
cRight = PointColor(j+1, i);
cUp = PointColor(j, i-1);
cDown = PointColor(j, i+1);
r = (BYTE)(((int)(GetRValue(cCur) << 2) + GetRValue(cLeft) + GetRValue(cRight) + GetRValue(cUp) + GetRValue(cDown)) >> 3);
g = (BYTE)(((int)(GetGValue(cCur) << 2) + GetGValue(cLeft) + GetGValue(cRight) + GetGValue(cUp) + GetGValue(cDown)) >> 3);
b = (BYTE)(((int)(GetBValue(cCur) << 2) + GetBValue(cLeft) + GetBValue(cRight) + GetBValue(cUp) + GetBValue(cDown)) >> 3);
PointColor(j, i, RGB(b,g,r)); // RGBs are physically inverted
cLeft = cCur;
cCur = cRight;
}
}
}
// nothing beats good old fashioned Bresenham
void CSurface::Line(const CPoint &p1, const CPoint &p2, COLORREF c)
{
int x1 = p1.x;
int x2 = p2.x;
int y1 = p1.y;
int y2 = p2.y;
int d, deltax, deltay, numpixels,
dinc1, dinc2,
xinc1, xinc2,
yinc1, yinc2;
// Calculate deltax and deltay for startup
deltax = ABS(x2 - x1);
deltay = ABS(y2 - y1);
// Initialize all vars based on which is the independent variable
if (deltax >= deltay) {
// x is independent variable
numpixels = deltax + 1;
dinc1 = deltay << 1;
dinc2 = (deltay - deltax) << 1;
d = dinc1 - deltax;
xinc1 = xinc2 = yinc2 = 1;
yinc1 = 0;
}
else {
// y is independent variable
numpixels = deltay + 1;
dinc1 = deltax << 1;
dinc2 = (deltax - deltay) << 1;
d = dinc1 - deltay;
xinc1 = 0;
xinc2 = yinc1 = yinc2 = 1;
}
// Make sure x and y move in the right directions
if (x1 > x2) {
xinc1 = -xinc1;
xinc2 = -xinc2;
}
if (y1 > y2) {
yinc1 = -yinc1;
yinc2 = -yinc2;
}
// Start drawing pixels at [x1, y1]
for (int i = numpixels; i > 0; i--) {
PointColor(x1, y1, c);
if (d < 0) {
d += dinc1;
x1 += xinc1;
y1 += yinc1;
}
else {
d += dinc2;
x1 += xinc2;
y1 += yinc2;
}
}
}
void CSurface::RandomLine(COLORREF c)
{
CPoint p1(Random(m_wndWidth), Random(m_wndHeight));
CPoint p2(Random(m_wndWidth), Random(m_wndHeight));
Line(p1, p2, c);
}
void CSurface::BlitBits()
{
ASSERT(m_wndHeight && m_wndWidth);
BOOL bStat = m_image.BitBlt(m_hDestDC, 0, 0,
m_wndWidth, m_wndHeight, 0, m_kDeltaY);
ASSERT(bStat);
}