I'm working on an application using ImGui for the UI, and I'm having trouble displaying special characters like the Indian Rupee symbol (₹) in my ImGui windows. Currently, these characters are showing up as ?
instead of the correct symbols.I'm specifically using OpenGL as the underlying renderer.
Here's what I've done so far:
Loaded a Font: I made sure to load a font that should support special characters.
Replacement Function: I have a function that replaces certain placeholder strings with special characters.
I have a function that replaces certain placeholder strings with special characters, including the Indian Rupee symbol. Here's the function:
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", "₹"}
// Added mapping for the Indian Rupee symbol }; 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; }
Im getting the following result for some special chars enter image description here
here you can see the code about conversion and rendering methods
or
for (size_t i = 0; i < contents.size();) {
// Get the Unicode value of the current character and convert it to 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;
// Render the character
draw_list->AddText(retrievedFont, retrievedFont->FontSize, adjusted_pen_pos, ImGui::GetColorU32(text_color), charStr.c_str(), NULL, 0.0f, NULL);
}
// Console output
// contents :: Char's : ₹ $ £ ¥ € ₠ ₡ ₤ ₥ ₦ ₧ ₨ ₩ ₪ ₫ € ₭ ₮ ₯ ₰ ₱ ₲ ₳ ₴ ₵ ₶ ₷ ₸ ₹ ₺ ₻ ₼ ₽ ₾ ₿
// charStr :: unicode :: 32
// charStr :: C unicode :: 67
// charStr :: h unicode :: 104
// charStr :: a unicode :: 97
// charStr :: r unicode :: 114
// charStr :: ' unicode :: 39
// charStr :: s unicode :: 115
// charStr :: unicode :: 32
// charStr :: : unicode :: 58
// charStr :: unicode :: 32
// charStr :: ₹ unicode :: 8377
// charStr :: unicode :: 32
// charStr :: $ unicode :: 36
// charStr :: unicode :: 32
// charStr :: £ unicode :: 163
// charStr :: unicode :: 32
// charStr :: ¥ unicode :: 165
// charStr :: unicode :: 32
// charStr :: € unicode :: 8364
// charStr :: unicode :: 32
// charStr :: ₠ unicode :: 8352
// charStr :: unicode :: 32
// charStr :: ₡ unicode :: 8353
// charStr :: unicode :: 32
// charStr :: ₤ unicode :: 8356
// charStr :: unicode :: 9
// charStr :: ₥ unicode :: 8357
// charStr :: unicode :: 32
// charStr :: ₦ unicode :: 8358
// charStr :: unicode :: 32
// charStr :: ₧ unicode :: 8359
// charStr :: unicode :: 9
// charStr :: ₨ unicode :: 8360
// charStr :: unicode :: 32
// charStr :: ₩ unicode :: 8361
// charStr :: unicode :: 32
// charStr :: ₪ unicode :: 8362
// charStr :: unicode :: 9
// charStr :: ₫ unicode :: 8363
// charStr :: unicode :: 32
// charStr :: € unicode :: 8364
// charStr :: unicode :: 32
// charStr :: ₭ unicode :: 8365
// charStr :: unicode :: 32
// charStr :: ₮ unicode :: 8366
// charStr :: unicode :: 32
// charStr :: ₯ unicode :: 8367
// charStr :: unicode :: 32
// charStr :: ₰ unicode :: 8368
// charStr :: unicode :: 32
// charStr :: ₱ unicode :: 8369
// charStr :: unicode :: 32
// charStr :: ₲ unicode :: 8370
// charStr :: unicode :: 32
// charStr :: ₳ unicode :: 8371
// charStr :: unicode :: 32
// charStr :: ₴ unicode :: 8372
// charStr :: unicode :: 32
// charStr :: ₵ unicode :: 8373
// charStr :: unicode :: 32
// charStr :: ₶ unicode :: 8374
// charStr :: unicode :: 32
// charStr :: ₷ unicode :: 8375
-------------------------------------- Font loading code ---------------------------------------
// Function to load fonts for ImGui in a custom application
void workose_studio_load_fonts()
{
std::string defaultfont = workose_project_root_directory + "fonts/Roboto-Regular.ttf";
// Get ImGui input/output configuration
ImGuiIO &io = ImGui::GetIO();
ImFontConfig config;
// Get the default glyph range for the font
const ImWchar *glyph_ranges = io.Fonts->GetGlyphRangesDefault();
// Add the default font to ImGui with specified parameters
ImFont *font = ImGui::GetIO().Fonts->AddFontFromFileTTF(
defaultfont.c_str(),
18,
&config,
glyph_ranges);
// Store information about the default font
workose_studio_font_data.font = font;
workose_studio_font_data.path = defaultfont;
// Map the default font information to the key "default"
workose_studio_g_myFonts.fontMap["default"] = workose_studio_font_data;
// Get the glyph range for Chinese characters
const ImWchar *glyph_ranges1 = io.Fonts->GetGlyphRangesChineseFull();
// Initialize an array to store font names
std::vector<std::string> font_name;
// Check if layout and element details are available
if (workose_studio_get_layout_and_element_details.size() > 0)
{
// Iterate over layout elements
for (nlohmann::json::iterator it = workose_studio_get_layout_and_element_details[0][0].begin(); it != workose_studio_get_layout_and_element_details[0][0].end(); ++it)
{
nlohmann::json layout_elements = it.value()["layout_elements"];
// Iterate over layout element details
for (nlohmann::json::iterator it = layout_elements.begin(); it != layout_elements.end(); ++it)
{
std::string element_type = it.value()["LAYOUT_ELEMENT_TYPE"];
// Check if the element type is "text"
if (element_type == "text")
{
nlohmann::json paragraphs;
// Extract and decode element JSON style attributes
std::string element_json_style_attributes = it.value()["ELEMENT_JSON_STYLE_ATTRIBUTES"];
std::string decode_data = urldecode(element_json_style_attributes);
nlohmann::json json_data = nlohmann::json::parse(decode_data);
// Check for the presence of specific style attributes
if (json_data.find("frame_style") != json_data.end() && json_data["frame_style"].find("tableDetils") != json_data["frame_style"].end())
{
// Check if the "tableDetils" field is empty
if (json_data["frame_style"]["tableDetils"].empty())
{
nlohmann::json decoded_json = nlohmann::json::parse(decode_data);
// Check for the presence of "paragraphs" in the decoded JSON
if (decoded_json.contains("paragraphs"))
{
paragraphs = decoded_json["paragraphs"];
// Store used fonts from paragraphs
storeusedfonts(paragraphs);
}
}
else
{
// table condition
const nlohmann::json &frame_style = json_data["frame_style"];
// Check for the presence of "tableDetils" in "frame_style"
if (frame_style.contains("tableDetils"))
{
const nlohmann::json &table_details = frame_style["tableDetils"];
// Check for the presence of "tableContentArray" in "tableDetils"
if (table_details.contains("tableContentArray"))
{
const nlohmann::json &table_content_array = table_details["tableContentArray"];
size_t numColumns = table_content_array[std::to_string(0)].size();
// Iterate over table columns and rows
for (size_t x = 0; x < numColumns; ++x)
{
for (size_t j = 0; j < table_content_array.size(); ++j)
{
const nlohmann::json &row_j = table_content_array[std::to_string(j)];
// Check for the presence of the current column in the current row
if (row_j.contains(std::to_string(x)))
{
const nlohmann::json &cell_ij = row_j[std::to_string(x)];
// Check for the presence of "style" in the cell
if (cell_ij.contains("style"))
{
const nlohmann::json &styleObj = cell_ij["style"];
// Check for the presence of "paragraphs" in the style
if (styleObj.contains("paragraphs"))
{
paragraphs = styleObj["paragraphs"];
// Store used fonts from paragraphs
storeusedfonts(paragraphs);
}
}
}
}
}
}
}
}
}
}
}
}
}
}
The Rupee sign (U+20B9) is not covered by the ImGui default glyph range or the Chinese range. You need to construct a custom glyph range (just pairs of start and stop codepoints) and specify that when loading the font. Same for the other missing glyphs.
The FAQ entry for this has the following examples:
ImVector<ImWchar> ranges;
ImFontGlyphRangesBuilder builder;
builder.AddText("Hello world"); // Add a string (here "Hello world" contains 7 unique characters)
builder.AddChar(0x20B9); // Add a specific character
builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges
builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted)
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", 16.0f, nullptr, ranges.Data);