本帖最后由 nicholasldf 于 2016-1-13 11:16 编辑
已经有很多移植例子了,为什么还要写一个? 因为看了很多例子,基本都是按照uCGUI的处理方式,需要一个GUI_UC_EncodeNone.c文件处理非unicode中文字体编码,原子提供的例子也是这样的方式,,但在我这里,显示有很多问题,可以说不能工作,至少STemWinV5.26和V5.28都有问题。这个移植例子是基于以往例子的改进版本。不知道之前的版本会不会如此。 GUI_Type.h和GUI.h定义了多个结构体,基于这些结构体,实现了各种字体的框架。 结构体GUI_FONT定义了整个字体的信息以及接口函数指针,如字体高度、宽度、显示该字体的接口函数、计算该字体字符串长度宽度的函数、判断某个字符是否属于该字体等等。当YDist>YSize时,相当于上下行字符之间插入间隔。 struct GUI_FONT { GUI_DISPCHAR* pfDispChar;//显示该字体单个字符的接口函数 GUI_GETCHARDISTX*pfGetCharDistX;//计算该字体单个字符的像素宽度 GUI_GETFONTINFO* pfGetFontInfo;//获取该字体的信息 GUI_ISINFONT* pfIsInFont;//判断某个字符是否属于该字体 GUI_GETCHARINFO * pfGetCharInfo; //获取该字体单个字符信息 const tGUI_ENC_APIList* pafEncode;//该字体字符串操作接口 U8 YSize; //该字体的Y轴高度,指的是显示信息高度 U8 YDist; //该字体的Y轴距离,指的是字体占用高度,YDist>=YSize char XMag; //该字体的X轴放大 char YMag; //该字体的Y轴放大 union { constvoid GUI_UNI_PTR * pFontData; constGUI_FONT_MONO GUI_UNI_PTR * pMono; constGUI_FONT_PROP GUI_UNI_PTR * pProp; } p; //多功能指针 U8 Baseline; //该字体Y轴行数? U8 LHeight; /* height of a small lower case character(a,x) */ U8 CHeight; /* height of a small upper case character(A,X) */ };
下面定义了GUI_FONT结构体里面的函数指针类型。 typedefvoid GUI_DISPCHAR (U16 c); typedefint GUI_GETCHARDISTX(U16P c, int * pSizeX); typedefvoid GUI_GETFONTINFO (const GUI_FONT * pFont, GUI_FONTINFO * pfi); typedefchar GUI_ISINFONT (const GUI_FONT *pFont, U16 c); typedefint GUI_GETCHARINFO (U16P c,GUI_CHARINFO_EXT * pInfo); 结构体GUI_FONTINFO定义了字体信息,其中Baseline,LHeight,CHeight在GUI_FONT结构体里面也有对应的成员。 typedefstruct { U16Flags; U8Baseline; //字体高度 U8LHeight; /* height of a small lowercase character (a,x) */ U8CHeight; /* height of a small uppercase character (A,X) */ } GUI_FONTINFO; 结构体GUI_CHARINFO定义了字符信息,当XDist>XSize时,相当于相邻字符之间插入间隔。 typedefstruct { U8XSize; //字体X轴宽度,指的是显示信息宽度 U8XDist; //字体X轴距离,指的是字体占用宽度,XDist>=XSize U8BytesPerLine; //字体X轴字节数 constunsigned char * pData; } GUI_CHARINFO; 结构体GUI_CHARINFO_EXT定义了字符扩展信息,作为GUI_GETCHARINFO函数指针所指向的函数参数。 typedefstruct { U8XSize; U8YSize; I8XPos; I8YPos; U8XDist; constunsigned char * pData; } GUI_CHARINFO_EXT; 结构体tGUI_ENC_APIList定义了该字体字符串操作函数指针。 typedefint tGUI_GetLineDistX(const char * s,int Len); typedefint tGUI_GetLineLen (const char * s, int MaxLen); typedefvoid tGL_DispLine (const char * s,int Len); typedefstruct { tGUI_GetLineDistX* pfGetLineDistX; //获取该字体字符串X轴占用的像素点数 tGUI_GetLineLen * pfGetLineLen; //获取该字体字符串的长度 tGL_DispLine * pfDispLine; //显示该字体字符串 } tGUI_ENC_APIList; 结构体GUI_FONT_PROP定义了字体多个编码区域的地址和信息,因为一个字体可能存在多个编码区域,每个区域都有各自的信息,字体高度宽区可能都不一样。 typedefstruct GUI_FONT_PROP { U16PFirst; //区域第一个字符的编码 U16PLast; //区域最好一个字符的编码 constGUI_CHARINFO * paCharInfo; //属于该区域字符的字体信息 conststruct GUI_FONT_PROP * pNext; //指向字体下一个编码区域 } GUI_FONT_PROP; 基于上述这些结构体,我们开始实现中文汉字支持功能,字体名字为CNHZK。由于没有emWin源代码,这里参照了uCGUI的核心源码,如参照GUIEncSJ.C文件的GetLineDistX、_GetLineLen_SJIS、_DispLine_SJIS函数实现。此外还参照了GUI_SIF_Prop.c、GUI_GetFontInfo.C、GUIAAChar4.c、F16_HK.C等文件。 需要注意:网上大多数中文支持都是参照uCGUI支持中文的移植方式,需要用到GUI_UC_EncodeNone.c文件处理非unicode中文字体编码,这里需要删掉,否则中文显示会抖动窜动。实际上,如果实现了GUICNHZK_DispLine函数,则每次显示HZK字体字符串,都会调用该函数,而这个函数是我们自己实现的,这样我们就可以自己处理中文字体编码细节了,如果没有实现GUICNHZK_DispLine,则GUI核心会直接调用GUICNHZK_DispChar函数,这时候GUI核心要被告知如何处理字体编码,但怎么告知呢?emWin不开源,不好解决。按照uCGUI那种方式实现GUI_UC_EncodeNone.c,工作的有问题,至少在STemWinV5.26和V5.28上面都有问题。 目前支持12、16、24三种大小,将HZK12,HZK16, HZK24字库文件放置在SDCard或者外置SpiFlash等存储介质。按照类似的方法,可以扩展支持其他各种各样的字体。
首先在GUIType.h增加下列声明和宏定义。 externconst tGUI_ENC_APIList GUI_ENC_APIList_CNHZK;// /*HZK12, HZK16, HZK24 : chinese 16x12, 16x16, 24x24 fonts */ #defineGUI_FONTTYPE_CNHZK \ GUICNHZK_DispChar, \ GUICNHZK_GetCharDistX, \ GUICNHZK_GetFontInfo, \ GUICNHZK_IsInFont, \ GUICNHZK_GetCharInfo, \ &GUI_ENC_APIList_CNHZK 其次在GUI.h添加下列字体声明和宏定义。 externGUI_CONST_STORAGE GUI_FONT GUI_Font16x12_CNHZK;// externGUI_CONST_STORAGE GUI_FONT GUI_Font16x16_CNHZK;// externGUI_CONST_STORAGE GUI_FONT GUI_Font24x24_CNHZK;// #defineGUI_FONT_16x12_CNHZK &GUI_Font16x12_CNHZK// #defineGUI_FONT_16x16_CNHZK &GUI_Font16x16_CNHZK// #defineGUI_FONT_24x24_CNHZK &GUI_Font24x24_CNHZK// 定义GUI_Font16x12_CNHZK字体的相关信息。 ///////////////////Chinese_Font_16x12Define Start/////////////////////// GUI_CONST_STORAGE GUI_CHARINFO GUI_Font16x12_CNHZK_CharInfo[2] = { {8, 8, 1, (void*)0},//ASCII8x12,X轴宽度为8,1字节,Y轴高度为12 {16, 16, 2, (void*)0},//CHINESE16x12,X轴宽度为16,2字节,Y轴高度为12 };
GUI_CONST_STORAGE GUI_FONT_PROP GUI_Font16x12_CNHZK_PropHZK = { 0xA1A1, //HZK12字库第一个字符的编码 0xFFFF, //HZK12字库最后一个字符的编码 &GUI_Font16x12_CNHZK_CharInfo[1], //HZK12字库字体信息 (void *)0, };
GUI_CONST_STORAGE GUI_FONT_PROP GUI_Font16x12_CNHZK_PropASC = { 0x0000, //ASCII12字库第一个字符的编码 0x007F, //ASCII12字库最后一个字符的编码 &GUI_Font16x12_CNHZK_CharInfo[0], //ASCII12字库字体信息 (void GUI_CONST_STORAGE*)&GUI_Font16x12_CNHZK_PropHZK, //指向HZK12字库 };
GUI_CONST_STORAGE GUI_FONT GUI_Font16x12_CNHZK = { GUI_FONTTYPE_CNHZK,//接口函数指针列表 12, //字体Y轴高度 12, //字体Y轴距离 1, //字体X轴放大 1, //字体Y轴放大 (void GUI_CONST_STORAGE*)&GUI_Font16x12_CNHZK_PropASC //指向Prop列表 }; ////////////////////Chinese_Font_16x12Define End//////////////////// 定义GUI_Font16x16_CNHZK字体的相关信息。 ///////////////////Chinese_Font_16x16Define Start/////////////////// GUI_CONST_STORAGE GUI_CHARINFO GUI_Font16x16_CNHZK_CharInfo[2] = { {16, 16, 2, (void*)0},//ASCII 16x16,X轴宽度为16,2字节,Y轴高度为16 {16, 16, 2, (void*)0},//CHINESE 16x16,X轴宽度为16,2字节,Y轴高度为16 };
GUI_CONST_STORAGE GUI_FONT_PROP GUI_Font16x16_CNHZK_PropHZK = { 0xA1A1, //HZK16字库第一个字符的编码 0xFFFF, //HZK16字库最后一个字符的编码 &GUI_Font16x16_CNHZK_CharInfo[1], //HZK16字库字体信息 (void *)0, };
GUI_CONST_STORAGE GUI_FONT_PROP GUI_Font16x16_CNHZK_PropASC = { 0x0000, //ASCII16字库第一个字符的编码 0x007F, //ASCII16字库最后一个字符的编码 &GUI_Font16x16_CNHZK_CharInfo[0], //ASCII16字库字体信息 (void GUI_CONST_STORAGE*)&GUI_Font16x16_CNHZK_PropHZK, //指向HZK16字库 };
GUI_CONST_STORAGE GUI_FONT GUI_Font16x16_CNHZK = { GUI_FONTTYPE_CNHZK,//接口函数指针列表 16, //字体Y轴高度 16, //字体Y轴距离 1, //字体X轴放大 1, //字体Y轴放大 (void GUI_CONST_STORAGE*)&GUI_Font16x16_CNHZK_PropASC //指向Prop列表 }; //////////////////////Chinese_Font_16x16Define End////////////////////// 定义GUI_Font24x24_CNHZK字体的相关信息。 /////////////////////Chinese_Font_24x24Define Start///////////////////// GUI_CONST_STORAGE GUI_CHARINFO GUI_Font24x24_CNHZK_CharInfo[2] = { {24, 24, 3, (void*)0},//ASCII 24x24,X轴宽度为24,3字节,Y轴高度为24 {24, 24, 3, (void*)0},//CHINESE 24x24,X轴宽度为24,3字节,Y轴高度为24 };
GUI_CONST_STORAGE GUI_FONT_PROP GUI_Font24x24_CNHZK_PropHZK = { 0xA1A1, //HZK24字库第一个字符的编码 0xFFFF, //HZK24字库最后一个字符的编码 &GUI_Font24x24_CNHZK_CharInfo[1], //HZK24字库字体信息 (void *)0, };
GUI_CONST_STORAGE GUI_FONT_PROP GUI_Font24x24_CNHZK_PropASC = { 0x0000, //ASCII24字库第一个字符的编码 0x007F, //ASCII24字库最后一个字符的编码 &GUI_Font24x24_CNHZK_CharInfo[0], //ASCII24字库字体信息 (void GUI_CONST_STORAGE*)&GUI_Font24x24_CNHZK_PropHZK, //指向HZK24字库 };
GUI_CONST_STORAGE GUI_FONT GUI_Font24x24_CNHZK = { GUI_FONTTYPE_CNHZK,//接口函数指针列表 24, //字体Y轴高度 24, //字体Y轴距离 1, //字体X轴放大 1, //字体Y轴放大 (void GUI_CONST_STORAGE*)&GUI_Font24x24_CNHZK_PropASC //指向Prop列表 }; //////////////////////Chinese_Font_24x24Define End////////////////////// 从存储介质获取字体数据的接口函数,如果是ASCII字符(小于等于127),则从Font12.c、Font16.c、Font24.c三个文件获取字体数字,如果是汉字,则从外部存储介质读取字体数据。 //getdata from file named of HZK12, HZK16, HZK24 staticvoid GUI_GetChineseFontData(const GUI_FONT_PROP GUI_UNI_PTR *pProp, U16P c) 显示中文字体单个字符的接口函数。 voidGUICNHZK_DispChar(U16 c) 获取中文字体单个字符的X轴宽度,还有乘以放大系数(一般为1)。 intGUICNHZK_GetCharDistX(U16P c, int *pSizeX) *pSizeX = (pProp->paCharInfo)->XSize *GUI_pContext->pAFont->XMag; 获取中文字体信息, voidGUICNHZK_GetFontInfo(const GUI_FONT * pFont, GUI_FONTINFO * pfi) 判断字符c是否属于中文字体,根据GUI_FONT_PROP结构体的First和Last判断。 charGUICNHZK_IsInFont(const GUI_FONT * pFont, U16 c) if((c >= pProp->First) && (c <= pProp->Last) ) 这个函数暂时没有实现。 intGUICNHZK_GetCharInfo(U16P c, GUI_CHARINFO_EXT * pInfo) 获取中文字体字符串的像素总长度,其内部进一步调用GUICNHZK_GetCharDistX获取每一个字符的像素宽度,需要注意的是ASCII字符占用1个字节,中文占用2个字节。 intGUICNHZK_GetLineDistX(const char * s, int Len) 获取中文字体字符串的长度,需要注意,ASCII字符占用1字节,中文占用2字节。 intGUICNHZK_GetLineLen(const char * s, int MaxLen)
显示中文字体字符串。 voidGUICNHZK_DispLine(const char * s, int Len)
中文字体字符串操作函数指针结构体。 consttGUI_ENC_APIList GUI_ENC_APIList_CNHZK ={ GUICNHZK_GetLineDistX, GUICNHZK_GetLineLen, GUICNHZK_DispLine, };
底层函数的实现。
/*********************************************************************
*
* GUICNHZK_DispChar
*
* Purpose:
* This is the routine that displays a character. It is used by all
* other routines which display characters as a subroutine.
*/
//void GUI##Type##_DispChar(U16P c);
void GUICNHZK_DispChar(U16 c)
{
GUI_DRAWMODE OldDrawMode, DrawMode;
const GUI_FONT_PROP GUI_UNI_PTR *pProp;
const GUI_CHARINFO GUI_UNI_PTR *pCharInfo;
//see if c is belong to the font scope
pProp = GUI_pContext->pAFont->p.pProp;
for (; pProp; pProp = pProp->pNext) {
if( (c >= pProp->First) && (c <= pProp->Last) ) break;
}
if(0 == pProp) return;
//save and set DrawMode
DrawMode = GUI_pContext->TextMode;
OldDrawMode = LCD_SetDrawMode(DrawMode);
//Get font data from HZK12, HZK16, HZK24
GUI_GetChineseFontData(pProp, c);
//write font data
pCharInfo = pProp->paCharInfo;
LCD_DrawBitmap(GUI_pContext->DispPosX, GUI_pContext->DispPosY,
pCharInfo->XSize, GUI_pContext->pAFont->YSize,
GUI_pContext->pAFont->XMag, GUI_pContext->pAFont->YMag,
1, /* Bits per Pixel */
pCharInfo->BytesPerLine,
&GUI_FontDataBuf[0],
&LCD_BKCOLORINDEX
);
//Fill empty pixel lines
if (GUI_pContext->pAFont->YDist > GUI_pContext->pAFont->YSize) {
int YMag = GUI_pContext->pAFont->YMag;
int YDist = GUI_pContext->pAFont->YDist * YMag;
int YSize = GUI_pContext->pAFont->YSize * YMag;
if (DrawMode != LCD_DRAWMODE_TRANS) {
LCD_COLOR OldColor = GUI_GetColor();
GUI_SetColor(GUI_GetBkColor());
LCD_FillRect(GUI_pContext->DispPosX, GUI_pContext->DispPosY + YSize,
GUI_pContext->DispPosX + pCharInfo->XSize,
GUI_pContext->DispPosY + YDist);
GUI_SetColor(OldColor);
}
}
//Restore draw mode
LCD_SetDrawMode(OldDrawMode);
GUI_pContext->DispPosX += pCharInfo->XDist * GUI_pContext->pAFont->XMag;
}
/*********************************************************************
*
* GUICNHZK_GetCharDistX
*/
//int GUI##Type##_GetCharDistX(U16P c, int * pSizeX);
int GUICNHZK_GetCharDistX(U16P c, int *pSizeX)
{
const GUI_FONT_PROP GUI_UNI_PTR *pProp = GUI_pContext->pAFont->p.pProp;
for(; pProp; pProp = pProp->pNext) {
if( (c >= pProp->First) && (c <= pProp->Last) ) break;
}
if(pProp){
*pSizeX = (pProp->paCharInfo)->XSize * GUI_pContext->pAFont->XMag;
}else{
*pSizeX = 0;
}
return *pSizeX;
}
/*********************************************************************
*
* GUICNHZK_GetFontInfo
*/
//void GUI##Type##_GetFontInfo (const GUI_FONT * pFont, GUI_FONTINFO * pfi);
void GUICNHZK_GetFontInfo(const GUI_FONT * pFont, GUI_FONTINFO * pfi)
{
uint32_t FontCode;
GUI_USE_PARA(pFont);
//ysize - 12, 16, 24
FontCode = GUI_pContext->pAFont->YSize;
if(12 == FontCode){
pfi->Baseline = 12;
pfi->LHeight = 12;
pfi->CHeight = 12;
pfi->Flags = GUI_FONTINFO_FLAG_PROP;
}else if(16 == FontCode){
pfi->Baseline = 16;
pfi->LHeight = 16;
pfi->CHeight = 16;
pfi->Flags = GUI_FONTINFO_FLAG_PROP;
}else if(24 == FontCode){
pfi->Baseline = 24;
pfi->LHeight = 24;
pfi->CHeight = 24;
pfi->Flags = GUI_FONTINFO_FLAG_PROP;
}else{
return;
}
}
/*********************************************************************
*
* GUICNHZK_IsInFont
*/
//char GUI##Type##_IsInFont (const GUI_FONT * pFont, U16 c);
char GUICNHZK_IsInFont(const GUI_FONT * pFont, U16 c)
{
const GUI_FONT_PROP GUI_UNI_PTR *pProp = GUI_pContext->pAFont->p.pProp;
GUI_USE_PARA(pFont);
for(; pProp; pProp = pProp->pNext) {
if( (c >= pProp->First) && (c <= pProp->Last) ) break;
}
if(pProp){
return 1;
}else{
return 0;
}
}
/*********************************************************************
*
* GUICNHZK_GetCharInfo
*/
//int GUI##Type##_GetCharInfo (U16P c, GUI_CHARINFO_EXT * pInfo)
int GUICNHZK_GetCharInfo(U16P c, GUI_CHARINFO_EXT * pInfo)
{
return 0;
}
/*********************************************************************
*
* GUICNHZK_GetLineDistX
*/
int GUICNHZK_GetLineDistX(const char * s, int Len)
{
int Dist =0, SizeX;
U16 c0, c1;
if(0 == s) return 0;
while( ((c0=*(const U8*)s) !=0) && Len >=0 ) {
s++; Len--;
if (c0 > 127) {
c1 = *(const U8*)s++;
Len--;
Dist += GUICNHZK_GetCharDistX((c1<<8)|c0, &SizeX);
} else {
Dist += GUICNHZK_GetCharDistX(c0, &SizeX);
}
}
return Dist;
}
/*********************************************************************
*
* GUICNHZK_GetLineLen
* Purpose:
* Returns the number of characters in a string.
*/
int GUICNHZK_GetLineLen(const char * s, int MaxLen)
{
int Len =0;
U16 c0;
while( ((c0=*(const U8*)s) !=0) && Len < MaxLen ) {
s++;
if (c0 > 127) {
Len++; s++;
} else {
switch (c0) {
case '\n': return Len;
}
}
Len++;
}
return Len;
}
/*********************************************************************
*
* GUICNHZK_DispLine
*/
void GUICNHZK_DispLine(const char * s, int Len)
{
U16 c0, c1;
while (--Len >=0) {
c0 = *(const U8*)s++;
if (c0 > 127) {
c1 = *(const U8*)s++;
Len--;
GUICNHZK_DispChar((c1<<8) | c0);
} else {
GUICNHZK_DispChar(c0);
}
}
}
/*********************************************************************
*
* GUI_ENC_APIList_CNHZK
*/
const tGUI_ENC_APIList GUI_ENC_APIList_CNHZK = {
GUICNHZK_GetLineDistX,
GUICNHZK_GetLineLen,
GUICNHZK_DispLine,
};
|