|
楼主 |
发表于 2013-10-22 10:30:51
|
显示全部楼层
UCGUI教程三——UCGUI外部字库
实验目的:增加UCGUI外部汉字库,实现汉字显示
主要内容:
一、了解UCGUI字库相关函数和数据结构
二、了解UCGUI字库显示调用过程
三、增加汉字显示代码,实现汉字显示
一、了解UCGUI字库相关函数和数据结构
1、GUI_FONTTYPE_PROP宏定义
首先了解下UCGUI字库显示的相关函数,在GUIType.h里有以下一段代码。
/* PROP: Proportional fonts */
DECLARE_FONT(PROP); //声明一组函数
#define GUI_FONTTYPE_PROP \
GUIPROP_DispChar, \
GUIPROP_GetCharDistX, \
GUIPROP_GetFontInfo, \
GUIPROP_IsInFont, \
(tGUI_ENC_APIList*)0 //以上是宏GUI_FONTTYPE_PROP的定义,宏展开后为上面几个函数名。
实际使用时GUI_FONTTYPE_PROP会被插入到字库的GUI_FONT 结构体里,如GUI_Font24B_ASCII的定义如下:
GUI_CONST_STORAGE GUI_FONT GUI_Font24B_ASCII = {
GUI_FONTTYPE_PROP /* type of font */
,24 /* height of font */
,24 /* space of font y */
,1 /* magnification x */
,1 /* magnification y */
,{&GUI_Font24B_ASCII_Prop1}
,19, 11, 15
};
也就说GUI_FONTTYPE_PROP是字库对应的一组关于显示的函数。
2、DECLARE_FONT宏定义
上面还有个DECLARE_FONT(PROP),这个DECLARE_FONT宏在GUIType.h里定义如下
#define DECLARE_FONT(Type) \
void GUI##Type##_DispChar (U16P c); \
int GUI##Type##_GetCharDistX(U16P c); \
void GUI##Type##_GetFontInfo (const GUI_FONT GUI_UNI_PTR * pFont, GUI_FONTINFO * pfi); \
char GUI##Type##_IsInFont (const GUI_FONT GUI_UNI_PTR * pFont, U16 c)
这里主要是要弄明白##的含义:
##是C语言宏定义中的连接符,用来把前后两个参数连接起来。
例如DECLARE_FONT(PROP);
宏展开后为以下一段代码:
void GUIPROP_DispChar (U16P c); \
int GUIPROP_GetCharDistX(U16P c); \
void GUIPROP_GetFontInfo (const GUI_FONT GUI_UNI_PTR * pFont, GUI_FONTINFO * pfi); \
char GUIPROP_IsInFont (const GUI_FONT GUI_UNI_PTR * pFont, U16 c);
那么DECLARE_FONT(PROP);是相当于声明上面几个字库显示相关函数。
3、GUI_FONT结构体的定义
GUI_FONT结构体的定义如下:
struct GUI_FONT {
GUI_DISPCHAR* pfDispChar; //函数指针,显示字符函数
GUI_GETCHARDISTX* pfGetCharDistX; //函数指针,获得字符宽度
GUI_GETFONTINFO* pfGetFontInfo; //函数指针,获得字符信息
GUI_ISINFONT* pfIsInFont; //函数指针,判断字符是否在字库编码内
const tGUI_ENC_APIList* pafEncode; //结构体指针,一组字符编码相关函数。若为空,则默认用GUI_UC_EncodeNone.c里的函数
U8 YSize; //字库的高度
U8 YDist; //字库的Y间距
U8 XMag; //X放大倍数
U8 YMag; //Y放大倍数
union {
const void GUI_UNI_PTR * pFontData;
const GUI_FONT_MONO GUI_UNI_PTR * pMono;
const GUI_FONT_PROP GUI_UNI_PTR * pProp; //GUI_FONT_PROP结构体指针
} p;
U8 Baseline;
U8 LHeight; /* height of a small lower case character (a,x) */
U8 CHeight; /* height of a small upper case character (A,X) */
};
4、GUI_FONT_PROP结构体
typedef struct GUI_FONT_PROP {
U16P First; /* first character */ //字库里的第一个字符的编码
U16P Last; /* last character */ //字库里的最后一个字符的编码
const GUI_CHARINFO GUI_UNI_PTR * paCharInfo; /* address of first character */ //第一个字符的GUI_CHARINFO结构信息
const struct GUI_FONT_PROP GUI_UNI_PTR * pNext; /* pointer to next */ //结构体指针,指向下一个GUI_FONT_PROP结构
} GUI_FONT_PROP;
5、GUI_CHARINFO结构体
typedef struct {
U8 XSize; //字库的宽度
U8 XDist; //字库的X间距
U8 BytesPerLine; //一行点阵数据占用的字节数。如16x16点阵,一行占用2个字节
const unsigned char GUI_UNI_PTR * pData; //指向字库点阵表首地址
} GUI_CHARINFO;
二、了解UCGUI字库显示调用过程
如在程序里调用GUI_DispStringAt("abc", 0, 0); 会调用下面的一系列函数,最终调用字库对应的pfDispChar进行显示:
GUI_DispStringAt -> GUI_DispString -> GUI__DispLine -> _DispLine -> GUI_Context.pAFont->pfDispChar(Char)
pfDispChar即是字库对应的显示函数,很多字库是调用GUIPROP_DispChar来显示,GUIPROP_DispChar定义如下:
void GUIPROP_DispChar(U16P c) {
int BytesPerLine; //一行点阵数据占用的字节数
GUI_DRAWMODE DrawMode = GUI_Context.TextMode; //字符显示模式,是否透明显示等
const GUI_FONT_PROP GUI_UNI_PTR * pProp = GUIPROP_FindChar(GUI_Context.pAFont->p.pProp, c); //查找字符对应的GUI_FONT_PROP结构体指针
if (pProp) {
GUI_DRAWMODE OldDrawMode;
const GUI_CHARINFO GUI_UNI_PTR * pCharInfo = pProp->paCharInfo+(c-pProp->First); //获得字符的pCharInfo信息。其中c-pProp->First是字符的paCharInfo结构体相对第一个字符paCharInfo的偏移
BytesPerLine = pCharInfo->BytesPerLine; //获得字符的一行点阵数据占用的字节数
OldDrawMode = LCD_SetDrawMode(DrawMode); //获得字符显示模式
LCD_DrawBitmap( GUI_Context.DispPosX, GUI_Context.DispPosY, //把字符点阵数据扫描到LCD上
pCharInfo->XSize,
GUI_Context.pAFont->YSize,
GUI_Context.pAFont->XMag,
GUI_Context.pAFont->YMag,
1, /* Bits per Pixel */
BytesPerLine,
pCharInfo->pData, //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;
}
}
三、增加汉字显示代码,实现汉字显示
1、首先定义汉字字库
首先增加文件hzk16.c,定义汉字字库GUI_CHARINFO,GUI_FONT_PROP,GUI_FONT 等结构体信息:
#include "..\core\GUI.H"
#ifndef GUI_FLASH
#define GUI_FLASH
#endif
extern GUI_FLASH const GUI_FONT GUI_FontHZ16;
GUI_FLASH const GUI_CHARINFO GUI_FontHZ16_CharInfo[] = {
{ 8, 8, 1, (void GUI_FLASH *)"0:/font/ASC16" },
{ 16, 16, 2, (void GUI_FLASH *)"0:/font/HZK16" },
};
GUI_FLASH const GUI_FONT_PROP GUI_FontHZ16_PropHZ= {
0xa1a1,
0xf7fe,
&GUI_FontHZ16_CharInfo[1],
(void *)0,
};
GUI_FLASH const GUI_FONT_PROP GUI_FontHZ16_PropASC= {
0x0020,
0x007f,
&GUI_FontHZ16_CharInfo[0],
(void GUI_FLASH *)&GUI_FontHZ16_PropHZ ,
};
GUI_FLASH const GUI_FONT GUI_FontHZ16 = {
GUI_FONTTYPE_PROP_XBF,
16,
16,
1,
1,
(void GUI_FLASH *)&GUI_FontHZ16_PropASC
};
然后在GUI.h里加入声明:
extern GUI_CONST_STORAGE GUI_FONT GUI_FontHZ16;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2、定义外部字库相关宏
在GUIType.h里增加以下宏定义,定义字库相关显示函数:
/* PROP: Proportional fonts */
DECLARE_FONT(PROP_XBF);
#define GUI_FONTTYPE_PROP_XBF \
GUIPROP_XBF_DispChar, \
GUIPROP_XBF_GetCharDistX, \
GUIPROP_XBF_GetFontInfo, \
GUIPROP_XBF_IsInFont, \
(tGUI_ENC_APIList*)0
3、修改GUI_UC_EncodeNone.c里面的代码,使系统支持GB2312汉字编码。
上面的(tGUI_ENC_APIList*)0表示用默认编码,当字体显示函数调用涉及到编码时,如果字体没有定义编码,则默认采用GUI_UC_EncodeNone.c里面的函数:
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 */
};
这里默认都是ASCII编码的,我们要增加汉字显示,所以要对_GetCharCode这几个函数进行修改。
/* File : GUI_UC_EncodeNone.c */
#include "GUI_Protected.h"
/**********************************************************************/
static U16 _GetCharCode(const char GUI_UNI_PTR * s) {
if(*s > 0xA0) //增加对汉字编码判断
return *(const U16 GUI_UNI_PTR *)s;
else
return *(const U8 GUI_UNI_PTR *)s;
}
/**********************************************************************/
static int _GetCharSize(const char GUI_UNI_PTR * s) {
GUI_USE_PARA(s);
if(*s > 0xA0) //增加对汉字编码判断
{
return 2;
}
else
{
return 1;
}
}
/**********************************************************************/
static int _CalcSizeOfChar(U16 Char) {
GUI_USE_PARA(Char);
if(Char > 0xA0) //增加对汉字编码判断
{
return 2;
}
else
{
return 1;
}
}
/**********************************************************************/
static int _Encode(char *s, U16 Char) {
if(Char > 0xA0) //增加对汉字编码判断
{
*(U16*)s = (U16)(Char);
return 2;
}
else
{
*s = (U8)(Char);
return 1;
}
}
/**********************************************************************/
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 */
};
/**********************************************************************/
void GUI_UC_SetEncodeNone(void) {
GUI_LOCK();
GUI_Context.pUC_API = &GUI__API_TableNone;
GUI_UNLOCK();
}
4、增加GUI_XBF_Prop.c,实现外部汉字库显示相关函数。
/*File : GUI_XBF_Prop.c */
#include <stddef.h> /* needed for definition of NULL */
#include "GUI_Private.h"
#include "ff.h"
/*********************************************************************
*
* GUIPROP_FindChar
*/
static const GUI_FONT_PROP GUI_UNI_PTR * GUIPROP_FindChar(const GUI_FONT_PROP GUI_UNI_PTR* pProp, U16P c) {
for (; pProp; pProp = pProp->pNext) {
if ((c>=pProp->First) && (c<=pProp->Last))
break;
}
return pProp;
}
/*********************************************************************
*
* _GetpCharData
*/
static const U8 * _GetpCharData(const GUI_FONT_PROP GUI_UNI_PTR * pProp, U16P c, U8 * pData) {
FIL fl;
U32 len;
U32 offset;
U8 byteOfDots;
U8 *fileName;
const GUI_CHARINFO GUI_UNI_PTR * pCharInfo = pProp->paCharInfo;
byteOfDots = GUI_Context.pAFont->YSize * pCharInfo->BytesPerLine;
fileName = (char *)pCharInfo->pData;
if (c < 0xA1)
{
offset = c * byteOfDots;
}
else
{
offset = 94 * ((c & 0xFF) - 0xA1) * byteOfDots + ((c >> 8) - 0xA1) * byteOfDots;
}
f_open (&fl, fileName, FA_READ);
f_lseek(&fl, offset);
f_read (&fl, pData, byteOfDots, &len);
f_close(&fl);
return 0;
}
/*********************************************************************
*
* Exported code
*
**********************************************************************
*/
/*********************************************************************
*
* GUI_XBF_DispChar
*/
void GUIPROP_XBF_DispChar(U16P c) {
U8 Data[128];
int BytesPerLine;
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 = pProp->paCharInfo;
BytesPerLine = pCharInfo->BytesPerLine;
_GetpCharData(pProp, c, Data);
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,
Data,
&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;
}
}
/*********************************************************************
*
* GUI_XBF_GetCharDistX
*/
int GUIPROP_XBF_GetCharDistX(U16P c) {
const GUI_FONT_PROP GUI_UNI_PTR * pProp = GUIPROP_FindChar(GUI_Context.pAFont->p.pProp, c);
return (pProp) ? (pProp->paCharInfo)->XSize * GUI_Context.pAFont->XMag : 0;
}
/*********************************************************************
*
* GUI_XBF_GetFontInfo
*/
void GUIPROP_XBF_GetFontInfo(const GUI_FONT GUI_UNI_PTR * pFont, GUI_FONTINFO * pfi) {
GUI_USE_PARA(pFont);
pfi->Flags = GUI_FONTINFO_FLAG_PROP;
}
/*********************************************************************
*
* GUI_XBF_IsInFont
*/
char GUIPROP_XBF_IsInFont(const GUI_FONT GUI_UNI_PTR * pFont, U16 c) {
const GUI_FONT_PROP GUI_UNI_PTR * pProp = GUIPROP_FindChar(pFont->p.pProp, c);
return (pProp==NULL) ? 0 : 1;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
程序已更新到网盘
百为STM32_UCGUI汉字显示.rar
运行图片
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|