Skip to content

Methods for Displaying Chinese Characters in Embedded Rust

kingzcheung
Published date:
Edit this post

Due to limited resources in embedded scenarios, default display libraries typically only support English, numbers, and a small set of characters, but not Chinese characters. For example, none of the built-in character sets in embedded-graphics support Chinese character display.

Therefore, we need to generate our own Chinese character display library. This library can generate Chinese character sets supported by embedded-graphics.

https://github.com/embedded-graphics/bdf

Before generating, you need to convert the open-type format Chinese character set file to BDF format. You can use the otf2bdf tool to complete this conversion.

sudo apt install otf2bdf
#or
brew install otf2bdf

The generated API looks something like this:


fn main() {
    let font = FontConverter::new("Regular.bdf", "REGULAR_FONT")
        //.glyphs('a'..='z')
        .glyphs('\u{0000}'..='\u{007F}') // ASCII
        .glyphs('\u{4E00}'..='\u{9FFF}') // Common Chinese font range
        .glyphs('\u{2E80}'..='\u{2EF3}') // Common traditional Chinese character range
        .missing_glyph_substitute('?') // Substitute character
        .convert_eg_bdf()
        .unwrap();
 let font: MonoFontOutput = converter.convert_mono_font()?;
   font.save_png(png)?;
}

If the characters to be displayed are very fixed and limited, we can completely manually specify the Chinese characters to include. For example, when I generate a font library for displaying a temperature and humidity meter, I only need these characters:

温,湿,度,0,1,2,3,4,5,6,7,8,9,C,°,:,%

Just specify directly:

converter.glyphs(&['温','湿','度','0','1','2','3','4', '5', '6', '7', '8', '9','C','°',':',',' ,'%',' '][..]);

Similar command:

cargo run -r --bin eg-font-converter  ./vivosans.bdf REGULAR_FONT --rust font.rs  --data regular_font.data

Copy the two generated files above to your project and you can use them.

However, the Chinese and English character spacing generated by the above method is very large and doesn’t look good.

IMG_20260209_221127

The bdf project also provides an eg-bdf format, which displays Chinese correctly. So I modified the original generation command and added a --convert-type parameter:

match args.convert_type {
        ConvertType::EgBdf => {
            let font: EgBdfOutput = converter.convert_eg_bdf()?;

            if let Some(rust) = &args.rust {
                std::fs::write(rust, font.rust())
                    .with_context(|| format!("Failed to write Rust file {}", rust.to_string_lossy()))?;
            }

            if let Some(data) = &args.data {
                std::fs::write(data, font.data())
                    .with_context(|| format!("Failed to write data file {}", data.to_string_lossy()))?;
            }

            // eg-bdf uses save method
            font.save("./output")?;
        }
        ConvertType::MonoFont => {
            let font: MonoFontOutput = converter.convert_mono_font()?;

            if let Some(rust) = &args.rust {
                std::fs::write(rust, font.rust())
                    .with_context(|| format!("Failed to write Rust file {}", rust.to_string_lossy()))?;
            }

            if let Some(data) = &args.data {
                std::fs::write(data, font.data())
                    .with_context(|| format!("Failed to write data file {}", data.to_string_lossy()))?;
            }

            if let Some(png) = &args.png {
                font.save_png(png)?;
            }
        }
    }
cargo run -r --bin eg-font-converter  \
    ./vivosans.bdf REGULAR_FONT  \
    --glyph-list 温,湿,度,0,1,2,3,4,5,6,7,8,9,C,°,:,% \
    --convert-type eg-bdf

Similarly, put the generated files back into the project, and add the eg-bdf crate from the bdf project (this crate is not published to crates.io) to your project’s Cargo.toml.

Use it directly as follows:

let temp_str = alloc::format!("温度:{}°C", temp);
let hum_str = alloc::format!("湿度:{}%", hum);
let temp_character_style = BdfTextStyle::new(&REGULAR_FONT, Rgb565::new(31, 41, 0)); // White
let hum_character_style = BdfTextStyle::new(&REGULAR_FONT, Rgb565::new(0, 63, 31)); // White

The result is shown below:

IMG_20260209_225748

Previous
Rust嵌入式开发:在st7789屏幕上显示图片
Next
在嵌入式 Rust 中显示中文字符的方法