floem icon indicating copy to clipboard operation
floem copied to clipboard

Allow loading fonts dynamically

Open MinusGix opened this issue 1 year ago • 2 comments

Some programs need to load fonts dynamically because they're not installed on the system (ex: programs that package their fonts, or programs like pdf viewers that only have access at runtime).
It would be nice to allow this. I think it can be done with a newer version of cosmic-text, which exposes FontSystem as a parameter that can be passed around when constructing text.
I expect that we can capture most use-cases with a floem-wide FontSystem, but it would probably be easy to allow custom font systems as needed when constructing a TextLayout.
Though, newer versions of cosmic-text seem to get rid of TextLayout. However Buffer/BufferLine seem like they've become replacements, though I've only glanced at them.

MinusGix avatar Jul 26 '23 04:07 MinusGix

I previously did this by using a cosmic_text fontdb.

Then on text layouts I applied the font family loaded from the database.

This is some old code but this is how I did this.

    let (preview_font_family, set_preview_font_family) =
        create_signal(cx.scope, String::from("SF Pro Display"));
    let mut font_db = floem::cosmic_text::fontdb::Database::new();

    font_db.load_system_fonts();
    let font_families: Vec<String> = font_db
        .faces()
        .map(|val| {
            let fams = &val.families;
            fams.iter()
                .map(|(family, _)| family.clone())
                .map(|family| family.replace('.', ""))
                .collect()
        })
        .collect();
    let set: HashSet<String> = font_families.into_iter().collect();
    let mut font_families: im::Vector<String> = set.into_iter().collect();
    font_families.sort();

    // return
    stack(move || {
        (
            stack(move || {
                (
                    // preview window
                    container(|| {
                        rich_text(move || {
                            set_preview_text.update(|prev_text| {
                                prev_text.set_text(
                                    &main_text_input.get(),
                                    AttrsList::new(
                                        Attrs::new()
                                            .family(&[FamilyOwned::Name(preview_font_family.get())])
                                            .color(theme.with(|theme| {
                                                theme.get_color("function", Color::BLACK)
                                            }))
                                            .weight(floem::cosmic_text::Weight::LIGHT)
                                            .font_size(preview_text_size.get()), // .color(theme.foreground.color),
                                    ),
                                )
                            });
                            preview_text.get()
                        })
                    })

Could be nice to have a global font system though.

jrmoulton avatar Jul 27 '23 19:07 jrmoulton

Ah I misunderstood the use case you were talking about. I missed the important part where the need is non-system fonts

jrmoulton avatar Jul 27 '23 20:07 jrmoulton

This issue can be closed. Loading fonts can be done through the lapce fork of cosmic text with the load_font_* functions

jrmoulton avatar Jun 02 '24 17:06 jrmoulton

Example implementation https://github.com/lapce/lapce/blob/8b1fb7a2ffef3e4e71f686a91d661d2d2e5d558f/lapce-app/src/app.rs#L3512-L3535

panekj avatar Jun 02 '24 18:06 panekj