uefi 字体缺失,显示不正确

本文介绍UEFI环境下汉字显示原理及实现方法,包括通过Unicode码映射到字库的具体过程,并提供了一个生成对应Unicode码字库的示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于graphic,uefi显示汉字时会有一个unicode码,然后由unicode码找到对应的字库,类似下面的

 {0x7400,0x00,{0x00,0x00,0x00,0x00,0xf8,0x31,0x33,0x3f,0x36,0x30,0x7b,0x30,0x30,0x33,0x3a,0xfa,0x83,0x02,0x00},{0x00,0x00,0x00,0x00,0xe0,0xf0,0xb8,0x5e,0xec,0x40,0xf8,0x18,0x30,0xfc,0x0c,0x0c,0xfc,0x0c,0x00},{0x00,0x00,0x00}},

这个unicode码就是0x7400,后面跟着的是一个类似下面的东西转换过来的。

 

一个16*19位的图片转换过来的,0是不显示的,1是显示的。

一般,汉字是宽体字,16*19.英文字符是窄体字 8*19

2张字体t图片来自:如何让UEFI BIOS支持汉字显示:汉字编码与显示实践 - 知乎

 


VOID
EFIAPI
RegisterFontPackage (
  IN  EFI_EVENT       Event,
  IN  VOID            *Context
  )
{
  EFI_STATUS                           Status;
  EFI_HII_SIMPLE_FONT_PACKAGE_HDR      *SimplifiedFont;
  UINT32                               PackageLength;
  UINT8                                *Package;
  UINT8                                *Location;
  EFI_HII_DATABASE_PROTOCOL            *HiiDatabase;
  EFI_HII_HANDLE              mHiiHandle;

  //
  // Locate HII Database Protocol
  //
  Status = gBS->LocateProtocol (
                  &gEfiHiiDatabaseProtocolGuid,
                  NULL,
                  (VOID **) &HiiDatabase
                  );
  if (EFI_ERROR (Status)) {
    return;
  }

  //
  // Add 4 bytes to the header for entire length for HiiAddPackages use only.
  //
  //    +--------------------------------+ <-- Package
  //    |                                |
  //    |    PackageLength(4 bytes)      |
  //    |                                |
  //    |--------------------------------| <-- SimplifiedFont
  //    |                                |
  //    |EFI_HII_SIMPLE_FONT_PACKAGE_HDR |
  //    |                                |
  //    |--------------------------------| <-- Location
  //    |                                |
  //    |     gCnFontWideGlyphData       |
  //    |                                |
  //    +--------------------------------+

  PackageLength   = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR) + mWideFontSize + 4;
  Package = AllocateZeroPool (PackageLength);
  ASSERT (Package != NULL);

  WriteUnaligned32((UINT32 *) Package,PackageLength);
  SimplifiedFont = (EFI_HII_SIMPLE_FONT_PACKAGE_HDR *) (Package + 4);
  SimplifiedFont->Header.Length        = (UINT32) (PackageLength - 4);
  SimplifiedFont->Header.Type          = EFI_HII_PACKAGE_SIMPLE_FONTS;
  SimplifiedFont->NumberOfNarrowGlyphs = 0;
  SimplifiedFont->NumberOfWideGlyphs   = (UINT16) (mWideFontSize / sizeof (EFI_WIDE_GLYPH));

  Location = (UINT8 *) (&SimplifiedFont->NumberOfWideGlyphs + 1);
  CopyMem (Location, gCnFontWideGlyphData, mWideFontSize);

  //
  // Add this simplified font package to a package list then install it.
  //
  mHiiHandle = HiiAddPackages (
                 &gEfiCallerIdGuid,
                 NULL,
                 Package,
                 NULL
                 );
  ASSERT (mHiiHandle != NULL);
  FreePool (Package);
}

后面系统会通过RegisterFontPackage  函数中的HiiAddPackages  注册字体库,这样就可以通过unicode码来获取对应的字库文件。

有些厂商的字库文件可能会有缺失部分unicode码,因此,需要手动生成对应的字库文件。

<html>
   <head>
   </head>
   <body>
     Text:
     <canvas id="a" width="32" height="32"></canvas> //画布大小 单位像素
     <script type="text/javascript">
       var a_canvas = document.getElementById("a");
       var context = a_canvas.getContext("2d");
       const FW = 16;                                                              //宽度 单位像素
       const FH = 19;                                                              //高度, 单位像素
       context.strokeRect(10,  10, FW, FH);
       context.font = "bold 15px times new roman"      //设置想要的字体,与css定义相同,不支持的字体会使用相近的
       context.fillstyle='#00f';                   //画布初始化
       var fontstr="{<BR>";
       //for(i=0x4e00; i< 0x4fa5;i++){ 
       function formatHH(x){
         var l = x.length;
         var s = x;
         if (l == 1)
           s = "0" + x;
         return s;
       }
       for(i=0x7400; i< 0x7401;i++){//要处理的unicode16 编码的范围,汉子0x4e00到0x9f5
         context.clearRect(10,  10, FW, FH);
         context.fillText(String.fromCharCode(i), 10, 10+FW); //写字符到画布
         var bitmapimg = context.getImageData(10,10, FW,FH); //读画布位图
         //var bitmapimg = context.getImageData(0,0, 32,32);
         var bitmap = bitmapimg.data;
         //document.write(bitmap.length+"<BR>");
         //for(var b = 0; b< bitmap.length; b++)
         //   document.write(" " + bitmap[b] );
                //将表述字符的画布位图转化为数据结构
           var left = " ";
           var right = " ";
         for( row =0;row <19; row++){
           var a = 0;
           for(col =0; col <8; col ++){
             if(bitmap[row * 16 *4 + col*4 +3] >10)//判断透明度的值,误差就是这里产生的
               a = (a<<1) | 1;
             else
               a = a<< 1
           }
           left = left + "0x" + formatHH(a.toString(16)) ;
           if(row <18) left = left + ",";
           a = 0;
           for(;col<16; col++){
             if(bitmap[row * 16 *4 + col*4+3] >10)
               a = (a<<1) | 1;
             else
               a = a<< 1;

           }
           right = right + "0x" + formatHH(a.toString(16)) ; 
           if(row <18) right= right+ ",";
         }
         fontstr = fontstr + "{ 0x"+ i.toString(16) + ", 0x00, " + "{" +  left +"}, {" + right +"}, {0x00,0x00,0x00} },"+ "<BR>";
       }
fontstr = fontstr + "{ 0x00, 0x00, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} <BR> };"
document.write(fontstr);
</script>
   </body>
</html>

可使用上面的html生成对应的unicdoe码,字库。

其中的for(i=0x7400; i< 0x7401;i++){//要处理的unicode16 编码的范围,汉子0x4e00到0x9f5

用来控制要生成的范围,该代码来自:(等我找一下)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值