You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ImGui窗口中显示₹、₤、₿等特殊字符?

问题:ImGui+OpenGL应用中特殊字符(如₹)显示为问号的解决方法

开发基于ImGui和OpenGL的应用时,印度卢比符号(₹)等特殊字符渲染时显示为?。控制台输出显示特殊字符的Unicode值正确,但渲染失败。已完成以下操作:

  • 加载了声称支持特殊字符的Roboto-Regular.ttf字体
  • 实现了占位符到特殊字符的替换函数,包含₹的映射

相关代码

替换函数

std::string replaceSpecialChars(const std::string& str) {
    std::string replacedStr = str;
    std::map<std::string, std::string> replacements = {
        {"1397904493", "®"}, {"1397776754", "¶"}, {"1400073811", "§"},
        {"1396991858", "°"}, {"1396929140", "©"}, {"1398041963", "™"},
        {"1397059140", "–"}, {"1397058884", "—"}, {"1397969521", "’"},
        {"1397967985", "‘"}, {"1396986737", "\""}, {"1397969777", "'"},
        {"1397645907", " "}, {"1396984945", "“"}, {"1396986481", "”"},
        {"1396862068", "•"}, {"1397518451", "…"}, {"1398320179", "₹"}
    };
    for (const auto &pair : replacements) {
        size_t pos = replacedStr.find(pair.first);
        while (pos != std::string::npos) {
            replacedStr.replace(pos, pair.first.length(), pair.second);
            pos = replacedStr.find(pair.first, pos + 1);
        }
    }
    return replacedStr;
}

渲染代码

for (size_t i = 0; i < contents.size();) {
    // 获取当前字符的Unicode值并转换为UTF-8
    uint32_t unicode = workose_studio_getUTF8Unicode(contents, i);
    std::string charStr = utf8::utf32to8(std::u32string(1, unicode));
    std::cout << " charStr :: " << charStr << " unicode :: " << unicode << std::endl;
    // 渲染字符
    draw_list->AddText(retrievedFont, retrievedFont->FontSize, adjusted_pen_pos, ImGui::GetColorU32(text_color), charStr.c_str(), NULL, 0.0f, NULL);
}

// 控制台输出片段
// contents :: Char's : ₹ $ £ ¥ € ₠ ₡ ₤ ₥ ₦ ₧ ₨ ₩ ₪ ₫ € ₭ ₮ ₯ ₰ ₱ ₲ ₳ ₴ ₵ ₶ ₷ ₸ ₹ ₺ ₻ ₼ ₽ ₾ ₿
// charStr :: ₹ unicode :: 8377
// ...其余字符输出

字体加载代码

// 为ImGui加载字体的自定义函数
void workose_studio_load_fonts()
{
    std::string defaultfont = workose_project_root_directory + "fonts/Roboto-Regular.ttf";

    // 获取ImGui IO配置
    ImGuiIO &io = ImGui::GetIO();
    ImFontConfig config;

    // 获取默认字体Glyph范围
    const ImWchar *glyph_ranges = io.Fonts->GetGlyphRangesDefault();

    // 添加默认字体到ImGui
    ImFont *font = ImGui::GetIO().Fonts->AddFontFromFileTTF(
        defaultfont.c_str(),
        18,
        &config,
        glyph_ranges);

    // 存储默认字体信息
    workose_studio_font_data.font = font;
    workose_studio_font_data.path = defaultfont;
    workose_studio_g_myFonts.fontMap["default"] = workose_studio_font_data;

    // 获取中文全字符Glyph范围(未使用)
    const ImWchar *glyph_ranges1 = io.Fonts->GetGlyphRangesChineseFull();

    std::vector<std::string> font_name;

    // 从布局元素中提取并存储使用的字体(略)
    if (workose_studio_get_layout_and_element_details.size() > 0)
    {
        // ...原有遍历逻辑
    }
}

解决方案

1. 扩展字体Glyph范围

默认的GetGlyphRangesDefault()仅包含基础ASCII和少量扩展字符,不包含₹(U+20B9)等货币符号。需替换为包含目标字符的Glyph范围:

// 方法1:使用全字符范围(内存占用较大)
const ImWchar* glyph_ranges = io.Fonts->GetGlyphRangesFull();

// 方法2:自定义范围,仅包含需要的字符(推荐)
static const ImWchar custom_ranges[] = {
    0x0020, 0x00FF, // 基础ASCII+扩展拉丁字符
    0x20A0, 0x20CF, // 货币符号区间(包含₹ U+20B9)
    0x0000, // 必须以0结尾
};
const ImWchar* glyph_ranges = custom_ranges;

将上述代码替换字体加载中的glyph_ranges定义,确保目标字符被包含。

2. 验证字体对目标字符的支持

用字体查看工具(如FontForge)检查Roboto-Regular.ttf是否包含₹符号。如果缺失,替换为已知支持的字体(如Noto Sans)。

3. 确保字体加载后重建纹理

加载字体后必须重建字体纹理并上传到GPU,否则新Glyph不会生效。在workose_studio_load_fonts()末尾添加:

// 重建字体纹理
io.Fonts->Build();

// 自定义OpenGL渲染器需手动上传纹理
GLuint font_texture;
glGenTextures(1, &font_texture);
glBindTexture(GL_TEXTURE_2D, font_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, io.Fonts->TexWidth, io.Fonts->TexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, io.Fonts->TexPixels);

// 将纹理ID传给ImGui
io.Fonts->TexID = (void*)(intptr_t)font_texture;

若使用ImGui默认OpenGL绑定器,此步骤可能已自动处理,但自定义渲染器需手动执行。

4. 简化渲染逻辑

ImGui原生支持UTF-8字符串渲染,无需手动拆分字符,避免编码错误:

// 直接渲染完整UTF-8字符串
draw_list->AddText(retrievedFont, retrievedFont->FontSize, adjusted_pen_pos, ImGui::GetColorU32(text_color), contents.c_str());

内容的提问来源于stack exchange,提问作者vinith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 12:44:49