LoRa_APRS_iGate/lib/Display/Bitmap.cpp

354 wiersze
8.8 KiB
C++

#include "Bitmap.h"
#include "FontConfig.h"
#include "OLEDDisplay.h"
//#include "OLEDDisplayFonts.h"
// cppcheck-suppress unusedFunction
Bitmap::Bitmap(uint width, uint height) : _width(width), _height(height), _buffer(0) {
allocateBuffer();
}
// cppcheck-suppress unusedFunction
Bitmap::Bitmap(OLEDDisplay *display) : _width(display->getWidth()), _height(display->getHeight()), _buffer(0) {
allocateBuffer();
}
// cppcheck-suppress unusedFunction
Bitmap::~Bitmap() {
if (_buffer != 0) {
delete _buffer;
}
}
// cppcheck-suppress unusedFunction
uint Bitmap::getWidth() const {
return _width;
}
// cppcheck-suppress unusedFunction
uint Bitmap::getHeight() const {
return _height;
}
// cppcheck-suppress unusedFunction
void Bitmap::setPixel(int x, int y) {
if (x >= 0 && x < _width && y >= 0 && y < _height) {
_buffer[x + (y / 8) * _width] |= (1 << (y % 8));
}
}
// cppcheck-suppress unusedFunction
void Bitmap::clearPixel(int x, int y) {
if (x >= 0 && x < _width && y >= 0 && y < _height) {
_buffer[x + (y / 8) * _width] &= ~(1 << (y % 8));
}
}
// cppcheck-suppress unusedFunction
bool Bitmap::getPixel(int x, int y) const {
if (x >= 0 && x < _width && y >= 0 && y < _height) {
return _buffer[x + (y / 8) * _width] & (1 << (y % 8));
}
return false;
}
// cppcheck-suppress unusedFunction
void Bitmap::clear() {
memset(_buffer, 0, _width * _height / 8);
}
// cppcheck-suppress unusedFunction
void Bitmap::drawLine(int x0, int y0, int x1, int y1) {
int dx = abs(x1 - x0);
int dy = abs(y1 - y0);
int sx = x0 < x1 ? 1 : -1;
int sy = y0 < y1 ? 1 : -1;
int err = (dx > dy ? dx : -dy) / 2;
while (true) {
setPixel(x0, y0);
if (x0 == x1 && y0 == y1)
break;
int e2 = err;
if (e2 > -dx) {
err -= dy;
x0 += sx;
}
if (e2 < dy) {
err += dx;
y0 += sy;
}
}
}
// cppcheck-suppress unusedFunction
void Bitmap::drawHorizontalLine(int x, int y, int length) {
if (y < 0 || y >= _height) {
return;
}
for (int i = 0; i < length; i++) {
setPixel(x + i, y);
}
}
// cppcheck-suppress unusedFunction
void Bitmap::drawVerticalLine(int x, int y, int length) {
if (x < 0 || x >= _width) {
return;
}
for (int i = 0; i < length; i++) {
setPixel(x, y + i);
}
}
// cppcheck-suppress unusedFunction
void Bitmap::drawRect(int x, int y, int width, int height) {
drawHorizontalLine(x, y, width);
drawVerticalLine(x, y, height);
drawVerticalLine(x + width - 1, y, height);
drawHorizontalLine(x, y + height - 1, width);
}
// cppcheck-suppress unusedFunction
void Bitmap::fillRect(int x, int y, int width, int height) {
for (int i = 0; i < width; i++) {
drawVerticalLine(x + i, y, height);
}
}
// cppcheck-suppress unusedFunction
void Bitmap::drawCircle(int x0, int y0, int radius) {
int x = 0;
int y = radius;
int dp = 1 - radius;
do {
if (dp < 0) {
dp = dp + (x++) * 2 + 3;
} else {
dp = dp + (x++) * 2 - (y--) * 2 + 5;
}
setPixel(x0 + x, y0 + y); // For the 8 octants
setPixel(x0 - x, y0 + y);
setPixel(x0 + x, y0 - y);
setPixel(x0 - x, y0 - y);
setPixel(x0 + y, y0 + x);
setPixel(x0 - y, y0 + x);
setPixel(x0 + y, y0 - x);
setPixel(x0 - y, y0 - x);
} while (x < y);
setPixel(x0 + radius, y0);
setPixel(x0, y0 + radius);
setPixel(x0 - radius, y0);
setPixel(x0, y0 - radius);
}
// cppcheck-suppress unusedFunction
void Bitmap::fillCircle(int x0, int y0, int radius) {
int x = 0;
int y = radius;
int dp = 1 - radius;
do {
if (dp < 0) {
dp = dp + (x++) * 2 + 3;
} else {
dp = dp + (x++) * 2 - (y--) * 2 + 5;
}
drawHorizontalLine(x0 - x, y0 - y, 2 * x);
drawHorizontalLine(x0 - x, y0 + y, 2 * x);
drawHorizontalLine(x0 - y, y0 - x, 2 * y);
drawHorizontalLine(x0 - y, y0 + x, 2 * y);
} while (x < y);
drawHorizontalLine(x0 - radius, y0, 2 * radius);
}
// cppcheck-suppress unusedFunction
void Bitmap::drawCircleQuads(int x0, int y0, int radius, int quads) {
int x = 0;
int y = radius;
int dp = 1 - radius;
while (x < y) {
if (dp < 0) {
dp = dp + (x++) * 2 + 3;
} else {
dp = dp + (x++) * 2 - (y--) * 2 + 5;
}
if (quads & 0x1) {
setPixel(x0 + x, y0 - y);
setPixel(x0 + y, y0 - x);
}
if (quads & 0x2) {
setPixel(x0 - y, y0 - x);
setPixel(x0 - x, y0 - y);
}
if (quads & 0x4) {
setPixel(x0 - y, y0 + x);
setPixel(x0 - x, y0 + y);
}
if (quads & 0x8) {
setPixel(x0 + x, y0 + y);
setPixel(x0 + y, y0 + x);
}
}
if (quads & 0x1 && quads & 0x8) {
setPixel(x0 + radius, y0);
}
if (quads & 0x4 && quads & 0x8) {
setPixel(x0, y0 + radius);
}
if (quads & 0x2 && quads & 0x4) {
setPixel(x0 - radius, y0);
}
if (quads & 0x1 && quads & 0x2) {
setPixel(x0, y0 - radius);
}
}
// cppcheck-suppress unusedFunction
void Bitmap::drawProgressBar(int x, int y, int width, int height, int progress) {
int radius = height / 2;
int xRadius = x + radius;
int yRadius = y + radius;
int doubleRadius = 2 * radius;
int innerRadius = radius - 2;
drawCircleQuads(xRadius, yRadius, radius, 0b00000110);
drawHorizontalLine(xRadius, y, width - doubleRadius + 1);
drawHorizontalLine(xRadius, y + height, width - doubleRadius + 1);
drawCircleQuads(x + width - radius, yRadius, radius, 0b00001001);
uint16_t maxProgressWidth = (width - doubleRadius + 1) * progress / 100;
fillCircle(xRadius, yRadius, innerRadius);
fillRect(xRadius + 1, y + 2, maxProgressWidth, height - 3);
fillCircle(xRadius + maxProgressWidth, yRadius, innerRadius);
}
// cppcheck-suppress unusedFunction
int Bitmap::drawChar(int x, int y, char c) {
fontDesc_t const *font = getSystemFont();
if (c == ' ') {
return x + font->widthInPixel * 4 / 10;
}
unsigned char cu = (unsigned char)c;
if (cu < font->firstChar || cu > font->lastChar) {
cu = '?';
}
int firstPixelBitPos = 0;
for (int i = 0; i < (cu - font->firstChar); i++) {
firstPixelBitPos = firstPixelBitPos + font->pData[i];
}
firstPixelBitPos = firstPixelBitPos * font->heightInPixel;
unsigned char const *pDataStart = &(font->pData[font->lastChar - font->firstChar + 1]);
const int top = y;
const int widthInPixel = font->pData[cu - font->firstChar];
for (int i = 0; i < widthInPixel * font->heightInPixel; i++) {
int bytePos = firstPixelBitPos / 8;
int bitPos = firstPixelBitPos % 8;
if (pDataStart[bytePos] & (1 << bitPos)) {
setPixel(x, y);
} else {
clearPixel(x, y);
}
firstPixelBitPos++;
y++;
if (y == top + font->heightInPixel) {
y = top;
x++;
}
}
return x + FONT_CHAR_SPACING;
}
// cppcheck-suppress unusedFunction
int Bitmap::drawString(int x, int y, String text) {
int next_x = x;
for (int i = 0; i < text.length(); i++) {
next_x = drawChar(next_x, y, text[i]);
}
return next_x;
}
// cppcheck-suppress unusedFunction
void Bitmap::drawStringf(int x, int y, char *buffer, String format, ...) {
va_list myargs;
va_start(myargs, format);
vsprintf(buffer, format.c_str(), myargs);
va_end(myargs);
drawString(x, y, buffer);
}
// cppcheck-suppress unusedFunction
int Bitmap::drawStringLF(int x, int y, String text) {
fontDesc_t const *font = getSystemFont();
int next_x = x;
for (int i = 0; i < text.length(); i++) {
if (next_x + font->widthInPixel > _width) {
next_x = 0;
y += font->heightInPixel;
}
next_x = drawChar(next_x, y, text[i]);
}
return next_x;
}
// cppcheck-suppress unusedFunction
void Bitmap::drawStringLFf(int x, int y, char *buffer, String format, ...) {
va_list myargs;
va_start(myargs, format);
vsprintf(buffer, format.c_str(), myargs);
va_end(myargs);
drawStringLF(x, y, buffer);
}
/*void Bitmap::drawBitmap(int x, int y, const Bitmap & bitmap)
{
if(_width < x + bitmap.getWidth() || _height < y + bitmap.getHeight())
{
return;
}
for(int _x = 0; _x < bitmap.getWidth(); _x++)
{
for(int _y = 0; _y < bitmap.getHeight(); _y++)
{
if(bitmap.getPixel(_x, _y))
{
// _buffer[x + (y / 8) * _width] |= (1 << (y % 8));
// return _buffer[x + (y / 8) * _width] & (1 << (y % 8));
Serial.print(_x);
Serial.print(" ");
Serial.println(_y);
setPixel(x + _x, y + _y);
}
else
{
clearPixel(x + _x, y + _y);
}
}
}
}*/
// cppcheck-suppress unusedFunction
void Bitmap::allocateBuffer() {
_buffer = new uint8_t[_width * _height / 8];
clear();
}