作者: ucgui
日期: 2005-06-25
来源: http://www.ucgui.com
文档版本: v1.0.0.0
要高效的利用汉字, 最好的办法是建立自己的小汉字库,要做到这一点, 就必须理解汉字库的构成原理及汉字的显示原理.否则常规的汉字库太大了, 网上流传的HZK12.C文件, 是一个完全的汉字库源码文件,是按照UCGUI中处理文字显示的基本原理来显示汉字的----即以点阵位图来显示文字. 但是这个文件很大, 不可能直接在嵌入式当中使用的..
我认为一种可行的比较灵活的办法是, 将可能用到的汉字集中在一块编一个序号,比如说"世界你好", 则编号分别为0xa1a1,0xa1a2,0xa1a3,0xa1a4, 请注意这些编码与机内码没有任何关联, 是我们自定义的文字机内码.
世-------->0xa1a1
界-------->0xa1a2
你-------->0xa1a3
好-------->0xa1a4
构建SmallHZK12.c如下:显示"世界你好".
调用时如下:
void MainTask(void)
{
// ToD Make sure hardware is initilized first!!
//自定义小字库时用.
const unsigned char helloworld[]={0xa1, 0xa1, 0xa1, 0xa2, 0xa1, 0xa3, 0xa1, 0xa4, 0x00};
//标准字库时用
//const unsigned char helloworld[]={0xca, 0xc0, 0xbd, 0xe7, 0xc4, 0xe3, 0xba, 0xc3, 0x00};
GUI_Init();
GUI_DispString((const char*)helloworld);
while(1){
//GUI_DispStringHCenterAt("TEST汉字支持 ", 50, GUI_GetDispPosY());
GUI_Delay(800);
}
}
/***********************************************************************
REVISION LOG ENTRY
Revision By: ucgui
Revised on 2005-6-17 19:09:52
QQ:106719880
Email:ucgui@163.com
Home:http://www.ucgui.com
Comments: SmallHZK12.c
***********************************************************************/
#include "GUI.H"
#ifndef GUI_FLASH
#define GUI_FLASH
#endif
extern GUI_FLASH const GUI_FONT GUI_FontHZ12;
//世
GUI_FLASH const unsigned char acFontHZ12_cac0[24] = {
0x04,0x40, 0x24,0x40, 0x24,0x40, 0x24,0x40, 0xff,0xf0, 0x24,0x40, 0x24,0x40, 0x24,0x40, 0x27,0xc0, 0x24,0x40, 0x20,0x00, 0x3f,0xf0
};
//界
GUI_FLASH const unsigned char acFontHZ12_bde7[24] = {
0x3f,0xc0, 0x24,0x40, 0x3f,0xc0, 0x24,0x40, 0x3f,0xc0, 0x04,0x00, 0x0b,0x00, 0x38,0xf0, 0xc9,0x20, 0x09,0x00, 0x11,0x00, 0x61,0x00
};
//你
GUI_FLASH const unsigned char acFontHZ12_c4e3[24] = {
0x12,0x00, 0x12,0x00, 0x27,0xf0, 0x24,0x20, 0x69,0x40, 0xa1,0x00, 0x25,0x40, 0x25,0x20, 0x29,0x10, 0x31,0x10, 0x25,0x00, 0x22,0x00
};
//好
GUI_FLASH const unsigned char acFontHZ12_bac3[24] = {
0x20,0x00, 0x27,0xe0, 0x20,0x40, 0xf8,0x80, 0x48,0x80, 0x48,0xa0, 0x57,0xf0, 0x50,0x80, 0x30,0x80, 0x28,0x80, 0x4a,0x80, 0x81,0x00
};
GUI_FLASH const GUI_CHARINFO GUI_FontHZ12_CharInfo[4] = {
{ 12, 12, 2, (void GUI_FLASH *)&acFontHZ12_cac0 },
{ 12, 12, 2, (void GUI_FLASH *)&acFontHZ12_bde7 },
{ 12, 12, 2, (void GUI_FLASH *)&acFontHZ12_c4e3 },
{ 12, 12, 2, (void GUI_FLASH *)&acFontHZ12_bac3 }
};
GUI_FLASH const GUI_FONT_PROP GUI_FontHZ12_Propa2= {
0xa1a1,
0xa1fe,
&GUI_FontHZ12_CharInfo[0],
0
};
GUI_FLASH const GUI_FONT GUI_FontHZ12 = {
GUI_FONTTYPE_PROP_SJIS,
12,
12,
1,
1,
(void GUI_FLASH *)&GUI_FontHZ12_Propa2
};
不过目前有一个问题, 就是显示结果挤在一块了.只是显示半个字节.这个问题下一步解决..
呵呵.....先吃钣...
[2005/07/14]
昨天晚上已经解决了半个汉字的问题, 写了一篇详细些的文档, 不过由于拷错文件, 没持拷过来, 所以暂且只贴了代码, 没有大多的详细说明.
在上一文中已经提供了一种自定义小型字库的说明, 现在再提出另外一种建立小型字库的方法, 这两种差别不大, 但构造方法还是有区别的, 希望大家可以对自定义字库(其实也就是自定义自己的字体)有本质的认识, 很多朋友对于UCGUI当中字体文件的.C文件是如何产生的不清楚原理, 也有许多朋友不不清楚自定义汉字字体的原理与方法, 这里我就如何自定义小型汉字库做了很清楚的说明, 须要的朋友可以看看....
从HZK16中取出所须的汉字, 组成新的字库文件, 再变成UCGUI中所须的源文件. 这样讲是非常抽象的, 首先, 你取出的汉字, 其机内码不是连续的, 那么这样一来, 如果还是使用汉字的标准机内码的话, 则必须为每一个要用到的汉字都建立一个GUI_FONT_PROP结构, 一个汉字一个, 在将他们链接成链表, 这样做唯一好处是可以直接以如下方法:
const unsigned char helloworld[]="世界你好";
GUI_DispString((const char*)helloworld);
依*编译器来将"世界你好"转变成汉字机内码的字符串. 但我们亦可手工构造要显示的汉字如下:
const unsigned char helloworld[]={0xca, 0xc0, 0xbd, 0xe7, 0xc4, 0xe3, 0xba, 0xc3, 0x00};
GUI_DispString((const char*)helloworld);
如上两种比较, 结果是一样的,唯一不同的是, 第一种方法显示汉字时, 无须使用知道汉字的机内码, 而是由编译器来转换的, 但我要说的是, 其实两者本质是一样的, 只是对使用者来说有表面上的不同.比较以上的两种显示汉字时构造字符串的方法, 我们可以得到一个启示, 对于第二种, 我们可以采取自定义汉字机内码, 然后直接通过自定义机内码来显示汉字, 这一点我已经在"建立自定义小型汉字库说明"一文当中说明了, 现在我想说的是对于采用第一种方法显示汉字的建立自定义小型字库的方法:
使用如下:
void MainTask(void)
{
char helloworld[] = "世界你好";
GUI_Init();
GUI_DispString((const char*)helloworld);
while(1){
GUI_Delay(800);
}
}
构造SmallHZK12_2.c如下:
/***********************************************************************
REVISION LOG ENTRY
Revision By: ucgui
Revised on 2005-6-17 19:09:52
QQ:106719880
Email:ucgui@163.com
Home:http://www.ucgui.com
Comments: SmallHZK12_2.c
这时是第二种自定义小型汉字库的方法,在这种方法下可以采用
char hellworld[]="世界你好";这种方法来方便的显示汉字, 比
第一种方法容易使用, 不过缺点是每一个字对应一个GUI_FONT_PROP结构
体, 明显占用了多的内存, 减慢查找显示的速度.
***********************************************************************/
#include "GUI.H"
#ifndef GUI_FLASH
#define GUI_FLASH
#endif
extern GUI_FLASH const GUI_FONT GUI_FontHZ12;
//世
GUI_FLASH const unsigned char acFontHZ12_cac0[24] = {
0x04,0x40, 0x24,0x40, 0x24,0x40, 0x24,0x40, 0xff,0xf0, 0x24,0x40, 0x24,0x40, 0x24,0x40,
0x27,0xc0, 0x24,0x40, 0x20,0x00, 0x3f,0xf0
};
//界
GUI_FLASH const unsigned char acFontHZ12_bde7[24] = {
0x3f,0xc0, 0x24,0x40, 0x3f,0xc0, 0x24,0x40, 0x3f,0xc0, 0x04,0x00, 0x0b,0x00, 0x38,0xf0,
0xc9,0x20, 0x09,0x00, 0x11,0x00, 0x61,0x00
};
//你
GUI_FLASH const unsigned char acFontHZ12_c4e3[24] = {
0x12,0x00, 0x12,0x00, 0x27,0xf0, 0x24,0x20, 0x69,0x40, 0xa1,0x00, 0x25,0x40,
0x25,0x20, 0x29,0x10, 0x31,0x10, 0x25,0x00, 0x22,0x00
};
//好
GUI_FLASH const unsigned char acFontHZ12_bac3[24] = {
0x20,0x00, 0x27,0xe0, 0x20,0x40, 0xf8,0x80, 0x48,0x80, 0x48,0xa0, 0x57,0xf0, 0x50,0x80,
0x30,0x80, 0x28,0x80, 0x4a,0x80, 0x81,0x00
};
GUI_FLASH const GUI_CHARINFO GUI_FontHZ12_CharInfo[4] = {
{ 12, 12, 2, (void GUI_FLASH *)&acFontHZ12_cac0 },
{ 12, 12, 2, (void GUI_FLASH *)&acFontHZ12_bde7 },
{ 12, 12, 2, (void GUI_FLASH *)&acFontHZ12_c4e3 },
{ 12, 12, 2, (void GUI_FLASH *)&acFontHZ12_bac3 }
};
GUI_FLASH const GUI_FONT_PROP GUI_FontHZ12_Propa4= {
0xbac3,
0xbac4,
&GUI_FontHZ12_CharInfo[3],
0
};
GUI_FLASH const GUI_FONT_PROP GUI_FontHZ12_Propa3= {
0xc4e3,
0xc4e4,
&GUI_FontHZ12_CharInfo[2],
(void *)&GUI_FontHZ12_Propa4
};
GUI_FLASH const GUI_FONT_PROP GUI_FontHZ12_Propa2= {
0xbde7,
0xbde8,
&GUI_FontHZ12_CharInfo[1],
(void *)&GUI_FontHZ12_Propa3
};
GUI_FLASH const GUI_FONT_PROP GUI_FontHZ12_Propa1= {
0xcac0,
0xcac1,
&GUI_FontHZ12_CharInfo[0],
(void *)&GUI_FontHZ12_Propa2
};
GUI_FLASH const GUI_FONT GUI_FontHZ12 = {
GUI_FONTTYPE_PROP_SJIS,
12,
12,
1,
1,
(void GUI_FLASH *)&GUI_FontHZ12_Propa1
};
SmallHZK12_2.C自定义小字库及说明下载:
UCDOS这个中文DOS平台, 想必知道的人不少了....
在网上, 也流传了UCDOS下的转换后的HZK12.C这个专用于UCGUI的字体文件下载, 但是没有见到hzk16,hzk24等的
宋体/黑体/楷体的.C文件下载..
这里我制作了他们的. C文件, 并且提供转换代码下载:
.c字体文件特点:
1.对于字体文件有注解, 可以让大家更清晰的认清UCGUI下所用的字体文件的结构.
2.只取汉字当中有汉字的区, 从0xb0a1~0xb0fe, 0xb1a1~0xb1fe, 0xb2a1~0xb2fe....0xf7a1~0xf7fe, 不包含其
它无用的区域, 在hzk12.c当中包含了0xa1a1~0xa1ff等一些无用区域.
[1]. 转换好的字库文件下载:
hzk24h.c--------24号黑体字
hzk24s.c--------24号宋体字
hzk24k.c--------24号楷体字
hzk16s.c--------16号宋体字
hzk16fs.c-------16号仿宋字
hzk12s.c--------12号宋体字
http://www.ucgui.com/ucgui/UCGUIFontTool.rar
1. 完成字体生成工具动态库, 调用接口为ShowGenFontHZDlg(), 弹出字体生成界面,
导出汉字GBK的汉字字体.c文件. 专门用于UCGUI.
2. 可以自定义导出汉字.C文件, 输入自己要使用的汉字及ASCII字符.
3. 跳过0xaaa1~0xafff这几分区, 因为这几个分区没对有对应任何的汉字.
[更新记录] 2005/08/22
16:36 2005-8-21
关于转换字体中的2bpp及4bpp.
1.创建字体时, 可以有三种选择:
[1]标准字体,无光滑处理.
[2]二位光滑处理, 即字符点阵中每个象素占2位.
[3]四位光滑处理, 即字符点阵中每个象素占4位.
在有光滑处理的候, 由于点阵中一个象素可以有多位来表示, 也即表明每个象素点可以有多种颜色. 在2bpp的情况下, 每个象素点可以有4种颜色. 4bpp中, 每个象素点可以16种颜色; 在进行光滑处理时, 是为了防止锯齿, 所以为了平滑过渡, 在产生锯齿的地方填充上一些相近颜色, 即可以合锯齿不太明显. 所以2bpp的可以认为是4级灰度. 4bpp可以认为是16级灰度光滑处理.
当选择了光滑处理后, 可以在对每个字符的点阵进行填色, 人为的进行光滑处理, 但如果在选择光滑处理时选择Internal的话, 转换工具自制为对字符进行光滑处理. 导出即可使用.
[更新记录] 2005/08/15
字体转换工具放下很久了, 一直没弄了, 这个周未弄了一下, 唉, 有时候有些东西要做完还是须要坚持, 开始把最难的弄出来了, 后面就没想再继续做简单的修改了...拖到现在....
2:17 2005-08-14
1.修改导出每个字符宽度所占用字节数. 即指GUI_CHARINFO结构中的BytesPerLine.以后将陆续加入如下功能:
1.可以直接转换出UNICODE的. 也可以选择GBK码.
2.可以转换指定范围, 这个官方已经支持的, 很方便于自定义字库.
3.可以根据输入的指定字符来产生.C文件,方便自定义字库.
4.更文件的支持UNICODE的显示处理.
2:35 2005-7-22 v1.0.0.0
1.发布1.0.0.0, 正确导出点阵, 但导出字符宽度所占字节数老是1, 不能正确使用.C文件.
一. 字体转换工作修改版下载:
http://www.ucgui.com/ucgui/ucGUI-FontConvert-Modiy.rar
二. 网友的ucgui_font.exe字体.C生成工具, 04年10月份就有了, 可惜现在才露面...
http://www.ucgui.com/ucgui/ucgui_font.rar
三. 我自己生成的UCGUI 汉字GBK码到UNICODE转换码表
http://www.ucgui.com/ucgui/GBKConvertTableUnicode.rar
四. 以下是修改版的字体转换工具导出的.C文件的示例:
英文字体elephant 72号字体导出.c文件
http://www.ucgui.com/ucgui/Elephant123.rar
英文字体elephant 72号字体显示示例
http://www.ucgui.com/ucgui/GUISim1005_BigFontView.rar
1..C文件中每个字符的BytesPerLine, 即每行字数是不对的, 默认是1,要正确使用请自行修改.
2.目前导出的.C文件的每个字符的点阵当中的BytesPerLine亦不对, 正确的暂不公开, 稍后修改完整即行公开,有什么问题请与我联系:ucgui@163.com
三. 字体转换工具调试日志:
2:50 2005-7-24
这个周未来了一个朋友, 本来可以早点弄完的, 不过弄完了没在公司, 不能上网, 还是一样的.开始, 我的hiew用不了, 是demo版的, 不能存修改后的文件, 没有办法, 又不能上网下载, 所以就只能用OLLDBG来一句一句的写代码, 然后直接将汇编的二进制数据加到PE文件代码空间未用的部分.比较麻烦, 但代码不多, 还好, 写错一句就要重头来, 惨!
2:35 2005-7-22
今天心情有点郁闷, 在olldbg中调试追踪及IDA中静态调试时精神不是特别集中...
今天的事太郁闷了...还是不能做到心无旁物, 居然有这样的大学四年的同学, 不知是我的
悲哀, 还是他的悲哀, 这事太郁闷了....
关于从TRUETYPE字体中如何提取一个字符的点阵数据?
以下步骤中, 如果选中字体是UNICODE时, 所有函数尾部加(GetPixel除外).
1. 首先通过这个字符的的代码来获取这个字符的宽高(单位为象素), 用GetTextExtentPoint函数.
BOOL GetTextExtentPoint(
HDC hdc, // handle to device context
LPCTSTR lpString, // pointer to text string
int cbString, // number of characters in string
LPSIZE lpSize // pointer to structure for string size
);
2. 再将这个字符通过TextOut函数输出到指定的HDC当中(此HDC可以任一指定窗体的), 位置是(0,0).
BOOL TextOut(
HDC hdc, // handle to device context
int nXStart, // x-coordinate of starting position
int nYStart, // y-coordinate of starting position
LPCTSTR lpString, // pointer to string
int cbString // number of characters in string
);
3. 再通过GetPixel来从点(0,0)开始, 一行一行的获取指定字符的点阵信息.
COLORREF GetPixel(
HDC hdc, // handle to device context
int XPos, // x-coordinate of pixel
int nYPos // y-coordinate of pixel
);
以上就是基本的原理, 非常的简单, 也是大多数软件采取的从TRUETYPE字体中提取字符点阵信息的原理. 剩下的破解工作其实就是查看输出的那个函数. 代码中已经有现成的读取指定字符真正点阵的函数. 直接调用就可以了...所做的工作其实不多了....
1:00 2005-7-21
1.获取到取一个字符点阵的原理, 是显示字符后对过GetPixel来取该字符的点阵信息.对于任何的字体, 无论是点阵字体还是TRUETYPE字体, 显示之后都是点阵的集合, 所以这是提取TYUETYPE字体对应点阵字体的基本原理.
2.但问题是显示该字符时, 显示在什么位置, 是否显示一个字符取一个字符点阵??
3.进一步了解到生成字体时, 选择标准字体与光滑处理的字体时的区别.
2:25 2005-7-20
1.明白字符显示出来来用的SetPixel, 但不明白是为何不用TEXTOUT来显示字符呢? 显示字符前必须先取到字符的点阵信息.
2.初步理解程序的数据结构, 但还是有好多细节不明.
1:40 2005-7-19
1.理解到点阵信息的获取是通过TRUETYPE字体来提取的, 并非先前所想的提取WIN下面的点阵字体的数据.
2.初步理解到取点阵信息时并不是直接从TYUETYPE字体文件中取, 而是通过显示后提取象素.
1:50 2005-7-18
1.选中一个字符时, 在下面的方格中显示, 是通过先画矩形, 再填充块来实现的, 根据点菜来画块.
2.通过上面的大框选中字符, 下面的框显示字符的点阵, 是在下面框的ondraw当中实现的.
0:45 2005-7-17
静态反汇编工具: IDA4.5版, 静态查看方便, 跳转到指地址方便, 亦可进行动态调试, IAD还有一个很方便的功能是可以在其当中为函数写注解, 这一点非常的重要, 调试时很多的函数都是要反复读的, 由于没有函数, 很难记起, 所以要上注解会很方便阅读代码(注间注解的时候先输入";"符号才弹出填写注解的框), 当然也可以自己为已经清楚功能的函数重命名, 把sub_XXX这一类名改成可读性强的.
动态调试工具: olldbg1.09版, 这个工具动态调试时, 有两个很有用的优点.
1.可以设定读写指定内存时断点.这一点可以用于很方便追踪到读写某一块内存的代码.
2.可以在调用指定WIN的API时在汇编中标明参数, 并且在堆栈中标明. 还有就是当前存写地址的数据也会自动标出.
1.发现是被压缩过的, 用的是UPX工具, 版本1.93的即可成功解压.
2.初步发觉是MFC写的程序, 其中大量的MFC类, 是静态连接MFC库的.
3.MFC写的程序, 由于比SDK多了一层类的封装, 很多的虚函数调用都没有名字可看, 对于调试难度非常大.
4.大至决定调试程序时, 只能根据特征字符串来追踪, 这也是大多数破解才有的办法, 在程序中有字符串等信息, 可以大至了解到字符串所在函数的功能. 比如说, 如果要找输出.C字体文件的东东, 由于有一堆的特征串, 很容易找到.一般来说很少程序将字符串加密的.
5.初步决定首先要调试理解程序, 必顺先理解TRUETYPE字体转换的原理.
ucos的GUI图形系统ucgui的模似器源码设计文档及各种资料
近日整理修改了几篇以前写的有关UCGUI的技术文章,提供给大家下载.
希望大家可以对文章中表达不准备及不到位有错误的地方指出来, 以在下一版中修正.
一."UCGUI的模拟器UCGUISim的设计文档", 6100余字,主要介绍了UCGUI的模拟器的构成及使用,并着重讲角了模拟器的实现原理,理解模拟器的原理有助加深对UCGUI的理解;了解UCGUI在图形驱动模块的层次结构,对于UCGUI的移植会有更加清晰的认识。
二."UCGUI的动态内存分配的原理深入分析", 5500余字,了解UCGUI的朋友,一定了解UCGUI中的窗口体系,窗口是动态创建的,其中当然要用到动态的内存申请,现在我们就这个话题在UCGUI3.24版源码基础上进行深入分析,了解UCGUI中的动态内存分配功能,这是了解其窗口系统及内存设备场景的基础,这一点非常的重要。文中并深入讲解了此动态内存是从何处得来的问题,描述了程序代码段及数据段以及程序连接加载运行的一些相关知识。
三."UCGUI窗体管理及消息处理机制分析",12500余字,本文主要介绍了UCGUI中的对话框的消息处理机制,并指出在现有UCGUI上如何增加多窗体支持,并在分析解决问题时着重介绍了其输入设备消息WM_TOUTCH及WM_KEY两类消息处理方法,并同时初步指出一种在UCGUI中实现模态对话框以及透明窗体的原理说明,不还有窗体重画消息WM_PAINT消息处理原理。
四."UCGUI简介", 3000余字,从整体上介绍了UCGUI的基本功能/设计思想/架构/设计目标.让学习UCGUI的人可以从大体上把握UCGUI的一些基本概念, 了解其模块化的设计架构及模块的划分.
五."UCGUI的性能与资源占用", 1000余字,从资源占用的角度分析了UCGUI各个模块的资源占用特性,UCGUI各个模块均是可配制的,了解它对于安排硬件及软件功能支持均非常大的意义.
六.有关嵌入式图形系统学习的大体导向
文档下载:
http://www.ucgui.com/ucgui/ucgui_pdf.rar
联系客服