Font Porting

This chapter will analyze the font library code segment and explain how to replace HoneyGUI’s native font library with a custom one provided by the developer, or how to add customized features.

Dot Matrix Font Library Porting

Glyph Loading

Text Encoding Conversion

In the file font_mem.c, within the function gui_font_get_dot_info(), process_content_by_charset() parses the text content of the text widget and saves it as Unicode (UTF-32) in unicode_buf. The number of Unicode characters is returned in unicode_len.

uint32_t *unicode_buf = NULL;
uint16_t unicode_len = 0;
unicode_len = process_content_by_charset(text->charset, text->content, text->len, &unicode_buf);
if (unicode_len == 0)
{
    gui_log("Warning! After process, unicode len of text: %s is 0!\n", text->base.name);
    text->font_len = 0;
    return;
}

For the specific implementation of process_content_by_charset(), please refer to draw_font.c.

Note

The parsing process supports UTF-8, UTF-16, and UTF-32.

Subsequently, Unicode information in unicode_buf will be used to index text data from the font library.

Text encoding conversion for minor languages, such as Arabic character concatenation and other calculations involving Unicode, can be performed either before or after the encoding conversion. If the conversion is done later, unicode_len must be updated accordingly.

Note

The unit of unicode_len is bytes, not the number of characters.

Font Library Indexing

In the file font_mem.c, within the function gui_font_get_dot_info(), the Unicode value is parsed and then used to index glyph information from the font library designated by the text widget.

Since the font library tool has the crop attribute and two indexing modes, different parsing code is used to find text data and dot matrix data in the font library file using the Unicode value.

The purpose of the font library parsing code is to populate the chr structure array, which is structured as follows:

typedef struct
{
    uint32_t unicode;
    int16_t x;
    int16_t y;
    int16_t w;
    int16_t h;
    uint8_t char_y;
    uint8_t char_w;
    uint8_t char_h;
    uint8_t *dot_addr;
    uint8_t *buf;
    gui_img_t *emoji_img;
} mem_char_t;

Each member has the following meanings:

  • Unicode: The Unicode of the dot matrix text, expressed in UTF-32LE format.

  • x: The X-coordinate of the upper-left corner of the dot matrix text boundary, determined during layout, used to set the drawing coordinates of the text.

  • y: The Y-coordinate of the upper-left corner of the dot matrix text boundary, determined during layout, used to set the drawing coordinates of the text.

  • w: The data width of the character in the dot matrix data. Due to byte alignment and compression characteristics, this value is not always equal to the font size.

  • h: The height of the dot matrix text, which is always equal to the font size, used to define the basic drawing area and for multi-line layout.

  • char_y: The number of blank rows above the character, representing the Y-coordinate distance between the topmost pixel of the text dot matrix and the upper boundary, used to constrain the drawing area.

  • char_w: The pixel width of the character, representing the difference in the X-coordinate between the leftmost boundary (starting point) and the rightmost pixel of the text. This value is used to constrain the drawing area during drawing and represents the text width during layout.

  • char_h: The pixel height of the character, representing the Y-coordinate distance between the bottommost pixel of the text dot matrix and the upper boundary. The value of char_h minus char_y gives the actual pixel height of the dot matrix.

  • dot_addr: The starting address of the dot matrix data corresponding to the text.

  • emoji_img: The pointer to the widget corresponding to the Emoji image. This value is NULL if the Emoji feature is not used.

https://foruda.gitee.com/images/1729762447610163035/4ae24c0c_9325830.png

Glyph Example

During the font library indexing phase, all members of chr except for the x and y coordinates will be populated to prepare for the next step of layout.

Note

Due to differences in data storage rules under different modes, the drawing areas also vary. For example, char_y and char_h are only effective when crop=1 and index_method=0.

Since this stage involves using the Unicode to look up width information for the dot matrix text and the dot matrix data pointer, it’s best to complete the Unicode-level text transformations before this step. For example, Arabic script ligatures should be handled in this stage, whereas Thai glyph fusion should be handled during the layout stage.

If you are porting using your custom font library, you can populate the chr data structures using information from your custom font library. The default parts can be used for the subsequent layout and drawing stages.

Layout

The text widget supports various layout modes.

The specific layout functionality is located in the file font_mem.c in the function gui_font_mem_layout(). Each layout mode has a different layout logic; however, all depend on the glyph information chr and the boundary information rect provided by the text widget.

The rect struct array is structured as follows:

typedef struct gui_text_rect
{
    int16_t x1;
    int16_t y1;
    int16_t x2;
    int16_t y2;
    int16_t xboundleft;
    int16_t xboundright;
    int16_t yboundtop;
    int16_t yboundbottom;
} gui_text_rect_t;

The rect is the display range of the widget passed from the widget layer. In this structure, x1 and x2 represent the X-coordinates of the left and right borders, respectively, while y1 and y2 represent the Y-coordinates of the top and bottom borders, respectively.

These values are calculated internally by the widget based on its position and size at the time of creation. From the four coordinates of rect, you can calculate rect_w (width) and rect_h (height).

There are also four bound values used by the scrolling text widget (scroll_text) to handle display boundaries. These bound values are currently not used by the regular text widget (text).

Developers can add new layout modes as per their requirements.

By enabling the English word wrapping feature (wordwrap) via the function gui_text_wordwrap_set, the multi-line layout will adhere to English word wrapping rules to prevent words from being split across lines.

Character Rendering

The code for rendering bitmap characters is located in the rtk_draw_unicode function in font_mem.c.

You can enable matrix operations for the text widget to support text scaling effects; the rendering code for this feature is in rtk_draw_unicode_matrix in font_mem_matrix.c.

Additionally, you can enable a feature to convert text into an image for achieving complex effects; this rendering code is found in gui_font_bmp2img_one_char in font_mem_img.c.

The character rendering stage does not involve any layout information; it only reads the glyph information and renders it to the screen buffer.

Each character’s rendering is constrained by three boundaries: the widget’s boundary, the screen’s boundary, and the current character’s boundary.

If developers wish to use a special font library for rendering, they need to modify the bitmap data parsing code and draw the pixels into the screen buffer.

API

Defines

FONT_MALLOC_PSRAM(x)
FONT_FREE_PSRAM(x)
FONT_FILE_BMP_FLAG

Functions

uint8_t gui_font_mem_init(uint8_t *font_bin_addr)

Initialize the character binary file and store the font and corresponding information in the font list.

Parameters:

font_bin_addr – the binary file address of this font type

uint8_t gui_font_mem_init_ftl(uint8_t *font_bin_addr)

Initialize the character binary file and store the font and corresponding information in the font list.

Parameters:

font_bin_addr – font file address

Returns:

uint8_t

uint8_t gui_font_mem_init_fs(uint8_t *font_bin_addr)

Initialize the character binary file and store the font and corresponding information in the font list.

Parameters:

font_bin_addr – font file address

Returns:

uint8_t

uint8_t gui_font_mem_init_mem(uint8_t *font_bin_addr)

Initialize the character binary file and store the font and corresponding information in the font list.

Parameters:

font_bin_addr – font file address

Returns:

uint8_t

uint8_t gui_font_mem_destroy(uint8_t *font_bin_addr)

Destroy this flot type in font list.

Parameters:

font_bin_addr – font file address

Returns:

uint8_t

void gui_font_mem_load(gui_text_t *text, gui_text_rect_t *rect)

Preprocessing of bitmap fonts using internal engines.

Parameters:
  • text – Widget pointer

  • rect – Widget boundary

void gui_font_mem_draw(gui_text_t *text, gui_text_rect_t *rect)

Drawing of bitmap fonts using internal engine.

Parameters:
  • text – Widget pointer

  • rect – Widget boundary

void gui_font_mem_unload(gui_text_t *text)

Post-processing work for drawing bitmap fonts using internal engines.

Parameters:

text – Widget pointer

void gui_font_mem_obj_destroy(gui_text_t *text)

GUI_FONT_SRC_BMP text widget destroy function.

Parameters:

text – Widget pointer

uint32_t gui_get_mem_char_width(void *content, void *font_bin_addr, TEXT_CHARSET charset)

Get the pixel width of the text in the current font file.

Parameters:
  • content – text pointer

  • font_bin_addr – font file address

  • charset – text encoding format

Returns:

uint32_t

uint32_t gui_get_mem_utf8_char_width(void *content, void *font_bin_addr)

Get the pixel width of the utf-8 text in the current font file.

Parameters:
  • content – text pointer

  • font_bin_addr – font file address

Returns:

uint32_t

uint8_t get_fontlib_by_size(uint8_t font_size)

Get the fontlib name object.

Parameters:

font_size – font size

Returns:

uint8_t font lib index

uint8_t get_fontlib_by_name(uint8_t *font_file)

Get the fontlib name object.

Parameters:

font_file – font file

Returns:

uint8_t font lib index

void gui_font_mem_layout(gui_text_t *text, gui_text_rect_t *rect)

text layout by mode

Parameters:
  • text – Widget pointer

  • rect – Widget boundary

void gui_font_get_dot_info(gui_text_t *text)

get dot info by utf-8 or utf-16

Parameters:

text – Widget pointer

struct GUI_CHAR_HEAD

Public Members

uint8_t char_y
uint8_t baseline
uint8_t char_w
uint8_t char_h
struct mem_char_t

mem char struct start

Public Members

uint32_t unicode
int16_t x
int16_t y
int16_t w
int16_t h
uint8_t char_y
uint8_t char_w
uint8_t char_h
uint8_t *dot_addr
uint8_t *buf
gui_img_t *emoji_img
struct MEM_FONT_LIB

mem char struct end

Public Members

uint8_t *font_file
uint8_t font_size
FONT_SRC_MODE type
uint8_t *data
struct GUI_FONT_HEAD_BMP

Public Members

uint8_t head_length
uint8_t file_type
uint8_t version[4]
uint8_t font_size
uint8_t rendor_mode
uint8_t bold
uint8_t italic
uint8_t scan_mode
uint8_t index_method
uint8_t crop
uint8_t rsvd
uint32_t index_area_size
uint8_t font_name_length
uint8_t *font_name

Enums

enum TEXT_CHARSET

text rect struct end

text encoding format enum

Values:

enumerator UTF_8
enumerator UTF_16
enumerator UTF_16LE
enumerator UNICODE_ENCODING
enumerator UTF_16BE
enumerator UTF_32LE
enumerator UTF_32BE

Functions

uint16_t process_content_by_charset(TEXT_CHARSET charset_type, uint8_t *content, uint16_t len, uint32_t **p_buf_ptr)

Converts content from a specified charset to Unicode code points.

Parameters:
  • charset_type – The charset type of the content.

  • content – Input content to be converted.

  • len – Length of the input content in bytes.

  • p_buf_ptr – Pointer to the buffer that will hold the Unicode code points.

Returns:

The length of the Unicode code points array.

uint32_t get_len_by_char_num(uint8_t *utf8, uint32_t char_num)

Get the len by char num object.

Parameters:
  • utf8

  • char_num

Returns:

uint32_t

uint32_t generate_emoji_file_path_from_unicode(const uint32_t *unicode_buf, uint32_t len, char *file_path)

Function to generate file path based on a given Unicode sequence.

Parameters:
  • unicode_buf

  • len

  • file_path

Returns:

int

struct gui_text_rect_t

text rect struct start

Public Members

int16_t x1
int16_t y1
int16_t x2
int16_t y2
int16_t xboundleft
int16_t xboundright
int16_t yboundtop
int16_t yboundbottom