问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

如何改造 Linux 虚拟终端显示文字

发布网友 发布时间:2022-04-21 21:26

我来回答

1个回答

热心网友 时间:2023-12-13 19:22

  要想控制台能支持汉字显示,需要解决 3 个问题:

  必须使用 UTF-8 模式 ( 默认 vc->utf=1 即可 )

  虚拟控制台的 vc_screenbuf 必须修改以为 glyph 提供至少 16bit 的空间。

  图形控制台需要 vc_font包含更多的字符,不只是 255 个,并提供代码绘制双倍宽度的中文字形,字体中的字符按照 UNICODE
排列,这样 glyph 就是字符的 UNICODE 编码。

  修改虚拟控制台

  一开始,我的打算是 vc_screenbuf 修改为 unsigned long long* 类型,32bit 给字符属性,分别表示 16bit
终端前景色和背景色。glyph 则拥有 31bit 的空间 , 因为汉字的宽度为双倍的英文字母 ,其中 1 bit 用来表示双字符宽度。比如 '我' 会表达为
两个 '我',第二个'我'的最高位为 1:绘制任何字形的时候,只绘制字形的左半部分;如果发现最高位为 1
则绘制字体位图中的右半部分。这样同样的绘制代码可以适应英文字母和汉字。写入 vc_screenbuf 的时候,
如果是双倍宽度的字符,需要同时写入两份,第二份的最高位置 1 就可以。但是 vc_screenbuf
的格式已经被到处假定为每字符两个字节。如此修改导致牵一发动全身。许多艰涩难懂的代码都依赖 vc_screenbuf 是
每字符两个字节的设定,直接修改定义后,光是编译器能直接检测出来的就有百余个地方需要修改,还有更多的逻辑并不能被编译器检测出来。如此修改的后果就是会出现许多隐晦的错误,非常难于调式。挣扎后,为最终选择了另一条道路
:

  为汉字重新分配一块 vc_unicode_screenbuf

  vc_unicode_screenbuf 紧挨着 vc_screenbuf , 事实上 vc_screenbuf
在分配空间的时候,多分配了一倍的空间,多分配的空间充作 vc_unicode_screenbuf,因此 struct vc_data 里并没有添加
vc_unicode_screenbuf 成员。 vc_unicode_screenbuf 同样为每字符 2 个字节,并不包含字符属性,所以 2
个字节如数用来保存 glyph。vc_screenbuf 格式未变,所以 vgacon 不需要修改,这就减少了大量的工作量。向 vc_screenbuf
写入字符的时候,同时写入一份到 vc_unicode_screenbuf 。如果是汉字,由于其 glyph 大于 254 , 所以 vc_screenbuf
的那两个字符 ( 汉字双倍宽度 ) 实际写入的是 0xff 和 0xfe ( 故而上文提到是 glyph 大于 254 的字符 ,0xfe 被保留它用了
)。0xff 表示该字符的 glyph 要到 vc_unicode_screenbuf 提取,然后绘制左半部分;0xfe 表示该字符的 glyph 要到
vc_unicode_screenbuf 提取,然后绘制右半部分。对于 glyph 大于 254 但是又不是双倍宽度的字符,就不需要 0xfe
作陪了。比如屏幕上显示的文字是黑底白字的 “牛 B” , vc_screenbuf 的内容就是 “0x00ff, 0x0ffe, 0x0f42 ” ,
vc_unicode_screenbuf 的内容则是 “牛 , 牛 ,b”
。这是因为一个汉字为两倍的英文字母宽度。在屏幕文字缓冲区上也必须占用两个字符的位置。并且必须有一种机制能知道应该绘制左半部分和右半部分,我使用的就是 0xff
和 0xfe。

  修改图形控制台绘制代码

  要修改的地方只有 3 个。

  struct console_font 添加 charcount 成员。将主线内核的字体设置为 charcount = 255。 主线内核带的字体都是
255 个 glyph 的,所以没有添加字符个数的必要。不过我们即将要添加的字体会有数万字符。

  添加一个新的字体,复盖 UNICODE BMP 基本区域的所有符号。

  修改字符绘制代码,添加 vc_unicode_screenbuf 的支持。

  字符绘制代码的修改比较繁琐,代码分布在 drivers/video/console/ 下的多个文件中。fbcon_putc(s) 由由
vc->vc_sw->con_putc(s) 调用, fbcon_putc(s) 转而调用分散于 drivers/video/console/
的多个 puts 实现。因为终端要支持 console_rotate , decoration , timing , 故而每种模式下的绘制实现都是不同的。我拿
drivers/video/console/bitblt.c 最常用的不倾斜、不加装饰等的终端模式为例来讲解绘图部分的修改。由于中文字体为 16x16
点阵,是对齐的字体,故而其绘制代码为 bit_putcs_aligned() 原先的代码以 glyph 为下标到 vc->vc_font->data
获得字体数据,然后调用 fb_pad_aligned_buffer 执行块拷贝操作。我的修改很简单,原来获得字体数据的代码修改后放入 font_bits()
辅助函数。 在 font_bits 里,要判断 glyph 是否为 0xff 或者 0xfe, 如果不是,使用 glyph 为下标获得字体的左半部分后并返回。
如果是,则从 vc_unicode_screenbuf 获得真正的 glyph 数值,然后再依据现有的 glyph 是 0xff 还是 0xfe
去获得字体的右半部分还是左半部分返回。font_bits 获得字体数据后执行 fb_pad_aligned_buffer 块拷贝。需要修改的地方还有
drivers/video/console/fbcon_ccw.c fbcon_cw.c fbcon_ub.c 。依原理进行修改即可。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
逃跑吧!少年 逃跑吧少年有哪些彩蛋? 逃跑吧!少年 逃跑吧少年失忆者怎么玩? 逃跑吧!少年 逃跑吧少年失忆者动作举荧光棒在哪获得? 考驾照周六有考试吗 烟台星期六可以考驾照吗 考驾照的站岗星期六星期天可以站吗 如何看待张艺谋导演的电影《满江红》被指“辱女”? 满江红艺伎叫什么 月经不来尿尿前好像憋着似的一上厕所就尿的不多 怎么学英语歌?我学不会? 短期交强险可以买吗 车辆交强险可以买短期吗 交强险可以买三个月吗 交强险临时保险最短买几天 什么情况可以投保短期交强险 交强险交三个月行吗 交强险允许出具短期保单 为什么在电脑上下载的视频在我的电脑上打不开? 交强险可以投短期保险 电脑上的视频下载后打不开 交强险可以交三个月吗 电脑上下载视频怎么打不开 交强险投保的期间是怎样的,我可不可以投保短期交... 电脑上视频文件打不开怎么回事 交强险可以保短期吗 电脑视频打不开怎么办? 二手车交强险可以买短期的吗? 我的电脑里的视频打不开怎么回事啊 什么情况下可以购买短期车险? 为什么我的笔记本电脑视频打不开 linux下tty纯文本终端的字体大小是否可以不借助任... 怎样调整Linux超级终端中字体大小 linux terminal字体变大的快捷键 linux怎么改变终端的字体颜色 Linux下VIM字体怎么设置? 佳能相机网格线如何取消 佳能相机网格线有偏差怎么办? 索尼sonyoc57相机中的网格线是什么意思 一两万的光子床实为取暖器,为何总会有人相信这种“... 光子床真的有效果吗? 请问有人躺过光子能量床吗? 如何用ppt做工作汇报 工作汇报PPT怎么做? 如何制作汇报型PPT 梦福康光子床真实价格 光子床的危害 如何制作ppt报告 神州泰康光子床好不好用?价格怎么样? 学习汇报的ppt怎么做 ppt如何制作图表,要做一个汇报的ppt,不知道该怎么做