| /** @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); | |
| 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; | |
| } |