diff --git a/src/console_gui.cpp b/src/console_gui.cpp index fa00d2fc38..754aa2128e 100644 --- a/src/console_gui.cpp +++ b/src/console_gui.cpp @@ -397,7 +397,7 @@ void IConsoleSwitch() #ifdef __ANDROID__ { char buf[1024] = ""; - char *pos = &buf; + char *pos = &buf[0]; for (IConsoleLine &line : _iconsole_buffer) { if (!line.buffer.empty()) { diff --git a/src/fontcache.cpp b/src/fontcache.cpp index 2a5772fc3b..1e820e01b1 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -22,6 +22,9 @@ #include "safeguards.h" +static void LoadFontHelper([[maybe_unused]] FontSize fs); +static void TryLoadDefaultTrueTypeFont([[maybe_unused]] FontSize fs); + /** Default heights for the different sizes of fonts. */ static const int _default_font_height[FS_END] = {10, 6, 18, 10}; static const int _default_font_ascender[FS_END] = { 8, 5, 15, 8}; @@ -99,6 +102,30 @@ bool GetFontAAState(FontSize size, bool check_blitter) return _fcsettings.global_aa || GetFontCacheSubSetting(size)->aa; } +void ResizeFont(FontSize font_size, uint size) +{ + FontCacheSubSetting *setting = GetFontCacheSubSetting(font_size); + + if (setting->size == size) { + return; + } + + setting->size = size; + + // Default fonts are empty here. We will allow the user to resize the default font: + if (setting->font.empty()){ + TryLoadDefaultTrueTypeFont(font_size); + } else { + LoadFontHelper(font_size); + } + + LoadStringWidthTable(); + UpdateAllVirtCoords(); + ReInitAllWindows(true); + + if (_save_config) SaveToConfig(); +} + void SetFont(FontSize fontsize, const std::string &font, uint size, bool aa) { FontCacheSubSetting *setting = GetFontCacheSubSetting(fontsize); @@ -154,6 +181,18 @@ extern void LoadCoreTextFont(FontSize fs); extern void LoadCoreTextFont(FontSize fs, const std::string &file_name, uint size); #endif +static void LoadFontHelper([[maybe_unused]] FontSize fs) +{ +#ifdef WITH_FREETYPE + LoadFreeTypeFont(fs); +#elif defined(_WIN32) + LoadWin32Font(fs); +#elif defined(WITH_COCOA) + LoadCoreTextFont(fs); +#endif +} + + static void TryLoadDefaultTrueTypeFont([[maybe_unused]] FontSize fs) { #if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA) diff --git a/src/fontcache.h b/src/fontcache.h index 9ba6055504..12b41da880 100644 --- a/src/fontcache.h +++ b/src/fontcache.h @@ -242,6 +242,7 @@ inline FontCacheSubSetting *GetFontCacheSubSetting(FontSize fs) void InitFontCache(bool monospace); void UninitFontCache(); +void ResizeFont(FontSize font_size, uint32_t size); bool HasAntialiasedFonts(); bool GetFontAAState(FontSize size, bool check_blitter = true); diff --git a/src/lang/english.txt b/src/lang/english.txt index de901f25fe..3554d5d97b 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -947,6 +947,8 @@ STR_GAME_OPTIONS_TAB_GENERAL :General STR_GAME_OPTIONS_TAB_GENERAL_TT :{BLACK}Choose general settings STR_GAME_OPTIONS_TAB_INTERFACE :Interface STR_GAME_OPTIONS_TAB_INTERFACE_TT :{BLACK}Choose interface settings +STR_GAME_OPTIONS_TAB_FONTS :Fonts +STR_GAME_OPTIONS_TAB_FONTS_TT :{BLACK}Choose font settings STR_GAME_OPTIONS_TAB_GRAPHICS :Graphics STR_GAME_OPTIONS_TAB_GRAPHICS_TT :{BLACK}Choose graphics settings STR_GAME_OPTIONS_TAB_SOUND :Sound @@ -1073,6 +1075,11 @@ STR_GAME_OPTIONS_PARTICIPATE_SURVEY_LINK_TOOLTIP :{BLACK}This ope STR_GAME_OPTIONS_PARTICIPATE_SURVEY_PREVIEW :{BLACK}Preview survey result STR_GAME_OPTIONS_PARTICIPATE_SURVEY_PREVIEW_TOOLTIP :{BLACK}Show the survey result of the current running game +STR_GAME_OPTIONS_FONT_MONO :{BLACK}Mono font +STR_GAME_OPTIONS_FONT_SMALL :{BLACK}Small font +STR_GAME_OPTIONS_FONT_NORMAL :{BLACK}Normal font +STR_GAME_OPTIONS_FONT_LARGE :{BLACK}Large font + STR_GAME_OPTIONS_GRAPHICS :{BLACK}Graphics STR_GAME_OPTIONS_REFRESH_RATE :{BLACK}Display refresh rate diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 56d13007b0..b060bbbb6b 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -95,8 +95,6 @@ static uint GetCurrentResolutionIndex() static void ShowCustCurrency(); -static void ReconstructUserInterface(); - /** Window for displaying the textfile of a BaseSet. */ template struct BaseSetTextfileWindow : public TextfileWindow { @@ -359,11 +357,23 @@ std::unique_ptr MakeNWidgetSocialPlugins() return std::make_unique(); } +static inline FontCacheSubSetting *getSafeFontCacheSub(FontSize fs) { + FontCache *fc = FontCache::Get(fs); + FontCacheSubSetting *setting = GetFontCacheSubSetting(fs); + /* Make sure all non sprite fonts are loaded. */ + if (!setting->font.empty() && !fc->HasParent()) { + InitFontCache(fs == FS_MONO); + fc = FontCache::Get(fs); + } + return setting; +} + struct GameOptionsWindow : Window { GameSettings *opt; bool reload; int gui_scale; int button_ratio; + uint32_t font_sizes[FS_END]; static inline WidgetID active_tab = WID_GO_TAB_GENERAL; GameOptionsWindow(WindowDesc *desc) : Window(desc) @@ -372,6 +382,10 @@ struct GameOptionsWindow : Window { this->reload = false; this->gui_scale = _gui_scale; this->button_ratio = _button_ratio; + for (FontSize fs = FS_BEGIN; fs < FS_END; fs++){ + FontCacheSubSetting *fc = getSafeFontCacheSub(fs); + font_sizes[fs] = fc->size; + } AddCustomRefreshRates(); @@ -523,7 +537,15 @@ struct GameOptionsWindow : Window { SetDParam(0, _autosave_dropdown[index - 1]); break; } + case WID_GO_LANG_DROPDOWN: SetDParamStr(0, _current_language->own_name); break; + case WID_GO_NORMAL_FONT_VALUE: + case WID_GO_SMALL_FONT_VALUE: + case WID_GO_LARGE_FONT_VALUE: + case WID_GO_MONO_FONT_VALUE: { + SetDParam(0, this->font_sizes[static_cast(Clamp(widget - WID_GO_NORMAL_FONT_VALUE, FS_BEGIN, FS_END))]); + break; + } case WID_GO_BASE_GRF_DROPDOWN: SetDParamStr(0, BaseGraphics::GetUsedSet()->GetListLabel()); break; case WID_GO_BASE_SFX_DROPDOWN: SetDParamStr(0, BaseSounds::GetUsedSet()->GetListLabel()); break; case WID_GO_BASE_MUSIC_DROPDOWN: SetDParamStr(0, BaseMusic::GetUsedSet()->GetListLabel()); break; @@ -596,7 +618,7 @@ struct GameOptionsWindow : Window { void SetTab(WidgetID widget) { - this->SetWidgetsLoweredState(false, WID_GO_TAB_GENERAL, WID_GO_TAB_INTERFACE, WID_GO_TAB_GRAPHICS, WID_GO_TAB_SOUND, WID_GO_TAB_SOCIAL); + this->SetWidgetsLoweredState(false, WID_GO_TAB_GENERAL, WID_GO_TAB_INTERFACE, WID_GO_TAB_FONTS, WID_GO_TAB_GRAPHICS, WID_GO_TAB_SOUND, WID_GO_TAB_SOCIAL); this->LowerWidget(widget); GameOptionsWindow::active_tab = widget; @@ -604,9 +626,10 @@ struct GameOptionsWindow : Window { switch (widget) { case WID_GO_TAB_GENERAL: pane = 0; break; case WID_GO_TAB_INTERFACE: pane = 1; break; - case WID_GO_TAB_GRAPHICS: pane = 2; break; - case WID_GO_TAB_SOUND: pane = 3; break; - case WID_GO_TAB_SOCIAL: pane = 4; break; + case WID_GO_TAB_FONTS: pane = 2; break; + case WID_GO_TAB_GRAPHICS: pane = 3; break; + case WID_GO_TAB_SOUND: pane = 4; break; + case WID_GO_TAB_SOCIAL: pane = 5; break; default: NOT_REACHED(); } @@ -700,6 +723,7 @@ struct GameOptionsWindow : Window { switch (widget) { case WID_GO_TAB_GENERAL: case WID_GO_TAB_INTERFACE: + case WID_GO_TAB_FONTS: case WID_GO_TAB_GRAPHICS: case WID_GO_TAB_SOUND: case WID_GO_TAB_SOCIAL: @@ -800,6 +824,24 @@ struct GameOptionsWindow : Window { ClearFontCache(); break; #endif /* HAS_TRUETYPE_FONT */ + case WID_GO_NORMAL_FONT_L: + case WID_GO_NORMAL_FONT_R: + case WID_GO_SMALL_FONT_L: + case WID_GO_SMALL_FONT_R: + case WID_GO_LARGE_FONT_L: + case WID_GO_LARGE_FONT_R: + case WID_GO_MONO_FONT_L: + case WID_GO_MONO_FONT_R: { + int index = widget - WID_GO_NORMAL_FONT_L; + FontSize fs = static_cast(Clamp((widget - WID_GO_NORMAL_FONT_L) / 2, FS_BEGIN, FS_END)); + + if (index % 2 == 0) { + this->font_sizes[fs] = Clamp(this->font_sizes[fs] - 1, 0, 200); + } else { + this->font_sizes[fs] = Clamp(this->font_sizes[fs] + 1, 0, 200); + } + } + case WID_GO_MOUSE_CURSOR: if (_settings_client.gui.draw_mouse_cursor) { UndrawMouseCursor(); @@ -917,13 +959,35 @@ struct GameOptionsWindow : Window { } } + bool anySizeSettingChanged() + { + if (this->gui_scale != _gui_scale || this->button_ratio != _button_ratio) { + return true; + } + + for (FontSize fs = FS_BEGIN; fs < FS_END; fs++){ + FontCacheSubSetting *fc = getSafeFontCacheSub(fs); + if (this->font_sizes[fs] != fc->size) + return true; + } + + return false; + } void OnMouseLoop() override { - if (_left_button_down || (this->gui_scale == _gui_scale && this->button_ratio == _button_ratio)) return; + if (_left_button_down || !anySizeSettingChanged()) return; _gui_scale_cfg = this->gui_scale; _button_ratio_cfg = this->button_ratio; + for (FontSize fs = FS_BEGIN; fs < FS_END; fs++){ + FontCacheSubSetting *fc = getSafeFontCacheSub(fs); + if (this->font_sizes[fs] != fc->size) { + ResizeFont(fs, this->font_sizes[fs]); + return; + } + } + if (AdjustGUIZoom(false)) { ReInitAllWindows(true); this->SetWidgetLoweredState(WID_GO_GUI_SCALE_AUTO, false); @@ -1055,6 +1119,7 @@ static constexpr NWidgetPart _nested_game_options_widgets[] = { NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPadding(WidgetDimensions::unscaled.sparse), NWidget(WWT_TEXTBTN, COLOUR_YELLOW, WID_GO_TAB_GENERAL), SetMinimalTextLines(2, 0), SetDataTip(STR_GAME_OPTIONS_TAB_GENERAL, STR_GAME_OPTIONS_TAB_GENERAL_TT), SetFill(1, 0), NWidget(WWT_TEXTBTN, COLOUR_YELLOW, WID_GO_TAB_INTERFACE), SetMinimalTextLines(2, 0), SetDataTip(STR_GAME_OPTIONS_TAB_INTERFACE, STR_GAME_OPTIONS_TAB_INTERFACE_TT), SetFill(1, 0), + NWidget(WWT_TEXTBTN, COLOUR_YELLOW, WID_GO_TAB_FONTS), SetMinimalTextLines(2, 0), SetDataTip(STR_GAME_OPTIONS_TAB_FONTS, STR_GAME_OPTIONS_TAB_FONTS_TT), SetFill(1, 0), NWidget(WWT_TEXTBTN, COLOUR_YELLOW, WID_GO_TAB_GRAPHICS), SetMinimalTextLines(2, 0), SetDataTip(STR_GAME_OPTIONS_TAB_GRAPHICS, STR_GAME_OPTIONS_TAB_GRAPHICS_TT), SetFill(1, 0), NWidget(WWT_TEXTBTN, COLOUR_YELLOW, WID_GO_TAB_SOUND), SetMinimalTextLines(2, 0), SetDataTip(STR_GAME_OPTIONS_TAB_SOUND, STR_GAME_OPTIONS_TAB_SOUND_TT), SetFill(1, 0), NWidget(WWT_TEXTBTN, COLOUR_YELLOW, WID_GO_TAB_SOCIAL), SetMinimalTextLines(2, 0), SetDataTip(STR_GAME_OPTIONS_TAB_SOCIAL, STR_GAME_OPTIONS_TAB_SOCIAL_TT), SetFill(1, 0), @@ -1106,6 +1171,18 @@ static constexpr NWidgetPart _nested_game_options_widgets[] = { NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_GUI_SCALE_BEVELS, STR_NULL), NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_GUI_SCALE_BEVEL_BUTTON), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_GUI_SCALE_BEVELS_TOOLTIP), EndContainer(), + NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0), + NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_CONFIG_SETTING_MOUSE_CURSOR, STR_NULL), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_MOUSE_CURSOR), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_CONFIG_SETTING_MOUSE_CURSOR_HELPTEXT), + EndContainer(), + NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0), + NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_CONFIG_SETTING_WINDOWS_TITLEBARS, STR_NULL), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_WINDOWS_TITLEBARS), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_CONFIG_SETTING_WINDOWS_TITLEBARS_HELPTEXT), + EndContainer(), + EndContainer(), + + /* Fonts tab */ + NWidget(NWID_VERTICAL), SetPadding(WidgetDimensions::unscaled.sparse), SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0), #ifdef HAS_TRUETYPE_FONT NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0), NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_GUI_FONT_SPRITE, STR_NULL), @@ -1117,12 +1194,28 @@ static constexpr NWidgetPart _nested_game_options_widgets[] = { EndContainer(), #endif /* HAS_TRUETYPE_FONT */ NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0), - NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_CONFIG_SETTING_MOUSE_CURSOR, STR_NULL), - NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_MOUSE_CURSOR), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_CONFIG_SETTING_MOUSE_CURSOR_HELPTEXT), + NWidget(WWT_TEXT, COLOUR_GREY), SetTextStyle(TC_BLACK, FS_NORMAL), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_FONT_NORMAL, STR_NULL), + NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_GO_NORMAL_FONT_L), SetDataTip(AWV_DECREASE, STR_NULL), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_NORMAL_FONT_VALUE), SetDataTip(STR_JUST_INT, STR_NULL), SetTextStyle(TC_WHITE), + NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_GO_NORMAL_FONT_R), SetDataTip(AWV_INCREASE, STR_NULL), EndContainer(), NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0), - NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_CONFIG_SETTING_WINDOWS_TITLEBARS, STR_NULL), - NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_WINDOWS_TITLEBARS), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_CONFIG_SETTING_WINDOWS_TITLEBARS_HELPTEXT), + NWidget(WWT_TEXT, COLOUR_GREY), SetTextStyle(TC_BLACK, FS_SMALL), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_FONT_SMALL, STR_NULL), + NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_GO_SMALL_FONT_L), SetDataTip(AWV_DECREASE, STR_NULL), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_SMALL_FONT_VALUE), SetDataTip(STR_JUST_INT, STR_NULL), SetTextStyle(TC_WHITE), + NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_GO_SMALL_FONT_R), SetDataTip(AWV_INCREASE, STR_NULL), + EndContainer(), + NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0), + NWidget(WWT_TEXT, COLOUR_GREY), SetTextStyle(TC_BLACK, FS_LARGE), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_FONT_LARGE, STR_NULL), + NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_GO_LARGE_FONT_L), SetDataTip(AWV_DECREASE, STR_NULL), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_LARGE_FONT_VALUE), SetDataTip(STR_JUST_INT, STR_NULL), SetTextStyle(TC_WHITE), + NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_GO_LARGE_FONT_R), SetDataTip(AWV_INCREASE, STR_NULL), + EndContainer(), + NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0), + NWidget(WWT_TEXT, COLOUR_GREY), SetTextStyle(TC_BLACK, FS_MONO), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_FONT_MONO, STR_NULL), + NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_GO_MONO_FONT_L), SetDataTip(AWV_DECREASE, STR_NULL), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_MONO_FONT_VALUE), SetDataTip(STR_JUST_INT, STR_NULL), SetTextStyle(TC_WHITE), + NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_GO_MONO_FONT_R), SetDataTip(AWV_INCREASE, STR_NULL), EndContainer(), EndContainer(), diff --git a/src/widgets/settings_widget.h b/src/widgets/settings_widget.h index 038481eabe..7db3b28cf9 100644 --- a/src/widgets/settings_widget.h +++ b/src/widgets/settings_widget.h @@ -14,6 +14,7 @@ enum GameOptionsWidgets : WidgetID { WID_GO_TAB_GENERAL, ///< General tab. WID_GO_TAB_INTERFACE, ///< Interface tab. + WID_GO_TAB_FONTS, ///< Fonts tab. WID_GO_TAB_GRAPHICS, ///< Graphics tab. WID_GO_TAB_SOUND, ///< Sound tab. WID_GO_TAB_SOCIAL, ///< Social tab. @@ -36,6 +37,18 @@ enum GameOptionsWidgets : WidgetID { WID_GO_GUI_SCALE_BEVEL_BUTTON, ///< Toggle for chunky bevels. WID_GO_GUI_FONT_SPRITE, ///< Toggle whether to prefer the sprite font over TTF fonts. WID_GO_GUI_FONT_AA, ///< Toggle whether to anti-alias fonts. + WID_GO_NORMAL_FONT_VALUE, ///< Toggle whether to anti-alias fonts. + WID_GO_SMALL_FONT_VALUE, ///< Toggle whether to anti-alias fonts. + WID_GO_LARGE_FONT_VALUE, ///< Toggle whether to anti-alias fonts. + WID_GO_MONO_FONT_VALUE, ///< Toggle whether to anti-alias fonts. + WID_GO_NORMAL_FONT_L, ///< Toggle whether to anti-alias fonts. + WID_GO_NORMAL_FONT_R, ///< Toggle whether to anti-alias fonts. + WID_GO_SMALL_FONT_L, ///< Toggle whether to anti-alias fonts. + WID_GO_SMALL_FONT_R, ///< Toggle whether to anti-alias fonts. + WID_GO_LARGE_FONT_L, ///< Toggle whether to anti-alias fonts. + WID_GO_LARGE_FONT_R, ///< Toggle whether to anti-alias fonts. + WID_GO_MONO_FONT_L, ///< Toggle whether to anti-alias fonts. + WID_GO_MONO_FONT_R, ///< Toggle whether to anti-alias fonts. WID_GO_BASE_GRF_DROPDOWN, ///< Use to select a base GRF. WID_GO_BASE_GRF_PARAMETERS, ///< Base GRF parameters. WID_GO_BASE_GRF_OPEN_URL, ///< Open base GRF URL.