56 {0b00000000, 0b00000001},
57 {0b00000000, 0b00000010},
58 {0b00000000, 0b00000100},
59 {0b00000001, 0b00000000},
62 {0b00000000, 0b00001000},
63 {0b00000000, 0b00010000},
64 {0b00000000, 0b00100000},
65 {0b00000010, 0b00000000},
71 " ",
"▘",
"▖",
"▌",
"▝",
"▀",
"▞",
"▛",
72 "▗",
"▚",
"▄",
"▙",
"▐",
"▜",
"▟",
"█",
77 {
" ", 0b0000}, {
"▘", 0b0001}, {
"▖", 0b0010}, {
"▌", 0b0011},
78 {
"▝", 0b0100}, {
"▀", 0b0101}, {
"▞", 0b0110}, {
"▛", 0b0111},
79 {
"▗", 0b1000}, {
"▚", 0b1001}, {
"▄", 0b1010}, {
"▙", 0b1011},
80 {
"▐", 0b1100}, {
"▜", 0b1101}, {
"▟", 0b1110}, {
"█", 0b1111},
83constexpr auto nostyle = [](Pixel& ) {};
93 storage_(width_ * height_ / 8 ) {}
99 auto it = storage_.find(XY{x, y});
100 return (
it == storage_.end()) ?
Pixel() :
it->second.content;
141 Cell&
cell = storage_[XY{x / 2, y / 4}];
142 if (
cell.type != CellType::kBraille) {
143 cell.content.character =
"⠀";
144 cell.type = CellType::kBraille;
158 Cell&
cell = storage_[XY{x / 2, y / 4}];
159 if (
cell.type != CellType::kBraille) {
160 cell.content.character =
"⠀";
161 cell.type = CellType::kBraille;
176 Cell&
cell = storage_[XY{x / 2, y / 4}];
177 if (
cell.type != CellType::kBraille) {
178 cell.content.character =
"⠀";
179 cell.type = CellType::kBraille;
217 const int dx = std::abs(
x2 -
x1);
218 const int dy = std::abs(
y2 -
y1);
219 const int sx =
x1 <
x2 ? 1 : -1;
220 const int sy =
y1 <
y2 ? 1 : -1;
223 if (!IsIn(
x1,
y1) && !IsIn(
x2,
y2)) {
226 if (
dx +
dx > width_ * height_) {
231 for (
int i = 0; i <
length; ++i) {
343 int dx = (1 + 2 * x) *
e2 *
e2;
407 int dx = (1 + 2 * x) *
e2 *
e2;
473 Cell&
cell = storage_[XY{x / 2, y / 2}];
474 if (
cell.type != CellType::kBlock) {
475 cell.content.character =
" ";
476 cell.type = CellType::kBlock;
492 Cell&
cell = storage_[XY{x / 2, y / 4}];
493 if (
cell.type != CellType::kBlock) {
494 cell.content.character =
" ";
495 cell.type = CellType::kBlock;
501 value &= ~(1U <<
bit);
513 Cell&
cell = storage_[XY{x / 2, y / 4}];
514 if (
cell.type != CellType::kBlock) {
515 cell.content.character =
" ";
516 cell.type = CellType::kBlock;
560 const int dx = std::abs(
x2 -
x1);
561 const int dy = std::abs(
y2 -
y1);
562 const int sx =
x1 <
x2 ? 1 : -1;
563 const int sy =
y1 <
y2 ? 1 : -1;
566 if (!IsIn(
x1,
y1) && !IsIn(
x2,
y2)) {
569 if (
dx +
dx > width_ * height_) {
574 for (
int i = 0; i <
length; ++i) {
688 int dx = (1 + 2 * x) *
e2 *
e2;
754 int dx = (1 + 2 * x) *
e2 *
e2;
796 const std::string& value,
808 const std::string& value,
815 Cell&
cell = storage_[XY{x / 2, y / 4}];
816 cell.type = CellType::kCell;
817 cell.content.character =
it;
828 Cell&
cell = storage_[XY{x / 2, y / 4}];
829 cell.type = CellType::kCell;
842 const int dx_begin = std::max(0, -x);
843 const int dy_begin = std::max(0, -y);
844 const int dx_end = std::min(
image.dimx(), width_ - x);
845 const int dy_end = std::min(
image.dimy(), height_ - y);
849 Cell&
cell = storage_[XY{
853 cell.type = CellType::kCell;
863 style(storage_[XY{x / 2, y / 4}].content);
869class CanvasNodeBase :
public Node {
871 CanvasNodeBase() =
default;
875 const int y_max = std::min(c.
height() / 4, box_.y_max - box_.y_min + 1);
876 const int x_max = std::min(c.
width() / 2, box_.x_max - box_.x_min + 1);
877 for (
int y = 0; y < y_max; ++y) {
878 for (
int x = 0; x < x_max; ++x) {
879 screen.PixelAt(box_.x_min + x, box_.y_min + y) = c.
GetPixel(x, y);
884 virtual const Canvas&
canvas() = 0;
892 class Impl :
public CanvasNodeBase {
895 requirement_.min_x = (
canvas_->width() + 1) / 2;
896 requirement_.min_y = (
canvas_->height() + 3) / 4;
901 return std::make_shared<Impl>(
canvas);
909 class Impl :
public CanvasNodeBase {
911 Impl(
int width,
int height, std::function<
void(
Canvas&)>
fn)
912 : width_(width), height_(height),
fn_(std::move(
fn)) {}
914 void ComputeRequirement()
final {
915 requirement_.min_x = (width_ + 1) / 2;
916 requirement_.min_y = (height_ + 3) / 4;
920 const int width = (box_.x_max - box_.x_min + 1) * 2;
921 const int height = (box_.y_max - box_.y_min + 1) * 4;
924 CanvasNodeBase::Render(
screen);
933 return std::make_shared<Impl>(width, height, std::move(
fn));
A class representing terminal colors.
An adapter. Own or reference an immutable object.
A rectangular grid of Pixel.
A rectangular grid of Pixel.
std::shared_ptr< Node > Element
std::shared_ptr< T > Make(Args &&... args)
std::vector< std::string > Utf8ToGlyphs(const std::string &input)
Element canvas(ConstRef< Canvas >)
Produce an element from a Canvas, or a reference to a Canvas.
void Render(Screen &screen, const Element &element)
Display an element on a ftxui::Screen.
Decorator color(Color)
Decorate using a foreground color.
void DrawImage(int x, int y, const Image &)
Draw a predefined image, with top-left corner at the given coordinate You can supply negative coordin...
void DrawBlockLine(int x1, int y1, int x2, int y2)
Draw a line made of block characters.
void DrawPointEllipseFilled(int x, int y, int r1, int r2)
Draw a filled ellipse made of braille dots.
void DrawPointLine(int x1, int y1, int x2, int y2)
Draw a line made of braille dots.
void DrawText(int x, int y, const std::string &value)
Draw a piece of text.
std::function< void(Pixel &)> Stylizer
void DrawBlockOn(int x, int y)
Draw a block.
void DrawPointCircleFilled(int x, int y, int radius)
Draw a filled circle made of braille dots.
void DrawPointOn(int x, int y)
Draw a braille dot.
void DrawPointOff(int x, int y)
Erase a braille dot.
Pixel GetPixel(int x, int y) const
Get the content of a cell.
void DrawBlockEllipseFilled(int x1, int y1, int r1, int r2)
Draw a filled ellipse made of block characters.
void DrawPointEllipse(int x, int y, int r1, int r2)
Draw an ellipse made of braille dots.
void DrawPoint(int x, int y, bool value)
Draw a braille dot.
void DrawBlockEllipse(int x1, int y1, int r1, int r2)
Draw an ellipse made of block characters.
void DrawBlockToggle(int x, int y)
Toggle a block. If it is filled, it will be erased. If it is empty, it will be filled.
void DrawBlockCircle(int x1, int y1, int radius)
Draw a circle made of block characters.
void DrawBlockCircleFilled(int x1, int y1, int radius)
Draw a filled circle made of block characters.
void DrawPointCircle(int x, int y, int radius)
Draw a circle made of braille dots.
void DrawBlockOff(int x, int y)
Erase a block.
void DrawBlock(int x, int y, bool value)
Draw a block.
void Style(int x, int y, const Stylizer &style)
Modify a pixel at a given location.
void DrawPointToggle(int x, int y)
Toggle a braille dot. A filled one will be erased, and the other will be drawn.
void DrawPixel(int x, int y, const Pixel &)
Directly draw a predefined pixel at the given coordinate.
A Unicode character and its associated style.