// DrawFunc.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include "DrawFunc.h"
#include <windows.h>
#include <math.h>
#include <vector>
#include <algorithm>
#include "..\Common\Curve Simplification\DPHull.h" // for sketch simplification
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
namespace DrawFunc {
namespace Sketch {
void Create(DrawItAPI* api, const POINT* mouse, const DRAWDATA* data)
{
switch (data->count_data) {
case 0: {
api->AddData(api->AddPoint(mouse));
} break;
default: {
api->AddData(api->AddPoint(mouse));
} break;
};
}
struct DPPOINT {
double x;
double y;
};
void Complete(DrawItAPI* api, const DRAWDATA* data)
{
std::vector<DPPOINT> points;
points.resize(data->count_data);
for (unsigned int i = 0; i < points.size(); ++i) {
const POINT* pt = api->GetPoint(data->data[i]);
points[i].x = pt->x;
points[i].y = pt->y;
}
CDPHull hull;
hull.SetTol(5.0);
hull.SetCurve(points.size(), (DP_POINT*)&points[0].x);
hull.Approximate();
hull.InjectDPInOriginal();
points.resize(hull.GetDPNPoints());
for (unsigned int i = 0; i < points.size(); ++i) {
POINT p = { (LONG)points[i].x, (LONG)points[i].y };
api->SetPoint(data->data[i], &p);
}
for (; i < data->count_data; ++i) {
api->RemovePoint(data->data[i]);
}
api->ResizeData(points.size());
}
void Draw(DrawItAPI* api, HDC dc, const DRAWDATA* data)
{
switch (data->count_data) {
default: {
const POINT* pt = api->GetPoint(data->data[0]);
::MoveToEx(dc, pt->x, pt->y, NULL);
for (unsigned long i = 1; i < data->count_data; ++i) {
const POINT* pt = api->GetPoint(data->data[i]);
::LineTo(dc, pt->x, pt->y);
const int o = 4;
::MoveToEx(dc, pt->x + o, pt->y + o, NULL);
::LineTo(dc, pt->x - o, pt->y - o);
::MoveToEx(dc, pt->x + o, pt->y - o, NULL);
::LineTo(dc, pt->x - o, pt->y + o);
::MoveToEx(dc, pt->x, pt->y, NULL);
}
} break;
case 1: {
const POINT* pt = api->GetPoint(data->data[0]);
::SetPixel(dc, pt->x, pt->y, RGB(0,0,0));
} break;
case 0:
break;
};
}
static CLIENTCALLBACKS callbacks = { &Create, &Complete, &Draw };
};
namespace Line {
void Create(DrawItAPI* api, const POINT* mouse, const DRAWDATA* data)
{
switch (data->count_data) {
case 0: {
api->AddData(api->AddPoint(mouse));
api->AddData(api->AddPoint(mouse));
} break;
case 2: {
api->SetPoint(data->data[1], mouse);
} break;
default:
break;
};
}
void Complete(DrawItAPI* api, const DRAWDATA* data)
{
}
void Draw(DrawItAPI* api, HDC dc, const DRAWDATA* data)
{
switch (data->count_data) {
default: {
const POINT* pt = api->GetPoint(data->data[0]);
::MoveToEx(dc, pt->x, pt->y, NULL);
for (unsigned long i = 1; i < data->count_data; ++i) {
const POINT* pt = api->GetPoint(data->data[i]);
::LineTo(dc, pt->x, pt->y);
}
} break;
case 1: {
const POINT* pt = api->GetPoint(data->data[0]);
::SetPixel(dc, pt->x, pt->y, RGB(0,0,0));
} break;
case 0:
break;
};
}
static CLIENTCALLBACKS callbacks = { &Create, &Complete, &Draw };
};
namespace Spline {
void Create(DrawItAPI* api, const POINT* mouse, const DRAWDATA* data)
{
switch (data->count_data) {
case 0: {
api->AddData(api->AddPoint(mouse));
api->AddData(api->AddPoint(mouse));
api->AddData(api->AddPoint(mouse));
api->AddData(api->AddPoint(mouse));
} break;
case 4: {
POINT start = *api->GetPoint(data->data[0]);
POINT mid = { (mouse->x + start.x)/2, (mouse->y + start.y)/2 };
POINT pt1 = { mid.x, mid.y + 50 };
POINT pt2 = { mid.x, mid.y - 50 };
api->SetPoint(data->data[1], &pt1);
api->SetPoint(data->data[2], &pt2);
api->SetPoint(data->data[3], mouse);
} break;
default:
break;
};
}
void Complete(DrawItAPI* api, const DRAWDATA* data)
{
}
void Draw(DrawItAPI* api, HDC dc, const DRAWDATA* data)
{
const unsigned int remainder = data->count_data % 3;
std::vector<POINT> spline; spline.reserve(100);
for (unsigned long i = 0; i < data->count_data; ++i)
spline.push_back(*api->GetPoint(data->data[i]));
switch (remainder) {
case 2: // need two more ("from" and "to" control points) so just make something up
{
std::vector<POINT>::iterator i = spline.end();
spline.insert(--i, spline[data->count_data - 2]);
}
case 0: // need one more (just the "to" control point) so just duplicate the "to" point
spline.push_back(spline.back());
case 1: // just right
::PolyBezier(dc, &spline[0], spline.size());
break;
};
}
static CLIENTCALLBACKS callbacks = { &Create, &Complete, &Draw };
};
namespace Rectangle {
void Create(DrawItAPI* api, const POINT* mouse, const DRAWDATA* data)
{
switch (data->count_data) {
case 0: {
api->AddData(api->AddPoint(mouse));
api->AddData(api->AddPoint(mouse));
} break;
case 2: {
api->SetPoint(data->data[1], mouse);
} break;
default:
break;
};
}
void Complete(DrawItAPI* api, const DRAWDATA* data)
{
}
void Draw(DrawItAPI* api, HDC dc, const DRAWDATA* data)
{
static const COLORREF color1 = RGB(255,128,128);
static const COLORREF color2 = RGB(255,255,128);
switch (data->count_data) {
case 2: {
const POINT* pt1 = api->GetPoint(data->data[0]);
const POINT* pt2 = api->GetPoint(data->data[1]);
TRIVERTEX vert[2];
const unsigned short scale = 0xFFFF / 0xFF;
vert[0].x = pt1->x;
vert[0].y = pt1->y;
vert[0].Red = GetRValue(color1) * scale;
vert[0].Green = GetGValue(color1) * scale;
vert[0].Blue = GetBValue(color1) * scale;
vert[0].Alpha = 0xFFFF;
vert[1].x = pt2->x;
vert[1].y = pt2->y;
vert[1].Red = GetRValue(color2) * scale;
vert[1].Green = GetGValue(color2) * scale;
vert[1].Blue = GetBValue(color2) * scale;
vert[1].Alpha = 0xFFFF;
GRADIENT_RECT gRect;
gRect.UpperLeft = 0;
gRect.LowerRight = 1;
::GradientFill(dc, vert, 2, &gRect, 1, GRADIENT_FILL_RECT_V);
} break;
default:
break;
};
}
static CLIENTCALLBACKS callbacks = { &Create, &Complete, &Draw };
};
namespace Circle {
void Create(DrawItAPI* api, const POINT* mouse, const DRAWDATA* data)
{
switch (data->count_data) {
case 0: {
api->AddData(api->AddPoint(mouse));
api->AddData(api->AddPoint(mouse));
} break;
case 2: {
api->SetPoint(data->data[1], mouse);
} break;
default:
break;
};
}
void Complete(DrawItAPI* api, const DRAWDATA* data)
{
}
void Draw(DrawItAPI* api, HDC dc, const DRAWDATA* data)
{
switch (data->count_data) {
case 2:
{
const POINT* on1 = api->GetPoint(data->data[0]);
const POINT* on2 = api->GetPoint(data->data[1]);
const unsigned int size = static_cast<unsigned int>(sqrt((double)(on1->x - on2->x) * (on1->x - on2->x)
+ (on1->y - on2->y) * (on1->y - on2->y)) / 2);
POINT center;
center.x = (on1->x + on2->x) / 2;
center.y = (on1->y + on2->y) / 2;
::Ellipse(dc, center.x - size, center.y - size, center.x + size, center.y + size);
} break;
default:
break;
};
}
static CLIENTCALLBACKS callbacks = { &Create, &Complete, &Draw };
};
namespace Ellipse {
void Create(DrawItAPI* api, const POINT* mouse, const DRAWDATA* data)
{
switch (data->count_data) {
case 0: {
api->AddData(api->AddPoint(mouse));
api->AddData(api->AddPoint(mouse));
} break;
case 2: {
api->SetPoint(data->data[1], mouse);
} break;
default:
break;
};
}
void Complete(DrawItAPI* api, const DRAWDATA* data)
{
srand(time(0));
if ((rand() % 100) == 0) { // crash randomly
char* foo = NULL;
foo[0]++;
}
}
void Draw(DrawItAPI* api, HDC dc, const DRAWDATA* data)
{
switch (data->count_data) {
case 2: {
const POINT* pt1 = api->GetPoint(data->data[0]);
const POINT* pt2 = api->GetPoint(data->data[1]);
::Ellipse(dc, pt1->x, pt1->y, pt2->x, pt2->y);
} break;
default:
break;
};
}
static CLIENTCALLBACKS callbacks = { &Create, &Complete, &Draw };
};
}; // namespace DrawFunc
DRAWFUNC_API bool DrawDllInit(PFNADDCLIENTCALLBACKS fnAdd)
{
bool ok = true;
unsigned int lineCode = (*fnAdd)(&DrawFunc::Line::callbacks);
unsigned int sketchCode = (*fnAdd)(&DrawFunc::Sketch::callbacks);
// unsigned int splineCode = (*fnAdd)(&DrawFunc::Spline::callbacks);
unsigned int rectangleCode = (*fnAdd)(&DrawFunc::Rectangle::callbacks);
unsigned int circleCode = (*fnAdd)(&DrawFunc::Circle::callbacks);
unsigned int ellipseCode = (*fnAdd)(&DrawFunc::Ellipse::callbacks);
return true;
}