From d7e93a96e59fce50ade8f2688741417063d13fc7 Mon Sep 17 00:00:00 2001 From: Sergey Isakov Date: Mon, 23 Mar 2020 17:51:20 +0300 Subject: [PATCH] adopt DrawMainMenu to XTheme Signed-off-by: Sergey Isakov --- .../CloverX64.xcodeproj/project.pbxproj | 8 ++ rEFIt_UEFI/libeg/XImage.cpp | 54 ++++++-- rEFIt_UEFI/libeg/XImage.h | 2 + rEFIt_UEFI/libeg/XTheme.h | 2 +- rEFIt_UEFI/refit/menu.cpp | 117 +++++------------- rEFIt_UEFI/refit/screen.cpp | 109 +++++++++++++++- 6 files changed, 196 insertions(+), 96 deletions(-) diff --git a/Xcode/CloverX64/CloverX64.xcodeproj/project.pbxproj b/Xcode/CloverX64/CloverX64.xcodeproj/project.pbxproj index 0e4c96ed7..818159b85 100644 --- a/Xcode/CloverX64/CloverX64.xcodeproj/project.pbxproj +++ b/Xcode/CloverX64/CloverX64.xcodeproj/project.pbxproj @@ -207,6 +207,8 @@ 9AC780B52417EE53005CDD5C /* global_test.h in Headers */ = {isa = PBXBuildFile; fileRef = 9AC780B42417EE53005CDD5C /* global_test.h */; }; 9AC780B82417F359005CDD5C /* XStringWP.h in Headers */ = {isa = PBXBuildFile; fileRef = 9AC780B62417F359005CDD5C /* XStringWP.h */; }; 9AC780B92417F359005CDD5C /* XStringWP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC780B72417F359005CDD5C /* XStringWP.cpp */; }; + A5E326312428F4EE002240E8 /* XTheme.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5E3262F2428F4EE002240E8 /* XTheme.cpp */; }; + A5E326322428F4EE002240E8 /* XTheme.h in Headers */ = {isa = PBXBuildFile; fileRef = A5E326302428F4EE002240E8 /* XTheme.h */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -411,6 +413,8 @@ 9AC780B42417EE53005CDD5C /* global_test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = global_test.h; sourceTree = ""; }; 9AC780B62417F359005CDD5C /* XStringWP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XStringWP.h; sourceTree = ""; }; 9AC780B72417F359005CDD5C /* XStringWP.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XStringWP.cpp; sourceTree = ""; }; + A5E3262F2428F4EE002240E8 /* XTheme.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XTheme.cpp; sourceTree = ""; }; + A5E326302428F4EE002240E8 /* XTheme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XTheme.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -632,6 +636,8 @@ 9AC77F7124176C04005CDD5C /* XImage.h */, 9AC77F7024176C04005CDD5C /* XPointer.cpp */, 9AC77F6324176C04005CDD5C /* XPointer.h */, + A5E3262F2428F4EE002240E8 /* XTheme.cpp */, + A5E326302428F4EE002240E8 /* XTheme.h */, ); path = libeg; sourceTree = ""; @@ -754,6 +760,7 @@ 9AC7808B24176C04005CDD5C /* panic.h in Headers */, 9AC7806B24176C04005CDD5C /* MSKEK.h in Headers */, 9AC7807224176C04005CDD5C /* menu_items.h in Headers */, + A5E326322428F4EE002240E8 /* XTheme.h in Headers */, 9AC780B82417F359005CDD5C /* XStringWP.h in Headers */, 9AC7801C24176C04005CDD5C /* nvidia.h in Headers */, 9AC7808524176C04005CDD5C /* operatorNewDelete.h in Headers */, @@ -965,6 +972,7 @@ 9AC7804624176C04005CDD5C /* BmLib.cpp in Sources */, 9AC7804024176C04005CDD5C /* card_vlist.cpp in Sources */, 9AC780B32417EE4B005CDD5C /* global_test.cpp in Sources */, + A5E326312428F4EE002240E8 /* XTheme.cpp in Sources */, 9AC7805624176C04005CDD5C /* load_icns.cpp in Sources */, 9AC7805124176C04005CDD5C /* egemb_font.cpp in Sources */, 9AC7806424176C04005CDD5C /* securemenu.cpp in Sources */, diff --git a/rEFIt_UEFI/libeg/XImage.cpp b/rEFIt_UEFI/libeg/XImage.cpp index a80ca981d..7bd4ccb61 100644 --- a/rEFIt_UEFI/libeg/XImage.cpp +++ b/rEFIt_UEFI/libeg/XImage.cpp @@ -43,6 +43,20 @@ XImage::XImage(EG_IMAGE* egImage) } } +EFI_STATUS XImage::FromEGImage(const EG_IMAGE* egImage) +{ + if ( egImage) { + setSizeInPixels(egImage->Width, egImage->Height); + CopyMem(&PixelData[0], egImage->PixelData, GetSizeInBytes()); + } else { + setSizeInPixels(0, 0); + } + if (GetSizeInBytes() == 0) { + return EFI_NOT_FOUND; + } + return EFI_SUCCESS; +} + XImage& XImage::operator= (const XImage& other) { // Width = other.GetWidth(); @@ -556,24 +570,42 @@ EFI_STATUS XImage::LoadXImage(EFI_FILE *BaseDir, const XStringW& IconName) //while compose uses old object void XImage::EnsureImageSize(IN UINTN NewWidth, IN UINTN NewHeight, IN CONST EFI_GRAPHICS_OUTPUT_BLT_PIXEL& Color) { -// EG_IMAGE *NewImage; - -// if (isEmpty()) -// return; if (NewWidth == Width && NewHeight == Height) return; -/* NewImage = egCreateFilledImage(Width, Height, true, Color); // TODO : import that method to directly deal with XImage - if (NewImage == NULL) { - return; // panic instead ? - } */ XImage NewImage(NewWidth, NewHeight); NewImage.Fill(Color); -// Compose(0, 0, NewImage, false); -// egFreeImage(NewImage); NewImage.Compose(0, 0, (*this), false); setSizeInPixels(NewWidth, NewHeight); //include reallocate but loose data -// CopyScaled(NewImage, 1.f); CopyMem(&PixelData[0], &NewImage.PixelData[0], GetSizeInBytes()); //we have to copy pixels twice? because we can't return newimage instead of this } + +void XImage::DummyImage(IN UINTN PixelSize) +{ + + UINTN LineOffset; + CHAR8 *Ptr, *YPtr; + + setSizeInPixels(PixelSize, PixelSize); + + LineOffset = PixelSize * 4; + + YPtr = (CHAR8 *)GetPixelPtr(0,0) + ((PixelSize - 32) >> 1) * (LineOffset + 4); + for (UINTN y = 0; y < 32; y++) { + Ptr = YPtr; + for (UINTN x = 0; x < 32; x++) { + if (((x + y) % 12) < 6) { + *Ptr++ = 0; + *Ptr++ = 0; + *Ptr++ = 0; + } else { + *Ptr++ = 0; + *Ptr++ = ~0; //yellow + *Ptr++ = ~0; + } + *Ptr++ = ~111; + } + YPtr += LineOffset; + } +} diff --git a/rEFIt_UEFI/libeg/XImage.h b/rEFIt_UEFI/libeg/XImage.h index 9f55fb562..79a1190aa 100644 --- a/rEFIt_UEFI/libeg/XImage.h +++ b/rEFIt_UEFI/libeg/XImage.h @@ -87,6 +87,7 @@ public: EFI_STATUS FromPNG(const UINT8 * Data, UINTN Lenght); EFI_STATUS ToPNG(UINT8** Data, UINTN& OutSize); EFI_STATUS FromSVG(const CHAR8 *SVGData, float scale); + EFI_STATUS FromEGImage(const EG_IMAGE* egImage); void GetArea(const EG_RECT& Rect); void GetArea(INTN x, INTN y, UINTN W, UINTN H); void Draw(INTN x, INTN y, float scale); @@ -96,6 +97,7 @@ public: EFI_STATUS LoadXImage(EFI_FILE *Dir, const XStringW& FileName); //for example LoadImage(ThemeDir, L"icons\\" + Name); EFI_STATUS LoadXImage(EFI_FILE *BaseDir, const char* IconName); void EnsureImageSize(IN UINTN Width, IN UINTN Height, IN CONST EFI_GRAPHICS_OUTPUT_BLT_PIXEL& Color); + void DummyImage(IN UINTN PixelSize); }; diff --git a/rEFIt_UEFI/libeg/XTheme.h b/rEFIt_UEFI/libeg/XTheme.h index 6fd180a55..1a14c0cce 100644 --- a/rEFIt_UEFI/libeg/XTheme.h +++ b/rEFIt_UEFI/libeg/XTheme.h @@ -85,7 +85,7 @@ public: XImage BigBack; //it size is not equal to screen size will be scaled or cropped XImage Banner; //same as logo in the array, make a link? XImage SelectionImages[6]; - XImage Button[4]; + XImage Buttons[4]; XImage ScrollbarBackgroundImage; XImage BarStartImage; XImage BarEndImage; diff --git a/rEFIt_UEFI/refit/menu.cpp b/rEFIt_UEFI/refit/menu.cpp index 39d579994..065d63860 100644 --- a/rEFIt_UEFI/refit/menu.cpp +++ b/rEFIt_UEFI/refit/menu.cpp @@ -2560,7 +2560,8 @@ UINTN REFIT_MENU_SCREEN::RunGenericMenu(IN MENU_STYLE_FUNC StyleFunc, IN OUT INT } if (HaveTimeout) { - TimeoutMessage = PoolPrint(L"%s in %d seconds", TimeoutText, TimeoutCountdown); + TimeoutMessage = PoolPrint(L"%s in %d seconds", TimeoutText.data(), TimeoutCountdown); + // XStringW TOMessage = TimeoutText + L" in " + WPrintf("%d", TimeoutCountdown) + L" seconds"; ((*this).*(StyleFunc))(MENU_FUNCTION_PAINT_TIMEOUT, TimeoutMessage); FreePool(TimeoutMessage); } @@ -4176,103 +4177,77 @@ VOID REFIT_MENU_SCREEN::GraphicsMenuStyle(IN UINTN Function, IN CONST CHAR16 *Pa * Draw entries for GUI. */ #if USE_XTHEME +// move it to class XTheme? VOID DrawMainMenuEntry(REFIT_ABSTRACT_MENU_ENTRY *Entry, BOOLEAN selected, INTN XPos, INTN YPos) { - EG_IMAGE* MainImage = NULL; - EG_IMAGE* BadgeImage = NULL; + XImage MainImage(0,0); + XImage BadgeImage(0,0); bool NewImageCreated = false; - INTN Scale = GlobalConfig.MainEntriesSize >> 3; //usually it is 128>>3 == 16. if 256>>3 == 32 - if (Entry->Row == 0 && Entry->getDriveImage() && !(GlobalConfig.HideBadges & HDBADGES_SWAP)) { - MainImage = Entry->getDriveImage(); + if (Entry->Row == 0 && Entry->getDriveImage() && !(ThemeX.HideBadges & HDBADGES_SWAP)) { + MainImage.FromEGImage(Entry->getDriveImage()); } else { - MainImage = Entry->Image; + MainImage.FromEGImage(Entry->Image); } //this should be inited by the Theme - if (!MainImage) { + if (MainImage.isEmpty()) { if (!IsEmbeddedTheme()) { - MainImage = egLoadIcon(ThemeDir, GetIconsExt(L"icons\\os_mac", L"icns"), Scale << 3); +// MainImage = egLoadIcon(ThemeDir, GetIconsExt(L"icons\\os_mac", L"icns"), Scale << 3); + MainImage = ThemeX.GetIcon("os_mac"); } - if (!MainImage) { - MainImage = DummyImage(Scale << 3); + if (MainImage.isEmpty()) { + MainImage.DummyImage(ThemeX.MainEntriesSize); } - if (MainImage) { + if (!MainImage.isEmpty()) { NewImageCreated = true; } } // DBG("Entry title=%s; Width=%d\n", Entry->Title, MainImage->Width); -#if USE_XTHEME float fScale; - if (TypeSVG) { + if (ThemeX.TypeSVG) { fScale = (selected ? 1.f : -1.f); } else { - fScale = ((Entry->Row == 0) ? (MainEntriesSize/128.f * (selected ? 1.f : -1.f)): 1.f) ; + fScale = ((Entry->Row == 0) ? (ThemeX.MainEntriesSize/128.f * (selected ? 1.f : -1.f)): 1.f) ; } -#else - if (GlobalConfig.TypeSVG) { - Scale = 16 * (selected ? 1 : -1); - } else { - Scale = ((Entry->Row == 0) ? (Scale * (selected ? 1 : -1)): 16) ; - } -#endif - if (Entry->Row == 0) { - BadgeImage = Entry->getBadgeImage(); + BadgeImage.FromEGImage(Entry->getBadgeImage()); } //else null -#if USE_XTHEME - INTN index = ((Entry->Row == 0) ? 0 : 2) + (selected ? 0 : 1); - XImage& TopImage = *SelectionImages[index]; - if(SelectionOnTop) { - BaseImage.Draw(XPos, YPos, fScale); + XImage& TopImage = ThemeX.SelectionImages[((Entry->Row == 0) ? 0 : 2) + (selected ? 0 : 1)]; + + if(ThemeX.SelectionOnTop) { + MainImage.Draw(XPos, YPos, fScale); BadgeImage.Draw(XPos, YPos, fScale); TopImage.Draw(XPos, YPos, fScale); } else { TopImage.Draw(XPos, YPos, fScale); - BaseImage.Draw(XPos, YPos, fScale); + MainImage.Draw(XPos, YPos, fScale); BadgeImage.Draw(XPos, YPos, fScale); } -#else - if (GlobalConfig.SelectionOnTop) { - SelectionImages[0]->HasAlpha = TRUE; - SelectionImages[2]->HasAlpha = TRUE; - //MainImage->HasAlpha = TRUE; - BltImageCompositeBadge(MainImage, - SelectionImages[((Entry->Row == 0) ? 0 : 2) + (selected ? 0 : 1)], - BadgeImage, - XPos, YPos, Scale); - } else { - BltImageCompositeBadge(SelectionImages[((Entry->Row == 0) ? 0 : 2) + (selected ? 0 : 1)], - MainImage, - BadgeImage, - XPos, YPos, Scale); - } -#endif // draw BCS indicator // Needy: if Labels (Titles) are hidden there is no point to draw the indicator - if (GlobalConfig.BootCampStyle && !(GlobalConfig.HideUIFlags & HIDEUI_FLAG_LABEL)) { - SelectionImages[4]->HasAlpha = TRUE; + if (ThemeX.BootCampStyle && !(ThemeX.HideUIFlags & HIDEUI_FLAG_LABEL)) { +// ThemeX.SelectionImages[4]->HasAlpha = TRUE; // indicator is for row 0, main entries, only if (Entry->Row == 0) { - BltImageAlpha(SelectionImages[4 + (selected ? 0 : 1)], - XPos + (row0TileSize / 2) - (INTN)(INDICATOR_SIZE * 0.5f * GlobalConfig.Scale), - row0PosY + row0TileSize + TextHeight + (INTN)((BCSMargin * 2) * GlobalConfig.Scale), - &MenuBackgroundPixel, Scale); +// BltImageAlpha(SelectionImages[4 + (selected ? 0 : 1)], +// XPos + (row0TileSize / 2) - (INTN)(INDICATOR_SIZE * 0.5f * GlobalConfig.Scale), +// row0PosY + row0TileSize + TextHeight + (INTN)((BCSMargin * 2) * GlobalConfig.Scale), +// &MenuBackgroundPixel, Scale); + TopImage = ThemeX.SelectionImages[4 + (selected ? 0 : 1)]; + TopImage.Draw(XPos + (ThemeX.row0TileSize / 2) - (INTN)(INDICATOR_SIZE * 0.5f * ThemeX.Scale), + row0PosY + ThemeX.row0TileSize + TextHeight + (INTN)((BCSMargin * 2) * ThemeX.Scale), fScale); } } Entry->Place.XPos = XPos; Entry->Place.YPos = YPos; - Entry->Place.Width = MainImage->Width; - Entry->Place.Height = MainImage->Height; - //we can't free MainImage because it may be new image or it may be a link to entry image - // a workaround - if (NewImageCreated) { - egFreeImage(MainImage); - } + Entry->Place.Width = MainImage.GetWidth(); + Entry->Place.Height = MainImage.GetHeight(); + } #else @@ -4302,40 +4277,17 @@ VOID DrawMainMenuEntry(REFIT_ABSTRACT_MENU_ENTRY *Entry, BOOLEAN selected, INTN } } // DBG("Entry title=%s; Width=%d\n", Entry->Title, MainImage->Width); -#if USE_XTHEME - float fScale; - if (TypeSVG) { - fScale = (selected ? 1.f : -1.f); - } else { - fScale = ((Entry->Row == 0) ? (MainEntriesSize/128.f * (selected ? 1.f : -1.f)): 1.f) ; - } -#else if (GlobalConfig.TypeSVG) { Scale = 16 * (selected ? 1 : -1); } else { Scale = ((Entry->Row == 0) ? (Scale * (selected ? 1 : -1)): 16) ; } -#endif if (Entry->Row == 0) { BadgeImage = Entry->getBadgeImage(); } //else null -#if USE_XTHEME - INTN index = ((Entry->Row == 0) ? 0 : 2) + (selected ? 0 : 1); - XImage& TopImage = *SelectionImages[index]; - if(SelectionOnTop) { - BaseImage.Draw(XPos, YPos, fScale); - BadgeImage.Draw(XPos, YPos, fScale); - TopImage.Draw(XPos, YPos, fScale); - } else { - TopImage.Draw(XPos, YPos, fScale); - BaseImage.Draw(XPos, YPos, fScale); - BadgeImage.Draw(XPos, YPos, fScale); - } - -#else if (GlobalConfig.SelectionOnTop) { SelectionImages[0]->HasAlpha = TRUE; SelectionImages[2]->HasAlpha = TRUE; @@ -4350,7 +4302,6 @@ VOID DrawMainMenuEntry(REFIT_ABSTRACT_MENU_ENTRY *Entry, BOOLEAN selected, INTN BadgeImage, XPos, YPos, Scale); } -#endif // draw BCS indicator // Needy: if Labels (Titles) are hidden there is no point to draw the indicator if (GlobalConfig.BootCampStyle && !(GlobalConfig.HideUIFlags & HIDEUI_FLAG_LABEL)) { diff --git a/rEFIt_UEFI/refit/screen.cpp b/rEFIt_UEFI/refit/screen.cpp index c6a33f0bf..7503961a3 100644 --- a/rEFIt_UEFI/refit/screen.cpp +++ b/rEFIt_UEFI/refit/screen.cpp @@ -1008,7 +1008,114 @@ VOID REFIT_MENU_SCREEN::UpdateAnime() } LastDraw = Now; } +#if USE_XTHEME +//by initial we use EG_IMAGE anime +VOID REFIT_MENU_SCREEN::InitAnime() +{ + CHAR16 FileName[256]; + CHAR16 *Path; + EG_IMAGE *p = NULL; + EG_IMAGE *Last = NULL; + GUI_ANIME *Anime; + if (GlobalConfig.TextOnly) return; + // + for (Anime = GuiAnime; Anime != NULL && Anime->ID != ID; Anime = Anime->Next); + + // Check if we should clear old film vars (no anime or anime path changed) + // + if (gThemeOptionsChanged || !Anime || !Film || IsEmbeddedTheme() || + gThemeChanged) { + // DBG(" free screen\n"); + if (Film) { + //free images in the film + for (INTN i = 0; i <= Frames; i++) { //really there are N+1 frames + // free only last occurrence of repeated frames + if (Film[i] != NULL && (i == Frames || Film[i] != Film[i+1])) { + FreePool(Film[i]); + } + } + FreePool(Film); + Film = NULL; + Frames = 0; + } + } + // Check if we should load anime files (first run or after theme change) + if (Anime && Film == NULL) { + Path = Anime->Path; + Film = (EG_IMAGE**)AllocateZeroPool((Anime->Frames + 1) * sizeof(VOID*)); + if ((GlobalConfig.TypeSVG || Path) && Film) { + // Look through contents of the directory + UINTN i; + for (i = 0; i < Anime->Frames; i++) { + // DBG("Try to load file %s\n", FileName); + if (ThemeX.TypeSVG) { + p = LoadSvgFrame(i); + // DBG("frame %d loaded\n", i); + } else { + UnicodeSPrint(FileName, 512, L"%s\\%s_%03d.png", Path, Path, i); + p = egLoadImage(ThemeDir, FileName, TRUE); + } + if (!p) { + p = Last; + if (!p) break; + } else { + Last = p; + } + Film[i] = p; + } + if (Film[0] != NULL) { + Frames = i; + DBG(" found %d frames of the anime\n", i); + // Create background frame + Film[i] = egCreateImage(Film[0]->Width, Film[0]->Height, FALSE); + // Copy some settings from Anime into Screen + FrameTime = Anime->FrameTime; + Once = Anime->Once; +// Theme = (__typeof__(Theme))AllocateCopyPool(StrSize(GlobalConfig.Theme), GlobalConfig.Theme); + } /*else { + DBG("Film[0] == NULL\n"); + } */ + } + } + // Check if a new style placement value has been specified + if (Anime && (Anime->FilmX >=0) && (Anime->FilmX <=100) && + (Anime->FilmY >=0) && (Anime->FilmY <=100) && + (Film != NULL) && (Film[0] != NULL)) { + // Check if screen size being used is different from theme origination size. + // If yes, then recalculate the animation placement % value. + // This is necessary because screen can be a different size, but anim is not scaled. + FilmPlace.XPos = HybridRepositioning(Anime->ScreenEdgeHorizontal, Anime->FilmX, Film[0]->Width, UGAWidth, ThemeX.ThemeDesignWidth ); + FilmPlace.YPos = HybridRepositioning(Anime->ScreenEdgeVertical, Anime->FilmY, Film[0]->Height, UGAHeight, ThemeX.ThemeDesignHeight); + + // Does the user want to fine tune the placement? + FilmPlace.XPos = CalculateNudgePosition(FilmPlace.XPos, Anime->NudgeX, Film[0]->Width, UGAWidth); + FilmPlace.YPos = CalculateNudgePosition(FilmPlace.YPos, Anime->NudgeY, Film[0]->Height, UGAHeight); + + FilmPlace.Width = Film[0]->Width; + FilmPlace.Height = Film[0]->Height; + DBG("recalculated Film position\n"); + } else { + // We are here if there is no anime, or if we use oldstyle placement values + // For both these cases, FilmPlace will be set after banner/menutitle positions are known + FilmPlace.XPos = 0; + FilmPlace.YPos = 0; + FilmPlace.Width = 0; + FilmPlace.Height = 0; + } + if (Film != NULL && Film[0] != NULL) { + DBG(" Anime seems OK, init it\n"); + AnimeRun = TRUE; + CurrentFrame = 0; + LastDraw = 0; + } else { + // DBG("not run anime\n"); + AnimeRun = FALSE; + } + // DBG("anime inited\n"); +} + +#else VOID REFIT_MENU_SCREEN::InitAnime() { @@ -1120,7 +1227,7 @@ VOID REFIT_MENU_SCREEN::InitAnime() } // DBG("anime inited\n"); } - +#endif BOOLEAN REFIT_MENU_SCREEN::GetAnime() { GUI_ANIME *Anime;