From a36b187879e37cba824b81e916c7351780b798ba Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sat, 2 Nov 2024 03:53:33 -0400 Subject: [PATCH] Renderer of ANSI codes to SFML is now working. Does seem to be a little slow but that'll be easy to fix later. --- Makefile | 9 +++-- ansi_parser.cpp | 87 ++++++++++++++++++++++++++----------------- ansi_parser.hpp | 4 +- ansi_parser.rl | 32 ++++++++++++---- map.hpp | 6 +-- meson.build | 8 +--- render.cpp | 4 +- tests/ansi_parser.cpp | 8 +++- 8 files changed, 96 insertions(+), 62 deletions(-) diff --git a/Makefile b/Makefile index 7a79fcf..b1b1764 100644 --- a/Makefile +++ b/Makefile @@ -3,16 +3,17 @@ all: build test reset: powershell -executionpolicy bypass .\scripts\reset_build.ps1 -rageldev: - make ragel +%.cpp : %.rl + ragel -o $@ $< + +rageldev: ragel make test > test.txt vim test.txt ragel: - ragel -o .\scratchpad\testragel.cpp .\scratchpad\testragel.rl ragel -o .\ansi_parser.cpp .\ansi_parser.rl -build: +build: ansi_parser.cpp meson compile -j 4 -C builddir test: build diff --git a/ansi_parser.cpp b/ansi_parser.cpp index fb345eb..0c36f62 100644 --- a/ansi_parser.cpp +++ b/ansi_parser.cpp @@ -10,7 +10,7 @@ using namespace fmt; -#line 59 ".\\ansi_parser.rl" +#line 77 ".\\ansi_parser.rl" @@ -28,7 +28,7 @@ static const char _foo_key_offsets[] = { 27, 28, 29, 30, 31 }; -static const char _foo_trans_keys[] = { +static const int _foo_trans_keys[] = { 27, 91, 51, 52, 56, 57, 59, 50, 59, 48, 57, 59, 48, 57, 48, 57, 59, 48, 57, 48, 57, 109, 48, 57, @@ -85,15 +85,15 @@ static const int foo_error = 0; static const int foo_en_main = 19; -#line 62 ".\\ansi_parser.rl" +#line 80 ".\\ansi_parser.rl" -bool parse_ansi(std::string_view codes, sf::Color default_fg, sf::Color default_bg, WriteCB write) { - const char *start = NULL; +bool parse_ansi(std::wstring_view codes, sf::Color default_fg, sf::Color default_bg, WriteCB write) { + const wchar_t *start = NULL; int cs = 0; unsigned int value = 0; - const char *p = codes.data(); - const char *pe = p + codes.size(); - const char *eof = pe; + const wchar_t *p = codes.data(); + const wchar_t *pe = p + codes.size(); + const wchar_t *eof = pe; sf::Color bgcolor(default_bg); sf::Color color(default_fg); sf::Color &target = bgcolor; @@ -104,7 +104,7 @@ bool parse_ansi(std::string_view codes, sf::Color default_fg, sf::Color default_ cs = foo_start; } -#line 75 ".\\ansi_parser.rl" +#line 93 ".\\ansi_parser.rl" #line 97 ".\\ansi_parser.cpp" { @@ -112,7 +112,7 @@ bool parse_ansi(std::string_view codes, sf::Color default_fg, sf::Color default_ unsigned int _trans; const char *_acts; unsigned int _nacts; - const char *_keys; + const int *_keys; if ( p == pe ) goto _test_eof; @@ -124,9 +124,9 @@ _resume: _klen = _foo_single_lengths[cs]; if ( _klen > 0 ) { - const char *_lower = _keys; - const char *_mid; - const char *_upper = _keys + _klen - 1; + const int *_lower = _keys; + const int *_mid; + const int *_upper = _keys + _klen - 1; while (1) { if ( _upper < _lower ) break; @@ -147,9 +147,9 @@ _resume: _klen = _foo_range_lengths[cs]; if ( _klen > 0 ) { - const char *_lower = _keys; - const char *_mid; - const char *_upper = _keys + (_klen<<1) - 2; + const int *_lower = _keys; + const int *_mid; + const int *_upper = _keys + (_klen<<1) - 2; while (1) { if ( _upper < _lower ) break; @@ -180,65 +180,82 @@ _match: switch ( *_acts++ ) { case 0: -#line 13 ".\\ansi_parser.rl" +#line 14 ".\\ansi_parser.rl" { start = p; } break; case 1: -#line 17 ".\\ansi_parser.rl" +#line 18 ".\\ansi_parser.rl" { - auto [ptr, ec] = std::from_chars(start, p, value); - dbc::check(ec == std::errc(), "error in number parsing"); + value = 0; + size_t len = p - start; + dbc::check(start[0] != '-', "negative numbers not supported"); + + switch(len) { + case 10: value += (start[len-10] - '0') * 1000000000; + case 9: value += (start[len- 9] - '0') * 100000000; + case 8: value += (start[len- 8] - '0') * 10000000; + case 7: value += (start[len- 7] - '0') * 1000000; + case 6: value += (start[len- 6] - '0') * 100000; + case 5: value += (start[len- 5] - '0') * 10000; + case 4: value += (start[len- 4] - '0') * 1000; + case 3: value += (start[len- 3] - '0') * 100; + case 2: value += (start[len- 2] - '0') * 10; + case 1: value += (start[len- 1] - '0'); + break; + default: + dbc::sentinel("can't process > 10 digits"); + } } break; case 2: -#line 22 ".\\ansi_parser.rl" +#line 40 ".\\ansi_parser.rl" { } break; case 3: -#line 23 ".\\ansi_parser.rl" +#line 41 ".\\ansi_parser.rl" { target = color; } break; case 4: -#line 24 ".\\ansi_parser.rl" +#line 42 ".\\ansi_parser.rl" { target = bgcolor; } break; case 5: -#line 26 ".\\ansi_parser.rl" +#line 44 ".\\ansi_parser.rl" { write(bgcolor, color, (*p)); } break; case 6: -#line 30 ".\\ansi_parser.rl" +#line 48 ".\\ansi_parser.rl" { color = default_fg; } break; case 7: -#line 31 ".\\ansi_parser.rl" +#line 49 ".\\ansi_parser.rl" { bgcolor = default_bg; } break; case 8: -#line 33 ".\\ansi_parser.rl" +#line 51 ".\\ansi_parser.rl" { target.r = value; } break; case 9: -#line 34 ".\\ansi_parser.rl" +#line 52 ".\\ansi_parser.rl" { target.g = value; } break; case 10: -#line 35 ".\\ansi_parser.rl" +#line 53 ".\\ansi_parser.rl" { target.b = value; } break; case 11: -#line 36 ".\\ansi_parser.rl" +#line 54 ".\\ansi_parser.rl" { value = 0; } break; case 12: -#line 37 ".\\ansi_parser.rl" +#line 55 ".\\ansi_parser.rl" { } break; -#line 215 ".\\ansi_parser.cpp" +#line 232 ".\\ansi_parser.cpp" } } @@ -255,10 +272,10 @@ _again: while ( __nacts-- > 0 ) { switch ( *__acts++ ) { case 12: -#line 37 ".\\ansi_parser.rl" +#line 55 ".\\ansi_parser.rl" { } break; -#line 233 ".\\ansi_parser.cpp" +#line 250 ".\\ansi_parser.cpp" } } } @@ -266,7 +283,7 @@ _again: _out: {} } -#line 76 ".\\ansi_parser.rl" +#line 94 ".\\ansi_parser.rl" return p - pe == 0; } diff --git a/ansi_parser.hpp b/ansi_parser.hpp index 3d403ce..f0b0043 100644 --- a/ansi_parser.hpp +++ b/ansi_parser.hpp @@ -2,6 +2,6 @@ #include #include -typedef std::function WriteCB; +typedef std::function WriteCB; -bool parse_ansi(std::string_view codes, sf::Color default_fg, sf::Color default_bg, WriteCB write); +bool parse_ansi(std::wstring_view codes, sf::Color default_fg, sf::Color default_bg, WriteCB write); diff --git a/ansi_parser.rl b/ansi_parser.rl index be7577c..7434b9d 100644 --- a/ansi_parser.rl +++ b/ansi_parser.rl @@ -9,14 +9,32 @@ using namespace fmt; %%{ machine foo; + alphtype int; action tstart { start = fpc; } action number { - auto [ptr, ec] = std::from_chars(start, fpc, value); - dbc::check(ec == std::errc(), "error in number parsing"); + value = 0; + size_t len = fpc - start; + dbc::check(start[0] != '-', "negative numbers not supported"); + + switch(len) { + case 10: value += (start[len-10] - '0') * 1000000000; + case 9: value += (start[len- 9] - '0') * 100000000; + case 8: value += (start[len- 8] - '0') * 10000000; + case 7: value += (start[len- 7] - '0') * 1000000; + case 6: value += (start[len- 6] - '0') * 100000; + case 5: value += (start[len- 5] - '0') * 10000; + case 4: value += (start[len- 4] - '0') * 1000; + case 3: value += (start[len- 3] - '0') * 100; + case 2: value += (start[len- 2] - '0') * 10; + case 1: value += (start[len- 1] - '0'); + break; + default: + dbc::sentinel("can't process > 10 digits"); + } } action color24b { } @@ -60,13 +78,13 @@ using namespace fmt; %% write data; -bool parse_ansi(std::string_view codes, sf::Color default_fg, sf::Color default_bg, WriteCB write) { - const char *start = NULL; +bool parse_ansi(std::wstring_view codes, sf::Color default_fg, sf::Color default_bg, WriteCB write) { + const wchar_t *start = NULL; int cs = 0; unsigned int value = 0; - const char *p = codes.data(); - const char *pe = p + codes.size(); - const char *eof = pe; + const wchar_t *p = codes.data(); + const wchar_t *pe = p + codes.size(); + const wchar_t *eof = pe; sf::Color bgcolor(default_bg); sf::Color color(default_fg); sf::Color &target = bgcolor; diff --git a/map.hpp b/map.hpp index e403a89..80bdd98 100644 --- a/map.hpp +++ b/map.hpp @@ -11,10 +11,10 @@ #define INV_SPACE 1 #define WALL_VALUE 1 #define SPACE_VALUE 0 -#define WALL_TILE "#" +#define WALL_TILE "█" #define FLOOR_TILE "." -#define PLAYER_TILE "&" -#define ENEMY_TILE "!" +#define PLAYER_TILE "☺" +#define ENEMY_TILE "Ω" struct Room { size_t x = 0; diff --git a/meson.build b/meson.build index 8b3e324..317f936 100644 --- a/meson.build +++ b/meson.build @@ -20,7 +20,7 @@ runtests = executable('runtests', [ 'sound.cpp', 'collider.cpp', 'ansi_parser.cpp', - 'render.cpp', + #'render.cpp', 'tests/fsm.cpp', 'tests/dbc.cpp', 'tests/map.cpp', @@ -51,10 +51,4 @@ collider = executable('collider', [ ], dependencies: dependencies) -testragel = executable('testragel', [ - 'dbc.cpp', - './scratchpad/testragel.cpp' - ], - dependencies: dependencies) - test('tests', runtests) diff --git a/render.cpp b/render.cpp index 9870435..a737def 100644 --- a/render.cpp +++ b/render.cpp @@ -87,10 +87,10 @@ void SFMLRender::draw_screen(bool clear, float map_off_x, float map_off_y) { // make a copy so we don't modify the cached one auto bg_sprite = get_text_sprite(L'█'); auto bg_bounds = bg_sprite.getLocalBounds(); - sf::Color def_fg(color(Value::LIGHT_LIGHT)); + sf::Color def_fg(color(Value::MID)); sf::Color def_bg(color(Value::BLACK)); - parse_ansi(map_screenout, def_fg, def_bg, [&](sf::Color bg, sf::Color fg, char tile) { + parse_ansi(map_screen_utf8, def_fg, def_bg, [&](sf::Color bg, sf::Color fg, wchar_t tile) { if(tile == '\n') { // don't bother processing newlines, just skip y += $line_spacing; diff --git a/tests/ansi_parser.cpp b/tests/ansi_parser.cpp index ab29b40..fd35f29 100644 --- a/tests/ansi_parser.cpp +++ b/tests/ansi_parser.cpp @@ -2,6 +2,7 @@ #include #include #include "ansi_parser.hpp" +#include #include "ftxui/dom/elements.hpp" // for text, bgcolor, color, vbox, hbox, separator, operator|, Elements, Element, Fit, border @@ -52,11 +53,14 @@ std::string generate_colors() { TEST_CASE("test out ragel parser", "[gui]") { std::string colors = generate_colors(); + + std::wstring_convert> converter; + std::wstring colors_utf8 = converter.from_bytes(colors); + sf::Color default_fg(0,0,0); sf::Color default_bg(100,100,100); - println("--- PARSING"); - bool good = parse_ansi(colors, default_fg, default_bg, [&](sf::Color bgcolor, sf::Color color, char ch) { + bool good = parse_ansi(colors_utf8, default_fg, default_bg, [&](sf::Color bgcolor, sf::Color color, wchar_t ch) { bool correct_char = ch == '#' || ch == ' ' || ch == '\n' || ch == '\r'; // println("FG: {},{},{},{}; BG: {},{},{},{}; ch: {}", // color.r, color.g, color.b, color.a,