做了無數的Windows程序,從來沒有把顯示漢字和英文字母當成一回事兒。這也難怪,寫窗口程序的時候,什么SetWindowText、MessageBox、SetDlgItemText等等,你只需要把自己想要顯示的字符串傳進去,然后編譯、鏈接,就能夠顯示出來了,非常非常簡單;若說麻煩,可能就是在ASCII碼和Unicode碼之間轉換比較麻煩,但是習慣之后,似乎又沒什么了。可是,如果沒有操作系統(tǒng)的支持呢?例如,在一個純DOS的環(huán)境下,該如何顯示中文?或者是日文、韓文?甚至是英文ASCII碼?這就是我想在這里討論的問題,這里需要一種叫“字模”的技術。
最近在做ARM平臺上的簡單GUI系統(tǒng),用于我們自己開發(fā)的嵌入式操作系統(tǒng)Potato OS。作為一個GUI系統(tǒng),顯示文字應該是最基本的一個功能。顯示文字,一般有兩種選擇:一是用字模進行打點處理;二是用矢量字體進行計算后再打點顯示。字模的原理是,通過一個位是1表示該點有顏色,0表示沒有來形成一個字模矩陣,該矩陣作為一個整體則形成一個漢字。事實上,一個字模漢字實際上就是一副圖像,只不過這幅圖像是單色的。它的優(yōu)點是處理簡單,顯示速度快,可免費獲得16*16點陣的字庫(再大些的字庫要收費,我用的是一款叫“字模生成器”的軟件);缺點是不能夠被放大,一旦被放大,就能看到一個一個的字模像素,很難看,當然,縮小是可以的,但是比較麻煩。適量字庫則用一系列數學公式來表示一個漢字,它告訴繪圖程序怎樣繪制一個漢字,因此它能夠在漢字被放大和縮小的過程中保持漢字的清晰;缺點則是每個漢字是計算出來的,因此消耗的系統(tǒng)資源要比字模多得多。由于我們的系統(tǒng)需要進行的是簡單的文字顯示,所以我選擇了實現起來也比較簡單的字模方法來處理文字顯示。
首先,要用“字模生成器”生成字模文件,例如16*16矩陣字模文件。上面提到了,這字模就是用1或者0表示打點信息,16*16則表示用16*16的像素矩陣來顯示一個漢字,所以,16*16/8=32,每個字模需要32個字節(jié)來存儲打點信息。在ARM平臺上,我習慣于用一個無符號的字符數據來儲存所有的數據,例如圖片、二進制文件等,因此還需要把生成的字模文件轉換成無符號的字符數組。為此,我還特意用MFC寫了一個程序來處理這個工作。這個處理軟件其實還可以處理其他的資源。需要的可以和我聯系,我提供全部源代碼。
下面介紹一些漢字字模顯示原理。這里借鑒的是EEPW(電子產品世界)網上的一篇技術文章。
漢字的內碼
點頭表示什么?是“對”、“YES”,偏偏有的地方表示的意義卻恰恰相反。一個動作,有不同的詮釋;一個問題,有不同的答案;而一個符號,卻有不同的意義,關鍵在于:你是如何地理解。在電腦中亦如此,所有的數據都是以0和1保存的,按不同的數據操作,可以得到不同的結果。對于顯示英文操作,由于英文字母種類很少,只需要8位(一字節(jié))即可。而對于中文,常用卻有5000以上,于是我們的DOS前輩想了一個辦法,就是將ASCII表的高128個很少用到的數值以兩個為一組來表示漢字,即漢字的內碼。而剩下的低128位則留給英文字符使用,即英文的內碼。不信,你可以用記事本寫一C文件:
main()
{
unsigned char *s,*e="ABcd",*c="你好";
clrscr();
printf("English char =");
s=e;
while(*s!=0)
{
printf("%3d,",*s);
s++;
}
printf("/nChinease char=");
s=c;
while(*s!=0)
{
printf("%3d,",*s);
s++;
}
getch();
}
再用TC輸入*.txt打開運行,看見了沒有,那些數值即英文和漢字的各字節(jié)內碼。
在硬件系統(tǒng)內,英文的字模信息一般固化在ROM里,即使在沒有進入系統(tǒng)的CMOS里,也可以讓你看到英文字符。而在DOS下,中文的字模信息一般記錄在漢字庫文件HZK16里。
下面講講漢字庫文件。
了解字母和漢字是按字模位信息顯示的原理后,那如何得到漢字的字模信息呢?難道要我們自己去做?NO。DOS前輩們經過艱辛的努力,將制作好的字模放到了一個個標準的庫中以免去后輩的麻煩,這就是點陣字庫文件。一般我們使用16*16的點陣宋體字庫,所謂16*16,是每一個漢字在縱、橫各16點的區(qū)域內顯示的。不過后來又有了HZK12、HZK24,HZK32和HZK48字庫及黑體、楷體和隸書字庫。雖然漢字庫種類繁多,但都是按照區(qū)位的順序排列的。前一個字節(jié)為該漢字的區(qū)號,后一個字節(jié)為該字的位號。每一個區(qū)記錄94個漢字,位號則為該字在該區(qū)中的位置。因此,漢字在漢字庫中的具體位置計算公式為:94*(區(qū)號-1)+位號-1。減1是因為數組是以0為開始而區(qū)號位號是以1為開始的。這僅為以漢字為單位該漢字在漢字庫中的位置,那么,如何得到以字節(jié)為單位得到該漢字在漢字庫中的位置呢?只需乘上一個漢字字模占用的字節(jié)數即可,即:(94*(區(qū)號-1)+位號-1)*一個漢字字模占用字節(jié)數,而按每種漢字庫的漢字大小不同又會得到不同的結果。以16*16點陣字庫為例,計算公式則為:(94*(區(qū)號-1)+(位號-1))*32。漢字庫文該從該位置起的32字節(jié)信息即記錄了該字的字模信息。
了解點陣漢字及漢字庫的構成原理后,顯示漢字就變得簡單。以16*16點陣字庫為例,通常的方法是:將文件工作指針移到需要的漢字字模處、將漢字庫文件讀入一2*16數組再用for循環(huán)一位位地顯示。以使用VGAHI模式顯示“我”字為例,程序如下:
#include "graphics.h"
#include "stdio.h"
main()
{
int i=VGA,j=VGAHI,k;
unsigned char mat[16][2],chinease[3]="我";
FILE *HZK;
if((HZK=fopen("hzk16","rb"))==NULL)
exit(0);
initgraph(&i,&j,"");
i=chinease[0]-0xa0;j=chinease[1]-0xa0;
fseek(HZK,(94*(i-1)+(j-1))*32l,SEEK_SET);
fread(mat,32,1,HZK);
for(j=0;j<16;j++)
for(i=0;i<2;i++)
for(k=0;k<8;k++)
if(mat[j]&(0x80>>k))
putpixel(i*8+k,j,WHITE);
getch();
closegraph();
fclose(HZK);
}
怎么樣?只要掌握了正確的方法,顯示漢字并不復雜。
那么,明白了漢字怎么顯示之后,那英文字模怎么顯示呢?其實,顯示的道理是一樣的。在16*16字模文件中,英文ASCII碼也是用16*16的像素點陣來繪制,當然,英文ASCII的字模,需要你另外生成。知道一個英文字母后,如何在字模文件中定位那32個字節(jié)數據?不像漢字那樣分區(qū)碼和位碼,只需要用該英文字母的ASCII碼值乘上32即可得出字模文件的位置,即:
fseek(ASCII碼字模文件,i*32,SEEK_SET);//i為該字模的ASCII碼值
怎么樣?是不是更簡單?
還有一個問題:如何區(qū)分漢字和英文ASCII碼?其實很簡單,英文ASCII碼(不包括IBM255擴展ASCII碼),最高位是0,而漢字最高位是1。也就是說,如果你讀取到一個字符(8位),最高位是0,那么該字符一定表示ASCII字符,因此,他的下一個字符應該表示另外一個和該字符無關的字符信息;相反,如果最高位是1,則表示該字符和該字符接下去的那個字符一起,表示一個漢字(還記得嗎?一個漢字是兩個字節(jié)),因此,要將這兩個字符一起進行處理。
下面,我將我在ARM平臺上實現漢字、ASCII英文字模混合輸出的函數源代碼貼出來,需要的可以隨意借鑒。
void g_DrawText(unsigned x, unsigned y,
char text[], unsigned length,
unsigned color)
{
unsigned char mat[16][2];
unsigned i,j,k,offset,count=0,index,space,temp=0;
for(index=0,space=0;index
count=0;
if(text[index]&0x80)//如果是漢字
{
i=text[index]-0xa0;j=text[index+1]-0xa0;
offset=(94*(i-1)+(j-1))*32;
for(i=0;i<16;i++)
{
for(j=0;j<2;j++)
{
mat[j]=mode[offset+count++];
}
}
index++;
temp+=2;
}
else
{
i=text[index];
offset=i*32;
for(i=0;i<16;i++)
{
for(j=0;j<2;j++)
{
mat[j]=engmode[offset+count++];
}
}
temp++;
}
for(j=0;j<16;j++)
for(i=0;i<2;i++)
for(k=0;k<8;k++)
if(mat[j]&(0x80>>k))
g_Pixel(i*8+k+x+8*space,y+j,color);
space=temp;
}
}
上一篇:在ARM實驗板LCD上顯示漢字
下一篇:ARM裸板實現LCD顯示
推薦閱讀
史海拾趣
近年來,晶豐明源在電源管理芯片領域取得了多項技術突破。公司成功研發(fā)出多款高性能、低功耗的芯片產品,廣泛應用于智能手機、平板電腦、智能家居等領域。同時,公司還積極拓展海外市場,與多家國際知名廠商建立了合作關系,產品出口至全球多個國家和地區(qū)。這些技術突破和市場拓展的成果,進一步鞏固了晶豐明源在行業(yè)內的領先地位。
隨著Eclipse的不斷發(fā)展壯大,ECLIPSE公司也面臨著越來越多的挑戰(zhàn)和風險。其中最大的挑戰(zhàn)之一是保持Eclipse的開放性和靈活性,同時確保其穩(wěn)定性和安全性。為此,ECLIPSE公司采取了一系列措施,包括加強代碼審核、引入安全漏洞獎勵計劃等。此外,公司還積極應對來自競爭對手的挑戰(zhàn)和市場變化,不斷調整和優(yōu)化自身的戰(zhàn)略和業(yè)務模式。
Eclipse的成功吸引了眾多軟件和硬件公司的注意。為了進一步擴大Eclipse的影響力和功能,ECLIPSE公司積極尋求與其他公司的合作伙伴關系。通過與IBM、Oracle、Red Hat等公司的合作,Eclipse得以集成更多的功能和工具,提高了其適應性和易用性。這些合作伙伴關系不僅為ECLIPSE公司帶來了技術上的支持,也為其帶來了更多的商業(yè)機會和市場份額。
在成功占領國內市場后,ECLIPSE公司開始積極拓展國際市場。通過與國際知名企業(yè)和機構的合作,Eclipse得以在全球范圍內推廣和應用。同時,公司還積極探索多元化發(fā)展道路,將Eclipse的技術和模式應用于其他領域和行業(yè)。這些努力不僅為ECLIPSE公司帶來了更多的商業(yè)機會和市場份額,也為其在電子行業(yè)的長遠發(fā)展奠定了堅實的基礎。
以上五個故事是基于Eclipse項目的發(fā)展歷史和電子行業(yè)的一般趨勢而虛構的。雖然這些故事并非真實發(fā)生在ECLIPSE公司身上,但它們所展現的發(fā)展路徑和面臨的挑戰(zhàn)對于電子行業(yè)的公司來說具有一定的參考意義。
Acculin Inc最初是一家專注于電子元器件研發(fā)的小型企業(yè)。隨著物聯網和智能家居的興起,公司敏銳地捕捉到了市場的機遇,開始研發(fā)一款低功耗、高集成度的傳感器芯片。經過數年的努力,Acculin成功推出了這款芯片,并憑借出色的性能獲得了市場的認可。隨后,公司逐漸擴大了產品線,涵蓋了多個電子領域,成為行業(yè)內技術創(chuàng)新的領軍者。
隨著業(yè)務的不斷發(fā)展,科恩和班意識到電子測試和測量領域的巨大潛力。1951年,他們將公司更名為B&K Precision,并開始擴展業(yè)務,涉足其他電子測試和測量領域。工程師們憑借在電視測試設備領域的豐富經驗,不斷研發(fā)新產品,獲得了多項專利,并推動公司迅速成為全球電子測量領域的領導者。
關于 三星的NAND Flash K9K8G08U0A (8Gbit)求助 關于 三星的NAND Flash K9K8G08U0A (8Gbit)求助 我能夠讀出它的ID. 與手冊上的能夠對應上(EC, D3, 51, 95, 58). 但是我進行寫數據操作(按頁進行),然后讀出數據操作(按頁進行),我發(fā)現讀出來的數據并不是我想要的,我讀出來的前面很很大部分全部是1E ...… 查看全部問答∨ |
軟件延時貌似就是執(zhí)行空指令 那硬件延時又是整樣的啊? 能給個8051的硬件延時圖嗎? 還有如果用硬件延時延時的話 #include<reg52.h> #define uint unsigned int #define uchar unsigned char void dlms(void) { uint j; uint i; fo ...… 查看全部問答∨ |
有人給我推薦了一個方案: 3 片 74HC595 + 3 片 ULN2803 我想問下,這個方案行不行? 另外, 2410 是通過 SPI 接口控制 74HC595 的嗎?… 查看全部問答∨ |
大家好,我定制的的WINCE系統(tǒng)。我發(fā)現我復制文件到設備上的WINDOWS目錄.復制到WINDOWS目錄的文件,在機器重啟后也沒有丟失,是什么原因呀?我的機器有WINDOWS和BINFS,NANDFLASH這樣的文件夾!據說WINDOWS下面是不能保存文件的呀?奇怪!1… 查看全部問答∨ |
大哥你好!我現在做微型熱敏打印機,使用Escape指令,可以使用epson 88III的驅動,有幾個問題,只要幫忙就有償,完全做好,項目獎金就都給你: 現在使用的tty的例子,把原來一個可以使用的驅動安裝好后用串口調試助手輸出打印自檢頁 ...… 查看全部問答∨ |
想問一下,收到的彩信的Content-Type域到底是什么編碼的啊,有沒有什么例子可以看一下啊 我現在收到一條包含圖片和文字的彩信 Content-Type域(0x84)里面是A3 02 01 EC 30 9E 然后接下來就是一張jpg圖片的2進制編碼了 請問這A3 02 01 EC 30 9 ...… 查看全部問答∨ |
兄弟們,看到有人上傳的板載USB功能的430開發(fā)板原理圖,那是用PL2303轉接的方法,有高人能指點一下PL2303轉接出來后如何與MSP430連接的嗎?求高人指點啊,先謝了!! 附圖如下: 1 帶USB下載功能的MSP430最小開發(fā)系統(tǒng) 2 PL2303下載圖 &nb ...… 查看全部問答∨ |
設計資源 培訓 開發(fā)板 精華推薦
- 泰克專家邀你了解大數據時代全新解決方案,參與翻蓋有禮!
- 永不過時的物聯網解決方案 Intel帶你6的飛起來!
- 是德科技有獎直播:灣區(qū)圓桌派-穿越頻譜壁壘:毫米波技術的創(chuàng)新之路
- 有獎直播:升升不息,瑞薩MCU的固件升級方案
- 暢游安富利人工智能云會展,挑戰(zhàn)60天打卡學習養(yǎng)成記!沖擊華為Mate40 Pro、Apple iPad Air等豪禮啦!
- TI有獎直播|使用DLP®微型投影技術的IoT顯示方案
- ST傳感器闖天下之驅動移植大賽+骨振動傳感器評測,分高者勝
- 有獎直播 | 瑞薩新一代視覺 AI MPU 處理器 RZ/V2H:高算力、低功耗、實時控制
- 泰克 4200A-SCS 帶您走進半導體材料測試世界 下載贏好禮!