437 lines
10 KiB
C++
437 lines
10 KiB
C++
#include <common/math.hpp>
|
|
#include <common/purehdc.hpp>
|
|
#include <common/window.hpp>
|
|
#include <common/brush.hpp>
|
|
|
|
PureDevice::PureDevice(const Window &someWindow)
|
|
: mhDC(0), mhParent((HWND)someWindow), mDisposition(ReleaseDC), mGDIObjPrev(0), mPrevDrawMode(INVALIDROP)
|
|
{
|
|
if(!mhParent||!::IsWindow(mhParent))return;
|
|
mhDC=::GetDC(mhParent);
|
|
}
|
|
|
|
PureDevice::~PureDevice()
|
|
{
|
|
unselect();
|
|
destroyDevice();
|
|
}
|
|
|
|
WORD PureDevice::isOkay(void)const
|
|
{
|
|
switch(mDisposition)
|
|
{
|
|
case DeleteDC :
|
|
case AssumedDC :
|
|
return (mhDC?TRUE:FALSE);
|
|
case ReleaseDC :
|
|
return (mhDC&&(mhParent?::IsWindow(mhParent):TRUE));
|
|
case InvalidDC :
|
|
default :
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
void PureDevice::destroyDevice(void)
|
|
{
|
|
if(mhDC)
|
|
{
|
|
setDrawMode(INVALIDROP);
|
|
if(DeleteDC==mDisposition&&isOkay())::DeleteDC(mhDC);
|
|
else if(ReleaseDC==mDisposition&&isOkay())::ReleaseDC(mhParent,mhDC);
|
|
mhDC=0;
|
|
mhParent=0;
|
|
mDisposition=InvalidDC;
|
|
}
|
|
}
|
|
|
|
WORD PureDevice::select(const GDIObj someGDIObj,WORD selState)
|
|
{
|
|
if(!isOkay()||!someGDIObj)return FALSE;
|
|
if(selState)
|
|
{
|
|
if(mGDIObjPrev)::SelectObject(mhDC,mGDIObjPrev);
|
|
mGDIObjPrev=::SelectObject(mhDC,someGDIObj);
|
|
return TRUE;
|
|
}
|
|
if(!mGDIObjPrev)return FALSE;
|
|
::SelectObject(mhDC,mGDIObjPrev);
|
|
mGDIObjPrev=0;
|
|
return TRUE;
|
|
}
|
|
|
|
WORD PureDevice::compatibleDevice(const PureDevice &somePureDevice)
|
|
{
|
|
if(!somePureDevice.isOkay())return FALSE;
|
|
destroyDevice();
|
|
mhDC=::CreateCompatibleDC((HDC)somePureDevice);
|
|
mDisposition=DeleteDC;
|
|
return isOkay();
|
|
}
|
|
|
|
WORD PureDevice::compatibleDevice(void)
|
|
{
|
|
destroyDevice();
|
|
mhDC=::CreateCompatibleDC(0);
|
|
mDisposition=DeleteDC;
|
|
return isOkay();
|
|
}
|
|
|
|
WORD PureDevice::displayDevice(void)
|
|
{
|
|
destroyDevice();
|
|
mhDC=::CreateDC("DISPLAY",0,0,0);
|
|
mDisposition=DeleteDC;
|
|
return isOkay();
|
|
}
|
|
|
|
WORD PureDevice::screenDevice(void)
|
|
{
|
|
destroyDevice();
|
|
mhDC=::GetDC(0);
|
|
mDisposition=ReleaseDC;
|
|
return isOkay();
|
|
}
|
|
|
|
WORD PureDevice::roundRectangle(const Point ¢erPoint,int radius)
|
|
{
|
|
if(!isOkay())return false;
|
|
Point upperLeft;
|
|
Point lowerRight;
|
|
int diameter;
|
|
|
|
diameter=radius*2;
|
|
upperLeft.x(centerPoint.x()-radius);
|
|
upperLeft.y(centerPoint.y()-radius);
|
|
lowerRight.x(centerPoint.x()+radius);
|
|
lowerRight.y(centerPoint.y()+radius);
|
|
return roundRectangle(upperLeft,lowerRight,diameter,diameter);
|
|
}
|
|
|
|
WORD PureDevice::floodFill(const Point &xyPoint,const RGBColor &fillColor,const RGBColor &boundaryColor)const
|
|
{
|
|
HBRUSH hFillBrush(::CreateSolidBrush(fillColor));
|
|
HBRUSH hPrevBrush((HBRUSH)::SelectObject(mhDC,hFillBrush));
|
|
WORD returnCode;
|
|
|
|
returnCode=::FloodFill(mhDC,xyPoint.x(),xyPoint.y(),boundaryColor);
|
|
::SelectObject(mhDC,hPrevBrush);
|
|
::DeleteObject(hFillBrush);
|
|
return returnCode;
|
|
}
|
|
|
|
BOOL PureDevice::fillRect(const Rect &rect,Brush &brush)
|
|
{
|
|
if(!isOkay())return FALSE;
|
|
return ::FillRect(mhDC,(RECT*)((Rect&)rect),(HBRUSH)(GDIObj)brush);
|
|
}
|
|
|
|
WORD PureDevice::colorRect(const Rect &rect,const RGBColor &lineColor)const
|
|
{
|
|
if(!isOkay())return FALSE;
|
|
for(short index=rect.left();index<=rect.right();index++)
|
|
line(Point(index,rect.bottom()),Point(index,rect.top()),lineColor);
|
|
return TRUE;
|
|
}
|
|
|
|
WORD PureDevice::circle(Window &displayWindow,const Point &xyPoint,WORD radius,const RGBColor &someRGBColor)const
|
|
{
|
|
return circle(aspectValue(displayWindow),xyPoint,radius,someRGBColor);
|
|
}
|
|
|
|
WORD PureDevice::outlineRect(const Rect &rect,const Pen &pen)
|
|
{
|
|
Point p1;
|
|
Point p2;
|
|
|
|
if(!isOkay())return FALSE;
|
|
p1.x(rect.left());
|
|
p1.y(rect.top());
|
|
p2.x(rect.right());
|
|
p2.y(rect.top());
|
|
line(p1,p2,pen);
|
|
|
|
p1.x(rect.right());
|
|
p1.y(rect.top());
|
|
p2.x(rect.right());
|
|
p2.y(rect.bottom());
|
|
line(p1,p2,pen);
|
|
|
|
p1.x(rect.right());
|
|
p1.y(rect.bottom());
|
|
p2.x(rect.left());
|
|
p2.y(rect.bottom());
|
|
line(p1,p2,pen);
|
|
|
|
p1.x(rect.left());
|
|
p1.y(rect.bottom());
|
|
p2.x(rect.left());
|
|
p2.y(rect.top());
|
|
line(p1,p2,pen);
|
|
return TRUE;
|
|
}
|
|
|
|
WORD PureDevice::line(const Point &firstPoint,const Point &secondPoint,const Pen &somePen)const
|
|
{
|
|
if(!isOkay())return FALSE;
|
|
HPEN hPrevPen((HPEN)::SelectObject(mhDC,(HPEN)somePen));
|
|
lineDraw(firstPoint,secondPoint);
|
|
::SelectObject(mhDC,hPrevPen);
|
|
return TRUE;
|
|
}
|
|
|
|
WORD PureDevice::line(const Point &firstPoint,const Point &secondPoint)const
|
|
{
|
|
if(!isOkay())return FALSE;
|
|
lineDraw(firstPoint,secondPoint);
|
|
return TRUE;
|
|
}
|
|
|
|
WORD PureDevice::crossHair(const Point &midPoint,WORD sectionLength,const Pen &somePen)
|
|
{
|
|
Point leftPoint(midPoint);
|
|
Point topPoint(midPoint);
|
|
Point rightPoint(midPoint);
|
|
Point bottomPoint(midPoint);
|
|
HPEN hPrevPen;
|
|
|
|
if(!isOkay())return FALSE;
|
|
hPrevPen=(HPEN)::SelectObject(mhDC,(HPEN)somePen);
|
|
leftPoint.x(leftPoint.x()-sectionLength);
|
|
rightPoint.x(rightPoint.x()+sectionLength);
|
|
topPoint.y(topPoint.y()-sectionLength);
|
|
bottomPoint.y(bottomPoint.y()+sectionLength);
|
|
lineDraw(leftPoint,rightPoint);
|
|
lineDraw(topPoint,bottomPoint);
|
|
::SelectObject(mhDC,hPrevPen);
|
|
return TRUE;
|
|
}
|
|
|
|
WORD PureDevice::crossHairs(Array<Point> &midPoints,WORD sectionLength,const Pen &somePen)
|
|
{
|
|
WORD itemCount;
|
|
Point leftPoint;
|
|
Point topPoint;
|
|
Point rightPoint;
|
|
Point bottomPoint;
|
|
HPEN hPrevPen;
|
|
|
|
if(!isOkay()||!(itemCount=midPoints.size()))return FALSE;
|
|
hPrevPen=(HPEN)::SelectObject(mhDC,(HPEN)somePen);
|
|
for(short itemIndex=0;itemIndex<itemCount;itemIndex++)
|
|
{
|
|
leftPoint=midPoints[itemIndex];
|
|
topPoint=leftPoint;
|
|
rightPoint=leftPoint;
|
|
bottomPoint=leftPoint;
|
|
leftPoint.x(leftPoint.x()-sectionLength);
|
|
rightPoint.x(rightPoint.x()+sectionLength);
|
|
topPoint.y(topPoint.y()-sectionLength);
|
|
bottomPoint.y(bottomPoint.y()+sectionLength);
|
|
lineDraw(leftPoint,rightPoint);
|
|
lineDraw(topPoint,bottomPoint);
|
|
}
|
|
::SelectObject(mhDC,hPrevPen);
|
|
return TRUE;
|
|
}
|
|
|
|
WORD PureDevice::crossHairs(Array<Point> &midPoints,WORD sectionLength,RGBColor rgbColor)
|
|
{
|
|
WORD itemCount;
|
|
Point leftPoint;
|
|
Point topPoint;
|
|
Point rightPoint;
|
|
Point bottomPoint;
|
|
|
|
if(!isOkay()||!(itemCount=midPoints.size()))return FALSE;
|
|
for(short itemIndex=0;itemIndex<itemCount;itemIndex++)
|
|
{
|
|
leftPoint=midPoints[itemIndex];
|
|
topPoint=leftPoint;
|
|
rightPoint=leftPoint;
|
|
bottomPoint=leftPoint;
|
|
leftPoint.x(leftPoint.x()-sectionLength);
|
|
rightPoint.x(rightPoint.x()+sectionLength);
|
|
topPoint.y(topPoint.y()-sectionLength);
|
|
bottomPoint.y(bottomPoint.y()+sectionLength);
|
|
line(leftPoint,rightPoint,rgbColor);
|
|
line(topPoint,bottomPoint,rgbColor);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
WORD PureDevice::circle(WORD aspectValue,const Point &xyPoint,WORD radius,const RGBColor &someRGBColor)const
|
|
{
|
|
int a(radius);
|
|
int af;
|
|
int bf;
|
|
int b(0);
|
|
int target(1);
|
|
int radiusSquared(radius*radius);
|
|
|
|
if(!isOkay())return FALSE;
|
|
while(a>=b)
|
|
{
|
|
b=(int)(Math::sqrt(radiusSquared-(a*a))+.50);
|
|
int temp(target);
|
|
target=b;
|
|
b=temp;
|
|
while(b<target)
|
|
{
|
|
if(100.00!=aspectValue)af=(aspectValue*a)/100.00,bf=(aspectValue*b)/100.00;
|
|
else af=a,bf=b;
|
|
setPixel(Point(xyPoint.x()+af,xyPoint.y()+b),someRGBColor);
|
|
setPixel(Point(xyPoint.x()+bf,xyPoint.y()+a),someRGBColor);
|
|
setPixel(Point(xyPoint.x()-af,xyPoint.y()+b),someRGBColor);
|
|
setPixel(Point(xyPoint.x()-bf,xyPoint.y()+a),someRGBColor);
|
|
setPixel(Point(xyPoint.x()-af,xyPoint.y()-b),someRGBColor);
|
|
setPixel(Point(xyPoint.x()-bf,xyPoint.y()-a),someRGBColor);
|
|
setPixel(Point(xyPoint.x()+af,xyPoint.y()-b),someRGBColor);
|
|
setPixel(Point(xyPoint.x()+bf,xyPoint.y()-a),someRGBColor);
|
|
++b;
|
|
}
|
|
--a;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
PureDevice &PureDevice::operator=(const PureDevice &somePureDevice)
|
|
{
|
|
if(!somePureDevice.isOkay())return *this;
|
|
destroyDevice();
|
|
mDisposition=AssumedDC;
|
|
mhDC=(HDC)somePureDevice;
|
|
return *this;
|
|
}
|
|
|
|
PureDevice &PureDevice::operator=(const Window &someWindow)
|
|
{
|
|
return *this=(HWND)someWindow;
|
|
}
|
|
|
|
PureDevice &PureDevice::operator=(HWND hWnd)
|
|
{
|
|
if(!hWnd)return *this;
|
|
destroyDevice();
|
|
mhParent=hWnd;
|
|
mhDC=::GetDC(mhParent);
|
|
mDisposition=ReleaseDC;
|
|
return *this;
|
|
}
|
|
|
|
WORD PureDevice::horizontalResolution(void)const
|
|
{
|
|
if(!isOkay())return FALSE;
|
|
return ::GetDeviceCaps(mhDC,HORZRES);
|
|
}
|
|
|
|
WORD PureDevice::verticalResolution(void)const
|
|
{
|
|
if(!isOkay())return FALSE;
|
|
return ::GetDeviceCaps(mhDC,VERTRES);
|
|
}
|
|
|
|
WORD PureDevice::aspectValue(const Window &someWindow)const
|
|
{
|
|
if(!isOkay())return FALSE;
|
|
return (((1.00/((float)horizontalResolution()/(float)verticalResolution()))*((float)someWindow.width()/(float)someWindow.height()))*100);
|
|
}
|
|
|
|
WORD PureDevice::square(const Point ¢erPoint,WORD lineLength,RGBColor rgbColor)
|
|
{
|
|
WORD halfLength(lineLength>>0x01);
|
|
Point topLeft;
|
|
Point topRight;
|
|
Point bottomLeft;
|
|
Point bottomRight;
|
|
|
|
if(!isOkay())return FALSE;
|
|
topLeft.x(centerPoint.x()-halfLength);
|
|
topLeft.y(centerPoint.y()-halfLength);
|
|
topRight.x(centerPoint.x()+halfLength);
|
|
topRight.y(centerPoint.y()-halfLength);
|
|
bottomRight.x(centerPoint.x()+halfLength);
|
|
bottomRight.y(centerPoint.y()+halfLength);
|
|
bottomLeft.x(centerPoint.x()-halfLength);
|
|
bottomLeft.y(centerPoint.y()+halfLength);
|
|
line(topLeft,topRight,rgbColor);
|
|
line(topRight,bottomRight,rgbColor);
|
|
line(bottomRight,bottomLeft,rgbColor);
|
|
line(bottomLeft,topLeft,rgbColor);
|
|
return TRUE;
|
|
}
|
|
|
|
WORD PureDevice::line(const Point &firstPoint,const Point &secondPoint,const RGBColor &rgbColor)const
|
|
{
|
|
LONG xRunning(firstPoint.x());
|
|
LONG yRunning(firstPoint.y());
|
|
LONG xDelta;
|
|
LONG yDelta;
|
|
short xDir(1);
|
|
short yDir(1);
|
|
short steps;
|
|
|
|
if(!isOkay())return FALSE;
|
|
xRunning<<=0x10;
|
|
yRunning<<=0x10;
|
|
if(secondPoint.x()<firstPoint.x())xDir=-1;
|
|
if(secondPoint.y()<firstPoint.y())yDir=-1;
|
|
xDelta=secondPoint.x()-firstPoint.x();
|
|
yDelta=secondPoint.y()-firstPoint.y();
|
|
if(xDelta<0L)xDelta=-xDelta;
|
|
if(yDelta<0L)yDelta=-yDelta;
|
|
if(xDelta<yDelta)
|
|
{
|
|
xDelta<<=0x10;
|
|
if(yDelta)xDelta/=yDelta;
|
|
else xDelta=1L;
|
|
steps=yDelta;
|
|
yDelta=0x10000;
|
|
}
|
|
else
|
|
{
|
|
yDelta<<=0x10;
|
|
if(xDelta)yDelta/=xDelta;
|
|
else yDelta=1L;
|
|
steps=xDelta;
|
|
xDelta=0x10000;
|
|
}
|
|
if(-1==xDir&&-1==yDir)
|
|
{
|
|
for(short stepIndex=0;stepIndex<steps;stepIndex++)
|
|
{
|
|
setPixel(Point(xRunning>>0x10,yRunning>>0x10),rgbColor);
|
|
xRunning-=xDelta;
|
|
yRunning-=yDelta;
|
|
}
|
|
}
|
|
else if(-1==xDir&&1==yDir)
|
|
{
|
|
for(short stepIndex=0;stepIndex<steps;stepIndex++)
|
|
{
|
|
setPixel(Point(xRunning>>0x10,yRunning>>0x10),rgbColor);
|
|
xRunning-=xDelta;
|
|
yRunning+=yDelta;
|
|
}
|
|
}
|
|
else if(1==xDir&&-1==yDir)
|
|
{
|
|
for(short itemIndex=0;itemIndex<steps;itemIndex++)
|
|
{
|
|
setPixel(Point(xRunning>>0x10,yRunning>>0x10),rgbColor);
|
|
xRunning+=xDelta;
|
|
yRunning-=yDelta;
|
|
}
|
|
}
|
|
else if(1==xDir&&1==yDir)
|
|
{
|
|
for(short itemIndex=0;itemIndex<steps;itemIndex++)
|
|
{
|
|
setPixel(Point(xRunning>>0x10,yRunning>>0x10),rgbColor);
|
|
xRunning+=xDelta;
|
|
yRunning+=yDelta;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|