硬汉嵌入式论坛

 找回密码
 立即注册
查看: 643|回复: 7
收起左侧

[emWin] emwin显示中文字符出错

[复制链接]

77

主题

223

回帖

454

积分

高级会员

积分
454
发表于 2024-7-22 15:09:07 | 显示全部楼层 |阅读模式
本帖最后由 薪火相传 于 2024-7-22 15:10 编辑

参考安福莱emwin教程文档,生成12/16/24的GB2312字体库,中文都能正常显示,但是20*20显示的中文字符不对,比如下面显示“中文”变成了其他,数字倒是正常



生成过程如下

利用下面这个软件生成20*20的中文字体库


按照如下生成ascii库


最终和其他字库合在一起

其中代码如下

GUI_Font20.c

[C] 纯文本查看 复制代码
#include "GUI.h"
#include "GUI_Type.h"


GUI_CONST_STORAGE GUI_CHARINFO GUI_FontHZ20_CharInfo[2] =  
{     
      {  10,  10,  2, (void *)"A20"},    
      {  20,  20,  3, (void *)"H20"},        
}; 

GUI_CONST_STORAGE GUI_FONT_PROP GUI_FontHZ20_PropHZ= { 
      0x4081,  
      0xFEFE, 
      &GUI_FontHZ20_CharInfo[1], 
      (void *)0,  
};

GUI_CONST_STORAGE  GUI_FONT_PROP GUI_FontHZ20_PropASC= { 
      0x0000,
      0x007F,  
      &GUI_FontHZ20_CharInfo[0], 
      (void GUI_CONST_STORAGE *)&GUI_FontHZ20_PropHZ,  
}; 

GUI_CONST_STORAGE  GUI_FONT GUI_FontHZ20 =  
{ 
        GUI_FONTTYPE_USER,
        20,  
        20,  
        1,   
        1,   
        (void GUI_CONST_STORAGE *)&GUI_FontHZ20_PropASC
}; 

GUI_CONST_STORAGE  GUI_FONT GUI_FontHZ20x2 =  
{ 
        GUI_FONTTYPE_USER,
        20,  
        20,  
        2,   
        2,   
        (void GUI_CONST_STORAGE *)&GUI_FontHZ20_PropASC 
};



[C] 纯文本查看 复制代码
#include "GUI.h"
#include "GUI_Private.h"
#include "GUIDRV_Lin.h"

#include "sys_gui.h"

/* 点阵数据缓存, 必须大于等于单个字模需要的存储空间*/ 
#define BYTES_PER_FONT      512 
static U8 GUI_FontDataBuf[BYTES_PER_FONT];

void sf_ReadBuffer(uint8_t * _pBuf, uint32_t _uiReadAddr, uint32_t _uiSize)
{
        /* 如果读取的数据长度为0或者超出串行Flash地址空间,则直接返回 */
        if ((_uiSize == 0) ||(_uiReadAddr + _uiSize) > 0x800000)
        {
                return;
        }

    memcpy(_pBuf,(const void *)(FONT_ADDR+4+_uiReadAddr),_uiSize);
    
}


/*
*********************************************************************************************************
*        函 数 名: GUI_GetDataFromMemory
*        功能说明: 读取点阵数据
*        形    参: pProp  GUI_FONT_PROP类型结构
*             c      字符
*        返 回 值: 无
*********************************************************************************************************
*/
static void GUI_GetDataFromMemory(const GUI_FONT_PROP GUI_UNI_PTR *pProp, U16P c) 
{ 
    U16 BytesPerFont; 
    U32 oft = 0, BaseAdd; 
        U8 code1,code2;
        
        char *font = (char *)pProp->paCharInfo->pData; 

        /* 每个字模的数据字节数 */
    BytesPerFont = GUI_pContext->pAFont->YSize * pProp->paCharInfo->BytesPerLine; 
    if (BytesPerFont > BYTES_PER_FONT)
        {
                BytesPerFont = BYTES_PER_FONT;
        }

        /* 英文字符地址偏移计算 */ 

    if (c < 0x80)                                                                
    { 
                if(strncmp("A12", font, 3) == 0)     /* 6*12 ASCII字符 */
                {
                        BaseAdd = 0x00000000;
                }
                else if(strncmp("A16", font, 3) == 0) /* 8*16 ASCII字符 */
                {
                        BaseAdd = 0x00000C00;
                }
        else if(strncmp("A20", font, 3) == 0) /* 16*20 ASCII字符 */
                {
                        BaseAdd = 0x00001C00;
                }
                else if(strncmp("A24", font, 3) == 0) /* 12*24 ASCII字符 */
                {
                        BaseAdd = 0x00004400;
                }
                else if(strncmp("A32", font, 3) == 0) /* 24*48 ASCII字符 */
                {
                        BaseAdd = 0x00007400;
                }
        
        else if(strncmp("A48", font, 3) == 0) /* 32*64 ASCII字符 */
                {
                        BaseAdd = 0x0000B400;
                }
                
                oft = c* BytesPerFont + BaseAdd; 
    } 
        /* 汉字和全角字符的偏移地址计算 */
    else                                                                           
    { 
                if(strncmp("H12", font, 3) == 0)      /* 12*12 字符 */
                {
                        BaseAdd = 0x00014400;
                }
                else if(strncmp("H16", font, 3) == 0)  /* 16*16 字符 */
                {
                        BaseAdd = 0x000A0860;
                }
        else if(strncmp("H20", font, 3) == 0)  /* 20*20 字符 */
                {
                        BaseAdd = 0x0015B8E0;
                }
                else if(strncmp("H24", font, 3) == 0)  /* 24*24 字符 */
                {
                        BaseAdd = 0x001DCFD0;
                }
//                else if(strncmp("H32", font, 3) == 0)  /* 32*32 字符 */
//                {
//                        BaseAdd = 0x002FDE00;
//                }
                
                /* 根据汉字内码的计算公式锁定起始地址 */
                code2 = c >> 8;
                code1 = c & 0xFF;
                
                /* 由于字符编码是安顺序存储的,先存储到高位(区号),然后是低位(位号)。而我们用的是小端格式,
                   一个汉字两个字节,获取的16位变量,正好相反,16位变量的高位是位号,低位是区号。
                */
                oft = ((code1 - 0x81) * 190 + (code2- 0x40) - (code2 / 128))* BytesPerFont + BaseAdd;
    }
    
        /* 读取点阵数据 */
        sf_ReadBuffer(GUI_FontDataBuf, oft, BytesPerFont);
} 

/*
*********************************************************************************************************
*        函 数 名: GUIUSER_DispChar
*        功能说明: 显示字符
*        形    参: c 显示的字符
*        返 回 值: 无
*********************************************************************************************************
*/
void GUIUSER_DispChar(U16P c)  
{ 
    int BytesPerLine; 
    GUI_DRAWMODE DrawMode = GUI_pContext->TextMode; 
    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) 
    { 
        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_pContext->DispPosX, GUI_pContext->DispPosY,
                       pCharInfo->XSize, GUI_pContext->pAFont->YSize,
                       GUI_pContext->pAFont->XMag, GUI_pContext->pAFont->YMag,
                       1,    
                       BytesPerLine,
                       &GUI_FontDataBuf[0],
                       &LCD_BKCOLORINDEX
                       );
                
        /* 填充背景 */
        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);
            }
        }
                
        LCD_SetDrawMode(OldDrawMode);
//      if (!GUI_MoveRTL)
        GUI_pContext->DispPosX += pCharInfo->XDist * GUI_pContext->pAFont->XMag;
    }
} 

/*
*********************************************************************************************************
*        函 数 名: GUIUSER_X_GetCharDistX
*        功能说明: 获取字符的X轴间距
*        形    参: c  字符
*        返 回 值: 无
*********************************************************************************************************
*/
int GUIUSER_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;
    }
    return (pProp) ? (pProp->paCharInfo)->XSize * GUI_pContext->pAFont->XMag : 0;
}


哪位大佬指点一下?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115896
QQ
发表于 2024-7-22 16:07:52 | 显示全部楼层
这个是那个软件生成的,换个字体试试
回复

使用道具 举报

77

主题

223

回帖

454

积分

高级会员

积分
454
 楼主| 发表于 2024-7-22 21:33:55 | 显示全部楼层
eric2013 发表于 2024-7-22 16:07
这个是那个软件生成的,换个字体试试

图片没显示出来?,多国语言那个
回复

使用道具 举报

77

主题

223

回帖

454

积分

高级会员

积分
454
 楼主| 发表于 2024-7-23 09:16:00 | 显示全部楼层
eric2013 发表于 2024-7-22 16:07
这个是那个软件生成的,换个字体试试

这个字体也是有问题,感觉是编码地址算错了,因为都是正常显示一个字,但是 不是正确要显示的字
1.png
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115896
QQ
发表于 2024-7-23 10:24:00 | 显示全部楼层
薪火相传 发表于 2024-7-23 09:16
这个字体也是有问题,感觉是编码地址算错了,因为都是正常显示一个字,但是 不是正确要显示的字

也有可能这个点阵大小,计算错偏移地址了
回复

使用道具 举报

77

主题

223

回帖

454

积分

高级会员

积分
454
 楼主| 发表于 2024-7-23 13:43:05 | 显示全部楼层
eric2013 发表于 2024-7-23 10:24
也有可能这个点阵大小,计算错偏移地址了

硬汉兄,GUI_Font20.c这个文件有没有问题?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115896
QQ
发表于 2024-7-23 15:15:08 | 显示全部楼层
薪火相传 发表于 2024-7-23 13:43
硬汉兄,GUI_Font20.c这个文件有没有问题?

我没测试过20点阵。
回复

使用道具 举报

21

主题

481

回帖

544

积分

金牌会员

积分
544
发表于 2024-7-23 20:14:52 | 显示全部楼层
感觉用utf8的编码比较正常,目前主流editor对utf8的支持都很好
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-5-25 19:04 , Processed in 0.401190 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表