/** @file | |
Implementation for EFI_HII_FONT_PROTOCOL. | |
Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR> | |
This program and the accompanying materials | |
are licensed and made available under the terms and conditions of the BSD License | |
which accompanies this distribution. The full text of the license may be found at | |
http://opensource.org/licenses/bsd-license.php | |
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
**/ | |
#include "HiiDatabase.h" | |
EFI_GRAPHICS_OUTPUT_BLT_PIXEL mHiiEfiColors[16] = { | |
// | |
// B G R | |
// | |
{0x00, 0x00, 0x00, 0x00}, // BLACK | |
{0x98, 0x00, 0x00, 0x00}, // BLUE | |
{0x00, 0x98, 0x00, 0x00}, // GREEN | |
{0x98, 0x98, 0x00, 0x00}, // CYAN | |
{0x00, 0x00, 0x98, 0x00}, // RED | |
{0x98, 0x00, 0x98, 0x00}, // MAGENTA | |
{0x00, 0x98, 0x98, 0x00}, // BROWN | |
{0x98, 0x98, 0x98, 0x00}, // LIGHTGRAY | |
{0x30, 0x30, 0x30, 0x00}, // DARKGRAY - BRIGHT BLACK | |
{0xff, 0x00, 0x00, 0x00}, // LIGHTBLUE | |
{0x00, 0xff, 0x00, 0x00}, // LIGHTGREEN | |
{0xff, 0xff, 0x00, 0x00}, // LIGHTCYAN | |
{0x00, 0x00, 0xff, 0x00}, // LIGHTRED | |
{0xff, 0x00, 0xff, 0x00}, // LIGHTMAGENTA | |
{0x00, 0xff, 0xff, 0x00}, // YELLOW | |
{0xff, 0xff, 0xff, 0x00}, // WHITE | |
}; | |
/** | |
Insert a character cell information to the list specified by GlyphInfoList. | |
This is a internal function. | |
@param CharValue Unicode character value, which identifies a glyph | |
block. | |
@param GlyphInfoList HII_GLYPH_INFO list head. | |
@param Cell Incoming character cell information. | |
@retval EFI_SUCCESS Cell information is added to the GlyphInfoList. | |
@retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the | |
task. | |
**/ | |
EFI_STATUS | |
NewCell ( | |
IN CHAR16 CharValue, | |
IN LIST_ENTRY *GlyphInfoList, | |
IN EFI_HII_GLYPH_INFO *Cell | |
) | |
{ | |
HII_GLYPH_INFO *GlyphInfo; | |
ASSERT (Cell != NULL && GlyphInfoList != NULL); | |
GlyphInfo = (HII_GLYPH_INFO *) AllocateZeroPool (sizeof (HII_GLYPH_INFO)); | |
if (GlyphInfo == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
// | |
// GlyphInfoList stores a list of default character cell information, each is | |
// identified by "CharId". | |
// | |
GlyphInfo->Signature = HII_GLYPH_INFO_SIGNATURE; | |
GlyphInfo->CharId = CharValue; | |
if (Cell->AdvanceX == 0) { | |
Cell->AdvanceX = Cell->Width; | |
} | |
CopyMem (&GlyphInfo->Cell, Cell, sizeof (EFI_HII_GLYPH_INFO)); | |
InsertTailList (GlyphInfoList, &GlyphInfo->Entry); | |
return EFI_SUCCESS; | |
} | |
/** | |
Get a character cell information from the list specified by GlyphInfoList. | |
This is a internal function. | |
@param CharValue Unicode character value, which identifies a glyph | |
block. | |
@param GlyphInfoList HII_GLYPH_INFO list head. | |
@param Cell Buffer which stores output character cell | |
information. | |
@retval EFI_SUCCESS Cell information is added to the GlyphInfoList. | |
@retval EFI_NOT_FOUND The character info specified by CharValue does | |
not exist. | |
**/ | |
EFI_STATUS | |
GetCell ( | |
IN CHAR16 CharValue, | |
IN LIST_ENTRY *GlyphInfoList, | |
OUT EFI_HII_GLYPH_INFO *Cell | |
) | |
{ | |
HII_GLYPH_INFO *GlyphInfo; | |
LIST_ENTRY *Link; | |
ASSERT (Cell != NULL && GlyphInfoList != NULL); | |
// | |
// Since the EFI_HII_GIBT_DEFAULTS block won't increment CharValueCurrent, | |
// the value of "CharId" of a default character cell which is used for a | |
// EFI_HII_GIBT_GLYPH_DEFAULT or EFI_HII_GIBT_GLYPHS_DEFAULT should be | |
// less or equal to the value of "CharValueCurrent" of this default block. | |
// | |
// For instance, if the CharId of a GlyphInfoList is {1, 3, 7}, a default glyph | |
// with CharValue equals "7" uses the GlyphInfo with CharId = 7; | |
// a default glyph with CharValue equals "6" uses the GlyphInfo with CharId = 3. | |
// | |
for (Link = GlyphInfoList->BackLink; Link != GlyphInfoList; Link = Link->BackLink) { | |
GlyphInfo = CR (Link, HII_GLYPH_INFO, Entry, HII_GLYPH_INFO_SIGNATURE); | |
if (GlyphInfo->CharId <= CharValue) { | |
CopyMem (Cell, &GlyphInfo->Cell, sizeof (EFI_HII_GLYPH_INFO)); | |
return EFI_SUCCESS; | |
} | |
} | |
return EFI_NOT_FOUND; | |
} | |
/** | |
Convert the glyph for a single character into a bitmap. | |
This is a internal function. | |
@param Private HII database driver private data. | |
@param Char Character to retrieve. | |
@param StringInfo Points to the string font and color information | |
or NULL if the string should use the default | |
system font and color. | |
@param GlyphBuffer Buffer to store the retrieved bitmap data. | |
@param Cell Points to EFI_HII_GLYPH_INFO structure. | |
@param Attributes If not NULL, output the glyph attributes if any. | |
@retval EFI_SUCCESS Glyph bitmap outputted. | |
@retval EFI_OUT_OF_RESOURCES Unable to allocate the output buffer GlyphBuffer. | |
@retval EFI_NOT_FOUND The glyph was unknown can not be found. | |
@retval EFI_INVALID_PARAMETER Any input parameter is invalid. | |
**/ | |
EFI_STATUS | |
GetGlyphBuffer ( | |
IN HII_DATABASE_PRIVATE_DATA *Private, | |
IN CHAR16 Char, | |
IN EFI_FONT_INFO *StringInfo, | |
OUT UINT8 **GlyphBuffer, | |
OUT EFI_HII_GLYPH_INFO *Cell, | |
OUT UINT8 *Attributes OPTIONAL | |
) | |
{ | |
HII_DATABASE_RECORD *Node; | |
LIST_ENTRY *Link; | |
HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFont; | |
LIST_ENTRY *Link1; | |
UINT16 Index; | |
EFI_NARROW_GLYPH Narrow; | |
EFI_WIDE_GLYPH Wide; | |
HII_GLOBAL_FONT_INFO *GlobalFont; | |
UINTN HeaderSize; | |
EFI_NARROW_GLYPH *NarrowPtr; | |
EFI_WIDE_GLYPH *WidePtr; | |
if (GlyphBuffer == NULL || Cell == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if (Private == NULL || Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) { | |
return EFI_INVALID_PARAMETER; | |
} | |
ZeroMem (Cell, sizeof (EFI_HII_GLYPH_INFO)); | |
// | |
// If StringInfo is not NULL, it must point to an existing EFI_FONT_INFO rather | |
// than system default font and color. | |
// If NULL, try to find the character in simplified font packages since | |
// default system font is the fixed font (narrow or wide glyph). | |
// | |
if (StringInfo != NULL) { | |
if(!IsFontInfoExisted (Private, StringInfo, NULL, NULL, &GlobalFont)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if (Attributes != NULL) { | |
*Attributes = PROPORTIONAL_GLYPH; | |
} | |
return FindGlyphBlock (GlobalFont->FontPackage, Char, GlyphBuffer, Cell, NULL); | |
} else { | |
HeaderSize = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR); | |
for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) { | |
Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE); | |
for (Link1 = Node->PackageList->SimpleFontPkgHdr.ForwardLink; | |
Link1 != &Node->PackageList->SimpleFontPkgHdr; | |
Link1 = Link1->ForwardLink | |
) { | |
SimpleFont = CR (Link1, HII_SIMPLE_FONT_PACKAGE_INSTANCE, SimpleFontEntry, HII_S_FONT_PACKAGE_SIGNATURE); | |
// | |
// Search the narrow glyph array | |
// | |
NarrowPtr = (EFI_NARROW_GLYPH *) ((UINT8 *) (SimpleFont->SimpleFontPkgHdr) + HeaderSize); | |
for (Index = 0; Index < SimpleFont->SimpleFontPkgHdr->NumberOfNarrowGlyphs; Index++) { | |
CopyMem (&Narrow, NarrowPtr + Index,sizeof (EFI_NARROW_GLYPH)); | |
if (Narrow.UnicodeWeight == Char) { | |
*GlyphBuffer = (UINT8 *) AllocateZeroPool (EFI_GLYPH_HEIGHT); | |
if (*GlyphBuffer == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
Cell->Width = EFI_GLYPH_WIDTH; | |
Cell->Height = EFI_GLYPH_HEIGHT; | |
Cell->AdvanceX = Cell->Width; | |
CopyMem (*GlyphBuffer, Narrow.GlyphCol1, Cell->Height); | |
if (Attributes != NULL) { | |
*Attributes = (UINT8) (Narrow.Attributes | NARROW_GLYPH); | |
} | |
return EFI_SUCCESS; | |
} | |
} | |
// | |
// Search the wide glyph array | |
// | |
WidePtr = (EFI_WIDE_GLYPH *) (NarrowPtr + SimpleFont->SimpleFontPkgHdr->NumberOfNarrowGlyphs); | |
for (Index = 0; Index < SimpleFont->SimpleFontPkgHdr->NumberOfWideGlyphs; Index++) { | |
CopyMem (&Wide, WidePtr + Index, sizeof (EFI_WIDE_GLYPH)); | |
if (Wide.UnicodeWeight == Char) { | |
*GlyphBuffer = (UINT8 *) AllocateZeroPool (EFI_GLYPH_HEIGHT * 2); | |
if (*GlyphBuffer == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
Cell->Width = EFI_GLYPH_WIDTH * 2; | |
Cell->Height = EFI_GLYPH_HEIGHT; | |
Cell->AdvanceX = Cell->Width; | |
CopyMem (*GlyphBuffer, Wide.GlyphCol1, EFI_GLYPH_HEIGHT); | |
CopyMem (*GlyphBuffer + EFI_GLYPH_HEIGHT, Wide.GlyphCol2, EFI_GLYPH_HEIGHT); | |
if (Attributes != NULL) { | |
*Attributes = (UINT8) (Wide.Attributes | EFI_GLYPH_WIDE); | |
} | |
return EFI_SUCCESS; | |
} | |
} | |
} | |
} | |
} | |
return EFI_NOT_FOUND; | |
} | |
/** | |
Convert bitmap data of the glyph to blt structure. | |
This is a internal function. | |
@param GlyphBuffer Buffer points to bitmap data of glyph. | |
@param Foreground The color of the "on" pixels in the glyph in the | |
bitmap. | |
@param Background The color of the "off" pixels in the glyph in the | |
bitmap. | |
@param ImageWidth Width of the whole image in pixels. | |
@param RowWidth The width of the text on the line, in pixels. | |
@param RowHeight The height of the line, in pixels. | |
@param Transparent If TRUE, the Background color is ignored and all | |
"off" pixels in the character's drawn wil use the | |
pixel value from BltBuffer. | |
@param Origin On input, points to the origin of the to be | |
displayed character, on output, points to the | |
next glyph's origin. | |
**/ | |
VOID | |
NarrowGlyphToBlt ( | |
IN UINT8 *GlyphBuffer, | |
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground, | |
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background, | |
IN UINT16 ImageWidth, | |
IN UINTN RowWidth, | |
IN UINTN RowHeight, | |
IN BOOLEAN Transparent, | |
IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin | |
) | |
{ | |
UINT8 Xpos; | |
UINT8 Ypos; | |
UINT8 Height; | |
UINT8 Width; | |
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Buffer; | |
ASSERT (GlyphBuffer != NULL && Origin != NULL && *Origin != NULL); | |
Height = EFI_GLYPH_HEIGHT; | |
Width = EFI_GLYPH_WIDTH; | |
// | |
// Move position to the left-top corner of char. | |
// | |
Buffer = *Origin - EFI_GLYPH_HEIGHT * ImageWidth; | |
// | |
// Char may be partially displayed when CLIP_X or CLIP_Y is not set. | |
// | |
if (RowHeight < Height) { | |
Height = (UINT8) RowHeight; | |
} | |
if (RowWidth < Width) { | |
Width = (UINT8) RowWidth; | |
} | |
for (Ypos = 0; Ypos < Height; Ypos++) { | |
for (Xpos = 0; Xpos < Width; Xpos++) { | |
if ((GlyphBuffer[Ypos] & (1 << (EFI_GLYPH_WIDTH - Xpos - 1))) != 0) { | |
Buffer[Ypos * ImageWidth + Xpos] = Foreground; | |
} else { | |
if (!Transparent) { | |
Buffer[Ypos * ImageWidth + Xpos] = Background; | |
} | |
} | |
} | |
} | |
*Origin = *Origin + EFI_GLYPH_WIDTH; | |
} | |
/** | |
Convert bitmap data of the glyph to blt structure. | |
This is a internal function. | |
@param GlyphBuffer Buffer points to bitmap data of glyph. | |
@param Foreground The color of the "on" pixels in the glyph in the | |
bitmap. | |
@param Background The color of the "off" pixels in the glyph in the | |
bitmap. | |
@param ImageWidth Width of the whole image in pixels. | |
@param BaseLine BaseLine in the line. | |
@param RowWidth The width of the text on the line, in pixels. | |
@param RowHeight The height of the line, in pixels. | |
@param Transparent If TRUE, the Background color is ignored and all | |
"off" pixels in the character's drawn wil use the | |
pixel value from BltBuffer. | |
@param Cell Points to EFI_HII_GLYPH_INFO structure. | |
@param Attributes The attribute of incoming glyph in GlyphBuffer. | |
@param Origin On input, points to the origin of the to be | |
displayed character, on output, points to the | |
next glyph's origin. | |
**/ | |
VOID | |
GlyphToBlt ( | |
IN UINT8 *GlyphBuffer, | |
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground, | |
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background, | |
IN UINT16 ImageWidth, | |
IN UINT16 BaseLine, | |
IN UINTN RowWidth, | |
IN UINTN RowHeight, | |
IN BOOLEAN Transparent, | |
IN CONST EFI_HII_GLYPH_INFO *Cell, | |
IN UINT8 Attributes, | |
IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin | |
) | |
{ | |
UINT16 Xpos; | |
UINT16 Ypos; | |
UINT8 Data; | |
UINT16 Index; | |
UINT16 YposOffset; | |
UINTN OffsetY; | |
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer; | |
ASSERT (Origin != NULL && *Origin != NULL && Cell != NULL); | |
// | |
// Only adjust origin position if char has no bitmap. | |
// | |
if (GlyphBuffer == NULL) { | |
*Origin = *Origin + Cell->AdvanceX; | |
return; | |
} | |
// | |
// Move position to the left-top corner of char. | |
// | |
BltBuffer = *Origin + Cell->OffsetX - (Cell->OffsetY + Cell->Height) * ImageWidth; | |
YposOffset = (UINT16) (BaseLine - (Cell->OffsetY + Cell->Height)); | |
// | |
// Since non-spacing key will be printed OR'd with the previous glyph, don't | |
// write 0. | |
// | |
if ((Attributes & EFI_GLYPH_NON_SPACING) == EFI_GLYPH_NON_SPACING) { | |
Transparent = TRUE; | |
} | |
// | |
// The glyph's upper left hand corner pixel is the most significant bit of the | |
// first bitmap byte. | |
// | |
for (Ypos = 0; Ypos < Cell->Height && ((UINTN) (Ypos + YposOffset) < RowHeight); Ypos++) { | |
OffsetY = BITMAP_LEN_1_BIT (Cell->Width, Ypos); | |
// | |
// All bits in these bytes are meaningful. | |
// | |
for (Xpos = 0; Xpos < Cell->Width / 8; Xpos++) { | |
Data = *(GlyphBuffer + OffsetY + Xpos); | |
for (Index = 0; Index < 8 && ((UINTN) (Xpos * 8 + Index + Cell->OffsetX) < RowWidth); Index++) { | |
if ((Data & (1 << (8 - Index - 1))) != 0) { | |
BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Foreground; | |
} else { | |
if (!Transparent) { | |
BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Background; | |
} | |
} | |
} | |
} | |
if (Cell->Width % 8 != 0) { | |
// | |
// There are some padding bits in this byte. Ignore them. | |
// | |
Data = *(GlyphBuffer + OffsetY + Xpos); | |
for (Index = 0; Index < Cell->Width % 8 && ((UINTN) (Xpos * 8 + Index + Cell->OffsetX) < RowWidth); Index++) { | |
if ((Data & (1 << (8 - Index - 1))) != 0) { | |
BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Foreground; | |
} else { | |
if (!Transparent) { | |
BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Background; | |
} | |
} | |
} | |
} // end of if (Width % 8...) | |
} // end of for (Ypos=0...) | |
*Origin = *Origin + Cell->AdvanceX; | |
} | |
/** | |
Convert bitmap data of the glyph to blt structure. | |
This is a internal function. | |
@param GlyphBuffer Buffer points to bitmap data of glyph. | |
@param Foreground The color of the "on" pixels in the glyph in the | |
bitmap. | |
@param Background The color of the "off" pixels in the glyph in the | |
bitmap. | |
@param ImageWidth Width of the whole image in pixels. | |
@param BaseLine BaseLine in the line. | |
@param RowWidth The width of the text on the line, in pixels. | |
@param RowHeight The height of the line, in pixels. | |
@param Transparent If TRUE, the Background color is ignored and all | |
"off" pixels in the character's drawn wil use the | |
pixel value from BltBuffer. | |
@param Cell Points to EFI_HII_GLYPH_INFO structure. | |
@param Attributes The attribute of incoming glyph in GlyphBuffer. | |
@param Origin On input, points to the origin of the to be | |
displayed character, on output, points to the | |
next glyph's origin. | |
@return Points to the address of next origin node in BltBuffer. | |
**/ | |
VOID | |
GlyphToImage ( | |
IN UINT8 *GlyphBuffer, | |
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground, | |
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background, | |
IN UINT16 ImageWidth, | |
IN UINT16 BaseLine, | |
IN UINTN RowWidth, | |
IN UINTN RowHeight, | |
IN BOOLEAN Transparent, | |
IN CONST EFI_HII_GLYPH_INFO *Cell, | |
IN UINT8 Attributes, | |
IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin | |
) | |
{ | |
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Buffer; | |
ASSERT (Origin != NULL && *Origin != NULL && Cell != NULL); | |
Buffer = *Origin; | |
if ((Attributes & EFI_GLYPH_NON_SPACING) == EFI_GLYPH_NON_SPACING) { | |
// | |
// This character is a non-spacing key, print it OR'd with the previous glyph. | |
// without advancing cursor. | |
// | |
Buffer -= Cell->AdvanceX; | |
GlyphToBlt ( | |
GlyphBuffer, | |
Foreground, | |
Background, | |
ImageWidth, | |
BaseLine, | |
RowWidth, | |
RowHeight, | |
Transparent, | |
Cell, | |
Attributes, | |
&Buffer | |
); | |
} else if ((Attributes & EFI_GLYPH_WIDE) == EFI_GLYPH_WIDE) { | |
// | |
// This character is wide glyph, i.e. 16 pixels * 19 pixels. | |
// Draw it as two narrow glyphs. | |
// | |
NarrowGlyphToBlt ( | |
GlyphBuffer, | |
Foreground, | |
Background, | |
ImageWidth, | |
RowWidth, | |
RowHeight, | |
Transparent, | |
Origin | |
); | |
NarrowGlyphToBlt ( | |
GlyphBuffer + EFI_GLYPH_HEIGHT, | |
Foreground, | |
Background, | |
ImageWidth, | |
RowWidth, | |
RowHeight, | |
Transparent, | |
Origin | |
); | |
} else if ((Attributes & NARROW_GLYPH) == NARROW_GLYPH) { | |
// | |
// This character is narrow glyph, i.e. 8 pixels * 19 pixels. | |
// | |
NarrowGlyphToBlt ( | |
GlyphBuffer, | |
Foreground, | |
Background, | |
ImageWidth, | |
RowWidth, | |
RowHeight, | |
Transparent, | |
Origin | |
); | |
} else if ((Attributes & PROPORTIONAL_GLYPH) == PROPORTIONAL_GLYPH) { | |
// | |
// This character is proportional glyph, i.e. Cell->Width * Cell->Height pixels. | |
// | |
GlyphToBlt ( | |
GlyphBuffer, | |
Foreground, | |
Background, | |
ImageWidth, | |
BaseLine, | |
RowWidth, | |
RowHeight, | |
Transparent, | |
Cell, | |
Attributes, | |
Origin | |
); | |
} | |
} | |
/** | |
Write the output parameters of FindGlyphBlock(). | |
This is a internal function. | |
@param BufferIn Buffer which stores the bitmap data of the found | |
block. | |
@param BufferLen Length of BufferIn. | |
@param InputCell Buffer which stores cell information of the | |
encoded bitmap. | |
@param GlyphBuffer Output the corresponding bitmap data of the found | |
block. It is the caller's responsiblity to free | |
this buffer. | |
@param Cell Output cell information of the encoded bitmap. | |
@param GlyphBufferLen If not NULL, output the length of GlyphBuffer. | |
@retval EFI_SUCCESS The operation is performed successfully. | |
@retval EFI_INVALID_PARAMETER Any input parameter is invalid. | |
@retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the | |
task. | |
**/ | |
EFI_STATUS | |
WriteOutputParam ( | |
IN UINT8 *BufferIn, | |
IN UINTN BufferLen, | |
IN EFI_HII_GLYPH_INFO *InputCell, | |
OUT UINT8 **GlyphBuffer, OPTIONAL | |
OUT EFI_HII_GLYPH_INFO *Cell, OPTIONAL | |
OUT UINTN *GlyphBufferLen OPTIONAL | |
) | |
{ | |
if (BufferIn == NULL || InputCell == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if (Cell != NULL) { | |
CopyMem (Cell, InputCell, sizeof (EFI_HII_GLYPH_INFO)); | |
} | |
if (GlyphBuffer != NULL && BufferLen > 0) { | |
*GlyphBuffer = (UINT8 *) AllocateZeroPool (BufferLen); | |
if (*GlyphBuffer == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
CopyMem (*GlyphBuffer, BufferIn, BufferLen); | |
} | |
if (GlyphBufferLen != NULL) { | |
*GlyphBufferLen = BufferLen; | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
Parse all glyph blocks to find a glyph block specified by CharValue. | |
If CharValue = (CHAR16) (-1), collect all default character cell information | |
within this font package and backup its information. | |
@param FontPackage Hii string package instance. | |
@param CharValue Unicode character value, which identifies a glyph | |
block. | |
@param GlyphBuffer Output the corresponding bitmap data of the found | |
block. It is the caller's responsiblity to free | |
this buffer. | |
@param Cell Output cell information of the encoded bitmap. | |
@param GlyphBufferLen If not NULL, output the length of GlyphBuffer. | |
@retval EFI_SUCCESS The bitmap data is retrieved successfully. | |
@retval EFI_NOT_FOUND The specified CharValue does not exist in current | |
database. | |
@retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the | |
task. | |
**/ | |
EFI_STATUS | |
FindGlyphBlock ( | |
IN HII_FONT_PACKAGE_INSTANCE *FontPackage, | |
IN CHAR16 CharValue, | |
OUT UINT8 **GlyphBuffer, OPTIONAL | |
OUT EFI_HII_GLYPH_INFO *Cell, OPTIONAL | |
OUT UINTN *GlyphBufferLen OPTIONAL | |
) | |
{ | |
EFI_STATUS Status; | |
UINT8 *BlockPtr; | |
UINT16 CharCurrent; | |
UINT16 Length16; | |
UINT32 Length32; | |
EFI_HII_GIBT_GLYPHS_BLOCK Glyphs; | |
UINTN BufferLen; | |
UINT16 Index; | |
EFI_HII_GLYPH_INFO DefaultCell; | |
EFI_HII_GLYPH_INFO LocalCell; | |
INT16 MinOffsetY; | |
UINT16 BaseLine; | |
ASSERT (FontPackage != NULL); | |
ASSERT (FontPackage->Signature == HII_FONT_PACKAGE_SIGNATURE); | |
BaseLine = 0; | |
MinOffsetY = 0; | |
if (CharValue == (CHAR16) (-1)) { | |
// | |
// Collect the cell information specified in font package fixed header. | |
// Use CharValue =0 to represent this particular cell. | |
// | |
Status = NewCell ( | |
0, | |
&FontPackage->GlyphInfoList, | |
(EFI_HII_GLYPH_INFO *) ((UINT8 *) FontPackage->FontPkgHdr + 3 * sizeof (UINT32)) | |
); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
CopyMem ( | |
&LocalCell, | |
(UINT8 *) FontPackage->FontPkgHdr + 3 * sizeof (UINT32), | |
sizeof (EFI_HII_GLYPH_INFO) | |
); | |
BaseLine = (UINT16) (LocalCell.Height + LocalCell.OffsetY); | |
if (MinOffsetY > LocalCell.OffsetY) { | |
MinOffsetY = LocalCell.OffsetY; | |
} | |
} | |
BlockPtr = FontPackage->GlyphBlock; | |
CharCurrent = 1; | |
BufferLen = 0; | |
while (*BlockPtr != EFI_HII_GIBT_END) { | |
switch (*BlockPtr) { | |
case EFI_HII_GIBT_DEFAULTS: | |
// | |
// Collect all default character cell information specified by | |
// EFI_HII_GIBT_DEFAULTS. | |
// | |
if (CharValue == (CHAR16) (-1)) { | |
Status = NewCell ( | |
CharCurrent, | |
&FontPackage->GlyphInfoList, | |
(EFI_HII_GLYPH_INFO *) (BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK)) | |
); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
CopyMem ( | |
&LocalCell, | |
BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), | |
sizeof (EFI_HII_GLYPH_INFO) | |
); | |
if (BaseLine < LocalCell.Height + LocalCell.OffsetY) { | |
BaseLine = (UINT16) (LocalCell.Height + LocalCell.OffsetY); | |
} | |
if (MinOffsetY > LocalCell.OffsetY) { | |
MinOffsetY = LocalCell.OffsetY; | |
} | |
} | |
BlockPtr += sizeof (EFI_HII_GIBT_DEFAULTS_BLOCK); | |
break; | |
case EFI_HII_GIBT_DUPLICATE: | |
if (CharCurrent == CharValue) { | |
CopyMem (&CharValue, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (CHAR16)); | |
CharCurrent = 1; | |
BlockPtr = FontPackage->GlyphBlock; | |
continue; | |
} | |
CharCurrent++; | |
BlockPtr += sizeof (EFI_HII_GIBT_DUPLICATE_BLOCK); | |
break; | |
case EFI_HII_GIBT_EXT1: | |
BlockPtr += *(BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8)); | |
break; | |
case EFI_HII_GIBT_EXT2: | |
CopyMem ( | |
&Length16, | |
BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8), | |
sizeof (UINT16) | |
); | |
BlockPtr += Length16; | |
break; | |
case EFI_HII_GIBT_EXT4: | |
CopyMem ( | |
&Length32, | |
BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8), | |
sizeof (UINT32) | |
); | |
BlockPtr += Length32; | |
break; | |
case EFI_HII_GIBT_GLYPH: | |
CopyMem ( | |
&LocalCell, | |
BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), | |
sizeof (EFI_HII_GLYPH_INFO) | |
); | |
if (CharValue == (CHAR16) (-1)) { | |
if (BaseLine < LocalCell.Height + LocalCell.OffsetY) { | |
BaseLine = (UINT16) (LocalCell.Height + LocalCell.OffsetY); | |
} | |
if (MinOffsetY > LocalCell.OffsetY) { | |
MinOffsetY = LocalCell.OffsetY; | |
} | |
} | |
BufferLen = BITMAP_LEN_1_BIT (LocalCell.Width, LocalCell.Height); | |
if (CharCurrent == CharValue) { | |
return WriteOutputParam ( | |
BlockPtr + sizeof (EFI_HII_GIBT_GLYPH_BLOCK) - sizeof (UINT8), | |
BufferLen, | |
&LocalCell, | |
GlyphBuffer, | |
Cell, | |
GlyphBufferLen | |
); | |
} | |
CharCurrent++; | |
BlockPtr += sizeof (EFI_HII_GIBT_GLYPH_BLOCK) - sizeof (UINT8) + BufferLen; | |
break; | |
case EFI_HII_GIBT_GLYPHS: | |
BlockPtr += sizeof (EFI_HII_GLYPH_BLOCK); | |
CopyMem (&Glyphs.Cell, BlockPtr, sizeof (EFI_HII_GLYPH_INFO)); | |
BlockPtr += sizeof (EFI_HII_GLYPH_INFO); | |
CopyMem (&Glyphs.Count, BlockPtr, sizeof (UINT16)); | |
BlockPtr += sizeof (UINT16); | |
if (CharValue == (CHAR16) (-1)) { | |
if (BaseLine < Glyphs.Cell.Height + Glyphs.Cell.OffsetY) { | |
BaseLine = (UINT16) (Glyphs.Cell.Height + Glyphs.Cell.OffsetY); | |
} | |
if (MinOffsetY > Glyphs.Cell.OffsetY) { | |
MinOffsetY = Glyphs.Cell.OffsetY; | |
} | |
} | |
BufferLen = BITMAP_LEN_1_BIT (Glyphs.Cell.Width, Glyphs.Cell.Height); | |
for (Index = 0; Index < Glyphs.Count; Index++) { | |
if (CharCurrent + Index == CharValue) { | |
return WriteOutputParam ( | |
BlockPtr, | |
BufferLen, | |
&Glyphs.Cell, | |
GlyphBuffer, | |
Cell, | |
GlyphBufferLen | |
); | |
} | |
BlockPtr += BufferLen; | |
} | |
CharCurrent = (UINT16) (CharCurrent + Glyphs.Count); | |
break; | |
case EFI_HII_GIBT_GLYPH_DEFAULT: | |
Status = GetCell (CharCurrent, &FontPackage->GlyphInfoList, &DefaultCell); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
BufferLen = BITMAP_LEN_1_BIT (DefaultCell.Width, DefaultCell.Height); | |
if (CharCurrent == CharValue) { | |
return WriteOutputParam ( | |
BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), | |
BufferLen, | |
&DefaultCell, | |
GlyphBuffer, | |
Cell, | |
GlyphBufferLen | |
); | |
} | |
CharCurrent++; | |
BlockPtr += sizeof (EFI_HII_GLYPH_BLOCK) + BufferLen; | |
break; | |
case EFI_HII_GIBT_GLYPHS_DEFAULT: | |
CopyMem (&Length16, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (UINT16)); | |
Status = GetCell (CharCurrent, &FontPackage->GlyphInfoList, &DefaultCell); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
BufferLen = BITMAP_LEN_1_BIT (DefaultCell.Width, DefaultCell.Height); | |
BlockPtr += sizeof (EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK) - sizeof (UINT8); | |
for (Index = 0; Index < Length16; Index++) { | |
if (CharCurrent + Index == CharValue) { | |
return WriteOutputParam ( | |
BlockPtr, | |
BufferLen, | |
&DefaultCell, | |
GlyphBuffer, | |
Cell, | |
GlyphBufferLen | |
); | |
} | |
BlockPtr += BufferLen; | |
} | |
CharCurrent = (UINT16) (CharCurrent + Length16); | |
break; | |
case EFI_HII_GIBT_SKIP1: | |
CharCurrent = (UINT16) (CharCurrent + (UINT16) (*(BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK)))); | |
BlockPtr += sizeof (EFI_HII_GIBT_SKIP1_BLOCK); | |
break; | |
case EFI_HII_GIBT_SKIP2: | |
CopyMem (&Length16, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (UINT16)); | |
CharCurrent = (UINT16) (CharCurrent + Length16); | |
BlockPtr += sizeof (EFI_HII_GIBT_SKIP2_BLOCK); | |
break; | |
default: | |
ASSERT (FALSE); | |
break; | |
} | |
if (CharValue < CharCurrent) { | |
return EFI_NOT_FOUND; | |
} | |
} | |
if (CharValue == (CHAR16) (-1)) { | |
FontPackage->BaseLine = BaseLine; | |
FontPackage->Height = (UINT16) (BaseLine - MinOffsetY); | |
return EFI_SUCCESS; | |
} | |
return EFI_NOT_FOUND; | |
} | |
/** | |
Copy a Font Name to a new created EFI_FONT_INFO structure. | |
This is a internal function. | |
@param FontName NULL-terminated string. | |
@param FontInfo a new EFI_FONT_INFO which stores the FontName. | |
It's caller's responsibility to free this buffer. | |
@retval EFI_SUCCESS FontInfo is allocated and copied with FontName. | |
@retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the | |
task. | |
**/ | |
EFI_STATUS | |
SaveFontName ( | |
IN EFI_STRING FontName, | |
OUT EFI_FONT_INFO **FontInfo | |
) | |
{ | |
UINTN FontInfoLen; | |
ASSERT (FontName != NULL && FontInfo != NULL); | |
FontInfoLen = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + StrSize (FontName); | |
*FontInfo = (EFI_FONT_INFO *) AllocateZeroPool (FontInfoLen); | |
if (*FontInfo == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
StrCpy ((*FontInfo)->FontName, FontName); | |
return EFI_SUCCESS; | |
} | |
/** | |
Retrieve system default font and color. | |
@param Private HII database driver private data. | |
@param FontInfo Points to system default font output-related | |
information. It's caller's responsibility to free | |
this buffer. | |
@param FontInfoSize If not NULL, output the size of buffer FontInfo. | |
@retval EFI_SUCCESS Cell information is added to the GlyphInfoList. | |
@retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the | |
task. | |
@retval EFI_INVALID_PARAMETER Any input parameter is invalid. | |
**/ | |
EFI_STATUS | |
GetSystemFont ( | |
IN HII_DATABASE_PRIVATE_DATA *Private, | |
OUT EFI_FONT_DISPLAY_INFO **FontInfo, | |
OUT UINTN *FontInfoSize OPTIONAL | |
) | |
{ | |
EFI_FONT_DISPLAY_INFO *Info; | |
UINTN InfoSize; | |
if (Private == NULL || Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if (FontInfo == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
// | |
// The standard font always has the name "sysdefault". | |
// | |
InfoSize = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + StrSize (L"sysdefault"); | |
Info = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (InfoSize); | |
if (Info == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
Info->ForegroundColor = mHiiEfiColors[Private->Attribute & 0x0f]; | |
Info->BackgroundColor = mHiiEfiColors[Private->Attribute >> 4]; | |
Info->FontInfoMask = EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_SYS_STYLE; | |
Info->FontInfo.FontStyle = 0; | |
Info->FontInfo.FontSize = EFI_GLYPH_HEIGHT; | |
StrCpy (Info->FontInfo.FontName, L"sysdefault"); | |
*FontInfo = Info; | |
if (FontInfoSize != NULL) { | |
*FontInfoSize = InfoSize; | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
Check whether EFI_FONT_DISPLAY_INFO points to system default font and color or | |
returns the system default according to the optional inputs. | |
This is a internal function. | |
@param Private HII database driver private data. | |
@param StringInfo Points to the string output information, | |
including the color and font. | |
@param SystemInfo If not NULL, points to system default font and color. | |
@param SystemInfoLen If not NULL, output the length of default system | |
info. | |
@retval TRUE Yes, it points to system default. | |
@retval FALSE No. | |
**/ | |
BOOLEAN | |
IsSystemFontInfo ( | |
IN HII_DATABASE_PRIVATE_DATA *Private, | |
IN EFI_FONT_DISPLAY_INFO *StringInfo, | |
OUT EFI_FONT_DISPLAY_INFO **SystemInfo, OPTIONAL | |
OUT UINTN *SystemInfoLen OPTIONAL | |
) | |
{ | |
EFI_STATUS Status; | |
EFI_FONT_DISPLAY_INFO *SystemDefault; | |
UINTN DefaultLen; | |
BOOLEAN Flag; | |
ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE); | |
if (StringInfo == NULL && SystemInfo == NULL) { | |
return TRUE; | |
} | |
Status = GetSystemFont (Private, &SystemDefault, &DefaultLen); | |
ASSERT_EFI_ERROR (Status); | |
// | |
// Record the system default info. | |
// | |
if (SystemInfo != NULL) { | |
*SystemInfo = SystemDefault; | |
} | |
if (SystemInfoLen != NULL) { | |
*SystemInfoLen = DefaultLen; | |
} | |
if (StringInfo == NULL) { | |
return TRUE; | |
} | |
Flag = FALSE; | |
// | |
// Check the FontInfoMask to see whether it is retrieving system info. | |
// | |
if ((StringInfo->FontInfoMask & (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) == 0) { | |
if (StrCmp (StringInfo->FontInfo.FontName, SystemDefault->FontInfo.FontName) != 0) { | |
goto Exit; | |
} | |
} | |
if ((StringInfo->FontInfoMask & (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) == 0) { | |
if (StringInfo->FontInfo.FontSize != SystemDefault->FontInfo.FontSize) { | |
goto Exit; | |
} | |
} | |
if ((StringInfo->FontInfoMask & (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) == 0) { | |
if (StringInfo->FontInfo.FontStyle != SystemDefault->FontInfo.FontStyle) { | |
goto Exit; | |
} | |
} | |
if ((StringInfo->FontInfoMask & EFI_FONT_INFO_SYS_FORE_COLOR) == 0) { | |
if (CompareMem ( | |
&StringInfo->ForegroundColor, | |
&SystemDefault->ForegroundColor, | |
sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) | |
) != 0) { | |
goto Exit; | |
} | |
} | |
if ((StringInfo->FontInfoMask & EFI_FONT_INFO_SYS_BACK_COLOR) == 0) { | |
if (CompareMem ( | |
&StringInfo->BackgroundColor, | |
&SystemDefault->BackgroundColor, | |
sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) | |
) != 0) { | |
goto Exit; | |
} | |
} | |
Flag = TRUE; | |
Exit: | |
if (SystemInfo == NULL) { | |
if (SystemDefault != NULL) { | |
FreePool (SystemDefault); | |
} | |
} | |
return Flag; | |
} | |
/** | |
This function checks whether EFI_FONT_INFO exists in current database. If | |
FontInfoMask is specified, check what options can be used to make a match. | |
Note that the masks relate to where the system default should be supplied | |
are ignored by this function. | |
@param Private Hii database private structure. | |
@param FontInfo Points to EFI_FONT_INFO structure. | |
@param FontInfoMask If not NULL, describes what options can be used | |
to make a match between the font requested and | |
the font available. The caller must guarantee | |
this mask is valid. | |
@param FontHandle On entry, Points to the font handle returned by a | |
previous call to GetFontInfo() or NULL to start | |
with the first font. | |
@param GlobalFontInfo If not NULL, output the corresponding globa font | |
info. | |
@retval TRUE Existed | |
@retval FALSE Not existed | |
**/ | |
BOOLEAN | |
IsFontInfoExisted ( | |
IN HII_DATABASE_PRIVATE_DATA *Private, | |
IN EFI_FONT_INFO *FontInfo, | |
IN EFI_FONT_INFO_MASK *FontInfoMask, OPTIONAL | |
IN EFI_FONT_HANDLE FontHandle, OPTIONAL | |
OUT HII_GLOBAL_FONT_INFO **GlobalFontInfo OPTIONAL | |
) | |
{ | |
HII_GLOBAL_FONT_INFO *GlobalFont; | |
HII_GLOBAL_FONT_INFO *GlobalFontBackup1; | |
HII_GLOBAL_FONT_INFO *GlobalFontBackup2; | |
LIST_ENTRY *Link; | |
EFI_FONT_INFO_MASK Mask; | |
BOOLEAN Matched; | |
BOOLEAN VagueMatched1; | |
BOOLEAN VagueMatched2; | |
ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE); | |
ASSERT (FontInfo != NULL); | |
// | |
// Matched flag represents an exactly match; VagueMatched1 repensents a RESIZE | |
// or RESTYLE match; VagueMatched2 represents a RESIZE | RESTYLE match. | |
// | |
Matched = FALSE; | |
VagueMatched1 = FALSE; | |
VagueMatched2 = FALSE; | |
Mask = 0; | |
GlobalFontBackup1 = NULL; | |
GlobalFontBackup2 = NULL; | |
// The process of where the system default should be supplied instead of | |
// the specified font info beyonds this function's scope. | |
// | |
if (FontInfoMask != NULL) { | |
Mask = *FontInfoMask & (~SYS_FONT_INFO_MASK); | |
} | |
// | |
// If not NULL, FontHandle points to the next node of the last searched font | |
// node by previous call. | |
// | |
if (FontHandle == NULL) { | |
Link = Private->FontInfoList.ForwardLink; | |
} else { | |
Link = (LIST_ENTRY *) FontHandle; | |
} | |
for (; Link != &Private->FontInfoList; Link = Link->ForwardLink) { | |
GlobalFont = CR (Link, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE); | |
if (FontInfoMask == NULL) { | |
if (CompareMem (GlobalFont->FontInfo, FontInfo, GlobalFont->FontInfoSize) == 0) { | |
if (GlobalFontInfo != NULL) { | |
*GlobalFontInfo = GlobalFont; | |
} | |
return TRUE; | |
} | |
} else { | |
// | |
// Check which options could be used to make a match. | |
// | |
switch (Mask) { | |
case EFI_FONT_INFO_ANY_FONT: | |
if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle && | |
GlobalFont->FontInfo->FontSize == FontInfo->FontSize) { | |
Matched = TRUE; | |
} | |
break; | |
case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_STYLE: | |
if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) { | |
Matched = TRUE; | |
} | |
break; | |
case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE: | |
if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) { | |
Matched = TRUE; | |
} | |
break; | |
case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_ANY_STYLE: | |
Matched = TRUE; | |
break; | |
// | |
// If EFI_FONT_INFO_RESTYLE is specified, then the system may attempt to | |
// remove some of the specified styles to meet the style requested. | |
// | |
case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESTYLE: | |
if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) { | |
if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) { | |
Matched = TRUE; | |
} else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) { | |
VagueMatched1 = TRUE; | |
GlobalFontBackup1 = GlobalFont; | |
} | |
} | |
break; | |
// | |
// If EFI_FONT_INFO_RESIZE is specified, then the sytem may attempt to | |
// stretch or shrink a font to meet the size requested. | |
// | |
case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESIZE: | |
if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) { | |
if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) { | |
Matched = TRUE; | |
} else { | |
VagueMatched1 = TRUE; | |
GlobalFontBackup1 = GlobalFont; | |
} | |
} | |
break; | |
case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_RESIZE: | |
if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) { | |
if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) { | |
Matched = TRUE; | |
} else { | |
VagueMatched1 = TRUE; | |
GlobalFontBackup1 = GlobalFont; | |
} | |
} else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) { | |
if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) { | |
VagueMatched1 = TRUE; | |
GlobalFontBackup1 = GlobalFont; | |
} else { | |
VagueMatched2 = TRUE; | |
GlobalFontBackup2 = GlobalFont; | |
} | |
} | |
break; | |
case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_RESIZE: | |
if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) { | |
Matched = TRUE; | |
} else { | |
VagueMatched1 = TRUE; | |
GlobalFontBackup1 = GlobalFont; | |
} | |
break; | |
case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_RESTYLE: | |
if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) { | |
Matched = TRUE; | |
} else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) { | |
VagueMatched1 = TRUE; | |
GlobalFontBackup1 = GlobalFont; | |
} | |
break; | |
case EFI_FONT_INFO_ANY_STYLE: | |
if ((CompareMem ( | |
GlobalFont->FontInfo->FontName, | |
FontInfo->FontName, | |
StrSize (FontInfo->FontName) | |
) == 0) && | |
GlobalFont->FontInfo->FontSize == FontInfo->FontSize) { | |
Matched = TRUE; | |
} | |
break; | |
case EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_ANY_SIZE: | |
if (CompareMem ( | |
GlobalFont->FontInfo->FontName, | |
FontInfo->FontName, | |
StrSize (FontInfo->FontName) | |
) == 0) { | |
Matched = TRUE; | |
} | |
break; | |
case EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_RESIZE: | |
if (CompareMem ( | |
GlobalFont->FontInfo->FontName, | |
FontInfo->FontName, | |
StrSize (FontInfo->FontName) | |
) == 0) { | |
if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) { | |
Matched = TRUE; | |
} else { | |
VagueMatched1 = TRUE; | |
GlobalFontBackup1 = GlobalFont; | |
} | |
} | |
break; | |
case EFI_FONT_INFO_ANY_SIZE: | |
if ((CompareMem ( | |
GlobalFont->FontInfo->FontName, | |
FontInfo->FontName, | |
StrSize (FontInfo->FontName) | |
) == 0) && | |
GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) { | |
Matched = TRUE; | |
} | |
break; | |
case EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_RESTYLE: | |
if (CompareMem ( | |
GlobalFont->FontInfo->FontName, | |
FontInfo->FontName, | |
StrSize (FontInfo->FontName) | |
) == 0) { | |
if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) { | |
Matched = TRUE; | |
} else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) { | |
VagueMatched1 = TRUE; | |
GlobalFontBackup1 = GlobalFont; | |
} | |
} | |
break; | |
case EFI_FONT_INFO_RESTYLE: | |
if ((CompareMem ( | |
GlobalFont->FontInfo->FontName, | |
FontInfo->FontName, | |
StrSize (FontInfo->FontName) | |
) == 0) && | |
GlobalFont->FontInfo->FontSize == FontInfo->FontSize) { | |
if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) { | |
Matched = TRUE; | |
} else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) { | |
VagueMatched1 = TRUE; | |
GlobalFontBackup1 = GlobalFont; | |
} | |
} | |
break; | |
case EFI_FONT_INFO_RESIZE: | |
if ((CompareMem ( | |
GlobalFont->FontInfo->FontName, | |
FontInfo->FontName, | |
StrSize (FontInfo->FontName) | |
) == 0) && | |
GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) { | |
if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) { | |
Matched = TRUE; | |
} else { | |
VagueMatched1 = TRUE; | |
GlobalFontBackup1 = GlobalFont; | |
} | |
} | |
break; | |
case EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_RESTYLE: | |
if (CompareMem ( | |
GlobalFont->FontInfo->FontName, | |
FontInfo->FontName, | |
StrSize (FontInfo->FontName) | |
) == 0) { | |
if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) { | |
if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) { | |
Matched = TRUE; | |
} else { | |
VagueMatched1 = TRUE; | |
GlobalFontBackup1 = GlobalFont; | |
} | |
} else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) { | |
if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) { | |
VagueMatched1 = TRUE; | |
GlobalFontBackup1 = GlobalFont; | |
} else { | |
VagueMatched2 = TRUE; | |
GlobalFontBackup2 = GlobalFont; | |
} | |
} | |
} | |
break; | |
default: | |
break; | |
} | |
if (Matched) { | |
if (GlobalFontInfo != NULL) { | |
*GlobalFontInfo = GlobalFont; | |
} | |
return TRUE; | |
} | |
} | |
} | |
if (VagueMatched1) { | |
if (GlobalFontInfo != NULL) { | |
*GlobalFontInfo = GlobalFontBackup1; | |
} | |
return TRUE; | |
} else if (VagueMatched2) { | |
if (GlobalFontInfo != NULL) { | |
*GlobalFontInfo = GlobalFontBackup2; | |
} | |
return TRUE; | |
} | |
return FALSE; | |
} | |
/** | |
Check whether the unicode represents a line break or not. | |
This is a internal function. Please see Section 27.2.6 of the UEFI Specification | |
for a description of the supported string format. | |
@param Char Unicode character | |
@retval 0 Yes, it forces a line break. | |
@retval 1 Yes, it presents a line break opportunity | |
@retval 2 Yes, it requires a line break happen before and after it. | |
@retval -1 No, it is not a link break. | |
**/ | |
INT8 | |
IsLineBreak ( | |
IN CHAR16 Char | |
) | |
{ | |
switch (Char) { | |
// | |
// Mandatory line break characters, which force a line-break | |
// | |
case 0x000C: | |
case 0x000D: | |
case 0x2028: | |
case 0x2029: | |
return 0; | |
// | |
// Space characters, which is taken as a line-break opportunity | |
// | |
case 0x0020: | |
case 0x1680: | |
case 0x2000: | |
case 0x2001: | |
case 0x2002: | |
case 0x2003: | |
case 0x2004: | |
case 0x2005: | |
case 0x2006: | |
case 0x2008: | |
case 0x2009: | |
case 0x200A: | |
case 0x205F: | |
// | |
// In-Word Break Opportunities | |
// | |
case 0x200B: | |
return 1; | |
// | |
// A space which is not a line-break opportunity | |
// | |
case 0x00A0: | |
case 0x202F: | |
// | |
// A hyphen which is not a line-break opportunity | |
// | |
case 0x2011: | |
return -1; | |
// | |
// Hyphen characters which describe line break opportunities after the character | |
// | |
case 0x058A: | |
case 0x2010: | |
case 0x2012: | |
case 0x2013: | |
case 0x0F0B: | |
case 0x1361: | |
case 0x17D5: | |
return 1; | |
// | |
// A hyphen which describes line break opportunities before and after them, but not between a pair of them | |
// | |
case 0x2014: | |
return 2; | |
} | |
return -1; | |
} | |
/** | |
Renders a string to a bitmap or to the display. | |
@param This A pointer to the EFI_HII_FONT_PROTOCOL instance. | |
@param Flags Describes how the string is to be drawn. | |
@param String Points to the null-terminated string to be | |
displayed. | |
@param StringInfo Points to the string output information, | |
including the color and font. If NULL, then the | |
string will be output in the default system font | |
and color. | |
@param Blt If this points to a non-NULL on entry, this | |
points to the image, which is Width pixels wide | |
and Height pixels high. The string will be drawn | |
onto this image and | |
EFI_HII_OUT_FLAG_CLIP is implied. If this points | |
to a NULL on entry, then a buffer | |
will be allocated to hold the generated image and | |
the pointer updated on exit. It is the caller's | |
responsibility to free this buffer. | |
@param BltX Specifies the offset from the left and top edge | |
of the image of the first character cell in the | |
image. | |
@param BltY Specifies the offset from the left and top edge | |
of the image of the first character cell in the | |
image. | |
@param RowInfoArray If this is non-NULL on entry, then on exit, this | |
will point to an allocated buffer containing | |
row information and RowInfoArraySize will be | |
updated to contain the number of elements. | |
This array describes the characters which were at | |
least partially drawn and the heights of the | |
rows. It is the caller's responsibility to free | |
this buffer. | |
@param RowInfoArraySize If this is non-NULL on entry, then on exit it | |
contains the number of elements in RowInfoArray. | |
@param ColumnInfoArray If this is non-NULL, then on return it will be | |
filled with the horizontal offset for each | |
character in the string on the row where it is | |
displayed. Non-printing characters will have | |
the offset ~0. The caller is responsible to | |
allocate a buffer large enough so that there | |
is one entry for each character in the string, | |
not including the null-terminator. It is possible | |
when character display is normalized that some | |
character cells overlap. | |
@retval EFI_SUCCESS The string was successfully rendered. | |
@retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for | |
RowInfoArray or Blt. | |
@retval EFI_INVALID_PARAMETER The String or Blt was NULL. | |
@retval EFI_INVALID_PARAMETER Flags were invalid combination.. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
HiiStringToImage ( | |
IN CONST EFI_HII_FONT_PROTOCOL *This, | |
IN EFI_HII_OUT_FLAGS Flags, | |
IN CONST EFI_STRING String, | |
IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL, | |
IN OUT EFI_IMAGE_OUTPUT **Blt, | |
IN UINTN BltX, | |
IN UINTN BltY, | |
OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL, | |
OUT UINTN *RowInfoArraySize OPTIONAL, | |
OUT UINTN *ColumnInfoArray OPTIONAL | |
) | |
{ | |
EFI_STATUS Status; | |
HII_DATABASE_PRIVATE_DATA *Private; | |
UINT8 **GlyphBuf; | |
EFI_HII_GLYPH_INFO *Cell; | |
UINT8 *Attributes; | |
EFI_IMAGE_OUTPUT *Image; | |
EFI_STRING StringPtr; | |
EFI_STRING StringTmp; | |
EFI_HII_ROW_INFO *RowInfo; | |
UINTN LineWidth; | |
UINTN LineHeight; | |
UINTN LineOffset; | |
UINTN LastLineHeight; | |
UINTN BaseLineOffset; | |
UINT16 MaxRowNum; | |
UINT16 RowIndex; | |
UINTN Index; | |
UINTN NextIndex; | |
UINTN Index1; | |
EFI_FONT_DISPLAY_INFO *StringInfoOut; | |
EFI_FONT_DISPLAY_INFO *SystemDefault; | |
EFI_FONT_HANDLE FontHandle; | |
EFI_STRING StringIn; | |
EFI_STRING StringIn2; | |
UINT16 Height; | |
UINT16 BaseLine; | |
EFI_FONT_INFO *FontInfo; | |
BOOLEAN SysFontFlag; | |
EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground; | |
EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; | |
BOOLEAN Transparent; | |
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer; | |
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BufferPtr; | |
UINTN RowInfoSize; | |
BOOLEAN LineBreak; | |
UINTN StrLength; | |
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *RowBufferPtr; | |
HII_GLOBAL_FONT_INFO *GlobalFont; | |
// | |
// Check incoming parameters. | |
// | |
if (This == NULL || String == NULL || Blt == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if (*Blt == NULL) { | |
// | |
// These two flag cannot be used if Blt is NULL upon entry. | |
// | |
if ((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if ((Flags & EFI_HII_OUT_FLAG_CLIP) == EFI_HII_OUT_FLAG_CLIP) { | |
return EFI_INVALID_PARAMETER; | |
} | |
} | |
// | |
// These two flags require that EFI_HII_OUT_FLAG_CLIP be also set. | |
// | |
if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) == EFI_HII_OUT_FLAG_CLIP_CLEAN_X) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLIP_CLEAN_Y)) == EFI_HII_OUT_FLAG_CLIP_CLEAN_Y) { | |
return EFI_INVALID_PARAMETER; | |
} | |
// | |
// This flag cannot be used with EFI_HII_OUT_FLAG_CLEAN_X. | |
// | |
if ((Flags & (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) == (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if (*Blt == NULL) { | |
// | |
// Create a new bitmap and draw the string onto this image. | |
// | |
Image = AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT)); | |
if (Image == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
Image->Width = 800; | |
Image->Height = 600; | |
Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height *sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); | |
if (Image->Image.Bitmap == NULL) { | |
FreePool (Image); | |
return EFI_OUT_OF_RESOURCES; | |
} | |
// | |
// Other flags are not permitted when Blt is NULL. | |
// | |
Flags &= EFI_HII_OUT_FLAG_WRAP | EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_IGNORE_LINE_BREAK; | |
*Blt = Image; | |
} | |
StrLength = StrLen(String); | |
GlyphBuf = (UINT8 **) AllocateZeroPool (StrLength * sizeof (UINT8 *)); | |
ASSERT (GlyphBuf != NULL); | |
Cell = (EFI_HII_GLYPH_INFO *) AllocateZeroPool (StrLength * sizeof (EFI_HII_GLYPH_INFO)); | |
ASSERT (Cell != NULL); | |
Attributes = (UINT8 *) AllocateZeroPool (StrLength * sizeof (UINT8)); | |
ASSERT (Attributes != NULL); | |
RowInfo = NULL; | |
Status = EFI_SUCCESS; | |
StringIn2 = NULL; | |
SystemDefault = NULL; | |
StringIn = NULL; | |
// | |
// Calculate the string output information, including specified color and font . | |
// If StringInfo does not points to system font info, it must indicate an existing | |
// EFI_FONT_INFO. | |
// | |
StringInfoOut = NULL; | |
FontHandle = NULL; | |
Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This); | |
SysFontFlag = IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfo, &SystemDefault, NULL); | |
if (SysFontFlag) { | |
FontInfo = NULL; | |
Height = SystemDefault->FontInfo.FontSize; | |
BaseLine = SystemDefault->FontInfo.FontSize; | |
Foreground = SystemDefault->ForegroundColor; | |
Background = SystemDefault->BackgroundColor; | |
} else { | |
// | |
// StringInfo must not be NULL if it is not system info. | |
// | |
ASSERT (StringInfo != NULL); | |
Status = HiiGetFontInfo (This, &FontHandle, (EFI_FONT_DISPLAY_INFO *) StringInfo, &StringInfoOut, NULL); | |
if (Status == EFI_NOT_FOUND) { | |
// | |
// The specified EFI_FONT_DISPLAY_INFO does not exist in current database. | |
// Use the system font instead. Still use the color specified by StringInfo. | |
// | |
SysFontFlag = TRUE; | |
FontInfo = NULL; | |
Height = SystemDefault->FontInfo.FontSize; | |
BaseLine = SystemDefault->FontInfo.FontSize; | |
Foreground = ((EFI_FONT_DISPLAY_INFO *) StringInfo)->ForegroundColor; | |
Background = ((EFI_FONT_DISPLAY_INFO *) StringInfo)->BackgroundColor; | |
} else if (Status == EFI_SUCCESS) { | |
FontInfo = &StringInfoOut->FontInfo; | |
IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont); | |
Height = GlobalFont->FontPackage->Height; | |
BaseLine = GlobalFont->FontPackage->BaseLine; | |
Foreground = StringInfoOut->ForegroundColor; | |
Background = StringInfoOut->BackgroundColor; | |
} else { | |
goto Exit; | |
} | |
} | |
// | |
// Use the maxinum height of font as the base line. | |
// And, use the maxinum height as line height. | |
// | |
LineHeight = Height; | |
LastLineHeight = Height; | |
BaseLineOffset = Height - BaseLine; | |
// | |
// Parse the string to be displayed to drop some ignored characters. | |
// | |
StringPtr = String; | |
// | |
// Ignore line-break characters only. Hyphens or dash character will be displayed | |
// without line-break opportunity. | |
// | |
if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == EFI_HII_IGNORE_LINE_BREAK) { | |
StringIn = AllocateZeroPool (StrSize (StringPtr)); | |
if (StringIn == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Exit; | |
} | |
StringTmp = StringIn; | |
while (*StringPtr != 0) { | |
if (IsLineBreak (*StringPtr) == 0) { | |
StringPtr++; | |
} else { | |
*StringTmp++ = *StringPtr++; | |
} | |
} | |
*StringTmp = 0; | |
StringPtr = StringIn; | |
} | |
// | |
// If EFI_HII_IGNORE_IF_NO_GLYPH is set, then characters which have no glyphs | |
// are not drawn. Otherwise they are replaced wth Unicode character 0xFFFD. | |
// | |
StringIn2 = AllocateZeroPool (StrSize (StringPtr)); | |
if (StringIn2 == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Exit; | |
} | |
Index = 0; | |
StringTmp = StringIn2; | |
StrLength = StrLen(StringPtr); | |
while (*StringPtr != 0 && Index < StrLength) { | |
if (IsLineBreak (*StringPtr) == 0) { | |
*StringTmp++ = *StringPtr++; | |
Index++; | |
continue; | |
} | |
Status = GetGlyphBuffer (Private, *StringPtr, FontInfo, &GlyphBuf[Index], &Cell[Index], &Attributes[Index]); | |
if (Status == EFI_NOT_FOUND) { | |
if ((Flags & EFI_HII_IGNORE_IF_NO_GLYPH) == EFI_HII_IGNORE_IF_NO_GLYPH) { | |
GlyphBuf[Index] = NULL; | |
ZeroMem (&Cell[Index], sizeof (Cell[Index])); | |
Status = EFI_SUCCESS; | |
} else { | |
// | |
// Unicode 0xFFFD must exist in current hii database if this flag is not set. | |
// | |
Status = GetGlyphBuffer ( | |
Private, | |
REPLACE_UNKNOWN_GLYPH, | |
FontInfo, | |
&GlyphBuf[Index], | |
&Cell[Index], | |
&Attributes[Index] | |
); | |
if (EFI_ERROR (Status)) { | |
Status = EFI_INVALID_PARAMETER; | |
} | |
} | |
} | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
*StringTmp++ = *StringPtr++; | |
Index++; | |
} | |
*StringTmp = 0; | |
StringPtr = StringIn2; | |
// | |
// Draw the string according to the specified EFI_HII_OUT_FLAGS and Blt. | |
// If Blt is not NULL, then EFI_HII_OUT_FLAG_CLIP is implied, render this string | |
// to an existing image (bitmap or screen depending on flags) pointed by "*Blt". | |
// Otherwise render this string to a new allocated image and output it. | |
// | |
Image = *Blt; | |
BufferPtr = Image->Image.Bitmap + Image->Width * BltY + BltX; | |
if (Image->Height < BltY) { | |
// | |
// the top edge of the image should be in Image resolution scope. | |
// | |
Status = EFI_INVALID_PARAMETER; | |
goto Exit; | |
} | |
MaxRowNum = (UINT16) ((Image->Height - BltY) / Height); | |
if ((Image->Height - BltY) % Height != 0) { | |
LastLineHeight = (Image->Height - BltY) % Height; | |
MaxRowNum++; | |
} | |
RowInfo = (EFI_HII_ROW_INFO *) AllocateZeroPool (MaxRowNum * sizeof (EFI_HII_ROW_INFO)); | |
if (RowInfo == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Exit; | |
} | |
// | |
// Format the glyph buffer according to flags. | |
// | |
Transparent = (BOOLEAN) ((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT ? TRUE : FALSE); | |
for (RowIndex = 0, Index = 0; RowIndex < MaxRowNum && StringPtr[Index] != 0; ) { | |
LineWidth = 0; | |
LineBreak = FALSE; | |
// | |
// Clip the final row if the row's bottom-most on pixel cannot fit when | |
// EFI_HII_OUT_FLAG_CLEAN_Y is set. | |
// | |
if (RowIndex == MaxRowNum - 1) { | |
if ((Flags & EFI_HII_OUT_FLAG_CLIP_CLEAN_Y) == EFI_HII_OUT_FLAG_CLIP_CLEAN_Y && LastLineHeight < LineHeight ) { | |
// | |
// Don't draw at all if the row's bottom-most on pixel cannot fit. | |
// | |
break; | |
} | |
LineHeight = LastLineHeight; | |
} | |
// | |
// Calculate how many characters there are in a row. | |
// | |
RowInfo[RowIndex].StartIndex = Index; | |
while (LineWidth + BltX < Image->Width && StringPtr[Index] != 0) { | |
if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0 && | |
IsLineBreak (StringPtr[Index]) == 0) { | |
// | |
// It forces a line break that ends this row. | |
// | |
Index++; | |
LineBreak = TRUE; | |
break; | |
} | |
// | |
// If the glyph of the character is existing, then accumulate the actual printed width | |
// | |
LineWidth += (UINTN) Cell[Index].AdvanceX; | |
Index++; | |
} | |
// | |
// Record index of next char. | |
// | |
NextIndex = Index; | |
// | |
// Return to the previous char. | |
// | |
Index--; | |
if (LineBreak && Index > 0 ) { | |
// | |
// Return the previous non line break char. | |
// | |
Index --; | |
} | |
// | |
// If this character is the last character of a row, we need not | |
// draw its (AdvanceX - Width - OffsetX) for next character. | |
// | |
LineWidth -= (UINTN) (Cell[Index].AdvanceX - Cell[Index].Width - Cell[Index].OffsetX); | |
// | |
// Clip the right-most character if cannot fit when EFI_HII_OUT_FLAG_CLEAN_X is set. | |
// | |
if (LineWidth + BltX <= Image->Width || | |
(LineWidth + BltX > Image->Width && (Flags & EFI_HII_OUT_FLAG_CLIP_CLEAN_X) == 0)) { | |
// | |
// Record right-most character in RowInfo even if it is partially displayed. | |
// | |
RowInfo[RowIndex].EndIndex = Index; | |
RowInfo[RowIndex].LineWidth = LineWidth; | |
RowInfo[RowIndex].LineHeight = LineHeight; | |
RowInfo[RowIndex].BaselineOffset = BaseLineOffset; | |
} else { | |
// | |
// When EFI_HII_OUT_FLAG_CLEAN_X is set, it will not draw a character | |
// if its right-most on pixel cannot fit. | |
// | |
if (Index > RowInfo[RowIndex].StartIndex) { | |
// | |
// Don't draw the last char on this row. And, don't draw the second last char (AdvanceX - Width - OffsetX). | |
// | |
LineWidth -= (UINTN) (Cell[Index].Width + Cell[Index].OffsetX); | |
LineWidth -= (UINTN) (Cell[Index - 1].AdvanceX - Cell[Index - 1].Width - Cell[Index - 1].OffsetX); | |
RowInfo[RowIndex].EndIndex = Index - 1; | |
RowInfo[RowIndex].LineWidth = LineWidth; | |
RowInfo[RowIndex].LineHeight = LineHeight; | |
RowInfo[RowIndex].BaselineOffset = BaseLineOffset; | |
} else { | |
// | |
// There is no enough column to draw any character, so set current line width to zero. | |
// And go to draw Next line if LineBreak is set. | |
// | |
RowInfo[RowIndex].LineWidth = 0; | |
goto NextLine; | |
} | |
} | |
// | |
// EFI_HII_OUT_FLAG_WRAP will wrap the text at the right-most line-break | |
// opportunity prior to a character whose right-most extent would exceed Width. | |
// Search the right-most line-break opportunity here. | |
// | |
if ((Flags & EFI_HII_OUT_FLAG_WRAP) == EFI_HII_OUT_FLAG_WRAP && | |
(RowInfo[RowIndex].LineWidth + BltX > Image->Width || StringPtr[NextIndex] != 0) && | |
!LineBreak) { | |
if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0) { | |
LineWidth = RowInfo[RowIndex].LineWidth; | |
for (Index1 = RowInfo[RowIndex].EndIndex; Index1 >= RowInfo[RowIndex].StartIndex; Index1--) { | |
if (Index1 == RowInfo[RowIndex].EndIndex) { | |
LineWidth -= (Cell[Index1].Width + Cell[Index1].OffsetX); | |
} else { | |
LineWidth -= Cell[Index1].AdvanceX; | |
} | |
if (IsLineBreak (StringPtr[Index1]) > 0) { | |
LineBreak = TRUE; | |
if (Index1 > RowInfo[RowIndex].StartIndex) { | |
RowInfo[RowIndex].EndIndex = Index1 - 1; | |
} | |
// | |
// relocate to the character after the right-most line break opportunity of this line | |
// | |
NextIndex = Index1 + 1; | |
break; | |
} | |
// | |
// If don't find a line break opportunity from EndIndex to StartIndex, | |
// then jump out. | |
// | |
if (Index1 == RowInfo[RowIndex].StartIndex) | |
break; | |
} | |
// | |
// Update LineWidth to the real width | |
// | |
if (IsLineBreak (StringPtr[Index1]) > 0) { | |
if (Index1 == RowInfo[RowIndex].StartIndex) { | |
LineWidth = 0; | |
} else { | |
LineWidth -= (UINTN) (Cell[Index1 - 1].AdvanceX - Cell[Index1 - 1].Width - Cell[Index1 - 1].OffsetX); | |
} | |
RowInfo[RowIndex].LineWidth = LineWidth; | |
} | |
} | |
// | |
// If no line-break opportunity can be found, then the text will | |
// behave as if EFI_HII_OUT_FLAG_CLEAN_X is set. | |
// | |
if (!LineBreak) { | |
LineWidth = RowInfo[RowIndex].LineWidth; | |
Index1 = RowInfo[RowIndex].EndIndex; | |
if (LineWidth + BltX > Image->Width) { | |
if (Index1 > RowInfo[RowIndex].StartIndex) { | |
// | |
// Don't draw the last char on this row. And, don't draw the second last char (AdvanceX - Width - OffsetX). | |
// | |
LineWidth -= (UINTN) (Cell[Index1].Width + Cell[Index1].OffsetX); | |
LineWidth -= (UINTN) (Cell[Index1 - 1].AdvanceX - Cell[Index1 - 1].Width - Cell[Index1 - 1].OffsetX); | |
RowInfo[RowIndex].EndIndex = Index1 - 1; | |
RowInfo[RowIndex].LineWidth = LineWidth; | |
} else { | |
// | |
// There is no enough column to draw any character, so set current line width to zero. | |
// And go to draw Next line if LineBreak is set. | |
// | |
RowInfo[RowIndex].LineWidth = 0; | |
goto NextLine; | |
} | |
} | |
} | |
} | |
// | |
// LineWidth can't exceed Image width. | |
// | |
if (RowInfo[RowIndex].LineWidth + BltX > Image->Width) { | |
RowInfo[RowIndex].LineWidth = Image->Width - BltX; | |
} | |
// | |
// Draw it to screen or existing bitmap depending on whether | |
// EFI_HII_DIRECT_TO_SCREEN is set. | |
// | |
LineOffset = 0; | |
if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) { | |
BltBuffer = NULL; | |
if (RowInfo[RowIndex].LineWidth != 0) { | |
BltBuffer = AllocateZeroPool (RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); | |
if (BltBuffer == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Exit; | |
} | |
// | |
// Set BufferPtr to Origin by adding baseline to the starting position. | |
// | |
BufferPtr = BltBuffer + BaseLine * RowInfo[RowIndex].LineWidth; | |
} | |
for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) { | |
if (RowInfo[RowIndex].LineWidth > 0 && RowInfo[RowIndex].LineWidth > LineOffset) { | |
// | |
// Only BLT these character which have corrsponding glyph in font basebase. | |
// | |
GlyphToImage ( | |
GlyphBuf[Index1], | |
Foreground, | |
Background, | |
(UINT16) RowInfo[RowIndex].LineWidth, | |
BaseLine, | |
RowInfo[RowIndex].LineWidth - LineOffset, | |
RowInfo[RowIndex].LineHeight, | |
Transparent, | |
&Cell[Index1], | |
Attributes[Index1], | |
&BufferPtr | |
); | |
} | |
if (ColumnInfoArray != NULL) { | |
if ((GlyphBuf[Index1] == NULL && Cell[Index1].AdvanceX == 0) | |
|| RowInfo[RowIndex].LineWidth == 0) { | |
*ColumnInfoArray = (UINTN) ~0; | |
} else { | |
*ColumnInfoArray = LineOffset + Cell[Index1].OffsetX + BltX; | |
} | |
ColumnInfoArray++; | |
} | |
LineOffset += Cell[Index1].AdvanceX; | |
} | |
if (BltBuffer != NULL) { | |
Status = Image->Image.Screen->Blt ( | |
Image->Image.Screen, | |
BltBuffer, | |
EfiBltBufferToVideo, | |
0, | |
0, | |
BltX, | |
BltY, | |
RowInfo[RowIndex].LineWidth, | |
RowInfo[RowIndex].LineHeight, | |
0 | |
); | |
if (EFI_ERROR (Status)) { | |
FreePool (BltBuffer); | |
goto Exit; | |
} | |
FreePool (BltBuffer); | |
} | |
} else { | |
// | |
// Save the starting position for calculate the starting postition of next row. | |
// | |
RowBufferPtr = BufferPtr; | |
// | |
// Set BufferPtr to Origin by adding baseline to the starting position. | |
// | |
BufferPtr = BufferPtr + BaseLine * Image->Width; | |
for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) { | |
if (RowInfo[RowIndex].LineWidth > 0 && RowInfo[RowIndex].LineWidth > LineOffset) { | |
// | |
// Only BLT these character which have corrsponding glyph in font basebase. | |
// | |
GlyphToImage ( | |
GlyphBuf[Index1], | |
Foreground, | |
Background, | |
Image->Width, | |
BaseLine, | |
RowInfo[RowIndex].LineWidth - LineOffset, | |
RowInfo[RowIndex].LineHeight, | |
Transparent, | |
&Cell[Index1], | |
Attributes[Index1], | |
&BufferPtr | |
); | |
} | |
if (ColumnInfoArray != NULL) { | |
if ((GlyphBuf[Index1] == NULL && Cell[Index1].AdvanceX == 0) | |
|| RowInfo[RowIndex].LineWidth == 0) { | |
*ColumnInfoArray = (UINTN) ~0; | |
} else { | |
*ColumnInfoArray = LineOffset + Cell[Index1].OffsetX + BltX; | |
} | |
ColumnInfoArray++; | |
} | |
LineOffset += Cell[Index1].AdvanceX; | |
} | |
// | |
// Jump to starting position of next row. | |
// | |
if (RowIndex == 0) { | |
BufferPtr = RowBufferPtr - BltX + LineHeight * Image->Width; | |
} else { | |
BufferPtr = RowBufferPtr + LineHeight * Image->Width; | |
} | |
} | |
NextLine: | |
// | |
// Recalculate the start point of X/Y axis to draw multi-lines with the order of top-to-down | |
// | |
BltX = 0; | |
BltY += RowInfo[RowIndex].LineHeight; | |
RowIndex++; | |
Index = NextIndex; | |
if (!LineBreak) { | |
// | |
// If there is not a mandatory line break or line break opportunity, only render one line to image | |
// | |
break; | |
} | |
} | |
// | |
// Write output parameters. | |
// | |
RowInfoSize = RowIndex * sizeof (EFI_HII_ROW_INFO); | |
if (RowInfoArray != NULL) { | |
if (RowInfoSize > 0) { | |
*RowInfoArray = AllocateZeroPool (RowInfoSize); | |
if (*RowInfoArray == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Exit; | |
} | |
CopyMem (*RowInfoArray, RowInfo, RowInfoSize); | |
} else { | |
*RowInfoArray = NULL; | |
} | |
} | |
if (RowInfoArraySize != NULL) { | |
*RowInfoArraySize = RowIndex; | |
} | |
Status = EFI_SUCCESS; | |
Exit: | |
for (Index = 0; Index < StrLength; Index++) { | |
if (GlyphBuf[Index] != NULL) { | |
FreePool (GlyphBuf[Index]); | |
} | |
} | |
if (StringIn != NULL) { | |
FreePool (StringIn); | |
} | |
if (StringIn2 != NULL) { | |
FreePool (StringIn2); | |
} | |
if (StringInfoOut != NULL) { | |
FreePool (StringInfoOut); | |
} | |
if (RowInfo != NULL) { | |
FreePool (RowInfo); | |
} | |
if (SystemDefault != NULL) { | |
FreePool (SystemDefault); | |
} | |
if (GlyphBuf != NULL) { | |
FreePool (GlyphBuf); | |
} | |
if (Cell != NULL) { | |
FreePool (Cell); | |
} | |
if (Attributes != NULL) { | |
FreePool (Attributes); | |
} | |
return Status; | |
} | |
/** | |
Render a string to a bitmap or the screen containing the contents of the specified string. | |
@param This A pointer to the EFI_HII_FONT_PROTOCOL instance. | |
@param Flags Describes how the string is to be drawn. | |
@param PackageList The package list in the HII database to search | |
for the specified string. | |
@param StringId The string's id, which is unique within | |
PackageList. | |
@param Language Points to the language for the retrieved string. | |
If NULL, then the current system language is | |
used. | |
@param StringInfo Points to the string output information, | |
including the color and font. If NULL, then the | |
string will be output in the default system font | |
and color. | |
@param Blt If this points to a non-NULL on entry, this | |
points to the image, which is Width pixels wide | |
and Height pixels high. The string will be drawn | |
onto this image and | |
EFI_HII_OUT_FLAG_CLIP is implied. If this points | |
to a NULL on entry, then a buffer | |
will be allocated to hold the generated image and | |
the pointer updated on exit. It is the caller's | |
responsibility to free this buffer. | |
@param BltX Specifies the offset from the left and top edge | |
of the image of the first character cell in the | |
image. | |
@param BltY Specifies the offset from the left and top edge | |
of the image of the first character cell in the | |
image. | |
@param RowInfoArray If this is non-NULL on entry, then on exit, this | |
will point to an allocated buffer containing | |
row information and RowInfoArraySize will be | |
updated to contain the number of elements. | |
This array describes the characters which were at | |
least partially drawn and the heights of the | |
rows. It is the caller's responsibility to free | |
this buffer. | |
@param RowInfoArraySize If this is non-NULL on entry, then on exit it | |
contains the number of elements in RowInfoArray. | |
@param ColumnInfoArray If this is non-NULL, then on return it will be | |
filled with the horizontal offset for each | |
character in the string on the row where it is | |
displayed. Non-printing characters will have | |
the offset ~0. The caller is responsible to | |
allocate a buffer large enough so that there | |
is one entry for each character in the string, | |
not including the null-terminator. It is possible | |
when character display is normalized that some | |
character cells overlap. | |
@retval EFI_SUCCESS The string was successfully rendered. | |
@retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for | |
RowInfoArray or Blt. | |
@retval EFI_INVALID_PARAMETER The Blt or PackageList was NULL. | |
@retval EFI_INVALID_PARAMETER Flags were invalid combination. | |
@retval EFI_NOT_FOUND The specified PackageList is not in the Database or the stringid is not | |
in the specified PackageList. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
HiiStringIdToImage ( | |
IN CONST EFI_HII_FONT_PROTOCOL *This, | |
IN EFI_HII_OUT_FLAGS Flags, | |
IN EFI_HII_HANDLE PackageList, | |
IN EFI_STRING_ID StringId, | |
IN CONST CHAR8* Language, | |
IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL, | |
IN OUT EFI_IMAGE_OUTPUT **Blt, | |
IN UINTN BltX, | |
IN UINTN BltY, | |
OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL, | |
OUT UINTN *RowInfoArraySize OPTIONAL, | |
OUT UINTN *ColumnInfoArray OPTIONAL | |
) | |
{ | |
EFI_STATUS Status; | |
HII_DATABASE_PRIVATE_DATA *Private; | |
EFI_HII_STRING_PROTOCOL *HiiString; | |
EFI_STRING String; | |
UINTN StringSize; | |
UINTN FontLen; | |
EFI_FONT_INFO *StringFontInfo; | |
EFI_FONT_DISPLAY_INFO *NewStringInfo; | |
CHAR8 TempSupportedLanguages; | |
CHAR8 *SupportedLanguages; | |
UINTN SupportedLanguagesSize; | |
CHAR8 *CurrentLanguage; | |
CHAR8 *BestLanguage; | |
if (This == NULL || PackageList == NULL || Blt == NULL || PackageList == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if (!IsHiiHandleValid (PackageList)) { | |
return EFI_NOT_FOUND; | |
} | |
// | |
// Initialize string pointers to be NULL | |
// | |
SupportedLanguages = NULL; | |
CurrentLanguage = NULL; | |
BestLanguage = NULL; | |
String = NULL; | |
StringFontInfo = NULL; | |
NewStringInfo = NULL; | |
// | |
// Get the string to be displayed. | |
// | |
Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This); | |
HiiString = &Private->HiiString; | |
// | |
// Get the size of supported language. | |
// | |
SupportedLanguagesSize = 0; | |
Status = HiiString->GetLanguages ( | |
HiiString, | |
PackageList, | |
&TempSupportedLanguages, | |
&SupportedLanguagesSize | |
); | |
if (Status != EFI_BUFFER_TOO_SMALL) { | |
return Status; | |
} | |
SupportedLanguages = AllocatePool (SupportedLanguagesSize); | |
if (SupportedLanguages == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
Status = HiiString->GetLanguages ( | |
HiiString, | |
PackageList, | |
SupportedLanguages, | |
&SupportedLanguagesSize | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
if (Language == NULL) { | |
Language = ""; | |
} | |
GetEfiGlobalVariable2 (L"PlatformLang", &CurrentLanguage, NULL); | |
BestLanguage = GetBestLanguage ( | |
SupportedLanguages, | |
FALSE, | |
Language, | |
(CurrentLanguage == NULL) ? CurrentLanguage : "", | |
(CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang), | |
NULL | |
); | |
if (BestLanguage == NULL) { | |
Status = EFI_NOT_FOUND; | |
goto Exit; | |
} | |
StringSize = MAX_STRING_LENGTH; | |
String = (EFI_STRING) AllocateZeroPool (StringSize); | |
if (String == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Exit; | |
} | |
Status = HiiString->GetString ( | |
HiiString, | |
BestLanguage, | |
PackageList, | |
StringId, | |
String, | |
&StringSize, | |
&StringFontInfo | |
); | |
if (Status == EFI_BUFFER_TOO_SMALL) { | |
FreePool (String); | |
String = (EFI_STRING) AllocateZeroPool (StringSize); | |
if (String == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Exit; | |
} | |
Status = HiiString->GetString ( | |
HiiString, | |
BestLanguage, | |
PackageList, | |
StringId, | |
String, | |
&StringSize, | |
NULL | |
); | |
} | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
// | |
// When StringInfo specifies that string will be output in the system default font and color, | |
// use particular stringfontinfo described in string package instead if exists. | |
// StringFontInfo equals NULL means system default font attaches with the string block. | |
// | |
if (StringFontInfo != NULL && IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfo, NULL, NULL)) { | |
FontLen = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + StrSize (StringFontInfo->FontName); | |
NewStringInfo = AllocateZeroPool (FontLen); | |
if (NewStringInfo == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Exit; | |
} | |
NewStringInfo->FontInfoMask = EFI_FONT_INFO_SYS_FORE_COLOR | EFI_FONT_INFO_SYS_BACK_COLOR; | |
NewStringInfo->FontInfo.FontStyle = StringFontInfo->FontStyle; | |
NewStringInfo->FontInfo.FontSize = StringFontInfo->FontSize; | |
StrCpy (NewStringInfo->FontInfo.FontName, StringFontInfo->FontName); | |
Status = HiiStringToImage ( | |
This, | |
Flags, | |
String, | |
NewStringInfo, | |
Blt, | |
BltX, | |
BltY, | |
RowInfoArray, | |
RowInfoArraySize, | |
ColumnInfoArray | |
); | |
goto Exit; | |
} | |
Status = HiiStringToImage ( | |
This, | |
Flags, | |
String, | |
StringInfo, | |
Blt, | |
BltX, | |
BltY, | |
RowInfoArray, | |
RowInfoArraySize, | |
ColumnInfoArray | |
); | |
Exit: | |
if (SupportedLanguages != NULL) { | |
FreePool (SupportedLanguages); | |
} | |
if (CurrentLanguage != NULL) { | |
FreePool (CurrentLanguage); | |
} | |
if (BestLanguage != NULL) { | |
FreePool (BestLanguage); | |
} | |
if (String != NULL) { | |
FreePool (String); | |
} | |
if (StringFontInfo != NULL) { | |
FreePool (StringFontInfo); | |
} | |
if (NewStringInfo != NULL) { | |
FreePool (NewStringInfo); | |
} | |
return Status; | |
} | |
/** | |
Convert the glyph for a single character into a bitmap. | |
@param This A pointer to the EFI_HII_FONT_PROTOCOL instance. | |
@param Char Character to retrieve. | |
@param StringInfo Points to the string font and color information | |
or NULL if the string should use the default | |
system font and color. | |
@param Blt Thus must point to a NULL on entry. A buffer will | |
be allocated to hold the output and the pointer | |
updated on exit. It is the caller's | |
responsibility to free this buffer. | |
@param Baseline Number of pixels from the bottom of the bitmap to | |
the baseline. | |
@retval EFI_SUCCESS Glyph bitmap created. | |
@retval EFI_OUT_OF_RESOURCES Unable to allocate the output buffer Blt. | |
@retval EFI_WARN_UNKNOWN_GLYPH The glyph was unknown and was replaced with the | |
glyph for Unicode character 0xFFFD. | |
@retval EFI_INVALID_PARAMETER Blt is NULL or *Blt is not NULL. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
HiiGetGlyph ( | |
IN CONST EFI_HII_FONT_PROTOCOL *This, | |
IN CHAR16 Char, | |
IN CONST EFI_FONT_DISPLAY_INFO *StringInfo, | |
OUT EFI_IMAGE_OUTPUT **Blt, | |
OUT UINTN *Baseline OPTIONAL | |
) | |
{ | |
EFI_STATUS Status; | |
HII_DATABASE_PRIVATE_DATA *Private; | |
EFI_IMAGE_OUTPUT *Image; | |
UINT8 *GlyphBuffer; | |
EFI_FONT_DISPLAY_INFO *SystemDefault; | |
EFI_FONT_DISPLAY_INFO *StringInfoOut; | |
BOOLEAN Default; | |
EFI_FONT_HANDLE FontHandle; | |
EFI_STRING String; | |
EFI_HII_GLYPH_INFO Cell; | |
EFI_FONT_INFO *FontInfo; | |
UINT8 Attributes; | |
EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground; | |
EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; | |
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer; | |
UINT16 BaseLine; | |
if (This == NULL || Blt == NULL || *Blt != NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This); | |
Default = FALSE; | |
Image = NULL; | |
SystemDefault = NULL; | |
FontHandle = NULL; | |
String = NULL; | |
GlyphBuffer = NULL; | |
StringInfoOut = NULL; | |
FontInfo = NULL; | |
ZeroMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); | |
ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); | |
Default = IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfo, &SystemDefault, NULL); | |
if (!Default) { | |
// | |
// Find out a EFI_FONT_DISPLAY_INFO which could display the character in | |
// the specified color and font. | |
// | |
String = (EFI_STRING) AllocateZeroPool (sizeof (CHAR16) * 2); | |
if (String == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Exit; | |
} | |
*String = Char; | |
*(String + 1) = 0; | |
Status = HiiGetFontInfo (This, &FontHandle, StringInfo, &StringInfoOut, String); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
ASSERT (StringInfoOut != NULL); | |
FontInfo = &StringInfoOut->FontInfo; | |
Foreground = StringInfoOut->ForegroundColor; | |
Background = StringInfoOut->BackgroundColor; | |
} else { | |
Foreground = SystemDefault->ForegroundColor; | |
Background = SystemDefault->BackgroundColor; | |
} | |
Status = GetGlyphBuffer (Private, Char, FontInfo, &GlyphBuffer, &Cell, &Attributes); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
Image = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT)); | |
if (Image == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Exit; | |
} | |
Image->Width = Cell.Width; | |
Image->Height = Cell.Height; | |
if (Image->Width * Image->Height > 0) { | |
Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); | |
if (Image->Image.Bitmap == NULL) { | |
FreePool (Image); | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Exit; | |
} | |
// | |
// Set BaseLine to the char height. | |
// | |
BaseLine = (UINT16) (Cell.Height + Cell.OffsetY); | |
// | |
// Set BltBuffer to the position of Origin. | |
// | |
BltBuffer = Image->Image.Bitmap + (Cell.Height + Cell.OffsetY) * Image->Width - Cell.OffsetX; | |
GlyphToImage ( | |
GlyphBuffer, | |
Foreground, | |
Background, | |
Image->Width, | |
BaseLine, | |
Cell.Width + Cell.OffsetX, | |
BaseLine - Cell.OffsetY, | |
FALSE, | |
&Cell, | |
Attributes, | |
&BltBuffer | |
); | |
} | |
*Blt = Image; | |
if (Baseline != NULL) { | |
*Baseline = Cell.OffsetY; | |
} | |
Status = EFI_SUCCESS; | |
Exit: | |
if (Status == EFI_NOT_FOUND) { | |
// | |
// Glyph is unknown and replaced with the glyph for unicode character 0xFFFD | |
// | |
if (Char != REPLACE_UNKNOWN_GLYPH) { | |
Status = HiiGetGlyph (This, REPLACE_UNKNOWN_GLYPH, StringInfo, Blt, Baseline); | |
if (!EFI_ERROR (Status)) { | |
Status = EFI_WARN_UNKNOWN_GLYPH; | |
} | |
} else { | |
Status = EFI_WARN_UNKNOWN_GLYPH; | |
} | |
} | |
if (SystemDefault != NULL) { | |
FreePool (SystemDefault); | |
} | |
if (StringInfoOut != NULL) { | |
FreePool (StringInfoOut); | |
} | |
if (String != NULL) { | |
FreePool (String); | |
} | |
if (GlyphBuffer != NULL) { | |
FreePool (GlyphBuffer); | |
} | |
return Status; | |
} | |
/** | |
This function iterates through fonts which match the specified font, using | |
the specified criteria. If String is non-NULL, then all of the characters in | |
the string must exist in order for a candidate font to be returned. | |
@param This A pointer to the EFI_HII_FONT_PROTOCOL instance. | |
@param FontHandle On entry, points to the font handle returned by a | |
previous call to GetFontInfo() or NULL to start | |
with the first font. On return, points to the | |
returned font handle or points to NULL if there | |
are no more matching fonts. | |
@param StringInfoIn Upon entry, points to the font to return | |
information about. | |
If NULL, then the information about the system default | |
font will be returned. | |
@param StringInfoOut Upon return, contains the matching font's | |
information. If NULL, then no information is | |
returned. It's caller's responsibility to free | |
this buffer. | |
@param String Points to the string which will be tested to | |
determine if all characters are available. If | |
NULL, then any font is acceptable. | |
@retval EFI_SUCCESS Matching font returned successfully. | |
@retval EFI_NOT_FOUND No matching font was found. | |
@retval EFI_INVALID_PARAMETER StringInfoIn->FontInfoMask is an invalid combination. | |
@retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the | |
request. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
HiiGetFontInfo ( | |
IN CONST EFI_HII_FONT_PROTOCOL *This, | |
IN OUT EFI_FONT_HANDLE *FontHandle, | |
IN CONST EFI_FONT_DISPLAY_INFO *StringInfoIn, OPTIONAL | |
OUT EFI_FONT_DISPLAY_INFO **StringInfoOut, | |
IN CONST EFI_STRING String OPTIONAL | |
) | |
{ | |
HII_DATABASE_PRIVATE_DATA *Private; | |
EFI_STATUS Status; | |
EFI_FONT_DISPLAY_INFO *SystemDefault; | |
EFI_FONT_DISPLAY_INFO InfoOut; | |
UINTN StringInfoOutLen; | |
EFI_FONT_INFO *FontInfo; | |
HII_GLOBAL_FONT_INFO *GlobalFont; | |
EFI_STRING StringIn; | |
EFI_FONT_HANDLE LocalFontHandle; | |
if (This == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
FontInfo = NULL; | |
SystemDefault = NULL; | |
LocalFontHandle = NULL; | |
if (FontHandle != NULL) { | |
LocalFontHandle = *FontHandle; | |
} | |
Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This); | |
// | |
// Already searched to the end of the whole list, return directly. | |
// | |
if (LocalFontHandle == &Private->FontInfoList) { | |
LocalFontHandle = NULL; | |
Status = EFI_NOT_FOUND; | |
goto Exit; | |
} | |
// | |
// Get default system display info, if StringInfoIn points to | |
// system display info, return it directly. | |
// | |
if (IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfoIn, &SystemDefault, &StringInfoOutLen)) { | |
// | |
// System font is the first node. When handle is not NULL, system font can not | |
// be found any more. | |
// | |
if (LocalFontHandle == NULL) { | |
if (StringInfoOut != NULL) { | |
*StringInfoOut = AllocateCopyPool (StringInfoOutLen, SystemDefault); | |
if (*StringInfoOut == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
LocalFontHandle = NULL; | |
goto Exit; | |
} | |
} | |
LocalFontHandle = Private->FontInfoList.ForwardLink; | |
Status = EFI_SUCCESS; | |
goto Exit; | |
} else { | |
LocalFontHandle = NULL; | |
Status = EFI_NOT_FOUND; | |
goto Exit; | |
} | |
} | |
// | |
// StringInfoIn must not be NULL if it is not system default font info. | |
// | |
ASSERT (StringInfoIn != NULL); | |
// | |
// Check the font information mask to make sure it is valid. | |
// | |
if (((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) == | |
(EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) || | |
((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) == | |
(EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) || | |
((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) == | |
(EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) || | |
((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_ANY_SIZE)) == | |
(EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_ANY_SIZE)) || | |
((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_ANY_STYLE)) == | |
(EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_ANY_STYLE))) { | |
return EFI_INVALID_PARAMETER; | |
} | |
// | |
// Parse the font information mask to find a matching font. | |
// | |
CopyMem (&InfoOut, (EFI_FONT_DISPLAY_INFO *) StringInfoIn, sizeof (EFI_FONT_DISPLAY_INFO)); | |
if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_FONT) == EFI_FONT_INFO_SYS_FONT) { | |
Status = SaveFontName (SystemDefault->FontInfo.FontName, &FontInfo); | |
} else { | |
Status = SaveFontName (((EFI_FONT_DISPLAY_INFO *) StringInfoIn)->FontInfo.FontName, &FontInfo); | |
} | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_SIZE) == EFI_FONT_INFO_SYS_SIZE) { | |
InfoOut.FontInfo.FontSize = SystemDefault->FontInfo.FontSize; | |
} | |
if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_STYLE) == EFI_FONT_INFO_SYS_STYLE) { | |
InfoOut.FontInfo.FontStyle = SystemDefault->FontInfo.FontStyle; | |
} | |
if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_FORE_COLOR) == EFI_FONT_INFO_SYS_FORE_COLOR) { | |
InfoOut.ForegroundColor = SystemDefault->ForegroundColor; | |
} | |
if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_BACK_COLOR) == EFI_FONT_INFO_SYS_BACK_COLOR) { | |
InfoOut.BackgroundColor = SystemDefault->BackgroundColor; | |
} | |
ASSERT (FontInfo != NULL); | |
FontInfo->FontSize = InfoOut.FontInfo.FontSize; | |
FontInfo->FontStyle = InfoOut.FontInfo.FontStyle; | |
if (IsFontInfoExisted (Private, FontInfo, &InfoOut.FontInfoMask, LocalFontHandle, &GlobalFont)) { | |
// | |
// Test to guarantee all characters are available in the found font. | |
// | |
if (String != NULL) { | |
StringIn = String; | |
while (*StringIn != 0) { | |
Status = FindGlyphBlock (GlobalFont->FontPackage, *StringIn, NULL, NULL, NULL); | |
if (EFI_ERROR (Status)) { | |
LocalFontHandle = NULL; | |
goto Exit; | |
} | |
StringIn++; | |
} | |
} | |
// | |
// Write to output parameter | |
// | |
if (StringInfoOut != NULL) { | |
StringInfoOutLen = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (EFI_FONT_INFO) + GlobalFont->FontInfoSize; | |
*StringInfoOut = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (StringInfoOutLen); | |
if (*StringInfoOut == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
LocalFontHandle = NULL; | |
goto Exit; | |
} | |
CopyMem (*StringInfoOut, &InfoOut, sizeof (EFI_FONT_DISPLAY_INFO)); | |
CopyMem (&(*StringInfoOut)->FontInfo, GlobalFont->FontInfo, GlobalFont->FontInfoSize); | |
} | |
LocalFontHandle = GlobalFont->Entry.ForwardLink; | |
Status = EFI_SUCCESS; | |
goto Exit; | |
} | |
Status = EFI_NOT_FOUND; | |
Exit: | |
if (FontHandle != NULL) { | |
*FontHandle = LocalFontHandle; | |
} | |
if (SystemDefault != NULL) { | |
FreePool (SystemDefault); | |
} | |
if (FontInfo != NULL) { | |
FreePool (FontInfo); | |
} | |
return Status; | |
} | |