diff --git a/dep/imgui/include/IconsEmoji.h b/dep/imgui/include/IconsEmoji.h index cdae5fed5..991e3a871 100644 --- a/dep/imgui/include/IconsEmoji.h +++ b/dep/imgui/include/IconsEmoji.h @@ -30,3 +30,4 @@ #define ICON_EMOJI_REFRESH "\xf0\x9f\x94\x84" #define ICON_EMOJI_PROHIBITED "\xf0\x9f\x9a\xab" #define ICON_EMOJI_CALENDAR "\xF0\x9F\x93\x85" +#define ICON_EMOJI_HOURGLASS "\xe2\x8f\xb3" diff --git a/src/core/achievements.cpp b/src/core/achievements.cpp index d081746cb..8f0e067f4 100644 --- a/src/core/achievements.cpp +++ b/src/core/achievements.cpp @@ -205,8 +205,9 @@ static void LeaderboardFetchAllCallback(int result, const char* error_message, r #ifndef __ANDROID__ static void DrawAchievement(const rc_client_achievement_t* cheevo); static void DrawLeaderboardListEntry(const rc_client_leaderboard_t* lboard); -static void DrawLeaderboardEntry(const rc_client_leaderboard_entry_t& entry, bool is_self, float rank_column_width, - float name_column_width, float time_column_width, float column_spacing); +static void DrawLeaderboardEntry(const rc_client_leaderboard_entry_t& entry, u32 index, bool is_self, + float rank_column_width, float name_column_width, float time_column_width, + float column_spacing); #endif static std::string GetHashDatabasePath(); @@ -2782,7 +2783,6 @@ void Achievements::DrawAchievementsWindow() const ImVec4 background = ImGuiFullscreen::ModAlpha(UIStyle.BackgroundColor, alpha); const ImVec4 heading_background = ImGuiFullscreen::ModAlpha(UIStyle.BackgroundColor, heading_alpha); const ImVec2 display_size = ImGui::GetIO().DisplaySize; - const u32 text_color = ImGui::GetColorU32(ImGuiCol_Text); const float heading_height = LayoutScale(heading_height_unscaled); bool close_window = false; @@ -2832,8 +2832,8 @@ void Achievements::DrawAchievementsWindow() top += UIStyle.LargeFont->FontSize + spacing; - RenderShadowedTextClipped(UIStyle.LargeFont, title_bb.Min, title_bb.Max, text_color, text.c_str(), text.end_ptr(), - nullptr, ImVec2(0.0f, 0.0f), 0.0f, &title_bb); + RenderShadowedTextClipped(UIStyle.LargeFont, title_bb.Min, title_bb.Max, ImGui::GetColorU32(ImGuiCol_Text), + text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), 0.0f, &title_bb); const ImRect summary_bb(ImVec2(left, top), ImVec2(right, top + UIStyle.MediumFont->FontSize)); if (s_state.game_summary.num_core_achievements > 0) @@ -2858,8 +2858,10 @@ void Achievements::DrawAchievementsWindow() top += UIStyle.MediumFont->FontSize + spacing; - RenderShadowedTextClipped(UIStyle.MediumFont, summary_bb.Min, summary_bb.Max, text_color, text.c_str(), - text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), 0.0f, &summary_bb); + RenderShadowedTextClipped( + UIStyle.MediumFont, summary_bb.Min, summary_bb.Max, + ImGui::GetColorU32(ImGuiFullscreen::DarkerColor(ImGui::GetStyle().Colors[ImGuiCol_Text])), text.c_str(), + text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), 0.0f, &summary_bb); if (s_state.game_summary.num_core_achievements > 0) { @@ -3160,6 +3162,7 @@ bool Achievements::PrepareLeaderboardsWindow() void Achievements::DrawLeaderboardsWindow() { + using ImGuiFullscreen::DarkerColor; using ImGuiFullscreen::LayoutScale; using ImGuiFullscreen::RenderShadowedTextClipped; using ImGuiFullscreen::UIStyle; @@ -3180,6 +3183,7 @@ void Achievements::DrawLeaderboardsWindow() bool close_leaderboard_on_exit = false; ImRect bb; + SmallString text; const ImVec4 background = ImGuiFullscreen::ModAlpha(ImGuiFullscreen::UIStyle.BackgroundColor, alpha); const ImVec4 heading_background = ImGuiFullscreen::ModAlpha(ImGuiFullscreen::UIStyle.BackgroundColor, heading_alpha); @@ -3239,7 +3243,6 @@ void Achievements::DrawLeaderboardsWindow() float left = bb.Min.x + padding + image_height + spacing; float right = bb.Max.x - padding; float top = bb.Min.y + padding; - SmallString text; if (!is_leaderboard_open) { @@ -3268,6 +3271,7 @@ void Achievements::DrawLeaderboardsWindow() RenderShadowedTextClipped(UIStyle.LargeFont, title_bb.Min, title_bb.Max, text_color, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), 0.0f, &title_bb); + u32 summary_color; if (is_leaderboard_open) { const ImRect subtitle_bb(ImVec2(left, top), ImVec2(right, top + UIStyle.LargeFont->FontSize)); @@ -3275,10 +3279,12 @@ void Achievements::DrawLeaderboardsWindow() top += UIStyle.LargeFont->FontSize + spacing_small; - RenderShadowedTextClipped(UIStyle.LargeFont, subtitle_bb.Min, subtitle_bb.Max, text_color, text.c_str(), - text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), 0.0f, &subtitle_bb); + RenderShadowedTextClipped(UIStyle.LargeFont, subtitle_bb.Min, subtitle_bb.Max, + ImGui::GetColorU32(DarkerColor(ImGui::GetStyle().Colors[ImGuiCol_Text])), + text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), 0.0f, &subtitle_bb); text.assign(s_state.open_leaderboard->description); + summary_color = ImGui::GetColorU32(DarkerColor(DarkerColor(ImGui::GetStyle().Colors[ImGuiCol_Text]))); } else { @@ -3286,12 +3292,13 @@ void Achievements::DrawLeaderboardsWindow() for (u32 i = 0; i < s_state.leaderboard_list->num_buckets; i++) count += s_state.leaderboard_list->buckets[i].num_leaderboards; text = TRANSLATE_PLURAL_SSTR("Achievements", "This game has %n leaderboards.", "Leaderboard count", count); + summary_color = ImGui::GetColorU32(DarkerColor(ImGui::GetStyle().Colors[ImGuiCol_Text])); } const ImRect summary_bb(ImVec2(left, top), ImVec2(right, top + UIStyle.MediumFont->FontSize)); top += UIStyle.MediumFont->FontSize + spacing_small; - RenderShadowedTextClipped(UIStyle.MediumFont, summary_bb.Min, summary_bb.Max, text_color, text.c_str(), + RenderShadowedTextClipped(UIStyle.MediumFont, summary_bb.Min, summary_bb.Max, summary_color, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), 0.0f, &summary_bb); if (!is_leaderboard_open && !Achievements::IsHardcoreModeActive()) @@ -3299,11 +3306,15 @@ void Achievements::DrawLeaderboardsWindow() const ImRect hardcore_warning_bb(ImVec2(left, top), ImVec2(right, top + UIStyle.MediumFont->FontSize)); top += UIStyle.MediumFont->FontSize + spacing_small; - RenderShadowedTextClipped( - UIStyle.MediumFont, hardcore_warning_bb.Min, hardcore_warning_bb.Max, text_color, - TRANSLATE("Achievements", - "Submitting scores is disabled because hardcore mode is off. Leaderboards are read-only."), - nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f, &hardcore_warning_bb); + text.format( + ICON_EMOJI_WARNING " {}", + TRANSLATE_SV("Achievements", + "Submitting scores is disabled because hardcore mode is off. Leaderboards are read-only.")); + + RenderShadowedTextClipped(UIStyle.MediumFont, hardcore_warning_bb.Min, hardcore_warning_bb.Max, + ImGui::GetColorU32(DarkerColor(DarkerColor(ImGui::GetStyle().Colors[ImGuiCol_Text]))), + text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), 0.0f, + &hardcore_warning_bb); } if (is_leaderboard_open) @@ -3349,17 +3360,19 @@ void Achievements::DrawLeaderboardsWindow() bb.Min.x += LayoutScale(ImGuiFullscreen::LAYOUT_MENU_WINDOW_X_PADDING); bb.Max.x -= LayoutScale(ImGuiFullscreen::LAYOUT_MENU_WINDOW_X_PADDING); + const u32 heading_color = ImGui::GetColorU32(DarkerColor(ImGui::GetStyle().Colors[ImGuiCol_Text])); + const float midpoint = bb.Min.y + UIStyle.LargeFont->FontSize + LayoutScale(4.0f); float text_start_x = bb.Min.x + LayoutScale(15.0f) + padding; const ImRect rank_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(bb.Max.x, midpoint)); - RenderShadowedTextClipped(UIStyle.LargeFont, rank_bb.Min, rank_bb.Max, text_color, + RenderShadowedTextClipped(UIStyle.LargeFont, rank_bb.Min, rank_bb.Max, heading_color, TRANSLATE("Achievements", "Rank"), nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f, &rank_bb); text_start_x += rank_column_width + column_spacing; const ImRect user_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(bb.Max.x, midpoint)); - RenderShadowedTextClipped(UIStyle.LargeFont, user_bb.Min, user_bb.Max, text_color, + RenderShadowedTextClipped(UIStyle.LargeFont, user_bb.Min, user_bb.Max, heading_color, TRANSLATE("Achievements", "Name"), nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f, &user_bb); text_start_x += name_column_width + column_spacing; @@ -3372,7 +3385,7 @@ void Achievements::DrawLeaderboardsWindow() const ImRect score_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(bb.Max.x, midpoint)); RenderShadowedTextClipped( - UIStyle.LargeFont, score_bb.Min, score_bb.Max, text_color, + UIStyle.LargeFont, score_bb.Min, score_bb.Max, heading_color, Host::TranslateToCString( "Achievements", value_headings[std::min(s_state.open_leaderboard->format, NUM_RC_CLIENT_LEADERBOARD_FORMATS - 1)]), @@ -3380,7 +3393,7 @@ void Achievements::DrawLeaderboardsWindow() text_start_x += time_column_width + column_spacing; const ImRect date_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(bb.Max.x, midpoint)); - RenderShadowedTextClipped(UIStyle.LargeFont, date_bb.Min, date_bb.Max, text_color, + RenderShadowedTextClipped(UIStyle.LargeFont, date_bb.Min, date_bb.Max, heading_color, TRANSLATE("Achievements", "Date Submitted"), nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f, &date_bb); @@ -3452,7 +3465,7 @@ void Achievements::DrawLeaderboardsWindow() { for (u32 i = 0; i < s_state.leaderboard_nearby_entries->num_entries; i++) { - DrawLeaderboardEntry(s_state.leaderboard_nearby_entries->entries[i], + DrawLeaderboardEntry(s_state.leaderboard_nearby_entries->entries[i], i, static_cast(i) == s_state.leaderboard_nearby_entries->user_index, rank_column_width, name_column_width, time_column_width, column_spacing); } @@ -3472,24 +3485,23 @@ void Achievements::DrawLeaderboardsWindow() { for (u32 i = 0; i < list->num_entries; i++) { - DrawLeaderboardEntry(list->entries[i], static_cast(i) == list->user_index, rank_column_width, + DrawLeaderboardEntry(list->entries[i], i, static_cast(i) == list->user_index, rank_column_width, name_column_width, time_column_width, column_spacing); } } // Fetch next chunk if the loading indicator becomes visible (i.e. we scrolled enough). bool visible, hovered; - ImGuiFullscreen::MenuButtonFrame(TRANSLATE("Achievements", "Loading..."), false, - ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY, &visible, &hovered, - &bb.Min, &bb.Max); + text.format(ICON_FA_HOURGLASS_HALF " {}", TRANSLATE_SV("Achievements", "Loading...")); + ImGuiFullscreen::MenuButtonFrame(text.c_str(), false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY, + &visible, &hovered, &bb.Min, &bb.Max); if (visible) { const float midpoint = bb.Min.y + UIStyle.LargeFont->FontSize + LayoutScale(4.0f); const ImRect title_bb(bb.Min, ImVec2(bb.Max.x, midpoint)); - RenderShadowedTextClipped(UIStyle.LargeFont, title_bb.Min, title_bb.Max, text_color, - TRANSLATE("Achievements", "Loading..."), nullptr, nullptr, ImVec2(0, 0), 0.0f, - &title_bb); + RenderShadowedTextClipped(UIStyle.LargeFont, title_bb.Min, title_bb.Max, text_color, text.c_str(), + text.end_ptr(), nullptr, ImVec2(0, 0), 0.0f, &title_bb); if (!s_state.leaderboard_fetch_handle) FetchNextLeaderboardEntries(); @@ -3518,7 +3530,7 @@ void Achievements::DrawLeaderboardsWindow() FullscreenUI::BeginTransition(&CloseLeaderboard); } -void Achievements::DrawLeaderboardEntry(const rc_client_leaderboard_entry_t& entry, bool is_self, +void Achievements::DrawLeaderboardEntry(const rc_client_leaderboard_entry_t& entry, u32 index, bool is_self, float rank_column_width, float name_column_width, float time_column_width, float column_spacing) { @@ -3542,7 +3554,11 @@ void Achievements::DrawLeaderboardEntry(const rc_client_leaderboard_entry_t& ent text.format("{}", entry.rank); - const u32 text_color = is_self ? IM_COL32(255, 242, 0, 255) : ImGui::GetColorU32(ImGuiCol_Text); + const u32 text_color = + is_self ? + IM_COL32(255, 242, 0, 255) : + ImGui::GetColorU32(((index % 2) == 0) ? ImGuiFullscreen::DarkerColor(ImGui::GetStyle().Colors[ImGuiCol_Text]) : + ImGui::GetStyle().Colors[ImGuiCol_Text]); const ImRect rank_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(bb.Max.x, midpoint)); RenderShadowedTextClipped(UIStyle.LargeFont, rank_bb.Min, rank_bb.Max, text_color, text.c_str(), text.end_ptr(), @@ -3617,17 +3633,17 @@ void Achievements::DrawLeaderboardListEntry(const rc_client_leaderboard_t* lboar const float midpoint = bb.Min.y + UIStyle.LargeFont->FontSize + LayoutScale(4.0f); const float text_start_x = bb.Min.x + LayoutScale(15.0f); - const u32 text_color = ImGui::GetColorU32(ImGuiCol_Text); const ImRect title_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(bb.Max.x, midpoint)); const ImRect summary_bb(ImVec2(text_start_x, midpoint), bb.Max); - RenderShadowedTextClipped(UIStyle.LargeFont, title_bb.Min, title_bb.Max, text_color, lboard->title, nullptr, nullptr, - ImVec2(0.0f, 0.0f), 0.0f, &title_bb); + RenderShadowedTextClipped(UIStyle.LargeFont, title_bb.Min, title_bb.Max, ImGui::GetColorU32(ImGuiCol_Text), + lboard->title, nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f, &title_bb); if (lboard->description && lboard->description[0] != '\0') { - RenderShadowedTextClipped(UIStyle.MediumFont, summary_bb.Min, summary_bb.Max, text_color, lboard->description, - nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f, &summary_bb); + RenderShadowedTextClipped(UIStyle.MediumFont, summary_bb.Min, summary_bb.Max, + ImGui::GetColorU32(ImGuiFullscreen::DarkerColor(ImGui::GetStyle().Colors[ImGuiCol_Text])), + lboard->description, nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f, &summary_bb); } if (pressed) diff --git a/src/util/imgui_glyph_ranges.inl b/src/util/imgui_glyph_ranges.inl index f2df46cbd..37447d8fc 100644 --- a/src/util/imgui_glyph_ranges.inl +++ b/src/util/imgui_glyph_ranges.inl @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin // SPDX-License-Identifier: CC-BY-NC-ND-4.0 -static constexpr ImWchar FA_ICON_RANGE[] = { 0xe06f,0xe070,0xe086,0xe086,0xf002,0xf002,0xf005,0xf005,0xf007,0xf007,0xf00c,0xf00e,0xf011,0xf013,0xf017,0xf017,0xf019,0xf019,0xf01c,0xf01c,0xf021,0xf023,0xf025,0xf026,0xf028,0xf028,0xf02e,0xf02e,0xf030,0xf030,0xf03a,0xf03a,0xf03d,0xf03e,0xf04a,0xf04c,0xf050,0xf050,0xf056,0xf056,0xf059,0xf059,0xf05e,0xf05e,0xf062,0xf063,0xf065,0xf067,0xf071,0xf071,0xf075,0xf075,0xf077,0xf078,0xf07b,0xf07c,0xf083,0xf085,0xf091,0xf091,0xf09c,0xf09c,0xf0ac,0xf0ae,0xf0b2,0xf0b2,0xf0c3,0xf0c3,0xf0c5,0xf0c5,0xf0c7,0xf0c9,0xf0cb,0xf0cb,0xf0d0,0xf0d0,0xf0dc,0xf0dc,0xf0e0,0xf0e0,0xf0e2,0xf0e2,0xf0e7,0xf0e8,0xf0eb,0xf0eb,0xf0f1,0xf0f1,0xf0f3,0xf0f3,0xf0fe,0xf0fe,0xf110,0xf110,0xf11b,0xf11c,0xf140,0xf140,0xf144,0xf144,0xf146,0xf146,0xf14a,0xf14a,0xf15b,0xf15d,0xf191,0xf192,0xf1ab,0xf1ab,0xf1c0,0xf1c0,0xf1c5,0xf1c5,0xf1de,0xf1de,0xf1e6,0xf1e6,0xf1eb,0xf1eb,0xf1f8,0xf1f8,0xf1fb,0xf1fc,0xf201,0xf201,0xf240,0xf240,0xf242,0xf242,0xf245,0xf245,0xf26c,0xf26c,0xf279,0xf279,0xf2c1,0xf2c1,0xf2d0,0xf2d0,0xf2db,0xf2db,0xf2f1,0xf2f2,0xf302,0xf302,0xf31e,0xf31e,0xf35d,0xf35d,0xf360,0xf360,0xf362,0xf362,0xf3c1,0xf3c1,0xf3fd,0xf3fd,0xf410,0xf410,0xf422,0xf422,0xf424,0xf424,0xf462,0xf462,0xf466,0xf466,0xf4ce,0xf4ce,0xf500,0xf500,0xf517,0xf517,0xf51f,0xf51f,0xf538,0xf538,0xf545,0xf545,0xf547,0xf548,0xf54c,0xf54c,0xf55b,0xf55b,0xf55d,0xf55d,0xf565,0xf565,0xf56e,0xf570,0xf5a2,0xf5a2,0xf5aa,0xf5aa,0xf5ae,0xf5ae,0xf5c7,0xf5c7,0xf5cb,0xf5cb,0xf5e7,0xf5e7,0xf5ee,0xf5ee,0xf61f,0xf61f,0xf65d,0xf65e,0xf6a9,0xf6a9,0xf6cf,0xf6cf,0xf70c,0xf70c,0xf70e,0xf70e,0xf78c,0xf78c,0xf794,0xf794,0xf7a0,0xf7a0,0xf7a4,0xf7a5,0xf7c2,0xf7c2,0xf807,0xf807,0xf815,0xf815,0xf818,0xf818,0xf84c,0xf84c,0xf853,0xf853,0xf87d,0xf87d,0xf8cc,0xf8cc,0x0,0x0 }; +static constexpr ImWchar FA_ICON_RANGE[] = { 0xe06f,0xe070,0xe086,0xe086,0xf002,0xf002,0xf005,0xf005,0xf007,0xf007,0xf00c,0xf00e,0xf011,0xf013,0xf017,0xf017,0xf019,0xf019,0xf01c,0xf01c,0xf021,0xf023,0xf025,0xf026,0xf028,0xf028,0xf02e,0xf02e,0xf030,0xf030,0xf03a,0xf03a,0xf03d,0xf03e,0xf04a,0xf04c,0xf050,0xf050,0xf056,0xf056,0xf059,0xf059,0xf05e,0xf05e,0xf062,0xf063,0xf065,0xf067,0xf071,0xf071,0xf075,0xf075,0xf077,0xf078,0xf07b,0xf07c,0xf083,0xf085,0xf091,0xf091,0xf09c,0xf09c,0xf0ac,0xf0ae,0xf0b2,0xf0b2,0xf0c3,0xf0c3,0xf0c5,0xf0c5,0xf0c7,0xf0c9,0xf0cb,0xf0cb,0xf0d0,0xf0d0,0xf0dc,0xf0dc,0xf0e0,0xf0e0,0xf0e2,0xf0e2,0xf0e7,0xf0e8,0xf0eb,0xf0eb,0xf0f1,0xf0f1,0xf0f3,0xf0f3,0xf0fe,0xf0fe,0xf110,0xf110,0xf11b,0xf11c,0xf140,0xf140,0xf144,0xf144,0xf146,0xf146,0xf14a,0xf14a,0xf15b,0xf15d,0xf191,0xf192,0xf1ab,0xf1ab,0xf1c0,0xf1c0,0xf1c5,0xf1c5,0xf1de,0xf1de,0xf1e6,0xf1e6,0xf1eb,0xf1eb,0xf1f8,0xf1f8,0xf1fb,0xf1fc,0xf201,0xf201,0xf240,0xf240,0xf242,0xf242,0xf245,0xf245,0xf252,0xf252,0xf26c,0xf26c,0xf279,0xf279,0xf2c1,0xf2c1,0xf2d0,0xf2d0,0xf2db,0xf2db,0xf2f1,0xf2f2,0xf302,0xf302,0xf31e,0xf31e,0xf35d,0xf35d,0xf360,0xf360,0xf362,0xf362,0xf3c1,0xf3c1,0xf3fd,0xf3fd,0xf410,0xf410,0xf422,0xf422,0xf424,0xf424,0xf462,0xf462,0xf466,0xf466,0xf4ce,0xf4ce,0xf500,0xf500,0xf517,0xf517,0xf51f,0xf51f,0xf538,0xf538,0xf545,0xf545,0xf547,0xf548,0xf54c,0xf54c,0xf55b,0xf55b,0xf55d,0xf55d,0xf565,0xf565,0xf56e,0xf570,0xf5a2,0xf5a2,0xf5aa,0xf5aa,0xf5ae,0xf5ae,0xf5c7,0xf5c7,0xf5cb,0xf5cb,0xf5e7,0xf5e7,0xf5ee,0xf5ee,0xf61f,0xf61f,0xf65d,0xf65e,0xf6a9,0xf6a9,0xf6cf,0xf6cf,0xf70c,0xf70c,0xf70e,0xf70e,0xf78c,0xf78c,0xf794,0xf794,0xf7a0,0xf7a0,0xf7a4,0xf7a5,0xf7c2,0xf7c2,0xf807,0xf807,0xf815,0xf815,0xf818,0xf818,0xf84c,0xf84c,0xf853,0xf853,0xf87d,0xf87d,0xf8cc,0xf8cc,0x0,0x0 }; static constexpr ImWchar PF_ICON_RANGE[] = { 0x2196,0x2199,0x219e,0x21a3,0x21b0,0x21b3,0x21ba,0x21c3,0x21c7,0x21ca,0x21d0,0x21d4,0x21e0,0x21e3,0x21e6,0x21e8,0x21eb,0x21eb,0x21ed,0x21ee,0x21f7,0x21f8,0x21fa,0x21fb,0x221a,0x221b,0x227a,0x227f,0x2284,0x2284,0x22bf,0x22c8,0x2349,0x2349,0x235e,0x235e,0x2360,0x2361,0x2364,0x2366,0x23b2,0x23b4,0x23cc,0x23cc,0x23ce,0x23ce,0x23f4,0x23f7,0x2427,0x243a,0x243c,0x243e,0x2446,0x2446,0x2460,0x246b,0x248f,0x248f,0x24f5,0x24fd,0x24ff,0x24ff,0x2717,0x2717,0x2753,0x2753,0x278a,0x278e,0x27fc,0x27fc,0xe000,0xe001,0xff21,0xff3a,0x1f52b,0x1f52b,0x0,0x0 };