270 lines
7.3 KiB
C++
270 lines
7.3 KiB
C++
/*
|
|
PIP - Platform Independent Primitives
|
|
Console output/input
|
|
Copyright (C) 2017 Ivan Pelipenko peri4ko@yandex.ru
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "piscreendrawer.h"
|
|
|
|
|
|
using namespace PIScreenTypes;
|
|
|
|
|
|
PIScreenDrawer::PIScreenDrawer(PIVector<PIVector<Cell> > & c): cells(c) {
|
|
arts_[LineVertical] =
|
|
#ifdef PIP_ICU
|
|
PIChar::fromUTF8("│");
|
|
#else
|
|
PIChar('|');
|
|
#endif
|
|
|
|
arts_[LineHorizontal] =
|
|
#ifdef PIP_ICU
|
|
PIChar::fromUTF8("─");
|
|
#else
|
|
PIChar('-');
|
|
#endif
|
|
|
|
arts_[Cross] =
|
|
#ifdef PIP_ICU
|
|
PIChar::fromUTF8("┼");
|
|
#else
|
|
PIChar('+');
|
|
#endif
|
|
|
|
arts_[CornerTopLeft] =
|
|
#ifdef PIP_ICU
|
|
PIChar::fromUTF8("┌");
|
|
#else
|
|
PIChar('+');
|
|
#endif
|
|
|
|
arts_[CornerTopRight] =
|
|
#ifdef PIP_ICU
|
|
PIChar::fromUTF8("┐");
|
|
#else
|
|
PIChar('+');
|
|
#endif
|
|
|
|
arts_[CornerBottomLeft] =
|
|
#ifdef PIP_ICU
|
|
PIChar::fromUTF8("└");
|
|
#else
|
|
PIChar('+');
|
|
#endif
|
|
|
|
arts_[CornerBottomRight] =
|
|
#ifdef PIP_ICU
|
|
PIChar::fromUTF8("┘");
|
|
#else
|
|
PIChar('+');
|
|
#endif
|
|
|
|
arts_[Unchecked] =
|
|
#ifdef PIP_ICU
|
|
PIChar::fromUTF8("☐");
|
|
#else
|
|
PIChar('O');
|
|
#endif
|
|
|
|
arts_[Checked] =
|
|
#ifdef PIP_ICU
|
|
PIChar::fromUTF8("☑");
|
|
#else
|
|
PIChar('0');
|
|
#endif
|
|
}
|
|
|
|
|
|
void PIScreenDrawer::clear() {
|
|
clear(cells);
|
|
}
|
|
|
|
|
|
void PIScreenDrawer::drawPixel(int x, int y, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) {
|
|
if (x < 0 || x >= width || y < 0 || y >= height) return;
|
|
cells[y][x].symbol = c;
|
|
cells[y][x].format.color_char = col_char;
|
|
cells[y][x].format.color_back = col_back;
|
|
cells[y][x].format.flags = flags_char;
|
|
}
|
|
|
|
|
|
void PIScreenDrawer::drawLine(int x0, int y0, int x1, int y1, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) {
|
|
if (x0 == x1 && y0 == y1) drawPixel(x0, y0, c, col_char, col_back, flags_char);
|
|
Cell cc;
|
|
cc.symbol = c;
|
|
cc.format.color_char = col_char;
|
|
cc.format.color_back = col_back;
|
|
cc.format.flags = flags_char;
|
|
int x = 0, y = 0;
|
|
if (piAbsi(x1 - x0) >= piAbsi(y1 - y0)) {
|
|
float dy = (y1 - y0) / float(piAbsi(x1 - x0)), cy = y0;
|
|
int dx = x0 < x1 ? 1 : -1;
|
|
for (int i = x0; i != x1; i += dx) {
|
|
x = i; y = piRound(cy);
|
|
if (x >= 0 && x < width && y >= 0 && y < height)
|
|
cells[y][x] = cc;
|
|
cy += dy;
|
|
}
|
|
y = piRound(cy);
|
|
if (x1 >= 0 && x1 < width && y >= 0 && y < height)
|
|
cells[y][x1] = cc;
|
|
} else {
|
|
float dx = (x1 - x0) / float(piAbsi(y1 - y0)), cx = x0;
|
|
int dy = y0 < y1 ? 1 : -1;
|
|
for (int i = y0; i != y1; i += dy) {
|
|
x = piRound(cx); y = i;
|
|
if (x >= 0 && x < width && y >= 0 && y < height)
|
|
cells[y][x] = cc;
|
|
cx += dx;
|
|
}
|
|
x = piRound(cx);
|
|
if (x >= 0 && x < width && y1 >= 0 && y1 < height)
|
|
cells[y1][x] = cc;
|
|
}
|
|
}
|
|
|
|
|
|
void PIScreenDrawer::drawRect(int x0, int y0, int x1, int y1, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) {
|
|
if (x0 == x1 && y0 == y1) drawPixel(x0, y0, c, col_char, col_back, flags_char);
|
|
Cell cc;
|
|
cc.symbol = c;
|
|
cc.format.color_char = col_char;
|
|
cc.format.color_back = col_back;
|
|
cc.format.flags = flags_char;
|
|
int dx = x0 < x1 ? 1 : -1;
|
|
int dy = y0 < y1 ? 1 : -1;
|
|
int xs[2] = {x0, x1};
|
|
int ys[2] = {y0, y1};
|
|
for (int k = 0; k < 2; ++k) {
|
|
int j = ys[k];
|
|
if (j >= 0 && j < height) {
|
|
PIVector<Cell> & cv(cells[j]);
|
|
for (int i = x0; i != x1; i += dx)
|
|
if (i >= 0 && i < width)
|
|
cv[i] = cc;
|
|
}
|
|
j = xs[k];
|
|
if (j >= 0 && j < width) {
|
|
for (int i = y0; i != y1; i += dy)
|
|
if (i >= 0 && i < height)
|
|
cells[i][j] = cc;
|
|
}
|
|
}
|
|
int i = x1, j = y1;
|
|
if (i >= 0 && i < width && j >= 0 && j < height)
|
|
cells[j][i] = cc;
|
|
}
|
|
|
|
|
|
void PIScreenDrawer::drawFrame(int x0, int y0, int x1, int y1, Color col_char, Color col_back, CharFlags flags_char) {
|
|
if (x0 == x1 && y0 == y1) return;
|
|
Cell cc;
|
|
cc.format.color_char = col_char;
|
|
cc.format.color_back = col_back;
|
|
cc.format.flags = flags_char;
|
|
int dx = x0 < x1 ? 1 : -1;
|
|
int dy = y0 < y1 ? 1 : -1;
|
|
int xs[2] = {x0, x1};
|
|
int ys[2] = {y0, y1};
|
|
for (int k = 0; k < 2; ++k) {
|
|
int j = ys[k];
|
|
if (j >= 0 && j < height) {
|
|
PIVector<Cell> & cv(cells[j]);
|
|
cc.symbol = artChar(LineHorizontal);
|
|
for (int i = x0 + 1; i != x1; i += dx)
|
|
if (i >= 0 && i < width)
|
|
cv[i] = cc;
|
|
}
|
|
j = xs[k];
|
|
if (j >= 0 && j < width) {
|
|
cc.symbol = artChar(LineVertical);
|
|
for (int i = y0 + 1; i != y1; i += dy)
|
|
if (i >= 0 && i < height)
|
|
cells[i][j] = cc;
|
|
}
|
|
}
|
|
int i = x0, j = y0; cc.symbol = artChar(CornerTopLeft);
|
|
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
|
|
i = x1, j = y0; cc.symbol = artChar(CornerTopRight);
|
|
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
|
|
i = x0, j = y1; cc.symbol = artChar(CornerBottomLeft);
|
|
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
|
|
i = x1, j = y1; cc.symbol = artChar(CornerBottomRight);
|
|
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
|
|
}
|
|
|
|
|
|
void PIScreenDrawer::fillRect(int x0, int y0, int x1, int y1, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) {
|
|
if (x0 == x1 && y0 == y1) drawPixel(x0, y0, c, col_char, col_back, flags_char);
|
|
Cell cc;
|
|
cc.symbol = c;
|
|
cc.format.color_char = col_char;
|
|
cc.format.color_back = col_back;
|
|
cc.format.flags = flags_char;
|
|
int dx = x0 < x1 ? 1 : -1;
|
|
int dy = y0 < y1 ? 1 : -1;
|
|
for (int j = y0; j != y1; j += dy)
|
|
if (j >= 0 && j < height) {
|
|
PIVector<Cell> & cv(cells[j]);
|
|
for (int i = x0; i != x1; i += dx)
|
|
if (i >= 0 && i < width)
|
|
cv[i] = cc;
|
|
}
|
|
}
|
|
|
|
|
|
void PIScreenDrawer::fillRect(int x0, int y0, int x1, int y1, PIVector<PIVector<Cell> > & content) {
|
|
if (x0 > x1) piSwap(x0, x1);
|
|
if (y0 > y1) piSwap(y0, y1);
|
|
int w = x1 - x0;
|
|
int h = y1 - y0;
|
|
for (int j = 0; j < h; ++j)
|
|
if (j < piMini(height, content.size_s())) {
|
|
if ((j + y0) >= 0 && (j + y0) < height) {
|
|
PIVector<Cell> & cv(cells[y0 + j]);
|
|
PIVector<Cell> & contv(content[j]);
|
|
for (int i = 0; i < piMini(w, contv.size_s()); ++i)
|
|
if ((i + x0) >= 0 && (i + x0) < width)
|
|
cv[x0 + i] = contv[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void PIScreenDrawer::clear(PIVector<PIVector<Cell> > & cells) {
|
|
for (int i = 0; i < cells.size_s(); ++i)
|
|
cells[i].fill(Cell());
|
|
}
|
|
|
|
|
|
void PIScreenDrawer::drawText(int x, int y, const PIString & s, Color col_char, Color col_back, CharFlags flags_char) {
|
|
if (x < 0 || x >= width || y < 0 || y >= height) return;
|
|
PIVector<Cell> & cv(cells[y]);
|
|
Cell cc;
|
|
cc.format.color_char = col_char;
|
|
cc.format.color_back = col_back;
|
|
cc.format.flags = flags_char;
|
|
for (int i = 0; i < s.size_s(); ++i) {
|
|
int j = i + x;
|
|
if (j >= 0 && j < width) {
|
|
cc.symbol = s[i];
|
|
cv[j] = cc;
|
|
}
|
|
}
|
|
}
|