中文字库简介,GB2312字库用法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了中文字库简介,GB2312字库用法相关的知识,希望对你有一定的参考价值。

参考技术A GB2312编码 :1981年5月1日发布的简体中文汉字编码国家标准。GB2312对汉字采用双字节编码,收录7445个图形字符,其中包括6763个汉字。

BIG5编码 :台湾地区繁体中文标准字符集,采用双字节编码,共收录13053个中文字,1984年实施。

GBK编码 :1995年12月发布的汉字编码国家标准,是对GB2312编码的扩充,对汉字采用双字节编码。GBK字符集共收录21003个汉字,包含国家标准GB13000-1中的全部中日韩汉字,和BIG5编码中的所有汉字。

GB18030编码 :2000年3月17日发布的汉字编码国家标准,是对GBK编码的扩充,覆盖中文、日文、朝鲜语和中国少数民族文字,其中收录27484个汉字。GB18030字符集采用单字节、双字节和四字节三种方式对字符编码。兼容GBK和GB2312字符集。

Unicode编码 :国际标准字符集,它将世界各种语言的每个字符定义一个唯一的编码,以满足跨语言、跨平台的文本信息转换。

GB2312编码是第一个汉字编码国家标准,由中国国家标准总局1980年发布,1981年5月1日开始使用。GB2312编码共收录汉字6763个,其中一级汉字3755个,二级汉字3008个。同时,GB2312编码收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。

分区表示

GB2312编码对所收录字符进行了“分区”处理,共94个区,每区含有94个位,共8836个码位。这种表示方式也称为区位码。

01-09区收录除汉字外的682个字符。

10-15区为空白区,没有使用。

16-55区收录3755个一级汉字,按拼音排序。

56-87区收录3008个二级汉字,按部首/笔画排序。

88-94区为空白区,没有使用。

举例来说,“啊”字是GB2312编码中的第一个汉字,它位于16区的01位,所以它的区位码就是1601。

双字节编码

GB2312规定对收录的每个字符采用两个字节表示,第一个字节为“高字节”,对应94个区;第二个字节为“低字节”,对应94个位。所以它的区位码范围是:0101-9494。区号和位号分别加上0xA0就是GB2312编码。例如最后一个码位是9494,区号和位号分别转换成十六进制是5E5E,0x5E+0xA0=0xFE,所以该码位的GB2312编码是FEFE。

GB2312编码范围:A1A1-FEFE,其中汉字的编码范围为B0A1-F7FE,第一字节0xB0-0xF7(对应区号:16-87),第二个字节0xA1-0xFE(对应位号:01-94)。

https://www.qqxiuzi.cn/zh/hanzi-gb2312-bianma.php ( GB2312编码表 )

https://www.qqxiuzi.cn/bianma/zifuji.php(转utf8)

HZK12  '16x12 宋体汉字点阵  一个汉字24Byte

HZK14  '16x14 宋体汉字点阵  一个汉字28Byte

HZK16  '16x16 宋体汉字点阵  一个汉字32Byte

HZK16F '16x16 繁体宋体汉字点阵  一个汉字32Byte

HZK24F '24x24 仿宋汉字打印点阵  一个汉字72Byte

HZK24H '24x24 黑体汉字打印点阵  一个汉字72Byte

HZK24K '24x24 楷体汉字打印点阵  一个汉字72Byte

HZK24S '24x24 宋体汉字打印点阵  一个汉字72Byte

HZK24T '24x24 宋体符号打印点阵  一个符号72Byte

HZK40S '40x40 宋体汉字点阵  一个汉字200Byte

HZK40T '40x40 宋体符号点阵  一个符号200Byte

HZK48S '48x48 宋体汉字点阵  一个汉字288Byte

HZK48T '48x48 宋体符号点阵  一个符号288Byte

HZK16字库是符合GB2312标准的16×16点阵字库

HZK16字库里的16×16汉字一共需要256个点来显示,也就是说需要32个字节才能达到显示一个普通汉字的目的。

一个汉字占两个字节,这两个中前一个字节为该汉字的区号,后一个字节为该字的位号。其中,每个区记录94个汉字,位号为该字在该区中的位置。所以要找到汉字在hzk16库中的位置就必须得到它的区码和位码。

区码: 汉字的 第一个字节-0xA0 (因为汉字编码是从0xA0区开始的, 所以文件最前面就是从0xA0区开始, 要算出相对区码)

位码: 汉字的 第二个字节-0xA0

这样我们就可以得到汉字在HZK16中的绝对偏移位置:

offset=(94*(区码-1)+(位码-1))*32

注解:

区码减1是因为数组是以0为开始而区号位号是以1为开始的

(94*(区号-1)+位号-1)是一个汉字字模占用的字节数

最后乘以32是因为汉字库文应从该位置起的32字节信息记录该字的字模信息(前面提到一个汉字要有32个字节显示)

如果你有UCDOS的HZK24S(宋体)、HZK24K(楷体)或HZK24H(黑体),你还可以使用不同字体的大字模汉字了。HZK24系列是24*24的点阵字库,每字模占用3*24字节。如果你按照HZK16的显示方法的话,你会看到......呵呵,字被放倒了。这是因为该类字库与一般的汉字库不同,这类大字模汉字库是专供打印的打印字库,为了打印的方便将字模都放倒了,你使用时,只要将字模的位信息纵横转置显示即可。例如你如果定义为mat[24][3]则应该这样输出:

for(i=0;i<24;i++)

for(j=0;j<24;j++)

if((0x80>>i%8)&mat[j][i/8]) /*转置显示*/

putpixel(j+x,y+i,color);

还有一类字库HZK12,虽然属于标准字库类型,但如果你将它的字模当作12*12位计算的话,根本无法正常显示汉字。因为字库设计者为了使用的方便,字摸每行的位数均补齐为8的整数倍,于是实际该字库的位长度是16*12,虽然每行都多出了4位,但这4位都是0(不显示),并不影响显示效果。

ESP32基础应用之lvgl显示中文

文章目录

1 工程简介

该工程在《ESP32基础应用之LVGL基础》之上实现中文的显示。
参考文章

  1. ESP32 IDF LVGL8.0 flash 外部字库显示 中文显示

2 工程实现

2.1 制作字库

使用软件LvglFontToolV0.4自作二进制字库文件。

  1. 在电脑(C:\\Windows\\Fonts)找到合适的字体,并复制到桌面
  2. 打开 LvglFontToolV0.4 软件
  3. 最后获得两个文件,并查看myFont.bin大小,好后续为字库分配分区表大小。

2.2 为字库自作分区表

分区表知识可参考乐鑫官网《API 指南 — 分区表

  1. 在官方例程中复制一份自定义分区表到lvgl工程中

    修改分区表中的内容后如下

    # Name,   Type, SubType, Offset,  Size, Flags
    # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
    nvs,        data, nvs,      0x9000,  0x6000,
    phy_init,   data, phy,      0xf000,  0x1000,
    factory,    app,  factory,  0x10000, 1M,
    font,    data, 0x40,             , 2M,  //type选择data;SubType自定义(大于0x3F);Size根据字库大小合理定义
    
  2. 在ESP32配置菜单中选择自定义分区表

2.3 将字库移植到lvgl工程中

  1. 将字库myFont.bin放置到lvgl工程目录下


    2. 将 myFont.c 放到合适的位置(注意需要将myFont.c添加到CMakeLists.txt)

2.4 将字库myFont.bin烧录到分区表中

  1. 命令esptool.py --chip esp32 --port COM4 --baud 115200 write_flash -z 0x110000 myFont.bin
    注意:烧录位置0x110000 可以通过自定义分区表计算,也可以在串口打印数据中查看

2.5 编写程序测试

  1. 修改myFont.c以适配工程,

    /*
    *---------------------------------------------------------------
    *                        Lvgl Font Tool                         
    *                                                               
    * 注:使用unicode编码                                              
    * 注:本字体文件由Lvgl Font Tool V0.4 生成                          
    * 作者:阿里(qq:617622104)                                         
    *---------------------------------------------------------------
    */
    #include "main.h"
    #include "esp_partition.h"
    #include "lvgl/lvgl.h"![在这里插入图片描述](https://img-blog.csdnimg.cn/9882e48826b24e988d12e61d7ad04e21.png)
    
    #include "lvgl_helpers.h"
    
    #define TAG "myFont.c"
    
    typedef struct
        uint16_t min;
        uint16_t max;
        uint8_t  bpp;
        uint8_t  reserved[3];
    x_header_t;
    typedef struct
        uint32_t pos;
    x_table_t;
    typedef struct
        uint8_t adv_w;
        uint8_t box_w;
        uint8_t box_h;
        int8_t  ofs_x;
        int8_t  ofs_y;
        uint8_t r;
    glyph_dsc_t;
    
    
    static x_header_t __g_xbf_hd = 
        .min = 0x0020,
        .max = 0x9fa0,
        .bpp = 2,
    ;![在这里插入图片描述](https://img-blog.csdnimg.cn/83af052dcf9a43bf942052986a0a4715.png)
    
    static uint8_t __g_font_buf[144];//如bin文件存在SPI FLASH可使用此buff
    
    esp_partition_t* partition_res=NULL;
    
    static uint8_t *__user_font_getdata(int offset, int size)
        //如字模保存在SPI FLASH, SPIFLASH_Read(__g_font_buf,offset,size);
        //如字模已加载到SDRAM,直接返回偏移地址即可如:return (uint8_t*)(sdram_fontddr+offset);
        static uint8_t first_in = 1;  
        if(first_in==1)
              
            partition_res=esp_partition_find_first(0x01,0x40,NULL);//这个函数第一个参数是我们分区表的第四行的,第二列的参数,第二个是第三列的值
            first_in=0;
            if (partition_res == NULL)
            
                ESP_LOGI(TAG,"Failed to open file for reading\\n");
                return NULL;
            else
                 ESP_LOGI(TAG,"Successfully open file for reading\\n");
            
        
        esp_err_t res=esp_partition_read(partition_res,offset,__g_font_buf,size);//读取数据
        if(res!=ESP_OK)
        
            ESP_LOGI(TAG,"Failed to reading\\n");
            
        return __g_font_buf;
    
    static const uint8_t * __user_font_get_bitmap(const lv_font_t * font, uint32_t unicode_letter) 
        if( unicode_letter>__g_xbf_hd.max || unicode_letter<__g_xbf_hd.min ) 
            return NULL;
        
        uint32_t unicode_offset = sizeof(x_header_t)+(unicode_letter-__g_xbf_hd.min)*4;
        uint32_t *p_pos = (uint32_t *)__user_font_getdata(unicode_offset, 4);
        if( p_pos[0] != 0 ) 
            uint32_t pos = p_pos[0];
            glyph_dsc_t * gdsc = (glyph_dsc_t*)__user_font_getdata(pos, sizeof(glyph_dsc_t));
            return __user_font_getdata(pos+sizeof(glyph_dsc_t), gdsc->box_w*gdsc->box_h*__g_xbf_hd.bpp/8);
        
        return NULL;
    
    static bool __user_font_get_glyph_dsc(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next) 
        if( unicode_letter>__g_xbf_hd.max || unicode_letter<__g_xbf_hd.min ) 
            return NULL;
        
        uint32_t unicode_offset = sizeof(x_header_t)+(unicode_letter-__g_xbf_hd.min)*4;
        uint32_t *p_pos = (uint32_t *)__user_font_getdata(unicode_offset, 4);
        if( p_pos[0] != 0 ) 
            glyph_dsc_t * gdsc = (glyph_dsc_t*)__user_font_getdata(p_pos[0], sizeof(glyph_dsc_t));
            dsc_out->adv_w = gdsc->adv_w;
            dsc_out->box_h = gdsc->box_h;
            dsc_out->box_w = gdsc->box_w;
            dsc_out->ofs_x = gdsc->ofs_x;
            dsc_out->ofs_y = gdsc->ofs_y;
            dsc_out->bpp   = __g_xbf_hd.bpp;
            return true;
        
        return false;
    
    //FangSong_GB2312,,-1
    //字模高度:18
    //XBF字体,外部bin文件
    lv_font_t myFont = 
        .get_glyph_bitmap = __user_font_get_bitmap,
        .get_glyph_dsc = __user_font_get_glyph_dsc,
        .line_height = 18,
        .base_line = 0,
    ;
    
  2. 在屏幕中显示中文

    #include "lvgl/lvgl.h"
    #include "lvgl_helpers.h"
    #include "esp_partition.h"
    LV_FONT_DECLARE(myFont);//引入字库
    static lv_obj_t * tv;
    static lv_style_t style_title;
    
    void fun(void)
    
        tv = lv_tabview_create(lv_scr_act(), NULL);   //以屏幕为父控件创建选项卡
        lv_obj_t * label = lv_label_create(tv, NULL);
        lv_style_init(&style_title);
        lv_style_set_text_font(&style_title, LV_STATE_DEFAULT, &myFont);
        lv_obj_add_style(label, LV_LABEL_PART_MAIN, &style_title);
        lv_obj_set_pos(label, 100,100);
        lv_label_set_text(label ,"你好世界2022-12-17");
    
    

    3 存在问题

    1. 文件之间的依赖行,即找不到所需的文件,这里要研究CMakeLists.txt文件
    2. 显示中文会很慢。

以上是关于中文字库简介,GB2312字库用法的主要内容,如果未能解决你的问题,请参考以下文章

第3版emWin教程第31章 emWin6.x的全字库的实现(GB2312编码,SPI Flash方案)

单片机上常用-GB2312GBK汉字取模与字库偏移地址的计算与汉字描点

字库芯片,了解一下!

字库芯片,了解一下!

GB2312编码

怎样在word中找到楷体gb2312