From d8c5a55fe8bcfebfddd45e5afc688384c690a09f Mon Sep 17 00:00:00 2001 From: Adolfo Reyna Date: Fri, 24 Jul 2026 21:28:24 -0400 Subject: [PATCH] Add firmware font size setting --- .../include/tactility/lvgl_fonts.h | 9 ++++ Modules/lvgl-module/source/lvgl_fonts.c | 26 ++++++++++- Modules/lvgl-module/source/symbols.c | 4 +- Tactility/Include/Tactility/lvgl/Lvgl.h | 7 +++ .../Tactility/settings/DisplaySettings.h | 8 ++++ Tactility/Source/app/display/Display.cpp | 33 ++++++++++++++ .../app/kerneldisplay/KernelDisplay.cpp | 33 ++++++++++++++ Tactility/Source/lvgl/Lvgl.cpp | 45 +++++++++++++++++++ Tactility/Source/settings/DisplaySettings.cpp | 38 ++++++++++++++++ 9 files changed, 200 insertions(+), 3 deletions(-) diff --git a/Modules/lvgl-module/include/tactility/lvgl_fonts.h b/Modules/lvgl-module/include/tactility/lvgl_fonts.h index 2420235b..26e65360 100644 --- a/Modules/lvgl-module/include/tactility/lvgl_fonts.h +++ b/Modules/lvgl-module/include/tactility/lvgl_fonts.h @@ -14,6 +14,15 @@ enum LvglFontSize { FONT_SIZE_LARGE, }; +enum LvglFontScale { + FONT_SCALE_SMALL, + FONT_SCALE_DEFAULT, + FONT_SCALE_LARGE, +}; + +void lvgl_set_text_font_scale(enum LvglFontScale font_scale); +enum LvglFontScale lvgl_get_text_font_scale(void); + const lv_font_t* lvgl_get_shared_icon_font(); uint32_t lvgl_get_shared_icon_font_height(); diff --git a/Modules/lvgl-module/source/lvgl_fonts.c b/Modules/lvgl-module/source/lvgl_fonts.c index aab97211..995aa987 100644 --- a/Modules/lvgl-module/source/lvgl_fonts.c +++ b/Modules/lvgl-module/source/lvgl_fonts.c @@ -13,8 +13,30 @@ extern const lv_font_t TT_LVGL_LAUNCHER_FONT_ICON_SYMBOL; extern const lv_font_t TT_LVGL_STATUSBAR_FONT_ICON_SYMBOL; extern const lv_font_t TT_LVGL_SHARED_FONT_ICON_SYMBOL; +static enum LvglFontScale text_font_scale = FONT_SCALE_DEFAULT; + +void lvgl_set_text_font_scale(enum LvglFontScale font_scale) { + check(font_scale >= FONT_SCALE_SMALL && font_scale <= FONT_SCALE_LARGE); + text_font_scale = font_scale; +} + +enum LvglFontScale lvgl_get_text_font_scale(void) { + return text_font_scale; +} + +static enum LvglFontSize resolve_text_font_size(enum LvglFontSize font_size) { + int resolved = (int)font_size + (int)text_font_scale - (int)FONT_SCALE_DEFAULT; + if (resolved < FONT_SIZE_SMALL) { + return FONT_SIZE_SMALL; + } + if (resolved > FONT_SIZE_LARGE) { + return FONT_SIZE_LARGE; + } + return (enum LvglFontSize)resolved; +} + uint32_t lvgl_get_text_font_height(enum LvglFontSize font_size) { - switch (font_size) { + switch (resolve_text_font_size(font_size)) { case FONT_SIZE_SMALL: return TT_LVGL_TEXT_FONT_SMALL_SIZE; case FONT_SIZE_DEFAULT: return TT_LVGL_TEXT_FONT_DEFAULT_SIZE; case FONT_SIZE_LARGE: return TT_LVGL_TEXT_FONT_LARGE_SIZE; @@ -22,7 +44,7 @@ uint32_t lvgl_get_text_font_height(enum LvglFontSize font_size) { } } const lv_font_t* lvgl_get_text_font(enum LvglFontSize font_size) { - switch (font_size) { + switch (resolve_text_font_size(font_size)) { case FONT_SIZE_SMALL: return &TT_LVGL_TEXT_FONT_SMALL_SYMBOL; case FONT_SIZE_DEFAULT: return &TT_LVGL_TEXT_FONT_DEFAULT_SYMBOL; case FONT_SIZE_LARGE: return &TT_LVGL_TEXT_FONT_LARGE_SYMBOL; diff --git a/Modules/lvgl-module/source/symbols.c b/Modules/lvgl-module/source/symbols.c index 005e6818..0bdc633e 100644 --- a/Modules/lvgl-module/source/symbols.c +++ b/Modules/lvgl-module/source/symbols.c @@ -13,6 +13,8 @@ const struct ModuleSymbol lvgl_module_symbols[] = { DEFINE_MODULE_SYMBOL(lvgl_is_running), DEFINE_MODULE_SYMBOL(lvgl_get_ui_density), // lvgl_fonts + DEFINE_MODULE_SYMBOL(lvgl_set_text_font_scale), + DEFINE_MODULE_SYMBOL(lvgl_get_text_font_scale), DEFINE_MODULE_SYMBOL(lvgl_get_shared_icon_font), DEFINE_MODULE_SYMBOL(lvgl_get_shared_icon_font_height), DEFINE_MODULE_SYMBOL(lvgl_get_text_font), @@ -473,4 +475,4 @@ const struct ModuleSymbol lvgl_module_symbols[] = { DEFINE_MODULE_SYMBOL(lv_area_get_width), DEFINE_MODULE_SYMBOL(lv_area_get_height), MODULE_SYMBOL_TERMINATOR -}; \ No newline at end of file +}; diff --git a/Tactility/Include/Tactility/lvgl/Lvgl.h b/Tactility/Include/Tactility/lvgl/Lvgl.h index 6e8bfbec..22d72a5c 100644 --- a/Tactility/Include/Tactility/lvgl/Lvgl.h +++ b/Tactility/Include/Tactility/lvgl/Lvgl.h @@ -1,5 +1,9 @@ #pragma once +namespace tt::settings::display { +enum class FontSize; +} + namespace tt::lvgl { #ifdef ESP_PLATFORM @@ -12,6 +16,9 @@ static constexpr auto* PATH_PREFIX = "A:/"; bool isStarted(); +/** Applies the selected semantic text size to the LVGL theme and future widgets. */ +void applyFontSize(settings::display::FontSize fontSize); + void start(); void stop(); diff --git a/Tactility/Include/Tactility/settings/DisplaySettings.h b/Tactility/Include/Tactility/settings/DisplaySettings.h index 03abc682..efdba988 100644 --- a/Tactility/Include/Tactility/settings/DisplaySettings.h +++ b/Tactility/Include/Tactility/settings/DisplaySettings.h @@ -22,8 +22,16 @@ enum class ScreensaverType { Count // Sentinel for bounds checking - must be last }; +enum class FontSize { + Small, + Default, + Large, + Count +}; + struct DisplaySettings { Orientation orientation; + FontSize fontSize = FontSize::Default; uint8_t gammaCurve; uint8_t backlightDuty; bool backlightTimeoutEnabled; diff --git a/Tactility/Source/app/display/Display.cpp b/Tactility/Source/app/display/Display.cpp index 820404c0..e582e3ef 100644 --- a/Tactility/Source/app/display/Display.cpp +++ b/Tactility/Source/app/display/Display.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -74,6 +75,21 @@ class HalDisplayApp final : public App { } } + static void onFontSizeChanged(lv_event_t* event) { + auto* app = static_cast(lv_event_get_user_data(event)); + auto* dropdown = static_cast(lv_event_get_target(event)); + uint32_t selected_index = lv_dropdown_get_selected(dropdown); + if (selected_index >= static_cast(settings::display::FontSize::Count)) { + return; + } + auto selected_size = static_cast(selected_index); + if (selected_size != app->displaySettings.fontSize) { + app->displaySettings.fontSize = selected_size; + app->displaySettingsUpdated = true; + lvgl::applyFontSize(selected_size); + } + } + static void onDisableWhenChargingChanged(lv_event_t* event) { auto* app = static_cast(lv_event_get_user_data(event)); auto* sw = static_cast(lv_event_get_target(event)); @@ -224,6 +240,23 @@ public: // Set the dropdown to match current orientation enum lv_dropdown_set_selected(orientation_dropdown, static_cast(displaySettings.orientation)); + // Font size + + auto* font_size_wrapper = lv_obj_create(main_wrapper); + lv_obj_set_size(font_size_wrapper, LV_PCT(100), LV_SIZE_CONTENT); + lv_obj_set_style_pad_all(font_size_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_border_width(font_size_wrapper, 0, LV_STATE_DEFAULT); + + auto* font_size_label = lv_label_create(font_size_wrapper); + lv_label_set_text(font_size_label, "Font size"); + lv_obj_align(font_size_label, LV_ALIGN_LEFT_MID, 0, 0); + + auto* font_size_dropdown = lv_dropdown_create(font_size_wrapper); + lv_dropdown_set_options(font_size_dropdown, "Small\nDefault\nLarge"); + lv_obj_align(font_size_dropdown, LV_ALIGN_RIGHT_MID, 0, 0); + lv_obj_add_event_cb(font_size_dropdown, onFontSizeChanged, LV_EVENT_VALUE_CHANGED, this); + lv_dropdown_set_selected(font_size_dropdown, static_cast(displaySettings.fontSize)); + // Screen timeout if (hal_display->supportsBacklightDuty()) { diff --git a/Tactility/Source/app/kerneldisplay/KernelDisplay.cpp b/Tactility/Source/app/kerneldisplay/KernelDisplay.cpp index 6db58af5..c57ad22f 100644 --- a/Tactility/Source/app/kerneldisplay/KernelDisplay.cpp +++ b/Tactility/Source/app/kerneldisplay/KernelDisplay.cpp @@ -11,6 +11,7 @@ #include #endif #include +#include #include #include @@ -69,6 +70,21 @@ class KernelDisplayApp final : public App { } } + static void onFontSizeChanged(lv_event_t* event) { + auto* app = static_cast(lv_event_get_user_data(event)); + auto* dropdown = static_cast(lv_event_get_target(event)); + uint32_t selected_index = lv_dropdown_get_selected(dropdown); + if (selected_index >= static_cast(settings::display::FontSize::Count)) { + return; + } + auto selected_size = static_cast(selected_index); + if (selected_size != app->displaySettings.fontSize) { + app->displaySettings.fontSize = selected_size; + app->displaySettingsUpdated = true; + lvgl::applyFontSize(selected_size); + } + } + static void onTimeoutSwitch(lv_event_t* event) { auto* app = static_cast(lv_event_get_user_data(event)); auto* sw = static_cast(lv_event_get_target(event)); @@ -183,6 +199,23 @@ public: // Set the dropdown to match current orientation enum lv_dropdown_set_selected(orientation_dropdown, static_cast(displaySettings.orientation)); + // Font size + + auto* font_size_wrapper = lv_obj_create(main_wrapper); + lv_obj_set_size(font_size_wrapper, LV_PCT(100), LV_SIZE_CONTENT); + lv_obj_set_style_pad_all(font_size_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_border_width(font_size_wrapper, 0, LV_STATE_DEFAULT); + + auto* font_size_label = lv_label_create(font_size_wrapper); + lv_label_set_text(font_size_label, "Font size"); + lv_obj_align(font_size_label, LV_ALIGN_LEFT_MID, 0, 0); + + auto* font_size_dropdown = lv_dropdown_create(font_size_wrapper); + lv_dropdown_set_options(font_size_dropdown, "Small\nDefault\nLarge"); + lv_obj_align(font_size_dropdown, LV_ALIGN_RIGHT_MID, 0, 0); + lv_obj_add_event_cb(font_size_dropdown, onFontSizeChanged, LV_EVENT_VALUE_CHANGED, this); + lv_dropdown_set_selected(font_size_dropdown, static_cast(displaySettings.fontSize)); + // Screen timeout // Note: DisplayIdleService doesn't act on these settings for kernel-driver displays yet // (it only looks up the deprecated tt::hal::display::DisplayDevice), so these currently diff --git a/Tactility/Source/lvgl/Lvgl.cpp b/Tactility/Source/lvgl/Lvgl.cpp index 601114be..6eb85fa8 100644 --- a/Tactility/Source/lvgl/Lvgl.cpp +++ b/Tactility/Source/lvgl/Lvgl.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,49 @@ bool isStarted() { return module_is_started(&lvgl_module); } +void applyFontSize(settings::display::FontSize fontSize) { + LvglFontScale scale; + switch (fontSize) { + using enum settings::display::FontSize; + case Small: + scale = FONT_SCALE_SMALL; + break; + case Large: + scale = FONT_SCALE_LARGE; + break; + case Default: + default: + scale = FONT_SCALE_DEFAULT; + break; + } + + lvgl_set_text_font_scale(scale); + const lv_font_t* font = lvgl_get_text_font(FONT_SIZE_DEFAULT); + + for (lv_display_t* display = lv_display_get_next(nullptr); + display != nullptr; + display = lv_display_get_next(display)) { +#if LV_USE_THEME_DEFAULT + if (lv_display_get_theme(display) == lv_theme_default_get()) { + lv_obj_t* screen = lv_display_get_screen_active(display); + lv_theme_default_init( + display, + lv_theme_get_color_primary(screen), + lv_theme_get_color_secondary(screen), + LV_THEME_DEFAULT_DARK, + font + ); + } +#endif + // The display layers are independent inheritance roots. Updating all of them makes + // the new size visible immediately in regular screens, overlays, and the status bar. + lv_obj_set_style_text_font(lv_display_get_screen_active(display), font, LV_PART_MAIN); + lv_obj_set_style_text_font(lv_display_get_layer_top(display), font, LV_PART_MAIN); + lv_obj_set_style_text_font(lv_display_get_layer_sys(display), font, LV_PART_MAIN); + lv_obj_set_style_text_font(lv_display_get_layer_bottom(display), font, LV_PART_MAIN); + } +} + void attachDevices() { LOG_I(TAG, "Adding devices"); @@ -55,6 +99,7 @@ void attachDevices() { if (rotation != lv_display_get_rotation(primary_lvgl_display)) { lv_display_set_rotation(primary_lvgl_display, rotation); } + applyFontSize(settings.fontSize); } // Start touch diff --git a/Tactility/Source/settings/DisplaySettings.cpp b/Tactility/Source/settings/DisplaySettings.cpp index 918e18de..b572c19c 100644 --- a/Tactility/Source/settings/DisplaySettings.cpp +++ b/Tactility/Source/settings/DisplaySettings.cpp @@ -17,6 +17,7 @@ static std::string getSettingsFilePath() { } constexpr auto* SETTINGS_KEY_ORIENTATION = "orientation"; +constexpr auto* SETTINGS_KEY_FONT_SIZE = "fontSize"; constexpr auto* SETTINGS_KEY_GAMMA_CURVE = "gammaCurve"; constexpr auto* SETTINGS_KEY_BACKLIGHT_DUTY = "backlightDuty"; constexpr auto* SETTINGS_KEY_TIMEOUT_ENABLED = "backlightTimeoutEnabled"; @@ -71,6 +72,34 @@ static bool fromString(const std::string& str, Orientation& orientation) { } } +static std::string toString(FontSize font_size) { + switch (font_size) { + using enum FontSize; + case Small: + return "Small"; + case Default: + return "Default"; + case Large: + return "Large"; + default: + std::unreachable(); + } +} + +static bool fromString(const std::string& str, FontSize& font_size) { + if (str == "Small") { + font_size = FontSize::Small; + return true; + } else if (str == "Default") { + font_size = FontSize::Default; + return true; + } else if (str == "Large") { + font_size = FontSize::Large; + return true; + } + return false; +} + static std::string toString(ScreensaverType type) { switch (type) { using enum ScreensaverType; @@ -132,6 +161,12 @@ bool load(DisplaySettings& settings) { orientation = getDefaultOrientation(); } + auto font_size_entry = map.find(SETTINGS_KEY_FONT_SIZE); + FontSize font_size = FontSize::Default; + if (font_size_entry != map.end()) { + fromString(font_size_entry->second, font_size); + } + auto gamma_entry = map.find(SETTINGS_KEY_GAMMA_CURVE); int gamma_curve = 0; if (gamma_entry != map.end()) { @@ -172,6 +207,7 @@ bool load(DisplaySettings& settings) { } settings.orientation = orientation; + settings.fontSize = font_size; settings.gammaCurve = gamma_curve; settings.backlightDuty = backlight_duty; settings.backlightTimeoutEnabled = timeout_enabled; @@ -185,6 +221,7 @@ bool load(DisplaySettings& settings) { DisplaySettings getDefault() { return DisplaySettings { .orientation = getDefaultOrientation(), + .fontSize = FontSize::Default, .gammaCurve = 1, .backlightDuty = 200, .backlightTimeoutEnabled = false, @@ -207,6 +244,7 @@ bool save(const DisplaySettings& settings) { map[SETTINGS_KEY_BACKLIGHT_DUTY] = std::to_string(settings.backlightDuty); map[SETTINGS_KEY_GAMMA_CURVE] = std::to_string(settings.gammaCurve); map[SETTINGS_KEY_ORIENTATION] = toString(settings.orientation); + map[SETTINGS_KEY_FONT_SIZE] = toString(settings.fontSize); map[SETTINGS_KEY_TIMEOUT_ENABLED] = settings.backlightTimeoutEnabled ? "1" : "0"; map[SETTINGS_KEY_TIMEOUT_MS] = std::to_string(settings.backlightTimeoutMs); map[SETTINGS_KEY_SCREENSAVER_TYPE] = toString(settings.screensaverType);