| 
									
										
										
										
											2023-08-19 13:56:36 +02:00
										 |  |  | // Copyright 2021 Arthur Sonzogni. All rights reserved.
 | 
					
						
							|  |  |  | // Use of this source code is governed by the MIT license that can be found in
 | 
					
						
							|  |  |  | // the LICENSE file.
 | 
					
						
							| 
									
										
										
										
											2021-12-23 14:17:33 +01:00
										 |  |  | #ifndef FTXUI_DOM_CANVAS_HPP
 | 
					
						
							|  |  |  | #define FTXUI_DOM_CANVAS_HPP
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-31 02:17:43 +02:00
										 |  |  | #include <cstddef>        // for size_t
 | 
					
						
							| 
									
										
										
										
											2022-01-07 11:03:54 +01:00
										 |  |  | #include <functional>     // for function
 | 
					
						
							|  |  |  | #include <string>         // for string
 | 
					
						
							|  |  |  | #include <unordered_map>  // for unordered_map
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-28 15:17:54 +02:00
										 |  |  | #include "ftxui/screen/color.hpp"  // for Color
 | 
					
						
							|  |  |  | #include "ftxui/screen/image.hpp"  // for Pixel, Image
 | 
					
						
							| 
									
										
										
										
											2021-12-23 14:17:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-04 23:39:03 +02:00
										 |  |  | #ifdef DrawText
 | 
					
						
							|  |  |  | // Workaround for WinUsr.h (via Windows.h) defining macros that break things.
 | 
					
						
							|  |  |  | // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-drawtext
 | 
					
						
							|  |  |  | #undef DrawText
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-23 14:17:33 +01:00
										 |  |  | namespace ftxui { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-05 11:35:14 +02:00
										 |  |  | /// @brief Canvas is a drawable buffer associated with drawing operations.
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | /// Canvas is a drawable area that can be used to create complex graphics. It
 | 
					
						
							|  |  |  | /// supports drawing points, lines, circles, ellipses, text, and images using
 | 
					
						
							|  |  |  | /// braille, block, or normal characters.
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | /// Note: A terminal contains cells. A cells is a unit of:
 | 
					
						
							|  |  |  | /// - 2x4 braille characters (1x1 pixel)
 | 
					
						
							|  |  |  | /// - 2x2 block characters (2x2 pixels)
 | 
					
						
							|  |  |  | /// - 2x4 normal characters (2x4 pixels)
 | 
					
						
							| 
									
										
										
										
											2025-07-02 15:23:01 +02:00
										 |  |  | ///
 | 
					
						
							| 
									
										
										
										
											2025-06-05 11:35:14 +02:00
										 |  |  | /// You need to multiply the x coordinate by 2 and the y coordinate by 4 to
 | 
					
						
							|  |  |  | /// get the correct position in the terminal.
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | /// @ingroup dom
 | 
					
						
							| 
									
										
										
										
											2021-12-23 14:17:33 +01:00
										 |  |  | struct Canvas { | 
					
						
							|  |  |  |  public: | 
					
						
							| 
									
										
										
										
											2022-03-31 02:17:43 +02:00
										 |  |  |   Canvas() = default; | 
					
						
							| 
									
										
										
										
											2021-12-23 14:17:33 +01:00
										 |  |  |   Canvas(int width, int height); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Getters:
 | 
					
						
							|  |  |  |   int width() const { return width_; } | 
					
						
							|  |  |  |   int height() const { return height_; } | 
					
						
							|  |  |  |   Pixel GetPixel(int x, int y) const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   using Stylizer = std::function<void(Pixel&)>; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Draws using braille characters --------------------------------------------
 | 
					
						
							|  |  |  |   void DrawPointOn(int x, int y); | 
					
						
							|  |  |  |   void DrawPointOff(int x, int y); | 
					
						
							|  |  |  |   void DrawPointToggle(int x, int y); | 
					
						
							|  |  |  |   void DrawPoint(int x, int y, bool value); | 
					
						
							|  |  |  |   void DrawPoint(int x, int y, bool value, const Stylizer& s); | 
					
						
							|  |  |  |   void DrawPoint(int x, int y, bool value, const Color& color); | 
					
						
							|  |  |  |   void DrawPointLine(int x1, int y1, int x2, int y2); | 
					
						
							|  |  |  |   void DrawPointLine(int x1, int y1, int x2, int y2, const Stylizer& s); | 
					
						
							|  |  |  |   void DrawPointLine(int x1, int y1, int x2, int y2, const Color& color); | 
					
						
							|  |  |  |   void DrawPointCircle(int x, int y, int radius); | 
					
						
							|  |  |  |   void DrawPointCircle(int x, int y, int radius, const Stylizer& s); | 
					
						
							|  |  |  |   void DrawPointCircle(int x, int y, int radius, const Color& color); | 
					
						
							|  |  |  |   void DrawPointCircleFilled(int x, int y, int radius); | 
					
						
							| 
									
										
										
										
											2022-01-07 11:03:54 +01:00
										 |  |  |   void DrawPointCircleFilled(int x, int y, int radius, const Stylizer& s); | 
					
						
							| 
									
										
										
										
											2021-12-23 14:17:33 +01:00
										 |  |  |   void DrawPointCircleFilled(int x, int y, int radius, const Color& color); | 
					
						
							|  |  |  |   void DrawPointEllipse(int x, int y, int r1, int r2); | 
					
						
							|  |  |  |   void DrawPointEllipse(int x, int y, int r1, int r2, const Color& color); | 
					
						
							|  |  |  |   void DrawPointEllipse(int x, int y, int r1, int r2, const Stylizer& s); | 
					
						
							|  |  |  |   void DrawPointEllipseFilled(int x, int y, int r1, int r2); | 
					
						
							| 
									
										
										
										
											2022-01-07 11:03:54 +01:00
										 |  |  |   void DrawPointEllipseFilled(int x, int y, int r1, int r2, const Color& color); | 
					
						
							|  |  |  |   void DrawPointEllipseFilled(int x, int y, int r1, int r2, const Stylizer& s); | 
					
						
							| 
									
										
										
										
											2021-12-23 14:17:33 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Draw using box characters -------------------------------------------------
 | 
					
						
							|  |  |  |   // Block are of size 1x2. y is considered to be a multiple of 2.
 | 
					
						
							|  |  |  |   void DrawBlockOn(int x, int y); | 
					
						
							|  |  |  |   void DrawBlockOff(int x, int y); | 
					
						
							|  |  |  |   void DrawBlockToggle(int x, int y); | 
					
						
							|  |  |  |   void DrawBlock(int x, int y, bool value); | 
					
						
							|  |  |  |   void DrawBlock(int x, int y, bool value, const Stylizer& s); | 
					
						
							|  |  |  |   void DrawBlock(int x, int y, bool value, const Color& color); | 
					
						
							|  |  |  |   void DrawBlockLine(int x1, int y1, int x2, int y2); | 
					
						
							|  |  |  |   void DrawBlockLine(int x1, int y1, int x2, int y2, const Stylizer& s); | 
					
						
							|  |  |  |   void DrawBlockLine(int x1, int y1, int x2, int y2, const Color& color); | 
					
						
							|  |  |  |   void DrawBlockCircle(int x1, int y1, int radius); | 
					
						
							|  |  |  |   void DrawBlockCircle(int x1, int y1, int radius, const Stylizer& s); | 
					
						
							|  |  |  |   void DrawBlockCircle(int x1, int y1, int radius, const Color& color); | 
					
						
							|  |  |  |   void DrawBlockCircleFilled(int x1, int y1, int radius); | 
					
						
							|  |  |  |   void DrawBlockCircleFilled(int x1, int y1, int radius, const Stylizer& s); | 
					
						
							|  |  |  |   void DrawBlockCircleFilled(int x1, int y1, int radius, const Color& color); | 
					
						
							|  |  |  |   void DrawBlockEllipse(int x1, int y1, int r1, int r2); | 
					
						
							|  |  |  |   void DrawBlockEllipse(int x1, int y1, int r1, int r2, const Stylizer& s); | 
					
						
							|  |  |  |   void DrawBlockEllipse(int x1, int y1, int r1, int r2, const Color& color); | 
					
						
							|  |  |  |   void DrawBlockEllipseFilled(int x1, int y1, int r1, int r2); | 
					
						
							|  |  |  |   void DrawBlockEllipseFilled(int x1, | 
					
						
							| 
									
										
										
										
											2022-01-07 11:03:54 +01:00
										 |  |  |                               int y1, | 
					
						
							|  |  |  |                               int r1, | 
					
						
							|  |  |  |                               int r2, | 
					
						
							|  |  |  |                               const Stylizer& s); | 
					
						
							| 
									
										
										
										
											2021-12-23 14:17:33 +01:00
										 |  |  |   void DrawBlockEllipseFilled(int x1, | 
					
						
							| 
									
										
										
										
											2022-01-07 11:03:54 +01:00
										 |  |  |                               int y1, | 
					
						
							|  |  |  |                               int r1, | 
					
						
							|  |  |  |                               int r2, | 
					
						
							|  |  |  |                               const Color& color); | 
					
						
							| 
									
										
										
										
											2021-12-23 14:17:33 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Draw using normal characters ----------------------------------------------
 | 
					
						
							|  |  |  |   // Draw using character of size 2x4 at position (x,y)
 | 
					
						
							|  |  |  |   // x is considered to be a multiple of 2.
 | 
					
						
							|  |  |  |   // y is considered to be a multiple of 4.
 | 
					
						
							|  |  |  |   void DrawText(int x, int y, const std::string& value); | 
					
						
							|  |  |  |   void DrawText(int x, int y, const std::string& value, const Color& color); | 
					
						
							| 
									
										
										
										
											2022-01-07 11:03:54 +01:00
										 |  |  |   void DrawText(int x, int y, const std::string& value, const Stylizer& style); | 
					
						
							| 
									
										
										
										
											2024-04-28 15:17:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-27 12:03:44 +03:00
										 |  |  |   // Draw using directly pixels or images --------------------------------------
 | 
					
						
							|  |  |  |   // x is considered to be a multiple of 2.
 | 
					
						
							|  |  |  |   // y is considered to be a multiple of 4.
 | 
					
						
							|  |  |  |   void DrawPixel(int x, int y, const Pixel&); | 
					
						
							|  |  |  |   void DrawImage(int x, int y, const Image&); | 
					
						
							| 
									
										
										
										
											2021-12-23 14:17:33 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Decorator:
 | 
					
						
							|  |  |  |   // x is considered to be a multiple of 2.
 | 
					
						
							|  |  |  |   // y is considered to be a multiple of 4.
 | 
					
						
							|  |  |  |   void Style(int x, int y, const Stylizer& style); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  private: | 
					
						
							|  |  |  |   bool IsIn(int x, int y) const { | 
					
						
							|  |  |  |     return x >= 0 && x < width_ && y >= 0 && y < height_; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2024-04-27 12:03:44 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-23 14:17:33 +01:00
										 |  |  |   enum CellType { | 
					
						
							| 
									
										
										
										
											2024-04-27 12:03:44 +03:00
										 |  |  |     kCell,     // Units of size 2x4
 | 
					
						
							|  |  |  |     kBlock,    // Units of size 2x2
 | 
					
						
							|  |  |  |     kBraille,  // Units of size 1x1
 | 
					
						
							| 
									
										
										
										
											2021-12-23 14:17:33 +01:00
										 |  |  |   }; | 
					
						
							| 
									
										
										
										
											2024-04-27 12:03:44 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-23 14:17:33 +01:00
										 |  |  |   struct Cell { | 
					
						
							| 
									
										
										
										
											2024-04-27 12:03:44 +03:00
										 |  |  |     CellType type = kCell; | 
					
						
							| 
									
										
										
										
											2021-12-23 14:17:33 +01:00
										 |  |  |     Pixel content; | 
					
						
							|  |  |  |   }; | 
					
						
							| 
									
										
										
										
											2024-04-27 12:03:44 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-23 14:17:33 +01:00
										 |  |  |   struct XY { | 
					
						
							|  |  |  |     int x; | 
					
						
							|  |  |  |     int y; | 
					
						
							|  |  |  |     bool operator==(const XY& other) const { | 
					
						
							|  |  |  |       return x == other.x && y == other.y; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   struct XYHash { | 
					
						
							| 
									
										
										
										
											2022-01-07 11:03:54 +01:00
										 |  |  |     size_t operator()(const XY& xy) const { | 
					
						
							| 
									
										
										
										
											2022-03-31 02:17:43 +02:00
										 |  |  |       constexpr size_t shift = 1024; | 
					
						
							|  |  |  |       return size_t(xy.x) * shift + size_t(xy.y); | 
					
						
							| 
									
										
										
										
											2022-01-07 11:03:54 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-23 14:17:33 +01:00
										 |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   int width_ = 0; | 
					
						
							|  |  |  |   int height_ = 0; | 
					
						
							|  |  |  |   std::unordered_map<XY, Cell, XYHash> storage_; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }  // namespace ftxui
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-07 11:03:54 +01:00
										 |  |  | #endif  // FTXUI_DOM_CANVAS_HPP
 |