?? ucgui中增加漢字顯示.txt
字號:
在UCGUI中增加漢字顯示的說明.
作 者: ucgui
email: ucgui@163.com
home: http://www.ucgui.com
版 本: v1.0.0.1
UCGUI中本身只支持E,沒有提供中文的字庫的.C源碼文件, 但是我們可以通過下面的方式來實現漢字的顯示...
我們知道, 在DOS下經常利用點陣來顯示漢字. 帶漢字顯示的程序,很多都會自己帶上漢字庫, 這個字庫里放的就是每個漢字的點陣.
一. 漢字的顯示原理之一 -----------------點陣漢字.
簡單的理解, 所謂一個字的點陣. 其實就是指這個漢字用多少個象素點來描述. 每個象素點顯示為什么顏色, 通常情況下, HZK16采用的是16*16點陣, 即256個象素點描述一個漢字.
這些點的顏色分為兩種, 一種是前景色, 一種是顯示為背景色.
那么,關于那些點顯示為前景色, 那些點顯示為背景色, 是如何得知的呢??
可以這樣來考慮, 你在紙上比較正正方方的寫一個規則的楷字, 然后在這個字的從上到下,左到右, 分別畫十七條直線, 那么這個字就被放置于一個16*16的方格之內, 這樣我們就可以很明顯的看出, 16*16的方格內的具體哪些點有筆劃經過, 有筆劃經過與沒筆化經過的即就是應該被分別填充上前景色與背景色的點.
現在,找到了一個漢字的點陣, 那么還須要用數據來記錄點陣的信息, 通常情況下, 我們會用32個字節來表示16*16點陣的漢字, 即每一行用二個字節來記錄十六個象素點的色色彩情況, 0表示背景色, 1表示前景色. 16行其須要32個字節.
點陣漢字的原理同時也決定了它的缺點, 他不具務放大特性, 因為它的顯示是基于被定死的點陣, 放大后, 會產生明顯的鋸齒,非常的難看, 當然, 可以進行一些光滑處理, 但基本上沒有多在的改觀.
但點陣漢字簡易, 對于復雜漢字, 它比矢量顯示漢字法更快帶.矢量顯示是基于記錄漢字的筆化的. 對于簡單的漢字它比較占優勢, 容易放大處理. 但對于復雜的漢字, 表示起來, 則筆化太多..復雜.
二. 關于字庫的建立及其原理.
現在講完了漢字點陣. 也說了一個漢字點陣的存放方式, 但具體的點陣如何存放, 讀者也應該了解.
通常情況下, 一般的DOS下的程序都會提供一個漢字庫, 這樣在脫離漢字平臺(如UCDO)的支持下也可以進行漢字顯示, 但是這樣會存一個問題, 就是如果每個DOS下的程序員都這么做的話, 就會造成一定的磁盤空間浪費. 所以有的DOS下的程序,針對自己所需要的漢字, 就會定制自己的小型字庫, 那么字庫的制作到底應該如何進行呢? 下面我們將就這個問題進行一些基本的討論.
眾所周知,一個ASCII字符占一個字節,它的數值從0到255, 那么漢字字符將如何與ASCII字符區別開來呢?
實際上,仔細觀察ASCII字符表,從第161(即0xa1)個字符開始,后面的字符并不經常為E文所使用。充分利用這一特性,將161-255之間的數值空間作為漢字的標識碼。既然255-161 = 94不能滿足漢字容量的要求,就將每兩個字符并在一塊(即一個漢字占兩個字節),顯然,94* 94 =8836基本上已經滿足了常用漢字個數的要求。
從以上的討論可以知道, 用二個字節來表示一個漢字, 其原因就是上面說的, 這個就是我們常說的漢字機內碼, 一個漢字的機內碼是由值都大于0xa1的值組成的.
說完機內碼, 有的朋友可能就會問題, 機內碼與建立漢字字庫有什么關系呢??
我們常見的標準的漢字字庫HZX16(點陣16*16),HZK24(24*24)兩種.由上面的討論我們得知, 一個漢字點陣須要256個象素點陣來表示, 我們采用一個字節的8位來表示八個象素, 其須32個字節; 字庫中要存放的是所有常用的漢字的二進制點陣數據, 它的存放是有序的, 下面我們說一下這個順序:
首先.對于"我"字來說, 它的機內碼是0xce,0xd2; 機內碼每個字節均從0xa1開始, 那么我們已經采用的建立點陣字在庫中的索引方法是:
將整個字庫里面的漢字是94*94的二維數組, 要找任意一個漢字的點陣, 就須要知道這個漢字在這個二維數組當中的X維與Y維.
x維 = (機內碼字節1-0xa1) & 0x7f;
y維 = (機內碼字節2-0xa1) & 0x7f;
求漢字在X,Y維后, 那么按照每個漢字占用32個字節, 則可以得出漢字相對于字庫頭的偏移是 offset = (x*94 + y)*32;
其實,X與Y就是漢字的區位碼, 漢字的區位碼是從0-94的. 但實際上只用了16-87..
其中一級漢字在16-55..二級漢字在56-87.是按照一定的規則來確定區位碼的.對于一級漢字.是按拼音首字母級筆劃.二級漢字是按部首來的.我特意生了一個漢字的區痊碼,機內碼.在字庫中偏移的文件..大家可以下載來看一下. 可以知道:
啊-------------區位碼(x = 15, y = 0); offset=b040; 機內碼:(0xb0,0xa1);
所以漢字的區內碼,機內碼,偏移的信息,請下載這個文件查看.
http://www.macro-tax.com/home/ucgui/HZK_info.rar
其中,區位碼(x=0-14)與(88-94)都是沒有對應漢字的.字庫中實際的對應漢字點陣字數為94*72=6768個漢字.
實際上, 一個字庫中有前16*32個字節沒有表示具體的漢字的, 在字庫里被用來表示什么東西沒有什么具體的要求, 如果說你自己要做一個字庫.那么這一段你可以自己發揮, 填充為一個中文的符號,笑臉,特別文字什么的.這些沒有具體的要求.
同理.對于(88---94)*32, 你也可以自己發揮. 然后告知別人如何使用,因為這個沒有標準, 所以一定要有特別的說明,別人才可可以使用.
在一般的HZK16當中, 最前16*32個節有表示兩個大小的"A"及兩個感嘆號, 一個在圓內的"帥"字..大家可以仔細看一下,其它幾個沒作特別使用.
三.應用程序中進行漢這顯示的處理
那么, 在以上我們談了漢字的顯示原理, 漢字字庫的存放原理, 其實都是為了更方便的讓我們自由使用..
在實際小, 一個應用程序未必須要顯示所有的漢字, 可能他僅須要顯示1000個常用的漢字, 那么就可制作一個1000個常用的小型漢字字庫, 即所需要的漢字庫從250K降到32K左右了, 大大的減少了資源占用,使用上非常的靈活.
四. 在UCGUI中如何加入漢字顯示的支持.
UCGUI中沒有漢字功能的支持, 但其實只要稍加改造, 我們就可以解決點陣漢字顯示的問題.
UCGUI中, 對于E文的顯示, 也同樣采用的是點陣的方式, 而且有8*8,6*8, 16*8, 16*16等各種點陣, 這里, 我們可以實現在設置顯示16*16的E文字體時, 加上我們的漢字顯示, 因為是同樣的點陣, 我們不用任何改造, 只要有HZK16文件, 就可以在此E文字體下顯示漢字了.
全部的改造基本上集中在這個函數內部.
oid GL_DispLine(const char GUI_FAR *s, int Len, const GUI_RECT *pRect);
這個函數在GUI\Core\GUIChar.c 文件內部
要支持漢字顯示, 那么必須改成如下形式.
void GL_DispLine(const char GUI_FAR *s, int Len, const GUI_RECT *pRect) {
/*
Check if we have anything to do at all ...
If the window manager has already set the clipping rect, it does not
make sense to due this. So it makes sense only if
a) The window manager is not used (-> Configuration)
or
b) The window manager is inactive (-> Memory device active)
*/
if (GUI_Context.pClipRect_HL) {
if (GUI_RectsIntersect(GUI_Context.pClipRect_HL, pRect) == 0)
return;
}
if (GUI_Context.pAFont->pafEncode) {
GUI_Context.pAFont->pafEncode->pfDispLine(s, Len);
return;
}
#if (GUI_SUPPORT_UNICODE)
{
U8 c0;
char UCActive=0;
while (--Len >=0) {
c0=*(U8*)s++;
if (UCActive) {
if (c0 == GUI_UC_ENDCHAR)
UCActive = 0;
else {
U8 c1 = *(U8*)s++;
Len--;
GL_DispChar (GUI_DB2UC(c0, c1));
}
} else { /* Unicode not active */
if (c0 == GUI_UC_STARTCHAR)
UCActive = 1;
else
{
//增加漢字支持所加的...2005-6-13 0:14:09
if (c0&0x80 && (*(U8*)s)&0x80){
char hz[3];
hz[0]=c0;
hz[1]=*(U8*)s;
hz[2]=0;
WriteHZ(0,0,hz,0);
s++;
}
else
GL_DispChar(c0);
}
}
}
}
#else
{
U8 c0;
while (--Len >=0) {
c0=*(U8*)s++;
//增加漢字支持所加的...2005-6-13 0:14:09
if (c0&0x80 && (*(U8*)s)&0x80){
char hz[3];
hz[0]=c0;
hz[1]=*(U8*)s;
hz[2]=0;
WriteHZ(0,0,hz,0);
s++;
}
else{
GL_DispChar(c0);
}
}
}
#endif
}
處理漢字顯示:
int WriteHZ (int x, int y,const char *p,int color)
{
U16 c1,c2,rec;
long l;
char pixeldata[32];
int BytesPerLine;
GUI_DRAWMODE DrawMode = GUI_Context.TextMode;
GUI_DRAWMODE OldDrawMode;
if (handle<0 ) return 0;
if (p==NULL) return 0;
c1=(p[0]-0xa1)&0x07f;
c2=(p[1]-0xa1)&0x07f;
rec=c1*94+c2; //漢字庫94*94的二維結構...
l=rec*32L; //求字庫偏移...
lseek(handle,l,SEEK_SET);
read(handle,pixeldata,32);
BytesPerLine = 2;
OldDrawMode = LCD_SetDrawMode(DrawMode);
//半漢字點陣以二色位圖方式繪出, 前景色/背景色
LCD_DrawBitmap (GUI_Context.DispPosX, GUI_Context.DispPosY,
HZSIZEX,HZSIZEY,
1, 1,
1, /*Bits per Pixel */
BytesPerLine,
(U8*)pixeldata,
// NULL /* no palette means default palette */
&LCD_BKCOLORINDEX //在csword的bc3.0版本中, 是用NULL, 但在此處要要修改, 表明此位圖所用調色析 //為二色, 前景色與背景色...
);
LCD_SetDrawMode(OldDrawMode); /* Restore draw mode */
GUI_Context.DispPosX += HZSIZEX;
return 1;
}
另外, 除了以上所講的, 我在網上發現如下的一篇文章非常適合大家加強對漢字處理的理解. 漢字處理在DOS時代是一個比較熱門的技術, 但在現在的WIN時代.沒有什么人關注了, 但是在嵌入式開發了, 它還有一定的用武之地, 理解它還是有一定的幫助的.
一篇介紹漢字處理的文章, 非常不錯, 很基礎,很明白, 其分四節來講漢字的基本原理.
http://www.vcer.net/showTip.jsp?tipid=2291
我在vc下做的時候只要在Font目錄下加入漢字庫,GUI.h中增加extern const GUI_FONT GUI_FontHZ12;就可以顯示漢字了,不知道為什么要修改函授GL_DispLine,請指教,謝謝
漢字顯示用純字庫與.C字庫源碼文件的區別
樓上的, 其實我們所用的顯示漢字的途徑是不同的. 是兩種方法, 但都是以點陣來顯示來處理漢字顯示的, 不同點在于你的漢字點陣是與你的程序編譯在一起的, 漢字點陣的數據包含在你程序當中了.
你所說的方法, 其實用的是漢字庫弄出的點陣數據的.C文件, 這是別人從漢字庫中生成的. 這種方法與UCGUI中本身處理文字顯示的方法是相同的, 都提供了所須文字的點陣及顯示文字的方法函數. 關于具體如何實現, 我將會更詳細的寫一篇介紹文章.
至于我的漢字顯示, 說的是直接利用漢字庫, 而不用什么.C的漢字庫字體文件, 根本不用UCGUI中本身的一套方法, 但本質還是相同的, 以位圖來顯示點陣漢字, 為了顯示漢字, 須要點陣漢字庫, 及顯示漢字的函數(WriteHZ()). 而且還要修改UCGUI中的顯示字符的函數, 來特別處理漢字的顯示. 因為漢字的機內碼與ASCII中英文的有差別, 是從a1往上走的, 所以很容易區分開來.
關于你的. 你的是下載使用了中文字庫的.C文件, 這個在網上是有.如下.
一個優化過的完全版的ucGUI漢字庫_hzk12使用方法:
將解壓后的hzk12.c放到ucGUI的font路徑下
在GUI.H文件內加一行:extern const GUI_FONT GUI_FontHZ12;
按如下形式調用即可顯示中文了:
GUI_Init();
GUI_SetColor(GUI_RED);
GUI_SetFont(&GUI_FontHZ12);
GUI_SetTextAlign(GUI_TA_LEFT);
GUI_DispStringAt("漢字庫顯示測試",20,20);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -