rust 如何通过读取字体表的字段循环

x7yiwoj4  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(102)

我想遍历给定字体的所有字体表,并打印/获取表内容属性和值,但我不知道如何做到这一点。

[dependencies]
write-fonts = { version = "*", features = ["read"] }
use write_fonts::read::FontRef;

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 in font.table_directory.table_records() {
        let tag = table.tag();

        println!("    table {tag} ...");
        println!("    {tag}: {:?}", table);

        //for table_field in table {
        //    println!("    table field {table_field} ...");
        //}
    }
}
xmd2e60i

xmd2e60i1#

要从table_directory遍历一个表,你必须调用方法traverse来获得一个RecordResolver,然后实现SomeTable,得到一个iter,你可以将其转换为:

use write_fonts::read::traversal::{SomeRecord, SomeTable};
use write_fonts::read::FontRef;

fn main() {
    let font_bytes =
        include_bytes!("/usr/share/fonts/adobe-source-code-pro/SourceCodePro-Black.otf");
    let font = FontRef::new(font_bytes).expect("failed to read font data");

    for table in font.table_directory.table_records() {
        let tag = table.tag();

        println!("    table {tag} ...");
        println!("    {tag}: {:?}", table);

        let table = table.clone().traverse(font.table_data(tag).unwrap());
        for table_field in (&table as &dyn SomeTable).iter() {
            println!("{}: {:?}", table_field.name, table_field.value);
        }
    }
}

图书馆的API肯定是.

8zzbczxx

8zzbczxx2#

我设法找到了自己问题的答案:

use font_types::Tag;
use read_fonts::{traversal::SomeTable, FileRef, FontRef, ReadError, TableProvider, TopLevelTable};
use read_fonts::tables;

fn get_some_table<'a>(
    font: &FontRef<'a>,
    tag: Tag,
) -> Result<Box<dyn SomeTable<'a> + 'a>, ReadError> {
    match tag {
        tables::gpos::Gpos::TAG => font.gpos().map(|x| Box::new(x) as _),
        tables::gsub::Gsub::TAG => font.gsub().map(|x| Box::new(x) as _),
        tables::cmap::Cmap::TAG => font.cmap().map(|x| Box::new(x) as _),
        tables::fvar::Fvar::TAG => font.fvar().map(|x| Box::new(x) as _),
        tables::avar::Avar::TAG => font.avar().map(|x| Box::new(x) as _),
        tables::gdef::Gdef::TAG => font.gdef().map(|x| Box::new(x) as _),
        tables::glyf::Glyf::TAG => font.glyf().map(|x| Box::new(x) as _),
        tables::head::Head::TAG => font.head().map(|x| Box::new(x) as _),
        tables::hhea::Hhea::TAG => font.hhea().map(|x| Box::new(x) as _),
        tables::hmtx::Hmtx::TAG => font.hmtx().map(|x| Box::new(x) as _),
        tables::loca::Loca::TAG => font.loca(None).map(|x| Box::new(x) as _),
        tables::maxp::Maxp::TAG => font.maxp().map(|x| Box::new(x) as _),
        tables::name::Name::TAG => font.name().map(|x| Box::new(x) as _),
        tables::post::Post::TAG => font.post().map(|x| Box::new(x) as _),
        tables::colr::Colr::TAG => font.colr().map(|x| Box::new(x) as _),
        tables::stat::Stat::TAG => font.stat().map(|x| Box::new(x) as _),
        tables::vhea::Vhea::TAG => font.vhea().map(|x| Box::new(x) as _),
        tables::vmtx::Vmtx::TAG => font.vmtx().map(|x| Box::new(x) as _),
        tables::os2::Os2::TAG => font.os2().map(|x| Box::new(x) as _),
        //tables::cff::Cff::TAG => font.cff().map(|x| Box::new(x) as _), #^^^^^^^^^^^ the trait `SomeTable<'a>` is not implemented for `Cff<'_>`
        _ => Err(ReadError::TableIsMissing(tag)),
    }
}

pub const DSIG: Tag = Tag::new(b"DSIG");

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 tag in font
        .table_directory
        .table_records()
        .iter()
        .map(|rec| rec.tag())
    {
        println!("    table {tag} ...");
        let table = get_some_table(&font, tag);

        if !!!matches!(tag, tables::cff::Cff::TAG | tables::cff2::Cff2::TAG | DSIG ) {
            for (_i, field) in table.unwrap().iter().enumerate() {
                println!("    field.name: {:?}",field.name);
                println!("    field.value: {:?}", field.value);
            }
        }

    }

}

它可能不是最好的代码,但它工作。所以,我非常感谢人们对代码的改进。它包含存储在这里的代码:Github链接[1]:https://github.com/googlefonts/fontations/blob/d4e07eb3b45836f3241e5a5343fdb697c40d978b/otexplorer/src/main.rs#L100

相关问题