Skip to content

Commit 25aef45

Browse files
committed
readme
1 parent 2d87d06 commit 25aef45

File tree

2 files changed

+81
-19
lines changed

2 files changed

+81
-19
lines changed

demos/main.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,32 @@ int main()
3535
//std::cout << "Still the same - state was changed!\n";
3636
//std::cout << oof::reset_formatting() << oof::hposition(10) << "All back to normal\n";
3737

38+
// oof::screen scr(10, 3, 0, 0, ' ');
39+
// for(uint64_t i=0; ; ++i){
40+
// int j = 0;
41+
// for (auto& cell : scr) {
42+
// cell.m_letter = 'A' + (j + i) % 26;
43+
// cell.m_format.m_bg_color.red = j * 8;
44+
// ++j;
45+
// }
46+
// std::cout << scr.get_string();
47+
// }
48+
49+
// oof::pixel_screen screen(10, 10);
50+
// const auto t0 = std::chrono::high_resolution_clock::now();
51+
// while(true){
52+
// const auto t1 = std::chrono::high_resolution_clock::now();
53+
// const double seconds = std::chrono::duration<double>(t1-t0).count();
54+
//
55+
// for (oof::color& pixel : screen) {
56+
// pixel.red = 127.5 + 127.5 * std::sin(1.0 * seconds);
57+
// pixel.green = 127.5 + 127.5 * std::sin(2.0 * seconds);
58+
// pixel.blue = 127.5 + 127.5 * std::sin(3.0 * seconds);
59+
// }
60+
// fast_print(screen.get_string());
61+
// }
62+
63+
3864
int demo_choice = 0;
3965
print_choice("Bars");
4066
print_choice("Text crawl");

readme.md

Lines changed: 55 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Oof (omnipotent output friend)
2-
It's common for C++ programs to write output to the console. But consoles are far more capable than what they are usually used for. The magic lies in the so-called [Virtual Terminal sequences](https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences) (sometimes also confusingly called ["escape codes"](https://en.wikipedia.org/wiki/ANSI_escape_code)): These cryptic character sequences allow complete control over position, color and other properties of written characters. Your omnipotent output friend (*oof*) wraps this in a single C++ header.
2+
It's common for C++ programs to write output to the console. But consoles are far more capable than what they are usually used for. The magic lies in the so-called [Virtual Terminal sequences](https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences) (sometimes also confusingly called ["escape codes"](https://en.wikipedia.org/wiki/ANSI_escape_code)): These cryptic character sequences allow complete control over position, color and other properties of written characters. Oof is a single C++ header that wraps these in a convenient way
33

4-
On top of that, *oof* provides two special interfaces that can apply two different optimizations to the resulting stream of VT sequences, so that real-time outputs like those below are possible. Note that everything in these videos are letters in a console window:
4+
On top of that, *oof* provides two special interfaces that heavily optimizes the resulting stream of VT sequences, so that real-time outputs like those below are possible. Note that everything in these videos are letters in a console window:
55

66
https://user-images.githubusercontent.com/6044318/142469815-ce680909-9151-4322-85aa-01dc9ba29c1d.mp4
77

@@ -11,7 +11,7 @@ https://user-images.githubusercontent.com/6044318/142469849-e359955d-fa3a-47d9-9
1111

1212
https://user-images.githubusercontent.com/6044318/142469871-39f34712-f05e-4f8a-818a-b023081c1eee.mp4
1313

14-
## Usage details
14+
## Usage
1515
To use the library, include `oof.h`. As with most header-only libraries, that include must be preceeded with `#define OOF_IMPL` in **one** cpp file. That way, the function implementations are only compiled once.
1616

1717
The simple interface consists of the functions below.
@@ -59,7 +59,9 @@ auto move_up (int amount) -> ...
5959
auto move_down (int amount) -> ...
6060
```
6161
62-
Those functions return a magic type that can `operator<<` into `std::cout` and `std::wcout`. They also implicitly convert into `std::string` and `std::wstring` so you can build up your own strings with them. Example:
62+
Index colors are simply colors refered to by an index. The colors behind the indices can be set with `set_index_color()`.
63+
64+
All these functions return a magic type that can `operator<<` into `std::cout` and `std::wcout`. Example:
6365
```c++
6466
std::cout << oof::fg_color(oof::color{ 255, 100, 100 }) << "This is red\n";
6567
std::cout << "Still the same - state was changed!\n";
@@ -68,21 +70,63 @@ std::cout << oof::reset_formatting() << oof::hposition(10) << "All back to norma
6870

6971
![example](https://user-images.githubusercontent.com/6044318/142437248-a999738c-2191-4ccc-be78-132685e2169c.png)
7072

73+
They also implicitly convert into `std::string` and `std::wstring` so you can build up your own strings with them.
74+
7175
The type `oof::color` is just a `struct color { uint8_t red{}, green{}, blue{}; }`. You're encouraged to `std::bit_cast`, `reinterpret_cast` or `memcpy` your favorite 3-byte RGB color type into this.
7276

7377
## Performance and screen interfaces
7478
Each printing command (regardless of wether it's `printf`, `std::cout` or something OS-specific) is pretty expensive. If performance is a priority, then consider building up your string first, and printing it in one go.
7579

76-
For real-time output, there is even more potential: If a program keeps track of the current state of the screen, it can avoid overriding cells that haven't changed. Even more: Changing the console cursor state (even without printing anything) is expensive. By avoiding unnecessary state changes, the performance can be optimized even more. Both of these optimizations are implemented in the `screen` and `pixel_screen` classes.
80+
If you want real-time output, ie continuously changing what's on the screen, there's even more potential: If a program keeps track of the current state of the screen, it can avoid writing cells that haven't changed. And: Changing the console cursor state (even without printing anything) is expensive. By avoiding unnecessary state changes, the performance can be optimized even more. Both of these optimizations are implemented in the `screen` and `pixel_screen` classes.
81+
82+
`oof::screen` lets you define a rectangle of your console window, and set the state of every single cell. Its `get_string()` and `write_string(string_type&)` methods then output an optimized string to achieve the desired state. This assumes that the user didn't interfere - so don't. The difference between `get_string()` and `write_string(string_type&)` is that the passed string will be used to avoid allocating a new string. So it'll avoid memory waste. Almost always, the cost of building up the string is tiny vs the cost of printing, so don't worry about this too much.
83+
84+
Example for `oof::screen` usage:
85+
```c++
86+
oof::screen scr(10, 3, 0, 0, ' ');
87+
for(uint64_t i=0; ; ++i){
88+
int j = 0;
89+
for (auto& cell : scr) {
90+
cell.m_letter = 'A' + (j + i) % 26;
91+
cell.m_format.m_bg_color.red = j * 8;
92+
++j;
93+
}
94+
std::cout << scr.get_string();
95+
}
96+
```
97+
![screen_example](https://user-images.githubusercontent.com/6044318/142577018-cc25f98e-0572-4179-ac65-ffa79964d25c.gif)
98+
99+
The API in general is pretty low level compared to [other](https://github.com/ArthurSonzogni/FTXUI) [libraries](https://github.com/ggerganov/imtui), focused on high performance and modularity. You're encouraged to use it to build your own components. A good example for this is [the horizontal bars demo](demos/bars_demo.cpp):
77100
78-
`oof::screen` lets you define a rectangle of your console window, and set the state of every single cell. Its `get_string()` and `write_string(string_type&)` methods then output an *optimal* string to achieve the desired state. This assumes that the user didn't interfere - so don't.
101+
![bars_demo](https://user-images.githubusercontent.com/6044318/142583233-c026da81-815e-4486-9588-b02ecd9c6ac8.gif)
79102
80-
`oof::pixel_screen` does the same for a niche case. Consoles always write text, ie letters. With most fonts, a single letter or cell is much taller than wide. By using a very special character that exactly fills the upper half of a cell, the visible area gets effectively transformed into (almost) square pixels. Exactly that's done by the `pixel_screen` class. There you only set colors and give up control of the letters themselves. Note that that type often has `halfline` type parameters. That's due to the fact that a "pixel" is now just half a line high.
103+
Consoles always write text, ie letters. With most fonts, a single letter or cell is much taller than wide. By using a very special character that exactly fills the upper half of a cell, the visible area gets effectively transformed into (almost) square pixels. Exactly that's done by the `pixel_screen` class. There you only set colors and give up control of the letters themselves. Note that that type often has `halfline` type parameters. That's due to the fact that a "pixel" is now just half a line high.
104+
105+
### `oof::pixel_screen`
106+
Example for `oof::pixel_screen` usage:
107+
```c++
108+
oof::pixel_screen screen(10, 10);
109+
const auto t0 = std::chrono::high_resolution_clock::now();
110+
while(true){
111+
const auto t1 = std::chrono::high_resolution_clock::now();
112+
const double seconds = std::chrono::duration<double>(t1-t0).count();
113+
114+
for (oof::color& pixel : screen) {
115+
pixel.red = 127.5 + 127.5 * std::sin(1.0 * seconds);
116+
pixel.green = 127.5 + 127.5 * std::sin(2.0 * seconds);
117+
pixel.blue = 127.5 + 127.5 * std::sin(3.0 * seconds);
118+
}
119+
fast_print(screen.get_string());
120+
}
121+
```
122+
![pixel_screen_example](https://user-images.githubusercontent.com/6044318/142581841-66a235d1-d1e8-4f02-b7e7-2c9889a321e6.gif)
123+
124+
The source code from the demo videos at the beginning is in this repo under /demos. That code uses a not-included and yet unreleased helper library (`s9w::`) for colors and math. But those aren't crucial if you just want to have a look.
81125

82126
## Notes
83127
Consoles display text. Text is displayed via fonts. If you use letters that aren't included in your console font, that will result in visual artifacts - duh. This especially important for the `pixel_display` type, as it uses the mildly special [Block element](https://en.wikipedia.org/wiki/Block_Elements) '▀'. Some fonts may not have them included. Others do, but have them poorly aligned or sized - breaking up the even pixel grid.
84128

85-
This is a short overview of common monospce fonts and how well they are suited for "pixel" displays. Note that many are great in some sizes, ugly in others.
129+
This is a short overview of common monospce fonts and how well they are suited for "pixel" displays. Note that many are great in some sizes but ugly in others.
86130

87131
| | Font name |
88132
|---|---|
@@ -152,14 +196,6 @@ auto enable_vt_mode() -> void
152196
}
153197
```
154198

155-
Also note that while the VT sequences are universal, not all consoles programs and operating systems may support them. I only have access to a windows machine so I can't make any claims on other operating systems.
156-
157-
Be warned that the [new Windows Terminal](https://github.com/microsoft/terminal) has some problems with irregular frame pacing. It will report high FPS but "feel" much choppier than good old `cmd.exe`.
158-
159-
## Similar projects
160-
Tere's [FXTUI](https://github.com/ArthurSonzogni/FTXUI) and [imtui](https://github.com/ggerganov/imtui) which write complete text-based user interfaces.
161-
162-
## TODO
163-
- components to write higher-level compoennts
164-
- helper functions
165-
- demo videos, demo code, s9w lib
199+
- If you use `pixel_screen` or `screen<std::wstring>` in combination with `std::wcout`, you might not see the output. That's because unicode output might need some magic to enable. Either google that, or use the recommended `fast_print` above as it's faster and doesn't suffer from these problems.
200+
- While the VT sequences are universal, not all consoles programs and operating systems may support them. I only have access to a windows machine so I can't make any claims on other operating systems.
201+
- The [new Windows Terminal](https://github.com/microsoft/terminal) has some problems with irregular frame pacing. It will report high FPS but "feel" much choppier than good old `cmd.exe`.

0 commit comments

Comments
 (0)