* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/*
+ * Modifications copyright (c) 2012-2013 Roderick W. Smith
+ *
+ * Modifications distributed under the terms of the GNU General Public
+ * License (GPL) version 3 (GPLv3), a copy of which must be distributed
+ * with this source code or binaries made from it.
+ *
+ */
#include "libegint.h"
#include "../refind/global.h"
EG_IMAGE * egCopyImage(IN EG_IMAGE *Image)
{
- EG_IMAGE *NewImage;
+ EG_IMAGE *NewImage = NULL;
- NewImage = egCreateImage(Image->Width, Image->Height, Image->HasAlpha);
+ if (Image != NULL)
+ NewImage = egCreateImage(Image->Width, Image->Height, Image->HasAlpha);
if (NewImage == NULL)
return NULL;
// Basic file operations
//
-EFI_STATUS egLoadFile(IN EFI_FILE* BaseDir, IN CHAR16 *FileName,
- OUT UINT8 **FileData, OUT UINTN *FileDataLength)
+EFI_STATUS egLoadFile(IN EFI_FILE* BaseDir, IN CHAR16 *FileName, OUT UINT8 **FileData, OUT UINTN *FileDataLength)
{
EFI_STATUS Status;
EFI_FILE_HANDLE FileHandle;
static EFI_GUID ESPGuid = { 0xc12a7328, 0xf81f, 0x11d2, { 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } };
-static EFI_STATUS egFindESP(OUT EFI_FILE_HANDLE *RootDir)
+EFI_STATUS egFindESP(OUT EFI_FILE_HANDLE *RootDir)
{
EFI_STATUS Status;
UINTN HandleCount = 0;
}
Status = refit_call5_wrapper(BaseDir->Open, BaseDir, &FileHandle, FileName,
- EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0);
+ EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0);
if (EFI_ERROR(Status))
return Status;
// Loading images from files and embedded data
//
-static CHAR16 * egFindExtension(IN CHAR16 *FileName)
-{
- UINTN i;
-
- for (i = StrLen(FileName); i >= 0; i--) {
- if (FileName[i] == '.')
- return FileName + i + 1;
- if (FileName[i] == '/' || FileName[i] == '\\')
- break;
- }
- 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.
+// Decode the specified image data. 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)
+static EG_IMAGE * egDecodeAny(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN IconSize, IN BOOLEAN WantAlpha)
{
EG_IMAGE *NewImage = NULL;
- // Note: The UEFI implementation in Gigabyte's Hybrid EFI is buggy and does
- // a case-sensitive comparison in StriCmp rather than the case-insensitive
- // comparison that the spec says should be done. As a workaround, we repeat
- // the comparison twice here.
- // dispatch by extension
- if ((StriCmp(Format, L"BMP") == 0) || (StriCmp(Format, L"bmp") == 0)) {
- NewImage = egDecodeBMP(FileData, FileDataLength, IconSize, WantAlpha);
- } else if ((StriCmp(Format, L"ICNS") == 0) || (StriCmp(Format, L"icns") == 0)) {
- NewImage = egDecodeICNS(FileData, FileDataLength, IconSize, WantAlpha);
- } else if ((StriCmp(Format, L"PNG") == 0) || (StriCmp(Format, L"png") == 0)) {
+ NewImage = egDecodeICNS(FileData, FileDataLength, IconSize, WantAlpha);
+ if (NewImage == NULL)
NewImage = egDecodePNG(FileData, FileDataLength, IconSize, WantAlpha);
- } // if/else
+ if (NewImage == NULL)
+ NewImage = egDecodeBMP(FileData, FileDataLength, IconSize, WantAlpha);
return NewImage;
}
return NULL;
// decode it
- NewImage = egDecodeAny(FileData, FileDataLength, egFindExtension(FileName), 128, WantAlpha);
+ NewImage = egDecodeAny(FileData, FileDataLength, 128, WantAlpha);
FreePool(FileData);
return NewImage;
}
// Load an icon from (BaseDir)/Path, extracting the icon of size IconSize x IconSize.
-// If the initial attempt is unsuccessful, try again, replacing the directory
-// component of Path with DEFAULT_ICONS_DIR.
-// Note: The assumption is that BaseDir points to rEFInd's home directory and Path
-// includes one subdirectory level. If this changes in future revisions, it may be
-// necessary to alter the code that tries again with DEFAULT_ICONS_DIR.
// Returns a pointer to the image data, or NULL if the icon could not be loaded.
EG_IMAGE * egLoadIcon(IN EFI_FILE* BaseDir, IN CHAR16 *Path, IN UINTN IconSize)
{
EFI_STATUS Status;
UINT8 *FileData;
UINTN FileDataLength;
- CHAR16 *FileName, FileName2[256];
EG_IMAGE *NewImage;
if (BaseDir == NULL || Path == NULL)
// load file
Status = egLoadFile(BaseDir, Path, &FileData, &FileDataLength);
- if (EFI_ERROR(Status)) {
- FileName = Basename(Path); // Note: FileName is a pointer within Path; DON'T FREE IT!
- SPrint(FileName2, 255, L"%s\\%s", DEFAULT_ICONS_DIR, FileName);
- Status = egLoadFile(BaseDir, FileName2, &FileData, &FileDataLength);
- if (EFI_ERROR(Status))
- return NULL;
- }
+ if (EFI_ERROR(Status))
+ return NULL;
// decode it
- NewImage = egDecodeAny(FileData, FileDataLength, egFindExtension(Path), IconSize, TRUE);
+ NewImage = egDecodeAny(FileData, FileDataLength, IconSize, TRUE);
FreePool(FileData);
if ((NewImage->Width != IconSize) || (NewImage->Height != IconSize)) {
Print(L"Warning: Attempt to load icon of the wrong size from '%s'\n", Path);
return NewImage;
} // EG_IMAGE *egLoadIcon()
-EG_IMAGE * egDecodeImage(IN UINT8 *FileData, IN UINTN FileDataLength, IN CHAR16 *Format, IN BOOLEAN WantAlpha)
-{
- return egDecodeAny(FileData, FileDataLength, Format, 128, WantAlpha);
-}
+// Returns an icon of any type from the specified subdirectory using the specified
+// base name. All directory references are relative to BaseDir. For instance, if
+// SubdirName is "myicons" and BaseName is "os_linux", this function will return
+// an image based on "myicons/os_linux.icns" or "myicons/os_linux.png", in that
+// order of preference. Returns NULL if no such file is a valid icon file.
+EG_IMAGE * egLoadIconAnyType(IN EFI_FILE *BaseDir, IN CHAR16 *SubdirName, IN CHAR16 *BaseName, IN UINTN IconSize) {
+ EG_IMAGE *Image = NULL;
+ CHAR16 *Extension;
+ CHAR16 FileName[256];
+ UINTN i = 0;
+
+ while (((Extension = FindCommaDelimited(ICON_EXTENSIONS, i++)) != NULL) && (Image == NULL)) {
+ SPrint(FileName, 255, L"%s\\%s.%s", SubdirName, BaseName, Extension);
+ Image = egLoadIcon(BaseDir, FileName, IconSize);
+ MyFreePool(Extension);
+ } // while()
+
+ return Image;
+} // EG_IMAGE *egLoadIconAnyType()
+
+// Returns an icon with any extension in ICON_EXTENSIONS from either the directory
+// specified by GlobalConfig.IconsDir or DEFAULT_ICONS_DIR. The input BaseName
+// should be the icon name without an extension. For instance, if BaseName is
+// os_linux, GlobalConfig.IconsDir is myicons, DEFAULT_ICONS_DIR is icons, and
+// ICON_EXTENSIONS is "icns,png", this function will return myicons/os_linux.icns,
+// myicons/os_linux.png, icons/os_linux.icns, or icons/os_linux.png, in that
+// order of preference. Returns NULL if no such icon can be found. All file
+// references are relative to SelfDir.
+EG_IMAGE * egFindIcon(IN CHAR16 *BaseName, IN UINTN IconSize) {
+ EG_IMAGE *Image = NULL;
+
+ if (GlobalConfig.IconsDir != NULL) {
+ Image = egLoadIconAnyType(SelfDir, GlobalConfig.IconsDir, BaseName, IconSize);
+ }
+
+ if (Image == NULL) {
+ Image = egLoadIconAnyType(SelfDir, DEFAULT_ICONS_DIR, BaseName, IconSize);
+ }
+
+ return Image;
+} // EG_IMAGE * egFindIcon()
EG_IMAGE * egPrepareEmbeddedImage(IN EG_EMBEDDED_IMAGE *EmbeddedImage, IN BOOLEAN WantAlpha)
{
// compose
if (CompWidth > 0) {
-// if (CompImage->HasAlpha) {
-// CompImage->HasAlpha = FALSE;
-// egSetPlane(PLPTR(CompImage, a), 0, CompImage->Width * CompImage->Height);
-// }
-
if (TopImage->HasAlpha) {
egRawCompose(CompImage->PixelData + PosY * CompImage->Width + PosX, TopImage->PixelData,
CompWidth, CompHeight, CompImage->Width, TopImage->Width);
CompWidth, CompHeight, CompImage->Width, TopImage->Width);
}
}
-}
+} /* VOID egComposeImage() */
EG_IMAGE * egEnsureImageSize(IN EG_IMAGE *Image, IN UINTN Width, IN UINTN Height, IN EG_PIXEL *Color)
{
egFreeImage(Image);
return NULL;
}
+ Image->HasAlpha = FALSE;
egComposeImage(NewImage, Image, 0, 0);
egFreeImage(Image);