mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-30 22:42:03 +08:00
Merge branch 'lm_imgui_atlas'
This commit is contained in:
commit
99c8bb2dbb
@ -3282,11 +3282,20 @@ void ImFont::AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst)
|
||||
|
||||
const ImFontGlyph* ImFont::FindGlyph(ImWchar c) const
|
||||
{
|
||||
if (c >= (size_t)IndexLookup.Size)
|
||||
// PrusaSlicer extension: call the following function whenever the fallback is needed.
|
||||
// The goal is to not modify ImGui code too much.
|
||||
void imgui_rendered_fallback_glyph(ImWchar c);
|
||||
|
||||
|
||||
if (c >= (size_t)IndexLookup.Size) {
|
||||
imgui_rendered_fallback_glyph(c);
|
||||
return FallbackGlyph;
|
||||
}
|
||||
const ImWchar i = IndexLookup.Data[c];
|
||||
if (i == (ImWchar)-1)
|
||||
if (i == (ImWchar)-1) {
|
||||
imgui_rendered_fallback_glyph(c);
|
||||
return FallbackGlyph;
|
||||
}
|
||||
return &Glyphs.Data[i];
|
||||
}
|
||||
|
||||
|
@ -1823,7 +1823,7 @@ void GLCanvas3D::render()
|
||||
|
||||
#ifdef SHOW_IMGUI_DEMO_WINDOW
|
||||
if (show_imgui_demo_window) ImGui::ShowDemoWindow();
|
||||
#endif // SHOW_IMGUI_DEMO_WINDOW
|
||||
#endif // SHOW_IMGUI_DEMO_WINDOW
|
||||
|
||||
const bool is_looking_downward = camera.is_looking_downward();
|
||||
|
||||
|
@ -46,6 +46,40 @@
|
||||
// suggest location
|
||||
#include "libslic3r/ClipperUtils.hpp" // Slic3r::intersection
|
||||
|
||||
|
||||
// Following two sets keeps characters that ImGui tried to render, but they were not in the atlas,
|
||||
// and ones that we already tried to add into the atlas.
|
||||
std::set<ImWchar> s_missing_chars;
|
||||
std::set<ImWchar> s_fixed_chars;
|
||||
bool s_font_cjk;
|
||||
|
||||
// This is a free function that ImGui calls when it renders
|
||||
// a fallback glyph for c.
|
||||
void imgui_rendered_fallback_glyph(ImWchar c)
|
||||
{
|
||||
if (ImGui::GetIO().Fonts->Fonts[0] == ImGui::GetFont()) {
|
||||
// Only do this when we are using the default ImGui font. Otherwise this would conflict with
|
||||
// EmbossStyleManager's font handling and we would load glyphs needlessly.
|
||||
auto it = s_fixed_chars.find(c);
|
||||
if (it == s_fixed_chars.end()) {
|
||||
// This is the first time we are trying to fix this character.
|
||||
s_missing_chars.emplace(c);
|
||||
} else {
|
||||
// We already tried to add this, but it is still not there. There is a chance
|
||||
// that loading the CJK font would make this available.
|
||||
if (! s_font_cjk) {
|
||||
s_font_cjk = true;
|
||||
s_missing_chars.emplace(c);
|
||||
s_fixed_chars.erase(it);
|
||||
} else {
|
||||
// We did everything we could. The glyph was not available.
|
||||
// Do not try to add it anymore.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
@ -148,6 +182,47 @@ ImGuiWrapper::ImGuiWrapper()
|
||||
init_style();
|
||||
|
||||
ImGui::GetIO().IniFilename = nullptr;
|
||||
|
||||
static const ImWchar ranges_latin2[] =
|
||||
{
|
||||
0x0020, 0x00FF, // Basic Latin + Latin Supplement
|
||||
0x0100, 0x017F, // Latin Extended-A
|
||||
0,
|
||||
};
|
||||
static const ImWchar ranges_turkish[] = {
|
||||
0x0020, 0x01FF, // Basic Latin + Latin Supplement
|
||||
0x0100, 0x017F, // Latin Extended-A
|
||||
0x0180, 0x01FF, // Turkish
|
||||
0,
|
||||
};
|
||||
static const ImWchar ranges_vietnamese[] =
|
||||
{
|
||||
0x0020, 0x00FF, // Basic Latin
|
||||
0x0102, 0x0103,
|
||||
0x0110, 0x0111,
|
||||
0x0128, 0x0129,
|
||||
0x0168, 0x0169,
|
||||
0x01A0, 0x01A1,
|
||||
0x01AF, 0x01B0,
|
||||
0x1EA0, 0x1EF9,
|
||||
0,
|
||||
};
|
||||
|
||||
m_lang_glyphs_info.emplace_back("cs", ranges_latin2, false);
|
||||
m_lang_glyphs_info.emplace_back("pl", ranges_latin2, false);
|
||||
m_lang_glyphs_info.emplace_back("hu", ranges_latin2, false);
|
||||
m_lang_glyphs_info.emplace_back("sl", ranges_latin2, false);
|
||||
m_lang_glyphs_info.emplace_back("ru", ImGui::GetIO().Fonts->GetGlyphRangesCyrillic(), false); // Default + about 400 Cyrillic characters
|
||||
m_lang_glyphs_info.emplace_back("uk", ImGui::GetIO().Fonts->GetGlyphRangesCyrillic(), false);
|
||||
m_lang_glyphs_info.emplace_back("be", ImGui::GetIO().Fonts->GetGlyphRangesCyrillic(), false);
|
||||
m_lang_glyphs_info.emplace_back("tr", ranges_turkish, false);
|
||||
m_lang_glyphs_info.emplace_back("vi", ranges_vietnamese, false);
|
||||
m_lang_glyphs_info.emplace_back("ja", ImGui::GetIO().Fonts->GetGlyphRangesJapanese(), true); // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs
|
||||
m_lang_glyphs_info.emplace_back("ko", ImGui::GetIO().Fonts->GetGlyphRangesKorean(), true); // Default + Korean characters
|
||||
m_lang_glyphs_info.emplace_back("zh_TW",ImGui::GetIO().Fonts->GetGlyphRangesChineseFull(), true); // Traditional Chinese: Default + Half-Width + Japanese Hiragana/Katakana + full set of about 21000 CJK Unified Ideographs
|
||||
m_lang_glyphs_info.emplace_back("zh", ImGui::GetIO().Fonts->GetGlyphRangesChineseSimplifiedCommon(), true); // Simplified Chinese: Default + Half-Width + Japanese Hiragana/Katakana + set of 2500 CJK Unified Ideographs for common simplified Chinese
|
||||
m_lang_glyphs_info.emplace_back("th", ImGui::GetIO().Fonts->GetGlyphRangesThai(), false);
|
||||
m_lang_glyphs_info.emplace_back("else", ImGui::GetIO().Fonts->GetGlyphRangesDefault(), false);
|
||||
}
|
||||
|
||||
ImGuiWrapper::~ImGuiWrapper()
|
||||
@ -167,62 +242,18 @@ void ImGuiWrapper::set_language(const std::string &language)
|
||||
}
|
||||
|
||||
const ImWchar *ranges = nullptr;
|
||||
size_t idx = language.find('_');
|
||||
std::string lang = (idx == std::string::npos) ? language : language.substr(0, idx);
|
||||
static const ImWchar ranges_latin2[] =
|
||||
{
|
||||
0x0020, 0x00FF, // Basic Latin + Latin Supplement
|
||||
0x0100, 0x017F, // Latin Extended-A
|
||||
0,
|
||||
};
|
||||
static const ImWchar ranges_turkish[] = {
|
||||
0x0020, 0x01FF, // Basic Latin + Latin Supplement
|
||||
0x0100, 0x017F, // Latin Extended-A
|
||||
0x0180, 0x01FF, // Turkish
|
||||
0,
|
||||
};
|
||||
static const ImWchar ranges_vietnamese[] =
|
||||
{
|
||||
0x0020, 0x00FF, // Basic Latin
|
||||
0x0102, 0x0103,
|
||||
0x0110, 0x0111,
|
||||
0x0128, 0x0129,
|
||||
0x0168, 0x0169,
|
||||
0x01A0, 0x01A1,
|
||||
0x01AF, 0x01B0,
|
||||
0x1EA0, 0x1EF9,
|
||||
0,
|
||||
};
|
||||
m_font_cjk = false;
|
||||
if (lang == "cs" || lang == "pl" || lang == "hu" || lang == "sl") {
|
||||
ranges = ranges_latin2;
|
||||
} else if (lang == "ru" || lang == "uk" || lang == "be") {
|
||||
ranges = ImGui::GetIO().Fonts->GetGlyphRangesCyrillic(); // Default + about 400 Cyrillic characters
|
||||
} else if (lang == "tr") {
|
||||
ranges = ranges_turkish;
|
||||
} else if (lang == "vi") {
|
||||
ranges = ranges_vietnamese;
|
||||
} else if (lang == "ja") {
|
||||
ranges = ImGui::GetIO().Fonts->GetGlyphRangesJapanese(); // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs
|
||||
m_font_cjk = true;
|
||||
} else if (lang == "ko") {
|
||||
ranges = ImGui::GetIO().Fonts->GetGlyphRangesKorean(); // Default + Korean characters
|
||||
m_font_cjk = true;
|
||||
} else if (lang == "zh") {
|
||||
ranges = (language == "zh_TW") ?
|
||||
// Traditional Chinese
|
||||
// Default + Half-Width + Japanese Hiragana/Katakana + full set of about 21000 CJK Unified Ideographs
|
||||
ImGui::GetIO().Fonts->GetGlyphRangesChineseFull() :
|
||||
// Simplified Chinese
|
||||
// Default + Half-Width + Japanese Hiragana/Katakana + set of 2500 CJK Unified Ideographs for common simplified Chinese
|
||||
ImGui::GetIO().Fonts->GetGlyphRangesChineseSimplifiedCommon();
|
||||
m_font_cjk = true;
|
||||
} else if (lang == "th") {
|
||||
ranges = ImGui::GetIO().Fonts->GetGlyphRangesThai(); // Default + Thai characters
|
||||
} else {
|
||||
ranges = ImGui::GetIO().Fonts->GetGlyphRangesDefault(); // Basic Latin, Extended Latin
|
||||
|
||||
// Get glyph ranges for current language, std CLK flag to inform which font files need to be loaded.
|
||||
for (const auto& [lang_str, lang_ranges, lang_cjk] : m_lang_glyphs_info) {
|
||||
if (boost::istarts_with(language, lang_str) || lang_str == "else") {
|
||||
ranges = lang_ranges;
|
||||
s_font_cjk = lang_cjk;
|
||||
}
|
||||
}
|
||||
|
||||
s_missing_chars.clear();
|
||||
s_fixed_chars.clear();
|
||||
|
||||
if (ranges != m_glyph_ranges) {
|
||||
m_glyph_ranges = ranges;
|
||||
destroy_font();
|
||||
@ -371,6 +402,13 @@ void ImGuiWrapper::render()
|
||||
ImGui::Render();
|
||||
render_draw_data(ImGui::GetDrawData());
|
||||
m_new_frame_open = false;
|
||||
|
||||
if (! s_missing_chars.empty()) {
|
||||
// If there were some characters that ImGui was unable to render, we will destroy current font.
|
||||
// It will be rebuilt in the next call of new_frame including these.
|
||||
destroy_font();
|
||||
this->set_requires_extra_frame();
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGuiWrapper::button(const std::string& label, const ImVec2 &size, bool enable)
|
||||
@ -1101,16 +1139,23 @@ void ImGuiWrapper::init_font(bool compress)
|
||||
|
||||
builder.AddChar(ImWchar(0x2026)); // …
|
||||
|
||||
if (m_font_cjk) {
|
||||
// This is a temporary fix of https://github.com/prusa3d/PrusaSlicer/issues/8171. The translation
|
||||
// contains characters not in the ImGui ranges for simplified Chinese. For now, just add them manually.
|
||||
// In future, it might be worth to parse the dictionary and add all the necessary characters.
|
||||
if (s_font_cjk) {
|
||||
// https://github.com/prusa3d/PrusaSlicer/issues/8171: The translation
|
||||
// contains characters not in the ImGui ranges for simplified Chinese. Add them manually.
|
||||
// This should no longer be needed because the following block would add them automatically.
|
||||
builder.AddChar(ImWchar(0x5ED3));
|
||||
builder.AddChar(ImWchar(0x8F91));
|
||||
}
|
||||
|
||||
// Add the characters that that needed the fallback character.
|
||||
for (ImWchar c : s_missing_chars) {
|
||||
builder.AddChar(c);
|
||||
s_fixed_chars.emplace(c);
|
||||
}
|
||||
s_missing_chars.clear();
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (m_font_cjk)
|
||||
if (s_font_cjk)
|
||||
// Apple keyboard shortcuts are only contained in the CJK fonts.
|
||||
builder.AddRanges(ranges_keyboard_shortcuts);
|
||||
#endif
|
||||
@ -1118,7 +1163,13 @@ void ImGuiWrapper::init_font(bool compress)
|
||||
|
||||
//FIXME replace with io.Fonts->AddFontFromMemoryTTF(buf_decompressed_data, (int)buf_decompressed_size, m_font_size, nullptr, ranges.Data);
|
||||
//https://github.com/ocornut/imgui/issues/220
|
||||
ImFont* font = io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/" + (m_font_cjk ? "NotoSansCJK-Regular.ttc" : "NotoSans-Regular.ttf")).c_str(), m_font_size, nullptr, ranges.Data);
|
||||
ImFont* font = io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/" + "NotoSans-Regular.ttf").c_str(), m_font_size, nullptr, ranges.Data);
|
||||
if (s_font_cjk) {
|
||||
ImFontConfig config;
|
||||
config.MergeMode = true;
|
||||
io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/" + "NotoSansCJK-Regular.ttc").c_str(), m_font_size, &config, ranges.Data);
|
||||
}
|
||||
|
||||
if (font == nullptr) {
|
||||
font = io.Fonts->AddFontDefault();
|
||||
if (font == nullptr) {
|
||||
@ -1126,16 +1177,6 @@ void ImGuiWrapper::init_font(bool compress)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
ImFontConfig config;
|
||||
config.MergeMode = true;
|
||||
if (! m_font_cjk) {
|
||||
// Apple keyboard shortcuts are only contained in the CJK fonts.
|
||||
[[maybe_unused]]ImFont *font_cjk = io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/NotoSansCJK-Regular.ttc").c_str(), m_font_size, &config, ranges_keyboard_shortcuts);
|
||||
assert(font_cjk != nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
float font_scale = m_font_size/15;
|
||||
int icon_sz = lround(16 * font_scale); // default size of icon is 16 px
|
||||
|
||||
@ -1514,6 +1555,13 @@ void ImGuiWrapper::destroy_font()
|
||||
io.Fonts->TexID = 0;
|
||||
glsafe(::glDeleteTextures(1, &m_font_texture));
|
||||
m_font_texture = 0;
|
||||
|
||||
// We have destroyed current font, including all characters that we may have added dynamically.
|
||||
// Move move all characters that we already added into the list of missing chars again,
|
||||
// so they are all added at once.
|
||||
for (ImWchar c : s_fixed_chars)
|
||||
s_missing_chars.emplace(c);
|
||||
s_fixed_chars.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,9 +31,9 @@ namespace GUI {
|
||||
|
||||
class ImGuiWrapper
|
||||
{
|
||||
std::vector<std::tuple<std::string, const ImWchar*, bool>> m_lang_glyphs_info; // language prefix, ranges, whether it needs CLK font
|
||||
const ImWchar* m_glyph_ranges{ nullptr };
|
||||
// Chinese, Japanese, Korean
|
||||
bool m_font_cjk{ false };
|
||||
float m_font_size{ 18.0 };
|
||||
unsigned m_font_texture{ 0 };
|
||||
float m_style_scaling{ 1.0 };
|
||||
|
Loading…
x
Reference in New Issue
Block a user