support for VolumeIcon.icns

Signed-off-by: SergeySlice <sergey.slice@gmail.com>
This commit is contained in:
SergeySlice 2020-03-15 14:06:04 +03:00
parent 4b8b175619
commit 9ab5a63908
6 changed files with 304 additions and 287 deletions

View File

@ -4222,6 +4222,8 @@ InitTheme(
GlobalConfig.TypeSVG = FALSE;
GlobalConfig.BootCampStyle = FALSE;
GlobalConfig.Scale = 1.0f;
GlobalConfig.BannerPosX = 0;
GlobalConfig.BannerPosY = 0;
if (DayLight) {
DBG("use daylight theme\n");

View File

@ -841,46 +841,6 @@ EG_IMAGE * egEnsureImageSize(IN EG_IMAGE *Image, IN INTN Width, IN INTN Height,
//
// misc internal functions
//
//these functions used for icns, not with png
VOID egInsertPlane(IN UINT8 *SrcDataPtr, IN UINT8 *DestPlanePtr, IN UINTN PixelCount)
{
UINTN i;
if (!SrcDataPtr || !DestPlanePtr) {
return;
}
for (i = 0; i < PixelCount; i++) {
*DestPlanePtr = *SrcDataPtr++;
DestPlanePtr += 4;
}
}
VOID egSetPlane(IN UINT8 *DestPlanePtr, IN UINT8 Value, IN UINT64 PixelCount)
{
UINT64 i;
if (!DestPlanePtr) {
return;
}
for (i = 0; i < PixelCount; i++) {
*DestPlanePtr = Value;
DestPlanePtr += 4;
}
}
VOID egCopyPlane(IN UINT8 *SrcPlanePtr, IN UINT8 *DestPlanePtr, IN UINTN PixelCount)
{
UINTN i;
if (!SrcPlanePtr || !DestPlanePtr) {
return;
}
for (i = 0; i < PixelCount; i++) {
*DestPlanePtr = *SrcPlanePtr;
DestPlanePtr += 4; SrcPlanePtr += 4;
}
}
EG_IMAGE * egDecodePNG(IN UINT8 *FileData, IN UINTN FileDataLength, IN BOOLEAN WantAlpha) {
EG_IMAGE *NewImage = NULL;

View File

@ -174,7 +174,7 @@ VOID egRawComposeOnFlat(IN OUT EG_PIXEL *CompBasePtr, IN EG_PIXEL *TopBasePtr,
//VOID egCopyPlane(IN UINT8 *SrcPlanePtr, IN UINT8 *DestPlanePtr, IN UINTN PixelCount);
//EG_IMAGE * egDecodeBMP(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN IconSize, IN BOOLEAN WantAlpha);
//EG_IMAGE * egDecodeICNS(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN IconSize, IN BOOLEAN WantAlpha);
EG_IMAGE * egDecodeICNS(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN IconSize, IN BOOLEAN WantAlpha);
EG_IMAGE * egDecodePNG(IN UINT8 *FileData, IN UINTN FileDataLength, IN BOOLEAN WantAlpha);

527
rEFIt_UEFI/libeg/load_icns.cpp Normal file → Executable file
View File

@ -1,246 +1,285 @@
///*
// * libeg/load_icns.c
// * Loading function for .icns Apple icon images
// *
// * Copyright (c) 2006 Christoph Pfisterer
// * All rights reserved.
// *
// * Redistribution and use in source and binary forms, with or without
// * modification, are permitted provided that the following conditions are
// * met:
// *
// * * Redistributions of source code must retain the above copyright
// * notice, this list of conditions and the following disclaimer.
// *
// * * Redistributions in binary form must reproduce the above copyright
// * notice, this list of conditions and the following disclaimer in the
// * documentation and/or other materials provided with the
// * distribution.
// *
// * * Neither the name of Christoph Pfisterer nor the names of the
// * contributors may be used to endorse or promote products derived
// * from this software without specific prior written permission.
// *
// * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// */
////#if !defined(LODEPNG)
//#include "libegint.h"
/*
* libeg/load_icns.c
* Loading function for .icns Apple icon images
*
* Copyright (c) 2006 Christoph Pfisterer
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Christoph Pfisterer nor the names of the
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//#if !defined(LODEPNG)
#include "libegint.h"
#ifndef DEBUG_ALL
#define DEBUG_IMG 0
#else
#define DEBUG_IMG DEBUG_ALL
#endif
#if DEBUG_IMG == 0
#define DBG(...)
#else
#define DBG(...) DebugLog(DEBUG_IMG, __VA_ARGS__)
#endif
#define PLPTR(imagevar, colorname) ((UINT8 *) &((imagevar)->PixelData->colorname))
//these functions used for icns, not with png
VOID egInsertPlane(IN UINT8 *SrcDataPtr, IN UINT8 *DestPlanePtr, IN UINTN PixelCount)
{
UINTN i;
if (!SrcDataPtr || !DestPlanePtr) {
return;
}
for (i = 0; i < PixelCount; i++) {
*DestPlanePtr = *SrcDataPtr++;
DestPlanePtr += 4;
}
}
VOID egSetPlane(IN UINT8 *DestPlanePtr, IN UINT8 Value, IN UINT64 PixelCount)
{
UINT64 i;
if (!DestPlanePtr) {
return;
}
for (i = 0; i < PixelCount; i++) {
*DestPlanePtr = Value;
DestPlanePtr += 4;
}
}
VOID egCopyPlane(IN UINT8 *SrcPlanePtr, IN UINT8 *DestPlanePtr, IN UINTN PixelCount)
{
UINTN i;
if (!SrcPlanePtr || !DestPlanePtr) {
return;
}
for (i = 0; i < PixelCount; i++) {
*DestPlanePtr = *SrcPlanePtr;
DestPlanePtr += 4; SrcPlanePtr += 4;
}
}
//
//#ifndef DEBUG_ALL
//#define DEBUG_IMG 0
//#else
//#define DEBUG_IMG DEBUG_ALL
// Decompress .icns RLE data
//
VOID egDecompressIcnsRLE(IN OUT UINT8 **CompData, IN OUT UINTN *CompLen, IN UINT8 *PixelData, IN UINTN PixelCount)
{
UINT8 *cp;
UINT8 *cp_end;
UINT8 *pp;
UINTN pp_left;
UINTN len, i;
UINT8 value;
// setup variables
cp = *CompData;
cp_end = cp + *CompLen;
pp = PixelData;
pp_left = PixelCount;
// decode
while (cp + 1 < cp_end && pp_left > 0) {
len = *cp++;
if (len & 0x80) { // compressed data: repeat next byte
len -= 125;
if (len > pp_left)
break;
value = *cp++;
for (i = 0; i < len; i++) {
*pp = value;
pp += 4;
}
} else { // uncompressed data: copy bytes
len++;
if (len > pp_left || cp + len > cp_end)
break;
for (i = 0; i < len; i++) {
*pp = *cp++;
pp += 4;
}
}
pp_left -= len;
}
if (pp_left > 0) {
DBG(" egDecompressIcnsRLE: still need %d bytes of pixel data\n", pp_left);
}
// record what's left of the compressed data stream
*CompData = cp;
*CompLen = (UINTN)(cp_end - cp);
}
//
// Load Apple .icns icons
//
EG_IMAGE * egDecodeICNS(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN IconSize, IN BOOLEAN WantAlpha)
{
EG_IMAGE *NewImage;
UINT8 *Ptr, *BufferEnd, *DataPtr, *MaskPtr;
UINT32 BlockLen, DataLen, MaskLen;
UINTN FetchPixelSize, PixelCount, i;
UINT8 *CompData;
UINTN CompLen;
UINT8 *SrcPtr;
EG_PIXEL *DestPtr;
if (FileDataLength < 8 || FileData == NULL ||
FileData[0] != 'i' || FileData[1] != 'c' || FileData[2] != 'n' || FileData[3] != 's') {
// not an icns file...
DBG("not icns\n");
return NULL;
}
FetchPixelSize = IconSize;
for (;;) {
DataPtr = NULL;
DataLen = 0;
MaskPtr = NULL;
MaskLen = 0;
Ptr = FileData + 8;
BufferEnd = FileData + FileDataLength;
// iterate over tagged blocks in the file
while (Ptr + 8 <= BufferEnd) {
BlockLen = ((UINT32)Ptr[4] << 24) + ((UINT32)Ptr[5] << 16) + ((UINT32)Ptr[6] << 8) + (UINT32)Ptr[7];
if (Ptr + BlockLen > BufferEnd) // block continues beyond end of file
break;
// extract the appropriate blocks for each pixel size
if (FetchPixelSize == 128) {
if (Ptr[0] == 'i' && Ptr[1] == 't' && Ptr[2] == '3' && Ptr[3] == '2') {
if (Ptr[8] == 0 && Ptr[9] == 0 && Ptr[10] == 0 && Ptr[11] == 0) {
DataPtr = Ptr + 12;
DataLen = BlockLen - 12;
}
} else if (Ptr[0] == 't' && Ptr[1] == '8' && Ptr[2] == 'm' && Ptr[3] == 'k') {
MaskPtr = Ptr + 8;
MaskLen = BlockLen - 8;
}
} else if (FetchPixelSize == 48) {
if (Ptr[0] == 'i' && Ptr[1] == 'h' && Ptr[2] == '3' && Ptr[3] == '2') {
DataPtr = Ptr + 8;
DataLen = BlockLen - 8;
} else if (Ptr[0] == 'h' && Ptr[1] == '8' && Ptr[2] == 'm' && Ptr[3] == 'k') {
MaskPtr = Ptr + 8;
MaskLen = BlockLen - 8;
}
} else if (FetchPixelSize == 32) {
if (Ptr[0] == 'i' && Ptr[1] == 'l' && Ptr[2] == '3' && Ptr[3] == '2') {
DataPtr = Ptr + 8;
DataLen = BlockLen - 8;
} else if (Ptr[0] == 'l' && Ptr[1] == '8' && Ptr[2] == 'm' && Ptr[3] == 'k') {
MaskPtr = Ptr + 8;
MaskLen = BlockLen - 8;
}
} else if (FetchPixelSize == 16) {
if (Ptr[0] == 'i' && Ptr[1] == 's' && Ptr[2] == '3' && Ptr[3] == '2') {
DataPtr = Ptr + 8;
DataLen = BlockLen - 8;
} else if (Ptr[0] == 's' && Ptr[1] == '8' && Ptr[2] == 'm' && Ptr[3] == 'k') {
MaskPtr = Ptr + 8;
MaskLen = BlockLen - 8;
}
}
Ptr += BlockLen;
}
//TODO - take different larger size if not found
// FUTURE: try to load a different size and scale it later
if (DataPtr == NULL && FetchPixelSize == 128) {
FetchPixelSize = 32;
continue;
}
break;
}
if (DataPtr == NULL) {
DBG("not found such IconSize\n");
return NULL; // no image found
}
// allocate image structure and buffer
NewImage = egCreateImage(FetchPixelSize, FetchPixelSize, WantAlpha);
if (NewImage == NULL)
return NULL;
PixelCount = FetchPixelSize * FetchPixelSize;
if (DataLen < PixelCount * 3) {
// pixel data is compressed, RGB planar
CompData = DataPtr;
CompLen = DataLen;
egDecompressIcnsRLE(&CompData, &CompLen, PLPTR(NewImage, r), PixelCount);
egDecompressIcnsRLE(&CompData, &CompLen, PLPTR(NewImage, g), PixelCount);
egDecompressIcnsRLE(&CompData, &CompLen, PLPTR(NewImage, b), PixelCount);
// possible assertion: CompLen == 0
if (CompLen > 0) {
DBG(" egLoadICNSIcon: %d bytes of compressed data left\n", CompLen);
}
} else {
// pixel data is uncompressed, RGB interleaved
SrcPtr = DataPtr;
DestPtr = NewImage->PixelData;
for (i = 0; i < PixelCount; i++, DestPtr++) {
DestPtr->r = *SrcPtr++;
DestPtr->g = *SrcPtr++;
DestPtr->b = *SrcPtr++;
}
}
// add/set alpha plane
if (MaskPtr != NULL && MaskLen >= PixelCount && WantAlpha)
egInsertPlane(MaskPtr, PLPTR(NewImage, a), PixelCount);
else
egSetPlane(PLPTR(NewImage, a), WantAlpha ? 255 : 0, PixelCount);
// FUTURE: scale to originally requested size if we had to load another size
return NewImage;
}
//#endif
//
//#if DEBUG_IMG == 0
//#define DBG(...)
//#else
//#define DBG(...) DebugLog(DEBUG_IMG, __VA_ARGS__)
//#endif
//
//
////
//// Decompress .icns RLE data
////
//
//VOID egDecompressIcnsRLE(IN OUT UINT8 **CompData, IN OUT UINTN *CompLen, IN UINT8 *PixelData, IN UINTN PixelCount)
//{
// UINT8 *cp;
// UINT8 *cp_end;
// UINT8 *pp;
// UINTN pp_left;
// UINTN len, i;
// UINT8 value;
//
// // setup variables
// cp = *CompData;
// cp_end = cp + *CompLen;
// pp = PixelData;
// pp_left = PixelCount;
//
// // decode
// while (cp + 1 < cp_end && pp_left > 0) {
// len = *cp++;
// if (len & 0x80) { // compressed data: repeat next byte
// len -= 125;
// if (len > pp_left)
// break;
// value = *cp++;
// for (i = 0; i < len; i++) {
// *pp = value;
// pp += 4;
// }
// } else { // uncompressed data: copy bytes
// len++;
// if (len > pp_left || cp + len > cp_end)
// break;
// for (i = 0; i < len; i++) {
// *pp = *cp++;
// pp += 4;
// }
// }
// pp_left -= len;
// }
//
// if (pp_left > 0) {
// DBG(" egDecompressIcnsRLE: still need %d bytes of pixel data\n", pp_left);
// }
//
// // record what's left of the compressed data stream
// *CompData = cp;
// *CompLen = (UINTN)(cp_end - cp);
//}
//
////
//// Load Apple .icns icons
////
//
//EG_IMAGE * egDecodeICNS(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN IconSize, IN BOOLEAN WantAlpha)
//{
// EG_IMAGE *NewImage;
// UINT8 *Ptr, *BufferEnd, *DataPtr, *MaskPtr;
// UINT32 BlockLen, DataLen, MaskLen;
// UINTN FetchPixelSize, PixelCount, i;
// UINT8 *CompData;
// UINTN CompLen;
// UINT8 *SrcPtr;
// EG_PIXEL *DestPtr;
//
// if (FileDataLength < 8 || FileData == NULL ||
// FileData[0] != 'i' || FileData[1] != 'c' || FileData[2] != 'n' || FileData[3] != 's') {
// // not an icns file...
// DBG("not icns\n");
// return NULL;
// }
//
// FetchPixelSize = IconSize;
// for (;;) {
// DataPtr = NULL;
// DataLen = 0;
// MaskPtr = NULL;
// MaskLen = 0;
//
// Ptr = FileData + 8;
// BufferEnd = FileData + FileDataLength;
// // iterate over tagged blocks in the file
// while (Ptr + 8 <= BufferEnd) {
// BlockLen = ((UINT32)Ptr[4] << 24) + ((UINT32)Ptr[5] << 16) + ((UINT32)Ptr[6] << 8) + (UINT32)Ptr[7];
// if (Ptr + BlockLen > BufferEnd) // block continues beyond end of file
// break;
//
// // extract the appropriate blocks for each pixel size
// if (FetchPixelSize == 128) {
// if (Ptr[0] == 'i' && Ptr[1] == 't' && Ptr[2] == '3' && Ptr[3] == '2') {
// if (Ptr[8] == 0 && Ptr[9] == 0 && Ptr[10] == 0 && Ptr[11] == 0) {
// DataPtr = Ptr + 12;
// DataLen = BlockLen - 12;
// }
// } else if (Ptr[0] == 't' && Ptr[1] == '8' && Ptr[2] == 'm' && Ptr[3] == 'k') {
// MaskPtr = Ptr + 8;
// MaskLen = BlockLen - 8;
// }
//
// } else if (FetchPixelSize == 48) {
// if (Ptr[0] == 'i' && Ptr[1] == 'h' && Ptr[2] == '3' && Ptr[3] == '2') {
// DataPtr = Ptr + 8;
// DataLen = BlockLen - 8;
// } else if (Ptr[0] == 'h' && Ptr[1] == '8' && Ptr[2] == 'm' && Ptr[3] == 'k') {
// MaskPtr = Ptr + 8;
// MaskLen = BlockLen - 8;
// }
//
// } else if (FetchPixelSize == 32) {
// if (Ptr[0] == 'i' && Ptr[1] == 'l' && Ptr[2] == '3' && Ptr[3] == '2') {
// DataPtr = Ptr + 8;
// DataLen = BlockLen - 8;
// } else if (Ptr[0] == 'l' && Ptr[1] == '8' && Ptr[2] == 'm' && Ptr[3] == 'k') {
// MaskPtr = Ptr + 8;
// MaskLen = BlockLen - 8;
// }
//
// } else if (FetchPixelSize == 16) {
// if (Ptr[0] == 'i' && Ptr[1] == 's' && Ptr[2] == '3' && Ptr[3] == '2') {
// DataPtr = Ptr + 8;
// DataLen = BlockLen - 8;
// } else if (Ptr[0] == 's' && Ptr[1] == '8' && Ptr[2] == 'm' && Ptr[3] == 'k') {
// MaskPtr = Ptr + 8;
// MaskLen = BlockLen - 8;
// }
//
// }
//
// Ptr += BlockLen;
// }
// //TODO - take different larger size if not found
// // FUTURE: try to load a different size and scale it later
// if (DataPtr == NULL && FetchPixelSize == 128) {
// FetchPixelSize = 32;
// continue;
// }
//
// break;
// }
//
// if (DataPtr == NULL) {
// DBG("not found such IconSize\n");
// return NULL; // no image found
// }
//
// // allocate image structure and buffer
// NewImage = egCreateImage(FetchPixelSize, FetchPixelSize, WantAlpha);
// if (NewImage == NULL)
// return NULL;
// PixelCount = FetchPixelSize * FetchPixelSize;
//
// if (DataLen < PixelCount * 3) {
//
// // pixel data is compressed, RGB planar
// CompData = DataPtr;
// CompLen = DataLen;
// egDecompressIcnsRLE(&CompData, &CompLen, &NewImage->PixelData->r, PixelCount);
// egDecompressIcnsRLE(&CompData, &CompLen, &NewImage->PixelData->g, PixelCount);
// egDecompressIcnsRLE(&CompData, &CompLen, &NewImage->PixelData->b, PixelCount);
// // possible assertion: CompLen == 0
// if (CompLen > 0) {
// DBG(" egLoadICNSIcon: %d bytes of compressed data left\n", CompLen);
// }
//
// } else {
//
// // pixel data is uncompressed, RGB interleaved
// SrcPtr = DataPtr;
// DestPtr = NewImage->PixelData;
// for (i = 0; i < PixelCount; i++, DestPtr++) {
// DestPtr->r = *SrcPtr++;
// DestPtr->g = *SrcPtr++;
// DestPtr->b = *SrcPtr++;
// }
//
// }
//
// // Jief : not sure where they should define TODO !
// extern VOID egInsertPlane(IN UINT8 *SrcDataPtr, IN UINT8 *DestPlanePtr, IN UINTN PixelCount);
// extern VOID egSetPlane(IN UINT8 *DestPlanePtr, IN UINT8 Value, IN UINT64 PixelCount);
//
// // add/set alpha plane
// if (MaskPtr != NULL && MaskLen >= PixelCount && WantAlpha)
// egInsertPlane(MaskPtr, &NewImage->PixelData->a, PixelCount);
// else
// egSetPlane(&NewImage->PixelData->a, WantAlpha ? 255 : 0, PixelCount);
//
// // FUTURE: scale to originally requested size if we had to load another size
//
// return NewImage;
//}
////#endif
///* EOF */
/* EOF */

View File

@ -76,7 +76,7 @@
libeg/BmLib.cpp
libeg/image.cpp
# libeg/load_bmp.cpp
# libeg/load_icns.cpp
libeg/load_icns.cpp
libeg/libscreen.cpp
libeg/lodepng.cpp
libeg/lodepng.h

View File

@ -378,7 +378,23 @@ EG_IMAGE * LoadIcns(IN EFI_FILE_HANDLE BaseDir, IN CONST CHAR16 *FileName, IN UI
if (GlobalConfig.TextOnly) // skip loading if it's not used anyway
return NULL;
if (BaseDir) {
return egLoadIcon(BaseDir, FileName, PixelSize);
EFI_STATUS Status = EFI_NOT_FOUND;
UINT8 *FileData = NULL;
UINTN FileDataLength = 0;
EG_IMAGE *NewImage;
// load file
Status = egLoadFile(BaseDir, FileName, &FileData, &FileDataLength);
if (EFI_ERROR(Status)) {
return NULL;
}
// decode it
NewImage = egDecodeICNS(FileData, FileDataLength, PixelSize, TRUE);
FreePool(FileData);
return NewImage;
}
return DummyImage(PixelSize);
}