操作系统设计与实现:基于LoongArch架构
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.1.2 字符显示

在显示器驱动程序中,write_char函数(详见代码清单1.2)用于将指定的字符写入显存中指定的位置。write_char函数有3个参数,第1个参数为字符的ASCII值,第2个和第3个参数为字符显示位置的坐标。本节以显示字符“!”为例,分析write_char函数的处理过程,其中字符的显示位置为第2行第4列。

图1.1 MaQueOS显示参数

代码清单1.2 write_char函数

下面对代码清单1.2进行说明。

第13行中,如上节所述,每个字符对应一个8×16像素点阵的字模,“!”的字模如图1.2所示。其中,值为1的比特组成一个形状为!的图形。MaQueOS在显示器上支持显示的字符个数为95。这些可显示字符对应的字模存放在font.c文件的fonts数组中。如图1.2所示,每个字模需要16字节来表示,即在fonts数组中占用16项,因此,fonts数组中偏移为0的字模占用第0~15项,对应字符的ASCII值为32(空格),偏移为1的字模占用第16~31项,对应字符的ASCII值为33(“!”),以此类推,偏移为94的字模占用最后16项,对应字符的ASCII值为126(“~”)。

图1.2 字符“!”的字模

因为fonts数组中偏移为0的字模的对应字符的ASCII值为32,所以,为了获取字符的对应字模在fonts数组中的起始项(共16项),应先将字符的ASCII值减去32得到该字符的对应字模在fonts数组中的偏移,再乘以每个字模占用的字节数16,最终得到该字符的对应字模在fonts数组中的起始项。字符“!”的ASCII值为33,因此,对应字模在fonts数组中的偏移为1,再乘以每个字模占用字节数16,最终计算出该字模在fonts数组中的起始项为16。

第14行中,获取字符的起始像素在显存中的起始地址,计算过程如下:

1)计算出字符起始像素在显示器中的偏移量。如图1.1所示,因为一行字符占16行像素,所以第yy行字符前共有yy×16行像素。即,第yy行字符前像素的总数为yy×16×1280。又因为一列字符占8列像素,所以第xx列字符前共有xx×8列像素。若将字符“!”显示在显示器中的第2行第4列,因为第2行字符前像素的总数为2×16×1280=40960,并且在第2×16行像素中,第4列字符前像素的总数为4×8=32,所以字符“!”的起始像素在显示器上的偏移为40960+32=40992。

2)每个像素在显存中占4字节(NR_BYTE_PIX),其中前3字节分别代表B、G、R,决定了该像素的颜色。因此将步骤1中的计算结果乘以4,得到字符的起始像素在显存中的偏移。最后,将该偏移加上显存起始地址0x40000000(VRAM_BASE),得到字符的起始像素在显存中的起始地址。

第15~30行中,按行循环遍历字模,共遍历16字节。在第29行中,每行遍历结束后,需要重新计算字符的下一行像素的起始像素在显存中的起始地址。需要增加的字节数为(1280-8)×4,其中,1280-8表示显示器一行像素的总数(1280)减去字符一行像素的数量(8),4表示每个像素在显存中占用的字节数(结果为5088)。

对于第17~28行代码,在每行中,按列循环遍历字模,共遍历每个字节中的8位。其中,在第19~25行中,若字模中的当前位为1,则将对应像素在显存中的(B,G,R)对应的字节分别设置为(0,0,255),表示将该像素绘制为红色。在第26~27行中,若字模中的当前位为0,则直接跳过该位对应像素在显存中占用的4个字节。

如图1.2所示,当遍历至字符“!”对应字模的第0行第0列时,因为该位的值为0,所以不对像素进行绘制,直接跳过该位对应像素在显存中占用的4个字节。直至遍历到第2行第3列时,因为该位的值为1,所以将该位对应的像素绘制为红色。最终,当字模中的位全部遍历完成后,红色的字符“!”便显示在显示器上。