]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/HiiDatabaseDxe/Font.c
MdeModulePkg/HiiDatabase: Remove the incorrect calculation of font baseline
[mirror_edk2.git] / MdeModulePkg / Universal / HiiDatabaseDxe / Font.c
index b899cec3605888834a6ebfe716619e7565756a7f..5ecd6bd4a1e4f0d32e9c857a8451c7d7660b5824 100644 (file)
@@ -2,8 +2,8 @@
 Implementation for EFI_HII_FONT_PROTOCOL.\r
 \r
 \r
-Copyright (c) 2007 - 2009, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
 http://opensource.org/licenses/bsd-license.php\r
@@ -76,6 +76,9 @@ NewCell (
   //\r
   GlyphInfo->Signature = HII_GLYPH_INFO_SIGNATURE;\r
   GlyphInfo->CharId    = CharValue;\r
+  if (Cell->AdvanceX == 0) {\r
+    Cell->AdvanceX = Cell->Width;\r
+  }\r
   CopyMem (&GlyphInfo->Cell, Cell, sizeof (EFI_HII_GLYPH_INFO));\r
   InsertTailList (GlyphInfoList, &GlyphInfo->Entry);\r
 \r
@@ -221,7 +224,6 @@ GetGlyphBuffer (
             }\r
             Cell->Width    = EFI_GLYPH_WIDTH;\r
             Cell->Height   = EFI_GLYPH_HEIGHT;\r
-            Cell->OffsetY  = NARROW_BASELINE;\r
             Cell->AdvanceX = Cell->Width;\r
             CopyMem (*GlyphBuffer, Narrow.GlyphCol1, Cell->Height);\r
             if (Attributes != NULL) {\r
@@ -243,7 +245,6 @@ GetGlyphBuffer (
             }\r
             Cell->Width    = EFI_GLYPH_WIDTH * 2;\r
             Cell->Height   = EFI_GLYPH_HEIGHT;\r
-            Cell->OffsetY  = WIDE_BASELINE;\r
             Cell->AdvanceX = Cell->Width;\r
             CopyMem (*GlyphBuffer, Wide.GlyphCol1, EFI_GLYPH_HEIGHT);\r
             CopyMem (*GlyphBuffer + EFI_GLYPH_HEIGHT, Wide.GlyphCol2, EFI_GLYPH_HEIGHT);\r
@@ -270,16 +271,15 @@ GetGlyphBuffer (
                          bitmap.\r
   @param  Background     The color of the "off" pixels in the glyph in the\r
                          bitmap.\r
-  @param  ImageWidth     Width of the character or character cell, in\r
-                         pixels.\r
-  @param  ImageHeight    Height of the character or character cell, in\r
-                         pixels.\r
-  @param  Transparent             If TRUE, the Background color is ignored and all\r
-                                  "off" pixels in the character's drawn wil use the\r
-                                  pixel value from BltBuffer.\r
-  @param  Origin                  On input, points to the origin of the to be\r
-                                  displayed character, on output, points to the\r
-                                  next glyph's origin.\r
+  @param  ImageWidth     Width of the whole image in pixels.\r
+  @param  RowWidth       The width of the text on the line, in pixels.\r
+  @param  RowHeight      The height of the line, in pixels.\r
+  @param  Transparent    If TRUE, the Background color is ignored and all\r
+                         "off" pixels in the character's drawn wil use the\r
+                         pixel value from BltBuffer.\r
+  @param  Origin         On input, points to the origin of the to be\r
+                         displayed character, on output, points to the\r
+                         next glyph's origin.\r
 \r
 **/\r
 VOID\r
@@ -287,8 +287,9 @@ NarrowGlyphToBlt (
   IN     UINT8                         *GlyphBuffer,\r
   IN     EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,\r
   IN     EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,\r
-  IN     UINTN                         ImageWidth,\r
-  IN     UINTN                         ImageHeight,\r
+  IN     UINT16                        ImageWidth,\r
+  IN     UINTN                         RowWidth,\r
+  IN     UINTN                         RowHeight,\r
   IN     BOOLEAN                       Transparent,\r
   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin\r
   )\r
@@ -303,24 +304,35 @@ NarrowGlyphToBlt (
 \r
   Height = EFI_GLYPH_HEIGHT;\r
   Width  = EFI_GLYPH_WIDTH;\r
+  \r
+  //\r
+  // Move position to the left-top corner of char.\r
+  //\r
+  Buffer = *Origin - EFI_GLYPH_HEIGHT * ImageWidth;\r
 \r
-  ASSERT (Width <= ImageWidth && Height <= ImageHeight);\r
-\r
-  Buffer = *Origin;\r
+  //\r
+  // Char may be partially displayed when CLIP_X or CLIP_Y is not set. \r
+  //\r
+  if (RowHeight < Height) {\r
+    Height = (UINT8) RowHeight;\r
+  }\r
+  if (RowWidth < Width) {\r
+    Width = (UINT8) RowWidth;\r
+  }\r
 \r
   for (Ypos = 0; Ypos < Height; Ypos++) {\r
     for (Xpos = 0; Xpos < Width; Xpos++) {\r
-      if ((GlyphBuffer[Ypos] & (1 << Xpos)) != 0) {\r
-        Buffer[Ypos * ImageWidth + (Width - Xpos - 1)] = Foreground;\r
+      if ((GlyphBuffer[Ypos] & (1 << (EFI_GLYPH_WIDTH - Xpos - 1))) != 0) {\r
+        Buffer[Ypos * ImageWidth + Xpos] = Foreground;\r
       } else {\r
         if (!Transparent) {\r
-          Buffer[Ypos * ImageWidth + (Width - Xpos - 1)] = Background;\r
+          Buffer[Ypos * ImageWidth + Xpos] = Background;\r
         }\r
       }\r
     }\r
   }\r
 \r
-  *Origin = Buffer + Width;\r
+  *Origin = *Origin + EFI_GLYPH_WIDTH;\r
 }\r
 \r
 \r
@@ -334,10 +346,10 @@ NarrowGlyphToBlt (
                                   bitmap.\r
   @param  Background              The color of the "off" pixels in the glyph in the\r
                                   bitmap.\r
-  @param  ImageWidth              Width of the character or character cell, in\r
-                                  pixels.\r
-  @param  ImageHeight             Height of the character or character cell, in\r
-                                  pixels.\r
+  @param  ImageWidth              Width of the whole image in pixels.\r
+  @param  BaseLine                BaseLine in the line.\r
+  @param  RowWidth                The width of the text on the line, in pixels.\r
+  @param  RowHeight               The height of the line, in pixels.\r
   @param  Transparent             If TRUE, the Background color is ignored and all\r
                                   "off" pixels in the character's drawn wil use the\r
                                   pixel value from BltBuffer.\r
@@ -354,25 +366,38 @@ GlyphToBlt (
   IN     UINT8                         *GlyphBuffer,\r
   IN     EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,\r
   IN     EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,\r
-  IN     UINTN                         ImageWidth,\r
-  IN     UINTN                         ImageHeight,\r
+  IN     UINT16                        ImageWidth,\r
+  IN     UINT16                        BaseLine,\r
+  IN     UINTN                         RowWidth,\r
+  IN     UINTN                         RowHeight,\r
   IN     BOOLEAN                       Transparent,\r
   IN     CONST EFI_HII_GLYPH_INFO      *Cell,\r
   IN     UINT8                         Attributes,\r
   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin\r
   )\r
 {\r
-  UINT8                                Xpos;\r
-  UINT8                                Ypos;\r
-  UINT8                                Data;\r
-  UINT8                                Index;\r
-  UINTN                                OffsetY;\r
-  EFI_GRAPHICS_OUTPUT_BLT_PIXEL        *BltBuffer;\r
+  UINT16                                Xpos;\r
+  UINT16                                Ypos;\r
+  UINT8                                 Data;\r
+  UINT16                                Index;\r
+  UINT16                                YposOffset;\r
+  UINTN                                 OffsetY;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL         *BltBuffer;\r
 \r
-  ASSERT (GlyphBuffer != NULL && Origin != NULL && *Origin != NULL);\r
-  ASSERT (Cell->Width <= ImageWidth && Cell->Height <= ImageHeight);\r
+  ASSERT (Origin != NULL && *Origin != NULL && Cell != NULL);\r
 \r
-  BltBuffer = *Origin;\r
+  //\r
+  // Only adjust origin position if char has no bitmap.\r
+  //\r
+  if (GlyphBuffer == NULL) {\r
+    *Origin = *Origin + Cell->AdvanceX;\r
+    return;\r
+  }\r
+  //\r
+  // Move position to the left-top corner of char.\r
+  //\r
+  BltBuffer  = *Origin + Cell->OffsetX - (Cell->OffsetY + Cell->Height) * ImageWidth;\r
+  YposOffset = (UINT16) (BaseLine - (Cell->OffsetY + Cell->Height));\r
 \r
   //\r
   // Since non-spacing key will be printed OR'd with the previous glyph, don't\r
@@ -386,7 +411,7 @@ GlyphToBlt (
   // The glyph's upper left hand corner pixel is the most significant bit of the\r
   // first bitmap byte.\r
   //\r
-  for (Ypos = 0; Ypos < Cell->Height; Ypos++) {\r
+  for (Ypos = 0; Ypos < Cell->Height && ((UINTN) (Ypos + YposOffset) < RowHeight); Ypos++) {\r
     OffsetY = BITMAP_LEN_1_BIT (Cell->Width, Ypos);\r
 \r
     //\r
@@ -394,12 +419,12 @@ GlyphToBlt (
     //\r
     for (Xpos = 0; Xpos < Cell->Width / 8; Xpos++) {\r
       Data  = *(GlyphBuffer + OffsetY + Xpos);\r
-      for (Index = 0; Index < 8; Index++) {\r
-        if ((Data & (1 << Index)) != 0) {\r
-          BltBuffer[Ypos * ImageWidth + Xpos * 8 + (8 - Index - 1)] = Foreground;\r
+      for (Index = 0; Index < 8 && ((UINTN) (Xpos * 8 + Index + Cell->OffsetX) < RowWidth); Index++) {\r
+        if ((Data & (1 << (8 - Index - 1))) != 0) {\r
+          BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Foreground;\r
         } else {\r
           if (!Transparent) {\r
-            BltBuffer[Ypos * ImageWidth + Xpos * 8 + (8 - Index - 1)] = Background;\r
+            BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Background;\r
           }\r
         }\r
       }\r
@@ -410,7 +435,7 @@ GlyphToBlt (
       // There are some padding bits in this byte. Ignore them.\r
       //\r
       Data  = *(GlyphBuffer + OffsetY + Xpos);\r
-      for (Index = 0; Index < Cell->Width % 8; Index++) {\r
+      for (Index = 0; Index < Cell->Width % 8 && ((UINTN) (Xpos * 8 + Index + Cell->OffsetX) < RowWidth); Index++) {\r
         if ((Data & (1 << (8 - Index - 1))) != 0) {\r
           BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Foreground;\r
         } else {\r
@@ -423,7 +448,7 @@ GlyphToBlt (
 \r
   } // end of for (Ypos=0...)\r
 \r
-  *Origin = BltBuffer + Cell->Width;\r
+  *Origin = *Origin + Cell->AdvanceX;\r
 }\r
 \r
 \r
@@ -437,10 +462,10 @@ GlyphToBlt (
                                   bitmap.\r
   @param  Background              The color of the "off" pixels in the glyph in the\r
                                   bitmap.\r
-  @param  ImageWidth              Width of the character or character cell, in\r
-                                  pixels.\r
-  @param  ImageHeight             Height of the character or character cell, in\r
-                                  pixels.\r
+  @param  ImageWidth              Width of the whole image in pixels.\r
+  @param  BaseLine                BaseLine in the line.\r
+  @param  RowWidth                The width of the text on the line, in pixels.\r
+  @param  RowHeight               The height of the line, in pixels.\r
   @param  Transparent             If TRUE, the Background color is ignored and all\r
                                   "off" pixels in the character's drawn wil use the\r
                                   pixel value from BltBuffer.\r
@@ -458,8 +483,10 @@ GlyphToImage (
   IN     UINT8                         *GlyphBuffer,\r
   IN     EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,\r
   IN     EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,\r
-  IN     UINTN                         ImageWidth,\r
-  IN     UINTN                         ImageHeight,\r
+  IN     UINT16                        ImageWidth,\r
+  IN     UINT16                        BaseLine,\r
+  IN     UINTN                         RowWidth,\r
+  IN     UINTN                         RowHeight,\r
   IN     BOOLEAN                       Transparent,\r
   IN     CONST EFI_HII_GLYPH_INFO      *Cell,\r
   IN     UINT8                         Attributes,\r
@@ -468,8 +495,7 @@ GlyphToImage (
 {\r
   EFI_GRAPHICS_OUTPUT_BLT_PIXEL        *Buffer;\r
 \r
-  ASSERT (GlyphBuffer != NULL && Origin != NULL && *Origin != NULL);\r
-  ASSERT (Cell->Width <= ImageWidth && Cell->Height <= ImageHeight);\r
+  ASSERT (Origin != NULL && *Origin != NULL && Cell != NULL);\r
 \r
   Buffer = *Origin;\r
 \r
@@ -478,13 +504,15 @@ GlyphToImage (
     // This character is a non-spacing key, print it OR'd with the previous glyph.\r
     // without advancing cursor.\r
     //\r
-    Buffer -= Cell->Width;\r
+    Buffer -= Cell->AdvanceX;\r
     GlyphToBlt (\r
       GlyphBuffer,\r
       Foreground,\r
       Background,\r
       ImageWidth,\r
-      ImageHeight,\r
+      BaseLine,\r
+      RowWidth,\r
+      RowHeight,\r
       Transparent,\r
       Cell,\r
       Attributes,\r
@@ -501,7 +529,8 @@ GlyphToImage (
       Foreground,\r
       Background,\r
       ImageWidth,\r
-      ImageHeight,\r
+      RowWidth,\r
+      RowHeight,\r
       Transparent,\r
       Origin\r
       );\r
@@ -511,7 +540,8 @@ GlyphToImage (
       Foreground,\r
       Background,\r
       ImageWidth,\r
-      ImageHeight,\r
+      RowWidth,\r
+      RowHeight,\r
       Transparent,\r
       Origin\r
       );\r
@@ -525,7 +555,8 @@ GlyphToImage (
       Foreground,\r
       Background,\r
       ImageWidth,\r
-      ImageHeight,\r
+      RowWidth,\r
+      RowHeight,\r
       Transparent,\r
       Origin\r
       );\r
@@ -539,7 +570,9 @@ GlyphToImage (
       Foreground,\r
       Background,\r
       ImageWidth,\r
-      ImageHeight,\r
+      BaseLine,\r
+      RowWidth,\r
+      RowHeight,\r
       Transparent,\r
       Cell,\r
       Attributes,\r
@@ -581,7 +614,7 @@ WriteOutputParam (
   OUT UINTN                          *GlyphBufferLen OPTIONAL\r
   )\r
 {\r
-  if (BufferIn == NULL || BufferLen < 1 || InputCell == NULL) {\r
+  if (BufferIn == NULL || InputCell == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -589,7 +622,7 @@ WriteOutputParam (
     CopyMem (Cell, InputCell, sizeof (EFI_HII_GLYPH_INFO));\r
   }\r
 \r
-  if (GlyphBuffer != NULL) {\r
+  if (GlyphBuffer != NULL && BufferLen > 0) {\r
     *GlyphBuffer = (UINT8 *) AllocateZeroPool (BufferLen);\r
     if (*GlyphBuffer == NULL) {\r
       return EFI_OUT_OF_RESOURCES;\r
@@ -645,10 +678,14 @@ FindGlyphBlock (
   UINT16                              Index;\r
   EFI_HII_GLYPH_INFO                  DefaultCell;\r
   EFI_HII_GLYPH_INFO                  LocalCell;\r
+  INT16                               MinOffsetY;\r
+  UINT16                              BaseLine;\r
 \r
   ASSERT (FontPackage != NULL);\r
   ASSERT (FontPackage->Signature == HII_FONT_PACKAGE_SIGNATURE);\r
-\r
+  BaseLine  = 0;\r
+  MinOffsetY = 0;\r
+  \r
   if (CharValue == (CHAR16) (-1)) {\r
     //\r
     // Collect the cell information specified in font package fixed header.\r
@@ -662,6 +699,11 @@ FindGlyphBlock (
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
+    CopyMem (\r
+      &LocalCell,\r
+      (UINT8 *) FontPackage->FontPkgHdr + 3 * sizeof (UINT32),\r
+      sizeof (EFI_HII_GLYPH_INFO)\r
+      );\r
   }\r
 \r
   BlockPtr    = FontPackage->GlyphBlock;\r
@@ -684,6 +726,17 @@ FindGlyphBlock (
         if (EFI_ERROR (Status)) {\r
           return Status;\r
         }\r
+        CopyMem (\r
+          &LocalCell,\r
+          BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK),\r
+          sizeof (EFI_HII_GLYPH_INFO)\r
+          );\r
+        if (BaseLine < LocalCell.Height + LocalCell.OffsetY) {\r
+          BaseLine = (UINT16) (LocalCell.Height + LocalCell.OffsetY);\r
+        }\r
+        if (MinOffsetY > LocalCell.OffsetY) {\r
+          MinOffsetY = LocalCell.OffsetY;\r
+        }\r
       }\r
       BlockPtr += sizeof (EFI_HII_GIBT_DEFAULTS_BLOCK);\r
       break;\r
@@ -700,12 +753,12 @@ FindGlyphBlock (
       break;\r
 \r
     case EFI_HII_GIBT_EXT1:\r
-      BlockPtr += *(BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8));\r
+      BlockPtr += *(UINT8*)((UINTN)BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8));\r
       break;\r
     case EFI_HII_GIBT_EXT2:\r
       CopyMem (\r
         &Length16,\r
-        BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8),\r
+        (UINT8*)((UINTN)BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8)),\r
         sizeof (UINT16)\r
         );\r
       BlockPtr += Length16;\r
@@ -713,7 +766,7 @@ FindGlyphBlock (
     case EFI_HII_GIBT_EXT4:\r
       CopyMem (\r
         &Length32,\r
-        BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8),\r
+        (UINT8*)((UINTN)BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8)),\r
         sizeof (UINT32)\r
         );\r
       BlockPtr += Length32;\r
@@ -725,10 +778,18 @@ FindGlyphBlock (
         BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK),\r
         sizeof (EFI_HII_GLYPH_INFO)\r
         );\r
+      if (CharValue == (CHAR16) (-1)) {\r
+        if (BaseLine < LocalCell.Height + LocalCell.OffsetY) {\r
+          BaseLine = (UINT16) (LocalCell.Height + LocalCell.OffsetY);\r
+        }\r
+        if (MinOffsetY > LocalCell.OffsetY) {\r
+          MinOffsetY = LocalCell.OffsetY;\r
+        }\r
+      }\r
       BufferLen = BITMAP_LEN_1_BIT (LocalCell.Width, LocalCell.Height);\r
       if (CharCurrent == CharValue) {\r
         return WriteOutputParam (\r
-                 BlockPtr + sizeof (EFI_HII_GIBT_GLYPH_BLOCK) - sizeof (UINT8),\r
+                 (UINT8*)((UINTN)BlockPtr + sizeof (EFI_HII_GIBT_GLYPH_BLOCK) - sizeof (UINT8)),\r
                  BufferLen,\r
                  &LocalCell,\r
                  GlyphBuffer,\r
@@ -747,6 +808,15 @@ FindGlyphBlock (
       CopyMem (&Glyphs.Count, BlockPtr, sizeof (UINT16));\r
       BlockPtr += sizeof (UINT16);\r
 \r
+      if (CharValue == (CHAR16) (-1)) {\r
+        if (BaseLine < Glyphs.Cell.Height + Glyphs.Cell.OffsetY) {\r
+          BaseLine = (UINT16) (Glyphs.Cell.Height + Glyphs.Cell.OffsetY);\r
+        }\r
+        if (MinOffsetY > Glyphs.Cell.OffsetY) {\r
+          MinOffsetY = Glyphs.Cell.OffsetY;\r
+        }\r
+      }\r
+\r
       BufferLen = BITMAP_LEN_1_BIT (Glyphs.Cell.Width, Glyphs.Cell.Height);\r
       for (Index = 0; Index < Glyphs.Count; Index++) {\r
         if (CharCurrent + Index == CharValue) {\r
@@ -829,6 +899,8 @@ FindGlyphBlock (
   }\r
 \r
   if (CharValue == (CHAR16) (-1)) {\r
+    FontPackage->BaseLine = BaseLine;\r
+    FontPackage->Height   = (UINT16) (BaseLine - MinOffsetY);\r
     return EFI_SUCCESS;\r
   }\r
 \r
@@ -857,16 +929,18 @@ SaveFontName (
   )\r
 {\r
   UINTN         FontInfoLen;\r
+  UINTN         NameSize;\r
 \r
   ASSERT (FontName != NULL && FontInfo != NULL);\r
 \r
-  FontInfoLen = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + StrSize (FontName);\r
+  NameSize = StrSize (FontName);\r
+  FontInfoLen = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + NameSize;\r
   *FontInfo = (EFI_FONT_INFO *) AllocateZeroPool (FontInfoLen);\r
   if (*FontInfo == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  StrCpy ((*FontInfo)->FontName, FontName);\r
+  StrCpyS ((*FontInfo)->FontName, NameSize / sizeof (CHAR16), FontName);\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -895,6 +969,7 @@ GetSystemFont (
 {\r
   EFI_FONT_DISPLAY_INFO              *Info;\r
   UINTN                              InfoSize;\r
+  UINTN                              NameSize;\r
 \r
   if (Private == NULL || Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -906,7 +981,8 @@ GetSystemFont (
   //\r
   // The standard font always has the name "sysdefault".\r
   //\r
-  InfoSize = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + StrSize (L"sysdefault");\r
+  NameSize = StrSize (L"sysdefault");\r
+  InfoSize = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + NameSize;\r
   Info = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (InfoSize);\r
   if (Info == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
@@ -917,7 +993,7 @@ GetSystemFont (
   Info->FontInfoMask       = EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_SYS_STYLE;\r
   Info->FontInfo.FontStyle = 0;\r
   Info->FontInfo.FontSize  = EFI_GLYPH_HEIGHT;\r
-  StrCpy (Info->FontInfo.FontName, L"sysdefault");\r
+  StrCpyS (Info->FontInfo.FontName, NameSize / sizeof (CHAR16), L"sysdefault");\r
 \r
   *FontInfo = Info;\r
   if (FontInfoSize != NULL) {\r
@@ -964,8 +1040,12 @@ IsSystemFontInfo (
     return TRUE;\r
   }\r
 \r
+  SystemDefault = NULL;\r
+  DefaultLen    = 0;\r
+\r
   Status = GetSystemFont (Private, &SystemDefault, &DefaultLen);\r
   ASSERT_EFI_ERROR (Status);\r
+  ASSERT ((SystemDefault != NULL) && (DefaultLen != 0));\r
 \r
   //\r
   // Record the system default info.\r
@@ -1344,15 +1424,14 @@ IsFontInfoExisted (
 /**\r
   Check whether the unicode represents a line break or not.\r
 \r
-  This is a internal function.\r
+  This is a internal function. Please see Section 27.2.6 of the UEFI Specification\r
+  for a description of the supported string format.\r
 \r
   @param  Char                    Unicode character\r
 \r
-  @retval 0                       Yes, it is a line break.\r
-  @retval 1                       Yes, it is a hyphen that desires a line break\r
-                                  after this character.\r
-  @retval 2                       Yes, it is a dash that desires a line break\r
-                                  before and after it.\r
+  @retval 0                       Yes, it forces a line break.\r
+  @retval 1                       Yes, it presents a line break opportunity\r
+  @retval 2                       Yes, it requires a line break happen before and after it.\r
   @retval -1                      No, it is not a link break.\r
 \r
 **/\r
@@ -1361,61 +1440,64 @@ IsLineBreak (
   IN  CHAR16    Char\r
   )\r
 {\r
-  UINT8         Byte1;\r
-  UINT8         Byte2;\r
-\r
-  //\r
-  // In little endian, Byte1 is the low byte of Char, Byte2 is the high byte of Char.\r
-  //\r
-  Byte1 = *((UINT8 *) (&Char));\r
-  Byte2 = *(((UINT8 *) (&Char) + 1));\r
-\r
-  if (Byte2 == 0x20) {\r
-    switch (Byte1) {\r
-    case 0x00:\r
-    case 0x01:\r
-    case 0x02:\r
-    case 0x03:\r
-    case 0x04:\r
-    case 0x05:\r
-    case 0x06:\r
-    case 0x08:\r
-    case 0x09:\r
-    case 0x0A:\r
-    case 0x0B:\r
-    case 0x28:\r
-    case 0x29:\r
-    case 0x5F:\r
-      return 0;\r
-    case 0x10:\r
-    case 0x12:\r
-    case 0x13:\r
-      return 1;\r
-    case 0x14:\r
-      //\r
-      // BUGBUG: Does it really require line break before it and after it?\r
-      //\r
-      return 2;\r
-    }\r
-  } else if (Byte2 == 0x00) {\r
-    switch (Byte1) {\r
-    case 0x20:\r
-    case 0x0C:\r
-    case 0x0D:\r
-      return 0;\r
-    }\r
-  }\r
-\r
   switch (Char) {\r
-    case 0x1680:\r
+    //\r
+    // Mandatory line break characters, which force a line-break\r
+    //\r
+    case 0x000A:\r
+    case 0x000C:\r
+    case 0x000D:\r
+    case 0x2028:\r
+    case 0x2029:\r
       return 0;\r
+    //\r
+    // Space characters, which is taken as a line-break opportunity\r
+    //\r
+    case 0x0020:\r
+    case 0x1680:\r
+    case 0x2000:\r
+    case 0x2001:\r
+    case 0x2002:\r
+    case 0x2003:\r
+    case 0x2004:\r
+    case 0x2005:\r
+    case 0x2006:\r
+    case 0x2008:\r
+    case 0x2009:\r
+    case 0x200A:\r
+    case 0x205F:\r
+    //\r
+    // In-Word Break Opportunities\r
+    //\r
+    case 0x200B:\r
+      return 1;\r
+    //\r
+    // A space which is not a line-break opportunity\r
+    //\r
+    case 0x00A0:\r
+    case 0x202F:\r
+    //\r
+    // A hyphen which is not a line-break opportunity\r
+    //\r
+    case 0x2011:\r
+      return -1;\r
+    //\r
+    // Hyphen characters which describe line break opportunities after the character\r
+    //\r
     case 0x058A:\r
+    case 0x2010:\r
+    case 0x2012:\r
+    case 0x2013:\r
     case 0x0F0B:\r
     case 0x1361:\r
     case 0x17D5:\r
       return 1;\r
+    //\r
+    // A hyphen which describes line break opportunities before and after them, but not between a pair of them\r
+    //\r
+    case 0x2014:\r
+      return 2;\r
   }\r
-\r
   return -1;\r
 }\r
 \r
@@ -1500,10 +1582,13 @@ HiiStringToImage (
   EFI_HII_ROW_INFO                    *RowInfo;\r
   UINTN                               LineWidth;\r
   UINTN                               LineHeight;\r
+  UINTN                               LineOffset;\r
+  UINTN                               LastLineHeight;\r
   UINTN                               BaseLineOffset;\r
   UINT16                              MaxRowNum;\r
   UINT16                              RowIndex;\r
   UINTN                               Index;\r
+  UINTN                               NextIndex;\r
   UINTN                               Index1;\r
   EFI_FONT_DISPLAY_INFO               *StringInfoOut;\r
   EFI_FONT_DISPLAY_INFO               *SystemDefault;\r
@@ -1511,6 +1596,7 @@ HiiStringToImage (
   EFI_STRING                          StringIn;\r
   EFI_STRING                          StringIn2;\r
   UINT16                              Height;\r
+  UINT16                              BaseLine;\r
   EFI_FONT_INFO                       *FontInfo;\r
   BOOLEAN                             SysFontFlag;\r
   EFI_GRAPHICS_OUTPUT_BLT_PIXEL       Foreground;\r
@@ -1520,6 +1606,10 @@ HiiStringToImage (
   EFI_GRAPHICS_OUTPUT_BLT_PIXEL       *BufferPtr;\r
   UINTN                               RowInfoSize;\r
   BOOLEAN                             LineBreak;\r
+  UINTN                               StrLength;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL       *RowBufferPtr;\r
+  HII_GLOBAL_FONT_INFO                *GlobalFont;\r
+  UINT32                              PreInitBkgnd;\r
 \r
   //\r
   // Check incoming parameters.\r
@@ -1555,11 +1645,35 @@ HiiStringToImage (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  GlyphBuf = (UINT8 **) AllocateZeroPool (MAX_STRING_LENGTH * sizeof (UINT8 *));\r
+  if (*Blt == NULL) {\r
+    //\r
+    // Create a new bitmap and draw the string onto this image.\r
+    //\r
+    Image = AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));\r
+    if (Image == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    Image->Width  = 800;\r
+    Image->Height = 600;\r
+    Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height *sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+    if (Image->Image.Bitmap == NULL) {\r
+      FreePool (Image);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    //\r
+    // Other flags are not permitted when Blt is NULL.\r
+    //\r
+    Flags &= EFI_HII_OUT_FLAG_WRAP | EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_IGNORE_LINE_BREAK;\r
+    *Blt = Image;\r
+  }\r
+\r
+  StrLength = StrLen(String);\r
+  GlyphBuf = (UINT8 **) AllocateZeroPool (StrLength * sizeof (UINT8 *));\r
   ASSERT (GlyphBuf != NULL);\r
-  Cell = (EFI_HII_GLYPH_INFO *) AllocateZeroPool (MAX_STRING_LENGTH * sizeof (EFI_HII_GLYPH_INFO));\r
+  Cell = (EFI_HII_GLYPH_INFO *) AllocateZeroPool (StrLength * sizeof (EFI_HII_GLYPH_INFO));\r
   ASSERT (Cell != NULL);\r
-  Attributes = (UINT8 *) AllocateZeroPool (MAX_STRING_LENGTH * sizeof (UINT8));\r
+  Attributes = (UINT8 *) AllocateZeroPool (StrLength * sizeof (UINT8));\r
   ASSERT (Attributes != NULL);\r
 \r
   RowInfo       = NULL;\r
@@ -1579,8 +1693,10 @@ HiiStringToImage (
   SysFontFlag   = IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfo, &SystemDefault, NULL);\r
 \r
   if (SysFontFlag) {\r
+    ASSERT (SystemDefault != NULL);\r
     FontInfo   = NULL;\r
     Height     = SystemDefault->FontInfo.FontSize;\r
+    BaseLine   = SystemDefault->FontInfo.FontSize;\r
     Foreground = SystemDefault->ForegroundColor;\r
     Background = SystemDefault->BackgroundColor;\r
 \r
@@ -1598,19 +1714,30 @@ HiiStringToImage (
       SysFontFlag = TRUE;\r
       FontInfo    = NULL;\r
       Height      = SystemDefault->FontInfo.FontSize;\r
+      BaseLine    = SystemDefault->FontInfo.FontSize;\r
       Foreground  = ((EFI_FONT_DISPLAY_INFO *) StringInfo)->ForegroundColor;\r
       Background  = ((EFI_FONT_DISPLAY_INFO *) StringInfo)->BackgroundColor;\r
 \r
     } else if (Status == EFI_SUCCESS) {\r
       FontInfo   = &StringInfoOut->FontInfo;\r
-      Height     = StringInfoOut->FontInfo.FontSize;\r
+      IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont);\r
+      Height     = GlobalFont->FontPackage->Height;\r
+      BaseLine   = GlobalFont->FontPackage->BaseLine;\r
       Foreground = StringInfoOut->ForegroundColor;\r
       Background = StringInfoOut->BackgroundColor;\r
     } else {\r
       goto Exit;\r
     }\r
   }\r
-\r
+  \r
+  //\r
+  // Use the maxinum height of font as the base line.\r
+  // And, use the maxinum height as line height.\r
+  //\r
+  LineHeight     = Height;\r
+  LastLineHeight = Height;\r
+  BaseLineOffset = Height - BaseLine;\r
+  \r
   //\r
   // Parse the string to be displayed to drop some ignored characters.\r
   //\r
@@ -1649,16 +1776,20 @@ HiiStringToImage (
   }\r
   Index     = 0;\r
   StringTmp = StringIn2;\r
-\r
-  while (*StringPtr != 0 && Index < MAX_STRING_LENGTH) {\r
+  StrLength = StrLen(StringPtr);\r
+  while (*StringPtr != 0 && Index < StrLength) {\r
+    if (IsLineBreak (*StringPtr) == 0) {\r
+      *StringTmp++ = *StringPtr++;\r
+      Index++;\r
+      continue;\r
+    }\r
+    \r
     Status = GetGlyphBuffer (Private, *StringPtr, FontInfo, &GlyphBuf[Index], &Cell[Index], &Attributes[Index]);\r
     if (Status == EFI_NOT_FOUND) {\r
       if ((Flags & EFI_HII_IGNORE_IF_NO_GLYPH) == EFI_HII_IGNORE_IF_NO_GLYPH) {\r
-        if (GlyphBuf[Index] != NULL) {\r
-          FreePool (GlyphBuf[Index]);\r
-        }\r
         GlyphBuf[Index] = NULL;\r
-        StringPtr++;\r
+        ZeroMem (&Cell[Index], sizeof (Cell[Index]));\r
+        Status = EFI_SUCCESS;\r
       } else {\r
         //\r
         // Unicode 0xFFFD must exist in current hii database if this flag is not set.\r
@@ -1673,17 +1804,16 @@ HiiStringToImage (
                    );\r
         if (EFI_ERROR (Status)) {\r
           Status = EFI_INVALID_PARAMETER;\r
-          goto Exit;\r
         }\r
-        *StringTmp++ = *StringPtr++;\r
-        Index++;\r
       }\r
-    } else if (EFI_ERROR (Status)) {\r
+    }\r
+\r
+    if (EFI_ERROR (Status)) {\r
       goto Exit;\r
-    } else {\r
-      *StringTmp++ = *StringPtr++;\r
-      Index++;\r
     }\r
+\r
+    *StringTmp++ = *StringPtr++;\r
+    Index++;\r
   }\r
   *StringTmp = 0;\r
   StringPtr  = StringIn2;\r
@@ -1694,180 +1824,269 @@ HiiStringToImage (
   // to an existing image (bitmap or screen depending on flags) pointed by "*Blt".\r
   // Otherwise render this string to a new allocated image and output it.\r
   //\r
-  if (*Blt != NULL) {\r
-    Image     = *Blt;\r
-    BufferPtr = Image->Image.Bitmap + Image->Width * BltY + BltX;\r
-    MaxRowNum = (UINT16) (Image->Height / Height);\r
-    if (Image->Height % Height != 0) {\r
-      MaxRowNum++;\r
-    }\r
-\r
-    RowInfo = (EFI_HII_ROW_INFO *) AllocateZeroPool (MaxRowNum * sizeof (EFI_HII_ROW_INFO));\r
-    if (RowInfo == NULL) {\r
-      Status = EFI_OUT_OF_RESOURCES;\r
-      goto Exit;\r
-    }\r
-\r
+  Image     = *Blt;\r
+  BufferPtr = Image->Image.Bitmap + Image->Width * BltY + BltX;\r
+  if (Image->Height < BltY) {\r
     //\r
-    // Format the glyph buffer according to flags.\r
+    // the top edge of the image should be in Image resolution scope.\r
     //\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Exit;\r
+  }\r
+  MaxRowNum = (UINT16) ((Image->Height - BltY) / Height);\r
+  if ((Image->Height - BltY) % Height != 0) {\r
+    LastLineHeight = (Image->Height - BltY) % Height;\r
+    MaxRowNum++;\r
+  }\r
 \r
-    Transparent = (BOOLEAN) ((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT ? TRUE : FALSE);\r
-    if ((Flags & EFI_HII_OUT_FLAG_CLIP_CLEAN_Y) == EFI_HII_OUT_FLAG_CLIP_CLEAN_Y) {\r
-      //\r
-      // Don't draw at all if there is only one row and\r
-      // the row's bottom-most on pixel cannot fit.\r
-      //\r
-      if (MaxRowNum == 1 && SysFontFlag) {\r
-        Status = EFI_SUCCESS;\r
-        goto Exit;\r
-      }\r
-    }\r
+  RowInfo = (EFI_HII_ROW_INFO *) AllocateZeroPool (MaxRowNum * sizeof (EFI_HII_ROW_INFO));\r
+  if (RowInfo == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Exit;\r
+  }\r
 \r
-    for (RowIndex = 0, Index = 0; RowIndex < MaxRowNum && StringPtr[Index] != 0; ) {\r
-      LineWidth      = 0;\r
-      LineHeight     = 0;\r
-      BaseLineOffset = 0;\r
-      LineBreak      = FALSE;\r
+  //\r
+  // Format the glyph buffer according to flags.\r
+  //\r
+  Transparent = (BOOLEAN) ((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT ? TRUE : FALSE);\r
 \r
-      //\r
-      // Calculate how many characters there are in a row.\r
-      //\r
-      RowInfo[RowIndex].StartIndex = Index;\r
+  for (RowIndex = 0, Index = 0; RowIndex < MaxRowNum && StringPtr[Index] != 0; ) {\r
+    LineWidth      = 0;\r
+    LineBreak      = FALSE;\r
 \r
-      while (LineWidth + BltX < Image->Width && StringPtr[Index] != 0) {\r
-        LineWidth += (UINTN) Cell[Index].AdvanceX;\r
-        if (LineHeight < Cell[Index].Height) {\r
-          LineHeight = (UINTN) Cell[Index].Height;\r
-        }\r
+    //\r
+    // Clip the final row if the row's bottom-most on pixel cannot fit when\r
+    // EFI_HII_OUT_FLAG_CLEAN_Y is set.\r
+    //\r
+    if (RowIndex == MaxRowNum - 1) {\r
+      if ((Flags & EFI_HII_OUT_FLAG_CLIP_CLEAN_Y) == EFI_HII_OUT_FLAG_CLIP_CLEAN_Y && LastLineHeight < LineHeight ) {\r
+        //\r
+        // Don't draw at all if the row's bottom-most on pixel cannot fit.\r
+        //\r
+        break;\r
+      }\r
+      LineHeight = LastLineHeight;\r
+    }\r
 \r
-        if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0 &&\r
-            (Flags & EFI_HII_OUT_FLAG_WRAP) == 0 &&\r
-             IsLineBreak (StringPtr[Index]) > 0) {\r
-          //\r
-          // It is a line break that ends this row.\r
-          //\r
-          Index++;\r
-          break;\r
-        }\r
+    //\r
+    // Calculate how many characters there are in a row.\r
+    //\r
+    RowInfo[RowIndex].StartIndex = Index;\r
 \r
+    while (LineWidth + BltX < Image->Width && StringPtr[Index] != 0) {\r
+      if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0 &&\r
+           IsLineBreak (StringPtr[Index]) == 0) {\r
+        //\r
+        // It forces a line break that ends this row.\r
+        //\r
         Index++;\r
+        LineBreak = TRUE;\r
+        break;\r
       }\r
 \r
       //\r
-      // If this character is the last character of a row, we need not\r
-      // draw its (AdvanceX - Width) for next character.\r
+      // If the glyph of the character is existing, then accumulate the actual printed width\r
       //\r
-      Index--;\r
-      if (!SysFontFlag) {\r
-        LineWidth -= (UINTN) (Cell[Index].AdvanceX - Cell[Index].Width);\r
-      }\r
+      LineWidth += (UINTN) Cell[Index].AdvanceX;\r
 \r
+      Index++;\r
+    }\r
+\r
+    //\r
+    // Record index of next char.\r
+    //\r
+    NextIndex = Index;\r
+    //\r
+    // Return to the previous char.\r
+    //\r
+    Index--;\r
+    if (LineBreak && Index > 0 ) {\r
       //\r
-      // EFI_HII_OUT_FLAG_WRAP will wrap the text at the right-most line-break\r
-      // opportunity prior to a character whose right-most extent would exceed Width.\r
-      // Search the right-most line-break opportunity here.\r
+      // Return the previous non line break char.\r
       //\r
-      if ((Flags & EFI_HII_OUT_FLAG_WRAP) == EFI_HII_OUT_FLAG_WRAP) {\r
-        if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0) {\r
-          for (Index1 = RowInfo[RowIndex].EndIndex; Index1 >= RowInfo[RowIndex].StartIndex; Index1--) {\r
-            if (IsLineBreak (StringPtr[Index1]) > 0) {\r
-              LineBreak = TRUE;\r
-              RowInfo[RowIndex].EndIndex = Index1 - 1;\r
-              break;\r
-            }\r
-          }\r
-        }\r
-        //\r
-        // If no line-break opportunity can be found, then the text will\r
-        // behave as if EFI_HII_OUT_FLAG_CLEAN_X is set.\r
-        //\r
-        if (!LineBreak) {\r
-          Flags &= (~ (EFI_HII_OUT_FLAGS) EFI_HII_OUT_FLAG_WRAP);\r
-          Flags |= EFI_HII_OUT_FLAG_CLIP_CLEAN_X;\r
-        }\r
-      }\r
+      Index --;\r
+    }\r
+\r
+    //\r
+    // If this character is the last character of a row, we need not\r
+    // draw its (AdvanceX - Width - OffsetX) for next character.\r
+    //\r
+    LineWidth -= (UINTN) (Cell[Index].AdvanceX - Cell[Index].Width - Cell[Index].OffsetX);\r
 \r
+    //\r
+    // Clip the right-most character if cannot fit when EFI_HII_OUT_FLAG_CLEAN_X is set.\r
+    //\r
+    if (LineWidth + BltX <= Image->Width ||\r
+      (LineWidth + BltX > Image->Width && (Flags & EFI_HII_OUT_FLAG_CLIP_CLEAN_X) == 0)) {\r
+      //\r
+      // Record right-most character in RowInfo even if it is partially displayed.\r
+      //\r
+      RowInfo[RowIndex].EndIndex       = Index;\r
+      RowInfo[RowIndex].LineWidth      = LineWidth;\r
+      RowInfo[RowIndex].LineHeight     = LineHeight;\r
+      RowInfo[RowIndex].BaselineOffset = BaseLineOffset;\r
+    } else {\r
       //\r
-      // Clip the right-most character if cannot fit when EFI_HII_OUT_FLAG_CLEAN_X is set.\r
+      // When EFI_HII_OUT_FLAG_CLEAN_X is set, it will not draw a character\r
+      // if its right-most on pixel cannot fit.\r
       //\r
-      if (LineWidth + BltX <= Image->Width ||\r
-        (LineWidth + BltX > Image->Width && (Flags & EFI_HII_OUT_FLAG_CLIP_CLEAN_X) == 0)) {\r
+      if (Index > RowInfo[RowIndex].StartIndex) {\r
         //\r
-        // Record right-most character in RowInfo even if it is partially displayed.\r
+        // Don't draw the last char on this row. And, don't draw the second last char (AdvanceX - Width - OffsetX).\r
         //\r
-        RowInfo[RowIndex].EndIndex       = Index;\r
+        LineWidth -= (UINTN) (Cell[Index].Width + Cell[Index].OffsetX);\r
+        LineWidth -= (UINTN) (Cell[Index - 1].AdvanceX - Cell[Index - 1].Width - Cell[Index - 1].OffsetX);\r
+        RowInfo[RowIndex].EndIndex       = Index - 1;\r
         RowInfo[RowIndex].LineWidth      = LineWidth;\r
         RowInfo[RowIndex].LineHeight     = LineHeight;\r
         RowInfo[RowIndex].BaselineOffset = BaseLineOffset;\r
       } else {\r
         //\r
-        // When EFI_HII_OUT_FLAG_CLEAN_X is set, it will not draw a character\r
-        // if its right-most on pixel cannot fit.\r
+        // There is no enough column to draw any character, so set current line width to zero.\r
+        // And go to draw Next line if LineBreak is set.\r
         //\r
-        if (Index > 0) {\r
-          RowInfo[RowIndex].EndIndex       = Index - 1;\r
-          RowInfo[RowIndex].LineWidth      = LineWidth - Cell[Index].AdvanceX;\r
-          RowInfo[RowIndex].BaselineOffset = BaseLineOffset;\r
-          if (LineHeight > Cell[Index - 1].Height) {\r
-            LineHeight = Cell[Index - 1].Height;\r
+        RowInfo[RowIndex].LineWidth      = 0;\r
+        goto NextLine;\r
+      }\r
+    }\r
+\r
+    //\r
+    // EFI_HII_OUT_FLAG_WRAP will wrap the text at the right-most line-break\r
+    // opportunity prior to a character whose right-most extent would exceed Width.\r
+    // Search the right-most line-break opportunity here.\r
+    //\r
+    if ((Flags & EFI_HII_OUT_FLAG_WRAP) == EFI_HII_OUT_FLAG_WRAP && \r
+        (RowInfo[RowIndex].LineWidth + BltX > Image->Width || StringPtr[NextIndex] != 0) && \r
+        !LineBreak) {\r
+      if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0) {\r
+        LineWidth = RowInfo[RowIndex].LineWidth;\r
+        for (Index1 = RowInfo[RowIndex].EndIndex; Index1 >= RowInfo[RowIndex].StartIndex; Index1--) {\r
+          if (Index1 == RowInfo[RowIndex].EndIndex) {\r
+            LineWidth -= (Cell[Index1].Width + Cell[Index1].OffsetX);\r
+          } else {\r
+            LineWidth -= Cell[Index1].AdvanceX;\r
+          }\r
+          if (IsLineBreak (StringPtr[Index1]) > 0) {\r
+            LineBreak = TRUE;\r
+            if (Index1 > RowInfo[RowIndex].StartIndex) {\r
+              RowInfo[RowIndex].EndIndex = Index1 - 1;\r
+            }\r
+            //\r
+            // relocate to the character after the right-most line break opportunity of this line\r
+            //\r
+            NextIndex = Index1 + 1;\r
+            break;\r
           }\r
-          RowInfo[RowIndex].LineHeight     = LineHeight;\r
-        } else {\r
           //\r
-          // There is only one column and it can not be drawn so that return directly.\r
+          // If don't find a line break opportunity from EndIndex to StartIndex,\r
+          // then jump out.\r
           //\r
-          Status = EFI_SUCCESS;\r
-          goto Exit;\r
+          if (Index1 == RowInfo[RowIndex].StartIndex)\r
+            break;\r
         }\r
-      }\r
 \r
+        //\r
+        // Update LineWidth to the real width\r
+        //\r
+        if (IsLineBreak (StringPtr[Index1]) > 0) {\r
+          if (Index1 == RowInfo[RowIndex].StartIndex) {\r
+            LineWidth = 0;\r
+          } else {\r
+            LineWidth -= (UINTN) (Cell[Index1 - 1].AdvanceX - Cell[Index1 - 1].Width - Cell[Index1 - 1].OffsetX);\r
+          }\r
+          RowInfo[RowIndex].LineWidth = LineWidth;\r
+        }\r
+      }\r
       //\r
-      // Clip the final row if the row's bottom-most on pixel cannot fit when\r
-      // EFI_HII_OUT_FLAG_CLEAN_Y is set.\r
+      // If no line-break opportunity can be found, then the text will\r
+      // behave as if EFI_HII_OUT_FLAG_CLEAN_X is set.\r
       //\r
-      if (RowIndex == MaxRowNum - 1 && Image->Height < LineHeight) {\r
-        LineHeight = Image->Height;\r
-        if ((Flags & EFI_HII_OUT_FLAG_CLIP_CLEAN_Y) == EFI_HII_OUT_FLAG_CLIP_CLEAN_Y) {\r
-          //\r
-          // Don't draw at all if the row's bottom-most on pixel cannot fit.\r
-          //\r
-          break;\r
+      if (!LineBreak) {\r
+        LineWidth = RowInfo[RowIndex].LineWidth;\r
+        Index1    = RowInfo[RowIndex].EndIndex;\r
+        if (LineWidth + BltX > Image->Width) {\r
+          if (Index1 > RowInfo[RowIndex].StartIndex) {\r
+            //\r
+            // Don't draw the last char on this row. And, don't draw the second last char (AdvanceX - Width - OffsetX).\r
+            //\r
+            LineWidth -= (UINTN) (Cell[Index1].Width + Cell[Index1].OffsetX);\r
+            LineWidth -= (UINTN) (Cell[Index1 - 1].AdvanceX - Cell[Index1 - 1].Width - Cell[Index1 - 1].OffsetX);\r
+            RowInfo[RowIndex].EndIndex       = Index1 - 1;\r
+            RowInfo[RowIndex].LineWidth      = LineWidth;\r
+          } else {\r
+            //\r
+            // There is no enough column to draw any character, so set current line width to zero.\r
+            // And go to draw Next line if LineBreak is set.\r
+            //\r
+            RowInfo[RowIndex].LineWidth = 0;\r
+            goto NextLine;\r
+          }\r
         }\r
       }\r
+    }\r
+    \r
+    //\r
+    // LineWidth can't exceed Image width.\r
+    //\r
+    if (RowInfo[RowIndex].LineWidth + BltX > Image->Width) {\r
+      RowInfo[RowIndex].LineWidth = Image->Width - BltX;\r
+    }\r
 \r
-      //\r
-      // Draw it to screen or existing bitmap depending on whether\r
-      // EFI_HII_DIRECT_TO_SCREEN is set.\r
-      //\r
-      if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {\r
+    //\r
+    // Draw it to screen or existing bitmap depending on whether\r
+    // EFI_HII_DIRECT_TO_SCREEN is set.\r
+    //\r
+    LineOffset = 0;\r
+    if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {\r
+      BltBuffer = NULL;\r
+      if (RowInfo[RowIndex].LineWidth != 0) {\r
         BltBuffer = AllocateZeroPool (RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
         if (BltBuffer == NULL) {\r
           Status = EFI_OUT_OF_RESOURCES;\r
           goto Exit;\r
         }\r
-        BufferPtr = BltBuffer;\r
-        for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {\r
+        //\r
+        // Initialize the background color.\r
+        //\r
+        PreInitBkgnd = Background.Blue | Background.Green << 8 | Background.Red << 16;\r
+        SetMem32 (BltBuffer,RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL),PreInitBkgnd);\r
+        //\r
+        // Set BufferPtr to Origin by adding baseline to the starting position.\r
+        //\r
+        BufferPtr = BltBuffer + BaseLine * RowInfo[RowIndex].LineWidth;\r
+      }\r
+      for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {\r
+        if (RowInfo[RowIndex].LineWidth > 0 && RowInfo[RowIndex].LineWidth > LineOffset) {\r
+          //\r
+          // Only BLT these character which have corrsponding glyph in font basebase.\r
+          //\r
           GlyphToImage (\r
             GlyphBuf[Index1],\r
             Foreground,\r
             Background,\r
-            RowInfo[RowIndex].LineWidth,\r
+            (UINT16) RowInfo[RowIndex].LineWidth,\r
+            BaseLine,\r
+            RowInfo[RowIndex].LineWidth - LineOffset,\r
             RowInfo[RowIndex].LineHeight,\r
             Transparent,\r
             &Cell[Index1],\r
             Attributes[Index1],\r
             &BufferPtr\r
-            );\r
-          if (ColumnInfoArray != NULL) {\r
-            if (Index1 == RowInfo[RowIndex].StartIndex) {\r
-              *ColumnInfoArray = 0;\r
-            } else {\r
-              *ColumnInfoArray = Cell[Index1 -1].AdvanceX;\r
-            }\r
-            ColumnInfoArray++;\r
+          );\r
+        }\r
+        if (ColumnInfoArray != NULL) {\r
+          if ((GlyphBuf[Index1] == NULL && Cell[Index1].AdvanceX == 0) \r
+              || RowInfo[RowIndex].LineWidth == 0) {\r
+            *ColumnInfoArray = (UINTN) ~0;\r
+          } else {\r
+            *ColumnInfoArray = LineOffset + Cell[Index1].OffsetX + BltX;\r
           }\r
+          ColumnInfoArray++;\r
         }\r
+        LineOffset += Cell[Index1].AdvanceX;\r
+      }\r
+\r
+      if (BltBuffer != NULL) {\r
         Status = Image->Image.Screen->Blt (\r
                                         Image->Image.Screen,\r
                                         BltBuffer,\r
@@ -1884,102 +2103,101 @@ HiiStringToImage (
           FreePool (BltBuffer);\r
           goto Exit;\r
         }\r
-\r
+  \r
         FreePool (BltBuffer);\r
-\r
-      } else {\r
-        for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {\r
+      }\r
+    } else {\r
+      //\r
+      // Save the starting position for calculate the starting postition of next row. \r
+      //\r
+      RowBufferPtr = BufferPtr;\r
+      //\r
+      // Set BufferPtr to Origin by adding baseline to the starting position.\r
+      //\r
+      BufferPtr = BufferPtr + BaseLine * Image->Width;\r
+      for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {\r
+        if (RowInfo[RowIndex].LineWidth > 0 && RowInfo[RowIndex].LineWidth > LineOffset) {\r
+          //\r
+          // Only BLT these character which have corrsponding glyph in font basebase.\r
+          //\r
           GlyphToImage (\r
             GlyphBuf[Index1],\r
             Foreground,\r
             Background,\r
             Image->Width,\r
-            Image->Height,\r
+            BaseLine,\r
+            RowInfo[RowIndex].LineWidth - LineOffset,\r
+            RowInfo[RowIndex].LineHeight,\r
             Transparent,\r
             &Cell[Index1],\r
             Attributes[Index1],\r
             &BufferPtr\r
-            );\r
-          if (ColumnInfoArray != NULL) {\r
-            if (Index1 == RowInfo[RowIndex].StartIndex) {\r
-              *ColumnInfoArray = 0;\r
-            } else {\r
-              *ColumnInfoArray = Cell[Index1 -1].AdvanceX;\r
-            }\r
-            ColumnInfoArray++;\r
+          );\r
+        }\r
+        if (ColumnInfoArray != NULL) {\r
+          if ((GlyphBuf[Index1] == NULL && Cell[Index1].AdvanceX == 0) \r
+              || RowInfo[RowIndex].LineWidth == 0) {\r
+            *ColumnInfoArray = (UINTN) ~0;\r
+          } else {\r
+            *ColumnInfoArray = LineOffset + Cell[Index1].OffsetX + BltX;\r
           }\r
+          ColumnInfoArray++;\r
         }\r
-        //\r
-        // Jump to next row\r
-        //\r
-        BufferPtr += BltX + Image->Width * (LineHeight - 1);\r
+        LineOffset += Cell[Index1].AdvanceX;\r
       }\r
 \r
-      Index++;\r
-      RowIndex++;\r
-\r
+      //\r
+      // Jump to starting position of next row.\r
+      //\r
+      if (RowIndex == 0) {\r
+        BufferPtr = RowBufferPtr - BltX + LineHeight * Image->Width;\r
+      } else {\r
+        BufferPtr = RowBufferPtr + LineHeight * Image->Width;\r
+      }\r
     }\r
 \r
+NextLine:\r
     //\r
-    // Write output parameters.\r
+    // Recalculate the start point of Y axis to draw multi-lines with the order of top-to-down\r
     //\r
-    RowInfoSize = RowIndex * sizeof (EFI_HII_ROW_INFO);\r
-    if (RowInfoArray != NULL) {\r
+    BltY += RowInfo[RowIndex].LineHeight;\r
+\r
+    RowIndex++;\r
+    Index = NextIndex;\r
+\r
+    if (!LineBreak) {\r
+      //\r
+      // If there is not a mandatory line break or line break opportunity, only render one line to image\r
+      //\r
+      break;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Write output parameters.\r
+  //\r
+  RowInfoSize = RowIndex * sizeof (EFI_HII_ROW_INFO);\r
+  if (RowInfoArray != NULL) {\r
+    if (RowInfoSize > 0) {\r
       *RowInfoArray = AllocateZeroPool (RowInfoSize);\r
       if (*RowInfoArray == NULL) {\r
         Status = EFI_OUT_OF_RESOURCES;\r
         goto Exit;\r
       }\r
       CopyMem (*RowInfoArray, RowInfo, RowInfoSize);\r
+    } else {\r
+      *RowInfoArray = NULL;\r
     }\r
-    if (RowInfoArraySize != NULL) {\r
-      *RowInfoArraySize = RowIndex;\r
-    }\r
-\r
-  } else {\r
-    //\r
-    // Create a new bitmap and draw the string onto this image.\r
-    //\r
-    Image = AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));\r
-    if (Image == NULL) {\r
-      return EFI_OUT_OF_RESOURCES;\r
-    }\r
-    Image->Width  = 800;\r
-    Image->Height = 600;\r
-    Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height *sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
-    if (Image->Image.Bitmap == NULL) {\r
-      FreePool (Image);\r
-      return EFI_OUT_OF_RESOURCES;\r
-    }\r
-\r
-    //\r
-    // Other flags are not permitted when Blt is NULL.\r
-    //\r
-    Flags &= EFI_HII_OUT_FLAG_WRAP | EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_IGNORE_LINE_BREAK;\r
-    Status = HiiStringToImage (\r
-               This,\r
-               Flags,\r
-               String,\r
-               StringInfo,\r
-               &Image,\r
-               BltX,\r
-               BltY,\r
-               RowInfoArray,\r
-               RowInfoArraySize,\r
-               ColumnInfoArray\r
-               );\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
-\r
-    *Blt = Image;\r
+  }\r
+  if (RowInfoArraySize != NULL) {\r
+    *RowInfoArraySize = RowIndex;\r
   }\r
 \r
   Status = EFI_SUCCESS;\r
 \r
 Exit:\r
 \r
-  for (Index = 0; Index < MAX_STRING_LENGTH; Index++) {\r
+  for (Index = 0; Index < StrLength; Index++) {\r
     if (GlyphBuf[Index] != NULL) {\r
       FreePool (GlyphBuf[Index]);\r
     }\r
@@ -2097,6 +2315,7 @@ HiiStringIdToImage (
   EFI_STRING                          String;\r
   UINTN                               StringSize;\r
   UINTN                               FontLen;\r
+  UINTN                               NameSize;\r
   EFI_FONT_INFO                       *StringFontInfo;\r
   EFI_FONT_DISPLAY_INFO               *NewStringInfo;\r
   CHAR8                               TempSupportedLanguages;\r
@@ -2120,7 +2339,6 @@ HiiStringIdToImage (
   CurrentLanguage    = NULL;\r
   BestLanguage       = NULL;\r
   String             = NULL;\r
-  StringInfo         = NULL;\r
   StringFontInfo     = NULL;\r
   NewStringInfo      = NULL;\r
 \r
@@ -2162,7 +2380,7 @@ HiiStringIdToImage (
   if (Language == NULL) {\r
     Language = "";\r
   }\r
-  CurrentLanguage = GetEfiGlobalVariable (L"PlatformLang");\r
+  GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&CurrentLanguage, NULL);\r
   BestLanguage = GetBestLanguage (\r
                    SupportedLanguages,\r
                    FALSE,\r
@@ -2220,7 +2438,8 @@ HiiStringIdToImage (
   // StringFontInfo equals NULL means system default font attaches with the string block.\r
   //\r
   if (StringFontInfo != NULL && IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfo, NULL, NULL)) {\r
-    FontLen = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + StrSize (StringFontInfo->FontName);\r
+    NameSize = StrSize (StringFontInfo->FontName);\r
+    FontLen = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + NameSize;\r
     NewStringInfo = AllocateZeroPool (FontLen);\r
     if (NewStringInfo == NULL) {      \r
       Status = EFI_OUT_OF_RESOURCES;\r
@@ -2229,7 +2448,7 @@ HiiStringIdToImage (
     NewStringInfo->FontInfoMask       = EFI_FONT_INFO_SYS_FORE_COLOR | EFI_FONT_INFO_SYS_BACK_COLOR;\r
     NewStringInfo->FontInfo.FontStyle = StringFontInfo->FontStyle;\r
     NewStringInfo->FontInfo.FontSize  = StringFontInfo->FontSize;    \r
-    StrCpy (NewStringInfo->FontInfo.FontName, StringFontInfo->FontName);\r
+    StrCpyS (NewStringInfo->FontInfo.FontName, NameSize / sizeof (CHAR16), StringFontInfo->FontName);\r
   \r
     Status = HiiStringToImage (\r
                This, \r
@@ -2330,6 +2549,7 @@ HiiGetGlyph (
   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      Foreground;\r
   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      Background;\r
   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BltBuffer;\r
+  UINT16                             BaseLine;\r
 \r
   if (This == NULL || Blt == NULL || *Blt != NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -2368,10 +2588,12 @@ HiiGetGlyph (
     if (EFI_ERROR (Status)) {\r
       goto Exit;\r
     }\r
+    ASSERT (StringInfoOut != NULL);\r
     FontInfo   = &StringInfoOut->FontInfo;\r
     Foreground = StringInfoOut->ForegroundColor;\r
     Background = StringInfoOut->BackgroundColor;\r
   } else {\r
+    ASSERT (SystemDefault != NULL);\r
     Foreground = SystemDefault->ForegroundColor;\r
     Background = SystemDefault->BackgroundColor;\r
   }\r
@@ -2389,25 +2611,36 @@ HiiGetGlyph (
   Image->Width   = Cell.Width;\r
   Image->Height  = Cell.Height;\r
 \r
-  Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
-  if (Image->Image.Bitmap == NULL) {\r
-    FreePool (Image);\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto Exit;\r
-  }\r
+  if (Image->Width * Image->Height > 0) {\r
+    Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+    if (Image->Image.Bitmap == NULL) {\r
+      FreePool (Image);\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Exit;\r
+    }\r
 \r
-  BltBuffer = Image->Image.Bitmap;\r
-  GlyphToImage (\r
-    GlyphBuffer,\r
-    Foreground,\r
-    Background,\r
-    Image->Width,\r
-    Image->Height,\r
-    FALSE,\r
-    &Cell,\r
-    Attributes,\r
-    &BltBuffer\r
-    );\r
+    //\r
+    // Set BaseLine to the char height.\r
+    //\r
+    BaseLine  = (UINT16) (Cell.Height + Cell.OffsetY);\r
+    //\r
+    // Set BltBuffer to the position of Origin. \r
+    //\r
+    BltBuffer = Image->Image.Bitmap + (Cell.Height + Cell.OffsetY) * Image->Width - Cell.OffsetX;\r
+    GlyphToImage (\r
+      GlyphBuffer,\r
+      Foreground,\r
+      Background,\r
+      Image->Width,\r
+      BaseLine,\r
+      Cell.Width + Cell.OffsetX,\r
+      BaseLine - Cell.OffsetY,\r
+      FALSE,\r
+      &Cell,\r
+      Attributes,\r
+      &BltBuffer\r
+      );\r
+  }\r
 \r
   *Blt = Image;\r
   if (Baseline != NULL) {\r
@@ -2460,14 +2693,15 @@ Exit:
                                   with the  first font. On return, points to the\r
                                   returned font handle or points to NULL if there\r
                                   are no more matching fonts.\r
-  @param  StringInfoIn            Upon entry, points to the font to return\r
-                                  information about. \r
-                                  If NULL, then the information about the system default \r
-                                  font will be returned.\r
-  @param  StringInfoOut           Upon return, contains the matching font's\r
-                                  information.  If NULL, then no information is\r
-                                  returned. It's caller's responsibility to free\r
-                                  this buffer.\r
+  @param  StringInfoIn            Upon entry, points to the font to return information\r
+                                  about. If NULL, then the information about the system\r
+                                  default font will be returned.\r
+  @param  StringInfoOut           Upon return, contains the matching font's information.\r
+                                  If NULL, then no information is returned. This buffer\r
+                                  is allocated with a call to the Boot Service AllocatePool().\r
+                                  It is the caller's responsibility to call the Boot \r
+                                  Service FreePool() when the caller no longer requires\r
+                                  the contents of StringInfoOut.\r
   @param  String                  Points to the string which will be tested to\r
                                   determine  if all characters are available. If\r
                                   NULL, then any font  is acceptable.\r
@@ -2503,6 +2737,7 @@ HiiGetFontInfo (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  StringInfoOutLen = 0;\r
   FontInfo        = NULL;\r
   SystemDefault   = NULL;\r
   LocalFontHandle = NULL;\r
@@ -2598,7 +2833,7 @@ HiiGetFontInfo (
     InfoOut.BackgroundColor = SystemDefault->BackgroundColor;\r
   }\r
   \r
-\r
+  ASSERT (FontInfo != NULL);\r
   FontInfo->FontSize  = InfoOut.FontInfo.FontSize;\r
   FontInfo->FontStyle = InfoOut.FontInfo.FontStyle;\r
 \r