93 lines
2.6 KiB
C++
93 lines
2.6 KiB
C++
|
#include "libwasm.h"
|
||
|
#include "canvas.h"
|
||
|
|
||
|
int round (const double a) {
|
||
|
return int (a + 0.5);
|
||
|
}
|
||
|
|
||
|
Canvas::Canvas(const int w, const int h) : width(w), height(h),
|
||
|
outpixel(0u), current(0xFF000000), matrix (1.0, 0.0, 0.0, -1.0, 0.5 * (real) w, 0.5 * (real) (h)) {
|
||
|
data = new Color [w * h];
|
||
|
}
|
||
|
|
||
|
Canvas::~Canvas() {
|
||
|
delete [] data;
|
||
|
}
|
||
|
void Canvas::fill (const Color & c) {
|
||
|
for (int y=0; y<height; y++) {
|
||
|
for (int x=0; x<width; x++) {
|
||
|
at (x, y) = c;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
Color & Canvas::at (const int x, const int y) {
|
||
|
if (!bound(x, y)) return outpixel;
|
||
|
const int result = x + y * width;
|
||
|
return data [result];
|
||
|
}
|
||
|
bool Canvas::bound (const int x, const int y) const {
|
||
|
if (x < 0) return false;
|
||
|
if (y < 0) return false;
|
||
|
if (x >= width) return false;
|
||
|
if (y >= height) return false;
|
||
|
return true;
|
||
|
}
|
||
|
void Canvas::line (const int xp, const int yp, const int xe, const int ye, const bool doted) {
|
||
|
bool dot = true;
|
||
|
int x1 = xp, y1 = yp;
|
||
|
const int x2 = xe, y2 = ye;
|
||
|
bool done = false;
|
||
|
int mx = 0, my = 0;
|
||
|
// Determine direction and distance
|
||
|
const int xd = (x1 < x2) ? 1 : -1;
|
||
|
const int yd = (y1 < y2) ? 1 : -1;
|
||
|
const int xl = (x1 < x2) ? (x2 - x1) : (x1 - x2);
|
||
|
const int yl = (y1 < y2) ? (y2 - y1) : (y1 - y2);
|
||
|
while (!done) {
|
||
|
if (x1 == x2 && y1 == y2) done = true;
|
||
|
if (dot) at(x1,y1) = current; // Plot pixel
|
||
|
if (doted) dot = !dot;
|
||
|
mx += xl;
|
||
|
if (x1 != x2 && mx > yl) x1 += xd, mx -= yl;
|
||
|
my += yl;
|
||
|
if (y1 != y2 && my > xl) y1 += yd, my -= xl;
|
||
|
}
|
||
|
}
|
||
|
void Canvas::rect (const int x0, const int y0, const int x1, const int y1) {
|
||
|
for (int y=y0; y<y1; y++) {
|
||
|
for (int x=x0; x<x1; x++) {
|
||
|
at(x, y) = current;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Canvas::line (const FPoint & begin, const FPoint & end, const bool doted) {
|
||
|
const FPoint b (matrix * begin);
|
||
|
const FPoint e (matrix * end );
|
||
|
const int x0 = (const int) round (b.x);
|
||
|
const int y0 = (const int) round (b.y);
|
||
|
const int x1 = (const int) round (e.x);
|
||
|
const int y1 = (const int) round (e.y);
|
||
|
// printf("%d:%d - %d:%d\n", x0, y0, x1, y1);
|
||
|
line (x0, y0, x1, y1, doted);
|
||
|
}
|
||
|
void Canvas::circ (const FPoint & center, const real radius) {
|
||
|
if (radius == 0) return;
|
||
|
double x = radius, y = 0.0;
|
||
|
const double dx = 1.0 / radius;
|
||
|
const double ms = radius * 6.3;
|
||
|
real count = 0.0;
|
||
|
// kruh se da nakreslit i bez sin a cos, rychle ale trochu nepresne
|
||
|
for (;;) {
|
||
|
x += y * dx; y -= x * dx;
|
||
|
const FPoint e (center.x + x, center.y + y);
|
||
|
const FPoint t (matrix * e);
|
||
|
at ((int) round (t.x), (int) round (t.y)) = current;
|
||
|
count += 1.0;
|
||
|
if (count > ms) break;
|
||
|
}
|
||
|
}
|
||
|
void Canvas::setMatrix (const Matrix& m) {
|
||
|
matrix = m;
|
||
|
}
|