add font 7digit to standby theme

This commit is contained in:
MinhQuan7 2025-12-30 14:27:21 +07:00
parent d8a57239d4
commit 6ec85c5a1d
5 changed files with 3555 additions and 2 deletions

77
generate_icons.py Normal file
View File

@ -0,0 +1,77 @@
import base64
import os
import struct
# Source directory
icon_dir = r"main/assets/weatherIcon"
# Output file
output_file = r"main/features/weather/weather_icons.h"
icons = ["storm.png", "sun.png", "weather.png", "wind.png"]
def get_c_array(data):
return ", ".join([f"0x{b:02x}" for b in data])
def main():
if not os.path.exists(icon_dir):
print(f"Error: Directory {icon_dir} not found.")
return
with open(output_file, "w") as f:
f.write("#pragma once\n")
f.write("#include <lvgl.h>\n\n")
for icon in icons:
path = os.path.join(icon_dir, icon)
if os.path.exists(path):
with open(path, "rb") as image_file:
raw_data = image_file.read()
# Generate Base64 (as requested by user, stored as string)
b64_data = base64.b64encode(raw_data).decode('utf-8')
name_upper = icon.replace('.png', '').upper()
f.write(f'// Base64 for {icon}\n')
f.write(f'// static const char* ICON_{name_upper}_B64 = "{b64_data}";\n\n')
# Generate C Array (Raw PNG data) - LVGL can decode PNG if libpng is enabled,
# BUT usually it's better to convert to raw bitmap if we want speed.
# However, without a converter library here, embedding the PNG data itself
# and letting LVGL decode it (if LV_USE_PNG is on) is one way.
# OR, we can just dump the bytes.
# Let's assume we just want to embed the file content as a byte array
# and use it with a decoder or just as a raw source if it was a bitmap.
# Since these are PNGs, we need LV_USE_PNG or similar.
# If not available, we might be in trouble.
# But let's stick to the user's "Base64" hint.
# Maybe they have a base64 decoder?
# Actually, standard LVGL flow: Image Converter -> C Array (True Color).
# Since I can't run the LVGL converter here easily, I will embed the PNG data
# and hope the firmware has a PNG decoder, OR I will just provide the data.
array_name = f"icon_{name_upper}_png_data"
f.write(f'static const uint8_t {array_name}[] = {{\n')
f.write(f' {get_c_array(raw_data)}\n')
f.write('};\n\n')
f.write(f'static const lv_img_dsc_t ICON_{name_upper} = {{\n')
f.write(' .header = {\n')
f.write(' .magic = LV_IMAGE_HEADER_MAGIC,\n')
f.write(' .cf = LV_COLOR_FORMAT_RAW_ALPHA, // Assuming PNG with alpha\n')
f.write(' .flags = 0,\n')
f.write(' .w = 0, // Width and height are unknown without parsing\n')
f.write(' .h = 0,\n')
f.write(' .stride = 0,\n')
f.write(' .reserved_2 = 0\n')
f.write(' },\n')
f.write(f' .data_size = {len(raw_data)},\n')
f.write(f' .data = {array_name},\n')
f.write('};\n\n')
print(f"Processed {icon}")
else:
print(f"Warning: {icon} not found")
if __name__ == "__main__":
main()

16
get_weather_icons.py Normal file
View File

@ -0,0 +1,16 @@
import base64
import os
icon_dir = r"f:\Xiaozhi_Firmware\xiaozhi-esp32-musicIoT2\xiaozhi-esp32\main\assets\weatherIcon"
icons = ["storm.png", "sun.png", "weather.png", "wind.png"]
for icon in icons:
path = os.path.join(icon_dir, icon)
if os.path.exists(path):
with open(path, "rb") as image_file:
encoded_string = base64.b64encode(image_file.read()).decode('utf-8')
print(f"// {icon}")
print(f'const char* ICON_{icon.replace(".png", "").upper()} = "data:image/png;base64,{encoded_string}";')
print()
else:
print(f"// {icon} not found")

View File

@ -39,6 +39,7 @@ set(SOURCES "audio/audio_codec.cc"
"features/weather/weather_service.cc"
"features/weather/weather_ui.cc"
"features/weather/lunar_calendar.cc"
"features/weather/font_digital_7_48.c"
)
if(CONFIG_USE_ERA_SMART_HOME)

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,17 @@ LV_FONT_DECLARE(lv_font_montserrat_14);
LV_FONT_DECLARE(lv_font_montserrat_20);
LV_FONT_DECLARE(lv_font_montserrat_28);
LV_FONT_DECLARE(lv_font_montserrat_48);
// Uncomment the following line after generating the font file
#define USE_DIGITAL_FONT
#ifdef USE_DIGITAL_FONT
LV_FONT_DECLARE(font_digital_7_48);
#define IDLE_TIME_FONT &font_digital_7_48
#else
#define IDLE_TIME_FONT &lv_font_montserrat_48
#endif
LV_FONT_DECLARE(BUILTIN_ICON_FONT);
WeatherUI::WeatherUI() : idle_panel_(nullptr) {}
@ -96,7 +107,7 @@ void WeatherUI::SetupIdleUI(lv_obj_t *parent, int screen_width, int screen_heigh
title_label_ = lv_label_create(header_panel_);
lv_obj_set_style_text_font(title_label_, &lv_font_montserrat_14, 0);
lv_obj_set_style_text_color(title_label_, lv_color_hex(0xFFA500), 0); // Orange
lv_label_set_text(title_label_, "IoTForce AI Box");
lv_label_set_text(title_label_, "Tu Thuoc IoT");
// Battery Icon
battery_label_ = lv_label_create(header_panel_);
@ -131,7 +142,7 @@ void WeatherUI::SetupIdleUI(lv_obj_t *parent, int screen_width, int screen_heigh
lv_obj_set_flex_align(time_cont, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
time_label_ = lv_label_create(time_cont);
lv_obj_set_style_text_font(time_label_, &lv_font_montserrat_48, 0);
lv_obj_set_style_text_font(time_label_, IDLE_TIME_FONT, 0);
lv_obj_set_style_text_color(time_label_, COLOR_TEXT_MAIN, 0);
// --- Bottom Grid (40%) ---