mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-26 16:47:40 +01:00
293 lines
8.8 KiB
C++
293 lines
8.8 KiB
C++
/*
|
|
* a class to keep definitions for all theme settings
|
|
*/
|
|
|
|
extern "C" {
|
|
#include <Protocol/GraphicsOutput.h>
|
|
}
|
|
|
|
#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
|
|
""
|
|
};
|
|
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;
|
|
}
|
|
|
|
|
|
|