linux点阵ascii像素字体,点阵字体显示系列之一:ASCII码字库的显示 | 迟思堂工作室...
起因:
早在閱讀tslib源代碼時就注意到里面有font_8x8.c和font_8x16.c兩個文件(后來才得知,它們來自Linux內核,具體目錄是./drivers/video/console),它們包含了在屏幕上顯示所需的所有字符(當然,是可打印字符),由此也看了一下tslib顯示字符的代碼。對將來在觸摸屏上顯示漢字有所幫助,——這是后話,暫且按下不提。
上面所說的字符當然是ASCII碼了,這種編碼學過計算機的人可能會很熟悉,就不多講了。本文所述者,就是通過ASCII碼字庫文件(網(wǎng)上有下載)和上面提到的其中之一的文件在終端上顯示ASCII字符。這也為研究漢字顯示打下基礎(此為假話,寫文章及做作所需也,實際上本文作者是先研究漢字顯示再研究ASCII碼顯示的,勿模仿,切切)。
本文中使用的字庫是8×16,每個字符占用內存空間為16字節(jié)(后面不再提及),文中顯示字符所做工作有下面幾步(顯示漢字也差不多,當然,這又是后話 ):
1、打開字庫文件(似乎是廢話);
2、計算出要打印的字符在字庫文件中的偏移量(亦即網(wǎng)上所說的“尋址”);
3、將這個偏移地址的數(shù)據(jù)(16字節(jié))讀取緩沖區(qū)中;
4、顯示這個緩沖區(qū),為1者打印,為0者留空。(由于是在終端上顯示,因此,可以使用如“#”、“*”等字符代替。)
先說說如何找到某個字符在字庫文件中的偏移量。字庫里的字符排序是符合ASCII碼順序的,而每個字符占16字節(jié),因此,將要打印的字符與16相乘,便得到這個字符在字庫中的位置了,這個位置之后的16個字節(jié)的數(shù)據(jù),就是這個字符了。比如大寫字母“A”,十六進制是0x41(“A”還是十進制的65、八進制的101,其實都是一回事),它與0x10(十進制的16)相乘,得到0x410(計算機中使用十六進制十分方便,對于某些試題要求計算出某地址的十進制,我表示不理解,既不直觀,又不方便,還容易出錯)。使用十六進制編輯器(用UE相信會更方便些)查看這個偏移量,會發(fā)現(xiàn)有如下數(shù)據(jù):
$ hexdump -C ../HZK/ASC16 | grep 41000000410? 00 00 10 38 6c c6 c6 fe? c6 c6 c6 c6 00 00 00 00? |…8l………..|
所謂的字庫,里面就是一些二進制數(shù)據(jù)。我們看看上面得到“A”的16個字節(jié)數(shù)據(jù)顯示效果是怎樣的。將上面的十六進制數(shù)據(jù)按二進制輸出,一個字節(jié)一行,共占16行,如下:
0000000000000000
00010000
00111000
01101100
11000110
11000110
11111110
11000110
11000110
11000110
11000110
00000000
00000000
00000000
00000000
不直觀,將出現(xiàn)0的地方留空,則變成如下形狀(受網(wǎng)頁影響,為美觀起見進行調整,雖非實際中二進制所示,但形狀是一致的):
1
111
11? 11
11????? 11
11????? 11
1111111
11????? 11
11????? 11
11????? 11
11????? 11
上面的便是傳說中的“A”了。
下面就用代碼讀取字庫信息,并顯示出來。完整代碼如下:
/***************************************************源代碼文件編碼:ANSI
測試環(huán)境編碼:zh_CN.UTF-8、zh_CN.gd2312
* ************************************************/
#include#include
#include
#include
#include
#include
#include
#include
#ifdef?DEBUG
#define?debug(fmt,?…)?printf(fmt,?#__VA_ARGS__)
#else
#define?debug(fmt,?…)
#endif
void?display_font_ascii(char?*asc)
{
int?i,?j;
debug(“=================n”);
for(i=0;i<16;i++)
{
for(j=0;j<8;j++)
{
/*?逐位相與,為1者打印“*”,否則打印空格?*/
if(asc[i]?&?(0x80>>j))
printf(“*”);
else
printf(” “);
}
printf(“n”);
}
debug(“=================n”);
}
int?main()
{
int?i;
unsigned?char?*p;
unsigned?char?asciicode[]?=?“Ab”;
unsigned?long?offset;
FILE?*asc;
char?ascii[16];
if((asc=fopen(“ASC16″,“rb”))==NULL)
{
perror(“Can’t Open ASC16″);
exit(0);
}
/*?ASCII字庫文件?*/
for?(i?=?0;?i?
{
debug(“%c %xn”,?asciicode[i],?asciicode[i]); /*?打印數(shù)值?*/
offset?=?asciicode[i]*16;
debug(“offset: %xn”,?offset); /*?打印偏移量?*/
fseek(asc,offset,SEEK_SET);
fread(ascii,16,1,asc);????????????? /*?讀取16字節(jié)?*/
display_font_ascii(ascii);??????? /*?顯示?*/
}
fclose(asc);
return?0;
}
由于是示意性代碼,不必糾結于代碼優(yōu)化、代碼風格等等問題。效果(同樣進行了調整)如下:
$ ./a.out*
***
**? **
**????? **
**????? **
*******
**????? **
**????? **
**????? **
**????? **
***
**
**
****
**? **
**??? **
**??? **
**??? **
**??? **
*****
還有另一種方法,不讀取字庫,而是將所有的字符存放于某個數(shù)組中,比如像font_8x16.c文件中的fontdata_8x16數(shù)組。這里假設數(shù)組為ascii_code,那么,上面的代碼只需修改一小部分,如下:
for (i = 0; i < sizeof(asciicode)-1; i++){
debug(“%c %xn”, asciicode[i], asciicode[i]);
offset = asciicode[i]* 16; // 尋址
p = ascii_code+offset;????// 查找字符在ascii_code數(shù)組中的偏移量
debug(“offset: %xn”, offset);
display_font_ascii(p);
}
效果是一樣的,所不同的是,前一種方法需要讀取字庫文件,后一種方法直接在內存中讀取,完整的ASCII碼占用空間為4KB。不過,ASCII中可打印的字符共96個(經(jīng)過認真數(shù)那些可打印的字符,發(fā)現(xiàn)實際上是95個(即32號到126號),這里將127號算上了,具體的請搜索一下ASCII),占用空間為96*16,即1536字節(jié)。由于前面0x20(即32)個字符在顯示中沒有用到,因此是可以去掉的,這樣一來,尋址方式又稍有不同,如下:
for (i = 0; i < sizeof(asciicode)-1; i++){
debug(“%c %xn”, asciicode[i], asciicode[i]);
offset = (asciicode[i] – 0x20 )* 16; // 尋址
p = ascii_code+offset;????// 查找字符在ascii_code數(shù)組中的偏移量
debug(“offset: %xn”, offset);
display_font_ascii(p);
}
由于文中涉及知識、代碼、字庫文件都可以在網(wǎng)絡上找到,因此文中就不提供下載了。
資料:
1、ASCII碼字庫,有多種形式,如8*16、8*12,名稱為ASC12、ASC16,搜索一下就能找到。
2、“字庫數(shù)組”,可以在Linux內核源代碼的./drivers/video/console目錄下找到很多相關代碼文件,如font_8x8.c、font_8x16.c、font_sun8x16.c等等。像font_8x16.c文件,代碼中說是由cpi2fnt這個東西產(chǎn)生的,但搜索一下,沒什么介紹,英文的又不想去看,對這個東西也就不了解了。
3、可以搜索一下字庫生成工具,用這些工具可以生成需要的字庫。
總結
以上是生活随笔為你收集整理的linux点阵ascii像素字体,点阵字体显示系列之一:ASCII码字库的显示 | 迟思堂工作室...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux ndk编译静态库,Andro
- 下一篇: linux vim(gvim) 多标签页