]> code.delx.au - refind/blobdiff - refind/icns.c
Refinements to PNG support.
[refind] / refind / icns.c
index 54a3ea7f1599099c9a0af7ea2f1f0111174f1778..0f55c8d207967ab7c4efdd3e5fbb2b07f846a3ae 100644 (file)
@@ -38,6 +38,7 @@
 #include "lib.h"
 #include "icns.h"
 #include "config.h"
+#include "../refind/screen.h"
 
 //
 // well-known icons
 
 typedef struct {
     EG_IMAGE    *Image;
-    CHAR16      *Path;
+    CHAR16      *FileName;
     UINTN       PixelSize;
 } BUILTIN_ICON;
 
 BUILTIN_ICON BuiltinIconTable[BUILTIN_ICON_COUNT] = {
-    { NULL, L"icons\\func_about.icns", 48 },
-    { NULL, L"icons\\func_reset.icns", 48 },
-    { NULL, L"icons\\func_shutdown.icns", 48 },
-    { NULL, L"icons\\tool_shell.icns", 48 },
-    { NULL, L"icons\\tool_part.icns", 48 },
-    { NULL, L"icons\\tool_rescue.icns", 48 },
-    { NULL, L"icons\\vol_internal.icns", 32 },
-    { NULL, L"icons\\vol_external.icns", 32 },
-    { NULL, L"icons\\vol_optical.icns", 32 },
+   { NULL, L"func_about.icns", 48 },
+   { NULL, L"func_reset.icns", 48 },
+   { NULL, L"func_shutdown.icns", 48 },
+   { NULL, L"func_exit.icns", 48 },
+   { NULL, L"tool_shell.icns", 48 },
+   { NULL, L"tool_part.icns", 48 },
+   { NULL, L"tool_rescue.icns", 48 },
+   { NULL, L"tool_apple_rescue.icns", 48 },
+   { NULL, L"tool_mok_tool.icns", 48 },
+   { NULL, L"vol_internal.icns", 32 },
+   { NULL, L"vol_external.icns", 32 },
+   { NULL, L"vol_optical.icns", 32 },
 };
 
 EG_IMAGE * BuiltinIcon(IN UINTN Id)
 {
+    CHAR16 FileName[256];
+
     if (Id >= BUILTIN_ICON_COUNT)
         return NULL;
-    
-    if (BuiltinIconTable[Id].Image == NULL)
-        BuiltinIconTable[Id].Image = LoadIcnsFallback(SelfDir, BuiltinIconTable[Id].Path, BuiltinIconTable[Id].PixelSize);
-    
+
+    if (BuiltinIconTable[Id].Image == NULL) {
+        SPrint(FileName, 255, L"%s\\%s", GlobalConfig.IconsDir ? GlobalConfig.IconsDir : DEFAULT_ICONS_DIR,
+               BuiltinIconTable[Id].FileName);
+        BuiltinIconTable[Id].Image = LoadIcnsFallback(SelfDir, FileName, BuiltinIconTable[Id].PixelSize);
+    } // if
+
     return BuiltinIconTable[Id].Image;
 }
 
+// Construct filename for all valid icon extensions and try to load it.
+// Returns image data or NULL if it can't be found.
+static EG_IMAGE * LoadIconAnyFormat(IN CHAR16 *IconsDir, IN CHAR16 *BaseName, IN CHAR16 *OsName) {
+   CHAR16     FileName[256];
+   CHAR16     *Extension;
+   EG_IMAGE   *Image = NULL;
+   UINTN      Index = 0;
+
+   while (((Extension = FindCommaDelimited(ICON_EXTENSIONS, Index++)) != NULL) && (Image == NULL)) {
+      SPrint(FileName, 255, L"%s\\%s_%s.%s", IconsDir, BaseName, OsName, Extension);
+
+      // try to load it
+      Image = egLoadIcon(SelfDir, FileName, 128);
+      MyFreePool(Extension);
+   } // while()
+   return Image;
+} // EG_IMAGE * LoadIconAnyFormat()
+
 //
 // Load an icon for an operating system
 //
 
+// Load an OS icon from among the comma-delimited list provided in OSIconName.
+// Searches for icons with extensions in the ICON_EXTENSIONS list (via
+// LoadIconAnyFormat()).
+// Returns image data. On failure, returns an ugly "dummy" icon.
 EG_IMAGE * LoadOSIcon(IN CHAR16 *OSIconName OPTIONAL, IN CHAR16 *FallbackIconName, BOOLEAN BootLogo)
 {
-    EG_IMAGE        *Image;
-    CHAR16          CutoutName[16];
-    CHAR16          FileName[256];
-    UINTN           StartIndex, Index, NextIndex;
+    EG_IMAGE        *Image = NULL;
+    CHAR16          *CutoutName;
+    UINTN           Index = 0;
 
     if (GlobalConfig.TextOnly)      // skip loading if it's not used anyway
         return NULL;
-    Image = NULL;
 
     // try the names from OSIconName
-    for (StartIndex = 0; OSIconName != NULL && OSIconName[StartIndex]; StartIndex = NextIndex) {
-        // find the next name in the list
-        NextIndex = 0;
-        for (Index = StartIndex; OSIconName[Index]; Index++) {
-            if (OSIconName[Index] == ',') {
-                NextIndex = Index + 1;
-                break;
-            }
-        }
-        if (OSIconName[Index] == 0)
-            NextIndex = Index;
-        
-        // construct full path
-        if (Index > StartIndex + 15)   // prevent buffer overflow
-            continue;
-        CopyMem(CutoutName, OSIconName + StartIndex, (Index - StartIndex) * sizeof(CHAR16));
-        CutoutName[Index - StartIndex] = 0;
-        SPrint(FileName, 255, L"icons\\%s_%s.icns",
-               BootLogo ? L"boot" : L"os", CutoutName);
-        
-        // try to load it
-        Image = egLoadIcon(SelfDir, FileName, 128);
-        if (Image != NULL)
-            return Image;
-    }
+    while (((CutoutName = FindCommaDelimited(OSIconName, Index++)) != NULL) && (Image == NULL)) {
+       Image = LoadIconAnyFormat(GlobalConfig.IconsDir ? GlobalConfig.IconsDir : DEFAULT_ICONS_DIR,
+                                 BootLogo ? L"boot" : L"os", CutoutName);
+       MyFreePool(CutoutName);
+    } // while()
 
     // try the fallback name
-    SPrint(FileName, 255, L"icons\\%s_%s.icns",
-           BootLogo ? L"boot" : L"os", FallbackIconName);
-    Image = egLoadIcon(SelfDir, FileName, 128);
+    if (Image == NULL)
+       Image = LoadIconAnyFormat(GlobalConfig.IconsDir ? GlobalConfig.IconsDir : DEFAULT_ICONS_DIR,
+                                 BootLogo ? L"boot" : L"os", FallbackIconName);
+
+    // try the fallback name with os_ instead of boot_
+    if (BootLogo && (Image == NULL))
+       Image = LoadIconAnyFormat(GlobalConfig.IconsDir ? GlobalConfig.IconsDir : DEFAULT_ICONS_DIR,
+                                 L"os", FallbackIconName);
+
     if (Image != NULL)
         return Image;
-    
-    // try the fallback name with os_ instead of boot_
-    if (BootLogo)
-        return LoadOSIcon(NULL, FallbackIconName, FALSE);
-    
-    return DummyImage(128);
-}
+    else
+       return DummyImage(128);
+} /* EG_IMAGE * LoadOSIcon() */
 
-//
-// Load an image from a .icns file
-//
 
-EG_IMAGE * LoadIcns(IN EFI_FILE_HANDLE BaseDir, IN CHAR16 *FileName, IN UINTN PixelSize)
-{
-    if (GlobalConfig.TextOnly)      // skip loading if it's not used anyway
-        return NULL;
-    return egLoadIcon(BaseDir, FileName, PixelSize);
-}
+// Load an image from a .icns or .png file. FileNames contains a comma-delimited
+// list of potential filanems; the function tries each in turn until it finds
+// a loadable icon. If no file has a valid icon, it returns NULL.
+EG_IMAGE * LoadIcns(IN EFI_FILE_HANDLE BaseDir, IN CHAR16 *FileNames, IN UINTN PixelSize) {
+   CHAR16   *FileName;
+   EG_IMAGE *Image = NULL;
+   UINTN    Index = 0;
+
+   if (GlobalConfig.TextOnly)      // skip loading if it's not used anyway
+      return NULL;
+
+   while (((FileName = FindCommaDelimited(FileNames, Index++)) != NULL) && (Image == NULL)) {
+      Image = egLoadIcon(BaseDir, FileName, PixelSize);
+   }
+   return Image;
+} // EG_IMAGE * LoadIcns()
 
 static EG_PIXEL BlackPixel  = { 0x00, 0x00, 0x00, 0 };
 //static EG_PIXEL YellowPixel = { 0x00, 0xff, 0xff, 0 };
@@ -147,11 +165,11 @@ EG_IMAGE * DummyImage(IN UINTN PixelSize)
     EG_IMAGE        *Image;
     UINTN           x, y, LineOffset;
     CHAR8           *Ptr, *YPtr;
-    
+
     Image = egCreateFilledImage(PixelSize, PixelSize, TRUE, &BlackPixel);
-    
+
     LineOffset = PixelSize * 4;
-    
+
     YPtr = (CHAR8 *)Image->PixelData + ((PixelSize - 32) >> 1) * (LineOffset + 4);
     for (y = 0; y < 32; y++) {
         Ptr = YPtr;
@@ -169,7 +187,7 @@ EG_IMAGE * DummyImage(IN UINTN PixelSize)
         }
         YPtr += LineOffset;
     }
-    
+
     return Image;
 }