关于ucgui的字库

合集下载

基于 UCGUI 库的外扩中文字库研究与实现

基于 UCGUI 库的外扩中文字库研究与实现

基于 UCGUI 库的外扩中文字库研究与实现李建红;刘丹;徐展【期刊名称】《计算机工程》【年(卷),期】2014(40)2【摘要】UCGUI 是实时嵌入式系统中广泛使用的图形用户界面,但 UCGUI 不支持中文字符编解码。

为此,提出一种支持中文字符编解码的方法。

在分析 UCGUI 字符编解码框架基础上,修改内核代码,添加 GB2312汉字编解码驱动,实现中文字符显示编解码服务。

针对 UCGUI 中文显示时中文字库占用空间大与 MCU 存储空间有限的矛盾,提出一种字体驱动与字模数据分离的中文字体设计方法,包括为外扩字体设计专用驱动、字模数据存储接口及存储方法。

在 UCGUI 仿真平台环境下的测试结果表明,该字库在 UCGUI 系列环境下,具有较好的可用性和通用性,可弥补 UCGUI 界面库在低成本嵌入式系统中难以实现中文显示的缺陷。

%UCGUI is a graphical user interface library which is widely used in real-time embedded system. As it does not support Chinese character set, a method to support Chinese character by adding GB2312 Chinese character codingis proposed. This paper designs and implements a font drive program by which font data is separated from UCGUI library code, including drive for extended font, font data access interface & method. Font drive is tested on the UCGUI simulators and is completely compatible with the UCGUI library. This makes up for technical blank of Chinese display in low-cost embedded system with UCGUI library.【总页数】5页(P271-274,279)【作者】李建红;刘丹;徐展【作者单位】电子科技大学电子科学技术研究院,成都 611731;电子科技大学电子科学技术研究院,成都 611731;电子科技大学电子科学技术研究院,成都611731【正文语种】中文【中图分类】TP391.41【相关文献】1.基于蒙古文编码国家标准的OpenType字库研究与实现 [J], 斯日古楞;呼斯勒2.基于STM32平台实现UCGUI外挂中文字库 [J], 马志刚3.基于网络处理器外扩TCAM的研究与实现 [J], 李诗革;李文耀;王欢4.中文字库芯片GT30L32S4W在emWin图形库中的应用 [J], 赵云5.ARM-Linux外扩AD驱动程序的研究与实现 [J], 曹毅;何慎学;陈会鸽因版权原因,仅展示原文概要,查看原文内容请购买。

如何将ucgui的汉字库存放到外部的flash memory

如何将ucgui的汉字库存放到外部的flash memory

(原创)如何将ucgui的汉字库存放到外部的flash memory(ucgui)(汉字库)(外部flash)摘要:在ARM7系统中,都不会有足够大的程序存储器来存放大容量的汉字库,因此当系统中要用到汉字库时,需要将其存储在外部的FLASH Memory,而ucgui的字符显示函数是直接从程序存储器取数据的,因此需要在原始代码里增加一个接口,来指向外部的FLASH Memory。

简介:ucgui中,字符显示的底层函数是GUICharP.c 中的void GUIPROP_DispChar(U16P c) 函数,我们将这个函数修改如下:/*********************************************************************** GUIPROP_DispChar** Purpose:* This is the routine that displays a character. It is used by all* other routines which display characters as a subroutine.*/void GUIPROP_DispChar(U16P c) {int BytesPerLine;U8 BytesPerFont; //一个字的字节数U32 base,oft; //字库的起始地址和偏移量GUI_DRAWMODE DrawMode = GUI_Context.TextMode;const GUI_FONT_PROP GUI_UNI_PTR * pProp = GUIPROP_FindChar(GUI_Context.pAFont->p.pProp, c); if (pProp) {GUI_DRAWMODE OldDrawMode;const GUI_CHARINFO GUI_UNI_PTR * pCharInfo;//支持3种字体==if((GUI_Context.pAFont == &GUI_FontHZ16)||(GUI_Context.pAFont == &GUI_FontHZ24)||(GUI_Context.pAFont == &GUI_FontHZ32)){pCharInfo = pProp->paCharInfo;base = (U32)pProp->paCharInfo->pData;BytesPerFont = GUI_Context.pAFont->YSize * pProp->paCharInfo->BytesPerLine; //每个字模的数据字节数if (BytesPerFont > BYTES_PER_FONT){BytesPerFont = BYTES_PER_FONT;if (c < 0x80) //英文字符地址偏移算法{oft = base + (c - 0x20) * BytesPerFont; //计算出字码在flash中的偏移地址}else//中文字符地址偏移算法{oft = base + (((c>>8) - 0xa1) * 94 + ((c&0xff) - 0xa1)) * BytesPerFont;}LCD_ReadFlashBit(oft, GUI_FontDataBuf, BytesPerFont);//取出字模数据BytesPerLine = pCharInfo->BytesPerLine;OldDrawMode = LCD_SetDrawMode(DrawMode);LCD_DrawBitmap( GUI_Context.DispPosX,GUI_Context.DispPosY,pCharInfo->XSize,GUI_Context.pAFont->YSize,GUI_Context.pAFont->XMag,GUI_Context.pAFont->YMag,1, /*Bits per Pixel */BytesPerLine,GUI_FontDataBuf,&LCD_BKCOLORINDEX);}//--else{pCharInfo = pProp->paCharInfo+(c-pProp->First);BytesPerLine = pCharInfo->BytesPerLine;OldDrawMode = LCD_SetDrawMode(DrawMode);LCD_DrawBitmap( GUI_Context.DispPosX,GUI_Context.DispPosY,pCharInfo->XSize,GUI_Context.pAFont->YSize,GUI_Context.pAFont->XMag,GUI_Context.pAFont->YMag,1, /*Bits per Pixel */BytesPerLine,pCharInfo->pData,&LCD_BKCOLORINDEX);/*Fill empty pixel lines */if (GUI_Context.pAFont->YDist > GUI_Context.pAFont->YSize) {int YMag = GUI_Context.pAFont->YMag;int YDist = GUI_Context.pAFont->YDist * YMag;int YSize = GUI_Context.pAFont->YSize * YMag;if (DrawMode != LCD_DRAWMODE_TRANS) {LCD_COLOR OldColor = GUI_GetColor();GUI_SetColor(GUI_GetBkColor());LCD_FillRect(GUI_Context.DispPosX,GUI_Context.DispPosY + YSize,GUI_Context.DispPosX + pCharInfo->XSize,GUI_Context.DispPosY + YDist);GUI_SetColor(OldColor);}}LCD_SetDrawMode(OldDrawMode); /*Restore draw mode */GUI_Context.DispPosX += pCharInfo->XDist * GUI_Context.pAFont->XMag; }}然后再加入FLASH操作的底层驱动(这里用的是SPI FLASH)/********************************************************************* ** Static code*********************************************************************** *///字模数据的暂存数组,以单个字模的最大字节数为设定值#define BYTES_PER_FONT 4*32 //最大支持32*32的汉字static U8 GUI_FontDataBuf[BYTES_PER_FONT];/********************************************************************* ** 读FLASH中的字库*/#include "spi_flash.h"#include "ssp.h"void LCD_ReadFlashBit(U32 addr,U8* buf,U8 Bytes){U8 i;SPI_FLASH_StartReadSequence(addr); //设置起始地址for(i=0;i<Bytes;i++){buf[i] = SPI_FLASH_SendByte(0xa5);}SPI_FLASH_CS_HIGH();}我们知道,ucgui访问字库的时候,是根据字库文件的索引表来查找汉字数据地址的,因此汉字库文件中的索引也要修改,以汉字库32为例/*******************************************************File Name : hzk32.CCompiler :Author : Liu_xfVersion : V1.0Date : 2011-3-28 11:25:54Description :ucgui的中文字库,与uc工具生成的字库文件不同的是,可以将大容量的汉字数组存入到外部的FALSH里当然这个也是由uc工具生成的文件修改而来的。

基于STM32平台实现UCGUI外挂中文字库

基于STM32平台实现UCGUI外挂中文字库

U CG UI是 一 种轻 量级 的嵌 入 式 图形 支 持 系
间 不足 而 无法 实 现程 序 的烧 写 . 所 以对 于大 量 文字
统 ,它 的设 计架 构 是模 块化 的, 由不 同 的模 块 中
的 上 运
的 随 机 显 示 ,更 好 的方 案 是 将 字 库 与 程 序 代 码 分 开 .但 是 U C GU I 本 身 并没 有 提供 从 外 部存 储 器读
行, 因为 它是 1 0 0 %的标准 C代 码编 写 的 . Uc Gu I 提 供一 个 可扩 展 的 2 D图形 库及 占用 极 少 R AM 的
窗 口管理 体系 ,非常适 合 如 S T M3 2 这样 的轻 量
级 嵌入 式 平 台 的 图形 界面 显示 I l J ,大 量 应用 于 各
作 者简 介 :马 志 刚 ( 1 9 7 9) ,云南 水 富人 ,讲师 ,硕 士,研 究方 向 :计算 机控 制 ,嵌入 式 系统 软硬 件
F O NT T YP E P R OP S J I S 的定 义 ,将字 符 显示 驱动
P Bl 2 P B1 3
PB 1 4 PB 1 5
绝 大部 分应 用场 合 都是 无法 事 先预 知有 哪些 汉字
需 要 显示 ,而 如果 把 所 有 常用 汉 字 按 照 uC G UI
S T M3 2处 理器 上外 接 F l a s h存储 芯片 来扩 大存储 空
间 .例 如 可 采 用 S P I接 口 的 Na n d F l a s h 芯 片 M2 5 P X1 6来 扩展 存储 空 间 ,该芯 片具有 1 6 Mb i t 容 量 ,具备 4 K 字 节子 区擦 除功 能 ,最 高支 持 7 5 Mh z

ucGUI移植详细设计及总结

ucGUI移植详细设计及总结

ucGUI移植详细设计及总结序本文档阐述了将ucGUI移植到IM12上的过程。

ucGUI版本为3.9,移植到IM12上,触摸屏及按键能够正常使用。

在ucGUI源码包的基础上,添加了一些接口函数以适应IM12,在使用时应该根据情况使用这些接口,这些新增加的函数的接口将在后面章节中详细讲述。

此外,适应IM12的ucGUI在Wind River Workbench 3.0环境下被编译成两个静态库文件libNoWindow.a和libWindow.a,编译程序时应该连接这两个库。

文档篇章安排如下:第一章,ucGUI源码包简介。

主要介绍了所使用的ucGUI图形库中各文件夹的内容及功能,并对IM12中与ucGUI移植相关的部分,包括触摸屏、LCD、按键板等进行了简单的介绍。

第二章,图形库移植。

阐述如何对ucGUI进行配置、编译,以在IM12的LCD上显示图形,此部分还未实现触摸屏及按键功能,只是纯粹的显示而已第三章,触摸屏移植。

第四章,按键移植。

第五章,带触摸屏及按键功能的ucGUI应用程序模板。

第一章ucGUI源码包简介ucGUI要移植到im12上,实际上就是根据im12的情况修改ucGUI中的一些配置项,或增加、删减一些程序以适应im12,同时要保持ucGUI的特性。

要做好移植工作,需对ucGUI 及IM12相关部分有足够的了解。

1.1ucGUI简介移植所采用的ucGUI版本为3.9,主要包含的文件夹如图1所示图1 ucGUI源码结构图各文件夹的主要内容如下:Config ----------- 配置文件GUI ----------- 源代码GUI_X ---------- 操作系统接口函数定义文件GUI 源代码文件:1)AntiAlias: 抗锯齿显示效果支持。

2)ConvertColor: 彩色显示的色彩转换支持。

3)ConvertMono: (b/w)和灰度显示的色彩转换支持。

4)Core: 核心文件,提供了GUI基本的功能。

uCGUI 汉字显示技巧及总结

uCGUI 汉字显示技巧及总结

UCGUI的基础应用汉字显示在uC/GUI中显示汉字,必要的一个步骤就是汉字取模。

通常有两种方法:一、单个字模法:使用字模取模软件,进行单个字的取模。

此方法可应用于显示汉字字数较少的情况下。

其优点是:占用存储空间小,无冗余。

但当显示汉字字数较多时,该方法则非常繁琐。

二、字模库法:该方式需要移植整个汉字字库,若项目要求需显示多种汉字字体,则需移植多种字体的字库。

其优点是:操作方便。

若嵌入式系统的FLASH存储容量够大时,该方式可行。

根据作者多年的项目实践,找到一个兼具上述两种方式优点的显示方案:利用UCGUIFontTool软件,提取windows自带的字模库。

该方法的使用步骤:1、将项目中所要显示的汉字根据字体进行分类并汇总。

2、使用UCGUIFontTool软件分别提取上述字模。

3、将所产生的.C文件添加到工程中。

4、更改gui.h中的配置,添加该汉字的宏定义,如图5、显示汉字前更改需显示的字体,如图6、利用函数进行显示。

该方法移植方便,易实现同时显示多种字体,无字模冗余,占用存储空间最小。

图片显示uC/GUI提供了位图的解决方案,在GUI显示图片时,需先将其他格式的图片转换为bmp格式。

可利用windows系统自带的画图软件打开一个图片,再另存为bmp格式,继而转换为.c 格式文件加入到工程中。

其操作步骤如下:1、将其他格式的图片另存为bmp格式。

2、打开UCGUI源码自带的工具uC-GUI-BitmapConvert,选择相应参数,并转换为.c文件。

3、将该.c文件加入到工程中。

4、添加外部变量,并调用相应函数进行显示。

如图5、也可UCGUI提供的缩放函数可对图片进行缩放显示。

如图这里说一个技巧:如果无需在显示过程中对图片进行缩放,那么建议在第二步的时候就完成图片的缩放操作,以减少CPU的工作量。

控件显示UCGUI提供了很多控件,这里不再赘述,每个控件的操作方式类同。

这里以按钮控件作为举例。

第18章emWin(UCGUI)汉字显示方式一(FontCvt的使用)

第18章emWin(UCGUI)汉字显示方式一(FontCvt的使用)

第18章汉字显示方式一(FontCvt的使用)本期教程主要跟大家介绍官方的小工具Font Converter的使用方法,使用官方的字体转换工具,字体的显示效果要比网上那些针对UCGUI设计的字体生成工具好非常多。

4位抗锯齿的显示效果更是非常棒。

在开头先跟大家强调两点,一个是这个字体小工具必须的使用STemWin软件包里面的,SEGGER官网下载的和MDK安装目录里面带的都是评估版,另一点是在教程中我会要求大家将要显示汉字的C文件转换为UTF-8编码,我仅仅是指的将这个显示汉字的C文件转换为UTF-8编码,这点要切记。

18. 1 使用FontCvt生成字库C文件的方法18. 2 在开发板上面实现中文显示18. 3 总结18.1使用FontCvt生成字库C文件的方法我们先讲如何用这个软件生成部分的汉字数据,这里就以“安富莱电子”五个字进行说明。

18.1.1第一步:打开选择Standard,16bit unicode18.1.2第二步:打开选择字体和字体大小18.1.3第三步:选择禁止所有的字符18.1.4第四步:用unicode软件转换函数用中文转unicode的小软件得到“安福莱电子”这5个字的unicode编码我这里在百度上面找了一个网页应用。

18.1.5第五步:在FontCvt上使能这个五个字的编码在Font Converter软件上面使能这个五个字的unicode编码,以“安”字为例它的unicode编码是5b89,这里有两种办法找这个字。

方法一:直接的在软件里面查找,根据左边的unicode编码。

方法二:通过限制范围查找。

18.1.6第六步:然后点击保存为C文件要将前面的五个字全部找到并使能以后再做保存。

18.2在开发板上面实现中文显示下面我们用18.1小节讲的汉字生成方式生成7中类型的字体。

前三种是Standard的宋体,大小是16,36和72.第四种是144*144点阵的,有没有这么大的字体,需要手动往大小选项里面填写144,并选择右侧的Pixels。

GUI汉字显示原理

GUI汉字显示原理

GUI汉字显示原理1、在UCGUI中有两种类型字体, 一种是等宽字体(Monospaced Font),即字体当中所有字都是同一宽度,它在UCGUI中的相应结构体是GUI_FONT_MONO, 一种是均衡字体(Proportional font), 这种字体中的字都有自己独立的宽度, 字体内的每个字都可以有不同宽度, 它在UCGUI中的相应结构体是GUI_FONT_PROP, 对于等宽字体, 一般都是将所有字的点阵存放在一个数组中, 因为每个字都宽度相同. 对于均衡字体, 则要单独用数组来定义每个字符的点阵, 然后将每一个字符的宽高及点阵存为一个数组即字符信息(ucgui中对应结体为GUI_CHARINFO), 所有字符信息再存到一个数组当即称为字符集, 它包含每个字的字符信息(点阵高宽及一行占几个字节), 所谓一行占几个字节, 是指这个字体的点阵每一行有多少个字节, 它与宽度高度单位不同, 宽度高度的单位是象素数.2.另外特别指出的是, 在等宽字体中不仅所有字符宽度相同,高宽也是相等的; 对于均衡字体, 不仅可以宽度不同, 高度也可以不同, 每一行有多少个字节自然也不同, 在均衡字体中每一个字符都单独定义之后才组成字体的字符集.3.字符集的问题, 在UCGUI中每种字体含的字符集不同, 这个可以参看UCGUI手册中的"Standard Font"一章,这一章中对于字符集有如下描述:ASCII: Only ASCII characters 0x20-0x7E (0x7F).[仅包含0x20-0x7E这个范围内的ansii字符]1: ASCII characters and European extensions 0xA0 - 0xFF.[除0x20-0x7E这个范围内的ansii字符, 还有0xA0 - 0xFF这个范围内的欧洲字符集, 这里要指出美国英语只用到0x20-0x7E, 它只考虑了自己的须求, 没有考虑其它国家的须求, 在欧洲是有拉丁字符的, 所以欧洲国家扩展了剩余的0xA0 - 0xFF这个范围内的来表示欧洲的字符集, 其实我们国家的汉字也是在这个范围内扩展的, 不过我们用的是二个字节来表示一个汉字, 是因为汉字太多, 这区区94个值无法满足汉字的须求, 94*94就差不多了. 汉字用到的第一个值为0xb0a1(啊), 最后一个为0xf7fe(齄), 在机内码1当中只用到a1+15~a0+86这个范围的, 关于机内码是这个意思: 对于"啊"字模,机内码:(0xb0,0xa1), 0xb0为"啊"字的机内码1,0xa1为机内码2. 对于机内码2合使用是0xa1~0xff这个范围内的所有值, 关于机内码及汉字显示的原理及汉字库的构成, 本论坛中有专门的一篇文章介绍--"ucgui中处理汉字显示的说明", 请查看此贴, 这里不多说了, 所以范围是这样确定的.]HK: Hiragana and Katakana[日文平假名与片假名].1HK: ASCII, European extensions, Hiragana and Katakana[ansii,欧洲字符集,日文平假与片假].D: Digit fonts[数字及运算符号集].以上的ASCII/1/HK/1Hk/D都是字符集的简单代号.3. 回过头来再看你的GUI_Font__21_Prop2,GUI_Font__21_Prop1. 那么很容易理解,GUI_Font__21_Prop2是欧洲字符集, 范围当然是0xa0-0xff. GUI_Font__21_Prop1中存的是ASCII字符集. 至于GUI_Font__21_CharInfo中则存的是全部的字符集的点阵信息, 包含所有字符信息. 最后, 将字体中包含的所有字符集用链表连接起来. 再将这个链表头指针存到字体结构(GUI_FONT)中的存放均衡字体的指针(const GUI_FONT_PROP* pProp)当中, 这样在处理字符的显示, 可以在这链表中查找所要显示的字符是在哪一个字符集中, 从而找到它的字符信息(即点阵数据及宽高).typedef struct {GUI_DISPCHAR* pfDispChar;GUI_GETCHARDISTX* pfGetCharDistX;GUI_GETFONTINFO* pfGetFontInfo;GUI_ISINFONT* pfIsInFont;tGUI_ENC_APIList* pafEncode;U8 YSize;U8 YDist;U8 XMag;U8 YMag;union {//此联合处存放均衡或是待宽字符集信息...void *pFontData;const GUI_FONT_MONO* pMono;const GUI_FONT_PROP* pProp;} p;U8 Baseline;} GUI_FONT;在GUI_Font__21_Prop1中的(void GUI_FLASH *)&GUI_Font__21_Prop2/* pointer to next GUI_FONT_PROP */在GUI_Font__21_Prop2中的(void GUI_FLASH *)&GUI_Font__21_Prop3/* pointer to next GUI_FONT_PROP */在GUI_FONT_MONO当中的成员next就是指向一下字符集的...这个链表是人工写成的.....链表最后一个成员的next指向空....这个链表的构造, 其实还是为了使用, 所以要理解它, 就要理解是如何用的.均衡字体的显示, 是在GUIPROPAA_DispChar这个函数中处理的, 要理解链表的构造就要理解这个函数,下面做简要的分析....void GUIPROPAA_DispChar(U16P c) {int BytesPerLine;GUI_DRAWMODE DrawMode = GUI_Context.TextMode;const GUI_FONT_PROP* pProp = GUIPROP_FindChar(GUI_Context.pAFont->p.pProp, c);if (pProp) {GUI_DRAWMODE OldDrawMode;const GUI_CHARINFO* pCharInfo = pProp->paCharInfo+(c-pProp->First);BytesPerLine = pCharInfo->BytesPerLine;OldDrawMode = LCD_SetDrawMode(DrawMode);Draw ( GUI_Context.DispPosX, GUI_Context.DispPosY,(pCharInfo->XSize+1)/2,GUI_Context.pAFont->YSize,BytesPerLine,(U8 const*) pCharInfo->pData);LCD_SetDrawMode(OldDrawMode); /* Restore draw mode */ GUI_Context.DispPosX += (pCharInfo->XDist+1)/2;}}而理解GUIPROPAA_DispChar的重点, 就是要理解它当中调用的用来寻找要显示的字符的字符信息的函数GUIPROP_FindChar, GUIPROP_FindChar主要是寻找字符所在的字符集(其实这个字符集在汉字应用当中,有些不同.在hzk12.c中, 作者是将汉字接区来分集的, 下面我们以hzk12.c 中的构造来讲解字符集链表:hzk12.c 中共分成(0xa1a1~0xa1fe),(0xa2a1~0xa2fe)...(0xf7a1~0xf7fe)共分成86个字集, 另外加上(0x0020, 0x007f)这个ANSCII字符集, hzk12.c中的链表中就其有87个字符集, 这里的字符集的意义就不再是一个标准的字符集了, 而只能称之为字符的集合而已, 没有严格意义上的字符集的意思).hzk12.c中, 字符集链表构成为: 字符集链表第一个元素为ascii字符集,第二个为机内码处于(0xa1a1~0xa1fe)间的汉字集, 最后一个为(0xf7a1,0xf7fe)....了解了汉字库的这个字符集链表的构成, 那么现在来看一下如何寻找一个要显示的字符处于哪个字符集当中, 找了那个字符集才能找到这个字符的字符信息....static const GUI_FONT_PROP* GUIPROP_FindChar(const GUI_FONT_PROP* pProp, U16P c) {for (pProp = GUI_Context.pAFont->p.pProp; pProp; pProp=(const GUI_FONT_PROP*) pProp->pNext) {if ((c>=pProp->First) && (c<=pProp->Last))break;}return pProp;}GUIPROP_FindChar 其实就是查找字符的机内码是位于哪个字符集之间, 比如寻找"啊"字, 机内码为0xb0a1,那么由上查找, 就可以知道它是位于链表中第16(0xb0-0xa1=16)个字符集(机内码处于0xb0a1~0xb0fe)当中, 那么就返回这个字符集的指针. 找到了要显示的字符所处的字符集, 再根据:const GUI_CHARINFO* pCharInfo = pProp->paCharInfo+(c-pProp->First);c-pProp->First即为该字符在此字符集中的偏移, pProp->paCharInfo为该字符集中第一个字符地址...这样就找到了要显示的字符的字符信息了(宽高及点阵数等), 理解了这个过程, 那么反过来理解这个字符集为何要如此构造, 就比较容易了...比如说: 为什么要将汉字分成86个字符集合? 这是由于汉字的机内码并没有用到所有的0xffff--xa1a1=0x5e5e中连续的值, 而是间断的, 0xa1a1~0xa1fe用到了, 0xa200~0xa2a1这段当中的值不能用(因为机内码2小于0xa1了), 只能用0xa2a1~0xa2fe, 所以这个特性决定了汉字的机内码分布是显区段的, 不能用一个单一的GUI_FONT_PROP 结点来表示出所有的字符集, 因为汉字是区间分布的, 不是连续的.比如说, 如下所示:GUI_FLASH const GUI_FONT_PROP GUI_FontHZ12_Propa1= {0xa1a1,0xfefe,&GUI_FontHZ12_CharInfo[ 96],(void *)&GUI_FontHZ12_Propa2};用以下一个结点来表示所有汉字, 如同ACSII, 那么我们分析一下它为什么不可以:首先对于区间(0xa1a1~0xa1fe)这第一个区间, 在以上的结构下, 这个区间内的字符还是能够正确找到所要显示的字符信息. 但对于(0xa2a1~0xa2fe)这个区间的, pProp->paCharInfo+(c-pProp->First)显然无法找到字符信息. 这是GUI_FontHZ12_CharInfo 这个所有字符信息集数组的结构决定的, 因为汉字未用的区间的在它上面没有体现, 它上面存放的是将分隔开的汉字区间连在一起的, 这样你就无法根据pProp->paCharInfo+(c-pProp->First)来找到字符的位置了....[ucgui原创]在UCGUI中增加汉字显示的说明.在UCGUI中增加汉字显示的说明.作者: ucguiemail:*************home:版本: v1.0.0.1UCGUI中本身只支持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文所使用。

ucGUI加载“完整”外部字库的方法

ucGUI加载“完整”外部字库的方法

ucGUI加载“完整”外部字库的方法ucGUI加载“完整”外部字库的方法(1)——从外扩NOR Flash中加载CPU:LPC2478NOR Flash:MX29LV640EBtypedef __packed struct {U8 XSize;U8 XDist;U8 BytesPerLine;const unsigned char GUI_UNI_PTR * pData;} GUI_CHARINFO;在我的平台下,外部NOR Flash的起始地址是0x80000000,其容量是8MB。

我使用ucGUI提供的字库工具生成的4位抗锯齿字库大小为1.8M字节(此为经过计算后纯字库数据的大小)。

考虑到字库内容的连续性,在NOR Flash中为字库存储分配一个固定的区域,在我的工程中将其配置为0x80600000,从该地址开始还有2M的存储空间。

程序中做如下定义(代码中的一些数字的意义后文解释):#define GUI_FONT_HWZS_NORFLASH_BASE (0x80600000) #define GUI_FONT_HWZS_PROP_SIZE (1008)#define GUI_FONT_HWZS_CHARINFO_SIZE (48167)#define GUI_FONT_HWZS_DATA_SIZE (1806048)GUI_FONT_PROP *GUI_Font_hwzs_22AA4_Prop = (GUI_FONT_PROP *)(GUI_FONT_HWZS_NORFLASH_BASE);GUI_CHARINFO *GUI_Font_hwzs_22AA4_CharInfo = (GUI_CHARINFO *)(GUI_FONT_HWZS_NORFLASH_BASE + GUI_FONT_HWZS_PROP_SIZE);char *GUI_Font_hwzs_22AA4_CharData =(char *)(GUI_FONT_HWZS_NORFLASH_BASE +GUI_FONT_HWZS_PROP_SIZE + GUI_FONT_HWZS_CHARINFO_SIZE);GUI_FLASH const GUI_FONT GUI_Font_hwzs_22AA4 ={GUIPROP_AA4_DispChar ,GUIPROP_AA4_GetCharDistX ,GUIPROP_AA4_GetFontInfo ,GUIPROP_AA4_IsInFont ,&GUI_ENC_APIList_SJIS ,24 /* height of font */ ,24 /* space of font y */ ,1 /* magnification x */ ,1 /* magnification y */ ,(void GUI_FLASH *)((GUI_FONT_PROP *)(GUI_FONT_HWZS_NORFLASH_BASE)) };借助Visual Studio 2008进行了字库二进制文件的生成。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

关于ucgui的字库1、在UCGUI中有两种类型字体, 一种是等宽字体(Monospaced Font),即字体当中所有字都是同一宽度,它在UCGUI中的相应结构体是GUI_FONT_MONO, 一种是均衡字体(Proportional font), 这种字体中的字都有自己独立的宽度, 字体内的每个字都可以有不同宽度, 它在UCGUI中的相应结构体是GUI_FONT_PROP, 对于等宽字体, 一般都是将所有字的点阵存放在一个数组中, 因为每个字都宽度相同. 对于均衡字体, 则要单独用数组来定义每个字符的点阵, 然后将每一个字符的宽高及点阵存为一个数组即字符信息(ucgui中对应结体为GUI_CHARINFO), 所有字符信息再存到一个数组当即称为字符集, 它包含每个字的字符信息(点阵高宽及一行占几个字节), 所谓一行占几个字节, 是指这个字体的点阵每一行有多少个字节, 它与宽度高度单位不同, 宽度高度的单位是象素数.2.另外特别指出的是, 在等宽字体中不仅所有字符宽度相同,高宽也是相等的; 对于均衡字体, 不仅可以宽度不同, 高度也可以不同, 每一行有多少个字节自然也不同, 在均衡字体中每一个字符都单独定义之后才组成字体的字符集.3.字符集的问题, 在UCGUI中每种字体含的字符集不同, 这个可以参看UCGUI手册中的"Standard Font"一章,这一章中对于字符集有如下描述:ASCII: Only ASCII characters 0x20-0x7E (0x7F).[仅包含0x20-0x7E这个范围内的ansii字符]1: ASCII characters and European extensions 0xA0 - 0xFF.[除0x20-0x7E这个范围内的ansii字符, 还有0xA0 - 0xFF这个范围内的欧洲字符集, 这里要指出美国英语只用到0x20-0x7E, 它只考虑了自己的须求, 没有考虑其它国家的须求, 在欧洲是有拉丁字符的, 所以欧洲国家扩展了剩余的0xA0 - 0xFF这个范围内的来表示欧洲的字符集, 其实我们国家的汉字也是在这个范围内扩展的, 不过我们用的是二个字节来表示一个汉字, 是因为汉字太多, 这区区94个值无法满足汉字的须求, 94*94就差不多了. 汉字用到的第一个值为0xb0a1(啊), 最后一个为0xf7fe(齄), 在机内码1当中只用到a1+15~a0+86这个范围的, 关于机内码是这个意思: 对于"啊"字模,机内码:(0xb0,0xa1), 0xb0为"啊"字的机内码1,0xa1为机内码2. 对于机内码2合使用是0xa1~0xff这个范围内的所有值, 关于机内码及汉字显示的原理及汉字库的构成, 本论坛中有专门的一篇文章介绍--"ucgui中处理汉字显示的说明",请查看此贴, 这里不多说了, 所以范围是这样确定的.]HK: Hiragana and Katakana[日文平假名与片假名].1HK: ASCII, European extensions, Hiragana and Katakana[ansii,欧洲字符集,日文平假与片假].D: Digit fonts[数字及运算符号集].以上的ASCII/1/HK/1Hk/D都是字符集的简单代号.3. 回过头来再看你的GUI_Font__21_Prop2,GUI_Font__21_Prop1. 那么很容易理解,GUI_Font__21_Prop2是欧洲字符集, 范围当然是0xa0-0xff. GUI_Font__21_Prop1中存的是ASCII字符集. 至于GUI_Font__21_CharInfo中则存的是全部的字符集的点阵信息, 包含所有字符信息. 最后, 将字体中包含的所有字符集用链表连接起来. 再将这个链表头指针存到字体结构(GUI_FONT)中的存放均衡字体的指针(constGUI_FONT_PROP* pProp)当中, 这样在处理字符的显示, 可以在这链表中查找所要显示的字符是在哪一个字符集中, 从而找到它的字符信息(即点阵数据及宽高).typedef struct {GUI_DISPCHAR* pfDispChar;GUI_GETCHARDISTX* pfGetCharDistX;GUI_GETFONTINFO* pfGetFontInfo;GUI_ISINFONT* pfIsInFont;tGUI_ENC_APIList* pafEncode;U8 YSize;U8 YDist;U8 XMag;U8 YMag;union {//此联合处存放均衡或是待宽字符集信息...void *pFontData;const GUI_FONT_MONO* pMono;const GUI_FONT_PROP* pProp;} p;U8 Baseline;} GUI_FONT;在GUI_Font__21_Prop1中的(void GUI_FLASH *)&amp;GUI_Font__21_Prop2/* pointer to nextGUI_FONT_PROP */在GUI_Font__21_Prop2中的(void GUI_FLASH*)&amp;GUI_Font__21_Prop3/* pointer to nextGUI_FONT_PROP */在GUI_FONT_MONO当中的成员next就是指向一下字符集的...这个链表是人工写成的.....链表最后一个成员的next指向空....这个链表的构造, 其实还是为了使用, 所以要理解它, 就要理解是如何用的.均衡字体的显示, 是在GUIPROPAA_DispChar这个函数中处理的, 要理解链表的构造就要理解这个函数,下面做简要的分析....void GUIPROPAA_DispChar(U16P c) {int BytesPerLine;GUI_DRAWMODE DrawMode = GUI_Context.TextMode;const GUI_FONT_PROP* pProp =GUIPROP_FindChar(GUI_Context.pAFont-&gt;p.pProp, c);if (pProp) {GUI_DRAWMODE OldDrawMode;const GUI_CHARINFO* pCharInfo =pProp-&gt;paCharInfo+(c-pProp-&gt;First);BytesPerLine = pCharInfo-&gt;BytesPerLine;OldDrawMode = LCD_SetDrawMode(DrawMode);Draw ( GUI_Context.DispPosX, GUI_Context.DispPosY,(pCharInfo-&gt;XSize+1)/2,GUI_Context.pAFont-&gt;YSize,BytesPerLine,(U8 const*) pCharInfo-&gt;pData);LCD_SetDrawMode(OldDrawMode); /* Restore draw mode */GUI_Context.DispPosX += (pCharInfo-&gt;XDist+1)/2; }}而理解GUIPROPAA_DispChar的重点, 就是要理解它当中调用的用来寻找要显示的字符的字符信息的函数GUIPROP_FindChar, GUIPROP_FindChar主要是寻找字符所在的字符集(其实这个字符集在汉字应用当中,有些不同.在hzk12.c中, 作者是将汉字接区来分集的, 下面我们以hzk12.c中的构造来讲解字符集链表:hzk12.c 中共分成(0xa1a1~0xa1fe),(0xa2a1~0xa2fe)...(0xf7a1~0xf7fe)共分成86个字集, 另外加上(0x0020, 0x007f)这个ANSCII字符集, hzk12.c中的链表中就其有87个字符集, 这里的字符集的意义就不再是一个标准的字符集了, 而只能称之为字符的集合而已, 没有严格意义上的字符集的意思).hzk12.c中, 字符集链表构成为: 字符集链表第一个元素为ascii字符集,第二个为机内码处于(0xa1a1~0xa1fe)间的汉字集, 最后一个为(0xf7a1,0xf7fe)....了解了汉字库的这个字符集链表的构成, 那么现在来看一下如何寻找一个要显示的字符处于哪个字符集当中, 找了那个字符集才能找到这个字符的字符信息....static const GUI_FONT_PROP* GUIPROP_FindChar(constGUI_FONT_PROP* pProp, U16P c) {for (pProp = GUI_Context.pAFont-&gt;p.pProp; pProp; pProp=(const GUI_FONT_PROP*) pProp-&gt;pNext) { if ((c&gt;=pProp-&gt;First) &amp;&amp;(c&lt;=pProp-&gt;Last))break;}return pProp;}GUIPROP_FindChar 其实就是查找字符的机内码是位于哪个字符集之间, 比如寻找"啊"字, 机内码为0xb0a1,那么由上查找, 就可以知道它是位于链表中第16(0xb0-0xa1=16)个字符集(机内码处于0xb0a1~0xb0fe)当中, 那么就返回这个字符集的指针. 找到了要显示的字符所处的字符集, 再根据:const GUI_CHARINFO* pCharInfo =pProp-&gt;paCharInfo+(c-pProp-&gt;First);c-pProp-&gt;First即为该字符在此字符集中的偏移,pProp-&gt;paCharInfo为该字符集中第一个字符地址...这样就找到了要显示的字符的字符信息了(宽高及点阵数等), 理解了这个过程, 那么反过来理解这个字符集为何要如此构造, 就比较容易了...比如说: 为什么要将汉字分成86个字符集合? 这是由于汉字的机内码并没有用到所有的0xffff--xa1a1=0x5e5e中连续的值, 而是间断的, 0xa1a1~0xa1fe用到了, 0xa200~0xa2a1这段当中的值不能用(因为机内码2小于0xa1了), 只能用0xa2a1~0xa2fe, 所以这个特性决定了汉字的机内码分布是显区段的, 不能用一个单一的GUI_FONT_PROP结点来表示出所有的字符集, 因为汉字是区间分布的, 不是连续的.比如说, 如下所示:GUI_FLASH const GUI_FONT_PROPGUI_FontHZ12_Propa1= {0xa1a1,0xfefe,&amp;GUI_FontHZ12_CharInfo[ 96],(void *)&amp;GUI_FontHZ12_Propa2};用以下一个结点来表示所有汉字, 如同ACSII, 那么我们分析一下它为什么不可以:首先对于区间(0xa1a1~0xa1fe)这第一个区间, 在以上的结构下, 这个区间内的字符还是能够正确找到所要显示的字符信息. 但对于(0xa2a1~0xa2fe)这个区间的,pProp-&gt;paCharInfo+(c-pProp-&gt;First)显然无法找到字符信息. 这是GUI_FontHZ12_CharInfo这个所有字符信息集数组的结构决定的, 因为汉字未用的区间的在它上面没有体现, 它上面存放的是将分隔开的汉字区间连在一起的, 这样你就无法根据pProp-&gt;paCharInfo+(c-pProp-&gt;First)来找到字符的位置了....[ucgui原创]在UCGUI中增加汉字显示的说明.在UCGUI中增加汉字显示的说明.作者: ucguiemail: ucgui@home: 版本: v1.0.0.1UCGUI中本身只支持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文所使用。

相关文档
最新文档