打印
[STM32]

emWin & STemWin & uCGUI 的中文支持

[复制链接]
3294|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
nicholasldf|  楼主 | 2016-1-12 17:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 nicholasldf 于 2016-1-13 14:41 编辑

  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等文件。
   
    目前支持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///////////////////////
省略
////////////////////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/////////////////////
省略..
//////////////////////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,
  };

相关帖子

沙发
nicholasldf|  楼主 | 2016-1-12 17:33 | 只看该作者
本帖最后由 nicholasldf 于 2016-1-13 14:43 编辑

底层函数的实现。

/********************************************************************************************
* Chinese font STemWin common bottom level interface API
*********************************************************************************************
*/
//Chinese font file pointer
#include  "ff_gen_drv.h"
static FIL  SDFileChinese;
//0-none, 1-CODE_16x12, 2-CODE_16x16, 3-CODE_24x24
static uint32_t FileOpenflag = 0;

//buffer for store font data read from HZK12, HZK16, HZK24
#define  CHINESE_FONT_BUFF_SIZE                576 //24 x 24 = 576 Bytes
static uint8_t GUI_FontDataBuf[CHINESE_FONT_BUFF_SIZE];

//get data from file named of HZK12, HZK16, HZK24
static void GUI_GetChineseFontData(const GUI_FONT_PROP GUI_UNI_PTR *pProp,  U16P c)
{
        uint32_t FontCode, temp, total, i;
        const uint8_t  *pBitMap;
        FRESULT   res1 = FR_OK;
       
        //ysize - 12, 16, 24
        FontCode = GUI_pContext->pAFont->YSize;
       
        //if it's a ASCII character, acquire data from Font12.c, Font16.c, Font24.c
    if (c < 0x80) {
                if(12 == FontCode){
                        total = 1*12;
                        pBitMap = Font12.table + total*(c - ' ');
                }else if(16 == FontCode){
                        total = 2*16;
                        pBitMap = Font16.table + total*(c - ' ');
                }else if(24 == FontCode){
                        total = 3*24;
                        pBitMap = Font24.table + total*(c - ' ');
                }else{
                        return;
                }
                for(i=0; i<total; i++){
                        GUI_FontDataBuf = pBitMap;
                }
                return;
        }
       
        //Chinese font data
        //Read HZK12, HZK16, HZK24 from SDCard
        if(12 == FontCode){
                total = 2*12;
                if(1 != FileOpenflag){
                        //close other opened font file
                        if(FileOpenflag)  res1 = f_close(&SDFileChinese);
                        if(res1 != FR_OK) { FileOpenflag = 0; return; }
                        //open aim file
                        res1 = f_open (&SDFileChinese, "SD:/HZK12", FA_READ);
                        //error
                        if(res1 == FR_OK){ FileOpenflag = 1; }else{ FileOpenflag = 0; return; }
                }
        }else if(16 == FontCode){
                total = 2*16;
                if(2 != FileOpenflag){
                        //close other opened font file
                        if(FileOpenflag)  res1 = f_close(&SDFileChinese);
                        if(res1 != FR_OK) { FileOpenflag = 0; return; }
                        //open aim file
                        res1 = f_open (&SDFileChinese, "SD:/HZK16", FA_READ);
                        //error
                        if(res1 == FR_OK){ FileOpenflag = 2; }else{ FileOpenflag = 0; return; }
                }
        }else if(24 == FontCode){
                total = 3*24;
                if(3 != FileOpenflag){
                        //close other opened font file
                        if(FileOpenflag)  res1 = f_close(&SDFileChinese);
                        if(res1 != FR_OK) { FileOpenflag = 0; return; }
                        //open aim file
                        res1 = f_open (&SDFileChinese, "SD:/HZK24OK", FA_READ);
                        //error
                        if(res1 == FR_OK){ FileOpenflag = 3; }else{ FileOpenflag = 0; return; }
                }
        }else{
                return;
        }
       
        //HZK24F,HZK24H,HZK24K,HZK24S,HZK24T,HZK24F
        //temp = (pString[0]-0xA1-15)*94 + pString[1]-0xA1;
       
        //HZK12,HZK16,HZK24
        temp = ((c&0xFF)-0xA1)*94 + (c>>8)-0xA1;
        temp *= total;
       
        //lseek
        res1 = f_lseek (&SDFileChinese, temp);
        if(res1 != FR_OK){
                f_close(&SDFileChinese);  FileOpenflag = 0;  return;//error
        }
        //read font data
        res1 = f_read (&SDFileChinese, GUI_FontDataBuf, total, &temp);
        if(res1 != FR_OK){
                f_close(&SDFileChinese);  FileOpenflag = 0;  return;//error
        }

}

/*********************************************************************
*
*       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)


/*********************************************************************
*
*       GUICNHZK_GetLineDistX
*/
int GUICNHZK_GetLineDistX(const char * s, int Len)


/*********************************************************************
*
*       GUICNHZK_GetLineLen
* Purpose:
*   Returns the number of characters in a string.
*/
int GUICNHZK_GetLineLen(const char * s, int MaxLen)


/*********************************************************************
*
*       GUICNHZK_DispLine
*/
void GUICNHZK_DispLine(const char * s, int Len)


/*********************************************************************
*
*       GUI_ENC_APIList_CNHZK
*/
const tGUI_ENC_APIList  GUI_ENC_APIList_CNHZK = {
        GUICNHZK_GetLineDistX,
        GUICNHZK_GetLineLen,
        GUICNHZK_DispLine,
};


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

61

主题

261

帖子

10

粉丝