From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001 From: Angelos Mouzakitis Date: Tue, 10 Oct 2023 14:33:42 +0000 Subject: Add submodule dependency files Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec --- .../MdeModulePkg/Universal/HiiDatabaseDxe/Font.c | 2904 ++++++++++++++++++++ 1 file changed, 2904 insertions(+) create mode 100644 roms/edk2/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c (limited to 'roms/edk2/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c') diff --git a/roms/edk2/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c b/roms/edk2/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c new file mode 100644 index 000000000..ee6c65287 --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c @@ -0,0 +1,2904 @@ +/** @file +Implementation for EFI_HII_FONT_PROTOCOL. + + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+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); + + 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; + IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont); + Height = GlobalFont->FontPackage->Height; + BaseLine = GlobalFont->FontPackage->BaseLine; + Foreground = StringInfoOut->ForegroundColor; + Background = StringInfoOut->BackgroundColor; + } else { + goto Exit; + } + } + + // + // Use the 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; +} + + -- cgit