硬汉嵌入式论坛

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

[emWin] 外部GB2312字库与UTF8字库生成,如何并存显示?

[复制链接]

14

主题

37

回帖

79

积分

初级会员

积分
79
发表于 2021-1-21 14:55:32 | 显示全部楼层 |阅读模式
首先,工程已经实现GBK2312全字库实现,参考的安富莱V6第25~27章。已经可以正常显示中文。

现在想在这个基础上去实现多语言切换,参考
http://www.armbbs.cn/forum.php?mod=viewthread&tid=94294&fromuid=58(多语言帖子)
http://www.armbbs.cn/forum.php?mod=viewthread&tid=87428&extra=&page=1(emwin字符生成工具)

单独显示多语言,也已经能正常显示。
但是,如果将GBK2312显示,与多语言显示放在一起显示,GBK2312显示中文就会消失。
说白了就是在mantask开头使能了UTF8:
        /* 使能UTF-8编码  必须要使能   */     
        GUI_UC_SetEncodeUTF8();                
                       
        GUI_SetColor(GUI_WHITE); /*设置文本颜色为白色*/

        /*也可以这样调用  在实际项目中很实用 */
        /*英文*/
        GUI_SetFont(FontWm[ENGLISH]);   /*设置字体*/
        GUI_DispStringAt (s_LangValue[ENGLISH] ,0, 100+50*ENGLISH); /*显示内容*/
       
         /*中文*/
        GUI_SetFont(FontWm[CHINESE]);   /*设置字体*/
        GUI_DispStringAt (s_LangValue[CHINESE] ,0, 100+50*CHINESE); /*显示内容*/       
       
        /*日文*/
        GUI_SetFont(FontWm[JAPANESE]);   /*设置字体*/
        GUI_DispStringAt (s_LangValue[JAPANESE],0, 100+50*JAPANESE); /*显示内容*/               
       
        /*土耳其语*/
        GUI_SetFont(FontWm[TURKISH]);   /*设置字体*/
        GUI_DispStringAt (s_LangValue[TURKISH] ,0, 100+50*TURKISH); /*显示内容*/       
        GUI_Delay(2000);
        GUI_Exec();
        GUI_UC_SetEncodeNone(); //禁用编码



/*显示GBK2312中文字符*/
        GUI_Clear();
        GUI_SetFont(&GUI_FontHZ16);
        GUI_DispStringAt("16号字体\r\n",0,0);



上面启用了UTF8字符,能显示多语言。然后禁用了编码,使用GUI_FontHZ16汉字显示
但是此时“16号字体” 只显示16,后面号字体不会显示。


如果在工程里面需要用到汉字,且也需要开启UTF8字符,那么怎么处理能正常显示GBK2312外部字库问题?
回复

使用道具 举报

14

主题

37

回帖

79

积分

初级会员

积分
79
 楼主| 发表于 2021-1-21 14:57:12 | 显示全部楼层
**********************************************************************
*/
/*********************************************************************
*
*       GUI_UC_SetEncodeNone
*/
void GUI_UC_SetEncodeNone(void) {
  GUI_LOCK();
  GUI_Context.pUC_API = &GUI__API_TableNone;
  GUI_UNLOCK();
}

  const GUI_UC_ENC_APILIST * pUC_API;    /* Unicode encoding API */

都已添加
回复

使用道具 举报

58

主题

267

回帖

446

积分

高级会员

积分
446
发表于 2021-1-21 15:45:16 | 显示全部楼层
ZMLZML1009 发表于 2021-1-21 14:57
**********************************************************************
*/
/*********************** ...

自己做 GBK 到 UNICODE 的转换,然后将 UNICODE 编码成 UTF8。
显示的时候使用转换得到的 UTF8 字符串,就行了。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107397
QQ
发表于 2021-1-22 09:12:32 | 显示全部楼层
ZMLZML1009 发表于 2021-1-21 14:57
**********************************************************************
*/
/*********************** ...

可以参考,我们的一个原始工程全部GBK的字库,为了显示UTF-8,做了个转换。

UTF-8字符串转GBK实现
http://www.armbbs.cn/forum.php?m ... 7029&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

14

主题

37

回帖

79

积分

初级会员

积分
79
 楼主| 发表于 2021-2-5 13:11:37 | 显示全部楼层
  1. /* 包含头文件 ----------------------------------------------------------------*/
  2. #include "task/MainTask.h"
  3. #include "language.h"
  4. /* 私有类型定义 --------------------------------------------------------------*/
  5. /* 私有宏定义 ----------------------------------------------------------------*/
  6. /* 私有变量 ------------------------------------------------------------------*/
  7. /* 用于选择使用的显示方法 */
  8. #define Method3  

  9. extern FATFS fs;                                                                                       

  10.         /* FatFs文件系统对象 */
  11. extern FIL file;                                                                                       

  12.         /* 文件对象 */
  13. extern FRESULT f_res;                   /* 文件操作结果 */
  14. extern UINT fnum;                                                      /* 文件成功读写数量 */

  15. #define XBF_KAITI24_ADDR       0X600000     //字库存放在SPI_FLash地址
  16. uint8_t tempbuf[256]={0};            /* 从SD卡读取数据的缓冲 */
  17. #define XBF_KAITI24_SIZE    (520)   // kaiti24.xbf字库文件存占用扇区数(每个扇区为4096个字节)
  18. void PG_PrintText(char *_str);







  19. /* 扩展变量 ------------------------------------------------------------------*/
  20. /* 私有函数原形 --------------------------------------------------------------*/
  21. /* 函数体 --------------------------------------------------------------------*/
  22. /**
  23.   * 函数功能: 对话框信息
  24.   * 输入参数: 无
  25.   * 返 回 值: 无
  26.   * 说    明: 无
  27.   */
  28. static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
  29.     { WINDOW_CreateIndirect,    "ARMM",             0,               0, 0,  320,480,0,0},
  30.     { TEXT_CreateIndirect,      "新年快乐",        GUI_ID_TEXT0,     0, 30, 80, 20, 0, 0x0, 0},
  31.     { TEXT_CreateIndirect,      "新年快乐",        GUI_ID_TEXT1,     0, 120, 80, 120, 0, 0x0, 0},
  32.     { TEXT_CreateIndirect,      "新年快乐",        GUI_ID_TEXT2,     0, 240, 240, 240, 0, 0x0,0},
  33.     { TEXT_CreateIndirect,      "新年快乐",        GUI_ID_TEXT3,     0, 340, 320, 320, 0, 0x0, 0},
  34. };

  35. /**
  36.   * 函数功能: 重绘
  37.   * 输入参数: 无
  38.   * 返 回 值: 无
  39.   * 说    明: 无
  40.   */
  41. void PaintDialog(WM_MESSAGE * pMsg)
  42. {
  43. //    WM_HWIN hWin = pMsg->hWin;
  44. }

  45. /**
  46.   * 函数功能: 对话框初始化
  47.   * 输入参数: 无
  48.   * 返 回 值: 无
  49.   * 说    明: 无
  50.   */
  51. void InitDialog(WM_MESSAGE * pMsg)
  52. {
  53.   WM_HWIN hWin = pMsg->hWin;
  54.   #if 0
  55.         /* 使能UTF-8编码  必须要使能   */     
  56.         GUI_UC_SetEncodeUTF8();                
  57.                        
  58.         GUI_SetColor(GUI_WHITE); /*设置文本颜色为白色*/

  59.         /*也可以这样调用  在实际项目中很实用 */
  60.         /*英文*/
  61.         GUI_SetFont(FontWm[ENGLISH]);   /*设置字体*/
  62.         GUI_DispStringAt (s_LangValue[ENGLISH] ,0, 100+50*ENGLISH); /*显示内容*/
  63.        
  64.          /*中文*/
  65.         GUI_SetFont(FontWm[CHINESE]);   /*设置字体*/
  66.         GUI_DispStringAt (s_LangValue[CHINESE] ,0, 100+50*CHINESE); /*显示内容*/       
  67.        
  68.         /*日文*/
  69.         GUI_SetFont(FontWm[JAPANESE]);   /*设置字体*/
  70.         GUI_DispStringAt (s_LangValue[JAPANESE],0, 100+50*JAPANESE); /*显示内容*/               
  71.        
  72.         /*土耳其语*/
  73.         GUI_SetFont(FontWm[TURKISH]);   /*设置字体*/
  74.         GUI_DispStringAt (s_LangValue[TURKISH] ,0, 100+50*TURKISH); /*显示内容*/       
  75.         GUI_Delay(2000);

  76.        

  77.         GUI_Clear();
  78.         GUI_Exec();
  79.         // GUI_UC_SetEncodeNone();
  80. #endif
  81.     //
  82.     //GUI_ID_TEXT0
  83.     //
  84.         TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT0), GUI_BLUE);
  85.   TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT0),&GUI_FontHZ12);
  86.         TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT1), GUI_CYAN);
  87.         TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT1),&GUI_FontHZ16);
  88.         TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT2), GUI_RED);
  89.         TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT2),&GUI_FontHZ24);
  90.         TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT3), GUI_GREEN);
  91.         TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT3),&GUI_FontHZ32);
  92. }

  93. /**
  94.   * 函数功能: 对话框回调函数
  95.   * 输入参数: 无
  96.   * 返 回 值: 无
  97.   * 说    明: 无
  98.   */
  99. static void _cbCallback(WM_MESSAGE * pMsg)
  100. {
  101.     int NCode, Id;
  102.     WM_HWIN hWin = pMsg->hWin;
  103.     switch (pMsg->MsgId)
  104.     {
  105.         case WM_PAINT:
  106.                                         PG_PrintText("16号字体吧你\r\n");
  107.             PaintDialog(pMsg);
  108.             break;
  109.                
  110.         case WM_INIT_DIALOG:
  111.             InitDialog(pMsg);
  112.             break;
  113.                
  114.         case WM_KEY:
  115.             switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key)
  116.             {
  117.                 case GUI_KEY_ESCAPE:
  118.                     GUI_EndDialog(hWin, 1);
  119.                     break;
  120.                                
  121.                 case GUI_KEY_ENTER:
  122.                     GUI_EndDialog(hWin, 0);
  123.                     break;
  124.             }
  125.             break;
  126.                        
  127.         case WM_NOTIFY_PARENT:
  128.             Id = WM_GetId(pMsg->hWinSrc);
  129.             NCode = pMsg->Data.v;        
  130.             switch (Id)
  131.             {
  132.                 case GUI_ID_OK:
  133.                     if(NCode==WM_NOTIFICATION_RELEASED)
  134.                         GUI_EndDialog(hWin, 0);
  135.                     break;
  136.                                        
  137.                 case GUI_ID_CANCEL:
  138.                     if(NCode==WM_NOTIFICATION_RELEASED)
  139.                         GUI_EndDialog(hWin, 0);
  140.                     break;
  141.             }
  142.             break;
  143.                        
  144.         default:
  145.             WM_DefaultProc(pMsg);
  146.     }
  147. }

  148. /**
  149.   * 函数功能: 往SPIFlash写入字库文件
  150.   * 输入参数: 无
  151.   * 返 回 值: 无
  152.   * 说    明: 无
  153.   */
  154. void LoadFontLib(void)
  155. {
  156.   uint32_t j;
  157.   uint32_t write_addr=0;

  158. /* 开背光 */
  159.   LCD_BK_ON();       
  160.         /* 清屏 */
  161.         GUI_SetBkColor(GUI_BLUE);
  162.         GUI_Clear();

  163. /* 第2步:打开文件 ***************************************************************/
  164.         f_res = f_open(&file, "0:gbk16.bin", FA_OPEN_EXISTING | FA_READ );
  165. //                f_res = f_open(&file, "0:GBK16.FON", FA_OPEN_EXISTING | FA_READ );
  166.         if (f_res !=  FR_OK)
  167.         {
  168.                 printf("font.bin文件打开失败");
  169.         }
  170.   write_addr=XBF_KAITI24_ADDR;
  171.   for(j=0;j<XBF_KAITI24_SIZE;j++)//擦除扇区
  172.   {
  173.     SPI_FLASH_SectorErase(write_addr+j*4096);
  174.   }
  175.   
  176. /* 第3步:复制SD卡中字库文件font.bin到SPI FLASH **********************************/
  177.   write_addr=XBF_KAITI24_ADDR;
  178.   while(f_res == FR_OK)
  179.   {
  180.    /* 读取一个扇区的数据到tempbuf */
  181.     f_res = f_read(&file, tempbuf, sizeof(tempbuf), &fnum);
  182.     if(f_res!=FR_OK)break;                         //执行错误  
  183.     /* 写数据到SPI FLASH */
  184.     SPI_FLASH_BufferWrite(tempbuf, write_addr, 256);
  185.     write_addr+=256;       
  186.     j++;
  187.     if(fnum !=256)break;   
  188.   }
  189.     f_close(&file);
  190.       
  191.         printf("updata font  is ok \r\n");
  192.         /* 等待1秒后开始进去emWin主界面 */
  193.         GUI_Delay(1000);
  194. }



  195. /*
  196. *********************************************************************************************************
  197. *    函 数 名: StrUTF8ToGBK
  198. *    功能说明: 将UTF8字符串转换GBK字符串
  199. *    形    参: utf8 输入字符串   
  200. *              gbk  输出字符串
  201. *              gbk_size 字符串size
  202. *    返 回 值: 字符串
  203. *********************************************************************************************************
  204. */
  205. char *StrUTF8ToGBK(char *utf8, char *gbk, uint16_t gbk_size)
  206. {   
  207.     uint8_t code1, code2;
  208.     char *_ptr;
  209.     char *_pOut;
  210.     uint16_t len = 0;
  211.    
  212.     _ptr = utf8;
  213.     _pOut = gbk;
  214.    
  215.     /* 开始循环处理字符 */
  216.     while (*_ptr != 0)
  217.     {
  218.         code1 = *_ptr; /* 读取字符串数据, 该数据可能是ascii代码,也可能汉字代码的高字节 */
  219.         if (code1 < 0x80)
  220.         {
  221.             if (len + 1 < gbk_size)
  222.             {
  223.                 *_pOut++ = code1;
  224.                
  225.                 len++;
  226.             }
  227.         }
  228.         else
  229.         {
  230.             /* 解读 UTF-8 编码非常简单。
  231.                 如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。
  232.                 UNICODE 最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0
  233.         
  234.                 110XXXXX  10XXXXXX           -- 支持
  235.                 1110XXXX  10XXXXXX 10XXXXXX  -- 支持
  236.                 11110XXX  10XXXXXX 10XXXXXX 10XXXXXX  -- 本转换程序不支持
  237.             */
  238.             {            
  239.                 uint8_t code3;
  240.                 uint32_t unicode1;
  241.                 uint16_t gb;
  242.                
  243.                 if ((code1 & 0xE0) == 0xC0)    /* 2字节 */
  244.                 {
  245.                     code2 = *++_ptr;
  246.                     if (code2 == 0)
  247.                     {
  248.                         break;
  249.                     }                           
  250.                     unicode1 = ((uint32_t)(code1 & 0x1F) << 6) + (code2 & 0x3F);                           
  251.                 }
  252.                 else if ((code1 & 0xF0) == 0xE0)    /* 3字节 */
  253.                 {
  254.                     code2 = *++_ptr;
  255.                     code3 = *++_ptr;
  256.                     if (code2 == 0 || code3 == 0)
  257.                     {
  258.                         break;
  259.                     }
  260.                     unicode1 = ((uint32_t)(code1 & 0x0F) << 12) + ((uint32_t)(code2 & 0x3F) << 6) + (code3 & 0x3F);
  261.                 }
  262.                 else if ((code1 & 0xF8) == 0xF0)    /* 4字节 */
  263.                 {
  264.                     code2 = *++_ptr;
  265.                     if (code2 == 0)
  266.                     {
  267.                         break;
  268.                     }                           
  269.                 }   
  270.                 else
  271.                 {
  272.                     code2 = *++_ptr;
  273.                     if (code2 == 0)
  274.                     {
  275.                         break;
  276.                     }                           
  277.                 }
  278.                
  279.                 /* 将UNICODE码转换为GB2312 */
  280.                 if (unicode1 > 0xFFFF)
  281.                 {
  282.                     break;
  283.                 }
  284.                 gb = ff_convert(unicode1, 0);    /* Unicode -> OEM */
  285.                
  286.                 code1 = gb >> 8;
  287.                 code2 = gb;
  288.                
  289.                 if (len + 2 < gbk_size)
  290.                 {
  291.                     *_pOut++ = code1;
  292.                     *_pOut++ = code2;
  293.                     
  294.                     len += 2;
  295.                 }
  296.             }
  297.         }
  298.         
  299.         _ptr++;
  300.     }
  301.    
  302.     *_pOut = 0;
  303.    
  304.     return gbk;
  305. }

  306. /*
  307. *********************************************************************************************************
  308. *    函 数 名: PG_PrintText
  309. *    功能说明: 烧录过程输出消息
  310. *    形    参: _str : 字符串
  311. *    返 回 值: 无
  312. *********************************************************************************************************
  313. */
  314. void PG_PrintText(char *_str)
  315. {
  316.     char str[128];
  317.    
  318.     /* 输出文本 */
  319.    StrUTF8ToGBK(_str, str, sizeof(str));
  320.          GUI_SetColor(GUI_WHITE); /*设置文本颜色为白色*/
  321.          GUI_SetFont(&GUI_FontHZ16);
  322.          GUI_DispStringAt(str,0,0);//:那你纳尼电子  
  323.          GUI_Delay(1000);
  324. }

  325. /**
  326.   * 函数功能: GUI功能函数
  327.   * 输入参数: 无
  328.   * 返 回 值: 无
  329.   * 说    明: 无
  330.   */
  331. void MainTask(void)
  332. {       
  333.                 uint8_t i;
  334.         /* 初始化 */
  335.     GUI_Init();
  336.   
  337.     LCD_BK_ON();

  338. //    LoadFontLib();
  339. //    /* 创建对话框 */
  340.   
  341.         PG_PrintText("16号字体吧你\r\n");
  342.   #if 1
  343.         /* 使能UTF-8编码  必须要使能   */     
  344.         GUI_UC_SetEncodeUTF8();                
  345.                        
  346.         GUI_SetColor(GUI_WHITE); /*设置文本颜色为白色*/

  347.         /*也可以这样调用  在实际项目中很实用 */
  348.         /*英文*/
  349.         GUI_SetFont(FontWm[ENGLISH]);   /*设置字体*/
  350.         GUI_DispStringAt (s_LangValue[ENGLISH] ,0, 100+50*ENGLISH); /*显示内容*/
  351.        
  352.          /*中文*/
  353.         GUI_SetFont(FontWm[CHINESE]);   /*设置字体*/
  354.         GUI_DispStringAt (s_LangValue[CHINESE] ,0, 100+50*CHINESE); /*显示内容*/       
  355.        
  356.         /*日文*/
  357.         GUI_SetFont(FontWm[JAPANESE]);   /*设置字体*/
  358.         GUI_DispStringAt (s_LangValue[JAPANESE],0, 100+50*JAPANESE); /*显示内容*/               
  359.        
  360.         /*土耳其语*/
  361.         GUI_SetFont(FontWm[TURKISH]);   /*设置字体*/
  362.         GUI_DispStringAt (s_LangValue[TURKISH] ,0, 100+50*TURKISH); /*显示内容*/       
  363.         GUI_Delay(2000);

  364.         GUI_Clear();
  365.        
  366. //   GUI_SetColor(GUI_WHITE); /*设置文本颜色为白色*/
  367. //         GUI_SetFont(&GUI_FontHZ16);
  368. //         GUI_DispStringAt("16号字体吧你\r\n",0,0);//:那你纳尼电子 ALIENTEK!         
  369. //         GUI_Delay(1000);
  370. //         GUI_Clear();       
  371.         PG_PrintText("16号字体吧你\r\n");
  372.        
  373.        
  374.        
  375.         GUI_Exec();
  376. //        GUI_UC_SetEncodeNone();
  377. #endif
  378. GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbCallback, 0, 0, 0);

  379.     while(1)
  380.     {
  381.       GUI_Delay(10);
  382.     }
  383. }

复制代码


回复

使用道具 举报

14

主题

37

回帖

79

积分

初级会员

积分
79
 楼主| 发表于 2021-2-5 13:21:50 | 显示全部楼层
我使用了硬汉哥的   StrUTF8ToGBK 函数,将UTF8转为GBK。可以转成GBK,但是显示GBK字库文字时,也是显示不出来的。        /* 使能UTF-8编码  必须要使能   */     
        GUI_UC_SetEncodeUTF8();

在此之前使用PG_PrintText("16号字体吧你\r\n");可以在屏幕上显示GBK汉字


但在此之后,再调用一次,就会显示不出来GBK汉字。


第一次调用GBK汉字

第一次调用GBK汉字

仿真

仿真

第二次调用GBK,汉字缺失

第二次调用GBK,汉字缺失
回复

使用道具 举报

9

主题

140

回帖

187

积分

初级会员

积分
187
QQ
发表于 2021-2-5 15:30:32 | 显示全部楼层
ZMLZML1009 发表于 2021-2-5 13:21
我使用了硬汉哥的   StrUTF8ToGBK 函数,将UTF8转为GBK。可以转成GBK,但是显示GBK字库文字时,也是显示不 ...

你的GB2312字库是专用的字库芯片,还是可编写的SPI FLASH芯片,如果是后者,到是可以试试上面你说的emwin字体工具V0.4里面,类型 "外部字体,XBF"格式。
回复

使用道具 举报

14

主题

37

回帖

79

积分

初级会员

积分
79
 楼主| 发表于 2021-2-5 16:47:09 | 显示全部楼层
allyzc 发表于 2021-2-5 15:30
你的GB2312字库是专用的字库芯片,还是可编写的SPI FLASH芯片,如果是后者,到是可以试试上面你说的emwin ...

用的SPI FLASH。之前一开始就是用的XBF,但是用显示SD卡内文件名时,中文使用XBF显示不正常,使用GBK显示正常,所以XBF字体被我PASS掉了
回复

使用道具 举报

9

主题

140

回帖

187

积分

初级会员

积分
187
QQ
发表于 2021-2-7 16:25:10 | 显示全部楼层
ZMLZML1009 发表于 2021-2-5 16:47
用的SPI FLASH。之前一开始就是用的XBF,但是用显示SD卡内文件名时,中文使用XBF显示不正常,使用GBK显示 ...

FATFS的中文是CC936,这是GBK编码,多国语言基本是用UTF8的了,这只能做GBK到UTF8的转换了
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-30 04:07 , Processed in 0.304578 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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