如何通过read-fonts遍历字体表字段并获取其属性与值
解决字体表字段遍历的方法
你当前的代码仅遍历了字体目录中的表记录(仅包含表标签、偏移量等元信息),要获取每个表的实际字段内容,需要通过FontRef解析对应表的二进制数据,再根据不同表的结构访问其属性。以下是具体实现步骤和代码示例:
1. 导入所需的表类型
write-fonts为每个标准字体表提供了对应的结构体,按需导入常用表类型即可:
use write_fonts::read::{FontRef, tables::{Head, Hhea, Maxp, Name, Os2}}; use write_fonts::types::Tag;
2. 解析并遍历表字段
遍历表记录时,通过font.read_table(tag)获取表的二进制数据,匹配表标签解析为对应结构体后,直接访问并打印其字段属性和值:
use write_fonts::read::{FontRef, tables::{Head, Hhea, Maxp, Name, Os2}}; use write_fonts::types::Tag; fn main() { let path_to_my_font_file = std::path::Path::new("/Users/ollimeier/Documents/Vary-Black.otf"); let font_bytes = std::fs::read(path_to_my_font_file).unwrap(); let font = FontRef::new(&font_bytes).expect("failed to read font data"); for table_record in font.table_directory.table_records() { let tag = table_record.tag(); println!("\n=== 表 {} ===", tag); // 读取表的二进制数据并解析 match font.read_table(tag) { Ok(table_data) => { match tag { Tag::HEAD => { let head = Head::read(table_data).unwrap(); println!("版本: {:?}", head.version); println!("字体修订版本: {:?}", head.font_revision); println!("单位每em: {:?}", head.units_per_em); println!("创建时间: {:?}", head.created); } Tag::HHEA => { let hhea = Hhea::read(table_data).unwrap(); println!("上升值: {:?}", hhea.ascent); println!("下降值: {:?}", hhea.descent); println!("行间距: {:?}", hhea.line_gap); println!("最大前进宽度: {:?}", hhea.advance_width_max); } Tag::MAXP => { let maxp = Maxp::read(table_data).unwrap(); println!("字形总数: {:?}", maxp.num_glyphs); println!("最大轮廓点数: {:?}", maxp.max_points); println!("最大轮廓段数: {:?}", maxp.max_contours); } Tag::NAME => { let name = Name::read(table_data).unwrap(); println!("名称记录数: {:?}", name.name_records.len()); for (idx, record) in name.name_records.iter().enumerate() { println!("记录{}: 类型={}, 语言={}, 内容={:?}", idx, record.name_id, record.lang_id, record.string(&name)); } } Tag::OS_2 => { let os2 = Os2::read(table_data).unwrap(); println!("字体权重: {:?}", os2.us_weight_class); println!("字体宽度: {:?}", os2.us_width_class); println!("xAvgCharWidth: {:?}", os2.x_avg_char_width); } _ => { println!("暂未处理该表类型,原始数据长度: {} 字节", table_data.len()); } } } Err(e) => { println!("读取表失败: {}", e); } } } }
关键说明
- 表解析逻辑:每个标准字体表都自带
read方法,传入表的二进制数据即可解析为对应结构体。 - 字段访问:解析后的结构体包含该表的所有定义字段,直接通过点语法(如
head.units_per_em)访问即可。 - 扩展支持:如果需要处理更多表类型,只需导入对应的结构体(如
Cmap、Glyf),并在match分支中添加对应解析逻辑即可。
内容的提问来源于stack exchange,提问作者Olli Meier
相关产品推荐
相关产品推荐

