pitrix/src/Window.cpp

135 lines
3.4 KiB
C++

#include "Window.h"
#include "functions.h"
Window* Window::getFullWindow() {
static Window win;
return &win;
}
void Window::setPixel(uint8_t x, uint8_t y, CRGB* color) {
if (x>=this->width || y>=this->height) return;
leds[this->coordsToGlobalIndex(x, y)] = *color;
}
void Window::setPixelByIndex(uint16_t index, CRGB* color) {
uint8_t x = index % this->width;
uint8_t y = index / this->width;
this->setPixel(x, y, color);
}
uint16_t Window::coordsToGlobalIndex(uint8_t x, uint8_t y) {
return XYsafe(x + this->x, y+this->y);
}
uint16_t Window::localToGlobalIndex(uint16_t index) {
uint8_t x = index % this->width;
uint8_t y = index / this->width;
return coordsToGlobalIndex(x, y);
}
void Window::clear() {
CRGB black(0x000000);
this->clear(&black);
}
void Window::clear(CRGB* color) {
for(int x=0; x<this->width; x++) for(int y=0; y<this->height; y++) this->setPixel(x, y, color);
}
void Window::drawChar(Font* font, uint8_t xPos, uint8_t yPos, const char c, CRGB* color, bool mask) {
if (!font->isCharAllowed(c)) return;
uint16_t position = font->getCharPosition(c);
uint8_t* data = new uint8_t[font->width];
memcpy_P(data, font->data + (position*font->width), font->width);
for(uint8_t y=0; y<font->height; y++) for(uint8_t x=0; x<font->width; x++) {
bool on = (data[x]>>(font->height - 1 - y) & 1) * 255;
if (mask) on = !on;
if (on) this->setPixel(x + xPos, y + yPos, color);
}
free(data);
}
void Window::addPixelColor(uint16_t index, CRGB* color) {
leds[localToGlobalIndex(index)] += *color;
}
void Window::fadeToBlackBy(fract8 speed) {
for (uint8_t x=0; x<this->width; x++) for(uint8_t y=0; y<this->height; y++) {
leds[coordsToGlobalIndex(x, y)].nscale8(255 - speed);
}
}
void Window::line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, CRGB* color) {
// Bresenham algorithm
int16_t dx = abs(x2-x1);
int16_t dy = abs(y2-y1);
int8_t sx = x1<x2 ? 1 : -1;
int8_t sy = y1<y2 ? 1 : -1;
int16_t err = dx + dy;
int16_t e2;
while (1) {
setPixel(x1, y1, color);
if (x1==x2 && y1==y2) break;
e2 = 2*err;
if (e2 > dy) { err += dy; x1 += sx; }
if (e2 < dx) { err += dx; y1 += sy; }
}
}
void Window::circle(uint8_t x0, uint8_t y0, uint8_t radius, CRGB* color) {
// Again, Bresenham
uint8_t f = 1 - radius;
int16_t ddF_x = 0;
int16_t ddF_y = -2 * radius;
uint8_t x = 0;
uint8_t y = radius;
setPixel(x0, y0 + radius, color);
setPixel(x0, y0 - radius, color);
setPixel(x0 + radius, y0, color);
setPixel(x0 - radius, y0, color);
while (x < y) {
if (f >= 0) {
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x + 1;
setPixel(x0 + x, y0 + y, color);
setPixel(x0 - x, y0 + y, color);
setPixel(x0 + x, y0 - y, color);
setPixel(x0 - x, y0 - y, color);
setPixel(x0 + y, y0 + x, color);
setPixel(x0 - y, y0 + x, color);
setPixel(x0 + y, y0 - x, color);
setPixel(x0 - y, y0 - x, color);
}
}
void Window::lineWithAngle(uint8_t x, uint8_t y, uint8_t angle, uint8_t length, CRGB* color) {
lineWithAngle(x, y, angle, 0, length, color);
}
void Window::lineWithAngle(uint8_t x, uint8_t y, uint8_t angle, uint8_t startdist, uint8_t length, CRGB* color) {
int16_t x1 = x;
int16_t y1 = y;
if (startdist > 0) {
x1 = x + scale8(startdist, cos8(angle));
y1 = y + scale8(startdist, sin8(angle));
}
int16_t x2 = x + scale8(startdist + length, cos8(angle));
int16_t y2 = y + scale8(startdist + length, sin8(angle));
line(x1, y1, x2, y2, color);
}