#include "common.h" #include "common.h" #include #include "fat/File.h" #include "json/ArduinoJson.h" #include "core/mini-printf.h" #include "core/math/Rgb.h" #include "ThemeInfoFactory.h" #pragma GCC optimize("Os") #define JSON_RESERVED_SIZE 2048 #define KEY_TYPE "type" #define KEY_NAME "name" #define KEY_DESCRIPTION "description" #define KEY_AUTHOR "author" #define KEY_PRIMARY_COLOR "primaryColor" #define KEY_COLOR_R "r" #define KEY_COLOR_G "g" #define KEY_COLOR_B "b" #define KEY_DARK_THEME "darkTheme" static bool tryParseThemeType(const char* themeTypeString, ThemeType& themeType) { if (!themeTypeString) return false; if (!strcasecmp(themeTypeString, "Material")) themeType = ThemeType::Material; else if (!strcasecmp(themeTypeString, "Custom")) themeType = ThemeType::Custom; else return false; return true; } static Rgb<8, 8, 8> parseColor(const JsonObjectConst& json, const Rgb<8, 8, 8>& defaultColor) { if (json.isNull()) { return defaultColor; } return Rgb<8, 8, 8>( json[KEY_COLOR_R] | 0, json[KEY_COLOR_G] | 0, json[KEY_COLOR_B] | 0 ); } static std::unique_ptr fromJson(const TCHAR* folderName, const JsonDocument& json) { ThemeType themeType; if (!tryParseThemeType(json[KEY_TYPE].as(), themeType)) { themeType = ThemeType::Custom; } return std::make_unique( folderName, themeType, json[KEY_NAME] | "", json[KEY_DESCRIPTION] | "", json[KEY_AUTHOR] | "", parseColor(json[KEY_PRIMARY_COLOR], Rgb<8, 8, 8>(0xFF, 0xFF, 0xFF)), json[KEY_DARK_THEME] | false ); } std::unique_ptr ThemeInfoFactory::CreateFromThemeFolder(const TCHAR* folderName) const { TCHAR pathBuffer[128]; mini_snprintf(pathBuffer, sizeof(pathBuffer), "/_pico/themes/%s/theme.json", folderName); const auto file = std::make_unique(); if (file->Open(pathBuffer, FA_READ | FA_OPEN_EXISTING) != FR_OK) { return nullptr; } u32 fileSize = file->GetSize(); if (fileSize == 0) { return nullptr; } std::unique_ptr fileData(new(cache_align) u8[fileSize]); u8* fileDataPtr = fileData.get(); u32 bytesRead = 0; if (file->Read(fileDataPtr, fileSize, bytesRead) != FR_OK) { return nullptr; } DynamicJsonDocument json(JSON_RESERVED_SIZE); if (deserializeJson(json, fileDataPtr, fileSize) != DeserializationError::Ok) { return nullptr; } return fromJson(folderName, json); }