Files
EnergyMonitor_Pico/libs/mare/mare_drawables.cpp
Emanuele Trabattoni c34e6931eb chardacters render
2021-08-15 18:54:16 +02:00

355 lines
9.6 KiB
C++

#include "mare.h"
#include "charmap.h"
namespace Render {
Drawable::Drawable(const size_t id, Drawable* parent, Mare* engine):
_id(id),
_parent(parent),
_engine(engine),
_origin({0,0}),
_bbox({0,0,0,0}),
_blendMode(Render::BlendMode::Add),
_dirty(false)
{
}
Drawable::~Drawable() {
}
//--------+--------+--------+--------+--------+--------+--------+--------+--------+--------//
//Point
DrawablePoint::DrawablePoint(const size_t id, Drawable* parent, Mare* engine, dim_t size):
Drawable(id, parent,engine),
_size(size)
{
}
DrawablePoint::~DrawablePoint() {
}
void DrawablePoint::render() {
uint8_t *buf;
pos_t o = getOrigin();
if (isDirty()){
buf = getBuffer();
//TODO: implement screen rotation and margin check
auto dx = engine()->getSize().x;
auto dy = engine()->getSize().y;
for (uint16_t xx(0); xx< _size.x; xx++){
for (uint16_t yy(0); yy < _size.y; yy++)
{
engine()->setPixel(buf,o.x+xx,o.y+yy,getBlendMode());
}
}
resetDirty();
}
}
//--------+--------+--------+--------+--------+--------+--------+--------+--------+--------//
//Line
DrawableLine::DrawableLine(const size_t id, Drawable* parent, Mare* engine):
Drawable(id, parent,engine),
_thickness(1),
_length(0),
_rotation(0)
{
setThickness(_thickness); // only to calc offset
}
DrawableLine::~DrawableLine()
{
}
void DrawableLine::render(){
uint8_t* buf = getBuffer();
auto tt = _thickness;
auto e = engine();
if (isDirty()) {
_rotation = _rotation % 360;
pos_t o = getOrigin();
pos_t res = {0,0};
for (uint16_t t(0); t < _thickness; ++t) {
for (uint16_t xx(0); xx < _length; ++xx) {
if (_rotation == 0 || _rotation == 180){
res.x = _rotation == 0 ? xx : -xx;
res.y = t-_ofst;
} else if (_rotation == 90 || _rotation == 270){
res.x = t-_ofst;
res.y = _rotation == 90 ? xx : -xx;
} else {
res = e->rotateXY(xx,t-_ofst,_rotation/180.0f*M_PI);
}
e->setPixel(buf,res.x+o.x,res.y+o.y,getBlendMode());
}
}
resetDirty();
}
}
//--------+--------+--------+--------+--------+--------+--------+--------+--------+--------//
//Rectangle
DrawableRectangle::DrawableRectangle(const size_t id, Drawable* parent, Mare* engine):
Drawable(id, parent,engine),
_thickness(1),
_rotation(0),
_dim({8,8}),
_outline(false)
{
}
DrawableRectangle::~DrawableRectangle()
{
}
void DrawableRectangle::createOutline(){
auto e = engine();
pos_t o = getOrigin();
auto rf = (_rotation % 360)/180.0f*M_PI;
if (l1 == nullptr) l1 = e->addDrawable<DrawableLine>();
if (l2 == nullptr) l2 = e->addDrawable<DrawableLine>();
if (l3 == nullptr) l3 = e->addDrawable<DrawableLine>();
if (l4 == nullptr) l4 = e->addDrawable<DrawableLine>();
l1->setRotation(_rotation);
l1->setLength(_dim.x);
l1->setThickness(_thickness);
l2->setRotation(_rotation+90);
l2->setLength(_dim.y);
l2->setThickness(_thickness);
l3->setRotation(_rotation);
l3->setLength(_dim.x);
l3->setThickness(_thickness);
l4->setRotation(_rotation+90);
l4->setLength(_dim.y);
l4->setThickness(_thickness);
uint8_t of = l2->_ofst;
pos_t res = {0,0};
l1->setOrigin(o);
res = e->rotateXY((_dim.x-of),0,rf);
l2->setOrigin({(p_t)(o.x+res.x), (p_t)(o.y+res.y)});
res = e->rotateXY(0,(_dim.y-of),rf);
l3->setOrigin({(p_t)(o.x+res.x), (p_t)(o.y+res.y)});
res = e->rotateXY(of,-of,rf);
l4->setOrigin({(p_t)(o.x+res.x), (p_t)(o.y+res.y)});
l1->setDirty();
l2->setDirty();
l3->setDirty();
l4->setDirty();
}
void DrawableRectangle::render()
{
uint8_t* buf = getBuffer();
auto tt = _thickness;
auto e = engine();
if (isDirty()) {
if (_outline) {
createOutline();
l1->render();
l2->render();
l3->render();
l4->render();
}
resetDirty();
}
}
//--------+--------+--------+--------+--------+--------+--------+--------+--------+--------//
//Circle
DrawableCircle::DrawableCircle(const size_t id, Drawable* parent, Mare* engine):
Drawable(id, parent,engine),
_thickness(1),
_radius(8),
_outline(false)
{
}
DrawableCircle::~DrawableCircle ()
{
}
void DrawableCircle::render()
{
auto e = engine();
uint8_t* buf = getBuffer();
auto tt = _thickness;
auto bm = getBlendMode();
const pos_t o = getOrigin();
const uint8_t t2 = _thickness >> 1;
const pos_t oo = {o.x-t2, o.y-t2};
auto dot = [buf, tt, e, bm] (p_t x, p_t y) {
for (uint16_t xx(0); xx < tt; ++xx) {
for (uint16_t yy(0); yy < tt; ++yy) {
e->setPixel(buf, xx+x, yy+y, bm);
}
}
};
auto pix = [buf,e,bm](p_t x, p_t y) {
e->setPixel(buf, x, y, bm);
};
if (isDirty()){
if (_outline){
const float st = M_PI_2/45;
pos_t pres;
for (float t(0); t <= M_TWOPI; t+=st){
auto res = e->rotateXY(_radius,0,t);
if (res != pres) {
dot(oo.x+res.x, oo.y+res.y);
dot(oo.x-res.x, oo.y+res.y);
dot(oo.x-res.x, oo.y+res.y);
dot(oo.x-res.x, oo.y-res.y);
pres=res;
}
}
}
resetDirty();
}
}
//--------+--------+--------+--------+--------+--------+--------+--------+--------+--------//
//Character
extern const _tFont* Font8_t;
extern const _tFont* Font12_t;
extern const _tFont* Font16_t;
extern const _tFont* Font20_t;
extern const _tFont* Font24_t;
DrawableChar::DrawableChar(const size_t id, Drawable* parent, Mare* engine, char c, Font f) :
Drawable(id, parent,engine),
_fontEnum(f),
_char(c)
{
switch (_fontEnum)
{
case Font::Font8:
_font = Font8_t;
break;
case Font::Font12:
_font = Font12_t;
break;
case Font::Font16:
_font = Font16_t;
break;
case Font::Font20:
_font = Font20_t;
break;
case Font::Font24:
_font = Font24_t;
break;
default:
break;
}
}
DrawableChar::~DrawableChar() {
}
void DrawableChar::render() {
uint8_t* buf = getBuffer();
const pos_t o = getOrigin();
const BlendMode bm = getBlendMode();
const uint8_t w = _font->Width;
const uint8_t h = _font->Height;
const uint16_t w_ch = w%7 ? (w/7)+1 : w/7;
const uint8_t* ch = _font->table + (_char - ' ') * w_ch * h;
for(uint8_t y(0); y < h; y++) {
for(uint8_t x(0); x < w; x++) {
const uint8_t* ch_v = ch + x / 7 + y * w_ch;
if (ch_v == 0) continue;
if ((*ch_v >> x) & 0x01){
engine()->setPixel(buf,o.x+x, o.y+y, bm);
}
}
}
}
//--------+--------+--------+--------+--------+--------+--------+--------+--------+--------//
//String
DrawableString::DrawableString(const size_t id, Drawable* parent, Mare* engine, std::string &s, Font f) :
Drawable(id, parent,engine),
_fontEnum(f),
_s(s)
{
_chars.reserve(s.size());
uint16_t idx(0);
for(auto c : _s){
_chars.push_back(engine->addDrawable<DrawableChar>(reinterpret_cast<char>(c),_fontEnum));
}
}
DrawableString::~DrawableString()
{
//free heap of drawable characters
for (auto c : _chars) {
delete c;
}
_chars.clear();
}
void DrawableString::render() {
pos_t ofs;
int32_t ofsX=0, ofsY=0;
switch(_rotation) {
case TextRotation::Rot0: {
ofsX = _chars.front()->_font->Width + _hSpace;
break;
}
case TextRotation::Rot180:{
ofsY = -_chars.front()->_font->Width - _hSpace;
break;
}
case TextRotation::Rot90: {
ofsY = _chars.front()->_font->Height + _vSpace;
break;
}
case TextRotation::Rot270: {
ofsY = _chars.front()->_font->Height + _vSpace;
break;
}
}
for (auto c : _chars){
if (c != nullptr){
c->setOrigin(ofs);
c->render();
ofs.x += ofsX;
ofs.y += ofsY;
}
}
}
//--------+--------+--------+--------+--------+--------+--------+--------+--------+--------//
//Custom
}