191 lines
3.8 KiB
C++
191 lines
3.8 KiB
C++
#ifndef LCD_DRAW
|
|
#define LCD_DRAW
|
|
|
|
#include <cmath>
|
|
#include <cstdint>
|
|
#include "../../data/Color.h"
|
|
//struct RGB {
|
|
|
|
// uint8_t r;
|
|
// uint8_t g;
|
|
// uint8_t b;
|
|
|
|
// RGB() : r(0), g(0), b(0) {;}
|
|
// RGB(uint8_t r, uint8_t g, uint8_t b) : r(r), g(g), b(b) {;}
|
|
|
|
// uint16_t toRGB565() const {
|
|
// return
|
|
// ((r >> 3) << 11) |
|
|
// ((g >> 2) << 5) |
|
|
// ((b >> 3) << 0);
|
|
// }
|
|
|
|
//};
|
|
|
|
class FontWrap {
|
|
|
|
uint16_t w;
|
|
uint16_t h;
|
|
const uint8_t* data;
|
|
const uint16_t* offsets;
|
|
|
|
static constexpr uint8_t off = 32;
|
|
|
|
public:
|
|
|
|
/** ctor */
|
|
FontWrap(const uint16_t w, const uint16_t h, const uint8_t* data, const uint16_t* offsets) : w(w), h(h), data(data), offsets(offsets) {
|
|
;
|
|
}
|
|
|
|
/** get the pixel-width of the given char */
|
|
uint8_t getCharWidht(char c) const {
|
|
if (c == 32) {return 3;} // whitespace
|
|
const int i = c-off;
|
|
return offsets[i+1] - offsets[i];
|
|
}
|
|
|
|
uint8_t getHeight() const {
|
|
return h;
|
|
}
|
|
|
|
uint16_t getWidth(const char* txt) const {
|
|
uint16_t sum = 0;
|
|
while(*txt) {
|
|
sum += getCharWidht(*txt);
|
|
++txt;
|
|
}
|
|
return sum;
|
|
}
|
|
|
|
/** draw the given string at the given position */
|
|
template <typename Scalar, typename Destination> void draw(const char* c, Scalar dx, Scalar dy, Destination& dst) const {
|
|
while(*c) {
|
|
draw(*c, dx, dy, dst);
|
|
dx += getCharWidht(*c);// + 1;
|
|
++c;
|
|
}
|
|
}
|
|
|
|
/** draw the given char at the given position */
|
|
template <typename Scalar, typename Destination> void draw(unsigned char c, Scalar dx, Scalar dy, Destination& dst) const {
|
|
|
|
if (c == 32) {return;} // skip whitespace
|
|
|
|
const uint16_t x1 = offsets[c-off];
|
|
const uint16_t x2 = offsets[c-off+1];
|
|
const uint16_t y1 = 0;
|
|
const uint16_t y2 = h;
|
|
|
|
for (uint16_t y = y1; y < y2; ++y) {
|
|
for (uint16_t x = x1; x < x2; ++x) {
|
|
const uint16_t idx = (x/8) + (y*this->w/8);
|
|
const uint8_t pxInFont = data[idx] & (1<<(x&7)); // pixel from font glyph
|
|
if (pxInFont) {
|
|
dst.setPixel(dx+x-x1, dy+y);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename Scalar, typename Destination> class Draw {
|
|
|
|
Destination& dst;
|
|
|
|
public:
|
|
|
|
Draw(Destination& dst) : dst(dst) {
|
|
|
|
}
|
|
|
|
void set(const Scalar x1, const Scalar y1) {
|
|
dst.set(x1, y1);
|
|
}
|
|
|
|
void setColor(const Color color) {
|
|
dst.setColor(color);
|
|
}
|
|
|
|
/** draw a line from (x0,y0) to (x1,y1) */
|
|
void drawLine(Scalar x1, Scalar y1, const Scalar x2, const Scalar y2) {
|
|
|
|
// int dx, dy, p, x, y;
|
|
|
|
// dx=x1-x0;
|
|
// dy=y1-y0;
|
|
|
|
// x=x0;
|
|
// y=y0;
|
|
|
|
// p=2*dy-dx;
|
|
|
|
// while(x < x1) {
|
|
// if(p >= 0) {
|
|
// dst.set(x,y);
|
|
// y=y+1;
|
|
// p=p+2*dy-2*dx;
|
|
// } else {
|
|
// dst.set(x,y);
|
|
// p=p+2*dy;
|
|
// }
|
|
// x=x+1;
|
|
// }
|
|
|
|
Scalar dx = abs(x2-x1);
|
|
Scalar sx = (x1<x2 ? 1 : -1);
|
|
Scalar dy = -abs(y2-y1);
|
|
Scalar sy = (y1<y2 ? 1 : -1);
|
|
Scalar err = dx+dy;
|
|
Scalar e2;
|
|
|
|
while( (x1!=x2) || (y1!=y2) ) {
|
|
dst.setPixel(x1,y1);
|
|
e2 = 2*err;
|
|
if (e2 > dy) { err += dy; x1 += sx; }
|
|
if (e2 < dx) { err += dx; y1 += sy; }
|
|
}
|
|
|
|
}
|
|
|
|
void fillRect(const Scalar x, const Scalar y, const Scalar w, const Scalar h) {
|
|
dst.fillRect(x,y,w,h);
|
|
}
|
|
|
|
void drawLineHor(const Scalar x1, const Scalar x2, const Scalar y) {
|
|
dst.fillRect(x1,y,x2-x1,1);
|
|
}
|
|
void drawLineVer(const Scalar y1, const Scalar y2, const Scalar x) {
|
|
dst.fillRect(x,y1,1,y2-y1);
|
|
}
|
|
|
|
void drawRect(const Scalar x, const Scalar y, const Scalar w, const Scalar h) {
|
|
drawLineHor(x,x+w, y); // top
|
|
drawLineHor(x,x+w, y+h); // bottom
|
|
drawLineVer(y,y+h, x); // left
|
|
drawLineVer(y,y+h, x+w); // right
|
|
}
|
|
|
|
// void drawRect(const Scalar x1, const Scalar y1, const Scalar x2, const Scalar y2) {
|
|
|
|
// for (Scalar s = x1; s <= x2; ++s) {dst.set(s, y1);}
|
|
// for (Scalar s = x1; s <= x2; ++s) {dst.set(s, y2);}
|
|
|
|
// for (Scalar s = y1+1; s < y2; ++s) {dst.set(x1, s);}
|
|
// for (Scalar s = y1+1; s < y2; ++s) {dst.set(x2, s);}
|
|
|
|
// }
|
|
|
|
Scalar abs(Scalar v) const {
|
|
if (v >= 0) {return v;}
|
|
return -v;
|
|
}
|
|
|
|
};
|
|
|
|
#endif
|