diff options
Diffstat (limited to 'MdeModulePkg/Universal/HiiDatabaseDxe/Font.c')
| -rw-r--r-- | MdeModulePkg/Universal/HiiDatabaseDxe/Font.c | 6036 |
1 files changed, 3018 insertions, 3018 deletions
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c index 8a0b12f72f..fc1fee17db 100644 --- a/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c +++ b/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c @@ -1,3018 +1,3018 @@ -/** @file
-Implementation for EFI_HII_FONT_PROTOCOL.
-
-
-Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#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 will 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 will 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 && (((UINT32)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 && (((UINT32)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 && (((UINT32)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 will 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 responsibility 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 responsibility 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)
- );
- }
-
- 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 += *(UINT8 *)((UINTN)BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8));
- break;
- case EFI_HII_GIBT_EXT2:
- CopyMem (
- &Length16,
- (UINT8 *)((UINTN)BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8)),
- sizeof (UINT16)
- );
- BlockPtr += Length16;
- break;
- case EFI_HII_GIBT_EXT4:
- CopyMem (
- &Length32,
- (UINT8 *)((UINTN)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 (
- (UINT8 *)((UINTN)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;
- }
-
- if (CharValue == (CHAR16)(-1)) {
- if (BaseLine < DefaultCell.Height + DefaultCell.OffsetY) {
- BaseLine = (UINT16)(DefaultCell.Height + DefaultCell.OffsetY);
- }
-
- if (MinOffsetY > DefaultCell.OffsetY) {
- MinOffsetY = DefaultCell.OffsetY;
- }
- }
-
- 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;
- }
-
- if (CharValue == (CHAR16)(-1)) {
- if (BaseLine < DefaultCell.Height + DefaultCell.OffsetY) {
- BaseLine = (UINT16)(DefaultCell.Height + DefaultCell.OffsetY);
- }
-
- if (MinOffsetY > DefaultCell.OffsetY) {
- MinOffsetY = DefaultCell.OffsetY;
- }
- }
-
- 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;
- UINTN NameSize;
-
- ASSERT (FontName != NULL && FontInfo != NULL);
-
- NameSize = StrSize (FontName);
- FontInfoLen = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + NameSize;
- *FontInfo = (EFI_FONT_INFO *)AllocateZeroPool (FontInfoLen);
- if (*FontInfo == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- StrCpyS ((*FontInfo)->FontName, NameSize / sizeof (CHAR16), 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;
- UINTN NameSize;
-
- 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".
- //
- NameSize = StrSize (L"sysdefault");
- InfoSize = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + NameSize;
- Info = (EFI_FONT_DISPLAY_INFO *)AllocateZeroPool (InfoSize);
- if (Info == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- Info->ForegroundColor = mHiiEfiColors[Private->Attribute & 0x0f];
- ASSERT ((Private->Attribute >> 4) < 8);
- 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;
- StrCpyS (Info->FontInfo.FontName, NameSize / sizeof (CHAR16), 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;
- }
-
- SystemDefault = NULL;
- DefaultLen = 0;
-
- Status = GetSystemFont (Private, &SystemDefault, &DefaultLen);
- ASSERT_EFI_ERROR (Status);
- ASSERT ((SystemDefault != NULL) && (DefaultLen != 0));
-
- //
- // 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 global 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 represents 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 system 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 0x000A:
- 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;
- UINT32 PreInitBkgnd;
-
- //
- // 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);
-
- FontInfo = 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) {
- ASSERT (SystemDefault != NULL);
- 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;
- if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont)) {
- Height = GlobalFont->FontPackage->Height;
- BaseLine = GlobalFont->FontPackage->BaseLine;
- Foreground = StringInfoOut->ForegroundColor;
- Background = StringInfoOut->BackgroundColor;
- } else {
- goto Exit;
- }
- } else {
- goto Exit;
- }
- }
-
- //
- // Use the maximum height of font as the base line.
- // And, use the maximum 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 with 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 -= (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 -= (Cell[Index].Width + Cell[Index].OffsetX);
- LineWidth -= (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 -= (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 -= (Cell[Index1].Width + Cell[Index1].OffsetX);
- LineWidth -= (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 = AllocatePool (RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
- if (BltBuffer == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- //
- // Initialize the background color.
- //
- PreInitBkgnd = Background.Blue | Background.Green << 8 | Background.Red << 16;
- SetMem32 (BltBuffer, RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), PreInitBkgnd);
- //
- // 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 corresponding glyph in font database.
- //
- 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 position 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 corresponding glyph in font database.
- //
- 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 Y axis to draw multi-lines with the order of top-to-down
- //
- 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 string id 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;
- UINTN NameSize;
- 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", (VOID **)&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)) {
- NameSize = StrSize (StringFontInfo->FontName);
- FontLen = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + NameSize;
- 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;
- StrCpyS (NewStringInfo->FontInfo.FontName, NameSize / sizeof (CHAR16), 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 {
- ASSERT (SystemDefault != NULL);
- 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. This buffer
- is allocated with a call to the Boot Service AllocatePool().
- It is the caller's responsibility to call the Boot
- Service FreePool() when the caller no longer requires
- the contents of StringInfoOut.
- @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;
- }
-
- StringInfoOutLen = 0;
- 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;
-}
+/** @file +Implementation for EFI_HII_FONT_PROTOCOL. + + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#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 will 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 will 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 && (((UINT32)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 && (((UINT32)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 && (((UINT32)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 will 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 responsibility 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 responsibility 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) + ); + } + + 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 += *(UINT8 *)((UINTN)BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8)); + break; + case EFI_HII_GIBT_EXT2: + CopyMem ( + &Length16, + (UINT8 *)((UINTN)BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8)), + sizeof (UINT16) + ); + BlockPtr += Length16; + break; + case EFI_HII_GIBT_EXT4: + CopyMem ( + &Length32, + (UINT8 *)((UINTN)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 ( + (UINT8 *)((UINTN)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; + } + + if (CharValue == (CHAR16)(-1)) { + if (BaseLine < DefaultCell.Height + DefaultCell.OffsetY) { + BaseLine = (UINT16)(DefaultCell.Height + DefaultCell.OffsetY); + } + + if (MinOffsetY > DefaultCell.OffsetY) { + MinOffsetY = DefaultCell.OffsetY; + } + } + + 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; + } + + if (CharValue == (CHAR16)(-1)) { + if (BaseLine < DefaultCell.Height + DefaultCell.OffsetY) { + BaseLine = (UINT16)(DefaultCell.Height + DefaultCell.OffsetY); + } + + if (MinOffsetY > DefaultCell.OffsetY) { + MinOffsetY = DefaultCell.OffsetY; + } + } + + 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; + UINTN NameSize; + + ASSERT (FontName != NULL && FontInfo != NULL); + + NameSize = StrSize (FontName); + FontInfoLen = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + NameSize; + *FontInfo = (EFI_FONT_INFO *)AllocateZeroPool (FontInfoLen); + if (*FontInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + StrCpyS ((*FontInfo)->FontName, NameSize / sizeof (CHAR16), 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; + UINTN NameSize; + + 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". + // + NameSize = StrSize (L"sysdefault"); + InfoSize = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + NameSize; + Info = (EFI_FONT_DISPLAY_INFO *)AllocateZeroPool (InfoSize); + if (Info == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Info->ForegroundColor = mHiiEfiColors[Private->Attribute & 0x0f]; + ASSERT ((Private->Attribute >> 4) < 8); + 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; + StrCpyS (Info->FontInfo.FontName, NameSize / sizeof (CHAR16), 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; + } + + SystemDefault = NULL; + DefaultLen = 0; + + Status = GetSystemFont (Private, &SystemDefault, &DefaultLen); + ASSERT_EFI_ERROR (Status); + ASSERT ((SystemDefault != NULL) && (DefaultLen != 0)); + + // + // 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 global 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 represents 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 system 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 0x000A: + 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; + UINT32 PreInitBkgnd; + + // + // 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); + + FontInfo = 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) { + ASSERT (SystemDefault != NULL); + 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; + if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont)) { + Height = GlobalFont->FontPackage->Height; + BaseLine = GlobalFont->FontPackage->BaseLine; + Foreground = StringInfoOut->ForegroundColor; + Background = StringInfoOut->BackgroundColor; + } else { + goto Exit; + } + } else { + goto Exit; + } + } + + // + // Use the maximum height of font as the base line. + // And, use the maximum 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 with 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 -= (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 -= (Cell[Index].Width + Cell[Index].OffsetX); + LineWidth -= (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 -= (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 -= (Cell[Index1].Width + Cell[Index1].OffsetX); + LineWidth -= (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 = AllocatePool (RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + if (BltBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + // + // Initialize the background color. + // + PreInitBkgnd = Background.Blue | Background.Green << 8 | Background.Red << 16; + SetMem32 (BltBuffer, RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), PreInitBkgnd); + // + // 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 corresponding glyph in font database. + // + 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 position 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 corresponding glyph in font database. + // + 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 Y axis to draw multi-lines with the order of top-to-down + // + 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 string id 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; + UINTN NameSize; + 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", (VOID **)&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)) { + NameSize = StrSize (StringFontInfo->FontName); + FontLen = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + NameSize; + 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; + StrCpyS (NewStringInfo->FontInfo.FontName, NameSize / sizeof (CHAR16), 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 { + ASSERT (SystemDefault != NULL); + 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. This buffer + is allocated with a call to the Boot Service AllocatePool(). + It is the caller's responsibility to call the Boot + Service FreePool() when the caller no longer requires + the contents of StringInfoOut. + @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; + } + + StringInfoOutLen = 0; + 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; +} |
