LVGL V8 font format

There are mainly two kinds of information stored in the font file, one is the character lattice array and the other is the corresponding unicode encoding array data. When the single-chip microcomputer parses the font, it finds the corresponding character lattice array according to the unicode encoding.

The dot matrix data in the font file generated by the LVGL font format is not like the fonts we usually use in single-chip microcomputers.
First of all, the number of bytes occupied by the dot matrix data of each character is not equal, such as single quotes "," and "@" characters, the number of bytes they occupy is not equal, this is to save space and empty the characters Rows and columns where not converted to dot matrix. In this case, other information is required to control the display position of the characters. Therefore, in addition to the character lattice array and unicode array, there is an important array glyph_dsc[] in the font data.

LVGL font structure

uint8_t   glyph_bitmap[]; 					//字形屏幕像素映射(字符点阵数组,将字符中空的行和列的地方不转化为点阵)
lv_font_fmt_txt_glyph_dsc_t   glyph_dsc; 	//描述unicode偏移、字形大小、位置偏移
uint16_t   unicode_list_0; 				    //unicode 列表(字符映射)
lv_font_fmt_txt_cmap_t   cmaps; 			//cmaps收集 unicode 列表和字符偏移
lv_font_fmt_txt_dsc_t   font_dsc; 		    //字体描述,用于将上面的信息收集打包
lv_font_t   ch_word; 						//程序中 label 等组件可以使用的字库。

parse font files

The program will first obtain the UTF-8 encoding of the character to be displayed, then convert UTF-8 to uncode encoding, then search the index of the corresponding unicode encoding in the unicode array in the font file, and then use the index to find the corresponding character in glyph_dsc data. Since unicode is arranged in ascending order, the median search method can be used to improve the search speed.

pixel depth bpp

The color of a pixel is described by how many bits of data in the computer. Computers use binary bits to represent the data of a pixel. The more data bits used to represent a pixel, the richer and finer the color value of the pixel, and the deeper the color depth.
There are several pixel depths: 1-bit, 2-bit, 4-bit, 8-bit, 16-bit, 24-bit, 32-bit.

The bpp of the font can be set to 1, 2, or 4. When a larger bpp value is selected, the required flash storage resources will also increase exponentially, but the larger the bpp value, the smoother the edge of the drawn font without glitches. Make the UI interface of our products look more magnificent.
insert image description here
For 1bpp fonts: use 1 bit to represent 1 pixel point, each pixel has only two states of on and off, and 1 Chinese character occupies 256/8=32Byte bytes
For 2bpp fonts: use 2 bits to represent 1 pixel point, Realize sub-pixel rendering, 1 Chinese character takes up 256 2/8=64Byte of space
For 4bpp fonts: use 4 bits to represent 1 pixel, realize sub-pixel rendering, 1 Chinese character takes up 256 4
/8=128Byte of space

Glyph screen pixmap

//存储符号的图像
static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
    
    
    /* U+56DE "回" */
    0x0, 0x11, 0xfb, 0xc1, 0x40, 0x29, 0xe5, 0x24,
    0xa4, 0x94, 0xb2, 0x98, 0x50, 0xa, 0x1, 0x7f,
    0xa8, 0xc, 0x0, 0x0,
    /* U+6D41 "流" */
    0x1, 0x0, 0x1, 0x0, 0xc0, 0x0, 0x3f, 0xc0,
    0x8, 0x0, 0x24, 0x13, 0xfc, 0x8, 0x0, 0x12,
    0xa0, 0x25, 0x40, 0x92, 0x81, 0x25, 0x26, 0x4a,
    0x45, 0x14, 0x84, 0xf, 0x80,
    /* U+96EA "雪" */
    0x0, 0x60, 0x7e, 0x4, 0x20, 0x9f, 0xfe, 0x82,
    0x20, 0xeb, 0x0, 0x2e, 0xe, 0x80, 0x1, 0xe0,
    0x78, 0x80, 0xa, 0x7, 0xd0, 0x0, 0x40, 0xff,
    0x0,
    /* U+98CE "风" */
    0x0, 0x0, 0x23, 0xc0, 0x78, 0x80, 0x85, 0x1,
    0xa, 0x2, 0xa4, 0x4, 0xc8, 0x8, 0x90, 0x13,
    0x20, 0x49, 0x20, 0xa2, 0x49, 0x80, 0xa4, 0x0,
    0xc0, 0x0, 0x80, 0x0, 0x0
};

Observing the glyph screen pixel mapping array, it can be obtained
that "back" occupies 20Byte
"stream" occupies 29Byte
"snow" occupies 25Byte
"wind" occupies 29Byte

font description

//这描述了一个字形
typedef struct {
    
    
#if LV_FONT_FMT_TXT_LARGE == 0
    uint32_t bitmap_index : 20;     /**< 字符对应的字模数据索引   Start index of the bitmap. A font can be max 1 MB.*/
    uint32_t adv_w : 12;            /**< 字符宽度,在此宽度之后绘制下一个字形。8.4 format(存储real_value * 16)。                Draw the next glyph after this width. 8.4 format (real_value * 16 is stored).*/
    uint8_t box_w;                  /**< 字模宽度                Width of the glyph's bounding box*/
    uint8_t box_h;                  /**< 字模高度                Height of the glyph's bounding box*/
    int8_t ofs_x;                   /**< 字模水平方向偏移(右边为正向)      x offset of the bounding box*/
    int8_t ofs_y;                   /**< 字模竖直方向偏移(上边为正向)(当字符需要在基线以下显示时使用这个参数让字模下沉)y offset of the bounding box. Measured from the top of the line*/
#else
    uint32_t bitmap_index;          /**< Start index of the bitmap. A font can be max 4 GB.*/
    uint32_t adv_w;                 /**< Draw the next glyph after this width. 28.4 format (real_value * 16 is stored).*/
    uint16_t box_w;                 /**< Width of the glyph's bounding box*/
    uint16_t box_h;                 /**< Height of the glyph's bounding box*/
    int16_t ofs_x;                  /**< x offset of the bounding box*/
    int16_t ofs_y;                  /**< y offset of the bounding box. Measured from the top of the line*/
#endif
} lv_font_fmt_txt_glyph_dsc_t;
static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
    
    
    {
    
    .bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */,
    {
    
    .bitmap_index = 0, .adv_w = 256, .box_w = 11, .box_h = 14, .ofs_x = 3, .ofs_y = -1},       //回
    {
    
    .bitmap_index = 20, .adv_w = 256, .box_w = 15, .box_h = 15, .ofs_x = 0, .ofs_y = -1},		//流
    {
    
    .bitmap_index = 49, .adv_w = 256, .box_w = 14, .box_h = 14, .ofs_x = 1, .ofs_y = -1},		//雪
    {
    
    .bitmap_index = 74, .adv_w = 256, .box_w = 15, .box_h = 15, .ofs_x = 1, .ofs_y = -2}		//风
};
  1. Member bitmap_index:
    From the array glyph_dsc, it can also be obtained from the array glyph_dsc that the screen pixel mapping of Chinese character glyphs occupies bytes:
    the index of the glyph data corresponding to the character "hui"bitmap_index=0
    The font data index corresponding to the character of "stream"bitmap_index=20, so "Hui" occupies 20 bytes
    Function: According to this data, the offset of each Chinese character in the glyph description array can be located
  2. Member adv_w:
    Indicates the character width, after which the next glyph is drawn.
    Because the 16*16 font (256 pixels) is selected, after drawing 256 pixels, it is the starting pixel of the next glyph
  3. Members box_w and box_h
    font width and font height
    insert image description here

cmaps structure

cmaps collects unicode lists and character offsets

unicode list

static const uint16_t unicode_list_0[] = {
    
    
    0x0, 0x1663, 0x400c, 0x41f0
};

/* U+56DE "back" /, / U+6D41 "flow" /, / U+96EA "snow" /, / U+98CE "wind" */
The minimum Unicode encoding of "back" is 0x56DE =22238
"flow" Unicode encoding minimum 0x6D41 = 27969
"Snow" Unicode encoding minimum 0x96EA = 38634
"Wind" Unicode encoding maximum 0x98CE = 39118

The unicode_list_0 array stores the offset of Unicode relative to the first character Unicode

  • unicode_list_0[0] =0x0, indicating that the Unicode offset of "Hui" is 0 relative to "Hui"
  • unicode_list_0[1] =0x1663, indicating that the Unicode offset of "stream" relative to "back" is 0x1663
  • unicode_list_0[2] =0x400c, indicating that the Unicode offset of "snow" relative to "back" is 0x400c
  • unicode_list_0[3] =0x41f0, indicating that the Unicode offset of "wind" relative to "back" is 0x41f0

Structure lv_font_fmt_txt_cmap_t cmaps member analysis

static const lv_font_fmt_txt_cmap_t cmaps[] =
{
    
    
    {
    
    
		.range_start = 22238, 
		.range_length = 16881, 
		.glyph_id_start = 1,
		.unicode_list = unicode_list_0, 
		.glyph_id_ofs_list = NULL, 
		.list_length = 4, 
		.type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
    }
};
  1. Member uint32_t range_start
    the first Unicode character in this range, because "back" is the first character, so .range_start = 22238,

  2. Member uint16_t range_length
    The number of Unicode characters associated with this range.
    "Back" is the first character 22238, "wind" is the last character 39118, the last Unicode character = range_start + range_length - 1
    so .range_length = 39118 - 22238 + 1 = 16881;

  3. Member uint16_t glyph_id_start
    The first glyph ID of this range (the array index of ' glyph_dsc '), because the glyph_dsc array index is reserved (id = 0 reserved), so glyph_id_start starts from 1.

  4. The member uint16_t *unicode_list
    pointer points to unicode_list_0.

  5. member void *glyph_id_ofs_list

  6. member uint16_t list_length
    length of 'unicode_list' and/or 'glyph_id_ofs_list'

  7. Member lv_font_fmt_txt_cmap_type_t type
    The type of character mapping

font_dsc structure

lv_font_fmt_txt_dsc_t font_dsc; //Font description, used to collect and package the above information

//描述存储字体的附加数据
#if LV_VERSION_CHECK(8, 0, 0)
/*存储所有自定义的字体数据*/
static  lv_font_fmt_txt_glyph_cache_t cache;
static const lv_font_fmt_txt_dsc_t font_dsc = {
    
    
#else
static lv_font_fmt_txt_dsc_t font_dsc = {
    
    
#endif
    .glyph_bitmap = glyph_bitmap, 	//所有字形的位图
    .glyph_dsc = glyph_dsc,       	//描述符号
    .cmaps = cmaps,					//将字形映射到Unicode字符。' lv_font_cmap_fmt_txt_t '变量的数组
	//存储字距调整值
	.kern_dsc = NULL,	//可以是' lv_font_fmt_txt_kern_pair_t *或' lv_font_kern_classes_fmt_txt_t * '根据“kern_classes”
    .kern_scale = 0,     			//按12.4格式缩放kern值
    .cmap_num = 1,					//cmap表的个数
    .bpp = 1,						//像素深度bpp: 1, 2, 4
    .kern_classes = 0,     			//“kern dsc”类型
    .bitmap_format = 0,             //位图的存储格式为' lv_font_fmt_txt_bitmap_format_t '
#if LV_VERSION_CHECK(8, 0, 0)
    .cache = &cache					//缓存最后一个字母和字形id
#endif
};

Font ch_word structure

/*初始化公共通用字体描述符*/
#if LV_VERSION_CHECK(8, 0, 0)
const lv_font_t ch_word = {
    
    
#else
lv_font_t ch_word = {
    
    
#endif
    .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt,    	/*从自定义字体数据中获取字形数据的函数指针*/
    .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt,    	/*从自定义字体数据中获取字形位图的函数指针*/
    .line_height = 17,          						/*字体所需的最大行高*/
    .base_line = 3,             						/*从底线开始测量基线*/
#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0)
    .subpx = LV_FONT_SUBPX_NONE,                        /*位图可以放大3倍以实现亚像素渲染*/
#endif
#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8
    .underline_position = -4,                           /*下划线顶部与基线之间的距离(< 0表示基线以下)*/
    .underline_thickness = 1,							/*下划线的厚度*/
#endif
    .dsc = &font_dsc           /*自定义字体数据。将通过' get_glyph_bitmap/dsc '访问*/
};

Font use

The font library needs to be declared before it is used

LV_FONT_DECLARE(ch_word); //Declare ch_word font

static lv_style_t style;
lv_style_set_text_font(&style,&ch_word);       //设置样式字体

Guess you like

Origin blog.csdn.net/m0_37187962/article/details/125577898