350 lines
11 KiB
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;
|
|
}
|
|
|