imgui富文本的实现


关于imgui的richtext,issue有一篇文章一直讨论这个的,但是好像也没有特别好的办法

两种实现

自己参考了两个实现[1],做了下,大体思想是在imgui 渲染的地方根据字符串中特别标识的字段重新获取颜色出来。两种方法差不多,只是特别标识用的方法不太一样

用##aabbccdd这种颜色标识

实现代码

bool ParseColor(const char* s, ImU32* col) {
    *col = 0;
    if (s[0] != '#' || s[1] != '#') {
        return false;
    }
    else {
        for (int i = 0; i < 8; ++i) {
            *col *= 16;
            char c = s[i + 2];
            if (c >= '0' && c <= '9') {
                *col += c - '0';
            }
            else if (c >= 'A' && c <= 'F') {
                *col += c - 'A' + 10;
            }
            else if (c >= 'a' && c <= 'f') {
                *col += c - 'a' + 10;
            }
            else {
                return false;
            }
        }
        ImU32 flip_col = 0;
        for (int i = 0; i < 4; ++i) {
            flip_col <<= 8;
            flip_col += (*col >> 8 * i) & 0x000000FF;
        }
        *col = flip_col;
        return true;
    }
}

然后在RenderText里面根据这个标识把颜色取出来

void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) const
// 省略...
    {
        int index = 0;
        int chain = 0;
        const char* s = text_begin;
        ImU32 temp_col;
        while (s < text_end) {
            if (s < text_end - 10 && ParseColor(s, &temp_col)) {
                col = temp_col;
                s += 10;
            }
            else {
                char_buf[index] = *s;
                col_buf[index] = col;
                ++index;
                ++s;
            }
        }
        text_begin = &char_buf[0];
        text_end = &char_buf[index];
    }

使用的时候如下:

ImGui::Text("##FF0000FFdear imgui says hello. (%s)", IMGUI_VERSION);

第二种做法是用Xterm color

代码实现和上面其实差不多,也是主要识别出那些字符是表示颜色的,然后把颜色摘出来不去绘制

// 识别颜色标识
bool ParseColor(const char* s, ImU32* col, int* skipChars)
    {
        if (s[0] != '\033' || s[1] != '[') {
            return false;
        }
        if (s[2] == 'm') {
            *col = 0xffcccccc;
            *skipChars = 3;
            return true;
        }
        if (s[2] == '0' && s[3] == 'm') {
            *col = 0xffcccccc;
            *skipChars = 4;
            return true;
        }
        const char* seqEnd = &s[2];
        while (*seqEnd != 'm') {
            seqEnd++;
        }
        std::string seq{ &s[2], seqEnd };
        std::string colorStr;
        for (const auto& el : jet::split(seq, ";")) {
            if (el[0] == '3' && el.size() == 2) {
                colorStr = el;
                break;
            }
        }
        if (!colorStr.empty()) {
            switch (colorStr[1]) {
            case '0': *col = 0xffcccccc; break;
            case '1': *col = 0xff7a77f2; break;
            case '2': *col = 0xff99cc99; break;
            case '3': *col = 0xff66ccff; break;
            case '4': *col = 0xffcc9966; break;
            case '5': *col = 0xffcc99cc; break;
            case '6': *col = 0xffcccc66; break;
            case '7': *col = 0xff2d2d2d; break;
            default: return false;
            }
        }
        *skipChars = static_cast<int>(seqEnd - s + 1);
        return true;
    }

// 渲染时候调用处理
{
            for (int i = 0; i < text_end - text_begin; i++) {
                char_skip[i] = false;
            }
            int index = 0;
            int skipChars = 0;
            const char* sLocal = s;
            ImU32 temp_col = col;
            while (sLocal < text_end) {
                if (sLocal < text_end - 4 && ParseColor(sLocal, &temp_col, &skipChars)) {
                    sLocal += skipChars;
                    for (int i = 0; i < skipChars; i++) {
                        char_skip[index + i] = true;
                    }
                    index += skipChars;
                }
                else {
                    char_buf[index] = *sLocal;
                    col_buf[index] = temp_col;
                    char_skip[index] = false;
                    ++index;
                    ++sLocal;
                }
            }
        }

使用代码

ImGui::TextRichColored(ImVec4(1, 0, 0, 1), "xxxxxxxxxxxx\033[48;5;34m xxxxxxxx  \033[48;5;35m yyyy");

说明:

  • 这里的ParseColor里面可以看到只支持一部分颜色,这是处理的不太好的地方,其实还有很多,可以看下参考[2][3]里面的256种颜色还是有很多的。最主要的是,他这里的颜色和真正的xterm颜色好像木有对上

ANSI and xterm color maps

参考[2]里面介绍了下Xterm的东东,大概是这种标识符不仅可以表示颜色,还可以表示一些控制的东东。但是有一部分标识码是用来表示256种颜色的

^[[99999S^[[99999;1HSystem colors (0..15 from xterm palette):
^[[48;5;0m  ^[[48;5;1m  ^[[48;5;2m  ^[[48;5;3m  ^[[48;5;4m  ^[[48;5;5m  ^[[48;5;6m  ^[[48;5;7m  ^[[0m
^[[48;5;8m  ^[[48;5;9m  ^[[48;5;10m  ^[[48;5;11m  ^[[48;5;12m  ^[[48;5;13m  ^[[48;5;14m  ^[[48;5;15m  ^[[0m

Color cube, 6x6x6 (16..231 from xterm palette):
^[[48;5;16m  ^[[48;5;17m  ^[[48;5;18m  ^[[48;5;19m  ^[[48;5;20m  ^[[48;5;21m  ^[[0m ^[[48;5;52m  ^[[48;5;53m  ^[[48;5;54m  ^[[48;5;55m  ^[[48;5;56m  ^[[48;5;57m  ^[[0m ^[[48;5;88m  ^[[48;5;89m  ^[[48;5;90m  ^[[48;5;91m  ^[[48;5;92m  ^[[48;5;93m  ^[[0m ^[[48;5;124m  ^[[48;5;125m  ^[[48;5;126m  ^[[48;5;127m  ^[[48;5;128m  ^[[48;5;129m  ^[[0m ^[[48;5;160m  ^[[48;5;161m  ^[[48;5;162m  ^[[48;5;163m  ^[[48;5;164m  ^[[48;5;165m  ^[[0m ^[[48;5;196m  ^[[48;5;197m  ^[[48;5;198m  ^[[48;5;199m  ^[[48;5;200m  ^[[48;5;201m  ^[[0m 
^[[48;5;22m  ^[[48;5;23m  ^[[48;5;24m  ^[[48;5;25m  ^[[48;5;26m  ^[[48;5;27m  ^[[0m ^[[48;5;58m  ^[[48;5;59m  ^[[48;5;60m  ^[[48;5;61m  ^[[48;5;62m  ^[[48;5;63m  ^[[0m ^[[48;5;94m  ^[[48;5;95m  ^[[48;5;96m  ^[[48;5;97m  ^[[48;5;98m  ^[[48;5;99m  ^[[0m ^[[48;5;130m  ^[[48;5;131m  ^[[48;5;132m  ^[[48;5;133m  ^[[48;5;134m  ^[[48;5;135m  ^[[0m ^[[48;5;166m  ^[[48;5;167m  ^[[48;5;168m  ^[[48;5;169m  ^[[48;5;170m  ^[[48;5;171m  ^[[0m ^[[48;5;202m  ^[[48;5;203m  ^[[48;5;204m  ^[[48;5;205m  ^[[48;5;206m  ^[[48;5;207m  ^[[0m 
^[[48;5;28m  ^[[48;5;29m  ^[[48;5;30m  ^[[48;5;31m  ^[[48;5;32m  ^[[48;5;33m  ^[[0m ^[[48;5;64m  ^[[48;5;65m  ^[[48;5;66m  ^[[48;5;67m  ^[[48;5;68m  ^[[48;5;69m  ^[[0m ^[[48;5;100m  ^[[48;5;101m  ^[[48;5;102m  ^[[48;5;103m  ^[[48;5;104m  ^[[48;5;105m  ^[[0m ^[[48;5;136m  ^[[48;5;137m  ^[[48;5;138m  ^[[48;5;139m  ^[[48;5;140m  ^[[48;5;141m  ^[[0m ^[[48;5;172m  ^[[48;5;173m  ^[[48;5;174m  ^[[48;5;175m  ^[[48;5;176m  ^[[48;5;177m  ^[[0m ^[[48;5;208m  ^[[48;5;209m  ^[[48;5;210m  ^[[48;5;211m  ^[[48;5;212m  ^[[48;5;213m  ^[[0m 
^[[48;5;34m  ^[[48;5;35m  ^[[48;5;36m  ^[[48;5;37m  ^[[48;5;38m  ^[[48;5;39m  ^[[0m ^[[48;5;70m  ^[[48;5;71m  ^[[48;5;72m  ^[[48;5;73m  ^[[48;5;74m  ^[[48;5;75m  ^[[0m ^[[48;5;106m  ^[[48;5;107m  ^[[48;5;108m  ^[[48;5;109m  ^[[48;5;110m  ^[[48;5;111m  ^[[0m ^[[48;5;142m  ^[[48;5;143m  ^[[48;5;144m  ^[[48;5;145m  ^[[48;5;146m  ^[[48;5;147m  ^[[0m ^[[48;5;178m  ^[[48;5;179m  ^[[48;5;180m  ^[[48;5;181m  ^[[48;5;182m  ^[[48;5;183m  ^[[0m ^[[48;5;214m  ^[[48;5;215m  ^[[48;5;216m  ^[[48;5;217m  ^[[48;5;218m  ^[[48;5;219m  ^[[0m 
^[[48;5;40m  ^[[48;5;41m  ^[[48;5;42m  ^[[48;5;43m  ^[[48;5;44m  ^[[48;5;45m  ^[[0m ^[[48;5;76m  ^[[48;5;77m  ^[[48;5;78m  ^[[48;5;79m  ^[[48;5;80m  ^[[48;5;81m  ^[[0m ^[[48;5;112m  ^[[48;5;113m  ^[[48;5;114m  ^[[48;5;115m  ^[[48;5;116m  ^[[48;5;117m  ^[[0m ^[[48;5;148m  ^[[48;5;149m  ^[[48;5;150m  ^[[48;5;151m  ^[[48;5;152m  ^[[48;5;153m  ^[[0m ^[[48;5;184m  ^[[48;5;185m  ^[[48;5;186m  ^[[48;5;187m  ^[[48;5;188m  ^[[48;5;189m  ^[[0m ^[[48;5;220m  ^[[48;5;221m  ^[[48;5;222m  ^[[48;5;223m  ^[[48;5;224m  ^[[48;5;225m  ^[[0m 
^[[48;5;46m  ^[[48;5;47m  ^[[48;5;48m  ^[[48;5;49m  ^[[48;5;50m  ^[[48;5;51m  ^[[0m ^[[48;5;82m  ^[[48;5;83m  ^[[48;5;84m  ^[[48;5;85m  ^[[48;5;86m  ^[[48;5;87m  ^[[0m ^[[48;5;118m  ^[[48;5;119m  ^[[48;5;120m  ^[[48;5;121m  ^[[48;5;122m  ^[[48;5;123m  ^[[0m ^[[48;5;154m  ^[[48;5;155m  ^[[48;5;156m  ^[[48;5;157m  ^[[48;5;158m  ^[[48;5;159m  ^[[0m ^[[48;5;190m  ^[[48;5;191m  ^[[48;5;192m  ^[[48;5;193m  ^[[48;5;194m  ^[[48;5;195m  ^[[0m ^[[48;5;226m  ^[[48;5;227m  ^[[48;5;228m  ^[[48;5;229m  ^[[48;5;230m  ^[[48;5;231m  ^[[0m 
Grayscale ramp (232..255 from xterm palette):
^[[48;5;232m  ^[[48;5;233m  ^[[48;5;234m  ^[[48;5;235m  ^[[48;5;236m  ^[[48;5;237m  ^[[48;5;238m  ^[[48;5;239m  ^[[48;5;240m  ^[[48;5;241m  ^[[48;5;242m  ^[[48;5;243m  ^[[48;5;244m  ^[[48;5;245m  ^[[48;5;246m  ^[[48;5;247m  ^[[48;5;248m  ^[[48;5;249m  ^[[48;5;250m  ^[[48;5;251m  ^[[48;5;252m  ^[[48;5;253m  ^[[48;5;254m  ^[[48;5;255m  ^[[0m

其中,这个^[是ascii种的ESC这个编码,也就是\033。

一开始看到这里的时候,其实我并不明白是啥意思,后来结合参考[3],大概明白了
(1) 从参考种的颜色xterm码来看,表示256种颜色不变的代码是**\033[48;5?m**,就把第三个数字换成0-255这个范围里面的字就是256种颜色
在这里插入图片描述

ANSI X3.64 and Xterm 256 colors in ConEmu
(2)参考[3]让我知道这个Xterm表示颜色的其实只有一个数字就表示了,他的范围是[00255],而还可以知道xterm和RGB对应的颜色
在这里插入图片描述

参考

[1]https://github.com/ocornut/imgui/issues/902
[2]https://conemu.github.io/en/AnsiEscapeCodes.html#SGR_Select_Graphic_Rendition_parameters
[3]https://jonasjacek.github.io/colors/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值