795 lines
21 KiB
C
795 lines
21 KiB
C
/** @file
|
|
The instance of GIF Decoder Library
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2020, Insyde Software Corp. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
*/
|
|
|
|
#include "H2OImageDecoderLibCommon.h"
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/TimerLib.h>
|
|
#include <Protocol/Cpu.h>
|
|
#include "Gif.h"
|
|
|
|
UINT8 *mOutStack = NULL;
|
|
LZW_ENTRY *mLzwTable = NULL;
|
|
|
|
STATIC
|
|
VOID
|
|
FixColorMapForTransparent(
|
|
UINT32 SizeOfColorTable,
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ColorMap
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
UINT32 MapSize;
|
|
|
|
//
|
|
// in 24bit mode, (0,0,0) is transparent; (0,0,1) drak red is black
|
|
//
|
|
MapSize = 1 << (SizeOfColorTable + 1);
|
|
for (Index = 0; Index < MapSize; Index++) {
|
|
if (ColorMap[Index].Blue == 0 &&
|
|
ColorMap[Index].Green == 0 &&
|
|
ColorMap[Index].Red == 0) {
|
|
ColorMap[Index].Red = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
Calculate the frequency.
|
|
|
|
@param Frequency
|
|
|
|
@retval EFI_SUCCESS The frequency is calculated.
|
|
@return other Some error occurs.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
GetFrequency (
|
|
UINT64 *Frequency
|
|
)
|
|
{
|
|
*Frequency = GetPerformanceCounterProperties (NULL, NULL);
|
|
*Frequency = DivU64x32 (*Frequency, 1000);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Create animation from file image buffer
|
|
|
|
@param [in] FileData
|
|
@param [in] FileSize
|
|
@param [in] Data Save private data information.
|
|
@param [out] Animation Contain all decompress images which are BLT format in GIF image data.
|
|
|
|
@retval EFI_SUCCESS create success
|
|
@retval EFI_INVALID_PARAMETER invalid parameter
|
|
@retval EFI_OUT_OF_RESOURCES allocate memory fail
|
|
@retval EFI_UNSUPPORTED format error
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
H2OHiiCreateAnimationFromMem (
|
|
IN UINT8 *FileData,
|
|
IN UINTN FileSize,
|
|
IN VOID *Data,
|
|
OUT ANIMATION **Animation
|
|
)
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
ANIMATION *AnimationEntry;
|
|
ANIMATION_FRAME *AnimationFrame;
|
|
GIF_LOGICAL_SCREEN_DESCRIPTOR GifScreen;
|
|
GIF_IMAGE_DESCRIPTOR ImageDesc;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ImageData;
|
|
UINT32 ImageSize;
|
|
GIF_GRAPHIC_CONTROL_EXTENSION GraphicControl;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL GlobalColorMap[256];
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL LocalColorMap[256];
|
|
UINT8 *CompressedData;
|
|
UINTN CompressedDataSize;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL BackupColor;
|
|
ANIMATION_FRAME *CurrentFrame;
|
|
|
|
|
|
Status = EFI_SUCCESS;
|
|
CompressedData = NULL;
|
|
CompressedDataSize = 0;
|
|
CurrentFrame = NULL;
|
|
ZeroMem (&BackupColor, sizeof (BackupColor));
|
|
|
|
ASSERT (Animation != NULL);
|
|
|
|
if (Animation == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (mOutStack == NULL) {
|
|
mOutStack = H2OImageDecoderLibAllocateZeroMem (4100 * sizeof (UINT8));
|
|
}
|
|
|
|
if (mLzwTable == NULL) {
|
|
mLzwTable = H2OImageDecoderLibAllocateZeroMem (4096 * sizeof (LZW_ENTRY));
|
|
}
|
|
AnimationEntry = (ANIMATION *) H2OImageDecoderLibAllocateZeroMem (sizeof (ANIMATION));
|
|
if (AnimationEntry == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto Err;
|
|
}
|
|
|
|
//
|
|
// Verify Gif Header and Get Logical Screen Descriptor and Global Color Map
|
|
//
|
|
Status = GifDecoderGetLogicalScreen (
|
|
&FileData,
|
|
&FileSize,
|
|
&GifScreen,
|
|
GlobalColorMap
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
goto Err;
|
|
}
|
|
|
|
FixColorMapForTransparent (GifScreen.PackedFields.SizeOfGlobalColorTable, GlobalColorMap);
|
|
|
|
AnimationEntry->Data = Data;
|
|
AnimationEntry->Width = GifScreen.LogicalScreenWidth;
|
|
AnimationEntry->Height = GifScreen.LogicalScreenHeight;
|
|
AnimationEntry->BkColor = GlobalColorMap[GifScreen.BackGroundColorIndex];
|
|
|
|
//
|
|
// default graphic control
|
|
//
|
|
GraphicControl.ExtensionIntroducer = EXTENSION_INTRODUCER;
|
|
GraphicControl.GraphicControlLabel = GRAPHIC_CONTROL_LABEL;
|
|
GraphicControl.BlockSize = 4;
|
|
GraphicControl.PackedFields.DisposalMethod = 0;
|
|
GraphicControl.PackedFields.UserInputFlag = 0;
|
|
GraphicControl.PackedFields.TransparentColorFlag = 0;
|
|
GraphicControl.DelayTime = 10;
|
|
GraphicControl.TransparentColorIndex = 0;
|
|
|
|
for (;;) {
|
|
//
|
|
// Get single image descriptor
|
|
//
|
|
Status = GifDecoderGetImageDesc (
|
|
&FileData,
|
|
&FileSize,
|
|
&ImageDesc,
|
|
LocalColorMap,
|
|
&GraphicControl
|
|
);
|
|
if (Status == EFI_NOT_FOUND) {
|
|
break;
|
|
}
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
goto Err;
|
|
}
|
|
|
|
|
|
if (ImageDesc.PackedFields.LocalColorTableFlag) {
|
|
FixColorMapForTransparent (ImageDesc.PackedFields.SizeOfLocalColorTable, LocalColorMap);
|
|
}
|
|
|
|
//
|
|
// transparent, set color to (0,0,0)
|
|
//
|
|
if (GraphicControl.PackedFields.TransparentColorFlag) {
|
|
if (!ImageDesc.PackedFields.LocalColorTableFlag) {
|
|
BackupColor = GlobalColorMap[GraphicControl.TransparentColorIndex];
|
|
GlobalColorMap[GraphicControl.TransparentColorIndex].Blue = 0;
|
|
GlobalColorMap[GraphicControl.TransparentColorIndex].Green = 0;
|
|
GlobalColorMap[GraphicControl.TransparentColorIndex].Red = 0;
|
|
} else {
|
|
LocalColorMap[GraphicControl.TransparentColorIndex].Blue = 0;
|
|
LocalColorMap[GraphicControl.TransparentColorIndex].Green = 0;
|
|
LocalColorMap[GraphicControl.TransparentColorIndex].Red = 0;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Get single image data
|
|
//
|
|
ImageSize = (UINTN) ImageDesc.ImageWidth * ImageDesc.ImageHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
|
ImageData = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)H2OImageDecoderLibAllocateMem (ImageSize);
|
|
if (ImageData == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto Err;
|
|
}
|
|
|
|
CompressedData = NULL;
|
|
CompressedDataSize = 0;
|
|
Status = GifDecoderGetImageData (
|
|
&FileData,
|
|
&FileSize,
|
|
&ImageDesc,
|
|
GlobalColorMap,
|
|
LocalColorMap,
|
|
&GraphicControl,
|
|
ImageData,
|
|
ImageSize,
|
|
CompressedData,
|
|
&CompressedDataSize
|
|
);
|
|
|
|
if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
|
|
goto Err;
|
|
}
|
|
|
|
CompressedData = (UINT8 *)H2OImageDecoderLibAllocateMem (CompressedDataSize);
|
|
if (CompressedData == NULL) {
|
|
goto Err;
|
|
}
|
|
|
|
Status = GifDecoderGetImageData (
|
|
&FileData,
|
|
&FileSize,
|
|
&ImageDesc,
|
|
GlobalColorMap,
|
|
LocalColorMap,
|
|
&GraphicControl,
|
|
ImageData,
|
|
ImageSize,
|
|
CompressedData,
|
|
&CompressedDataSize
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto Err;
|
|
}
|
|
H2OImageDecoderLibFreeMem (CompressedData, CompressedDataSize);
|
|
CompressedData = NULL;
|
|
|
|
//
|
|
// restore color map
|
|
//
|
|
if (GraphicControl.PackedFields.TransparentColorFlag) {
|
|
if (!ImageDesc.PackedFields.LocalColorTableFlag) {
|
|
GlobalColorMap[GraphicControl.TransparentColorIndex] = BackupColor;
|
|
}
|
|
}
|
|
|
|
//
|
|
// process animation frame
|
|
//
|
|
AnimationFrame = (ANIMATION_FRAME *) H2OImageDecoderLibAllocateZeroMem (sizeof (ANIMATION_FRAME));
|
|
if (AnimationFrame == NULL) {
|
|
goto Err;
|
|
}
|
|
|
|
AnimationFrame->Bitmap = ImageData;
|
|
AnimationFrame->Disposal = GraphicControl.PackedFields.DisposalMethod;
|
|
AnimationFrame->OffsetX = ImageDesc.ImageLeftPosition;
|
|
AnimationFrame->OffsetY = ImageDesc.ImageTopPosition;
|
|
AnimationFrame->Width = ImageDesc.ImageWidth;
|
|
AnimationFrame->Height = ImageDesc.ImageHeight;
|
|
AnimationFrame->Delay = GraphicControl.DelayTime;
|
|
if (GraphicControl.PackedFields.TransparentColorFlag) {
|
|
AnimationFrame->Transparent = TRUE;
|
|
} else {
|
|
AnimationFrame->Transparent = FALSE;
|
|
}
|
|
|
|
//
|
|
// add frame to animation frame linked list
|
|
//
|
|
|
|
AnimationFrame->Next = NULL;
|
|
if (AnimationEntry->Frames == NULL) {
|
|
AnimationEntry->Frames = AnimationFrame;
|
|
AnimationFrame->Prev = NULL;
|
|
} else if (CurrentFrame != NULL) {
|
|
CurrentFrame->Next = AnimationFrame;
|
|
AnimationFrame->Prev = CurrentFrame;
|
|
}
|
|
CurrentFrame = AnimationFrame;
|
|
}
|
|
|
|
*Animation = AnimationEntry;
|
|
return EFI_SUCCESS;
|
|
|
|
Err:
|
|
if (AnimationEntry != NULL) {
|
|
H2OHiiDestroyAnimation (AnimationEntry);
|
|
}
|
|
|
|
if (CompressedData != NULL) {
|
|
H2OImageDecoderLibFreeMem (CompressedData, CompressedDataSize);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Draw one animation frame
|
|
|
|
@param [in] Animation Animation contain all frame list
|
|
@param [in] Frame Frame for draw
|
|
@param [in] Gop Graphics output protocol interface
|
|
@param [in] BltWidth Blt width limit
|
|
@param [in] BltHeight Blt height limit
|
|
@param [in] BltX Image start x
|
|
@param [in] BltY Image start y
|
|
|
|
@retval EFI_SUCCESS draw frame success
|
|
@return other call blt fail
|
|
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
DrawAnimationFrame (
|
|
IN ANIMATION *Animation,
|
|
IN ANIMATION_FRAME *Frame,
|
|
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop,
|
|
IN UINTN BltWidth,
|
|
IN UINTN BltHeight,
|
|
IN UINTN BltX,
|
|
IN UINTN BltY
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuf;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltPtr;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitmapPtr;
|
|
|
|
UINTN Width;
|
|
UINTN Height;
|
|
UINTN X;
|
|
UINTN Y;
|
|
|
|
ASSERT (Animation != NULL && Gop != NULL);
|
|
if ((Animation == NULL) || (Gop == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (Frame == NULL) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// out of display range, do nothing
|
|
//
|
|
if ((((UINT32)BltX + Frame->OffsetX) > BltWidth) ||
|
|
(((UINT32)BltY + Frame->OffsetY) > BltHeight)) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Width = Frame->Width;
|
|
Height = Frame->Height;
|
|
|
|
if (Width > (BltWidth - BltX)) {
|
|
Width = BltWidth - BltX;
|
|
}
|
|
|
|
if (Height > (BltHeight - BltY)) {
|
|
Height = (BltHeight - BltY);
|
|
}
|
|
|
|
//
|
|
// draw frame image
|
|
//
|
|
|
|
if (Frame->Transparent) {
|
|
BltBuf = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)H2OImageDecoderLibAllocateMem (Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
|
Status = Gop->Blt (
|
|
Gop,
|
|
BltBuf,
|
|
EfiBltVideoToBltBuffer,
|
|
BltX + Frame->OffsetX,
|
|
BltY + Frame->OffsetY,
|
|
0,
|
|
0,
|
|
Width,
|
|
Height,
|
|
0
|
|
);
|
|
|
|
} else {
|
|
BltBuf = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)H2OImageDecoderLibAllocateZeroMem (Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
|
}
|
|
|
|
ASSERT (BltBuf != NULL);
|
|
if (BltBuf == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
for (Y = 0; Y < Height; Y++) {
|
|
BltPtr = &BltBuf[Y * Width];
|
|
BitmapPtr = &Frame->Bitmap[Y * Frame->Width];
|
|
for (X = 0; X < Width; X++) {
|
|
if ((BitmapPtr->Blue != 0) || (BitmapPtr->Green != 0) || (BitmapPtr->Red != 0)) {
|
|
*BltPtr = *BitmapPtr;
|
|
}
|
|
BltPtr++;
|
|
BitmapPtr++;
|
|
}
|
|
}
|
|
|
|
Status = Gop->Blt (
|
|
Gop,
|
|
BltBuf,
|
|
EfiBltBufferToVideo,
|
|
0,
|
|
0,
|
|
BltX + Frame->OffsetX,
|
|
BltY + Frame->OffsetY,
|
|
Width,
|
|
Height,
|
|
0
|
|
);
|
|
|
|
H2OImageDecoderLibFreeMem (BltBuf, Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Draw one animation frame for "Restore Previous Frame" disposal
|
|
|
|
@param [in] Animation Animation contain all frame list
|
|
@param [in] Frame Frame for draw
|
|
@param [in] Gop Graphics output protocol interface
|
|
@param [in] BltWidth Blt width limit
|
|
@param [in] BltHeight Blt height limit
|
|
@param [in] BltX Image start x
|
|
@param [in] BltY Image start y
|
|
|
|
@retval EFI_SUCCESS draw frame success
|
|
@return other call blt fail
|
|
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
RestorePrevFrame (
|
|
IN ANIMATION *Animation,
|
|
IN ANIMATION_FRAME *Frame,
|
|
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop,
|
|
IN UINTN BltWidth,
|
|
IN UINTN BltHeight,
|
|
IN UINTN BltX,
|
|
IN UINTN BltY
|
|
)
|
|
{
|
|
|
|
UINT16 Disposal;
|
|
EFI_STATUS Status;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL BkColor;
|
|
UINTN Width;
|
|
UINTN Height;
|
|
UINTN X;
|
|
UINTN Y;
|
|
|
|
Disposal = 256;
|
|
|
|
|
|
if (Frame != NULL) {
|
|
//
|
|
// out of display range, do nothing
|
|
//
|
|
if ((((UINT32)BltX + Frame->OffsetX) > BltWidth) ||
|
|
(((UINT32)BltY + Frame->OffsetY) > BltHeight)) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Disposal = Frame->Disposal;
|
|
Width = Frame->Width;
|
|
Height = Frame->Height;
|
|
X = BltX + Frame->OffsetX;
|
|
Y = BltX + Frame->OffsetY;
|
|
} else {
|
|
Width = Animation->Width;
|
|
Height = Animation->Height;
|
|
X = BltX;
|
|
Y = BltY;
|
|
}
|
|
|
|
BkColor = Animation->BkColor;
|
|
|
|
if (Width > (BltWidth - BltX)) {
|
|
Width = BltWidth - BltX;
|
|
}
|
|
|
|
if (Height > (BltHeight - BltY)) {
|
|
Height = (BltHeight - BltY);
|
|
}
|
|
|
|
switch (Disposal) {
|
|
|
|
case 2: // background color
|
|
case 256: // no frame
|
|
Status = Gop->Blt (
|
|
Gop,
|
|
&BkColor,
|
|
EfiBltVideoFill,
|
|
0,
|
|
0,
|
|
X,
|
|
Y,
|
|
Width,
|
|
Height,
|
|
0
|
|
);
|
|
if (Frame == NULL) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case 3: // restore
|
|
RestorePrevFrame (Animation, Frame->Prev, Gop, BltWidth, BltHeight, BltX, BltY);
|
|
return EFI_SUCCESS;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
DrawAnimationFrame (Animation, Frame, Gop, BltWidth, BltHeight, BltX, BltY);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Draw one animation frame by disposal
|
|
case 0, 1: do nothing
|
|
case 2: fill background color
|
|
case 3: restore previous frame
|
|
|
|
@param [in] Animation Animation contain all frame list
|
|
@param [in] Frame Frame for draw
|
|
@param [in] Gop Graphics output protocol interface
|
|
@param [in] BltWidth Blt width limit
|
|
@param [in] BltHeight Blt height limit
|
|
@param [in] BltX Image start x
|
|
@param [in] BltY Image start y
|
|
|
|
@retval EFI_SUCCESS draw frame success
|
|
@return other call blt fail
|
|
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
DrawAnimationFrameDisposal (
|
|
IN ANIMATION *Animation,
|
|
IN ANIMATION_FRAME *Frame,
|
|
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop,
|
|
IN UINTN BltWidth,
|
|
IN UINTN BltHeight,
|
|
IN UINTN BltX,
|
|
IN UINTN BltY
|
|
)
|
|
{
|
|
UINT16 Disposal;
|
|
EFI_STATUS Status;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL BkColor;
|
|
UINTN Width;
|
|
UINTN Height;
|
|
|
|
ASSERT (Animation->Frames != NULL);
|
|
|
|
Disposal = 256;
|
|
if (Frame != NULL) {
|
|
Disposal = Frame->Disposal;
|
|
} else {
|
|
ASSERT (Animation->Frames != NULL);
|
|
if (Animation->Frames == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
Frame = Animation->Frames;
|
|
}
|
|
|
|
BkColor = Animation->BkColor;
|
|
|
|
//
|
|
// out of display range, do nothing
|
|
//
|
|
if ((((UINT32)BltX + Frame->OffsetX) > BltWidth) ||
|
|
(((UINT32)BltY + Frame->OffsetY) > BltHeight)) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Width = Frame->Width;
|
|
Height = Frame->Height;
|
|
if (Width > (BltWidth - BltX)) {
|
|
Width = BltWidth - BltX;
|
|
}
|
|
|
|
if (Height > (BltHeight - BltY)) {
|
|
Height = (BltHeight - BltY);
|
|
}
|
|
|
|
switch (Disposal) {
|
|
|
|
case 2: // background color
|
|
//case 256: // no frame
|
|
Status = Gop->Blt (
|
|
Gop,
|
|
&BkColor,
|
|
EfiBltVideoFill,
|
|
0,
|
|
0,
|
|
BltX + Frame->OffsetX,
|
|
BltY + Frame->OffsetY,
|
|
Width,
|
|
Height,
|
|
0
|
|
);
|
|
break;
|
|
|
|
case 3: // restore
|
|
RestorePrevFrame (Animation, Frame->Prev, Gop, BltWidth, BltHeight, BltX, BltY);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
Draw next animation frame
|
|
|
|
@param [in] Entry Animation Refresh Entry for animation information in screen
|
|
@param [in] Gop Graphics output protocol interface
|
|
|
|
@retval EFI_SUCCESS draw frame success
|
|
@retval EFI_NOT_FOUND no next frame to draw
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
H2OHiiNextAnimationFrame (
|
|
IN ANIMATION_REFRESH_ENTRY *Entry,
|
|
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop
|
|
)
|
|
{
|
|
ASSERT (Entry != NULL && Entry->Animation != NULL &&
|
|
Entry->Animation->Frames != NULL);
|
|
if (Entry == NULL || Entry->Animation == NULL || Entry->Animation->Frames == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (Entry->Current == NULL) {
|
|
Entry->Current = Entry->Animation->Frames;
|
|
} else {
|
|
if (Entry->Current->Next == NULL) {
|
|
//
|
|
// if autoloop is true, play animaiton from first image again,
|
|
// else stop animation
|
|
//
|
|
if (Entry->AutoLoop) {
|
|
Entry->Current = Entry->Animation->Frames;
|
|
} else {
|
|
Entry->Current = NULL;
|
|
Entry->Status = ANIM_STATUS_STOP;
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
} else {
|
|
Entry->Current = Entry->Current->Next;
|
|
}
|
|
}
|
|
|
|
if (Entry->Current != NULL) {
|
|
// disposal
|
|
DrawAnimationFrameDisposal (Entry->Animation, Entry->Current->Prev, Gop, Entry->BltWidth, Entry->BltHeight, Entry->X, Entry->Y);
|
|
DrawAnimationFrame (Entry->Animation, Entry->Current, Gop, Entry->BltWidth, Entry->BltHeight, Entry->X, Entry->Y);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
By record tick and delay time to determinate draw image
|
|
|
|
@param [in] AnimationRefrshEntry Pointer to animation refresh entry
|
|
@param [in] Gop Point to graphics output protocol
|
|
@param [in] CpuFrequency Cpu Frequency for calculate tick elapsed time
|
|
|
|
@retval EFI_SUCCESS animation is playing
|
|
@retval EFI_NOT_FOUND animation is stopping
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
H2OHiiRefreshAnimation (
|
|
IN ANIMATION_REFRESH_ENTRY *AnimationRefrshEntry,
|
|
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop,
|
|
IN UINT64 CpuFrequency
|
|
)
|
|
{
|
|
UINT32 DelayTime;
|
|
UINT32 ElapsedTime;
|
|
UINT64 CurrentTick;
|
|
|
|
ASSERT (AnimationRefrshEntry != NULL);
|
|
if (AnimationRefrshEntry == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (AnimationRefrshEntry->Status == ANIM_STATUS_PLAY) {
|
|
|
|
if (CpuFrequency == 0) {
|
|
GetFrequency (&CpuFrequency);
|
|
}
|
|
|
|
if (AnimationRefrshEntry->Current != NULL) {
|
|
DelayTime = AnimationRefrshEntry->Current->Delay;
|
|
DelayTime = (DelayTime < 3) ? 3 : DelayTime;
|
|
} else {
|
|
DelayTime = 0;
|
|
}
|
|
|
|
//
|
|
// calculate elapsed time is 1/1000, but delay time is 1/100
|
|
//
|
|
CurrentTick = GetPerformanceCounter ();
|
|
ElapsedTime = (UINT32) DivU64x32 (CurrentTick - AnimationRefrshEntry->RecordTick, (UINT32) (CpuFrequency));
|
|
if (ElapsedTime > DelayTime * 10) {
|
|
H2OHiiNextAnimationFrame (AnimationRefrshEntry, Gop);
|
|
AnimationRefrshEntry->RecordTick = CurrentTick;
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
/**
|
|
Draw next animation frame
|
|
|
|
@param [in] Animation Contain all decompress images which are BLT format in GIF image data.
|
|
|
|
@retval EFI_SUCCESS free memory success
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
H2OHiiDestroyAnimation (
|
|
IN ANIMATION *Animation
|
|
)
|
|
{
|
|
|
|
ANIMATION_FRAME *Next;
|
|
ANIMATION_FRAME *Frame;
|
|
|
|
ASSERT (Animation != NULL);
|
|
if (Animation == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Frame = Animation->Frames;
|
|
while (Frame != NULL) {
|
|
Next = Frame->Next;
|
|
if (Frame->Bitmap != NULL) {
|
|
H2OImageDecoderLibFreeMem (Frame->Bitmap, (UINTN) Frame->Height * Frame->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
|
}
|
|
H2OImageDecoderLibFreeMem (Frame, sizeof (ANIMATION_FRAME));
|
|
Frame = Next;
|
|
};
|
|
|
|
H2OImageDecoderLibFreeMem (Animation, sizeof (ANIMATION));
|
|
|
|
return EFI_SUCCESS;
|
|
}
|