alder_lake_bios/Insyde/InsydeSetupPkg/Library/LayoutSupportLib/Font.c

350 lines
11 KiB
C

/** @file
;******************************************************************************
;* Copyright (c) 2013 - 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 "LayoutSupportLib.h"
EFI_STATUS
SeparateStringByFont (
IN CHAR16 *String,
IN EFI_FONT_DISPLAY_INFO *FontDisplayInfo,
IN UINT32 LimitWidth,
OUT EFI_IMAGE_OUTPUT **CharImageOutArray OPTIONAL,
OUT UINT32 *SeparateStrCount,
OUT UINT32 **SeparateStrOffsetArray OPTIONAL,
OUT UINT32 **SeparateStrWidthArray OPTIONAL,
OUT UINTN **SeparateStrArray
)
{
EFI_STATUS Status;
EFI_HII_FONT_PROTOCOL *HiiFont;
EFI_IMAGE_OUTPUT *ImageOut;
EFI_IMAGE_OUTPUT *ImageOutArray;
UINT32 Index;
UINT32 Stringlen;
UINT32 *BaselineArray;
UINT32 TotalWidth;
UINT32 TotalHeight;
UINT32 StrCount;
UINT32 *StrOffsetArray;
UINT32 *StrWidthArray;
UINTN *StrAddrArray;
UINT32 CurrentWidth;
CHAR16 *CurrentStr;
UINT32 CurrentStrLen;
Status = EFI_SUCCESS;
if (String == NULL || FontDisplayInfo == NULL) {
return EFI_INVALID_PARAMETER;
}
if (SeparateStrCount == NULL || SeparateStrArray == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = gBS->LocateProtocol (&gEfiHiiFontProtocolGuid, NULL, (VOID **) &HiiFont);
if (EFI_ERROR (Status)) {
return Status;
}
ImageOutArray = NULL;
BaselineArray = NULL;
StrOffsetArray = NULL;
StrWidthArray = NULL;
StrAddrArray = NULL;
Stringlen = (UINT32)(StrLen (String));
ImageOutArray = AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT) * Stringlen);
if (ImageOutArray == NULL) {
goto Error;
}
BaselineArray = AllocateZeroPool (sizeof (UINT32) * Stringlen);
if (BaselineArray == NULL) {
goto Error;
}
//
// Get ImageOut->Width and ImageOut->Height
//
TotalWidth = 0;
TotalHeight = 0;
for (Index = 0; Index < Stringlen; Index ++) {
ImageOut = NULL;
Status = HiiFont->GetGlyph (
HiiFont,
String[Index],
FontDisplayInfo,
&ImageOut,
(UINTN *)&BaselineArray[Index]
);
if (EFI_ERROR (Status)) {
continue;
}
//
// Save each ImageOut
//
if (ImageOut != NULL) {
if (ImageOut->Image.Bitmap != NULL) {
CopyMem (&ImageOutArray[Index], ImageOut, sizeof (EFI_IMAGE_OUTPUT));
SafeFreePool ((VOID **) &ImageOut);
}
}
TotalWidth += ImageOutArray[Index].Width;
TotalHeight = (UINT32)MAX (TotalHeight, ImageOutArray[Index].Height);
if (BaselineArray != NULL) {
TotalHeight = (UINT32)MAX (TotalHeight, BaselineArray[Index]);
}
}
//
// Separate line by width
//
StrCount = 1;
if (LimitWidth != 0) {
if (TotalWidth > LimitWidth) {
//
// Get separate string count
//
CurrentWidth = 0;
Index = 0;
while (Index < Stringlen) {
CurrentWidth += ImageOutArray[Index].Width;
if (CurrentWidth > LimitWidth || String[Index] == CHAR_CARRIAGE_RETURN) {
if (ImageOutArray[Index].Width > LimitWidth) {
//
// Can't fill one of words
//
SafeFreePool ((VOID **) &ImageOutArray);
SafeFreePool ((VOID **) &BaselineArray);
return EFI_BUFFER_TOO_SMALL;
}
StrCount ++;
CurrentWidth = 0;
Index --;
}
Index ++;
}
}
}
StrOffsetArray = AllocateZeroPool (sizeof (UINT32) * StrCount);
if (StrOffsetArray == NULL) {
goto Error;
}
StrWidthArray = AllocateZeroPool (sizeof (UINT32) * StrCount);
if (StrWidthArray == NULL) {
goto Error;
}
StrAddrArray = AllocateZeroPool (sizeof (UINTN) * StrCount);
if (StrAddrArray == NULL) {
goto Error;
}
if (StrCount == 1) {
for (Index = 0, CurrentWidth = 0;Index < Stringlen; Index ++) {
CurrentWidth += ImageOutArray[Index].Width;
}
StrWidthArray[0] = CurrentWidth;
StrAddrArray[0] = (UINTN)(UINTN *)CatSPrint (NULL, String);
} else {
//
// Get each separate string index
//
StrCount = 0;
CurrentWidth = 0;
Index = 0;
for (Index = 0, CurrentWidth = 0;Index < Stringlen; Index ++) {
CurrentWidth += ImageOutArray[Index].Width;
StrWidthArray[StrCount] = CurrentWidth;
if (CurrentWidth > LimitWidth || String[Index] == CHAR_CARRIAGE_RETURN) {
StrWidthArray[StrCount] -= ImageOutArray[Index].Width;
StrCount ++;
StrOffsetArray[StrCount] = Index;
CurrentWidth = 0;
Index --;
}
}
StrCount ++;
//
// Get separate strings
//
Index = 0;
while (Index < StrCount) {
CurrentStr = String + StrOffsetArray[Index];
if (Index == StrCount - 1) {
CurrentStrLen = (UINT32)(StrLen (CurrentStr));
} else {
CurrentStrLen = StrOffsetArray[Index + 1] - StrOffsetArray[Index];
}
StrAddrArray[Index] = (UINTN)(UINTN *)AllocateCopyPool (sizeof (CHAR16) * (CurrentStrLen + 1), CurrentStr);
if (StrAddrArray[Index] == 0) {
goto Error;
}
CurrentStr = (CHAR16 *)(UINTN *)StrAddrArray[Index];
CurrentStr[CurrentStrLen] = '\0';
Index ++;
}
}
SafeFreePool ((VOID **) &BaselineArray);
if (CharImageOutArray != NULL) {
*CharImageOutArray = ImageOutArray;
} else {
SafeFreePool ((VOID **) &ImageOutArray);
}
if (SeparateStrCount != NULL) {
*SeparateStrCount = StrCount;
}
if (SeparateStrOffsetArray != NULL) {
*SeparateStrOffsetArray = StrOffsetArray;
} else {
SafeFreePool ((VOID **) &StrOffsetArray);
}
if (SeparateStrWidthArray != NULL) {
*SeparateStrWidthArray = StrWidthArray;
} else {
SafeFreePool ((VOID **) &StrWidthArray);
}
*SeparateStrArray = StrAddrArray;
return EFI_SUCCESS;
Error:
SafeFreePool ((VOID **) &ImageOutArray);
SafeFreePool ((VOID **) &BaselineArray);
SafeFreePool ((VOID **) &StrOffsetArray);
SafeFreePool ((VOID **) &StrWidthArray);
SafeFreePool ((VOID **) &StrAddrArray);
return EFI_OUT_OF_RESOURCES;
}
EFI_STATUS
GetStringImageByFont (
IN CHAR16 *String,
IN RECT *Field,
IN EFI_FONT_DISPLAY_INFO *FontDisplayInfo,
OUT EFI_IMAGE_OUTPUT **ImageOutput
)
{
EFI_STATUS Status;
EFI_IMAGE_OUTPUT *CharImageOutArray;
UINT32 SeparateStringNum;
UINT32 *SeparateStringOffset;
UINT32 *SeparateStringWidth;
UINTN *SeparateStrings;
CHAR16 *SeparateString;
UINT32 StrIndex;
UINT32 CharIndex;
UINT32 CurrentWidth;
UINT32 LimitWidth;
UINT32 LimitHeight;
EFI_IMAGE_OUTPUT *ImageOut;
Status = EFI_SUCCESS;
if (String == NULL || FontDisplayInfo == NULL) {
return EFI_INVALID_PARAMETER;
}
LimitWidth = Field->right - Field->left;
LimitHeight = Field->bottom - Field->top;
Status = SeparateStringByFont (
String,
FontDisplayInfo,
LimitWidth,
&CharImageOutArray,
&SeparateStringNum,
&SeparateStringOffset,
&SeparateStringWidth,
&SeparateStrings
);
if (Status == EFI_BUFFER_TOO_SMALL) {
*ImageOutput = NULL;
return Status;
} else if (EFI_ERROR (Status)) {
*ImageOutput = NULL;
return Status;
}
ImageOut = AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
if (ImageOut == NULL) {
return EFI_OUT_OF_RESOURCES;
}
ImageOut->Width = (UINT16)LimitWidth;
ImageOut->Height = (UINT16)LimitHeight;
ImageOut->Image.Bitmap = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * ImageOut->Width * ImageOut->Height);
CurrentWidth = 0;
StrIndex = 0;
CharIndex = 0;
while (String[CharIndex] != '\0') {
if (CharImageOutArray[CharIndex].Width == 0) {
CharIndex ++;
continue;
}
if (CharIndex >= SeparateStringOffset[StrIndex + 1]) {
StrIndex ++;
CurrentWidth = 0;
continue;
}
Status = BltCopy(
CharImageOutArray[CharIndex].Image.Bitmap,
0,
0,
(UINTN)(CharImageOutArray[CharIndex].Width),
ImageOut->Image.Bitmap,
(UINTN)(CurrentWidth),
(UINTN)((UINTN)StrIndex * (UINTN)FontDisplayInfo->FontInfo.FontSize),
(UINTN)(ImageOut->Width),
(UINTN)(ImageOut->Height),
(UINTN)(CharImageOutArray[CharIndex].Width),
(UINTN)(CharImageOutArray[CharIndex].Height)
);
if (EFI_ERROR (Status)) {
*ImageOutput = NULL;
return EFI_BUFFER_TOO_SMALL;
}
CurrentWidth += CharImageOutArray[CharIndex].Width;
CharIndex ++;
}
ImageOut->Width = 0;
for (StrIndex = 0; StrIndex < SeparateStringNum; StrIndex ++) {
ImageOut->Width = MAX (ImageOut->Width, (UINT16)(SeparateStringWidth[StrIndex]));
SeparateString = (CHAR16 *)(UINTN *)(UINTN)(SeparateStrings[StrIndex]);
//SafeFreePool (&SeparateString);
}
SafeFreePool ((VOID **) &SeparateStrings);
SafeFreePool ((VOID **) &CharImageOutArray);
SafeFreePool ((VOID **) &SeparateStringOffset);
SafeFreePool ((VOID **) &SeparateStringWidth);
ImageOut->Height = (UINT16)SeparateStringNum * FontDisplayInfo->FontInfo.FontSize;
*ImageOutput = ImageOut;
return EFI_SUCCESS;
}