分类: LINUX
2011-10-12 15:03:43
摘要:
在ARM7系统中,都不会有足够大的程序存储器来存放大容量的汉字库,因此当系统中要用到汉字库时,需要将其存储在外部的FLASH Memory,而ucgui的字符显示函数是直接从程序存储器取数据的,因此需要在原始代码里增加一个接口,来指向外部的FLASH Memory。
简介:
ucgui中,字符显示的底层函数是 GUICharP.c 中的 void GUIPROP_DispChar(U16P c) 函数,我们将这个函数修改如下:
然后再加入FLASH操作的底层驱动(这里用的是SPI FLASH)
我们知道,ucgui访问字库的时候,是根据字库文件的索引表来查找汉字数据地址的,因此汉字库文件中的索引也要修改,以汉字库32为例
在GUI.H中添加汉字库在flash中的首地址,及字库声明
然后将字库下载到SPI FLASH中,注意三个字库的起始地址与GUI.h中定义的应该是一样的。还有字库生成时,也应该是标准的汉字库,满足 oft = base + (((c>>8) - 0xa1) * 94 + ((c&0xff) - 0xa1)) * BytesPerFont; 的计算方式。
结语:
有了将汉字库定义到外部FLASH的方法,则可以定义任意汉字库,不受程序FLASH大小的限制了。
附件:
-----------------------------------------------------------------------
手头的一个项目需要用到uCGUI看了hzk12.c,hzk16.c由于全部编译进stm32的flash,根本够用,于是查了一下资料,并参考了一些代码,实现了自定义字库的方法。该方法可以扩展任意字体。
需要修改的地方有三个:
1、GUItype.h
在该文件加入以下内容
DECLARE_FONT(PROP_X);
#define GUI_FONTTYPE_PROP_USER \
GUIPROP_X_DispChar, \
GUIPROP_X_GetCharDistX, \
GUIMONO_GetFontInfo, \
GUIMONO_IsInFont, \
(tGUI_ENC_APIList*)0
2、GUI_UC_EncodeNone.c
该文件修改为以下内容
/*
*********************************************************************************************************
* uC/GUI
* Universal graphic software for embedded applications
*
* (c) Copyright 2002, Micrium Inc., Weston, FL
* (c) Copyright 2002, SEGGER Microcontroller Systeme GmbH
*
* 礐/GUI is protected by international copyright laws. Knowledge of the
* source code may not be used to write a similar product. This file may
* only be used in accordance with a license and should not be redistributed
* in any way. We appreciate your understanding and fairness.
*
----------------------------------------------------------------------
File : GUI_UC_EncodeNone.c
Purpose : Encoding routines for non unicode systems (default)
---------------------------END-OF-HEADER------------------------------
*/
#include "GUI_Protected.h"
/*********************************************************************
*
* Static code
*
**********************************************************************
*/
/*********************************************************************
*
* _GetCharCode
*
* Purpose:
* Return the UNICODE character code of the current character.
*/
static U16 _GetCharCode(const char GUI_UNI_PTR * s) {
if((*s) > 0xA0)
{
return *(const U16 GUI_UNI_PTR *)s;
}
return *(const U8 GUI_UNI_PTR *)s;
}
/*********************************************************************
*
* _GetCharSize
*
* Purpose:
* Return the number of bytes of the current character.
*/
static int _GetCharSize(const char GUI_UNI_PTR * s) {
GUI_USE_PARA(s);
if((*s) > 0xA0)
{
return 2;
}
return 1;
}
/*********************************************************************
*
* _CalcSizeOfChar
*
* Purpose:
* Return the number of bytes needed for the given character.
*/
static int _CalcSizeOfChar(U16 Char) {
GUI_USE_PARA(Char);
if(Char > 0xA0A0)
{
return 2;
}
return 1;
}
/*********************************************************************
*
* _Encode
*
* Purpose:
* Encode character into 1/2/3 bytes.
*/
static int _Encode(char *s, U16 Char) {
if(Char > 0xA0A0)
{
*((U16 *)s) = (U16)(Char);
return 2;
}
*s = (U8)(Char);
return 1;
}
/*********************************************************************
*
* Static data
*
**********************************************************************
*/
/*********************************************************************
*
* _API_Table
*/
const GUI_UC_ENC_APILIST GUI__API_TableNone = {
_GetCharCode, /* return character code as U16 */
_GetCharSize, /* return size of character: 1 */
_CalcSizeOfChar, /* return size of character: 1 */
_Encode /* Encode character */
};
/*********************************************************************
*
* Exported code
*
**********************************************************************
*/
/*********************************************************************
*
* GUI_UC_SetEncodeNone
*/
void GUI_UC_SetEncodeNone(void) {
GUI_LOCK();
GUI_Context.pUC_API = &GUI__API_TableNone;
GUI_UNLOCK();
}
/*************************** End of file ****************************/
3、新建文件“GUICharPEx.c”,并加入工程
内容如下
#include
#include "GUI_Private.h"
#include "ff.h"
/*********************************************************************
*
* Static code
*
**********************************************************************
*/
//字模数据的暂存数组,以单个字模的最大字节数为设定值
#define BYTES_PER_FONT 128
static U8 GUI_FontDataBuf[BYTES_PER_FONT];
extern void GUI_X_GetFontData(char *font, U32 oft, U8 *ptr, U8 bytes);
//从外部存储器取得字模数据
static void GUI_GetDataFromMemory(const GUI_FONT_PROP GUI_UNI_PTR *pProp, U16P c)
{
U8 BytesPerFont;
U32 oft;
char *font = (char *)pProp->paCharInfo->pData;
BytesPerFont = GUI_Context.pAFont->YSize * pProp->paCharInfo->BytesPerLine; //每个字模的数据字节数
if (BytesPerFont > BYTES_PER_FONT){BytesPerFont = BYTES_PER_FONT;}
if (c < 0x80) //英文字符地址偏移算法
{
oft = c * BytesPerFont;
}
else
{
oft = ((((c >> 8)-0xA1)) + ((c & 0xFF)-0xA1) * 94)* BytesPerFont; //中文字符地址偏移算法包括符号
}
GUI_X_GetFontData(font, oft, GUI_FontDataBuf, BytesPerFont);
}
/*********************************************************************
*
* Public code
*
**********************************************************************
*/
/*********************************************************************
*
* 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_X_DispChar(U16P c)
{
int BytesPerLine;
GUI_DRAWMODE DrawMode = GUI_Context.TextMode;
const GUI_FONT_PROP GUI_UNI_PTR *pProp = GUI_Context.pAFont->p.pProp;
//搜索定位字库数据信息
for (; pProp; pProp = pProp->pNext)
{
if ((c >= pProp->First) && (c <= pProp->Last))break;
}
if (pProp)
{
GUI_DRAWMODE OldDrawMode;
const GUI_CHARINFO GUI_UNI_PTR * pCharInfo = pProp->paCharInfo;
GUI_GetDataFromMemory(pProp, c);//取出字模数据
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[0],
&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;
}
}
/*********************************************************************
*
* GUIPROP_GetCharDistX
*/
int GUIPROP_X_GetCharDistX(U16P c)
{
const GUI_FONT_PROP GUI_UNI_PTR * pProp = GUI_Context.pAFont->p.pProp;
for (; pProp; pProp = pProp->pNext)
{
if ((c >= pProp->First) && (c <= pProp->Last))break;
}
return (pProp) ? (pProp->paCharInfo)->XSize * GUI_Context.pAFont->XMag : 0;
}
GUI_CONST_STORAGE GUI_CHARINFO GUI_FontHZ16_CharInfo[2] =
{
{ 8, 8, 1, (void *)"sys/font/en12.dzk" }, //&ASC_ROM_8X16
{ 16, 16, 2, (void *)"sys/font/st12.dzk"}, //&HZ_ROM_16X16
};
GUI_CONST_STORAGE GUI_FONT_PROP GUI_FontHZ16_PropHZ= {
0xA1A1,
0xF7FE,
&GUI_FontHZ16_CharInfo[1],
(void *)0,
};
GUI_CONST_STORAGE GUI_FONT_PROP GUI_FontHZ16_PropASC= {
0x0000,
0x007F,
&GUI_FontHZ16_CharInfo[0],
(void GUI_CONST_STORAGE *)&GUI_FontHZ16_PropHZ,
};
GUI_CONST_STORAGE GUI_FONT GUI_FontHZ16 =
{
GUI_FONTTYPE_PROP_USER,
16,
16,
1,
1,
(void GUI_CONST_STORAGE *)&GUI_FontHZ16_PropASC
};
GUI_CONST_STORAGE GUI_FONT GUI_FontHZ16x2 =
{
GUI_FONTTYPE_PROP_USER,
16,
16,
2,
2,
(void GUI_CONST_STORAGE *)&GUI_FontHZ16_PropASC
};
/*---------------------------------------------------------------------------*/
/*字库外部函数部分-----------------------------------------------------------*/
void GUI_X_GetFontData(char* font, U32 oft, U8 *ptr, U8 bytes)
{
FIL fsrc; // 定义文件操作类
FRESULT res; // 定义操作结果变量
UINT br; // 定义读写数量变量
res = f_open(&fsrc, font, FA_OPEN_EXISTING | FA_READ); //打开字库文件
if(res != FR_OK)
{
//打开失败显示问号
}
res = f_lseek(&fsrc,oft); //找到首地址
res = f_read(&fsrc, ptr, bytes, &br); //读取32个字库点阵数据
res = f_close(&fsrc); //关闭字体
}
这样以后就可以设置新建的字体“GUI_FontHZ16”来显示汉字或英文或混合显示了
注意事项SD卡用的文件系统——fatFS,所以“FF.h”是文件系统的头文件,可以扩展自己的方法来获取字模。
适当的修改或添加内容就可以实现不同字体,不同的大小的字体了。
上传用到的字库,来自UCDOS,金山的DOS系统里面的。要注意的是,这两个字体是完整的,也就是说,“en12.dzk”偏移是重0开始
“st12.dzk”偏移是从"0xA1A1"开始,包含符号区和未使用区。
注意计算偏移地址时要正确,可以参考上面代码的这里:
if (c < 0x80) //英文字符地址偏移算法
{
oft = c * BytesPerFont;
}
else
{
oft = ((((c >> 8)-0xA1)) + ((c & 0xFF)-0xA1) * 94)* BytesPerFont; //中文字符地址偏移算法包括符号
}
其中“BytesPerFont”是uCGUI计算出来的每个字所需要的字节数,这里英文是16,中文是32。
所使用的字库文件:
点击此处下载 ourdev_622779PG8Y3X.rar(文件大小:139K) (原文件名:zk12.rar)