繪制系統(tǒng)內(nèi)核字體

我們已經(jīng)有了系統(tǒng)桌面,但還缺少一個(gè)重要因素,那就是字體摔竿,沒有字體就無法有效的傳遞信息面粮,因此,本節(jié)继低,我們看看熬苍,系統(tǒng)的字體是如何繪制的。

字體的繪制跟其他圖形一樣袁翁,都是通過將指定位置的像素點(diǎn)設(shè)置成給定顏色而形成的最終圖形柴底,如下圖:


image

我們看到,要繪制給定的字母梦裂,我們可以把一塊圖形區(qū)域先全部染成白色,然后在將某個(gè)位置的像素點(diǎn)的顏色設(shè)置成黑色盖淡,那么年柠,字體就顯示出來了。如果我們把字體的大小限定在一個(gè)8*16的長(zhǎng)方形區(qū)域褪迟,那么我們?cè)谶@個(gè)區(qū)域內(nèi)冗恨,將特定位置的像素點(diǎn)設(shè)置成黑色,其他點(diǎn)設(shè)置成白色味赃,那么我們就可以得到一個(gè)白底黑色的字體:


這里寫圖片描述

依據(jù)上圖掀抹,如果我們把8*16區(qū)域當(dāng)做一個(gè)二維數(shù)組,白色的像素我們用0表示心俗,黑色像素我們用1表示傲武,那么上圖的字符A, 最頂層的一行全是白色,所以用8個(gè)0表示城榛,第二行揪利,8個(gè)像素中,中間兩個(gè)像素設(shè)置成黑色狠持,于是對(duì)應(yīng)的二進(jìn)制數(shù)就是000 11 000, 對(duì)應(yīng)的16進(jìn)制數(shù)就是0x18, 依次類推疟位,這樣對(duì)整個(gè)字符A, 我們就有可以設(shè)置一個(gè)對(duì)應(yīng)的數(shù)組:

static char fontA[16] = {
0x00, 0x18, 0x18, 0x18,0x18,0x24,0x24,0x24,
0x24, 0x7e, 0x42, 0x42,0x42, 0xe7, 0x00, 0x00
};

拿到字體數(shù)組后,繪制時(shí)喘垂,把數(shù)組中的每一個(gè)數(shù)值取出來甜刻,看該數(shù)值的二進(jìn)制形式中,哪一位設(shè)置成1正勒,那么就給對(duì)應(yīng)的像素賦予黑色得院,如果設(shè)置成0,就給對(duì)應(yīng)的像素設(shè)置成白色章贞,代碼如下:

void showFont8(char *vram, int xsize, int x, int y, char c, char* font) {
    int i;
    char d;

    for (i = 0; i < 16; i++) {
        d = font[i]; 
        if ((d & 0x80) != 0) {vram[(y+i)*xsize + x + 0] = c;}
        if ((d & 0x40) != 0) {vram[(y+i)*xsize + x + 1] = c;}
        if ((d & 0x20) != 0) {vram[(y+i)*xsize + x + 2] = c;}
        if ((d & 0x10) != 0) {vram[(y+i)*xsize + x + 3] = c;}
        if ((d & 0x08) != 0) {vram[(y+i)*xsize + x + 4] = c;}
        if ((d & 0x04) != 0) {vram[(y+i)*xsize + x + 5] = c;}
        if ((d & 0x02) != 0) {vram[(y+i)*xsize + x + 6] = c;}
        if ((d & 0x01) != 0) {vram[(y+i)*xsize + x + 7] = c;}
    }

大家注意尿招,上面的代碼為什么要乘以 xsize 呢,xsize對(duì)應(yīng)屏幕的寬度,相隔一行的同一列上的像素點(diǎn)就谜,他們之間的距離正好是屏幕一行的寬度怪蔑,如果把屏幕看成是一個(gè)320*200 的二維數(shù)組screen[320][200], 那么點(diǎn)screen[1][1]和點(diǎn)screen[2][1] 之間的距離,就等于320.

在write_vga_desktop.c的主函數(shù)中丧荐,在for(;;)死循環(huán)前加入一句:
showFont8(vram, xsize, 20, 20, COL8_FFFFFF, fontA);

將上面的代碼結(jié)合進(jìn)write_vga_desktop.c缆瓣,編譯反編譯,結(jié)合到內(nèi)核后虹统,運(yùn)行效果如下:


這里寫圖片描述

我們看到弓坞,一個(gè)"A"字體就出現(xiàn)在屏幕做上方了。

####****增加更多字體
當(dāng)前我們只繪制了一個(gè)字符车荔,要繪制一系列字符的話渡冻,就需要相應(yīng)的數(shù)組,我們的做法是忧便,使用設(shè)計(jì)好的字體文件族吻,將字體文件轉(zhuǎn)換為二進(jìn)制數(shù)據(jù),先向大家展示這個(gè)字體文件的內(nèi)容樣式:

這里寫圖片描述

字體文件就是如上圖所示珠增,對(duì)每一個(gè)字符樣式進(jìn)行進(jìn)行設(shè)計(jì)超歌,一個(gè)“."就代表0,*代表1蒂教,同時(shí)巍举,我們會(huì)有一個(gè)附件工具程序叫makeFont,該程序?qū)⒋俗煮w文件讀入,然后轉(zhuǎn)換成對(duì)應(yīng)的16進(jìn)制數(shù)據(jù)凝垛。如下圖是makeFont工程的目錄懊悯,該目錄下有字體文件font.txt:


這里寫圖片描述

啟動(dòng)makeFont程序,并運(yùn)行之梦皮,完成后定枷,該工程目錄下會(huì)多出一個(gè)二進(jìn)制文件:fontData.inc:


這里寫圖片描述

該二進(jìn)制文件的局部?jī)?nèi)容如下:
systemFont:
db 00H ,00H ,00H ,00H ,00H ,00H ,00H ,00H ,00H ,00H ,00H ,00H ,00H ,00H ,00H ,00H
db 00H ,00H ,070H ,088H ,04H ,054H ,054H ,04H ,04H ,054H ,024H ,088H ,070H ,00H ,00H ,00H
db 00H ,00H ,070H ,0f8H ,0fcH ,0acH ,0acH ,0fcH ,0fcH ,0acH ,0dcH ,0f8H ,070H ,00H ,00H ,00H
db 00H ,00H ,00H ,00H ,0d8H ,0fcH ,0fcH ,0fcH ,0f8H ,070H ,020H ,00H ,00H ,00H ,00H ,00H
db 00H ,00H ,00H ,00H ,020H ,070H ,0f8H ,0fcH ,0f8H ,070H ,020H ,00H ,00H ,00H ,00H ,00H
db 00H ,00H ,00H ,00H ,020H ,070H ,0a8H ,0fcH ,0a8H ,020H ,070H ,00H ,00H ,00H ,00H ,00H
db 00H ,00H ,00H ,00H ,020H ,070H ,0f8H ,0fcH ,0acH ,020H ,070H ,00H ,00H ,00H ,00H ,00H
db 00H ,00H ,00H ,00H ,00H ,00H ,030H ,078H ,078H ,030H ,00H ,00H ,00H ,00H ,00H ,00H

makeFont程序的邏輯簡(jiǎn)單,只是把一行一行的文件讀入届氢,把一行中的"."當(dāng)做0欠窒,"*"當(dāng)做1,然后轉(zhuǎn)換成16進(jìn)制數(shù)寫入文件fontData.inc即可退子。

有了上面的字體二進(jìn)制文件后岖妄,我們直接將它include到內(nèi)核文件kernel.asm里,然后在我們的C語言程序中直接使用即可寂祥,在C語言中荐虐,我們先聲明一個(gè)外部變量數(shù)組:

extern char systemFont[16]

要想繪制某個(gè)字符,例如字符B,我們可以使用以下調(diào)用

showFont8(vram, xsize, 20, 20, COL8_FFFFFF, systemFont+'A'*16);

接下來我們給出顯示字符A,B,C,1,2,3的C語言部分代碼:

extern char systemFont[16];

void showFont8(char *vram, int xsize, int x, int y, char c, char* font);

void CMain(void) {
    struct BOOTINFO bootInfo;
    initBootInfo(&bootInfo);
    char*vram = bootInfo.vgaRam;
    int xsize = bootInfo.screenX, ysize = bootInfo.screenY;

    init_palette();
    
    boxfill8(vram, xsize, COL8_008484, 0, 0, xsize-1, ysize-29);
    boxfill8(vram, xsize, COL8_C6C6C6, 0, ysize-28, xsize-1, ysize-28);
    boxfill8(vram, xsize, COL8_FFFFFF, 0, ysize-27, xsize-1, ysize-27);
    boxfill8(vram, xsize, COL8_C6C6C6, 0, ysize-26, xsize-1, ysize-1);
    
    boxfill8(vram, xsize, COL8_FFFFFF, 3, ysize-24, 59, ysize-24);
    boxfill8(vram, xsize, COL8_FFFFFF, 2, ysize-24, 2, ysize-4);
    boxfill8(vram, xsize, COL8_848484, 3, ysize-4,  59, ysize-4);
    boxfill8(vram, xsize, COL8_848484, 59, ysize-23, 59, ysize-5);
    boxfill8(vram, xsize, COL8_000000, 2, ysize-3, 59, ysize-3);
    boxfill8(vram, xsize, COL8_000000, 60, ysize-24, 60, ysize-3);

    boxfill8(vram, xsize, COL8_848484, xsize-47, ysize-24, xsize-4, ysize-24);
    boxfill8(vram, xsize, COL8_848484, xsize-47, ysize-23, xsize-47, ysize-4);
    boxfill8(vram, xsize, COL8_FFFFFF, xsize-47, ysize-3, xsize-4, ysize-3);
    boxfill8(vram, xsize, COL8_FFFFFF, xsize-3,  ysize-24, xsize-3, ysize-3);
  
    showFont8(vram, xsize, 8, 8, COL8_FFFFFF, systemFont + 'A'*16);
    showFont8(vram, xsize, 16, 8, COL8_FFFFFF, systemFont + 'B'*16);
    showFont8(vram, xsize, 24, 8, COL8_FFFFFF, systemFont + 'C'*16);
    showFont8(vram, xsize, 32, 8, COL8_FFFFFF, systemFont + '1'*16);
    showFont8(vram, xsize, 48, 8, COL8_FFFFFF, systemFont + '2'*16);
    showFont8(vram, xsize, 64, 8, COL8_FFFFFF, systemFont + '3'*16);

    for(;;) {
       io_hlt();
    }

}

將代碼編譯并結(jié)合如內(nèi)核后丸凭,運(yùn)行效果如下:


這里寫圖片描述

字體C的顯示好像有點(diǎn)問題福扬,后面我會(huì)查查代碼腕铸,并及時(shí)更新。

####****顯示字符串
我們能夠顯示單個(gè)字符铛碑,只要稍加加工狠裹,我們就可以顯示一個(gè)字符串,顯示字符串只不過是將字符連在一起顯示罷了汽烦,具體代碼如下:

void showString(char* vram, int xsize, int x, int y, char color, unsigned char *s ) {
    for (; *s != 0x00; s++) {
       showFont8(vram, xsize, x, y,color, systemFont+ *s * 16);
       x += 8;
    }
}

編譯結(jié)合進(jìn)內(nèi)核后涛菠,運(yùn)行效果如下:


這里寫圖片描述

本文的所有代碼均可在網(wǎng)易云課堂下載:
Linux kernel Hacker, 從零構(gòu)建自己的內(nèi)核

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市撇吞,隨后出現(xiàn)的幾起案子俗冻,更是在濱河造成了極大的恐慌谷羞,老刑警劉巖屋剑,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異啦租,居然都是意外死亡煮岁,警方通過查閱死者的電腦和手機(jī)讥蔽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來人乓,“玉大人勤篮,你說我怎么就攤上這事都毒∩#” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵账劲,是天一觀的道長(zhǎng)戳护。 經(jīng)常有香客問我,道長(zhǎng)瀑焦,這世上最難降的妖魔是什么腌且? 我笑而不...
    開封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮榛瓮,結(jié)果婚禮上铺董,老公的妹妹穿的比我還像新娘。我一直安慰自己禀晓,他們只是感情好精续,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著粹懒,像睡著了一般重付。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上凫乖,一...
    開封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天确垫,我揣著相機(jī)與錄音弓颈,去河邊找鬼。 笑死删掀,一個(gè)胖子當(dāng)著我的面吹牛翔冀,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播爬迟,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼橘蜜,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了付呕?” 一聲冷哼從身側(cè)響起计福,我...
    開封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎徽职,沒想到半個(gè)月后象颖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡姆钉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年说订,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片潮瓶。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡陶冷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出毯辅,到底是詐尸還是另有隱情埂伦,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布思恐,位于F島的核電站沾谜,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏胀莹。R本人自食惡果不足惜基跑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望描焰。 院中可真熱鬧媳否,春花似錦、人聲如沸荆秦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽萄凤。三九已至室抽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間靡努,已是汗流浹背坪圾。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工晓折, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人兽泄。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓漓概,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親病梢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子胃珍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • ¥開啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個(gè)線程,因...
    小菜c閱讀 6,367評(píng)論 0 17
  • Ubuntu的發(fā)音 Ubuntu填抬,源于非洲祖魯人和科薩人的語言,發(fā)作 oo-boon-too 的音隧期。了解發(fā)音是有意...
    螢火蟲de夢(mèng)閱讀 99,204評(píng)論 9 467
  • 我今天為未來做的準(zhǔn)備:1.用心上班飒责,獲得的工資給我?guī)斫疱X,我很高興自己勞有所獲仆潮。很感謝各位領(lǐng)導(dǎo)和同事對(duì)我照顧宏蛉,讓...
    四葉草_3ddd閱讀 288評(píng)論 0 2
  • “風(fēng)雪之中,閣下何人性置?” 文/棲遲 目錄 上一章 洛九兒飛奔到三十里外的赤山破廟里拾并,整個(gè)人凍得直哆嗦。 廟外已下起...
    顧棲遲閱讀 215評(píng)論 0 2