Skip to content

write_fonts::FontBuilder not very ergonomic for font modification #1321

Open
@simoncozens

Description

@simoncozens

Consider this (real) situation: a library has a number of functions - one which fixes problems with the name table; one which fixes problems with the fvar table instances; one which fixes problems with the STAT table. In Python, these would have signatures like:

fix_name(font: TTFont) # Modifies TTFont
fix_fvar(font: TTFont) 
fix_stat(font: TTFont)

How would we port this to Rust? Sounds easy enough, but these tables have dependencies on each other - altering the fvar table may require adding new name table entries or deleting some, and similarly for STAT. If we had a "writeable FontRef", this would be doable:

fix_name(font: &mut write_fonts::FontRef);
fix_fvar(font: &mut write_fonts::FontRef);
fix_stat(font: &mut write_fonts::FontRef);

The closest we have to that is a FontBuilder, but if we have a FontBuilder object, we can't get at the name table any more; there's no way to .get() a table from inside it. So instead right now, we are forced to do this:

fix_name(font: FontRef) -> Result<Vec<u8>, Error> { 
    let mut new_font = FontBuilder::new();
    let name: Name = font.name()?.to_owned_table();
    do_stuff(&mut name);
    new_font.add_table(&name_table)?;
    Ok(new_font.copy_missing_tables(font).build())
}

And now, if I want to fix the name and the fear and the STAT, I have to decompile, modify, copy, compile several times over. Urgh. The alternative is to return modified Name, Stat, etc. structs, but that doesn't really help - if you want to modify multiple things at once, you have to also take these modified structs as (individual!) inputs to your function instead of a FontRef, and that's also nasty for the user. What we want is a bag of write_fonts::table structs that we can compile when we've done modifying them - that would give us a writable FontRef, the write_fonts equivalent of a read_fonts::FontRef.

The reason we can't have this right now is that add_table compiles the table, and build just builds the offset table and the table directory. If we could instead stick write_fonts::table::Name, write_fonts::table::Fvar, etc. structs into the FontBuilder - and if build() did all the compilation at the end - then it would be much easier to get those table structs out again and re-modify them.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions