servo / font-kit

A cross-platform font loading library written in Rust
Apache License 2.0
657 stars 98 forks source link

"Ubuntu" matches "Ubuntu-ExtraBold" #245

Open SamRodri opened 1 month ago

SamRodri commented 1 month ago

On Ubuntu 24.04, run: $ cargo run --example match-font -- "Ubuntu"

Output:

Path: /usr/share/fonts/truetype/ubuntu/Ubuntu[wdth,wght].ttf
Index: 393216
Family name: Ubuntu
PostScript name: Ubuntu-ExtraBold
Style: Normal
Weight: Weight(400.0)
Stretch: Stretch(1.0)

Interesting $ fc-match "Ubuntu :weight=400" has the same error, but Firefox matches the correct font.

mrobinson commented 1 month ago

I think this is expected behavior. "Ubuntu" is the family name and "Ubuntu Extra Bold" is the postscript name of a variant within that family. You will need to look through all the variants to find the one you need.

SamRodri commented 1 month ago

I expected font_kit::source::SystemSource::new().select_best_match to get the regular Ubuntu, given that the weight is NORMAL=400

SamRodri commented 1 month ago

I had a look into this:

First FontConfig does not have the same bug, they just use a different weight scale, normal is "80" there: $ fc-match "Ubuntu :weight=80" outputs "Ubuntu" "Regular"

Second, the issue is that the Ubuntu font uses "named variation instances" to define multiple weights on the same TTF file (not a TTC), the OS/2 table is the same for the entire file, with the same usWeightClass, I don't know where the "named instances" are stored.

This test code:

let family = font_kit::source::SystemSource::new()
    .select_family_by_name("Ubuntu")
    .unwrap();
for handle in family.fonts() {
    let (path, index) = match &handle {
        font_kit::handle::Handle::Path { path, font_index } => (path, font_index),
        font_kit::handle::Handle::Memory { .. } => unreachable!(),
    };
    let font = handle.load().unwrap();
    println!(
        "{}, index={}, {}, {:?}",
        path.file_name().unwrap().to_string_lossy(),
        index,
        font.postscript_name().unwrap(),
        font.properties().weight,
    );
}

Outputs:

Ubuntu[wdth,wght].ttf, index=393216, Ubuntu-ExtraBold, Weight(400.0)
Ubuntu[wdth,wght].ttf, index=589824, Ubuntu-Condensed, Weight(400.0)
Ubuntu[wdth,wght].ttf, index=524288, Ubuntu-CondensedLight, Weight(400.0)
Ubuntu[wdth,wght].ttf, index=720896, Ubuntu-CondensedBold, Weight(400.0)
Ubuntu[wdth,wght].ttf, index=655360, Ubuntu-CondensedMedium, Weight(400.0)
Ubuntu[wdth,wght].ttf, index=786432, Ubuntu-CondensedExtraBold, Weight(400.0)
<Ubuntu-Italic[wdth,wght].ttf omitted>
Ubuntu[wdth,wght].ttf, index=65536, Ubuntu-Thin, Weight(400.0)
Ubuntu[wdth,wght].ttf, index=0, Ubuntu-Regular, Weight(400.0)
Ubuntu[wdth,wght].ttf, index=131072, Ubuntu-Light, Weight(400.0)
Ubuntu[wdth,wght].ttf, index=327680, Ubuntu-Bold, Weight(400.0)
Ubuntu[wdth,wght].ttf, index=262144, Ubuntu-Medium, Weight(400.0)
Ubuntu[wdth,wght].ttf, index=458752, Ubuntu-CondensedThin, Weight(400.0)

Notice the same weight for all "fonts".