355 lines
9.6 KiB
C++
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
|
|
|
|
} |