From 6d9771bc329e987d5511134f63c738741b1f8f1e Mon Sep 17 00:00:00 2001 From: GHOST11111100 Date: Wed, 15 Jan 2025 18:42:16 +0300 Subject: [PATCH 1/5] added base hex color parser, and md statement --- src/graphics/ui/markdown.cpp | 77 ++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 21 deletions(-) diff --git a/src/graphics/ui/markdown.cpp b/src/graphics/ui/markdown.cpp index ab328e66..dd8613b5 100644 --- a/src/graphics/ui/markdown.cpp +++ b/src/graphics/ui/markdown.cpp @@ -1,15 +1,21 @@ #include "markdown.hpp" - #include "graphics/core/Font.hpp" using namespace markdown; +static inline int hexchar2int(char c) { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'a' && c <= 'f') return c - 'a' + 10; + if (c >= 'A' && c <= 'F') return c - 'A' + 10; + return -1; +} + template static inline void emit( CharT c, FontStylesScheme& styles, std::basic_stringstream& ss ) { ss << c; - styles.map.emplace_back(styles.palette.size()-1); + styles.map.emplace_back(styles.palette.size() - 1); } template @@ -21,21 +27,36 @@ static inline void emit_md( } template -static inline void restyle( - CharT c, - FontStyle& style, - FontStylesScheme& styles, - std::basic_stringstream& ss, - int& pos, - bool eraseMarkdown -) { - styles.palette.push_back(style); - if (!eraseMarkdown) { - emit_md(c, styles, ss); +static glm::vec4 parse_color(const std::basic_string_view& color_code) { + if (color_code.size() != 9 || color_code[0] != '#') { + return glm::vec4(1, 1, 1, 1); // default to white } - pos++; + + auto hex_to_float = [](char high, char low) { + int high_val = hexchar2int(high); + int low_val = hexchar2int(low); + if (high_val == -1 || low_val == -1) { + return 1.0f; // default to max value on error + } + return (high_val * 16 + low_val) / 255.0f; + }; + + return glm::vec4( + hex_to_float(color_code[1], color_code[2]), + hex_to_float(color_code[3], color_code[4]), + hex_to_float(color_code[5], color_code[6]), + hex_to_float(color_code[7], color_code[8]) + ); } +template +static inline void apply_color(const std::basic_string_view& color_code, FontStylesScheme& styles) { + FontStyle style = styles.palette.back(); + style.color = parse_color(color_code); + styles.palette.push_back(style); +} + +// TODO: Refactor md code processing template Result process_markdown( std::basic_string_view source, bool eraseMarkdown @@ -50,6 +71,19 @@ Result process_markdown( int pos = 0; while (pos < source.size()) { CharT first = source[pos]; + + if (first == '[' && pos + 10 < source.size() && source[pos + 1] == '#' && source[pos + 9] == ']') { + std::basic_string_view color_code = source.substr(pos + 1, 9); + apply_color(color_code, styles); + if (!eraseMarkdown) { + for (int i = 0; i < 10; ++i) { + emit_md(source[pos + i], styles, ss); + } + } + pos += 10; // Skip past the color code + continue; + } + if (first == '\\') { if (pos + 1 < source.size()) { CharT second = source[++pos]; @@ -67,32 +101,33 @@ Result process_markdown( pos--; } } else if (first == '*') { - if (pos + 1 < source.size() && source[pos+1] == '*') { + if (pos + 1 < source.size() && source[pos + 1] == '*') { pos++; if (!eraseMarkdown) emit_md(first, styles, ss); style.bold = !style.bold; - restyle(first, style, styles, ss, pos, eraseMarkdown); + styles.palette.push_back(style); continue; } style.italic = !style.italic; - restyle(first, style, styles, ss, pos, eraseMarkdown); + styles.palette.push_back(style); continue; - } else if (first == '_' && pos + 1 < source.size() && source[pos+1] == '_') { + } else if (first == '_' && pos + 1 < source.size() && source[pos + 1] == '_') { pos++; if (!eraseMarkdown) emit_md(first, styles, ss); style.underline = !style.underline; - restyle(first, style, styles, ss, pos, eraseMarkdown); + styles.palette.push_back(style); continue; - } else if (first == '~' && pos + 1 < source.size() && source[pos+1] == '~') { + } else if (first == '~' && pos + 1 < source.size() && source[pos + 1] == '~') { pos++; if (!eraseMarkdown) emit_md(first, styles, ss); style.strikethrough = !style.strikethrough; - restyle(first, style, styles, ss, pos, eraseMarkdown); + styles.palette.push_back(style); continue; } + if (first == '\n') { styles.palette.push_back(styles.palette.at(1)); } From 9ce34080f775b3c05afe83c1d814aa83be4a274c Mon Sep 17 00:00:00 2001 From: GHOST11111100 Date: Wed, 15 Jan 2025 19:07:48 +0300 Subject: [PATCH 2/5] fixed engine hang when using other special characters --- src/graphics/ui/markdown.cpp | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/graphics/ui/markdown.cpp b/src/graphics/ui/markdown.cpp index dd8613b5..8a1b13bf 100644 --- a/src/graphics/ui/markdown.cpp +++ b/src/graphics/ui/markdown.cpp @@ -56,7 +56,22 @@ static inline void apply_color(const std::basic_string_view& color_code, styles.palette.push_back(style); } -// TODO: Refactor md code processing +template +static inline void restyle( + CharT c, + FontStyle& style, + FontStylesScheme& styles, + std::basic_stringstream& ss, + int& pos, + bool eraseMarkdown +) { + styles.palette.push_back(style); + if (!eraseMarkdown) { + emit_md(c, styles, ss); + } + pos++; +} + template Result process_markdown( std::basic_string_view source, bool eraseMarkdown @@ -101,33 +116,32 @@ Result process_markdown( pos--; } } else if (first == '*') { - if (pos + 1 < source.size() && source[pos + 1] == '*') { + if (pos + 1 < source.size() && source[pos+1] == '*') { pos++; if (!eraseMarkdown) emit_md(first, styles, ss); style.bold = !style.bold; - styles.palette.push_back(style); + restyle(first, style, styles, ss, pos, eraseMarkdown); continue; } style.italic = !style.italic; - styles.palette.push_back(style); + restyle(first, style, styles, ss, pos, eraseMarkdown); continue; - } else if (first == '_' && pos + 1 < source.size() && source[pos + 1] == '_') { + } else if (first == '_' && pos + 1 < source.size() && source[pos+1] == '_') { pos++; if (!eraseMarkdown) emit_md(first, styles, ss); style.underline = !style.underline; - styles.palette.push_back(style); + restyle(first, style, styles, ss, pos, eraseMarkdown); continue; - } else if (first == '~' && pos + 1 < source.size() && source[pos + 1] == '~') { + } else if (first == '~' && pos + 1 < source.size() && source[pos+1] == '~') { pos++; if (!eraseMarkdown) emit_md(first, styles, ss); style.strikethrough = !style.strikethrough; - styles.palette.push_back(style); + restyle(first, style, styles, ss, pos, eraseMarkdown); continue; } - if (first == '\n') { styles.palette.push_back(styles.palette.at(1)); } From 6ca8dc18cf9a2b062fdc7a4e0a19f4e4f16b5ec8 Mon Sep 17 00:00:00 2001 From: GHOST11111100 Date: Wed, 15 Jan 2025 20:09:30 +0300 Subject: [PATCH 3/5] fix hex code length and use a exists hex to int method; added docs for color codes --- doc/en/text-styles.md | 31 +++++++++++++++++++++++++++++++ doc/ru/text-styles.md | 30 ++++++++++++++++++++++++++++++ src/graphics/ui/markdown.cpp | 20 +++++++------------- 3 files changed, 68 insertions(+), 13 deletions(-) diff --git a/doc/en/text-styles.md b/doc/en/text-styles.md index e85437e1..4afce42a 100644 --- a/doc/en/text-styles.md +++ b/doc/en/text-styles.md @@ -19,3 +19,34 @@ Styles can be combined. Example: Output: ***Message*** using *~~combed~~ combined* styles~~.~~ + +# Colors + +Text color can be set using a color code: [#RRGGBB] + + +| Component | Purpose | +| --------- | --------------------------------- | +| R | Represents the intensity of red | +| G | Represents the intensity of green | +| B | Represents the intensity of blue | + +### Example: + + + + [#ff0000] + Red Text + + + + + [#00ff00] + Green Text + + + + + [#0000ff] + Blue Text + diff --git a/doc/ru/text-styles.md b/doc/ru/text-styles.md index 0a09abe3..4fbe3ed5 100644 --- a/doc/ru/text-styles.md +++ b/doc/ru/text-styles.md @@ -19,3 +19,33 @@ Вывод: ***Сообщение***, демонстрирующее *~~обедненные~~ объединенные* стили~~.~~ + +## Цвета + +Цвет текста задается при помощи цветового кода: [#RRGGBB] + +| Компонент | Назначение | +| ------------ | ------------------------- | +| R | Используется для интенсивности красного | +| G | Используется для интенсивности зеленого | +| B | Используется для интенсивности синего | + +### Например: + + + + [#ff0000] + Красный Текст + + + + + [#00ff00] + Зеленый Текст + + + + + [#0000ff] + Синий Текст + \ No newline at end of file diff --git a/src/graphics/ui/markdown.cpp b/src/graphics/ui/markdown.cpp index 8a1b13bf..bbbc298a 100644 --- a/src/graphics/ui/markdown.cpp +++ b/src/graphics/ui/markdown.cpp @@ -1,15 +1,9 @@ #include "markdown.hpp" +#include "coders/commons.hpp" #include "graphics/core/Font.hpp" using namespace markdown; -static inline int hexchar2int(char c) { - if (c >= '0' && c <= '9') return c - '0'; - if (c >= 'a' && c <= 'f') return c - 'a' + 10; - if (c >= 'A' && c <= 'F') return c - 'A' + 10; - return -1; -} - template static inline void emit( CharT c, FontStylesScheme& styles, std::basic_stringstream& ss @@ -28,7 +22,7 @@ static inline void emit_md( template static glm::vec4 parse_color(const std::basic_string_view& color_code) { - if (color_code.size() != 9 || color_code[0] != '#') { + if (color_code.size() != 8 || color_code[0] != '#') { return glm::vec4(1, 1, 1, 1); // default to white } @@ -45,7 +39,7 @@ static glm::vec4 parse_color(const std::basic_string_view& color_code) { hex_to_float(color_code[1], color_code[2]), hex_to_float(color_code[3], color_code[4]), hex_to_float(color_code[5], color_code[6]), - hex_to_float(color_code[7], color_code[8]) + 1 ); } @@ -87,15 +81,15 @@ Result process_markdown( while (pos < source.size()) { CharT first = source[pos]; - if (first == '[' && pos + 10 < source.size() && source[pos + 1] == '#' && source[pos + 9] == ']') { - std::basic_string_view color_code = source.substr(pos + 1, 9); + if (first == '[' && pos + 9 < source.size() && source[pos + 1] == '#' && source[pos + 8] == ']') { + std::basic_string_view color_code = source.substr(pos + 1, 8); apply_color(color_code, styles); if (!eraseMarkdown) { - for (int i = 0; i < 10; ++i) { + for (int i = 0; i < 9; ++i) { emit_md(source[pos + i], styles, ss); } } - pos += 10; // Skip past the color code + pos += 9; // Skip past the color code continue; } From a93af583d19b9fd640ef287b90fabd0eaa7d0fe4 Mon Sep 17 00:00:00 2001 From: GHOST11111100 Date: Wed, 15 Jan 2025 21:22:13 +0300 Subject: [PATCH 4/5] added color code escaping --- src/graphics/ui/markdown.cpp | 70 ++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/src/graphics/ui/markdown.cpp b/src/graphics/ui/markdown.cpp index bbbc298a..8616facd 100644 --- a/src/graphics/ui/markdown.cpp +++ b/src/graphics/ui/markdown.cpp @@ -1,4 +1,5 @@ #include "markdown.hpp" + #include "coders/commons.hpp" #include "graphics/core/Font.hpp" @@ -23,14 +24,14 @@ static inline void emit_md( template static glm::vec4 parse_color(const std::basic_string_view& color_code) { if (color_code.size() != 8 || color_code[0] != '#') { - return glm::vec4(1, 1, 1, 1); // default to white + return glm::vec4(1, 1, 1, 1); // default to white } auto hex_to_float = [](char high, char low) { int high_val = hexchar2int(high); int low_val = hexchar2int(low); if (high_val == -1 || low_val == -1) { - return 1.0f; // default to max value on error + return 1.0f; // default to max value on error } return (high_val * 16 + low_val) / 255.0f; }; @@ -44,7 +45,9 @@ static glm::vec4 parse_color(const std::basic_string_view& color_code) { } template -static inline void apply_color(const std::basic_string_view& color_code, FontStylesScheme& styles) { +static inline void apply_color( + const std::basic_string_view& color_code, FontStylesScheme& styles +) { FontStyle style = styles.palette.back(); style.color = parse_color(color_code); styles.palette.push_back(style); @@ -73,7 +76,7 @@ Result process_markdown( std::basic_stringstream ss; FontStylesScheme styles { // markdown default - {{false, false, false, false, glm::vec4(1,1,1,0.5f)}, {}}, + {{false, false, false, false, glm::vec4(1, 1, 1, 0.5f)}, {}}, {} }; FontStyle style; @@ -81,18 +84,6 @@ Result process_markdown( while (pos < source.size()) { CharT first = source[pos]; - if (first == '[' && pos + 9 < source.size() && source[pos + 1] == '#' && source[pos + 8] == ']') { - std::basic_string_view color_code = source.substr(pos + 1, 8); - apply_color(color_code, styles); - if (!eraseMarkdown) { - for (int i = 0; i < 9; ++i) { - emit_md(source[pos + i], styles, ss); - } - } - pos += 9; // Skip past the color code - continue; - } - if (first == '\\') { if (pos + 1 < source.size()) { CharT second = source[++pos]; @@ -106,14 +97,39 @@ Result process_markdown( emit(second, styles, ss); pos++; continue; + case '[': + if (pos + 9 < source.size() && source[pos + 1] == '#' && + source[pos + 8] == ']') { + if (!eraseMarkdown) { + emit_md(source[pos - 1], styles, ss); + } + for (int i = 0; i < 10; ++i) { + + emit(source[pos + i], styles, ss); + } + + pos += 10; + continue; + } } pos--; } + } else if (first == '[' && pos + 9 < source.size() && + source[pos + 1] == '#' && source[pos + 8] == ']') { + std::basic_string_view color_code = + source.substr(pos + 1, 8); + apply_color(color_code, styles); + if (!eraseMarkdown) { + for (int i = 0; i < 9; ++i) { + emit_md(source[pos + i], styles, ss); + } + } + pos += 9; // Skip past the color code + continue; } else if (first == '*') { - if (pos + 1 < source.size() && source[pos+1] == '*') { + if (pos + 1 < source.size() && source[pos + 1] == '*') { pos++; - if (!eraseMarkdown) - emit_md(first, styles, ss); + if (!eraseMarkdown) emit_md(first, styles, ss); style.bold = !style.bold; restyle(first, style, styles, ss, pos, eraseMarkdown); continue; @@ -121,17 +137,17 @@ Result process_markdown( style.italic = !style.italic; restyle(first, style, styles, ss, pos, eraseMarkdown); continue; - } else if (first == '_' && pos + 1 < source.size() && source[pos+1] == '_') { + } else if (first == '_' && pos + 1 < source.size() && + source[pos + 1] == '_') { pos++; - if (!eraseMarkdown) - emit_md(first, styles, ss); + if (!eraseMarkdown) emit_md(first, styles, ss); style.underline = !style.underline; restyle(first, style, styles, ss, pos, eraseMarkdown); continue; - } else if (first == '~' && pos + 1 < source.size() && source[pos+1] == '~') { + } else if (first == '~' && pos + 1 < source.size() && + source[pos + 1] == '~') { pos++; - if (!eraseMarkdown) - emit_md(first, styles, ss); + if (!eraseMarkdown) emit_md(first, styles, ss); style.strikethrough = !style.strikethrough; restyle(first, style, styles, ss, pos, eraseMarkdown); continue; @@ -149,6 +165,8 @@ Result markdown::process(std::string_view source, bool eraseMarkdown) { return process_markdown(source, eraseMarkdown); } -Result markdown::process(std::wstring_view source, bool eraseMarkdown) { +Result markdown::process( + std::wstring_view source, bool eraseMarkdown +) { return process_markdown(source, eraseMarkdown); } From acb07c6664fb656ef6c0f9e0ce345f9560b6f656 Mon Sep 17 00:00:00 2001 From: GHOST11111100 Date: Wed, 15 Jan 2025 21:28:52 +0300 Subject: [PATCH 5/5] fixed color code highlight --- src/graphics/ui/markdown.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/graphics/ui/markdown.cpp b/src/graphics/ui/markdown.cpp index 8616facd..44991804 100644 --- a/src/graphics/ui/markdown.cpp +++ b/src/graphics/ui/markdown.cpp @@ -114,10 +114,8 @@ Result process_markdown( } pos--; } - } else if (first == '[' && pos + 9 < source.size() && - source[pos + 1] == '#' && source[pos + 8] == ']') { - std::basic_string_view color_code = - source.substr(pos + 1, 8); + } else if (first == '[' && pos + 9 <= source.size() && source[pos + 1] == '#' && source[pos + 8] == ']') { + std::basic_string_view color_code = source.substr(pos + 1, 8); apply_color(color_code, styles); if (!eraseMarkdown) { for (int i = 0; i < 9; ++i) {