mirror of
				https://github.com/ArthurSonzogni/FTXUI.git
				synced 2025-10-31 10:38:09 +08:00 
			
		
		
		
	Separate a reusable Image class from Screen (#834)
Co-authored-by: ArthurSonzogni <sonzogniarthur@gmail.com>
This commit is contained in:
		 Dimo Markov
					Dimo Markov
				
			
				
					committed by
					
						 ArthurSonzogni
						ArthurSonzogni
					
				
			
			
				
	
			
			
			 ArthurSonzogni
						ArthurSonzogni
					
				
			
						parent
						
							57ebf6c8c1
						
					
				
				
					commit
					a006bcafe1
				
			
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -3,6 +3,10 @@ | |||||||
| * | * | ||||||
| !*/ | !*/ | ||||||
|  |  | ||||||
|  | # Ignore build directories generated by default MSVC CMake integration | ||||||
|  | # (otherwise causes terribly slow indexing) | ||||||
|  | out/ | ||||||
|  |  | ||||||
| # Allowed top-level files: | # Allowed top-level files: | ||||||
| !.clang-format | !.clang-format | ||||||
| !.clang-tidy | !.clang-tidy | ||||||
|   | |||||||
| @@ -32,6 +32,9 @@ current (development) | |||||||
|   reflecting the current scroll position. Proposed by @ibrahimnasson in |   reflecting the current scroll position. Proposed by @ibrahimnasson in | ||||||
|   [issue 752](https://github.com/ArthurSonzogni/FTXUI/issues/752) |   [issue 752](https://github.com/ArthurSonzogni/FTXUI/issues/752) | ||||||
|  |  | ||||||
|  | ### Screen | ||||||
|  | - Feature: Add `Box::IsEmpty()`. | ||||||
|  |  | ||||||
| ### Build | ### Build | ||||||
| - Support for cmake's "unity/jumbo" builds. Fixed by @ClausKlein. | - Support for cmake's "unity/jumbo" builds. Fixed by @ClausKlein. | ||||||
|  |  | ||||||
|   | |||||||
| @@ -33,11 +33,14 @@ add_library(screen | |||||||
|   include/ftxui/screen/box.hpp |   include/ftxui/screen/box.hpp | ||||||
|   include/ftxui/screen/color.hpp |   include/ftxui/screen/color.hpp | ||||||
|   include/ftxui/screen/color_info.hpp |   include/ftxui/screen/color_info.hpp | ||||||
|  |   include/ftxui/screen/image.hpp | ||||||
|  |   include/ftxui/screen/pixel.hpp | ||||||
|   include/ftxui/screen/screen.hpp |   include/ftxui/screen/screen.hpp | ||||||
|   include/ftxui/screen/string.hpp |   include/ftxui/screen/string.hpp | ||||||
|   src/ftxui/screen/box.cpp |   src/ftxui/screen/box.cpp | ||||||
|   src/ftxui/screen/color.cpp |   src/ftxui/screen/color.cpp | ||||||
|   src/ftxui/screen/color_info.cpp |   src/ftxui/screen/color_info.cpp | ||||||
|  |   src/ftxui/screen/image.cpp | ||||||
|   src/ftxui/screen/screen.cpp |   src/ftxui/screen/screen.cpp | ||||||
|   src/ftxui/screen/string.cpp |   src/ftxui/screen/string.cpp | ||||||
|   src/ftxui/screen/terminal.cpp |   src/ftxui/screen/terminal.cpp | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ | |||||||
| #include <unordered_map>  // for unordered_map | #include <unordered_map>  // for unordered_map | ||||||
|  |  | ||||||
| #include "ftxui/screen/color.hpp"   // for Color | #include "ftxui/screen/color.hpp"   // for Color | ||||||
| #include "ftxui/screen/screen.hpp"  // for Pixel | #include "ftxui/screen/image.hpp"   // for Pixel, Image | ||||||
|  |  | ||||||
| #ifdef DrawText | #ifdef DrawText | ||||||
| // Workaround for WinUsr.h (via Windows.h) defining macros that break things. | // Workaround for WinUsr.h (via Windows.h) defining macros that break things. | ||||||
| @@ -94,6 +94,12 @@ struct Canvas { | |||||||
|   void DrawText(int x, int y, const std::string& value); |   void DrawText(int x, int y, const std::string& value); | ||||||
|   void DrawText(int x, int y, const std::string& value, const Color& color); |   void DrawText(int x, int y, const std::string& value, const Color& color); | ||||||
|   void DrawText(int x, int y, const std::string& value, const Stylizer& style); |   void DrawText(int x, int y, const std::string& value, const Stylizer& style); | ||||||
|  |    | ||||||
|  |   // 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&); | ||||||
|  |  | ||||||
|   // Decorator: |   // Decorator: | ||||||
|   // x is considered to be a multiple of 2. |   // x is considered to be a multiple of 2. | ||||||
| @@ -104,15 +110,18 @@ struct Canvas { | |||||||
|   bool IsIn(int x, int y) const { |   bool IsIn(int x, int y) const { | ||||||
|     return x >= 0 && x < width_ && y >= 0 && y < height_; |     return x >= 0 && x < width_ && y >= 0 && y < height_; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   enum CellType { |   enum CellType { | ||||||
|     kBraille, |     kCell,     // Units of size 2x4 | ||||||
|     kBlock, |     kBlock,    // Units of size 2x2 | ||||||
|     kText, |     kBraille,  // Units of size 1x1 | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   struct Cell { |   struct Cell { | ||||||
|     CellType type = kText; |     CellType type = kCell; | ||||||
|     Pixel content; |     Pixel content; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   struct XY { |   struct XY { | ||||||
|     int x; |     int x; | ||||||
|     int y; |     int y; | ||||||
|   | |||||||
| @@ -15,6 +15,7 @@ struct Box { | |||||||
|   static auto Intersection(Box a, Box b) -> Box; |   static auto Intersection(Box a, Box b) -> Box; | ||||||
|   static auto Union(Box a, Box b) -> Box; |   static auto Union(Box a, Box b) -> Box; | ||||||
|   bool Contain(int x, int y) const; |   bool Contain(int x, int y) const; | ||||||
|  |   bool IsEmpty(); | ||||||
|   bool operator==(const Box& other) const; |   bool operator==(const Box& other) const; | ||||||
|   bool operator!=(const Box& other) const; |   bool operator!=(const Box& other) const; | ||||||
| }; | }; | ||||||
|   | |||||||
							
								
								
									
										50
									
								
								include/ftxui/screen/image.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								include/ftxui/screen/image.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | |||||||
|  | // Copyright 2024 Arthur Sonzogni. All rights reserved. | ||||||
|  | // Use of this source code is governed by the MIT license that can be found in | ||||||
|  | // the LICENSE file. | ||||||
|  | #ifndef FTXUI_SCREEN_IMAGE_HPP | ||||||
|  | #define FTXUI_SCREEN_IMAGE_HPP | ||||||
|  |  | ||||||
|  | #include <cstdint>  // for uint8_t | ||||||
|  | #include <memory> | ||||||
|  | #include <string>  // for string, basic_string, allocator | ||||||
|  | #include <vector>  // for vector | ||||||
|  |  | ||||||
|  | #include "ftxui/screen/box.hpp"    // for Box | ||||||
|  | #include "ftxui/screen/pixel.hpp"  // for Pixel | ||||||
|  |  | ||||||
|  | namespace ftxui { | ||||||
|  |  | ||||||
|  | /// @brief A rectangular grid of Pixel. | ||||||
|  | /// @ingroup screen | ||||||
|  | class Image { | ||||||
|  |  public: | ||||||
|  |   // Constructors: | ||||||
|  |   Image() = delete; | ||||||
|  |   Image(int dimx, int dimy); | ||||||
|  |  | ||||||
|  |   // Access a character in the grid at a given position. | ||||||
|  |   std::string& at(int x, int y); | ||||||
|  |   const std::string& at(int x, int y) const; | ||||||
|  |  | ||||||
|  |   // Access a cell (Pixel) in the grid at a given position. | ||||||
|  |   Pixel& PixelAt(int x, int y); | ||||||
|  |   const Pixel& PixelAt(int x, int y) const; | ||||||
|  |  | ||||||
|  |   // Get screen dimensions. | ||||||
|  |   int dimx() const { return dimx_; } | ||||||
|  |   int dimy() const { return dimy_; } | ||||||
|  |  | ||||||
|  |   // Fill the image with space and default style | ||||||
|  |   void Clear(); | ||||||
|  |  | ||||||
|  |   Box stencil; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   int dimx_; | ||||||
|  |   int dimy_; | ||||||
|  |   std::vector<std::vector<Pixel>> pixels_; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace ftxui | ||||||
|  |  | ||||||
|  | #endif  // FTXUI_SCREEN_IMAGE_HPP | ||||||
							
								
								
									
										48
									
								
								include/ftxui/screen/pixel.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								include/ftxui/screen/pixel.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | |||||||
|  | // Copyright 2024 Arthur Sonzogni. All rights reserved. | ||||||
|  | // Use of this source code is governed by the MIT license that can be found in | ||||||
|  | // the LICENSE file. | ||||||
|  |  | ||||||
|  | #include <cstdint>                 // for uint8_t | ||||||
|  | #include <string>                  // for string, basic_string, allocator | ||||||
|  | #include "ftxui/screen/color.hpp"  // for Color, Color::Default | ||||||
|  |  | ||||||
|  | namespace ftxui { | ||||||
|  |  | ||||||
|  | /// @brief A Unicode character and its associated style. | ||||||
|  | /// @ingroup screen | ||||||
|  | struct Pixel { | ||||||
|  |   Pixel() | ||||||
|  |       : blink(false), | ||||||
|  |         bold(false), | ||||||
|  |         dim(false), | ||||||
|  |         inverted(false), | ||||||
|  |         underlined(false), | ||||||
|  |         underlined_double(false), | ||||||
|  |         strikethrough(false), | ||||||
|  |         automerge(false) {} | ||||||
|  |  | ||||||
|  |   // A bit field representing the style: | ||||||
|  |   bool blink : 1; | ||||||
|  |   bool bold : 1; | ||||||
|  |   bool dim : 1; | ||||||
|  |   bool inverted : 1; | ||||||
|  |   bool underlined : 1; | ||||||
|  |   bool underlined_double : 1; | ||||||
|  |   bool strikethrough : 1; | ||||||
|  |   bool automerge : 1; | ||||||
|  |  | ||||||
|  |   // The hyperlink associated with the pixel. | ||||||
|  |   // 0 is the default value, meaning no hyperlink. | ||||||
|  |   // It's an index for accessing Screen meta data | ||||||
|  |   uint8_t hyperlink = 0; | ||||||
|  |  | ||||||
|  |   // The graphemes stored into the pixel. To support combining characters, | ||||||
|  |   // like: a?, this can potentially contain multiple codepoints. | ||||||
|  |   std::string character = " "; | ||||||
|  |  | ||||||
|  |   // Colors: | ||||||
|  |   Color background_color = Color::Default; | ||||||
|  |   Color foreground_color = Color::Default; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace ftxui | ||||||
| @@ -9,48 +9,12 @@ | |||||||
| #include <string>  // for string, basic_string, allocator | #include <string>  // for string, basic_string, allocator | ||||||
| #include <vector>  // for vector | #include <vector>  // for vector | ||||||
|  |  | ||||||
| #include "ftxui/screen/box.hpp"       // for Box |  | ||||||
| #include "ftxui/screen/color.hpp"     // for Color, Color::Default | #include "ftxui/screen/color.hpp"     // for Color, Color::Default | ||||||
|  | #include "ftxui/screen/image.hpp"     // for Pixel, Image | ||||||
| #include "ftxui/screen/terminal.hpp"  // for Dimensions | #include "ftxui/screen/terminal.hpp"  // for Dimensions | ||||||
|  |  | ||||||
| namespace ftxui { | namespace ftxui { | ||||||
|  |  | ||||||
| /// @brief A unicode character and its associated style. |  | ||||||
| /// @ingroup screen |  | ||||||
| struct Pixel { |  | ||||||
|   Pixel() |  | ||||||
|       : blink(false), |  | ||||||
|         bold(false), |  | ||||||
|         dim(false), |  | ||||||
|         inverted(false), |  | ||||||
|         underlined(false), |  | ||||||
|         underlined_double(false), |  | ||||||
|         strikethrough(false), |  | ||||||
|         automerge(false) {} |  | ||||||
|  |  | ||||||
|   // A bit field representing the style: |  | ||||||
|   bool blink : 1; |  | ||||||
|   bool bold : 1; |  | ||||||
|   bool dim : 1; |  | ||||||
|   bool inverted : 1; |  | ||||||
|   bool underlined : 1; |  | ||||||
|   bool underlined_double : 1; |  | ||||||
|   bool strikethrough : 1; |  | ||||||
|   bool automerge : 1; |  | ||||||
|  |  | ||||||
|   // The hyperlink associated with the pixel. |  | ||||||
|   // 0 is the default value, meaning no hyperlink. |  | ||||||
|   uint8_t hyperlink = 0; |  | ||||||
|  |  | ||||||
|   // The graphemes stored into the pixel. To support combining characters, |  | ||||||
|   // like: a⃦, this can potentially contain multiple codepoints. |  | ||||||
|   std::string character = " "; |  | ||||||
|  |  | ||||||
|   // Colors: |  | ||||||
|   Color background_color = Color::Default; |  | ||||||
|   Color foreground_color = Color::Default; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /// @brief Define how the Screen's dimensions should look like. | /// @brief Define how the Screen's dimensions should look like. | ||||||
| /// @ingroup screen | /// @ingroup screen | ||||||
| namespace Dimension { | namespace Dimension { | ||||||
| @@ -60,36 +24,24 @@ Dimensions Full(); | |||||||
|  |  | ||||||
| /// @brief A rectangular grid of Pixel. | /// @brief A rectangular grid of Pixel. | ||||||
| /// @ingroup screen | /// @ingroup screen | ||||||
| class Screen { | class Screen : public Image { | ||||||
|  public: |  public: | ||||||
|   // Constructors: |   // Constructors: | ||||||
|   Screen(int dimx, int dimy); |   Screen(int dimx, int dimy); | ||||||
|   static Screen Create(Dimensions dimension); |   static Screen Create(Dimensions dimension); | ||||||
|   static Screen Create(Dimensions width, Dimensions height); |   static Screen Create(Dimensions width, Dimensions height); | ||||||
|  |  | ||||||
|   // Access a character in the grid at a given position. |  | ||||||
|   std::string& at(int x, int y); |  | ||||||
|   const std::string& at(int x, int y) const; |  | ||||||
|  |  | ||||||
|   // Access a cell (Pixel) in the grid at a given position. |  | ||||||
|   Pixel& PixelAt(int x, int y); |  | ||||||
|   const Pixel& PixelAt(int x, int y) const; |  | ||||||
|  |  | ||||||
|   std::string ToString() const; |   std::string ToString() const; | ||||||
|  |  | ||||||
|   // Print the Screen on to the terminal. |   // Print the Screen on to the terminal. | ||||||
|   void Print() const; |   void Print() const; | ||||||
|  |  | ||||||
|   // Get screen dimensions. |   // Fill the screen with space and reset any screen state, like hyperlinks, and cursor | ||||||
|   int dimx() const { return dimx_; } |   void Clear(); | ||||||
|   int dimy() const { return dimy_; } |  | ||||||
|  |  | ||||||
|   // Move the terminal cursor n-lines up with n = dimy(). |   // Move the terminal cursor n-lines up with n = dimy(). | ||||||
|   std::string ResetPosition(bool clear = false) const; |   std::string ResetPosition(bool clear = false) const; | ||||||
|  |  | ||||||
|   // Fill the screen with space. |  | ||||||
|   void Clear(); |  | ||||||
|  |  | ||||||
|   void ApplyShader(); |   void ApplyShader(); | ||||||
|  |  | ||||||
|   struct Cursor { |   struct Cursor { | ||||||
| @@ -107,6 +59,7 @@ class Screen { | |||||||
|     }; |     }; | ||||||
|     Shape shape; |     Shape shape; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   Cursor cursor() const { return cursor_; } |   Cursor cursor() const { return cursor_; } | ||||||
|   void SetCursor(Cursor cursor) { cursor_ = cursor; } |   void SetCursor(Cursor cursor) { cursor_ = cursor; } | ||||||
|  |  | ||||||
| @@ -115,12 +68,7 @@ class Screen { | |||||||
|   uint8_t RegisterHyperlink(const std::string& link); |   uint8_t RegisterHyperlink(const std::string& link); | ||||||
|   const std::string& Hyperlink(uint8_t id) const; |   const std::string& Hyperlink(uint8_t id) const; | ||||||
|  |  | ||||||
|   Box stencil; |  | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   int dimx_; |  | ||||||
|   int dimy_; |  | ||||||
|   std::vector<std::vector<Pixel>> pixels_; |  | ||||||
|   Cursor cursor_; |   Cursor cursor_; | ||||||
|   std::vector<std::string> hyperlinks_ = {""}; |   std::vector<std::string> hyperlinks_ = {""}; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -810,13 +810,49 @@ void Canvas::DrawText(int x, | |||||||
|       continue; |       continue; | ||||||
|     } |     } | ||||||
|     Cell& cell = storage_[XY{x / 2, y / 4}]; |     Cell& cell = storage_[XY{x / 2, y / 4}]; | ||||||
|     cell.type = CellType::kText; |     cell.type = CellType::kCell; | ||||||
|     cell.content.character = it; |     cell.content.character = it; | ||||||
|     style(cell.content); |     style(cell.content); | ||||||
|     x += 2; |     x += 2; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /// @brief Directly draw a predefined pixel at the given coordinate | ||||||
|  | /// @param x the x coordinate of the pixel. | ||||||
|  | /// @param y the y coordinate of the pixel. | ||||||
|  | /// @param p the pixel to draw. | ||||||
|  | void Canvas::DrawPixel(int x, int y, const Pixel& p) { | ||||||
|  |   Cell& cell = storage_[XY{x / 2, y / 4}]; | ||||||
|  |   cell.type = CellType::kCell; | ||||||
|  |   cell.content = p; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// @brief Draw a predefined image, with top-left corner at the given coordinate | ||||||
|  | ///   You can supply negative coordinates to align the image however you like -  | ||||||
|  | ///   only the 'visible' portion will be drawn | ||||||
|  | /// @param x the x coordinate corresponding to the top-left corner of the image. | ||||||
|  | /// @param y the y coordinate corresponding to the top-left corner of the image. | ||||||
|  | /// @param image the image to draw. | ||||||
|  | void Canvas::DrawImage(int x, int y, const Image& image) { | ||||||
|  |   x /= 2; | ||||||
|  |   y /= 4; | ||||||
|  |   const int dx_begin = std::max(0, -x); | ||||||
|  |   const int dy_begin = std::max(0, -y); | ||||||
|  |   const int dx_end = std::min(image.dimx(), width_ - x); | ||||||
|  |   const int dy_end = std::min(image.dimy(), height_ - y); | ||||||
|  |  | ||||||
|  |   for (int dy = dy_begin; dy < dy_end; ++dy) { | ||||||
|  |     for (int dx = dx_begin; dx < dx_end; ++dx) { | ||||||
|  |       Cell& cell = storage_[XY{ | ||||||
|  |           x + dx, | ||||||
|  |           y + dy, | ||||||
|  |       }]; | ||||||
|  |       cell.type = CellType::kCell; | ||||||
|  |       cell.content = image.PixelAt(dx, dy); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
| /// @brief Modify a pixel at a given location. | /// @brief Modify a pixel at a given location. | ||||||
| /// @param style a function that modifies the pixel. | /// @param style a function that modifies the pixel. | ||||||
| void Canvas::Style(int x, int y, const Stylizer& style) { | void Canvas::Style(int x, int y, const Stylizer& style) { | ||||||
|   | |||||||
| @@ -39,6 +39,12 @@ bool Box::Contain(int x, int y) const { | |||||||
|          y_max >= y; |          y_max >= y; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /// @return whether the box is empty. | ||||||
|  | /// @ingroup screen | ||||||
|  | bool Box::IsEmpty() { | ||||||
|  |   return x_min > x_max || y_min > y_max; | ||||||
|  | } | ||||||
|  |  | ||||||
| /// @return whether |other| is the same as |this| | /// @return whether |other| is the same as |this| | ||||||
| /// @ingroup screen | /// @ingroup screen | ||||||
| bool Box::operator==(const Box& other) const { | bool Box::operator==(const Box& other) const { | ||||||
|   | |||||||
							
								
								
									
										68
									
								
								src/ftxui/screen/image.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/ftxui/screen/image.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | |||||||
|  | // Copyright 2020 Arthur Sonzogni. All rights reserved. | ||||||
|  | // Use of this source code is governed by the MIT license that can be found in | ||||||
|  | // the LICENSE file. | ||||||
|  | #include <cstdint>  // for size_t | ||||||
|  | #include <iostream>  // for operator<<, stringstream, basic_ostream, flush, cout, ostream | ||||||
|  | #include <limits> | ||||||
|  | #include <map>      // for _Rb_tree_const_iterator, map, operator!=, operator== | ||||||
|  | #include <memory>   // for allocator, allocator_traits<>::value_type | ||||||
|  | #include <sstream>  // IWYU pragma: keep | ||||||
|  | #include <utility>  // for pair | ||||||
|  |  | ||||||
|  | #include "ftxui/screen/image.hpp" | ||||||
|  | #include "ftxui/screen/string.hpp"    // for string_width | ||||||
|  |  | ||||||
|  | namespace ftxui { | ||||||
|  |  | ||||||
|  | namespace | ||||||
|  | { | ||||||
|  |    Pixel& dev_null_pixel() { | ||||||
|  |       static Pixel pixel; | ||||||
|  |       return pixel; | ||||||
|  |    } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Image::Image(int dimx, int dimy) | ||||||
|  |     : stencil{0, dimx - 1, 0, dimy - 1}, | ||||||
|  |       dimx_(dimx), | ||||||
|  |       dimy_(dimy), | ||||||
|  |       pixels_(dimy, std::vector<Pixel>(dimx)) {} | ||||||
|  |  | ||||||
|  | /// @brief Access a character in a cell at a given position. | ||||||
|  | /// @param x The cell position along the x-axis. | ||||||
|  | /// @param y The cell position along the y-axis. | ||||||
|  | std::string& Image::at(int x, int y) { | ||||||
|  |   return PixelAt(x, y).character; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// @brief Access a character in a cell at a given position. | ||||||
|  | /// @param x The cell position along the x-axis. | ||||||
|  | /// @param y The cell position along the y-axis. | ||||||
|  | const std::string& Image::at(int x, int y) const { | ||||||
|  |   return PixelAt(x, y).character; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// @brief Access a cell (Pixel) at a given position. | ||||||
|  | /// @param x The cell position along the x-axis. | ||||||
|  | /// @param y The cell position along the y-axis. | ||||||
|  | Pixel& Image::PixelAt(int x, int y) { | ||||||
|  |   return stencil.Contain(x, y) ? pixels_[y][x] : dev_null_pixel(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// @brief Access a cell (Pixel) at a given position. | ||||||
|  | /// @param x The cell position along the x-axis. | ||||||
|  | /// @param y The cell position along the y-axis. | ||||||
|  | const Pixel& Image::PixelAt(int x, int y) const { | ||||||
|  |   return stencil.Contain(x, y) ? pixels_[y][x] : dev_null_pixel(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// @brief Clear all the pixel from the screen. | ||||||
|  | void Image::Clear() { | ||||||
|  |   for (auto& line : pixels_) { | ||||||
|  |     for (auto& cell : line) { | ||||||
|  |       cell = Pixel(); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace ftxui | ||||||
| @@ -42,11 +42,6 @@ namespace ftxui { | |||||||
|  |  | ||||||
| namespace { | namespace { | ||||||
|  |  | ||||||
| Pixel& dev_null_pixel() { |  | ||||||
|   static Pixel pixel; |  | ||||||
|   return pixel; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #if defined(_WIN32) | #if defined(_WIN32) | ||||||
| void WindowsEmulateVT100Terminal() { | void WindowsEmulateVT100Terminal() { | ||||||
|   static bool done = false; |   static bool done = false; | ||||||
| @@ -392,15 +387,11 @@ Screen Screen::Create(Dimensions dimension) { | |||||||
|   return {dimension.dimx, dimension.dimy}; |   return {dimension.dimx, dimension.dimy}; | ||||||
| } | } | ||||||
|  |  | ||||||
| Screen::Screen(int dimx, int dimy) | Screen::Screen(int dimx, int dimy) : Image{dimx, dimy} { | ||||||
|     : stencil{0, dimx - 1, 0, dimy - 1}, |  | ||||||
|       dimx_(dimx), |  | ||||||
|       dimy_(dimy), |  | ||||||
|       pixels_(dimy, std::vector<Pixel>(dimx)) { |  | ||||||
| #if defined(_WIN32) | #if defined(_WIN32) | ||||||
|   // The placement of this call is a bit weird, however we can assume that |   // The placement of this call is a bit weird, however we can assume that | ||||||
|   // anybody who instantiates a Screen object eventually wants to output |   // anybody who instantiates a Screen object eventually wants to output | ||||||
|   // something to the console. |   // something to the console. If that is not the case, use an instance of Image instead. | ||||||
|   // As we require UTF8 for all input/output operations we will just switch to |   // As we require UTF8 for all input/output operations we will just switch to | ||||||
|   // UTF8 encoding here |   // UTF8 encoding here | ||||||
|   SetConsoleOutputCP(CP_UTF8); |   SetConsoleOutputCP(CP_UTF8); | ||||||
| @@ -450,34 +441,6 @@ void Screen::Print() const { | |||||||
|   std::cout << ToString() << '\0' << std::flush; |   std::cout << ToString() << '\0' << std::flush; | ||||||
| } | } | ||||||
|  |  | ||||||
| /// @brief Access a character in a cell at a given position. |  | ||||||
| /// @param x The cell position along the x-axis. |  | ||||||
| /// @param y The cell position along the y-axis. |  | ||||||
| std::string& Screen::at(int x, int y) { |  | ||||||
|   return PixelAt(x, y).character; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// @brief Access a character in a cell at a given position. |  | ||||||
| /// @param x The cell position along the x-axis. |  | ||||||
| /// @param y The cell position along the y-axis. |  | ||||||
| const std::string& Screen::at(int x, int y) const { |  | ||||||
|   return PixelAt(x, y).character; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// @brief Access a cell (Pixel) at a given position. |  | ||||||
| /// @param x The cell position along the x-axis. |  | ||||||
| /// @param y The cell position along the y-axis. |  | ||||||
| Pixel& Screen::PixelAt(int x, int y) { |  | ||||||
|   return stencil.Contain(x, y) ? pixels_[y][x] : dev_null_pixel(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// @brief Access a cell (Pixel) at a given position. |  | ||||||
| /// @param x The cell position along the x-axis. |  | ||||||
| /// @param y The cell position along the y-axis. |  | ||||||
| const Pixel& Screen::PixelAt(int x, int y) const { |  | ||||||
|   return stencil.Contain(x, y) ? pixels_[y][x] : dev_null_pixel(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// @brief Return a string to be printed in order to reset the cursor position | /// @brief Return a string to be printed in order to reset the cursor position | ||||||
| ///        to the beginning of the screen. | ///        to the beginning of the screen. | ||||||
| /// | /// | ||||||
| @@ -517,11 +480,8 @@ std::string Screen::ResetPosition(bool clear) const { | |||||||
|  |  | ||||||
| /// @brief Clear all the pixel from the screen. | /// @brief Clear all the pixel from the screen. | ||||||
| void Screen::Clear() { | void Screen::Clear() { | ||||||
|   for (auto& line : pixels_) { |   Image::Clear(); | ||||||
|     for (auto& cell : line) { |  | ||||||
|       cell = Pixel(); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   cursor_.x = dimx_ - 1; |   cursor_.x = dimx_ - 1; | ||||||
|   cursor_.y = dimy_ - 1; |   cursor_.y = dimy_ - 1; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user