#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(); if (l2 == nullptr) l2 = e->addDrawable(); if (l3 == nullptr) l3 = e->addDrawable(); if (l4 == nullptr) l4 = e->addDrawable(); 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; extern const _tFont* Font12; extern const _tFont* Font16; extern const _tFont* Font20; extern const _tFont* Font24; 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; break; case Font::Font12: _font = *Font12; break; case Font::Font16: _font = *Font16; break; case Font::Font20: _font = *Font20; break; case Font::Font24: _font = *Font24; break; default: break; } } DrawableChar::~DrawableChar() { } void DrawableChar::render() { } //--------+--------+--------+--------+--------+--------+--------+--------+--------+--------// //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(c.c_str(),_fontEnum)); } } DrawableString::~DrawableString() { //free heap of drawable characters for (auto c : _chars) { delete c; } _chars.clear(); } void DrawableString::render() { for (auto c : _chars){ if (c != nullptr){ c->render(); } } } //--------+--------+--------+--------+--------+--------+--------+--------+--------+--------// //Custom }