UEFI开发探索17 – 使用HII显示汉字2

本篇博客的关键字:SimpleFont。

我始终在思考如何在UEFI Shell下显示汉字。上一篇中,参考书中的例子,基本了解了字符串资源是怎么组织的。当在TestString函数中,把参数Language改为”zh-Hans”,什么也没有显示。

看来还是缺少相应的字库。

UEFI下提供了SimpleFont和Font字体,前一个相对简单些,我先拿这个开刀。我参考的例子是《UEFI原理与编程》的\GUIbasics\font\SimpleFont,这个例子直接编译没有成功。我也没有去找原因,还是老办法,把它的例程移植到我自己的程序中来。

1 SimpleFont格式

SimpleFont有两种字体格式,窄字符和宽字符,在书中描述得很清楚。TianoCore的模拟环境中,也使用了SimpleFont的字库。

图1 SimpleFont结构体,摘自EfiHii.h

SimpleFont包中的字符数据以数组的形式附在结构体后面,看代码可以很容易了解:

图2 SimpleFont包的初始化(摘自本篇博客代码Luo2.c Line697–Line710)

2 生成字体文件

字体文件的生成,一般都需要自己写个小工具来提取。比如我之前的汉字显示方法,需要从字库中将所需要的字模一个个提取出来,形成符合自己要求的结构体文件。

书中提供了使用JavaScript提取字体数据的方法,非常方便。可以去读读本篇博客代码文件夹中的createdata.html(特别声明:此文件来源于《UEFI原理与编程》,版权属于原作者),将字符渲染到canvas中,分析canvas,生成EFI_WIDE_GLYPH格式的数据。其处理流程为:

  1. 建立画布,取得画布上下文context;
  2. 依次处理Unicode16编码从0x4E00到0x9FA5的每一个字符;
  3. 将字符写到context区域;
  4. 从context区域取出16×19位图;
  5. 将该位图转化为EFI_WIDE_GLYPH格式。

我对JavaScript不熟悉。从网上查找的资料,canvas只有Html5才支持,我是在win10的chrome 74.0.3729.169(正式版本) 中运行成功的。之前在winxp下的IE中,无法成功。看来是版本太老,不支持Html5。

生成的字库文件有4M多,把所有汉字都包含进去了。实际使用中不大可能需要这么多汉字,比如Oprom的开发,ROM空间只有几十K,无论如何也塞不进去。

最好的办法是写个程序,分析*.uni文件,看需要用到哪些汉字,再提取相应的字模,生成项目所需要的代码文件。

不过目前是在UEFI Shell下运行代码,程序空间不是问题,不需要做到这步,有空的时候写吧。

3 注册字体文件

准备工作完成后,最后一步是在程序中注册字体文件。类似上一篇博客中注册字符串,用HiiAddPackages()将字体包注册到HII数据库中。

这步比较简单,对我来说,只是将书中的CreatesimpleFontPkg()移植到我的代码中。

有几个地方需要修改:

  1. 添加头文件<Library/MemoryAllocationLib.h>,函数中用到了AllocateZeroPool()和FreePool();
  2. 函数中return -1修改为returun EFI_NOT_FOUND。函数返回值是EFI_STATUS,应该是UINT型,作者用了-1来返回,不知道是怎么回事。Return -1在我的程序中编译是无法通过的。

4 编译测试

将TestString()中设定的Language参数改为”zh-Hans”,准备测试UEFI Shell下的汉字显示。编译,运行:

图3 程序在TianoCore模拟环境中的运行结果

成功!给自己一万个 赞!

也就是说,之前猜想的运行逻辑没有错。当注册了字体文件后,字符串通过Unicode编码,在Hii数据库中寻找字模,找到后即可显示。

新的问题又来了,有没有办法在UEFI Shell中显示彩色的文字?(图中显示盘符用的是亮黄色的字符)

百度云链接:https://pan.baidu.com/s/1gccSosw8_UAGTI5gZPnLCA
提取码:dx23
代码在 10 HiiShellPrint-Chinese 下。

51 total views, 1 views today

发表评论

电子邮件地址不会被公开。 必填项已用*标注