mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2025-02-21 01:52:36 +01:00
Fix nanosvg leaks.
Move global variable textfaces in XTheme. Move global variable fontsDB in XTheme. Remove XTheme member SVGParser. SVGParser is deleted just after use. Remove XTheme members ImageSVG and ImageSVGnight. All images are rasterized at load, so no need to keep that. Remove XIcon setFilled because XIcon knows if it's filled or not by checking Image & ImageNight
This commit is contained in:
parent
8de61a22fb
commit
42cece9885
@ -10,7 +10,11 @@
|
||||
// Mem log sizes
|
||||
//
|
||||
#define MEM_LOG_INITIAL_SIZE (128 * 1024)
|
||||
#ifdef JIEF_DEBUG
|
||||
#define MEM_LOG_MAX_SIZE (10 * 1024 * 1024)
|
||||
#else
|
||||
#define MEM_LOG_MAX_SIZE (2 * 1024 * 1024)
|
||||
#endif
|
||||
#define MEM_LOG_MAX_LINE_SIZE 1024
|
||||
|
||||
|
||||
|
@ -457,6 +457,7 @@ static void transmitS8Printf(const char* buf, unsigned int nbchar, void* context
|
||||
// but not too big (if something gets out of controll)
|
||||
if (mMemLog->BufferSize + MEM_LOG_INITIAL_SIZE > MEM_LOG_MAX_SIZE) {
|
||||
// Out of resources!
|
||||
// Jief : Silent fail. TODO : At least put "Out of resource" at the end of the log
|
||||
return;
|
||||
}
|
||||
Offset = mMemLog->Cursor - mMemLog->Buffer;
|
||||
|
@ -115,14 +115,10 @@ const SETTINGS_DATA::SmbiosClass::SlotDeviceClass SETTINGS_DATA::SmbiosClass::Sl
|
||||
CUSTOM_LOADER_ENTRY::CUSTOM_LOADER_ENTRY(const CUSTOM_LOADER_ENTRY_SETTINGS& _settings) : settings(_settings)
|
||||
{
|
||||
if ( settings.ImageData.notEmpty() ) {
|
||||
if ( !EFI_ERROR(Image.Image.FromPNG(settings.ImageData.data(), settings.ImageData.size())) ) {
|
||||
Image.setFilled();
|
||||
}
|
||||
Image.Image.FromPNG(settings.ImageData.data(), settings.ImageData.size());
|
||||
}
|
||||
if ( settings.DriveImageData.notEmpty() ) {
|
||||
if ( !EFI_ERROR(DriveImage.Image.FromPNG(settings.DriveImageData.data(), settings.DriveImageData.size())) ) {
|
||||
DriveImage.setFilled();
|
||||
}
|
||||
DriveImage.Image.FromPNG(settings.DriveImageData.data(), settings.DriveImageData.size());
|
||||
}
|
||||
|
||||
if ( settings.CustomLogoTypeSettings == CUSTOM_BOOT_USER && settings.CustomLogoAsXString8.notEmpty() ) {
|
||||
|
@ -473,16 +473,12 @@ public:
|
||||
if ( settings.ImagePath.notEmpty() ) {
|
||||
Image.LoadXImage(&ThemeDir, settings.ImagePath);
|
||||
}else if ( settings.ImageData.notEmpty() ) {
|
||||
if ( !EFI_ERROR(Image.Image.FromPNG(settings.ImageData.data(), settings.ImageData.size())) ) {
|
||||
Image.setFilled();
|
||||
}
|
||||
Image.Image.FromPNG(settings.ImageData.data(), settings.ImageData.size());
|
||||
}
|
||||
if ( settings.DriveImagePath.notEmpty() ) {
|
||||
DriveImage.LoadXImage(&ThemeDir, settings.DriveImagePath);
|
||||
}else if ( settings.DriveImageData.notEmpty() ) {
|
||||
if ( !EFI_ERROR(DriveImage.Image.FromPNG(settings.DriveImageData.data(), settings.DriveImageData.size())) ) {
|
||||
DriveImage.setFilled();
|
||||
}
|
||||
DriveImage.Image.FromPNG(settings.DriveImageData.data(), settings.DriveImageData.size());
|
||||
}
|
||||
}
|
||||
|
||||
@ -560,9 +556,7 @@ public:
|
||||
if ( settings.ImagePath.notEmpty() ) {
|
||||
Image.LoadXImage(&ThemeDir, settings.ImagePath);
|
||||
} else if ( settings.ImageData.notEmpty() ) {
|
||||
if ( !EFI_ERROR(Image.Image.FromPNG(settings.ImageData.data(), settings.ImageData.size())) ) {
|
||||
Image.setFilled();
|
||||
}
|
||||
Image.Image.FromPNG(settings.ImageData.data(), settings.ImageData.size());
|
||||
}
|
||||
}
|
||||
UINT8 getFlags() const {
|
||||
|
@ -1180,7 +1180,6 @@ if ( Entry->APFSTargetUUID.Data1 == 0x99999999 ) {
|
||||
if (gSettings.GUI.CustomIcons && FileExists(Volume->RootDir, L"\\.VolumeIcon.icns")){
|
||||
Entry->Image.Image.LoadIcns(Volume->RootDir, L"\\.VolumeIcon.icns", 128);
|
||||
if (!Entry->Image.Image.isEmpty()) {
|
||||
Entry->Image.setFilled();
|
||||
DBG("%susing VolumeIcon.icns image from Volume\n", indent);
|
||||
}
|
||||
} else if (Image) {
|
||||
@ -1205,9 +1204,6 @@ if ( Entry->APFSTargetUUID.Data1 == 0x99999999 ) {
|
||||
Entry->BadgeImage.Image = XImage(Entry->Image.Image, 0);
|
||||
DBG("%sShow badge as OSImage.\n", indent);
|
||||
}
|
||||
if (!Entry->BadgeImage.Image.isEmpty()) {
|
||||
Entry->BadgeImage.setFilled();
|
||||
}
|
||||
}
|
||||
Entry->BootBgColor = BootBgColor;
|
||||
Entry->KernelAndKextPatches = Patches == NULL ? gSettings.KernelAndKextPatches : *Patches;
|
||||
|
@ -229,7 +229,6 @@ void REFIT_MAINMENU_SCREEN::DrawMainMenuEntry(REFIT_ABSTRACT_MENU_ENTRY *Entry,
|
||||
}
|
||||
if (MainIcon.Image.isEmpty()) {
|
||||
MainIcon.Image.DummyImage(MainSize);
|
||||
MainIcon.setFilled();
|
||||
}
|
||||
}
|
||||
|
||||
@ -349,8 +348,8 @@ void REFIT_MAINMENU_SCREEN::MainMenuStyle(IN UINTN Function, IN CONST CHAR16 *Pa
|
||||
// INTN i = 0;
|
||||
INTN MessageHeight = 0;
|
||||
// clovy
|
||||
if (ThemeX->TypeSVG && textFace[1].valid) {
|
||||
MessageHeight = (INTN)(textFace[1].size * RowHeightFromTextHeight * ThemeX->Scale);
|
||||
if (ThemeX->TypeSVG && ThemeX->getTextFace(1).valid) {
|
||||
MessageHeight = (INTN)(ThemeX->getTextFace(1).size * RowHeightFromTextHeight * ThemeX->Scale);
|
||||
} else {
|
||||
MessageHeight = (INTN)(ThemeX->TextHeight * RowHeightFromTextHeight * ThemeX->Scale);
|
||||
}
|
||||
@ -574,8 +573,8 @@ void REFIT_MAINMENU_SCREEN::MainMenuVerticalStyle(IN UINTN Function, IN CONST CH
|
||||
INTN VisibleHeight = (UGAHeight - EntriesPosY - (int)(LAYOUT_Y_EDGE * ThemeX->Scale) + EntriesGap) / (EntriesHeight + EntriesGap);
|
||||
EntriesPosX = UGAWidth - EntriesWidth - (int)((BAR_WIDTH + LAYOUT_X_EDGE) * ThemeX->Scale);
|
||||
INTN MessageHeight = 20;
|
||||
if (ThemeX->TypeSVG && textFace[1].valid) {
|
||||
MessageHeight = (INTN)(textFace[1].size * RowHeightFromTextHeight * ThemeX->Scale);
|
||||
if (ThemeX->TypeSVG && ThemeX->getTextFace(1).valid) {
|
||||
MessageHeight = (INTN)(ThemeX->getTextFace(1).size * RowHeightFromTextHeight * ThemeX->Scale);
|
||||
} else {
|
||||
MessageHeight = (INTN)(ThemeX->TextHeight * RowHeightFromTextHeight * ThemeX->Scale);
|
||||
}
|
||||
@ -684,8 +683,8 @@ void REFIT_MAINMENU_SCREEN::MainMenuVerticalStyle(IN UINTN Function, IN CONST CH
|
||||
|
||||
case MENU_FUNCTION_PAINT_TIMEOUT:
|
||||
INTN MessageHeight = 20;
|
||||
if (ThemeX->TypeSVG && textFace[1].valid) {
|
||||
MessageHeight = (INTN)(textFace[1].size * RowHeightFromTextHeight * ThemeX->Scale);
|
||||
if (ThemeX->TypeSVG && ThemeX->getTextFace(1).valid) {
|
||||
MessageHeight = (INTN)(ThemeX->getTextFace(1).size * RowHeightFromTextHeight * ThemeX->Scale);
|
||||
} else {
|
||||
MessageHeight = (INTN)(ThemeX->TextHeight * RowHeightFromTextHeight * ThemeX->Scale);
|
||||
}
|
||||
|
@ -705,22 +705,22 @@ UINTN REFIT_MENU_SCREEN::RunGenericMenu(IN OUT INTN *DefaultEntryIndex, OUT REFI
|
||||
TextStyle = 2;
|
||||
}
|
||||
if (ThemeX->TypeSVG) {
|
||||
if (!textFace[TextStyle].valid) {
|
||||
if (textFace[0].valid) {
|
||||
if (!ThemeX->getTextFace(TextStyle).valid) {
|
||||
if (ThemeX->getTextFace(0).valid) {
|
||||
TextStyle = 0;
|
||||
} else if (textFace[2].valid) {
|
||||
} else if (ThemeX->getTextFace(2).valid) {
|
||||
TextStyle = 2;
|
||||
} else if (textFace[1].valid) {
|
||||
} else if (ThemeX->getTextFace(1).valid) {
|
||||
TextStyle = 1;
|
||||
} else {
|
||||
DBG("no valid text style\n");
|
||||
textFace[TextStyle].size = ThemeX->TextHeight - 4;
|
||||
// ThemeX->getTextFace(TextStyle).size = ThemeX->TextHeight - 4;
|
||||
}
|
||||
}
|
||||
if (textFace[TextStyle].valid) {
|
||||
// TextHeight = (int)((textFace[TextStyle].size + 4) * GlobalConfig.Scale);
|
||||
if (ThemeX->getTextFace(TextStyle).valid) {
|
||||
// TextHeight = (int)((ThemeX->getTextFace(TextStyle].size + 4) * GlobalConfig.Scale);
|
||||
//clovy - row height / text size factor
|
||||
ThemeX->TextHeight = (int)((textFace[TextStyle].size * RowHeightFromTextHeight) * ThemeX->Scale);
|
||||
ThemeX->TextHeight = (int)((ThemeX->getTextFace(TextStyle).size * RowHeightFromTextHeight) * ThemeX->Scale);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1314,8 +1314,8 @@ INTN REFIT_MENU_SCREEN::DrawTextXY(IN const XStringW& Text, IN INTN XPos, IN INT
|
||||
}
|
||||
//TODO assume using embedded font for BootScreen
|
||||
//messages must be TextXYStyle = 1 if it is provided by theme
|
||||
if (!textFace[1].valid) {
|
||||
if (textFace[2].valid) {
|
||||
if (!ThemeX->getTextFace(1).valid) {
|
||||
if (ThemeX->getTextFace(2).valid) {
|
||||
TextXYStyle = 2;
|
||||
} else {
|
||||
TextXYStyle = 0;
|
||||
@ -1336,11 +1336,11 @@ INTN REFIT_MENU_SCREEN::DrawTextXY(IN const XStringW& Text, IN INTN XPos, IN INT
|
||||
|
||||
if (!isBootScreen && ThemeX->TypeSVG) {
|
||||
TextWidth += ThemeX->TextHeight * 2; //give more place for buffer
|
||||
if (!textFace[TextXYStyle].valid) {
|
||||
if (!ThemeX->getTextFace(TextXYStyle).valid) {
|
||||
DBG("no vaid text face for message!\n");
|
||||
Height = ThemeX->TextHeight;
|
||||
} else {
|
||||
Height = (int)(textFace[TextXYStyle].size * RowHeightFromTextHeight * ThemeX->Scale);
|
||||
Height = (int)(ThemeX->getTextFace(TextXYStyle).size * RowHeightFromTextHeight * ThemeX->Scale);
|
||||
}
|
||||
} else {
|
||||
Height = ThemeX->TextHeight;
|
||||
@ -1442,7 +1442,7 @@ void REFIT_MENU_SCREEN::DrawMenuText(IN const XStringW& Text, IN INTN SelectedWi
|
||||
if (ThemeX->TypeSVG) {
|
||||
//clovy - text vertically centred on Height
|
||||
ThemeX->RenderText(Text, &TextBufferX, 0,
|
||||
(INTN)((ThemeX->TextHeight - (textFace[TextStyle].size * ThemeX->Scale)) / 2),
|
||||
(INTN)((ThemeX->TextHeight - (ThemeX->getTextFace(TextStyle).size * ThemeX->Scale)) / 2),
|
||||
Cursor, TextStyle);
|
||||
} else {
|
||||
ThemeX->RenderText(Text, &TextBufferX, TEXT_XMARGIN, TEXT_YMARGIN, Cursor, TextStyle);
|
||||
|
@ -53,110 +53,61 @@ extern void DumpFloat2 (CONST char* s, float* t, int N);
|
||||
extern UINTN NumFrames;
|
||||
extern UINTN FrameTime;
|
||||
|
||||
textFaces textFace[4]; //0-help 1-message 2-menu 3-test, far future it will be infinite list with id
|
||||
|
||||
EFI_STATUS XTheme::ParseSVGXIcon(INTN Id, const XString8& IconNameX, OUT XImage* Image, OUT void **SVGIcon)
|
||||
EFI_STATUS XTheme::ParseSVGXIcon(NSVGparser* SVGParser, INTN Id, const XString8& IconNameX, OUT XImage* Image)
|
||||
{
|
||||
EFI_STATUS Status = EFI_NOT_FOUND;
|
||||
NSVGimage *SVGimage;
|
||||
NSVGparser *p = (NSVGparser *)SVGParser;
|
||||
NSVGrasterizer* rast = nsvgCreateRasterizer();
|
||||
SVGimage = p->image; // full theme SVG image
|
||||
NSVGimage* SVGimage = SVGParser->image; // full theme SVG image
|
||||
NSVGshape *shape;
|
||||
NSVGgroup *group;
|
||||
NSVGimage *IconImage; // separate SVG image
|
||||
NSVGshape *shapeNext, *shapesTail = NULL, *shapePrev;
|
||||
NSVGshape *shapeNext/*, *shapesTail = NULL, *shapePrev*/;
|
||||
|
||||
|
||||
float IconImageWidth = 0; // Width of the image.
|
||||
float IconImageHeight = 0; // Height of the image.
|
||||
|
||||
NSVGparser* p2 = nsvg__createParser();
|
||||
IconImage = p2->image;
|
||||
IconImage->clip.count = 0;
|
||||
shape = SVGimage->shapes;
|
||||
shapePrev = NULL;
|
||||
|
||||
while (shape) {
|
||||
group = shape->group;
|
||||
shapeNext = shape->next;
|
||||
while (group) {
|
||||
if (strcmp(group->id, IconNameX.c_str()) == 0) {
|
||||
strncpy(IconImage->id, group->id, 63);
|
||||
break;
|
||||
}
|
||||
group = group->parent;
|
||||
}
|
||||
if (group) { //the shape is in the group
|
||||
// keep this sample for debug purpose
|
||||
/* DBG("found shape %s", shape->id);
|
||||
DBG(" from group %s\n", group->id);
|
||||
if ((Id == BUILTIN_SELECTION_BIG) ||
|
||||
(Id == BUILTIN_ICON_BACKGROUND) ||
|
||||
(Id == BUILTIN_ICON_BANNER)) {
|
||||
shape->debug = true;
|
||||
} */
|
||||
int prevCount = IconImage->clip.count;
|
||||
for (int i=0; i<shape->clip.count; i++) {
|
||||
IconImage->clip.index[prevCount+i] = shape->clip.index[i];
|
||||
IconImage->clip.count++;
|
||||
}
|
||||
|
||||
if ( isShapeInGroup(shape, IconNameX.c_str()) )
|
||||
{
|
||||
if (BootCampStyle && IconNameX.contains("selection_big")) {
|
||||
shape->opacity = 0.f;
|
||||
}
|
||||
if (XString8().takeValueFrom(shape->id).contains("BoundingRect")) {
|
||||
//there is bounds after nsvgParse()
|
||||
IconImage->width = shape->bounds[2] - shape->bounds[0];
|
||||
IconImage->height = shape->bounds[3] - shape->bounds[1];
|
||||
DBG("parsed bounds: %f, %f\n", IconImage->width, IconImage->height);
|
||||
if ( IconImage->height < 1.f ) {
|
||||
IconImage->height = 200.f;
|
||||
IconImageWidth = shape->bounds[2] - shape->bounds[0];
|
||||
IconImageHeight = shape->bounds[3] - shape->bounds[1];
|
||||
// DBG("parsed bounds: %f, %f\n", IconImage.width, IconImage.height);
|
||||
if ( IconImageHeight < 1.f ) {
|
||||
IconImageHeight = 200.f;
|
||||
}
|
||||
if (IconNameX.contains("selection_big") && (!SelectionOnTop)) {
|
||||
MainEntriesSize = (int)(IconImage->width * Scale); //xxx
|
||||
MainEntriesSize = (int)(IconImageWidth * Scale); //xxx
|
||||
row0TileSize = MainEntriesSize + (int)(16.f * Scale);
|
||||
// DBG("main entry size = %lld\n", MainEntriesSize);
|
||||
}
|
||||
if (IconNameX.contains("selection_small") && (!SelectionOnTop)) {
|
||||
row1TileSize = (int)(IconImage->width * Scale);
|
||||
row1TileSize = (int)(IconImageWidth * Scale);
|
||||
}
|
||||
|
||||
// not exclude BoundingRect from IconImage?
|
||||
shape->flags = 0; //invisible
|
||||
if (shapePrev) {
|
||||
shapePrev->next = shapeNext;
|
||||
}
|
||||
else {
|
||||
SVGimage->shapes = shapeNext;
|
||||
}
|
||||
shape = shapeNext;
|
||||
continue; //while(shape) it is BoundingRect shape
|
||||
}
|
||||
shape->flags = NSVG_VIS_VISIBLE;
|
||||
// Add to tail
|
||||
|
||||
if (IconImage->shapes == NULL)
|
||||
IconImage->shapes = shape;
|
||||
else
|
||||
shapesTail->next = shape;
|
||||
shapesTail = shape;
|
||||
if (shapePrev) {
|
||||
shapePrev->next = shapeNext;
|
||||
}
|
||||
else {
|
||||
SVGimage->shapes = shapeNext;
|
||||
}
|
||||
} //the shape in the group
|
||||
else {
|
||||
shapePrev = shape;
|
||||
}
|
||||
shape = shapeNext;
|
||||
shape = shapeNext;
|
||||
} //while shape
|
||||
shapesTail->next = NULL;
|
||||
|
||||
IconImage->clipPaths = SVGimage->clipPaths;
|
||||
|
||||
if ( IconImageWidth == 0 || IconImageHeight == 0 ) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
float bounds[4];
|
||||
nsvg__imageBounds(IconImage, bounds);
|
||||
CopyMem(IconImage->realBounds, bounds, 4 * sizeof(float));
|
||||
nsvg__imageBounds(SVGimage, bounds, IconNameX.c_str());
|
||||
|
||||
if ((Id == BUILTIN_ICON_BANNER) && IconNameX.contains("Banner")) {
|
||||
BannerPosX = (int)(bounds[0] * Scale - CentreShift);
|
||||
if (BannerPosX < 0) {
|
||||
@ -166,25 +117,16 @@ EFI_STATUS XTheme::ParseSVGXIcon(INTN Id, const XString8& IconNameX, OUT XImage*
|
||||
// DBG("Banner position at parse [%lld,%lld]\n", BannerPosX, BannerPosY);
|
||||
}
|
||||
|
||||
float Height = IconImage->height * Scale;
|
||||
float Width = IconImage->width * Scale;
|
||||
float Height = IconImageHeight * Scale;
|
||||
float Width = IconImageWidth * Scale;
|
||||
if (Height < 0 || Width < 0) {
|
||||
nsvgDeleteRasterizer(rast);
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
// DBG("icon %s width=%f height=%f\n", IconNameX.c_str(), Width, Height);
|
||||
int iWidth = ((int)(Width+0.5f) + 7) & ~0x07u;
|
||||
int iHeight = ((int)(Height+0.5f) + 7) & ~0x07u;
|
||||
|
||||
XImage NewImage(iWidth, iHeight); //empty
|
||||
if (IconImage->shapes == NULL) {
|
||||
*Image = NewImage;
|
||||
// DBG("return empty with status=%s\n", efiStrError(Status));
|
||||
nsvgDeleteRasterizer(rast);
|
||||
return Status;
|
||||
}
|
||||
IconImage->scale = Scale;
|
||||
// DBG("begin rasterize %s\n", IconNameX.c_str());
|
||||
|
||||
float tx = 0.f, ty = 0.f;
|
||||
if ((Id != BUILTIN_ICON_BACKGROUND) &&
|
||||
(Id != BUILTIN_ICON_ANIME) &&
|
||||
@ -196,17 +138,10 @@ EFI_STATUS XTheme::ParseSVGXIcon(INTN Id, const XString8& IconNameX, OUT XImage*
|
||||
ty = (Height - realHeight) * 0.5f;
|
||||
}
|
||||
|
||||
nsvgRasterize(rast, IconImage, tx, ty, Scale, Scale, (UINT8*)NewImage.GetPixelPtr(0,0), iWidth, iHeight, iWidth*4);
|
||||
// DBG("%s rastered, blt\n", IconImage);
|
||||
|
||||
NSVGrasterizer* rast = nsvgCreateRasterizer();
|
||||
nsvgRasterize(rast, SVGimage, bounds, IconNameX.c_str(), tx, ty, Scale, Scale, (UINT8*)NewImage.GetPixelPtr(0,0), iWidth, iHeight, iWidth*4);
|
||||
nsvgDeleteRasterizer(rast);
|
||||
// nsvg__deleteParser(p2);
|
||||
// nsvgDelete(p2->image); //somehow we can't delete them producing memory leaks
|
||||
// well, we will use them later
|
||||
*Image = NewImage; //copy array
|
||||
if (SVGIcon) {
|
||||
*SVGIcon = (void*)IconImage; //copy pointer into parser
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
@ -217,18 +152,27 @@ EFI_STATUS XTheme::ParseSVGXTheme(UINT8* buffer, UINTN Size)
|
||||
|
||||
Icons.setEmpty();
|
||||
|
||||
#if 1 && defined(NANOSVG_MEMORY_ALLOCATION_TRACE)
|
||||
displayFreeMemory("XTheme::ParseSVGXTheme begin"_XS8);
|
||||
|
||||
#if defined(JIEF_DEBUG) && defined(NANOSVG_MEMORY_ALLOCATION_TRACE)
|
||||
if ( nsvg__nbDanglingPtr() > 0 ) {
|
||||
DBG("There is already dangling ptr. nano svg memory leak test not done\n");
|
||||
}else{
|
||||
char* buffer2 = (char*)malloc(Size);
|
||||
memcpy(buffer2, buffer, Size);
|
||||
nvsg__memoryallocation_verbose = false;
|
||||
SVGParser = nsvgParse(buffer2, 72, 1.f); //the buffer will be modified, it is how nanosvg works // Jief : NEVER cast const to not const. Just change the parameter to not const !!! Nothing better to deceive.
|
||||
// nsvg__deleteParser(SVGParser);
|
||||
NSVGparser* p = nsvgParse(buffer2, 72, 1.f); //the buffer will be modified, it is how nanosvg works
|
||||
nsvg__deleteParser(p);
|
||||
if ( nsvg__nbDanglingPtr() > 0 ) {
|
||||
// nsvg__outputDanglingPtr();
|
||||
// nvsg__memoryallocation_verbose = true; // there leaks. Activate verbose
|
||||
nsvg__outputDanglingPtr();
|
||||
nvsg__memoryallocation_verbose = true;
|
||||
#if 1
|
||||
// Do it a second time, to display all allocations and to be able to step in with debugger
|
||||
memcpy(buffer2, buffer, Size);
|
||||
p = nsvgParse(buffer2, 72, 1.f); //the buffer will be modified, it is how nanosvg works
|
||||
nsvg__deleteParser(p);
|
||||
nsvg__outputDanglingPtr();
|
||||
#endif
|
||||
}else{
|
||||
nvsg__memoryallocation_verbose = false; // be sure that nvsg__memoryallocation_verbose is false, as it seems there is no memory leaks
|
||||
}
|
||||
@ -238,9 +182,9 @@ if ( nsvg__nbDanglingPtr() > 0 ) {
|
||||
#endif
|
||||
|
||||
// --- Parse theme.svg --- low case
|
||||
NSVGparser *mainParser = nsvgParse((CHAR8*)buffer, 72, 1.f); //the buffer will be modified, it is how nanosvg works
|
||||
SVGParser = mainParser; //store the pointer for future use
|
||||
NSVGimage *SVGimage = mainParser->image;
|
||||
NSVGparser* SVGParser = nsvgParse((CHAR8*)buffer, 72, 1.f); //the buffer will be modified, it is how nanosvg works// Jief : NEVER cast const to not const. Just change the parameter to not const !!! Nothing better to deceive.
|
||||
|
||||
NSVGimage *SVGimage = SVGParser->image;
|
||||
if (!SVGimage) {
|
||||
// DBG("Theme not parsed!\n");
|
||||
return EFI_NOT_STARTED;
|
||||
@ -249,16 +193,16 @@ if ( nsvg__nbDanglingPtr() > 0 ) {
|
||||
// --- Get scale as theme design height vs screen height
|
||||
|
||||
// must be svg view-box. This is Design Width and Heigth
|
||||
float vbx = mainParser->viewWidth;
|
||||
float vby = mainParser->viewHeight;
|
||||
DBG("Theme view-bounds: w=%f h=%f units=px\n", vbx, vby); //Theme view-bounds: w=1600.000000 h=900.000000 units=px
|
||||
float vbx = SVGParser->viewWidth;
|
||||
float vby = SVGParser->viewHeight;
|
||||
// DBG("Theme view-bounds: w=%f h=%f units=px\n", vbx, vby); //Theme view-bounds: w=1600.000000 h=900.000000 units=px
|
||||
if (vby > 1.0f) {
|
||||
SVGimage->height = vby;
|
||||
} else {
|
||||
SVGimage->height = 768.f; //default height
|
||||
}
|
||||
float ScaleF = UGAHeight / SVGimage->height;
|
||||
DBG("using scale %f\n", ScaleF); // using scale 0.666667
|
||||
// DBG("using scale %f\n", ScaleF); // using scale 0.666667
|
||||
Scale = ScaleF;
|
||||
CentreShift = (vbx * Scale - (float)UGAWidth) * 0.5f;
|
||||
|
||||
@ -267,25 +211,27 @@ if ( nsvg__nbDanglingPtr() > 0 ) {
|
||||
BigBack.setEmpty();
|
||||
}
|
||||
Status = EFI_NOT_FOUND;
|
||||
if (!ThemeX->Daylight) {
|
||||
Status = ParseSVGXIcon(BUILTIN_ICON_BACKGROUND, "Background_night"_XS8, &BigBack, NULL); //we should have a place for SVG background
|
||||
if (!Daylight) {
|
||||
Status = ParseSVGXIcon(SVGParser, BUILTIN_ICON_BACKGROUND, "Background_night"_XS8, &BigBack);
|
||||
}
|
||||
if (EFI_ERROR(Status)) {
|
||||
Status = ParseSVGXIcon(BUILTIN_ICON_BACKGROUND, "Background"_XS8, &BigBack, NULL);
|
||||
Status = ParseSVGXIcon(SVGParser, BUILTIN_ICON_BACKGROUND, "Background"_XS8, &BigBack);
|
||||
}
|
||||
DBG(" Background parsed [%lld, %lld]\n", BigBack.GetWidth(), BigBack.GetHeight()); //Background parsed [1067, 133]
|
||||
|
||||
// DBG(" Background parsed [%lld, %lld]\n", BigBack.GetWidth(), BigBack.GetHeight()); //Background parsed [1067, 133]
|
||||
// --- Make Banner
|
||||
Banner.setEmpty(); //for the case of theme switch
|
||||
Status = EFI_NOT_FOUND;
|
||||
if (!ThemeX->Daylight) {
|
||||
Status = ParseSVGXIcon(BUILTIN_ICON_BANNER, "Banner_night"_XS8, &Banner, NULL);
|
||||
if (!Daylight) {
|
||||
Status = ParseSVGXIcon(SVGParser, BUILTIN_ICON_BANNER, "Banner_night"_XS8, &Banner);
|
||||
}
|
||||
if (EFI_ERROR(Status)) {
|
||||
Status = ParseSVGXIcon(BUILTIN_ICON_BANNER, "Banner"_XS8, &Banner, NULL);
|
||||
Status = ParseSVGXIcon(SVGParser, BUILTIN_ICON_BANNER, "Banner"_XS8, &Banner);
|
||||
}
|
||||
// DBG("Banner parsed\n");
|
||||
BanHeight = (int)(Banner.GetHeight() * Scale + 1.f);
|
||||
DBG(" parsed banner->width=%lld height=%lld\n", Banner.GetWidth(), BanHeight); //parsed banner->width=467 height=89
|
||||
// DBG(" parsed banner->width=%lld height=%lld\n", Banner.GetWidth(), BanHeight); //parsed banner->width=467 height=89
|
||||
|
||||
|
||||
// --- Make other icons
|
||||
for (INTN i = BUILTIN_ICON_FUNC_ABOUT; i <= BUILTIN_CHECKBOX_CHECKED; ++i) {
|
||||
@ -293,12 +239,11 @@ if ( nsvg__nbDanglingPtr() > 0 ) {
|
||||
continue;
|
||||
}
|
||||
XIcon* NewIcon = new XIcon(i, false); //initialize without embedded
|
||||
Status = ParseSVGXIcon(i, NewIcon->Name, &NewIcon->Image, &NewIcon->ImageSVG);
|
||||
Status = ParseSVGXIcon(SVGParser, i, NewIcon->Name, &NewIcon->Image);
|
||||
// DBG("parse %s status %s\n", NewIcon->Name.c_str(), efiStrError(Status));
|
||||
NewIcon->Native = !EFI_ERROR(Status);
|
||||
if (!EFI_ERROR(Status)) {
|
||||
NewIcon->setFilled();
|
||||
ParseSVGXIcon(i, NewIcon->Name + "_night"_XS8, &NewIcon->ImageNight, &NewIcon->ImageSVGnight);
|
||||
ParseSVGXIcon(SVGParser, i, NewIcon->Name + "_night"_XS8, &NewIcon->ImageNight);
|
||||
}
|
||||
// DBG("parse night %s status %s\n", NewIcon->Name.c_str(), efiStrError(Status));
|
||||
Icons.AddReference(NewIcon, true);
|
||||
@ -316,19 +261,19 @@ if ( nsvg__nbDanglingPtr() > 0 ) {
|
||||
for (INTN i = ICON_OTHER_OS; i < IconsNamesSize; ++i) {
|
||||
if (AsciiStrLen(IconsNames[i]) == 0) break;
|
||||
XIcon* NewIcon = new XIcon(i, false); //initialize without embedded
|
||||
Status = ParseSVGXIcon(i, NewIcon->Name, &NewIcon->Image, &NewIcon->ImageSVG);
|
||||
Status = ParseSVGXIcon(SVGParser, i, NewIcon->Name, &NewIcon->Image);
|
||||
// DBG("parse %s i=%lld status %s\n", NewIcon->Name.c_str(), i, efiStrError(Status));
|
||||
NewIcon->Native = !EFI_ERROR(Status);
|
||||
if (!EFI_ERROR(Status)) {
|
||||
ParseSVGXIcon(i, NewIcon->Name + "_night"_XS8, &NewIcon->ImageNight, &NewIcon->ImageSVGnight);
|
||||
ParseSVGXIcon(SVGParser, i, NewIcon->Name + "_night"_XS8, &NewIcon->ImageNight);
|
||||
}
|
||||
Icons.AddReference(NewIcon, true);
|
||||
}
|
||||
//selection for bootcampstyle
|
||||
XIcon *NewIcon = new XIcon(BUILTIN_ICON_SELECTION);
|
||||
Status = ParseSVGXIcon(BUILTIN_ICON_SELECTION, "selection_indicator"_XS8, &NewIcon->Image, &NewIcon->ImageSVG);
|
||||
Status = ParseSVGXIcon(SVGParser, BUILTIN_ICON_SELECTION, "selection_indicator"_XS8, &NewIcon->Image);
|
||||
if (!EFI_ERROR(Status)) {
|
||||
Status = ParseSVGXIcon(BUILTIN_ICON_SELECTION, "selection_indicator_night"_XS8, &NewIcon->ImageNight, &NewIcon->ImageSVGnight);
|
||||
Status = ParseSVGXIcon(SVGParser, BUILTIN_ICON_SELECTION, "selection_indicator_night"_XS8, &NewIcon->ImageNight);
|
||||
}
|
||||
Icons.AddReference(NewIcon, true);
|
||||
|
||||
@ -346,82 +291,7 @@ if ( nsvg__nbDanglingPtr() > 0 ) {
|
||||
for (INTN i = BUILTIN_RADIO_BUTTON; i <= BUILTIN_CHECKBOX_CHECKED; ++i) {
|
||||
Buttons[i - BUILTIN_RADIO_BUTTON] = GetIcon(i).GetBest(!Daylight);
|
||||
}
|
||||
//for (int i=0 ; i<6 ; i+=2 ) {
|
||||
//SelectionImages[i].Draw(i*100, 0);
|
||||
//}
|
||||
|
||||
//TODO parse anime like for PNG themes
|
||||
/*
|
||||
Dict = GetProperty(DictPointer, "Anime");
|
||||
if (Dict != NULL) {
|
||||
INTN Count = Get_TagCount (Dict);
|
||||
for (INTN i = 0; i < Count; i++) {
|
||||
FILM *NewFilm = new FILM;
|
||||
if (EFI_ERROR(GetElement(Dict, i, &Dict3))) {
|
||||
continue;
|
||||
}
|
||||
if (Dict3 == NULL) {
|
||||
break;
|
||||
}
|
||||
Dict2 = GetProperty(Dict3, "ID");
|
||||
NewFilm->SetIndex((UINTN)GetPropertyInteger(Dict2, 1)); //default=main screen
|
||||
|
||||
Dict2 = GetProperty(Dict3, "Path");
|
||||
if (Dict2 != NULL && (Dict2->isString()) && Dict2->getString()->stringValue().notEmpty() ) {
|
||||
NewFilm->Path.takeValueFrom(Dict2->getString()->stringValue());
|
||||
}
|
||||
|
||||
Dict2 = GetProperty(Dict3, "Frames");
|
||||
NewFilm->NumFrames = (UINTN)GetPropertyInteger(Dict2, 0);
|
||||
|
||||
Dict2 = GetProperty(Dict3, "FrameTime");
|
||||
NewFilm->FrameTime = (UINTN)GetPropertyInteger(Dict2, 50); //default will be 50ms
|
||||
|
||||
Dict2 = GetProperty(Dict3, "ScreenEdgeX");
|
||||
if (Dict2 != NULL && (Dict2->isString()) && Dict2->getString()->stringValue().notEmpty() ) {
|
||||
if (Dict2->getString()->stringValue().isEqual("left")) {
|
||||
NewFilm->ScreenEdgeHorizontal = SCREEN_EDGE_LEFT;
|
||||
} else if (Dict2->getString()->stringValue().isEqual("right")) {
|
||||
NewFilm->ScreenEdgeHorizontal = SCREEN_EDGE_RIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
Dict2 = GetProperty(Dict3, "ScreenEdgeY");
|
||||
if (Dict2 != NULL && (Dict2->isString()) && Dict2->getString()->stringValue().notEmpty() ) {
|
||||
if (Dict2->getString()->stringValue().isEqual("top")) {
|
||||
NewFilm->ScreenEdgeVertical = SCREEN_EDGE_TOP;
|
||||
} else if (Dict2->getString()->stringValue().isEqual("bottom")) {
|
||||
NewFilm->ScreenEdgeVertical = SCREEN_EDGE_BOTTOM;
|
||||
}
|
||||
}
|
||||
|
||||
//default values are centre
|
||||
|
||||
Dict2 = GetProperty(Dict3, "DistanceFromScreenEdgeX%");
|
||||
NewFilm->FilmX = GetPropertyInteger(Dict2, INITVALUE);
|
||||
|
||||
Dict2 = GetProperty(Dict3, "DistanceFromScreenEdgeY%");
|
||||
NewFilm->FilmY = GetPropertyInteger(Dict2, INITVALUE);
|
||||
|
||||
Dict2 = GetProperty(Dict3, "NudgeX");
|
||||
NewFilm->NudgeX = GetPropertyInteger(Dict2, INITVALUE);
|
||||
|
||||
Dict2 = GetProperty(Dict3, "NudgeY");
|
||||
NewFilm->NudgeY = GetPropertyInteger(Dict2, INITVALUE);
|
||||
|
||||
Dict2 = GetProperty(Dict3, "Once");
|
||||
NewFilm->RunOnce = IsPropertyTrue(Dict2);
|
||||
|
||||
NewFilm->GetFrames(ThemeX); //used properties: ID, Path, NumFrames
|
||||
ThemeX->Cinema.AddFilm(NewFilm);
|
||||
// delete NewFilm; //looks like already deleted
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
// nsvgDeleteRasterizer(rast);
|
||||
|
||||
TypeSVG = true;
|
||||
ThemeDesignHeight = (int)SVGimage->height;
|
||||
ThemeDesignWidth = (int)SVGimage->width;
|
||||
@ -430,16 +300,30 @@ if ( nsvg__nbDanglingPtr() > 0 ) {
|
||||
row1TileSize = (INTN)(64.f * Scale);
|
||||
MainEntriesSize = (INTN)(128.f * Scale);
|
||||
}
|
||||
// DBG("parsing svg theme finished\n");
|
||||
// DBG("parsing svg theme finished\n");
|
||||
|
||||
// It looks like the fonts are self-contained. So we can just keep fontsDB pointer and copy textfaces and delete the parser.
|
||||
// I'm not sure if font are self contained with all theme. To avoid deleting, just comment out the next line.
|
||||
// SVGParser will still be deleted at XTheme dtor. So it's not a memory leak.
|
||||
fontsDB = SVGParser->fontsDB;
|
||||
for (size_t i = 0; i < sizeof(textFace)/sizeof(textFace[0]); i++) {
|
||||
textFace[i] = SVGParser->textFace[i];
|
||||
}
|
||||
SVGParser->fontsDB = NULL; // To avoid nsvg__deleteParser to delete it;
|
||||
nsvg__deleteParser(SVGParser); // comment out this line and the next to keep the parser memory, in case of doubt that font are dependent.
|
||||
SVGParser = NULL;
|
||||
|
||||
displayFreeMemory("XTheme::ParseSVGXTheme end"_XS8);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS XTheme::LoadSvgFrame(INTN i, OUT XImage* XFrame)
|
||||
// 2023-11 This is currently never called.
|
||||
EFI_STATUS XTheme::LoadSvgFrame(NSVGparser* SVGParser, INTN i, OUT XImage* XFrame)
|
||||
{
|
||||
EFI_STATUS Status = EFI_NOT_FOUND;
|
||||
XString8 XFrameName = S8Printf("frame_%04lld", i+1);
|
||||
Status = ParseSVGXIcon(BUILTIN_ICON_ANIME, XFrameName, XFrame, NULL); //svg anime will be full redesigned
|
||||
Status = ParseSVGXIcon(SVGParser, BUILTIN_ICON_ANIME, XFrameName, XFrame); //svg anime will be full redesigned
|
||||
if (EFI_ERROR(Status)) {
|
||||
DBG("frame '%s' not loaded, status=%s\n", XFrameName.c_str(), efiStrError(Status));
|
||||
}
|
||||
@ -453,28 +337,21 @@ EFI_STATUS XTheme::LoadSvgFrame(INTN i, OUT XImage* XFrame)
|
||||
//textType = 0-help 1-message 2-menu 3-test
|
||||
//return text width in pixels
|
||||
//it is not theme member!
|
||||
INTN renderSVGtext(XImage* TextBufferXY_ptr, INTN posX, INTN posY, INTN textType, const XStringW& string, UINTN Cursor)
|
||||
INTN renderSVGtext(XImage* TextBufferXY_ptr, INTN posX, INTN posY, const textFaces& textFace, const XStringW& string, UINTN Cursor)
|
||||
{
|
||||
XImage& TextBufferXY = *TextBufferXY_ptr;
|
||||
INTN Width;
|
||||
|
||||
NSVGparser* p;
|
||||
NSVGrasterizer* rast;
|
||||
if (!textFace[textType].valid) {
|
||||
for (decltype(textType) i=0; i<4; i++) {
|
||||
if (textFace[i].valid) {
|
||||
textType = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!textFace[textType].valid) {
|
||||
DBG("valid fontface not found!\n");
|
||||
|
||||
if (!textFace.valid) {
|
||||
DBG("invalid fontface!\n");
|
||||
return 0;
|
||||
}
|
||||
NSVGfont* fontSVG = textFace[textType].font;
|
||||
UINT32 color = textFace[textType].color;
|
||||
INTN Height = (INTN)(textFace[textType].size * ThemeX->Scale);
|
||||
NSVGfont* fontSVG = textFace.font;
|
||||
UINT32 color = textFace.color;
|
||||
INTN Height = (INTN)(textFace.size * ThemeX->Scale);
|
||||
float Scale, sy;
|
||||
float x, y;
|
||||
if (!fontSVG) {
|
||||
@ -533,11 +410,30 @@ INTN renderSVGtext(XImage* TextBufferXY_ptr, INTN posX, INTN posY, INTN textType
|
||||
float RealWidth = p->image->realBounds[2] - p->image->realBounds[0];
|
||||
|
||||
nsvgDeleteRasterizer(rast);
|
||||
// nsvg__deleteParser(p);
|
||||
nsvgDelete(p->image);
|
||||
nsvg__deleteParser(p); // this deletes p->text;
|
||||
// nsvgDelete(p->image);
|
||||
// TODO delete parser p and p->text?
|
||||
return (INTN)RealWidth; //x;
|
||||
}
|
||||
|
||||
|
||||
INTN renderSVGtext(XImage* TextBufferXY_ptr, INTN posX, INTN posY, INTN textType, const XStringW& string, UINTN Cursor)
|
||||
{
|
||||
if (!ThemeX->getTextFace(textType).valid) {
|
||||
for (decltype(textType) i=0; i<4; i++) {
|
||||
if (ThemeX->getTextFace(i).valid) {
|
||||
textType = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ThemeX->getTextFace(textType).valid) {
|
||||
DBG("valid fontface not found!\n");
|
||||
return 0;
|
||||
}
|
||||
return renderSVGtext(TextBufferXY_ptr, posX, posY, ThemeX->getTextFace(textType), string, Cursor);
|
||||
}
|
||||
|
||||
void testSVG()
|
||||
{
|
||||
do {
|
||||
@ -654,9 +550,11 @@ void testSVG()
|
||||
break;
|
||||
}
|
||||
|
||||
textFace[3].font = p->font;
|
||||
textFace[3].color = NSVG_RGBA(0x80, 0xFF, 0, 255);
|
||||
textFace[3].size = Height;
|
||||
textFaces textFace;
|
||||
textFace.font = p->currentFont;
|
||||
textFace.color = NSVG_RGBA(0x80, 0xFF, 0, 255);
|
||||
textFace.size = Height;
|
||||
textFace.valid = true;
|
||||
// DBG("font parsed family=%s\n", p->font->fontFamily);
|
||||
FreePool(FileData);
|
||||
// Scale = Height / fontSVG->unitsPerEm;
|
||||
|
@ -90,7 +90,7 @@ void FILM::AddFrame(XImage* Frame, INTN Index)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 2023-11 : this is currently never called when theme is svg
|
||||
void FILM::GetFrames(XTheme& TheTheme /*, const XStringW& Path*/) // Path already exist as a member. Is it the same ?
|
||||
{
|
||||
const EFI_FILE *ThemeDir = &TheTheme.getThemeDir();
|
||||
@ -99,16 +99,12 @@ void FILM::GetFrames(XTheme& TheTheme /*, const XStringW& Path*/) // Path alread
|
||||
for (INTN Index = 0; Index < NumFrames; Index++) {
|
||||
XImage NewImage;
|
||||
Status = EFI_NOT_FOUND;
|
||||
if (TheTheme.TypeSVG) {
|
||||
Status = TheTheme.LoadSvgFrame(Index, &NewImage);
|
||||
} else {
|
||||
XStringW Name = SWPrintf("%ls\\%ls_%03lld.png", Path.wc_str(), Path.wc_str(), Index);
|
||||
// DBG("try to load %ls\n", Name.wc_str()); //fine
|
||||
if (FileExists(ThemeDir, Name)) {
|
||||
Status = NewImage.LoadXImage(ThemeDir, Name);
|
||||
}
|
||||
// DBG(" read status=%s\n", efiStrError(Status));
|
||||
XStringW Name = SWPrintf("%ls\\%ls_%03lld.png", Path.wc_str(), Path.wc_str(), Index);
|
||||
// DBG("try to load %ls\n", Name.wc_str()); //fine
|
||||
if (FileExists(ThemeDir, Name)) {
|
||||
Status = NewImage.LoadXImage(ThemeDir, Name);
|
||||
}
|
||||
// DBG(" read status=%s\n", efiStrError(Status));
|
||||
if (!EFI_ERROR(Status)) {
|
||||
AddFrame(&NewImage, Index);
|
||||
}
|
||||
@ -116,3 +112,20 @@ void FILM::GetFrames(XTheme& TheTheme /*, const XStringW& Path*/) // Path alread
|
||||
}
|
||||
|
||||
|
||||
// 2023-11 : this is currently never called
|
||||
// This should be 2 implementations of the same method in 2 different subclass, I think.
|
||||
void FILM::GetFramesSVG(NSVGparser* SVGParser, XTheme& TheTheme /*, const XStringW& Path*/) // Path already exist as a member. Is it the same ?
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
LastIndex = 0;
|
||||
for (INTN Index = 0; Index < NumFrames; Index++) {
|
||||
XImage NewImage;
|
||||
Status = TheTheme.LoadSvgFrame(SVGParser, Index, &NewImage);
|
||||
if (!EFI_ERROR(Status)) {
|
||||
AddFrame(&NewImage, Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -15,6 +15,7 @@ extern "C" {
|
||||
#include "../cpp_foundation/XArray.h"
|
||||
#include "../cpp_foundation/XString.h"
|
||||
#include "../libeg/libeg.h"
|
||||
#include "../libeg/nanosvg.h"
|
||||
#include "XImage.h"
|
||||
|
||||
class XTheme;
|
||||
@ -64,6 +65,7 @@ public:
|
||||
INTN LastFrameID() { return LastIndex; }
|
||||
XBool Finished() { return CurrentFrame == 0; }
|
||||
void GetFrames(XTheme& TheTheme/*, const XStringW& Path*/); //read image sequence from Theme/Path/
|
||||
void GetFramesSVG(NSVGparser* SVGParser, XTheme& TheTheme);
|
||||
void SetPlace(const EG_RECT& Rect) { FilmPlace = Rect; }
|
||||
void Advance() { ++CurrentFrame %= (LastIndex + 1); }
|
||||
void Reset() { CurrentFrame = 0; }
|
||||
|
@ -102,19 +102,8 @@ ImageNight.FromPNG(ACCESS_EMB_DATA(dark), ACCESS_EMB_SIZE(dark)); \
|
||||
}
|
||||
|
||||
|
||||
XIcon::~XIcon()
|
||||
XIcon::XIcon(INTN Index, XBool TakeEmbedded) : Id(Index), Empty(false)
|
||||
{
|
||||
// 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]);
|
||||
}
|
||||
@ -123,20 +112,6 @@ XIcon::XIcon(INTN Index, XBool TakeEmbedded) : Id(Index), Name(), Image(), Image
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -246,7 +221,6 @@ 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;
|
||||
}
|
||||
|
||||
|
@ -5,33 +5,31 @@
|
||||
#include "../cpp_foundation/XString.h"
|
||||
#include "XImage.h"
|
||||
#include "libeg.h"
|
||||
#include "nanosvg.h"
|
||||
#include "../Platform/BootLog.h"
|
||||
#include "../Platform/Utils.h"
|
||||
|
||||
extern CONST CHAR8* IconsNames[];
|
||||
extern const INTN IconsNamesSize;
|
||||
|
||||
|
||||
class XIcon
|
||||
{
|
||||
public:
|
||||
INTN Id; //for example BUILTIN_ICON_POINTER
|
||||
XString8 Name; //for example "os_moja", "vol_internal"
|
||||
XImage Image;
|
||||
XImage ImageNight;
|
||||
XBool Native;
|
||||
void *ImageSVG; //NSVGimage*
|
||||
void *ImageSVGnight;
|
||||
INTN Id = 0; //for example BUILTIN_ICON_POINTER
|
||||
XString8 Name = XString8(); //for example "os_moja", "vol_internal"
|
||||
XImage Image = XImage();
|
||||
XImage ImageNight = XImage();
|
||||
XBool Native = false;
|
||||
protected:
|
||||
XBool Empty;
|
||||
XBool Empty = true;
|
||||
public:
|
||||
XIcon(): Id(0), Name(), Image(), ImageNight(), Native(false), ImageSVG(nullptr), ImageSVGnight(nullptr), Empty(true) {};
|
||||
XIcon() {};
|
||||
XIcon(INTN Id, XBool Embedded = false);
|
||||
// Initialisation of ImageSVG(other.ImageSVG), ImageSVGnight(other.ImageSVGnight) is wrong because we just copy the pointer
|
||||
XIcon(const XIcon& other) : Id(other.Id), Name(other.Name), Image(other.Image), ImageNight(other.ImageNight), Native(other.Native), ImageSVG(other.ImageSVG), ImageSVGnight(other.ImageSVGnight), Empty(other.Empty) {} ;
|
||||
~XIcon();
|
||||
|
||||
|
||||
XBool isEmpty() const { return Empty; }
|
||||
void setFilled() { Empty = false; }
|
||||
void setEmpty() { Empty = true; }
|
||||
XBool isEmpty() const { return Image.isEmpty() && ImageNight.isEmpty(); }
|
||||
void setEmpty() { Id = 0; Name.setEmpty(); Image.setEmpty(); ImageNight.setEmpty(); Native = false; }
|
||||
|
||||
EFI_STATUS LoadXImage(const EFI_FILE *Dir, const XStringW& FileName); //for example LoadImage(ThemeDir, L"icons\\" + Name);
|
||||
EFI_STATUS LoadXImage(const EFI_FILE *Dir, const wchar_t* LIconName);
|
||||
@ -40,7 +38,6 @@ public:
|
||||
|
||||
// Default are not valid, as usual. We delete them. If needed, proper ones can be created
|
||||
// Icon(const Icon&) = delete;
|
||||
XIcon& operator=(const XIcon&); // = delete;
|
||||
const XImage& GetBest(XBool night) const;
|
||||
};
|
||||
|
||||
|
@ -431,41 +431,41 @@ EFI_STATUS XImage::ToPNG(UINT8** Data, UINTN& OutSize)
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* fill XImage object by raster data described in SVG file
|
||||
* caller should create the object with Width and Height and calculate scale
|
||||
* scale = 1 correspond to fill the rect with the image
|
||||
* scale = 0.5 will reduce image
|
||||
* but this procedure is mostly for testing purpose. Real SVG theme can't be divided to separate SVG files
|
||||
*/
|
||||
EFI_STATUS XImage::FromSVG(const CHAR8 *SVGData, float scale)
|
||||
{
|
||||
NSVGimage *SVGimage;
|
||||
NSVGparser* p;
|
||||
|
||||
NSVGrasterizer* rast = nsvgCreateRasterizer();
|
||||
if (!rast) return EFI_UNSUPPORTED;
|
||||
//we have to copy input data because nanosvg wants to change it
|
||||
char *input = (__typeof__(input))AllocateCopyPool(AsciiStrSize(SVGData), SVGData);
|
||||
if (!input) return EFI_DEVICE_ERROR;
|
||||
|
||||
p = nsvgParse(input, 72, 1.f); //the parse will change input contents
|
||||
SVGimage = p->image;
|
||||
if (SVGimage) {
|
||||
float ScaleX = Width / SVGimage->width;
|
||||
float ScaleY = Height / SVGimage->height;
|
||||
float Scale = (ScaleX > ScaleY) ? ScaleY : ScaleX;
|
||||
Scale *= scale;
|
||||
|
||||
DBG("Test image width=%d heigth=%d\n", (int)(SVGimage->width), (int)(SVGimage->height));
|
||||
nsvgRasterize(rast, SVGimage, 0.f, 0.f, Scale, Scale, (UINT8*)&PixelData[0], (int)Width, (int)Height, (int)Width * sizeof(PixelData[0]));
|
||||
FreePool(SVGimage);
|
||||
}
|
||||
// nsvg__deleteParser(p); //can't delete raster until we make imageChain
|
||||
nsvgDeleteRasterizer(rast);
|
||||
FreePool(input);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
///*
|
||||
// * fill XImage object by raster data described in SVG file
|
||||
// * caller should create the object with Width and Height and calculate scale
|
||||
// * scale = 1 correspond to fill the rect with the image
|
||||
// * scale = 0.5 will reduce image
|
||||
// * but this procedure is mostly for testing purpose. Real SVG theme can't be divided to separate SVG files
|
||||
// */
|
||||
//EFI_STATUS XImage::FromSVG(const CHAR8 *SVGData, float scale)
|
||||
//{
|
||||
// NSVGimage *SVGimage;
|
||||
// NSVGparser* p;
|
||||
//
|
||||
// NSVGrasterizer* rast = nsvgCreateRasterizer();
|
||||
// if (!rast) return EFI_UNSUPPORTED;
|
||||
// //we have to copy input data because nanosvg wants to change it
|
||||
// char *input = (__typeof__(input))AllocateCopyPool(AsciiStrSize(SVGData), SVGData);
|
||||
// if (!input) return EFI_DEVICE_ERROR;
|
||||
//
|
||||
// p = nsvgParse(input, 72, 1.f); //the parse will change input contents
|
||||
// SVGimage = p->image;
|
||||
// if (SVGimage) {
|
||||
// float ScaleX = Width / SVGimage->width;
|
||||
// float ScaleY = Height / SVGimage->height;
|
||||
// float Scale = (ScaleX > ScaleY) ? ScaleY : ScaleX;
|
||||
// Scale *= scale;
|
||||
//
|
||||
// DBG("Test image width=%d heigth=%d\n", (int)(SVGimage->width), (int)(SVGimage->height));
|
||||
// nsvgRasterize(rast, SVGimage, 0.f, 0.f, Scale, Scale, (UINT8*)&PixelData[0], (int)Width, (int)Height, (int)Width * sizeof(PixelData[0]));
|
||||
// FreePool(SVGimage);
|
||||
// }
|
||||
//// nsvg__deleteParser(p); //can't delete raster until we make imageChain // not sure why, but this is npt used so far. FIX if back in use.
|
||||
// nsvgDeleteRasterizer(rast);
|
||||
// FreePool(input);
|
||||
// return EFI_SUCCESS;
|
||||
//}
|
||||
|
||||
// Screen operations
|
||||
/*
|
||||
@ -556,12 +556,12 @@ void XImage::DrawWithoutCompose(INTN x, INTN y, UINTN width, UINTN height) const
|
||||
}
|
||||
//output combined image
|
||||
if (GraphicsOutput != NULL) {
|
||||
GraphicsOutput->Blt(GraphicsOutput, PixelData.data(),
|
||||
GraphicsOutput->Blt(GraphicsOutput, (*this).GetPixelPtr(0, 0),
|
||||
EfiBltBufferToVideo,
|
||||
0, 0, x, y, AreaWidth, AreaHeight, GetWidth()*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
||||
}
|
||||
else if (UgaDraw != NULL) {
|
||||
UgaDraw->Blt(UgaDraw, (EFI_UGA_PIXEL *)GetPixelPtr(0, 0), EfiUgaBltBufferToVideo,
|
||||
UgaDraw->Blt(UgaDraw, (EFI_UGA_PIXEL *)(*this).GetPixelPtr(0, 0), EfiUgaBltBufferToVideo,
|
||||
0, 0, x, y, AreaWidth, AreaHeight, GetWidth()*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
||||
}
|
||||
}
|
||||
|
@ -32,12 +32,13 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
XTheme* ThemeX = NULL;
|
||||
textFaces nullTextFaces;
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
InitTheme(const CHAR8* ChosenTheme)
|
||||
{
|
||||
EFI_STATUS Status = EFI_NOT_FOUND;
|
||||
EFI_STATUS Status = EFI_NOT_FOUND;
|
||||
UINTN i;
|
||||
TagDict* ThemeDict = NULL;
|
||||
// CHAR8 *ChosenTheme = NULL;
|
||||
@ -46,6 +47,9 @@ InitTheme(const CHAR8* ChosenTheme)
|
||||
|
||||
gRT->GetTime(&Now, NULL);
|
||||
DbgHeader("InitXTheme");
|
||||
|
||||
if ( ThemeX != NULL ) delete ThemeX;
|
||||
ThemeX = new XTheme();
|
||||
ThemeX->Init();
|
||||
|
||||
//initialize Daylight when we know timezone
|
||||
@ -64,33 +68,6 @@ InitTheme(const CHAR8* ChosenTheme)
|
||||
DBG("use night theme\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
// DBG("validate %d face\n", i);
|
||||
textFace[i].valid = false;
|
||||
}
|
||||
|
||||
NSVGfontChain *fontChain = fontsDB;
|
||||
while (fontChain) {
|
||||
NSVGfont *font = fontChain->font;
|
||||
// DBG("free font %s\n", font->fontFamily);
|
||||
NSVGfontChain *nextChain = fontChain->next;
|
||||
if (font) {
|
||||
nsvg__deleteFont(font);
|
||||
fontChain->font = NULL;
|
||||
}
|
||||
FreePool(fontChain);
|
||||
fontChain = nextChain;
|
||||
}
|
||||
//as all font freed then free the chain
|
||||
fontsDB = NULL;
|
||||
|
||||
/*
|
||||
if (mainParser) {
|
||||
nsvg__deleteParser(mainParser);
|
||||
DBG("parser deleted\n");
|
||||
mainParser = NULL;
|
||||
}
|
||||
*/
|
||||
ThemeX->FontImage.setEmpty();
|
||||
|
||||
Rnd = (ThemeNameArray.size() != 0) ? Now.Second % ThemeNameArray.size() : 0;
|
||||
@ -183,11 +160,10 @@ finish:
|
||||
ThemeX->FillByEmbedded();
|
||||
OldChosenTheme = 0xFFFF;
|
||||
|
||||
ThemeX->closeThemeDir();
|
||||
// if (ThemeX->ThemeDir != NULL) {
|
||||
// ThemeX->ThemeDir->Close(ThemeX->ThemeDir);
|
||||
// ThemeX->ThemeDir = NULL;
|
||||
// }
|
||||
if (ThemeX->ThemeDir != NULL) {
|
||||
ThemeX->ThemeDir->Close(ThemeX->ThemeDir);
|
||||
ThemeX->ThemeDir = NULL;
|
||||
}
|
||||
|
||||
// ThemeX->GetThemeTagSettings(NULL); already done
|
||||
//fill some fields
|
||||
@ -233,8 +209,9 @@ finish:
|
||||
if (!ThemeX->TypeSVG) {
|
||||
ThemeX->PrepareFont();
|
||||
}
|
||||
|
||||
//ThemeX->ClearScreen();
|
||||
|
||||
displayFreeMemory("InitTheme end"_XS8);
|
||||
return Status;
|
||||
}
|
||||
|
||||
@ -253,14 +230,11 @@ XTheme::XTheme() : Icons(), ThemeDir(0), HideBadges(0), HideUIFlags(0), Font(FON
|
||||
row0TileSize(0), row1TileSize(0), BanHeight(0), LayoutHeight(0), LayoutBannerOffset(0), LayoutButtonOffset(0), LayoutTextOffset(0),
|
||||
LayoutAnimMoveForMenuX(0), ScrollWidth(0), ScrollButtonsHeight(0), ScrollBarDecorationsHeight(0), ScrollScrollDecorationsHeight(0),
|
||||
FontWidth(0), FontHeight(0), TextHeight(0), Daylight(false), Background(), BigBack(), Banner(), SelectionImages(), Buttons(), ScrollbarBackgroundImage(), BarStartImage(), BarEndImage(),
|
||||
ScrollbarImage(), ScrollStartImage(), ScrollEndImage(), UpButtonImage(), DownButtonImage(), FontImage(), BannerPlace(), Cinema(), SVGParser(0)
|
||||
ScrollbarImage(), ScrollStartImage(), ScrollEndImage(), UpButtonImage(), DownButtonImage(), FontImage(), BannerPlace(), Cinema()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
XTheme::~XTheme() {
|
||||
//nothing todo?
|
||||
}
|
||||
|
||||
void XTheme::Init()
|
||||
{
|
||||
@ -735,7 +709,7 @@ XTheme::GetThemeTagSettings(const TagDict* DictPointer)
|
||||
NewFilm->RunOnce = IsPropertyNotNullAndTrue(Prop);
|
||||
|
||||
NewFilm->GetFrames(*ThemeX); //used properties: ID, Path, NumFrames
|
||||
ThemeX->Cinema.AddFilm(NewFilm);
|
||||
Cinema.AddFilm(NewFilm);
|
||||
// delete NewFilm; //looks like already deleted
|
||||
}
|
||||
}
|
||||
@ -839,7 +813,6 @@ XIcon& XTheme::GetIconAlt(INTN Id, INTN Alt) //if not found then take embedded
|
||||
// using Alt icon
|
||||
Icons[IdFound].Image = Icons[AltFound].Image;
|
||||
Icons[IdFound].ImageNight = Icons[AltFound].ImageNight;
|
||||
Icons[IdFound].setFilled();
|
||||
} else {
|
||||
// check for embedded with ID=Id
|
||||
XIcon *NewIcon = new XIcon(Id, true);
|
||||
@ -851,7 +824,6 @@ XIcon& XTheme::GetIconAlt(INTN Id, INTN Alt) //if not found then take embedded
|
||||
// using Embedded icon
|
||||
Icons[IdFound].Image = NewIcon->Image;
|
||||
Icons[IdFound].ImageNight = NewIcon->ImageNight;
|
||||
Icons[IdFound].setFilled();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -918,7 +890,6 @@ const XIcon& XTheme::LoadOSIcon(const XString8& Full)
|
||||
// else something
|
||||
if (DummyIcon.isEmpty()) { //initialize once per session
|
||||
DummyIcon.Image.DummyImage(MainEntriesSize);
|
||||
DummyIcon.setFilled();
|
||||
}
|
||||
}
|
||||
return DummyIcon;
|
||||
@ -1115,7 +1086,6 @@ void XTheme::FillByDir() //assume ThemeDir is defined by InitTheme() procedure
|
||||
}
|
||||
NewIcon->Native = !EFI_ERROR(Status);
|
||||
if (!EFI_ERROR(Status)) {
|
||||
NewIcon->setFilled();
|
||||
NewIcon->ImageNight.LoadXImage(ThemeDir, SWPrintf("%s_night", IconsNames[i]));
|
||||
}
|
||||
Icons.AddReference(NewIcon, true);
|
||||
|
@ -22,43 +22,15 @@ class TagStruct;
|
||||
|
||||
EFI_STATUS InitTheme (const CHAR8* ChosenTheme);
|
||||
|
||||
extern textFaces nullTextFaces;
|
||||
|
||||
class XTheme
|
||||
{
|
||||
public:
|
||||
XObjArray<XIcon> Icons;
|
||||
protected:
|
||||
XStringW m_ThemePath = NullXStringW;
|
||||
EFI_FILE *ThemeDir;
|
||||
EFI_FILE *ThemeDir = 0;
|
||||
|
||||
public:
|
||||
void openThemeDir() {
|
||||
if ( ThemeDir != NULL ) ThemeDir->Close(ThemeDir);
|
||||
/*Status = */self.getCloverDir().Open(&self.getCloverDir(), &ThemeDir, m_ThemePath.wc_str(), EFI_FILE_MODE_READ, 0);
|
||||
}
|
||||
void closeThemeDir() {
|
||||
if ( ThemeDir != NULL ) ThemeDir->Close(ThemeDir);
|
||||
ThemeDir = NULL;
|
||||
}
|
||||
// const XStringW& getThemePath() { return m_ThemePath; }
|
||||
// void setThemePath(const XStringW& aThemePath) {
|
||||
// m_ThemePath = aThemePath;
|
||||
// closeThemeDir();
|
||||
// openThemeDir();
|
||||
// }
|
||||
const EFI_FILE& getThemeDir() {
|
||||
return *ThemeDir;
|
||||
}
|
||||
XBool IsEmbeddedTheme(void)
|
||||
{
|
||||
if (embedded) {
|
||||
ThemeDir = NULL;
|
||||
}
|
||||
return ThemeDir == NULL;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
// UINTN DisableFlags;
|
||||
UINTN HideBadges;
|
||||
UINTN HideUIFlags;
|
||||
@ -146,20 +118,36 @@ public:
|
||||
|
||||
XCinema Cinema;
|
||||
|
||||
NSVGparser* SVGParser;
|
||||
public:
|
||||
NSVGfontChain* fontsDB = 0;
|
||||
textFaces textFace[4]; //0-help 1-message 2-menu 3-test, far future it will be infinite list with id // in VectorGraphics, I use sizeof(textFace)/sizeof(textFace[0]. So if you change that to a pointer, it'll break.
|
||||
|
||||
|
||||
void Init();
|
||||
XTheme(); //default constructor
|
||||
XTheme(const XTheme&) = delete;
|
||||
XTheme& operator=(const XTheme&) = delete;
|
||||
|
||||
~XTheme();
|
||||
~XTheme() {
|
||||
if ( ThemeDir != NULL ) ThemeDir->Close(ThemeDir);
|
||||
if ( fontsDB ) {
|
||||
nsvg__deleteFontChain(fontsDB);
|
||||
}
|
||||
for (size_t i=0 ; i < Icons.length() ; ++i ) {
|
||||
Icons[i].setEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const EFI_FILE& getThemeDir() const { return *ThemeDir; }
|
||||
XBool IsEmbeddedTheme(void) const { return embedded; }
|
||||
|
||||
|
||||
//fill the theme
|
||||
// const XImage& GetIcon(const char* Name);
|
||||
// const XImage& GetIcon(const CHAR16* Name);
|
||||
const XIcon& GetIcon(const XString8& Name); //get by name
|
||||
XIcon* GetIconP(const XString8& Name);
|
||||
const XIcon& GetIcon(INTN Id); //get by id
|
||||
XIcon& GetIconAlt(INTN Id, INTN Alt); //if id not found
|
||||
const XIcon& LoadOSIcon(const CHAR16* OSIconName); //TODO make XString provider
|
||||
@ -184,9 +172,14 @@ public:
|
||||
EFI_STATUS GetThemeTagSettings(const TagDict* DictPointer);
|
||||
void parseTheme(void* p, char** dict); //in nano project
|
||||
EFI_STATUS ParseSVGXTheme(UINT8* buffer, UINTN Size); // in VectorTheme
|
||||
EFI_STATUS ParseSVGXIcon(INTN Id, const XString8& IconNameX, XImage* Image, void **SVGIcon);
|
||||
EFI_STATUS ParseSVGXIcon(NSVGparser* SVGParser, INTN Id, const XString8& IconNameX, XImage* Image);
|
||||
TagDict* LoadTheme(const XStringW& TestTheme); //return TagStruct* why?
|
||||
EFI_STATUS LoadSvgFrame(INTN i, OUT XImage* XFrame); // for animation
|
||||
EFI_STATUS LoadSvgFrame(NSVGparser* SVGParser, INTN i, OUT XImage* XFrame); // for animation
|
||||
|
||||
const textFaces& getTextFace(size_t idx) {
|
||||
if (!TypeSVG ) return nullTextFaces;
|
||||
return textFace[idx];
|
||||
}
|
||||
|
||||
//screen operations
|
||||
void ClearScreen();
|
||||
|
@ -667,29 +667,38 @@ static void nsvg__deletePaths(NSVGpath* path)
|
||||
}
|
||||
}
|
||||
|
||||
static void nsvg__deleteGlyphs(NSVGglyph* glyphs)
|
||||
{
|
||||
while (glyphs) {
|
||||
NSVGglyph *next = glyphs->next;
|
||||
nsvg__deletePaths(glyphs->path);
|
||||
nsvg__delete(glyphs, "nsvg__deleteGlyphs"_XS8);
|
||||
glyphs = next;
|
||||
}
|
||||
}
|
||||
|
||||
void nsvg__deleteFont(NSVGfont* font)
|
||||
{
|
||||
NSVGglyph *glyphs, *next;
|
||||
if (!font) {
|
||||
return;
|
||||
}
|
||||
if (font->missingGlyph) {
|
||||
// DBG("missing glyph=%s\n", font->missingGlyph->name);
|
||||
nsvg__deletePaths(font->missingGlyph->path);
|
||||
nsvg__delete(font->missingGlyph, "nsvg__deleteFont"_XS8);
|
||||
font->missingGlyph = NULL;
|
||||
}
|
||||
glyphs = font->glyphs;
|
||||
while (glyphs) {
|
||||
// DBG(" glyph=%s\n", glyphs->name);
|
||||
next = glyphs->next;
|
||||
nsvg__deletePaths(glyphs->path);
|
||||
nsvg__delete(glyphs, "nsvg__deleteFont"_XS8);
|
||||
glyphs = next;
|
||||
}
|
||||
//DBG("nsvg__deleteFont %s %llx\n", font->id, uintptr_t(font));
|
||||
nsvg__deleteGlyphs(font->glyphs);
|
||||
nsvg__deleteGlyphs(font->missingGlyph);
|
||||
nsvg__delete(font, "nsvg__deleteFont"_XS8);
|
||||
}
|
||||
|
||||
void nsvg__deleteFontChain(NSVGfontChain *fontChain)
|
||||
{
|
||||
while (fontChain) {
|
||||
NSVGfont* font = fontChain->font;
|
||||
NSVGfontChain *nextChain = fontChain->next;
|
||||
nsvg__deleteFont(font);
|
||||
nsvg__delete(fontChain, "nsvg__deleteParser1"_XS8);
|
||||
fontChain = nextChain;
|
||||
}
|
||||
}
|
||||
|
||||
static void nsvg__deletePaint(NSVGpaint* paint)
|
||||
{
|
||||
if (!paint || !paint->paint.gradient) {
|
||||
@ -729,33 +738,41 @@ static void nsvg__deleteSymbols(NSVGsymbol* symbol)
|
||||
}
|
||||
}
|
||||
|
||||
static void nsvg__popAttr(NSVGparser* p);
|
||||
static NSVGattrib* nsvg__getAttr(NSVGparser* p);
|
||||
|
||||
void nsvg__deleteParser(NSVGparser* p)
|
||||
{
|
||||
int i;
|
||||
if (p != NULL) {
|
||||
nsvg__deleteStyles(p->styles);
|
||||
nsvg__deleteSymbols(p->symbols);
|
||||
nsvg__deletePaths(p->pathList);
|
||||
nsvg__deleteGradientData(p->gradients);
|
||||
// do not delete font here, as we free all fonts later by following fontsdb
|
||||
|
||||
nsvg__deleteFontChain(p->fontsDB);
|
||||
nsvgDelete(p->image);
|
||||
if (p->cpts > 0 && p->pts) {
|
||||
nsvg__delete(p->pts, "nsvg__deleteParser"_XS8);
|
||||
nsvg__delete(p->pts, "nsvg__deleteParser2"_XS8);
|
||||
}
|
||||
for (i=0; i<NSVG_MAX_ATTR; i++) {
|
||||
NSVGattrib* attr = &(p->attr[i]);
|
||||
|
||||
auto text = p->text;
|
||||
while ( text ) {
|
||||
nsvg__delete(text, "nsvg__deleteParser3"_XS8);
|
||||
text = text->next;
|
||||
}
|
||||
|
||||
while ( p->attrHead > 0 ) {
|
||||
NSVGattrib* attr = nsvg__getAttr(p);
|
||||
if (attr && attr->fontFace) {
|
||||
nsvg__delete(attr->fontFace, "nsvg__deleteParser2"_XS8);
|
||||
nsvg__delete(attr->fontFace, "nsvg__deleteParser3"_XS8);
|
||||
attr->fontFace = NULL;
|
||||
}
|
||||
while (attr->group) {
|
||||
NSVGgroup* group = attr->group->parent;
|
||||
nsvg__delete(attr->group, "nsvg__deleteParser3"_XS8);
|
||||
attr->group = group;
|
||||
if ( attr->group ) {
|
||||
nsvg__delete(attr->group, "nsvg__deleteParser4"_XS8);
|
||||
}
|
||||
nsvg__popAttr(p);
|
||||
}
|
||||
nsvg__delete(p, "nsvg__deleteParser4"_XS8);
|
||||
|
||||
nsvg__delete(p, "nsvg__deleteParser5"_XS8);
|
||||
}
|
||||
}
|
||||
|
||||
@ -843,8 +860,13 @@ static void nsvg__pushAttr(NSVGparser* p)
|
||||
|
||||
static void nsvg__popAttr(NSVGparser* p)
|
||||
{
|
||||
if (p->attrHead > 0)
|
||||
if (p->attrHead > 0) {
|
||||
auto attr = nsvg__getAttr(p);
|
||||
if ( attr->fontFace ) {
|
||||
nsvg__delete(attr->fontFace, "nsvg__popAttr"_XS8);
|
||||
}
|
||||
p->attrHead--;
|
||||
}
|
||||
}
|
||||
|
||||
static float nsvg__actualOrigX(NSVGparser* p)
|
||||
@ -3080,7 +3102,7 @@ static void nsvg__parseText(NSVGparser* p, char** dict)
|
||||
// DBG("required font %s required style=%c\n", text->fontFace->fontFamily, text->fontStyle);
|
||||
//if the font is not registered then we have to load new one
|
||||
NSVGfont *fontSVG = NULL;
|
||||
NSVGfontChain *fontChain = fontsDB;
|
||||
NSVGfontChain *fontChain = p->fontsDB;
|
||||
NSVGfontChain *fontChainSimilar = NULL;
|
||||
while (fontChain) {
|
||||
fontSVG = fontChain->font;
|
||||
@ -3117,14 +3139,21 @@ static void nsvg__parseText(NSVGparser* p, char** dict)
|
||||
if (!p1) {
|
||||
// DBG("font %s not parsed\n", text->fontFace->fontFamily);
|
||||
} else {
|
||||
fontSVG = fontsDB->font; //last added during parse file data
|
||||
// Jief : this is only taking the first font from the file. It would not be hard to take the whole p1->fontsDB and to link it on p->fontsDB
|
||||
NSVGfontChain* fc = p1->fontsDB;
|
||||
p1->fontsDB = p1->fontsDB->next;
|
||||
fc->next = p->fontsDB;
|
||||
p->fontsDB = fc;
|
||||
|
||||
fontSVG = p->fontsDB->font; //last added during parse file data
|
||||
text->font = fontSVG;
|
||||
nsvg__deleteParser(p1);
|
||||
}
|
||||
FreePool(FileData); //after load // don not use nsvg__delete because it's not allocated by nsvg__alloc...
|
||||
FileData = NULL;
|
||||
} else {
|
||||
// DBG("set embedded font\n");
|
||||
text->font = p->font; //else embedded if present which is also double fontChain
|
||||
text->font = p->currentFont; //else embedded if present which is also double fontChain
|
||||
}
|
||||
} else {
|
||||
// DBG("set found font %s\n", fontSVG->fontFamily);
|
||||
@ -3136,58 +3165,58 @@ static void nsvg__parseText(NSVGparser* p, char** dict)
|
||||
NSVGgroup* group = attr->group;
|
||||
while (group) {
|
||||
if (strcmp(group->id, "MessageRow") == 0) {
|
||||
if (!textFace[1].valid) {
|
||||
if (!p->textFace[1].valid) {
|
||||
//here we want to set text->font as p->font if text->groupID == MessageRow
|
||||
p->font = fontSVG;
|
||||
p->currentFont = fontSVG;
|
||||
p->fontSize = text->fontSize;
|
||||
p->fontColor = text->fontColor;
|
||||
textFace[1].font = fontSVG;
|
||||
textFace[1].size = (INTN)text->fontSize;
|
||||
textFace[1].color = text->fontColor;
|
||||
textFace[1].valid = true;
|
||||
p->textFace[1].font = fontSVG;
|
||||
p->textFace[1].size = (INTN)text->fontSize;
|
||||
p->textFace[1].color = text->fontColor;
|
||||
p->textFace[1].valid = true;
|
||||
// DBG("set message->font=%s color=%X size=%f as in MessageRow\n", fontSVG->fontFamily, text->fontColor, text->fontSize);
|
||||
}
|
||||
break;
|
||||
} else if (!ThemeX->Daylight && strcmp(group->id, "MessageRow_night") == 0) {
|
||||
//replace ThemeX->Daylight settings
|
||||
p->font = fontSVG;
|
||||
p->currentFont = fontSVG;
|
||||
p->fontSize = text->fontSize;
|
||||
p->fontColor = text->fontColor;
|
||||
textFace[1].font = fontSVG;
|
||||
textFace[1].size = (INTN)text->fontSize;
|
||||
textFace[1].color = text->fontColor;
|
||||
textFace[1].valid = true;
|
||||
p->textFace[1].font = fontSVG;
|
||||
p->textFace[1].size = (INTN)text->fontSize;
|
||||
p->textFace[1].color = text->fontColor;
|
||||
p->textFace[1].valid = true;
|
||||
// DBG("set message_night->font=%s color=%X size=%f as in MessageRow\n", fontSVG->fontFamily, text->fontColor, text->fontSize);
|
||||
break;
|
||||
} else if (strcmp(group->id, "MenuRows") == 0) {
|
||||
if (!textFace[2].valid) {
|
||||
textFace[2].font = fontSVG;
|
||||
textFace[2].size = (INTN)text->fontSize;
|
||||
textFace[2].color = text->fontColor;
|
||||
textFace[2].valid = true;
|
||||
if (!p->textFace[2].valid) {
|
||||
p->textFace[2].font = fontSVG;
|
||||
p->textFace[2].size = (INTN)text->fontSize;
|
||||
p->textFace[2].color = text->fontColor;
|
||||
p->textFace[2].valid = true;
|
||||
// DBG("set menu->font=%s color=%X size=%f as in MenuRows\n", fontSVG->fontFamily, text->fontColor, text->fontSize);
|
||||
}
|
||||
break;
|
||||
} else if (!ThemeX->Daylight && strcmp(group->id, "MenuRows_night") == 0) {
|
||||
textFace[2].font = fontSVG;
|
||||
textFace[2].size = (INTN)text->fontSize;
|
||||
textFace[2].color = text->fontColor;
|
||||
textFace[2].valid = true;
|
||||
p->textFace[2].font = fontSVG;
|
||||
p->textFace[2].size = (INTN)text->fontSize;
|
||||
p->textFace[2].color = text->fontColor;
|
||||
p->textFace[2].valid = true;
|
||||
break;
|
||||
} else if (strcmp(group->id, "HelpRows") == 0) {
|
||||
if (!textFace[0].valid) {
|
||||
textFace[0].font = fontSVG;
|
||||
textFace[0].size = (INTN)text->fontSize;
|
||||
textFace[0].color = text->fontColor;
|
||||
textFace[0].valid = true;
|
||||
if (!p->textFace[0].valid) {
|
||||
p->textFace[0].font = fontSVG;
|
||||
p->textFace[0].size = (INTN)text->fontSize;
|
||||
p->textFace[0].color = text->fontColor;
|
||||
p->textFace[0].valid = true;
|
||||
// DBG("set help->font=%s color=%X size=%f as in HelpRows\n", fontSVG->fontFamily, text->fontColor, text->fontSize);
|
||||
}
|
||||
break;
|
||||
} else if (!ThemeX->Daylight && strstr(group->id, "HelpRows_night") != NULL) {
|
||||
textFace[0].font = fontSVG;
|
||||
textFace[0].size = (INTN)text->fontSize;
|
||||
textFace[0].color = text->fontColor;
|
||||
textFace[0].valid = true;
|
||||
p->textFace[0].font = fontSVG;
|
||||
p->textFace[0].size = (INTN)text->fontSize;
|
||||
p->textFace[0].color = text->fontColor;
|
||||
p->textFace[0].valid = true;
|
||||
// DBG("set help_night->font=%s color=%X size=%f as in HelpRows\n", fontSVG->fontFamily, text->fontColor, text->fontSize);
|
||||
break;
|
||||
}
|
||||
@ -3673,6 +3702,8 @@ static void nsvg__parseGroup(NSVGparser* p, char** dict)
|
||||
}
|
||||
// DBG("parse group\n");
|
||||
NSVGgroup* group = (NSVGgroup*)nsvg__alloczero(sizeof(NSVGgroup), "nsvg__parseGroup"_XS8);
|
||||
group->next = p->image->groups;
|
||||
p->image->groups = group;
|
||||
|
||||
// if (curAttr->id[0] == '\0') //skip anonymous groups
|
||||
// return;
|
||||
@ -3812,10 +3843,10 @@ static void nsvg__parseFont(NSVGparser* p, char** dict)
|
||||
|
||||
NSVGfontChain* fontChain = (decltype(fontChain))nsvg__alloc(sizeof(*fontChain), "nsvg__parseFont fontChain"_XS8);
|
||||
fontChain->font = font;
|
||||
fontChain->next = fontsDB;
|
||||
p->font = font;
|
||||
fontChain->next = p->fontsDB;
|
||||
p->currentFont = font;
|
||||
|
||||
fontsDB = fontChain;
|
||||
p->fontsDB = fontChain;
|
||||
}
|
||||
|
||||
static void nsvg__parseFontFace(NSVGparser* p, char** dict)
|
||||
@ -3825,7 +3856,7 @@ static void nsvg__parseFontFace(NSVGparser* p, char** dict)
|
||||
// DBG("no parser\n");
|
||||
return;
|
||||
}
|
||||
NSVGfont* font = p->font; //if present??? assumed good svg structure
|
||||
NSVGfont* font = p->currentFont; //if present??? assumed good svg structure
|
||||
if (!font) {
|
||||
return;
|
||||
}
|
||||
@ -3982,6 +4013,7 @@ static void nsvg__parseGlyph(NSVGparser* p, char** dict, XBool missing)
|
||||
} else if (strcmp(dict[i], "glyph-name") == 0) {
|
||||
strncpy(glyph->name, dict[i+1], 16);
|
||||
glyph->name[15] = '\0';
|
||||
//DBG("nsvg__parseGlyph name=%s\n", glyph->name);
|
||||
if (strcmp(dict[i+1], "nonmarkingreturn") == 0) {
|
||||
glyph->unicode = L'\n';
|
||||
} else if (strcmp(dict[i+1], ".notdef") == 0) {
|
||||
@ -3993,24 +4025,28 @@ static void nsvg__parseGlyph(NSVGparser* p, char** dict, XBool missing)
|
||||
nsvg__parsePath(p, dict);
|
||||
|
||||
glyph->path = p->pathList;
|
||||
p->pathList = 0; //lastPath;
|
||||
p->pathList = 0;
|
||||
|
||||
if (p->font) {
|
||||
if (p->currentFont) {
|
||||
//DBG("nsvg__parseGlyph name=%s missign=%d currentfont=%s\n", glyph->name, (bool)missing, p->currentFont->id);
|
||||
if (missing) {
|
||||
p->font->missingGlyph = glyph;
|
||||
if (!glyph->horizAdvX && p->font->horizAdvX) {
|
||||
p->font->missingGlyph->horizAdvX = p->font->horizAdvX;
|
||||
//Jief : Having more than one missing glyph happen at least with cesium theme.
|
||||
// That's why I add them in the chain instead of just reassign p->currentFont->missingGlyph
|
||||
glyph->next = p->currentFont->missingGlyph;
|
||||
p->currentFont->missingGlyph = glyph;
|
||||
if (!glyph->horizAdvX && p->currentFont->horizAdvX) {
|
||||
p->currentFont->missingGlyph->horizAdvX = p->currentFont->horizAdvX;
|
||||
}
|
||||
} else {
|
||||
if (!glyph->horizAdvX) {
|
||||
if (p->font->missingGlyph) {
|
||||
glyph->horizAdvX = p->font->missingGlyph->horizAdvX;
|
||||
} else if (p->font->horizAdvX) {
|
||||
glyph->horizAdvX = p->font->horizAdvX;
|
||||
if (p->currentFont->missingGlyph) {
|
||||
glyph->horizAdvX = p->currentFont->missingGlyph->horizAdvX;
|
||||
} else if (p->currentFont->horizAdvX) {
|
||||
glyph->horizAdvX = p->currentFont->horizAdvX;
|
||||
}
|
||||
}
|
||||
glyph->next = p->font->glyphs;
|
||||
p->font->glyphs = glyph;
|
||||
glyph->next = p->currentFont->glyphs;
|
||||
p->currentFont->glyphs = glyph;
|
||||
}
|
||||
}
|
||||
// DBG("glyph %X parsed\n", glyph->unicode);
|
||||
@ -4480,10 +4516,23 @@ void takeXformBounds(NSVGshape *shape, float *xform, float *bounds)
|
||||
bounds[3] = nsvg__maxf(bounds[3], newBounds[5]);
|
||||
bounds[3] = nsvg__maxf(bounds[3], newBounds[7]);
|
||||
}
|
||||
|
||||
bool isShapeInGroup(NSVGshape* shape, const char* groupName)
|
||||
{
|
||||
NSVGgroup* group = shape->group;
|
||||
while (group) {
|
||||
if (strcmp(group->id, groupName) == 0) {
|
||||
return true;
|
||||
}
|
||||
group = group->parent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//image bounds for a shape group
|
||||
//bounds inited before use, called from nsvgParse
|
||||
//assumed each shape already has bounds calculated.
|
||||
int nsvg__shapesBound(/*NSVGimage* image,*/ NSVGshape *shapes, float* bounds)
|
||||
int nsvg__shapesBound(/*NSVGimage* image,*/ NSVGshape *shapes, float* bounds, const char* groupName)
|
||||
{
|
||||
NSVGshape *shape, *shapeLink;
|
||||
float xform[6];
|
||||
@ -4491,6 +4540,9 @@ int nsvg__shapesBound(/*NSVGimage* image,*/ NSVGshape *shapes, float* bounds)
|
||||
int count = 0;
|
||||
int visibility;
|
||||
for (shapeLink = shapes; shapeLink != NULL; shapeLink = shapeLink->next) {
|
||||
if ( groupName && !isShapeInGroup(shapeLink, groupName) ) {
|
||||
continue;
|
||||
}
|
||||
memcpy(&xform[0], shapeLink->xform, sizeof(float)*6);
|
||||
visibility = (shapeLink->flags & NSVG_VIS_VISIBLE); //check origin visibility, not link
|
||||
|
||||
@ -4521,7 +4573,6 @@ int nsvg__shapesBound(/*NSVGimage* image,*/ NSVGshape *shapes, float* bounds)
|
||||
|
||||
void nsvg__imageBounds(NSVGimage* image, float* bounds)
|
||||
{
|
||||
// NSVGimage* image = p->image;
|
||||
NSVGclipPath* clipPath;
|
||||
if (!bounds || !image) {
|
||||
return;
|
||||
@ -4536,13 +4587,13 @@ void nsvg__imageBounds(NSVGimage* image, float* bounds)
|
||||
while (clipPath != NULL) {
|
||||
for (int i = 0; i < image->clip.count; i++) {
|
||||
if (clipPath->index == image->clip.index[i]) {
|
||||
count += nsvg__shapesBound(clipPath->shapes, bounds);
|
||||
count += nsvg__shapesBound(clipPath->shapes, bounds, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
clipPath = clipPath->next;
|
||||
}
|
||||
count += nsvg__shapesBound(image->shapes, bounds);
|
||||
count += nsvg__shapesBound(image->shapes, bounds, NULL);
|
||||
// DBG("found shapes=%d\n", count);
|
||||
if (count == 0) {
|
||||
bounds[0] = bounds[1] = 0.0f;
|
||||
@ -4550,6 +4601,47 @@ void nsvg__imageBounds(NSVGimage* image, float* bounds)
|
||||
}
|
||||
}
|
||||
|
||||
NSVGclipPath* getClipPathWithIndex(NSVGimage* image, NSVGclipPathIndex idx)
|
||||
{
|
||||
NSVGclipPath* clipPath = image->clipPaths;
|
||||
for (NSVGclipPathIndex i = 0; i < idx; i++) clipPath = clipPath->next;
|
||||
return clipPath;
|
||||
|
||||
}
|
||||
|
||||
void nsvg__imageBounds(NSVGimage* image, float* bounds, const char* groupName)
|
||||
{
|
||||
if (!bounds || !image) {
|
||||
return;
|
||||
}
|
||||
bounds[0] = FLT_MAX;
|
||||
bounds[1] = FLT_MAX;
|
||||
bounds[2] = -FLT_MAX;
|
||||
bounds[3] = -FLT_MAX;
|
||||
|
||||
int count = 0;
|
||||
|
||||
NSVGshape *shape;
|
||||
for (shape = image->shapes; shape != NULL; shape = shape->next) {
|
||||
if ( groupName && !isShapeInGroup(shape, groupName) ) {
|
||||
continue;
|
||||
}
|
||||
// DBG("nsvg__imageBounds2 found shapes=%s shape->clip.count=%d\n", shape->id, shape->clip.count);
|
||||
for (int i = 0; i < shape->clip.count; i++) {
|
||||
NSVGclipPath* clipPath = getClipPathWithIndex(image, shape->clip.index[i]);
|
||||
if ( clipPath ) {
|
||||
// DBG("nsvg__imageBounds found clipPath %s\n", clipPath->id);
|
||||
count += nsvg__shapesBound(clipPath->shapes, bounds, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
count += nsvg__shapesBound(image->shapes, bounds, groupName);
|
||||
if (count == 0) {
|
||||
bounds[0] = bounds[1] = 0.0f;
|
||||
bounds[2] = bounds[3] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// units like "px" is not used so just exclude it
|
||||
NSVGparser* nsvgParse(char* input, /* const char* units,*/ float dpi, float opacity)
|
||||
{
|
||||
@ -4604,6 +4696,9 @@ void nsvg__deleteShapes(NSVGshape* shape)
|
||||
shape->fontFace = NULL;
|
||||
nsvg__deletePaint(&shape->fill);
|
||||
nsvg__deletePaint(&shape->stroke);
|
||||
if ( !shape->isText ) {
|
||||
nsvg__deletePaths(shape->paths);
|
||||
}
|
||||
}
|
||||
nsvg__delete(shape, "nsvg__deleteShapes"_XS8);
|
||||
shape = snext;
|
||||
@ -4629,7 +4724,7 @@ void nsvgDelete(NSVGimage* image)
|
||||
nsvg__deleteClipPaths(image->clipPaths);
|
||||
group = image->groups;
|
||||
while (group != NULL) {
|
||||
gnext = group->parent;
|
||||
gnext = group->next;
|
||||
nsvg__delete(group, "nsvgDelete group"_XS8);
|
||||
group = gnext;
|
||||
}
|
||||
|
@ -58,8 +58,8 @@ extern "C" {
|
||||
#define NSVG_MAX_ATTR 2048
|
||||
#define NSVG_MAX_CLIP_PATHS 1024 // also note NSVGclipPathIndex
|
||||
|
||||
#define NANOSVG_MEMORY_ALLOCATION_TRACE
|
||||
#ifdef JIEF_DEBUG
|
||||
#define NANOSVG_MEMORY_ALLOCATION_TRACE
|
||||
#define NANOSVG_MEMORY_ALLOCATION_TRACE_VERBOSE
|
||||
#endif
|
||||
|
||||
@ -164,6 +164,7 @@ typedef struct NSVGpattern {
|
||||
typedef struct NSVGgroup
|
||||
{
|
||||
char id[kMaxIDLength];
|
||||
struct NSVGgroup* next; // Pointer to parent group or NULL
|
||||
struct NSVGgroup* parent; // Pointer to next group or NULL
|
||||
int visibility;
|
||||
} NSVGgroup;
|
||||
@ -369,8 +370,6 @@ typedef struct textFaces {
|
||||
XBool valid = false;
|
||||
} textFaces;
|
||||
|
||||
extern textFaces textFace[]; //0-help 1-message 2-menu 3-test
|
||||
|
||||
typedef struct NSVGtext {
|
||||
char id[kMaxIDLength];
|
||||
// char class[64];
|
||||
@ -416,7 +415,8 @@ typedef struct NSVGparser
|
||||
NSVGstyles* styles;
|
||||
NSVGgradientData* gradients;
|
||||
NSVGshape* shapesTail;
|
||||
struct NSVGfont* font;
|
||||
struct NSVGfont* currentFont;
|
||||
NSVGfontChain* fontsDB;
|
||||
float opacity;
|
||||
// this is temporary set for Menu text, later each text will have own face
|
||||
float fontSize;
|
||||
@ -436,6 +436,8 @@ typedef struct NSVGparser
|
||||
XBool isText;
|
||||
char unknown[64];
|
||||
NSVGtext* text;
|
||||
textFaces textFace[4]; //0-help 1-message 2-menu 3-test, far future it will be infinite list with id
|
||||
|
||||
NSVGsymbol* symbols;
|
||||
NSVGpattern *patterns;
|
||||
NSVGclipPath* clipPath;
|
||||
@ -459,7 +461,7 @@ void nsvg__outputDanglingPtr();
|
||||
#endif
|
||||
|
||||
bool isShapeInGroup(NSVGshape* shape, const char* groupName);
|
||||
|
||||
NSVGclipPath* getClipPathWithIndex(NSVGimage* image, NSVGclipPathIndex idx);
|
||||
//---
|
||||
|
||||
// Duplicates a path.
|
||||
@ -482,7 +484,9 @@ void nsvg__xformSetScale(float* t, float sx, float sy);
|
||||
void nsvg__xformPremultiply(float* t, float* s);
|
||||
void nsvg__xformMultiply(float* t, float* s);
|
||||
void nsvg__deleteFont(NSVGfont* font);
|
||||
void nsvg__deleteFontChain(NSVGfontChain *fontChain);
|
||||
void nsvg__imageBounds(NSVGimage* image, float* bounds);
|
||||
void nsvg__imageBounds(NSVGimage* image, float* bounds, const char* groupName);
|
||||
float addLetter(NSVGparser* p, CHAR16 letter, float x, float y, float scale, UINT32 color);
|
||||
void RenderSVGfont(NSVGfont *fontSVG, UINT32 color);
|
||||
|
||||
@ -503,6 +507,9 @@ NSVGrasterizer* nsvgCreateRasterizer(void);
|
||||
// w - width of the image to render
|
||||
// h - height of the image to render
|
||||
// stride - number of bytes per scaleline in the destination buffer
|
||||
void nsvgRasterize(NSVGrasterizer* r,
|
||||
NSVGimage* image, float* bounds, const char* groupName, float tx, float ty, float scalex, float scaley,
|
||||
UINT8* dst, int w, int h, int stride);
|
||||
void nsvgRasterize(NSVGrasterizer* r,
|
||||
NSVGimage* image, float tx, float ty, float scalex, float scaley,
|
||||
UINT8* dst, int w, int h, int stride);
|
||||
@ -606,7 +613,4 @@ struct NSVGrasterizer
|
||||
NSVGstencil* stencilList;
|
||||
};
|
||||
|
||||
extern NSVGfontChain *fontsDB;
|
||||
//extern struct NSVGparser *mainParser;
|
||||
|
||||
#endif
|
||||
|
@ -1645,7 +1645,8 @@ static void nsvg__initPaint(NSVGcachedPaint* cache, NSVGpaint* paint, NSVGshape*
|
||||
|
||||
|
||||
static void nsvg__rasterizeShapes(NSVGrasterizer* r,
|
||||
NSVGshape* shapes, float tx, float ty, float scalex, float scaley,
|
||||
NSVGshape* shapes, const char* groupName,
|
||||
float tx, float ty, float scalex, float scaley,
|
||||
UINT8* dst, int w, int h, int stride,
|
||||
NSVGscanlineFunction fscanline)
|
||||
{
|
||||
@ -1679,6 +1680,9 @@ static void nsvg__rasterizeShapes(NSVGrasterizer* r,
|
||||
for (shape = shapes; shape != NULL; shape = shape->next) {
|
||||
if (!(shape->flags & NSVG_VIS_VISIBLE))
|
||||
continue;
|
||||
if ( groupName && !isShapeInGroup(shape, groupName) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(&xform[0], shape->xform, sizeof(float)*6);
|
||||
|
||||
@ -1801,7 +1805,7 @@ void nsvg__rasterizeClipPaths(
|
||||
|
||||
clipPath = image->clipPaths;
|
||||
while (clipPath != NULL) {
|
||||
nsvg__rasterizeShapes(r, clipPath->shapes, tx, ty, scalex, scaley,
|
||||
nsvg__rasterizeShapes(r, clipPath->shapes, NULL, tx, ty, scalex, scaley,
|
||||
&r->stencil[r->stencilSize * clipPath->index],
|
||||
w, h, r->stencilStride, nsvg__scanlineBit);
|
||||
clipPath = clipPath->next;
|
||||
@ -1812,14 +1816,22 @@ void nsvgRasterize(NSVGrasterizer* r,
|
||||
NSVGimage* image, float tx, float ty, float scalex, float scaley,
|
||||
UINT8* dst, int w, int h, int stride)
|
||||
{
|
||||
tx -= image->realBounds[0] * scalex;
|
||||
ty -= image->realBounds[1] * scaley;
|
||||
nsvgRasterize(r, image, &image->realBounds[0], NULL, tx, ty, scalex, scaley, dst, w, h, stride);
|
||||
}
|
||||
|
||||
void nsvgRasterize(NSVGrasterizer* r,
|
||||
NSVGimage* image, float* bounds, const char* groupName,
|
||||
float tx, float ty, float scalex, float scaley,
|
||||
UINT8* dst, int w, int h, int stride)
|
||||
{
|
||||
tx -= bounds[0] * scalex;
|
||||
ty -= bounds[1] * scaley;
|
||||
// DBG(" image %s will be scaled by [%f]\n", image->id, scalex);
|
||||
// DumpFloat(" image real bounds ", image->realBounds, 4);
|
||||
|
||||
nsvg__rasterizeClipPaths(r, image, w, h, tx, ty, scalex, scaley);
|
||||
|
||||
nsvg__rasterizeShapes(r, image->shapes, tx, ty, scalex, scaley,
|
||||
nsvg__rasterizeShapes(r, image->shapes, groupName, tx, ty, scalex, scaley,
|
||||
dst, w, h, stride, nsvg__scanlineSolid);
|
||||
|
||||
nsvg__unpremultiplyAlpha(dst, w, h, stride);
|
||||
|
@ -64,7 +64,6 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
const EFI_GRAPHICS_OUTPUT_BLT_PIXEL SemiWhitePixel = {0xFF, 0xFF, 0xFF, 0xD2}; //semitransparent white
|
||||
NSVGfontChain *fontsDB = NULL;
|
||||
|
||||
//
|
||||
// Text rendering
|
||||
|
@ -173,8 +173,6 @@ void UninitRefitLib(void)
|
||||
{
|
||||
// called before running external programs to close open file handles
|
||||
|
||||
//ThemeX->closeThemeDir();
|
||||
|
||||
selfOem.closeHandle();
|
||||
self.closeHandle();
|
||||
|
||||
@ -190,7 +188,6 @@ EFI_STATUS ReinitRefitLib(void)
|
||||
selfOem.reInitialize();
|
||||
|
||||
ReinitVolumes();
|
||||
//ThemeX->openThemeDir();
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
@ -669,7 +669,6 @@ void LOADER_ENTRY::StartLoader()
|
||||
EFI_HANDLE ImageHandle = NULL;
|
||||
EFI_LOADED_IMAGE *LoadedImage = NULL;
|
||||
CONST CHAR8 *InstallerVersion;
|
||||
NSVGfont *font; // , *nextFont;
|
||||
|
||||
DbgHeader("StartLoader");
|
||||
|
||||
@ -710,18 +709,21 @@ void LOADER_ENTRY::StartLoader()
|
||||
// mainParser
|
||||
// BuiltinIcons
|
||||
// OSIcons
|
||||
NSVGfontChain *fontChain = fontsDB;
|
||||
while (fontChain) {
|
||||
font = fontChain->font;
|
||||
NSVGfontChain *nextChain = fontChain->next;
|
||||
if (font) {
|
||||
nsvg__deleteFont(font);
|
||||
fontChain->font = NULL;
|
||||
|
||||
delete ThemeX;
|
||||
ThemeX = NULL;
|
||||
|
||||
|
||||
#ifdef NANOSVG_MEMORY_ALLOCATION_TRACE
|
||||
if ( nsvg__nbDanglingPtr() > 0 ) {
|
||||
DBG("There is %zu dangling ptr from SVG subsytem\n", nsvg__nbDanglingPtr());
|
||||
nsvg__outputDanglingPtr();
|
||||
}
|
||||
FreePool(fontChain);
|
||||
fontChain = nextChain;
|
||||
}
|
||||
fontsDB = NULL;
|
||||
#endif
|
||||
#ifdef JIEF_DEBUG
|
||||
displayFreeMemory("LOADER_ENTRY::StartLoader() atfer ThemeX deleted"_XS8);
|
||||
#endif
|
||||
|
||||
|
||||
if ( OSTYPE_IS_OSX(LoaderType) || OSTYPE_IS_OSX_RECOVERY(LoaderType) || OSTYPE_IS_OSX_INSTALLER(LoaderType) ) {
|
||||
|
||||
@ -1615,12 +1617,9 @@ void LOADER_ENTRY::StartLoader()
|
||||
Status = SaveBooterLog(&self.getCloverDir(), PREBOOT_LOG);
|
||||
}
|
||||
|
||||
#ifdef JIEF_DEBUG
|
||||
//Status = EFI_NOT_FOUND;
|
||||
displayFreeMemory("Just before lauching image"_XS8);
|
||||
|
||||
Status = gBS->StartImage (ImageHandle, 0, NULL); // point to OcStartImage from OC
|
||||
#else
|
||||
Status = gBS->StartImage (ImageHandle, 0, NULL); // point to OcStartImage from OC
|
||||
#endif
|
||||
|
||||
if ( EFI_ERROR(Status) ) {
|
||||
// Ideally, we would return to the menu, displaying an error message
|
||||
|
Loading…
Reference in New Issue
Block a user