/* PIP - Platform Independent Primitives Console output/input Copyright (C) 2019 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 . */ #include "piscreendrawer.h" using namespace PIScreenTypes; PIScreenDrawer::PIScreenDrawer(PIVector > & 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 & 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 & 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 & 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 > & 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 & cv(cells[y0 + j]); PIVector & 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 > & 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 & 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; } } }