diff --git a/Include/Library/MemLogLib.h b/Include/Library/MemLogLib.h index 852da0b458..e1f28a906e 100644 --- a/Include/Library/MemLogLib.h +++ b/Include/Library/MemLogLib.h @@ -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 diff --git a/Library/MemLogLibDefault/MemLogLib.c b/Library/MemLogLibDefault/MemLogLib.c index b47068d2a2..3da0a95afc 100644 --- a/Library/MemLogLibDefault/MemLogLib.c +++ b/Library/MemLogLibDefault/MemLogLib.c @@ -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; diff --git a/rEFIt_UEFI/Platform/Settings.cpp b/rEFIt_UEFI/Platform/Settings.cpp index b911e05a4c..34e0e4f039 100755 --- a/rEFIt_UEFI/Platform/Settings.cpp +++ b/rEFIt_UEFI/Platform/Settings.cpp @@ -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() ) { diff --git a/rEFIt_UEFI/Platform/Settings.h b/rEFIt_UEFI/Platform/Settings.h index 32a99cb991..e4452f2718 100755 --- a/rEFIt_UEFI/Platform/Settings.h +++ b/rEFIt_UEFI/Platform/Settings.h @@ -473,16 +473,12 @@ class CUSTOM_LEGACY_ENTRY 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 @@ class CUSTOM_TOOL_ENTRY 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 { diff --git a/rEFIt_UEFI/entry_scan/loader.cpp b/rEFIt_UEFI/entry_scan/loader.cpp index 415953451a..c63e495923 100644 --- a/rEFIt_UEFI/entry_scan/loader.cpp +++ b/rEFIt_UEFI/entry_scan/loader.cpp @@ -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; diff --git a/rEFIt_UEFI/gui/REFIT_MAINMENU_SCREEN.cpp b/rEFIt_UEFI/gui/REFIT_MAINMENU_SCREEN.cpp index 4ade95a0c0..293606b7aa 100644 --- a/rEFIt_UEFI/gui/REFIT_MAINMENU_SCREEN.cpp +++ b/rEFIt_UEFI/gui/REFIT_MAINMENU_SCREEN.cpp @@ -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); } diff --git a/rEFIt_UEFI/gui/REFIT_MENU_SCREEN.cpp b/rEFIt_UEFI/gui/REFIT_MENU_SCREEN.cpp index dc74119ede..c35460c552 100644 --- a/rEFIt_UEFI/gui/REFIT_MENU_SCREEN.cpp +++ b/rEFIt_UEFI/gui/REFIT_MENU_SCREEN.cpp @@ -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); diff --git a/rEFIt_UEFI/libeg/VectorGraphics.cpp b/rEFIt_UEFI/libeg/VectorGraphics.cpp index 8d9de63ba9..a8193f38e8 100755 --- a/rEFIt_UEFI/libeg/VectorGraphics.cpp +++ b/rEFIt_UEFI/libeg/VectorGraphics.cpp @@ -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*/; - NSVGparser* p2 = nsvg__createParser(); - IconImage = p2->image; - IconImage->clip.count = 0; - shape = SVGimage->shapes; - shapePrev = NULL; + float IconImageWidth = 0; // Width of the image. + float IconImageHeight = 0; // Height of the image. + + shape = SVGimage->shapes; 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; iclip.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; diff --git a/rEFIt_UEFI/libeg/XCinema.cpp b/rEFIt_UEFI/libeg/XCinema.cpp index a78c647d12..8839be5290 100644 --- a/rEFIt_UEFI/libeg/XCinema.cpp +++ b/rEFIt_UEFI/libeg/XCinema.cpp @@ -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,28 @@ 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); - } + 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); } + } +} + + +// 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); } @@ -116,3 +128,4 @@ void FILM::GetFrames(XTheme& TheTheme /*, const XStringW& Path*/) // Path alread } + diff --git a/rEFIt_UEFI/libeg/XCinema.h b/rEFIt_UEFI/libeg/XCinema.h index ec28d49069..73451cc0d3 100644 --- a/rEFIt_UEFI/libeg/XCinema.h +++ b/rEFIt_UEFI/libeg/XCinema.h @@ -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 @@ class FILM 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; } diff --git a/rEFIt_UEFI/libeg/XIcon.cpp b/rEFIt_UEFI/libeg/XIcon.cpp index 7cd22df128..157230162a 100644 --- a/rEFIt_UEFI/libeg/XIcon.cpp +++ b/rEFIt_UEFI/libeg/XIcon.cpp @@ -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; } diff --git a/rEFIt_UEFI/libeg/XIcon.h b/rEFIt_UEFI/libeg/XIcon.h index 1bf4017ab5..68ed8ae29e 100644 --- a/rEFIt_UEFI/libeg/XIcon.h +++ b/rEFIt_UEFI/libeg/XIcon.h @@ -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 @@ class XIcon // 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; }; diff --git a/rEFIt_UEFI/libeg/XImage.cpp b/rEFIt_UEFI/libeg/XImage.cpp index 20d49f754b..03090c5ccc 100644 --- a/rEFIt_UEFI/libeg/XImage.cpp +++ b/rEFIt_UEFI/libeg/XImage.cpp @@ -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)); } } diff --git a/rEFIt_UEFI/libeg/XTheme.cpp b/rEFIt_UEFI/libeg/XTheme.cpp index 4e2e283fae..896d23ed0b 100644 --- a/rEFIt_UEFI/libeg/XTheme.cpp +++ b/rEFIt_UEFI/libeg/XTheme.cpp @@ -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 @@ InitTheme(const CHAR8* ChosenTheme) 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 @@ InitTheme(const CHAR8* ChosenTheme) 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); diff --git a/rEFIt_UEFI/libeg/XTheme.h b/rEFIt_UEFI/libeg/XTheme.h index 730c412f27..9c5d7e2814 100644 --- a/rEFIt_UEFI/libeg/XTheme.h +++ b/rEFIt_UEFI/libeg/XTheme.h @@ -22,43 +22,15 @@ class TagStruct; EFI_STATUS InitTheme (const CHAR8* ChosenTheme); +extern textFaces nullTextFaces; class XTheme { public: XObjArray Icons; -protected: XStringW m_ThemePath = NullXStringW; - EFI_FILE *ThemeDir; - -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; - } - + EFI_FILE *ThemeDir = 0; -public: // UINTN DisableFlags; UINTN HideBadges; UINTN HideUIFlags; @@ -146,20 +118,36 @@ class XTheme 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 @@ class XTheme 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(); diff --git a/rEFIt_UEFI/libeg/nanosvg.cpp b/rEFIt_UEFI/libeg/nanosvg.cpp index d03770df4c..f46ffd6e49 100755 --- a/rEFIt_UEFI/libeg/nanosvg.cpp +++ b/rEFIt_UEFI/libeg/nanosvg.cpp @@ -667,29 +667,38 @@ static void nsvg__deletePaths(NSVGpath* path) } } -void nsvg__deleteFont(NSVGfont* font) +static void nsvg__deleteGlyphs(NSVGglyph* glyphs) { - 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; + NSVGglyph *next = glyphs->next; nsvg__deletePaths(glyphs->path); - nsvg__delete(glyphs, "nsvg__deleteFont"_XS8); + nsvg__delete(glyphs, "nsvg__deleteGlyphs"_XS8); glyphs = next; } +} + +void nsvg__deleteFont(NSVGfont* font) +{ + if (!font) { + return; + } + //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); + } + + auto text = p->text; + while ( text ) { + nsvg__delete(text, "nsvg__deleteParser3"_XS8); + text = text->next; } - for (i=0; iattr[i]); + + 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; } diff --git a/rEFIt_UEFI/libeg/nanosvg.h b/rEFIt_UEFI/libeg/nanosvg.h index b1c26a2cf6..1ec142a00d 100644 --- a/rEFIt_UEFI/libeg/nanosvg.h +++ b/rEFIt_UEFI/libeg/nanosvg.h @@ -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 diff --git a/rEFIt_UEFI/libeg/nanosvgrast.cpp b/rEFIt_UEFI/libeg/nanosvgrast.cpp index 5fd58e33c9..44a07a44be 100644 --- a/rEFIt_UEFI/libeg/nanosvgrast.cpp +++ b/rEFIt_UEFI/libeg/nanosvgrast.cpp @@ -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); diff --git a/rEFIt_UEFI/libeg/text.cpp b/rEFIt_UEFI/libeg/text.cpp index a36398714b..afe9424a82 100644 --- a/rEFIt_UEFI/libeg/text.cpp +++ b/rEFIt_UEFI/libeg/text.cpp @@ -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 diff --git a/rEFIt_UEFI/refit/lib.cpp b/rEFIt_UEFI/refit/lib.cpp index 2c2e7fb49a..86e8332b4a 100644 --- a/rEFIt_UEFI/refit/lib.cpp +++ b/rEFIt_UEFI/refit/lib.cpp @@ -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; } diff --git a/rEFIt_UEFI/refit/main.cpp b/rEFIt_UEFI/refit/main.cpp index d55b772c7a..c9d17cefd2 100644 --- a/rEFIt_UEFI/refit/main.cpp +++ b/rEFIt_UEFI/refit/main.cpp @@ -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; - Status = gBS->StartImage (ImageHandle, 0, NULL); // point to OcStartImage from OC -#else + displayFreeMemory("Just before lauching image"_XS8); + 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