/* * a class to keep definitions for all theme settings */ extern "C" { #include } #include "libegint.h" #include "../refit/screen.h" #include "../refit/lib.h" #include "XTheme.h" #include "nanosvg.h" #ifndef DEBUG_ALL #define DEBUG_XICON 1 #else #define DEBUG_XICON DEBUG_ALL #endif #if DEBUG_XICON == 0 #define DBG(...) #else #define DBG(...) DebugLog(DEBUG_XICON, __VA_ARGS__) #endif CONST CHAR8* IconsNames[] = { "func_about", "func_options", "func_clover", "func_secureboot", "func_secureboot_config", "func_reset", "func_shutdown", "func_help", "tool_shell", //8 "tool_part", "tool_rescue", "pointer",//11 "vol_internal", "vol_external", "vol_optical", "vol_firewire", "vol_clover" , "vol_internal_hfs" , //17 "vol_internal_apfs", "vol_internal_ntfs", "vol_internal_ext3" , "vol_recovery",//21 // not used? will be skipped while theme parsing "logo", "selection_small", "selection_big", //BUILTIN_SELECTION_BIG=24 we keep this numeration //os icons "os_mac", //0 + 25 "os_tiger", "os_leo", "os_snow", "os_lion", "os_cougar", "os_mav", "os_yos", "os_cap", //33 "os_sierra", "os_hsierra", "os_moja", //36 "os_cata", //37 //there is no reserve for 10.16, next oses should be added to the end of the list "os_linux", //13 + 25 = 38 "os_ubuntu", "os_suse", "os_freebsd", //16+25 = 41 "os_freedos", "os_win", "os_vista", "radio_button", //20+25 = 45 "radio_button_selected", "checkbox", //22+25 = 47 "checkbox_checked", "scrollbar_background", //24 - present here for SVG theme but should be done more common way "scrollbar_holder", "os_unknown", //51 == ICON_OTHER_OS "os_clover", //52 == ICON_CLOVER //other oses will be added below "os_bigsur", //53 == ICON_BIGSUR "os_monterey", //54 == ICON_MONTEREY "os_ventura", //55 == ICON_VENTURA "" }; const INTN IconsNamesSize = sizeof(IconsNames) / sizeof(IconsNames[0]); //icons class //if ImageNight is not set then Image should be used #define DEC_BUILTIN_ICON(id, ico) { \ Empty = EFI_ERROR(Image.FromPNG(ACCESS_EMB_DATA(ico), ACCESS_EMB_SIZE(ico))); \ } #define DEC_BUILTIN_ICON2(id, ico, dark) { \ Empty = EFI_ERROR(Image.FromPNG(ACCESS_EMB_DATA(ico), ACCESS_EMB_SIZE(ico))); \ ImageNight.FromPNG(ACCESS_EMB_DATA(dark), ACCESS_EMB_SIZE(dark)); \ } XIcon::~XIcon() { // memory leak : we can't free (yet?) ImageSVG and ImageSVGnight because operator might have copied it } XIcon::XIcon(INTN Index, XBool TakeEmbedded) : Id(Index), Name(), Image(), ImageNight(), Native(false), ImageSVG(nullptr), ImageSVGnight(nullptr), Empty(false) { // Id = Index; // Name.setEmpty(); // Native = false; // ImageSVG = nullptr; // ImageSVGnight = nullptr; if (Index >= BUILTIN_ICON_FUNC_ABOUT && Index < IconsNamesSize) { //full table Name.takeValueFrom(IconsNames[Index]); } if (TakeEmbedded) { GetEmbedded(); } } XIcon& XIcon::operator=(const XIcon& src) { Id = src.Id; Name = src.Name; Image = src.Image; ImageNight = src.ImageNight; Native = src.Native; Empty = src.Empty; //this moment we copy pointers. Later it will be class variables ImageSVG = src.ImageSVG; ImageSVGnight = src.ImageSVGnight; return *this; } void XIcon::GetEmbedded() { switch (Id) { case BUILTIN_ICON_FUNC_ABOUT: DEC_BUILTIN_ICON2(BUILTIN_ICON_FUNC_ABOUT, emb_func_about, emb_dark_func_about) break; case BUILTIN_ICON_FUNC_OPTIONS: DEC_BUILTIN_ICON2(BUILTIN_ICON_FUNC_OPTIONS, emb_func_options, emb_dark_func_options) break; case BUILTIN_ICON_FUNC_CLOVER: DEC_BUILTIN_ICON2(BUILTIN_ICON_FUNC_CLOVER, emb_func_clover, emb_dark_func_clover) break; case BUILTIN_ICON_FUNC_SECURE_BOOT: DEC_BUILTIN_ICON2(BUILTIN_ICON_FUNC_SECURE_BOOT, emb_func_secureboot, emb_dark_func_secureboot) break; case BUILTIN_ICON_FUNC_SECURE_BOOT_CONFIG: DEC_BUILTIN_ICON2(BUILTIN_ICON_FUNC_SECURE_BOOT_CONFIG, emb_func_secureboot_config, emb_dark_func_secureboot_config) break; case BUILTIN_ICON_FUNC_RESET: DEC_BUILTIN_ICON2(BUILTIN_ICON_FUNC_RESET, emb_func_reset, emb_dark_func_reset) break; case BUILTIN_ICON_FUNC_EXIT: DEC_BUILTIN_ICON2(BUILTIN_ICON_FUNC_EXIT, emb_func_exit, emb_dark_func_exit) break; case BUILTIN_ICON_FUNC_HELP: DEC_BUILTIN_ICON2(BUILTIN_ICON_FUNC_HELP, emb_func_help, emb_dark_func_help) break; case BUILTIN_ICON_TOOL_SHELL: DEC_BUILTIN_ICON2(BUILTIN_ICON_TOOL_SHELL, emb_func_shell, emb_dark_func_shell) break; case BUILTIN_ICON_BANNER: DEC_BUILTIN_ICON2(BUILTIN_ICON_BANNER, emb_logo, emb_dark_logo) break; case BUILTIN_SELECTION_SMALL: DEC_BUILTIN_ICON2(BUILTIN_SELECTION_SMALL, emb_selection_small, emb_dark_selection_small) break; case BUILTIN_SELECTION_BIG: DEC_BUILTIN_ICON2(BUILTIN_SELECTION_BIG, emb_selection_big, emb_dark_selection_big) break; //next icons have no dark image case BUILTIN_ICON_POINTER: DEC_BUILTIN_ICON(BUILTIN_ICON_POINTER, emb_pointer) break; case BUILTIN_ICON_VOL_INTERNAL: DEC_BUILTIN_ICON(BUILTIN_ICON_VOL_INTERNAL, emb_vol_internal) break; case BUILTIN_ICON_VOL_EXTERNAL: DEC_BUILTIN_ICON(BUILTIN_ICON_VOL_EXTERNAL, emb_vol_external) break; case BUILTIN_ICON_VOL_OPTICAL: DEC_BUILTIN_ICON(BUILTIN_ICON_VOL_OPTICAL, emb_vol_optical) break; case BUILTIN_ICON_VOL_BOOTER: DEC_BUILTIN_ICON(BUILTIN_ICON_VOL_BOOTER, emb_vol_internal_booter) break; case BUILTIN_ICON_VOL_INTERNAL_HFS: DEC_BUILTIN_ICON(BUILTIN_ICON_VOL_INTERNAL_HFS, emb_vol_internal_hfs) break; case BUILTIN_ICON_VOL_INTERNAL_APFS: DEC_BUILTIN_ICON(BUILTIN_ICON_VOL_INTERNAL_APFS, emb_vol_internal_apfs) break; case BUILTIN_ICON_VOL_INTERNAL_NTFS: DEC_BUILTIN_ICON(BUILTIN_ICON_VOL_INTERNAL_NTFS, emb_vol_internal_ntfs) break; case BUILTIN_ICON_VOL_INTERNAL_EXT3: DEC_BUILTIN_ICON(BUILTIN_ICON_VOL_INTERNAL_EXT3, emb_vol_internal_ext) break; case BUILTIN_ICON_VOL_INTERNAL_REC: DEC_BUILTIN_ICON(BUILTIN_ICON_VOL_INTERNAL_REC, emb_vol_internal_recovery) break; case BUILTIN_RADIO_BUTTON: DEC_BUILTIN_ICON(BUILTIN_RADIO_BUTTON, emb_radio_button) break; case BUILTIN_RADIO_BUTTON_SELECTED: DEC_BUILTIN_ICON(BUILTIN_RADIO_BUTTON_SELECTED, emb_radio_button_selected) break; case BUILTIN_CHECKBOX: DEC_BUILTIN_ICON(BUILTIN_CHECKBOX, emb_checkbox) break; case BUILTIN_CHECKBOX_CHECKED: DEC_BUILTIN_ICON(BUILTIN_CHECKBOX_CHECKED, emb_checkbox_checked) break; case BUILTIN_ICON_SELECTION: Name.takeValueFrom("selection_indicator"); DEC_BUILTIN_ICON(BUILTIN_ICON_SELECTION, emb_selection_indicator) break; default: // Image.setEmpty(); //done by ctor? break; } //something to do else? } //copy from XImage for our purpose EFI_STATUS XIcon::LoadXImage(const EFI_FILE *BaseDir, const char* IconName) { return LoadXImage(BaseDir, XStringW().takeValueFrom(IconName)); } EFI_STATUS XIcon::LoadXImage(const EFI_FILE *BaseDir, const wchar_t* LIconName) { return LoadXImage(BaseDir, XStringW().takeValueFrom(LIconName)); } //dont call this procedure for SVG theme BaseDir == NULL? //it can be used for other files EFI_STATUS XIcon::LoadXImage(const EFI_FILE *BaseDir, const XStringW& IconName) { EFI_STATUS Status = Image.LoadXImage(BaseDir, IconName); ImageNight.LoadXImage(BaseDir, IconName + L"_night"_XSW); if (!EFI_ERROR(Status)) setFilled(); return Status; } XImage* XIcon::GetBest(XBool night, XBool *free) { #if 1 if (ImageSVG) { NSVGimage* sImage = (NSVGimage*)ImageSVGnight; if (!night || !ImageSVGnight) sImage = (NSVGimage*)ImageSVG; float Scale = sImage->scale; NSVGrasterizer* rast = nsvgCreateRasterizer(); float Height = sImage->height * Scale; float Width = sImage->width * Scale; int iWidth = (int)(Width + 0.5f); int iHeight = (int)(Height + 0.5f); XImage* NewImage = new XImage(iWidth, iHeight); //TODO creating new XImage we have to delete it after use if (sImage->shapes == NULL) { if (free) *free = true; return NewImage; } float bounds[4]; nsvg__imageBounds(sImage, bounds); float tx = 0.f, ty = 0.f; float realWidth = (bounds[2] - bounds[0]) * Scale; float realHeight = (bounds[3] - bounds[1]) * Scale; tx = (Width - realWidth) * 0.5f; ty = (Height - realHeight) * 0.5f; nsvgRasterize(rast, sImage, tx, ty, Scale, Scale, (UINT8*)NewImage->GetPixelPtr(0,0), iWidth, iHeight, iWidth*4); nsvgDeleteRasterizer(rast); // if (night) ImageNight = *NewImage; // else Image = *NewImage; // delete NewImage; if (free) *free = true; return NewImage; } #endif XImage* RetImage = (night && !ImageNight.isEmpty())? &ImageNight : &Image; if (free) *free = false; return RetImage; }