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 ab328e66..44991804 100644 --- a/src/graphics/ui/markdown.cpp +++ b/src/graphics/ui/markdown.cpp @@ -1,5 +1,6 @@ #include "markdown.hpp" +#include "coders/commons.hpp" #include "graphics/core/Font.hpp" using namespace markdown; @@ -9,7 +10,7 @@ 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 @@ -20,6 +21,38 @@ static inline void emit_md( styles.map.emplace_back(0); } +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 + } + + 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]), + 1 + ); +} + +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); +} + template static inline void restyle( CharT c, @@ -43,13 +76,14 @@ 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; int pos = 0; while (pos < source.size()) { CharT first = source[pos]; + if (first == '\\') { if (pos + 1 < source.size()) { CharT second = source[++pos]; @@ -63,14 +97,37 @@ 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; @@ -78,17 +135,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; @@ -106,6 +163,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); }