#include <iostream>
namespace auto_list_exploit {
static auto li = {1,2};
using initializer_list = decltype(li);
}
template <typename CT=char>
class TextSurface {
using initializer_list = auto_list_exploit::initializer_list;
public:
struct point {
int x,y;
point(int x=0, int y=0) : x(x), y(y) {}
point(initializer_list list) : x((list.begin())[0]), y((list.begin())[1]) {}
};
private:
int m_width, m_height, m_data_count;
CT* m_data;
int OffsetOf(int x, int y) const { return y * m_width + x; }
bool IsInside(int x, int y) { return x >= 0 && y>= 0 && x < m_width && y < m_height; }
CT& at(int x, int y) { return m_data[OffsetOf(x,y)]; }
CT at(int x, int y) const { return m_data[OffsetOf(x,y)]; }
int Abs(int x) { return x < 0 ? -x : x; }
void Poly(const point& pfirst, CT value, const point& plast) {
Line(plast, pfirst, value);
}
template <typename ...Ts>
void Poly(const point& pfirst, CT value, const point& p0, const point& p1, Ts...args) {
Line(p0, p1, value);
Poly(pfirst, value, p1, args...);
}
public:
TextSurface(int width=0, int height=0) :
m_width(height ? width : 0),
m_height(width ? height : 0),
m_data_count(width * height)
{
m_data = m_data_count ? new CT[m_data_count] : nullptr;
Clear();
}
// Cannot copy
TextSurface(const TextSurface&) =delete;
TextSurface& operator = (const TextSurface&) =delete;
// Can return from functions
TextSurface& operator = (TextSurface&& src) {
delete [] m_data;
m_width = src.m_width; m_height = src.m_height; m_data_count = src.m_data_count;
m_data = src.m_data;
src.m_data = nullptr;
return *this;
}
TextSurface(TextSurface&& src) : m_data(nullptr) { operator = ((TextSurface&&)src); }
~TextSurface() { delete [] m_data; }
int Width() const { return m_width; }
int Height() const { return m_height; }
void Clear(CT value=' ') {
CT* p = m_data;
CT* pe = p + m_data_count;
while(p != pe) *(p++) = value;
}
void Line(int x0, int y0, int x1, int y1, CT value) {
const int dx = x1-x0;
const int dy = y1-y0;
if(!dx && !dy) {
if(IsInside(x0, y0)) { at(x0, y0) = value; }
return;
}
const bool ymajor = Abs(dy) > Abs(dx);
int x=x0, y=y0;
int &mj = ymajor ? y : x;
int &mn = ymajor ? x : y;
const int mje = ymajor ? y1 : x1;
const int mjst = mj < mje ? 1 : -1;
double mnd = mn;
double mnst = ymajor ? double(dx)/Abs(dy) : double(dy)/Abs(dx);
do {
mn = int(mnd + 0.5);
if(IsInside(x,y)) { at(x,y) = value; }
mj += mjst;
mnd += mnst;
} while(mj != mje+mjst);
}
void Line(const point& p0, const point& p1, CT value) { Line(p0.x, p0.y, p1.x, p1.y, value); }
template <typename ...Ts>
void Poly(CT value, const point& p0, const point& p1, Ts...args) {
Line(p0, p1, value);
Poly(p0, value, p1, args...);
}
// init-list overloads for triangle and quad (initializer_list can't be packed)
void Poly(CT value, initializer_list l0, initializer_list l1, initializer_list l2) { Poly(value, point(l0), point(l1), point(l2)); }
void Poly(CT value, initializer_list l0, initializer_list l1, initializer_list l2, initializer_list l3) { Poly(value, point(l0), point(l1), point(l2), point(l3)); }
void Rect(int x, int y, int width, int height, CT value) {
Poly(value, point(x,y), point(x+width-1, y), point(x+width-1, y+height-1), point(x, y+height-1));
}
// Label places text. xloc selects the meaning of the x coordinate.
// Its value is between -1 and 1: -1 for x at the left of the text,
// 0 for x in the middle, and 1 for x at the end of the text.
void Label(const CT* text, int x, int y, double xloc=-1) {
int len = 0;
while(text[len]) { ++len; }
x -= int((xloc + 1)/2 * (len - 1));
for(int i=0; i<len; ++i) {
if(IsInside(x,y)) { at(x,y) = text[i]; }
++x;
} }
void Present() const {
const CT* p = m_data;
for(int j=0; j<m_height; ++j) {
std::cout.write(p, m_width);
std::cout << '\n';
p += m_width;
} }
};
typedef TextSurface<char> CharSurface;
int main() {
CharSurface surf(60,20);
surf.Poly('*', {20,2}, {34,16}, {20,16});
surf.Label("14 ft", 18, 10, 1);
surf.Label("9 ft", 26, 17, 0);
surf.Present();
}
CSNpbmNsdWRlIDxpb3N0cmVhbT4KCgluYW1lc3BhY2UgYXV0b19saXN0X2V4cGxvaXQgewoJCXN0YXRpYyBhdXRvIGxpID0gezEsMn07CgkJdXNpbmcgaW5pdGlhbGl6ZXJfbGlzdCA9IGRlY2x0eXBlKGxpKTsKCX0KCgl0ZW1wbGF0ZSA8dHlwZW5hbWUgQ1Q9Y2hhcj4KCWNsYXNzIFRleHRTdXJmYWNlIHsKCQl1c2luZyBpbml0aWFsaXplcl9saXN0ID0gYXV0b19saXN0X2V4cGxvaXQ6OmluaXRpYWxpemVyX2xpc3Q7CglwdWJsaWM6CgkJc3RydWN0IHBvaW50IHsKCQkJaW50IHgseTsKCQkJcG9pbnQoaW50IHg9MCwgaW50IHk9MCkgOiB4KHgpLCB5KHkpIHt9CgkJCXBvaW50KGluaXRpYWxpemVyX2xpc3QgbGlzdCkgOiB4KChsaXN0LmJlZ2luKCkpWzBdKSwgeSgobGlzdC5iZWdpbigpKVsxXSkge30KCQl9OwoJcHJpdmF0ZToKCQlpbnQgbV93aWR0aCwgbV9oZWlnaHQsIG1fZGF0YV9jb3VudDsKCQlDVCogbV9kYXRhOwoKCQlpbnQgT2Zmc2V0T2YoaW50IHgsIGludCB5KSBjb25zdCB7IHJldHVybiB5ICogbV93aWR0aCArIHg7IH0KCQlib29sIElzSW5zaWRlKGludCB4LCBpbnQgeSkgeyByZXR1cm4geCA+PSAwICYmIHk+PSAwICYmIHggPCBtX3dpZHRoICYmIHkgPCBtX2hlaWdodDsgfQoJCUNUJiBhdChpbnQgeCwgaW50IHkpIHsgcmV0dXJuIG1fZGF0YVtPZmZzZXRPZih4LHkpXTsgfQoJCUNUIGF0KGludCB4LCBpbnQgeSkgY29uc3QgeyByZXR1cm4gbV9kYXRhW09mZnNldE9mKHgseSldOyB9CgoJCWludCBBYnMoaW50IHgpIHsgcmV0dXJuIHggPCAwID8gLXggOiB4OyB9CgoJCXZvaWQgUG9seShjb25zdCBwb2ludCYgcGZpcnN0LCBDVCB2YWx1ZSwgY29uc3QgcG9pbnQmIHBsYXN0KSB7CgkJCUxpbmUocGxhc3QsIHBmaXJzdCwgdmFsdWUpOwoJCX0KCQl0ZW1wbGF0ZSA8dHlwZW5hbWUgLi4uVHM+CgkJdm9pZCBQb2x5KGNvbnN0IHBvaW50JiBwZmlyc3QsIENUIHZhbHVlLCBjb25zdCBwb2ludCYgcDAsIGNvbnN0IHBvaW50JiBwMSwgVHMuLi5hcmdzKSB7CgkJCUxpbmUocDAsIHAxLCB2YWx1ZSk7CgkJCVBvbHkocGZpcnN0LCB2YWx1ZSwgcDEsIGFyZ3MuLi4pOwoJCX0KCXB1YmxpYzoKCQlUZXh0U3VyZmFjZShpbnQgd2lkdGg9MCwgaW50IGhlaWdodD0wKSA6IAoJCQltX3dpZHRoKGhlaWdodCA/IHdpZHRoIDogMCksIAoJCQltX2hlaWdodCh3aWR0aCA/IGhlaWdodCA6IDApLAoJCQltX2RhdGFfY291bnQod2lkdGggKiBoZWlnaHQpCgkJewoJCQltX2RhdGEgPSBtX2RhdGFfY291bnQgPyBuZXcgQ1RbbV9kYXRhX2NvdW50XSA6IG51bGxwdHI7CgkJCUNsZWFyKCk7CgkJfQoJCS8vIENhbm5vdCBjb3B5CgkJVGV4dFN1cmZhY2UoY29uc3QgVGV4dFN1cmZhY2UmKSA9ZGVsZXRlOwoJCVRleHRTdXJmYWNlJiBvcGVyYXRvciA9IChjb25zdCBUZXh0U3VyZmFjZSYpID1kZWxldGU7CgkJLy8gQ2FuIHJldHVybiBmcm9tIGZ1bmN0aW9ucwoJCVRleHRTdXJmYWNlJiBvcGVyYXRvciA9IChUZXh0U3VyZmFjZSYmIHNyYykgewoJCQlkZWxldGUgW10gbV9kYXRhOwoJCQltX3dpZHRoID0gc3JjLm1fd2lkdGg7IG1faGVpZ2h0ID0gc3JjLm1faGVpZ2h0OyBtX2RhdGFfY291bnQgPSBzcmMubV9kYXRhX2NvdW50OwoJCQltX2RhdGEgPSBzcmMubV9kYXRhOwoJCQlzcmMubV9kYXRhID0gbnVsbHB0cjsKCQkJcmV0dXJuICp0aGlzOwoJCX0KCQlUZXh0U3VyZmFjZShUZXh0U3VyZmFjZSYmIHNyYykgOiBtX2RhdGEobnVsbHB0cikgeyBvcGVyYXRvciA9ICgoVGV4dFN1cmZhY2UmJilzcmMpOyB9CgkJflRleHRTdXJmYWNlKCkgeyBkZWxldGUgW10gbV9kYXRhOyB9CgoJCWludCBXaWR0aCgpIGNvbnN0IHsgcmV0dXJuIG1fd2lkdGg7IH0KCQlpbnQgSGVpZ2h0KCkgY29uc3QgeyByZXR1cm4gbV9oZWlnaHQ7IH0KCQl2b2lkIENsZWFyKENUIHZhbHVlPScgJykgewoJCQlDVCogcCA9IG1fZGF0YTsKCQkJQ1QqIHBlID0gcCArIG1fZGF0YV9jb3VudDsKCQkJd2hpbGUocCAhPSBwZSkgKihwKyspID0gdmFsdWU7CgkJfQoJCXZvaWQgTGluZShpbnQgeDAsIGludCB5MCwgaW50IHgxLCBpbnQgeTEsIENUIHZhbHVlKSB7CgkJCWNvbnN0IGludCBkeCA9IHgxLXgwOwoJCQljb25zdCBpbnQgZHkgPSB5MS15MDsKCQkJaWYoIWR4ICYmICFkeSkgewoJCQkJaWYoSXNJbnNpZGUoeDAsIHkwKSkgeyBhdCh4MCwgeTApID0gdmFsdWU7IH0KCQkJCXJldHVybjsKCQkJfQoJCQljb25zdCBib29sIHltYWpvciA9IEFicyhkeSkgPiBBYnMoZHgpOwoJCQlpbnQgeD14MCwgeT15MDsKCQkJaW50ICZtaiA9IHltYWpvciA/IHkgOiB4OwoJCQlpbnQgJm1uID0geW1ham9yID8geCA6IHk7CgkJCWNvbnN0IGludCBtamUgPSB5bWFqb3IgPyB5MSA6IHgxOwoJCQljb25zdCBpbnQgbWpzdCA9IG1qIDwgbWplID8gMSA6IC0xOwoJCQlkb3VibGUgbW5kID0gbW47CgkJCWRvdWJsZSBtbnN0ID0geW1ham9yID8gZG91YmxlKGR4KS9BYnMoZHkpIDogZG91YmxlKGR5KS9BYnMoZHgpOwoJCQlkbyB7CgkJCQltbiA9IGludChtbmQgKyAwLjUpOwoJCQkJaWYoSXNJbnNpZGUoeCx5KSkgeyBhdCh4LHkpID0gdmFsdWU7IH0KCQkJCW1qICs9IG1qc3Q7CgkJCQltbmQgKz0gbW5zdDsKCQkJfSB3aGlsZShtaiAhPSBtamUrbWpzdCk7CgkJfQoJCXZvaWQgTGluZShjb25zdCBwb2ludCYgcDAsIGNvbnN0IHBvaW50JiBwMSwgQ1QgdmFsdWUpIHsgTGluZShwMC54LCBwMC55LCBwMS54LCBwMS55LCB2YWx1ZSk7IH0KCgkJdGVtcGxhdGUgPHR5cGVuYW1lIC4uLlRzPgoJCXZvaWQgUG9seShDVCB2YWx1ZSwgY29uc3QgcG9pbnQmIHAwLCBjb25zdCBwb2ludCYgcDEsIFRzLi4uYXJncykgewoJCQlMaW5lKHAwLCBwMSwgdmFsdWUpOwoJCQlQb2x5KHAwLCB2YWx1ZSwgcDEsIGFyZ3MuLi4pOwoJCX0KCQkvLyBpbml0LWxpc3Qgb3ZlcmxvYWRzIGZvciB0cmlhbmdsZSBhbmQgcXVhZCAoaW5pdGlhbGl6ZXJfbGlzdCBjYW4ndCBiZSBwYWNrZWQpCgkJdm9pZCBQb2x5KENUIHZhbHVlLCBpbml0aWFsaXplcl9saXN0IGwwLCBpbml0aWFsaXplcl9saXN0IGwxLCBpbml0aWFsaXplcl9saXN0IGwyKSB7IFBvbHkodmFsdWUsIHBvaW50KGwwKSwgcG9pbnQobDEpLCBwb2ludChsMikpOyB9CgkJdm9pZCBQb2x5KENUIHZhbHVlLCBpbml0aWFsaXplcl9saXN0IGwwLCBpbml0aWFsaXplcl9saXN0IGwxLCBpbml0aWFsaXplcl9saXN0IGwyLCBpbml0aWFsaXplcl9saXN0IGwzKSB7IFBvbHkodmFsdWUsIHBvaW50KGwwKSwgcG9pbnQobDEpLCBwb2ludChsMiksIHBvaW50KGwzKSk7IH0KCgkJdm9pZCBSZWN0KGludCB4LCBpbnQgeSwgaW50IHdpZHRoLCBpbnQgaGVpZ2h0LCBDVCB2YWx1ZSkgewoJCQlQb2x5KHZhbHVlLCBwb2ludCh4LHkpLCBwb2ludCh4K3dpZHRoLTEsIHkpLCBwb2ludCh4K3dpZHRoLTEsIHkraGVpZ2h0LTEpLCBwb2ludCh4LCB5K2hlaWdodC0xKSk7CgkJfQoJCS8vIExhYmVsIHBsYWNlcyB0ZXh0LiB4bG9jIHNlbGVjdHMgdGhlIG1lYW5pbmcgb2YgdGhlIHggY29vcmRpbmF0ZS4KCQkvLyBJdHMgdmFsdWUgaXMgYmV0d2VlbiAtMSBhbmQgMTogLTEgZm9yIHggYXQgdGhlIGxlZnQgb2YgdGhlIHRleHQsCgkJLy8gMCBmb3IgeCBpbiB0aGUgbWlkZGxlLCBhbmQgMSBmb3IgeCBhdCB0aGUgZW5kIG9mIHRoZSB0ZXh0LgoJCXZvaWQgTGFiZWwoY29uc3QgQ1QqIHRleHQsIGludCB4LCBpbnQgeSwgZG91YmxlIHhsb2M9LTEpIHsKCQkJaW50IGxlbiA9IDA7CgkJCXdoaWxlKHRleHRbbGVuXSkgeyArK2xlbjsgfQoJCQl4IC09IGludCgoeGxvYyArIDEpLzIgKiAobGVuIC0gMSkpOwoJCQlmb3IoaW50IGk9MDsgaTxsZW47ICsraSkgewoJCQkJaWYoSXNJbnNpZGUoeCx5KSkgeyBhdCh4LHkpID0gdGV4dFtpXTsgfQoJCQkJKyt4OwoJCX0JfQoJCXZvaWQgUHJlc2VudCgpIGNvbnN0IHsKCQkJY29uc3QgQ1QqIHAgPSBtX2RhdGE7IAoJCQlmb3IoaW50IGo9MDsgajxtX2hlaWdodDsgKytqKSB7CgkJCQlzdGQ6OmNvdXQud3JpdGUocCwgbV93aWR0aCk7CgkJCQlzdGQ6OmNvdXQgPDwgJ1xuJzsKCQkJCXAgKz0gbV93aWR0aDsKCQl9CX0KCX07CgoJdHlwZWRlZiBUZXh0U3VyZmFjZTxjaGFyPiBDaGFyU3VyZmFjZTsKCglpbnQgbWFpbigpIHsKCQlDaGFyU3VyZmFjZSBzdXJmKDYwLDIwKTsKCQlzdXJmLlBvbHkoJyonLCB7MjAsMn0sIHszNCwxNn0sIHsyMCwxNn0pOwoJCXN1cmYuTGFiZWwoIjE0IGZ0IiwgMTgsIDEwLCAxKTsKCQlzdXJmLkxhYmVsKCI5IGZ0IiwgMjYsIDE3LCAwKTsKCQlzdXJmLlByZXNlbnQoKTsKCX0=