From a3dd82017d0be4d3fdca46a722b41b5ff3777139 Mon Sep 17 00:00:00 2001 From: srs5694 Date: Tue, 15 Jan 2013 23:29:48 -0500 Subject: [PATCH] Improved submenu and information menu appearance over a full-screen banner. --- libeg/image.c | 3 + libeg/lodepng.c | 20 ++--- mkdistrib | 2 +- refind/global.h | 1 + refind/lib.c | 15 ---- refind/lib.h | 1 - refind/main.c | 4 +- refind/menu.c | 190 ++++++++++++++++++++++++++++++------------------ refind/screen.c | 2 +- 9 files changed, 134 insertions(+), 104 deletions(-) diff --git a/libeg/image.c b/libeg/image.c index 4cf282e..e940942 100644 --- a/libeg/image.c +++ b/libeg/image.c @@ -233,6 +233,9 @@ static CHAR16 * egFindExtension(IN CHAR16 *FileName) return FileName + StrLen(FileName); } +// Decode the specified data as the specified format. The IconSize parameter is +// relevant only for ICNS, for which it selects which ICNS sub-image is decoded. +// Returns a pointer to the resulting EG_IMAGE or NULL if decoding failed. static EG_IMAGE * egDecodeAny(IN UINT8 *FileData, IN UINTN FileDataLength, IN CHAR16 *Format, IN UINTN IconSize, IN BOOLEAN WantAlpha) { diff --git a/libeg/lodepng.c b/libeg/lodepng.c index 54c36ab..92bf3a1 100644 --- a/libeg/lodepng.c +++ b/libeg/lodepng.c @@ -6273,19 +6273,12 @@ unsigned encode(const std::string& filename, typedef struct _lode_color { - UINT16 red; - UINT16 green; - UINT16 blue; - UINT16 alpha; + UINT8 red; + UINT8 green; + UINT8 blue; + UINT8 alpha; } lode_color; -// typedef struct _lode_color8 { -// UINT16 red; -// UINT16 green; -// UINT16 blue; -// UINT16 alpha; -// } lode_color8; - EG_IMAGE * egDecodePNG(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN IconSize, IN BOOLEAN WantAlpha) { EG_IMAGE *NewImage = NULL; unsigned Error, Width, Height; @@ -6294,7 +6287,7 @@ EG_IMAGE * egDecodePNG(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN Ico UINTN i; Error = lodepng_decode_memory((unsigned char **) &PixelData, &Width, &Height, (unsigned char*) FileData, - (size_t) FileDataLength, LCT_RGBA, 16); + (size_t) FileDataLength, LCT_RGBA, 8); if (Error) { return NULL; @@ -6302,9 +6295,6 @@ EG_IMAGE * egDecodePNG(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN Ico // allocate image structure and buffer NewImage = egCreateImage(Width, Height, WantAlpha); -// Print(L"Have created image; it %s NULL\n", NewImage ? L"is not" : L"is"); -// Print(L"NewImage's size is %d x %d\n", NewImage->Width, NewImage->Height); -// PauseForKey(); if ((NewImage == NULL) || (NewImage->Width != Width) || (NewImage->Height != Height)) return NULL; diff --git a/mkdistrib b/mkdistrib index 45fa0df..af3ed1d 100755 --- a/mkdistrib +++ b/mkdistrib @@ -46,7 +46,7 @@ make clean # Prepare a place and copy files there.... mkdir -p ../snapshots/$1/refind-$1/icons -cp --preserve=timestamps icons/*icns ../snapshots/$1/refind-$1/icons/ +cp --preserve=timestamps icons/*.icns icons/*.png ../snapshots/$1/refind-$1/icons/ cp -a docs images keys include EfiLib libeg mok refind filesystems refind.spec install.sh mkrlconf.sh mvrefind.sh CREDITS.txt NEWS.txt BUILDING.txt COPYING.txt LICENSE.txt README.txt refind.inf Make.tiano Make.common Makefile refind.conf-sample ../snapshots/$1/refind-$1 # Go there and prepare a souce code zip file.... diff --git a/refind/global.h b/refind/global.h index 4e381db..1e20d9f 100644 --- a/refind/global.h +++ b/refind/global.h @@ -215,6 +215,7 @@ typedef struct { BOOLEAN ScanAllLinux; UINTN RequestedScreenWidth; UINTN RequestedScreenHeight; + UINTN BannerBottomEdge; UINTN RequestedTextMode; UINTN Timeout; UINTN HideUIFlags; diff --git a/refind/lib.c b/refind/lib.c index db3a6dd..8235fea 100644 --- a/refind/lib.c +++ b/refind/lib.c @@ -1336,21 +1336,6 @@ CHAR16 * StripEfiExtension(CHAR16 *FileName) { return Copy; } // CHAR16 * StripExtension() -// Replaces a filename extension of ".efi" with the specified string -// (Extension). If the input Path doesn't end in ".efi", Extension -// is added to the existing filename. -// VOID ReplaceEfiExtension(IN OUT CHAR16 *Path, IN CHAR16 *Extension) -// { -// UINTN PathLen; -// -// PathLen = StrLen(Path); -// // Note: Do StriCmp() twice to work around Gigabyte Hybrid EFI case-sensitivity bug.... -// if ((PathLen >= 4) && ((StriCmp(&Path[PathLen - 4], L".efi") == 0) || (StriCmp(&Path[PathLen - 4], L".EFI") == 0))) { -// Path[PathLen - 4] = 0; -// } // if -// StrCat(Path, Extension); -// } // VOID ReplaceEfiExtension() - // // memory string search // diff --git a/refind/lib.h b/refind/lib.h index 49786ca..4004c45 100644 --- a/refind/lib.h +++ b/refind/lib.h @@ -102,7 +102,6 @@ EFI_STATUS DirIterClose(IN OUT REFIT_DIR_ITER *DirIter); CHAR16 * Basename(IN CHAR16 *Path); CHAR16 * StripEfiExtension(CHAR16 *FileName); -//VOID ReplaceEfiExtension(IN OUT CHAR16 *Path, IN CHAR16 *Extension); INTN FindMem(IN VOID *Buffer, IN UINTN BufferLength, IN VOID *SearchString, IN UINTN SearchStringLength); VOID ReinitVolumes(VOID); diff --git a/refind/main.c b/refind/main.c index e10bab3..4638a62 100644 --- a/refind/main.c +++ b/refind/main.c @@ -106,7 +106,7 @@ static REFIT_MENU_SCREEN MainMenu = { L"Main Menu", NULL, 0, NULL, 0, NULL L"Insert or F2 for more options; Esc to refresh" }; static REFIT_MENU_SCREEN AboutMenu = { L"About", NULL, 0, NULL, 0, NULL, 0, NULL, L"Press Enter to return to main menu", L"" }; -REFIT_CONFIG GlobalConfig = { FALSE, FALSE, 0, 0, DONT_CHANGE_TEXT_MODE, 20, 0, 0, GRAPHICS_FOR_OSX, LEGACY_TYPE_MAC, 0, +REFIT_CONFIG GlobalConfig = { FALSE, FALSE, 0, 0, 0, DONT_CHANGE_TEXT_MODE, 20, 0, 0, GRAPHICS_FOR_OSX, LEGACY_TYPE_MAC, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, {TAG_SHELL, TAG_APPLE_RECOVERY, TAG_MOK_TOOL, TAG_ABOUT, TAG_SHUTDOWN, TAG_REBOOT, 0, 0, 0, 0, 0 }}; @@ -128,7 +128,7 @@ static VOID AboutrEFInd(VOID) if (AboutMenu.EntryCount == 0) { AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT); - AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.6.4.5"); + AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.6.4.6"); AddMenuInfoLine(&AboutMenu, L""); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer"); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith"); diff --git a/refind/menu.c b/refind/menu.c index 7f02652..39c9020 100644 --- a/refind/menu.c +++ b/refind/menu.c @@ -86,7 +86,6 @@ static CHAR16 ArrowDown[2] = { ARROW_DOWN, 0 }; static EG_IMAGE *SelectionImages[2] = { NULL, NULL }; static EG_PIXEL SelectionBackgroundPixel = { 0xff, 0xff, 0xff, 0 }; -static EG_IMAGE *TextBuffer = NULL; // // Graphics helper functions @@ -637,69 +636,142 @@ static VOID TextMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, // Display a submenu -static VOID DrawSubmenuText(IN CHAR16 *Text, IN UINTN SelectedWidth, IN UINTN XPos, IN UINTN YPos) +static VOID DrawSubmenuText(IN CHAR16 *Text, IN BOOLEAN Selected, IN UINTN FieldWidth, IN UINTN XPos, IN UINTN YPos) { - if (TextBuffer == NULL) - TextBuffer = egCreateImage(LAYOUT_TEXT_WIDTH, TEXT_LINE_HEIGHT, TRUE); - - egFillImage(TextBuffer, &MenuBackgroundPixel); - if (SelectedWidth > 0) { - // draw selection bar background - egFillImageArea(TextBuffer, 0, 0, SelectedWidth, TextBuffer->Height, - &SelectionBackgroundPixel); - } +// UINTN TextWidth = TEXT_XMARGIN * 2 + StrLen(Text) * FONT_CELL_WIDTH; + EG_IMAGE *TextBuffer; + + TextBuffer = egCreateImage(FieldWidth, TEXT_LINE_HEIGHT, FALSE); + + egFillImage(TextBuffer, &MenuBackgroundPixel); + if (Selected) { + // draw selection bar background + egFillImageArea(TextBuffer, 0, 0, FieldWidth, TextBuffer->Height, &SelectionBackgroundPixel); + } + + // render the text + egRenderText(Text, TextBuffer, TEXT_XMARGIN, TEXT_YMARGIN); + egDrawImageWithTransparency(TextBuffer, NULL, XPos, YPos, TextBuffer->Width, TextBuffer->Height); +// BltImage(TextBuffer, XPos, YPos); +} + +static VOID DrawMainMenuText(IN CHAR16 *Text, IN UINTN XPos, IN UINTN YPos) +{ + UINTN TextWidth, TextPosX; + EG_IMAGE *TextBuffer; + + TextBuffer = egCropImage(GlobalConfig.ScreenBackground, XPos, YPos, LAYOUT_TEXT_WIDTH, TEXT_LINE_HEIGHT); // render the text - egRenderText(Text, TextBuffer, TEXT_XMARGIN, TEXT_YMARGIN); + egMeasureText(Text, &TextWidth, NULL); + if (TextWidth > TextBuffer->Width) + TextPosX = 0; + else + TextPosX = (TextBuffer->Width - TextWidth) / 2; + egRenderText(Text, TextBuffer, TextPosX, 0); egDrawImageWithTransparency(TextBuffer, NULL, XPos, YPos, TextBuffer->Width, TextBuffer->Height); -// BltImage(TextBuffer, XPos, YPos); } +// Compute the size & position of the window that will hold a subscreen's information. +static VOID ComputeSubScreenWindowSize(REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, UINTN *XPos, UINTN *YPos, UINTN *Width, UINTN *Height, UINTN *LineWidth) { + UINTN i, ItemWidth, HintTop, BannerBottomEdge, TitleWidth, CenteredTop; + + *Width = 1; + *Height = 5; + TitleWidth = StrLen(Screen->Title); + if ((Screen->TitleImage) && (TitleWidth > (Screen->TitleImage->Width / FONT_CELL_WIDTH))) { + TitleWidth -= (Screen->TitleImage->Width / FONT_CELL_WIDTH); + } + if (TitleWidth > *Width) { + *Width = TitleWidth; + } + for (i = 0; i < Screen->InfoLineCount; i++) { + ItemWidth = StrLen(Screen->InfoLines[i]); + if (*Width < ItemWidth) { + *Width = ItemWidth; + } + (*Height)++; + } + for (i = 0; i <= State->MaxIndex; i++) { + ItemWidth = StrLen(Screen->Entries[i]->Title); + if (*Width < ItemWidth) { + *Width = ItemWidth; + } + (*Height)++; + } + *Width = TEXT_XMARGIN * 2 + *Width * FONT_CELL_WIDTH; + *LineWidth = *Width; + if (Screen->TitleImage) + *Width += (Screen->TitleImage->Width + TITLEICON_SPACING + FONT_CELL_WIDTH); + else + *Width += FONT_CELL_WIDTH; + + // Keep it within the bounds of the screen, or 2/3 of the screen's width + // for screens over 800 pixels wide + if (*Width > UGAWidth) + *Width = UGAWidth; + if ((*Width > (2 * UGAWidth) / 3) && (UGAWidth > 800)) + *Width = (2 * UGAWidth) / 3; + + *XPos = (UGAWidth - *Width) / 2; + + HintTop = UGAHeight - (FONT_CELL_HEIGHT * 3); // top of hint text + *Height *= TEXT_LINE_HEIGHT; + if (Screen->TitleImage && (*Height < (Screen->TitleImage->Height + TEXT_LINE_HEIGHT * 3))) + *Height = Screen->TitleImage->Height + TEXT_LINE_HEIGHT * 3; + + if (GlobalConfig.BannerBottomEdge >= HintTop) { // probably a full-screen image; treat it as an empty banner + BannerBottomEdge = 0; + } else { + BannerBottomEdge = GlobalConfig.BannerBottomEdge; + } + if (*Height > (HintTop -BannerBottomEdge - FONT_CELL_HEIGHT * 2)) { + BannerBottomEdge = 0; + } + if (*Height > (HintTop -BannerBottomEdge - FONT_CELL_HEIGHT * 2)) { + // TODO: Implement scrolling in text screen. + *Height = (HintTop - BannerBottomEdge - FONT_CELL_HEIGHT * 2); + } + *YPos = BannerBottomEdge + FONT_CELL_HEIGHT + (HintTop - BannerBottomEdge - *Height) / 2; + // Above often produces a text field that feels bottom-weighted, so adjust + // upward a bit, if possible.... + CenteredTop = ((UGAHeight - *Height) / 2); + if ((*YPos > CenteredTop) && (CenteredTop > BannerBottomEdge)) + *YPos = CenteredTop; +} // VOID ComputeSubScreenWindowSize() + // Displays sub-menus static VOID GraphicsMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINTN Function, IN CHAR16 *ParamText) { INTN i; UINTN ItemWidth; - static UINTN MenuWidth, EntriesPosX, EntriesPosY, TimeoutPosY; + static UINTN LineWidth, MenuWidth, MenuHeight, EntriesPosX, EntriesPosY, TimeoutPosY; + EG_IMAGE *Window; + EG_PIXEL *BackgroundPixel = &(GlobalConfig.ScreenBackground->PixelData[0]); State->ScrollMode = SCROLL_MODE_TEXT; switch (Function) { case MENU_FUNCTION_INIT: InitScroll(State, Screen->EntryCount, 0); - - // determine width of the menu - MenuWidth = 20; // minimum - for (i = 0; i < (INTN)Screen->InfoLineCount; i++) { - ItemWidth = StrLen(Screen->InfoLines[i]); - if (MenuWidth < ItemWidth) - MenuWidth = ItemWidth; - } - for (i = 0; i <= State->MaxIndex; i++) { - ItemWidth = StrLen(Screen->Entries[i]->Title); - if (MenuWidth < ItemWidth) - MenuWidth = ItemWidth; - } - MenuWidth = TEXT_XMARGIN * 2 + MenuWidth * FONT_CELL_WIDTH; - if (MenuWidth > LAYOUT_TEXT_WIDTH) - MenuWidth = LAYOUT_TEXT_WIDTH; - - if (Screen->TitleImage) - EntriesPosX = (UGAWidth + (Screen->TitleImage->Width + TITLEICON_SPACING) - MenuWidth) >> 1; - else - EntriesPosX = (UGAWidth - MenuWidth) >> 1; - EntriesPosY = ComputeRow0PosX() + TEXT_LINE_HEIGHT * 2; + ComputeSubScreenWindowSize(Screen, State, &EntriesPosX, &EntriesPosY, &MenuWidth, &MenuHeight, &LineWidth); TimeoutPosY = EntriesPosY + (Screen->EntryCount + 1) * TEXT_LINE_HEIGHT; // initial painting SwitchToGraphicsAndClear(); + Window = egCreateFilledImage(MenuWidth, MenuHeight, FALSE, BackgroundPixel); + egDrawImage(Window, EntriesPosX, EntriesPosY); egMeasureText(Screen->Title, &ItemWidth, NULL); - DrawSubmenuText(Screen->Title, 0, ((UGAWidth - ItemWidth) >> 1) - TEXT_XMARGIN, EntriesPosY - TEXT_LINE_HEIGHT * 2); - if (Screen->TitleImage) - BltImage(Screen->TitleImage, EntriesPosX - (Screen->TitleImage->Width + TITLEICON_SPACING), EntriesPosY); + DrawSubmenuText(Screen->Title, FALSE, (StrLen(Screen->Title) + 2) * FONT_CELL_WIDTH, + EntriesPosX + (MenuWidth - ItemWidth) / 2, EntriesPosY += TEXT_LINE_HEIGHT); + if (Screen->TitleImage) { + BltImageAlpha(Screen->TitleImage, EntriesPosX, EntriesPosY + TEXT_LINE_HEIGHT * 2, BackgroundPixel); + EntriesPosX += (Screen->TitleImage->Width + TITLEICON_SPACING); + } + EntriesPosY += (TEXT_LINE_HEIGHT * 2); if (Screen->InfoLineCount > 0) { for (i = 0; i < (INTN)Screen->InfoLineCount; i++) { - DrawSubmenuText(Screen->InfoLines[i], 0, EntriesPosX, EntriesPosY); + DrawSubmenuText(Screen->InfoLines[i], FALSE, LineWidth, EntriesPosX, EntriesPosY); EntriesPosY += TEXT_LINE_HEIGHT; } EntriesPosY += TEXT_LINE_HEIGHT; // also add a blank line @@ -713,31 +785,27 @@ static VOID GraphicsMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *Sta case MENU_FUNCTION_PAINT_ALL: for (i = 0; i <= State->MaxIndex; i++) { - DrawSubmenuText(Screen->Entries[i]->Title, (i == State->CurrentSelection) ? MenuWidth : 0, - EntriesPosX, EntriesPosY + i * TEXT_LINE_HEIGHT); + DrawSubmenuText(Screen->Entries[i]->Title, (i == State->CurrentSelection), LineWidth, + EntriesPosX, EntriesPosY + i * TEXT_LINE_HEIGHT); } if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_HINTS)) { - if ((Screen->Hint1 != NULL) && (StrLen(Screen->Hint1) > 0)) { - DrawSubmenuText(Screen->Hint1, 0, (UGAWidth - (StrLen(Screen->Hint1) * FONT_CELL_WIDTH)) / 2, - UGAHeight - (FONT_CELL_HEIGHT * 3)); - } - if ((Screen->Hint2 != NULL) && (StrLen(Screen->Hint2) > 0)) { - DrawSubmenuText(Screen->Hint2, 0, (UGAWidth - (StrLen(Screen->Hint2) * FONT_CELL_WIDTH)) / 2, - UGAHeight - (FONT_CELL_HEIGHT * 2)); - } // if + if ((Screen->Hint1 != NULL) && (StrLen(Screen->Hint1) > 0)) + DrawMainMenuText(Screen->Hint1, (UGAWidth - LAYOUT_TEXT_WIDTH) / 2, UGAHeight - (FONT_CELL_HEIGHT * 3)); + if ((Screen->Hint2 != NULL) && (StrLen(Screen->Hint2) > 0)) + DrawMainMenuText(Screen->Hint2, (UGAWidth - LAYOUT_TEXT_WIDTH) / 2, UGAHeight - (FONT_CELL_HEIGHT * 2)); } // if break; case MENU_FUNCTION_PAINT_SELECTION: // redraw selection cursor - DrawSubmenuText(Screen->Entries[State->PreviousSelection]->Title, 0, + DrawSubmenuText(Screen->Entries[State->PreviousSelection]->Title, FALSE, LineWidth, EntriesPosX, EntriesPosY + State->PreviousSelection * TEXT_LINE_HEIGHT); - DrawSubmenuText(Screen->Entries[State->CurrentSelection]->Title, MenuWidth, + DrawSubmenuText(Screen->Entries[State->CurrentSelection]->Title, TRUE, LineWidth, EntriesPosX, EntriesPosY + State->CurrentSelection * TEXT_LINE_HEIGHT); break; case MENU_FUNCTION_PAINT_TIMEOUT: - DrawSubmenuText(ParamText, 0, EntriesPosX, TimeoutPosY); + DrawSubmenuText(ParamText, FALSE, LineWidth, EntriesPosX, TimeoutPosY); break; } @@ -764,22 +832,6 @@ static VOID DrawMainMenuEntry(REFIT_MENU_ENTRY *Entry, BOOLEAN selected, UINTN X } // if } // VOID DrawMainMenuEntry() -static VOID DrawMainMenuText(IN CHAR16 *Text, IN UINTN XPos, IN UINTN YPos) -{ - UINTN TextWidth, TextPosX; - - TextBuffer = egCropImage(GlobalConfig.ScreenBackground, XPos, YPos, LAYOUT_TEXT_WIDTH, TEXT_LINE_HEIGHT); - - // render the text - egMeasureText(Text, &TextWidth, NULL); - if (TextWidth > TextBuffer->Width) - TextPosX = 0; - else - TextPosX = (TextBuffer->Width - TextWidth) / 2; - egRenderText(Text, TextBuffer, TextPosX, 0); - egDrawImageWithTransparency(TextBuffer, NULL, XPos, YPos, TextBuffer->Width, TextBuffer->Height); -} - static VOID PaintAll(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, UINTN *itemPosX, UINTN row0PosY, UINTN row1PosY, UINTN textPosY) { INTN i; diff --git a/refind/screen.c b/refind/screen.c index b9e3c8f..7ee1a18 100644 --- a/refind/screen.c +++ b/refind/screen.c @@ -464,9 +464,9 @@ VOID BltClearScreen(IN BOOLEAN ShowBanner) if (Banner != NULL) { BannerPosX = (Banner->Width < UGAWidth) ? ((UGAWidth - Banner->Width) / 2) : 0; BannerPosY = (ComputeRow0PosX() / 2) - Banner->Height; -// BannerPosY = ComputeRow0PosX() - Banner->Height - LAYOUT_BANNER_YGAP; if (BannerPosY < 0) BannerPosY = 0; + GlobalConfig.BannerBottomEdge = BannerPosY + Banner->Height; BltImage(Banner, (UINTN) BannerPosX, (UINTN) BannerPosY); } -- 2.39.2