kopia lustrzana https://github.com/lora-aprs/LoRa_APRS_iGate
354 wiersze
8.8 KiB
C++
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();
|
|
}
|