alexheretic / ab-glyph

Rust API for loading, scaling, positioning and rasterizing OpenType font glyphs
Apache License 2.0
372 stars 24 forks source link

About font scale_factor calculate #14

Closed TakWolf closed 4 years ago

TakWolf commented 4 years ago

For example:

    let font = FontRef::try_from_slice(include_bytes!("../assets/SourceHanSansSC/SourceHanSansSC-Regular.otf")).unwrap();
    let font_size = 24.0;
    let px_scale_font = font.as_scaled(font_size);

    dbg!(font.units_per_em().unwrap());
    dbg!(font.height_unscaled());
    dbg!(font.ascent_unscaled());
    dbg!(font.descent_unscaled());
    dbg!(px_scale_font.ascent());
    dbg!(px_scale_font.descent());

    println!("font size as units per em");
    let scale_factor = font_size / font.units_per_em().unwrap();
    dbg!(scale_factor);
    dbg!(font.ascent_unscaled() * scale_factor);

    println!("font size as height units");
    let scale_factor = font_size / font.height_unscaled();
    dbg!(scale_factor);
    dbg!(font.ascent_unscaled() * scale_factor);

output:

[src/main.rs:10] font.units_per_em().unwrap() = 1000.0
[src/main.rs:11] font.height_unscaled() = 1448.0
[src/main.rs:12] font.ascent_unscaled() = 1160.0
[src/main.rs:13] font.descent_unscaled() = -288.0
[src/main.rs:14] px_scale_font.ascent() = 19.226519
[src/main.rs:15] px_scale_font.descent() = -4.773481
font size as units per em
[src/main.rs:19] scale_factor = 0.024
[src/main.rs:20] font.ascent_unscaled() * scale_factor = 27.84
font size as height units
[src/main.rs:24] scale_factor = 0.016574586
[src/main.rs:25] font.ascent_unscaled() * scale_factor = 19.226519

In font Roboto, units per em = 1000, height = 1448 so the text rasterize seems smaller.

Font size is 24px, left is in chrome, right is in ab_glyph.

image

I am not sure which is correct, but I found in another font parse library fontdue: It use units_per_em.

https://github.com/mooman219/fontdue/blob/master/src/font.rs#L243-L247

    /// Calculates the glyph scale factor for a given px size.
    #[inline(always)]
    fn scale_factor(px: f32, units_per_em: f32) -> f32 {
        px / units_per_em
    }

======================

I try to adjust the scale factory to fit units_per_em, it seems size equal:

 let text_size = text_size * (font.font().height_unscaled() / font.font().units_per_em().unwrap());

image

======================================= Chrome demo: http://static.takwolf.com/font-test/index.html https://github.com/TakWolf/static.takwolf.com/blob/master/font-test/index.html

ab-glyph demo: https://github.com/TakWolf/tge/blob/feature/ab-glyph/examples/text_layout.rs

alexheretic commented 4 years ago

ab-glyph doesn't use units_per_em for scale, it follows the rusttype method. So using PxScale 24 means the font height will be 24 pixels (I wasn't aware of any better way at the time).

You can just make your own calculation and apply it to scales if you need consistency with something else.

TakWolf commented 4 years ago

Thank yout.

I want to know what is the standard practice? Could I believe rusttype? I can't find a reference and prefer chrome, because it seems more authoritative.


~~Now there is a only way to draw font thar is to use OutlinedGlyph, And OutlinedGlyph have a Glyph(with a scale) How to get a font drawer without hack scale?~~

alexheretic commented 4 years ago

I want to know what is the standard practice? Could I believe rusttype? I can't find a reference and prefer chrome, because it seems more authoritative.

I've raised an issue to discuss this #15. Changing would involve a breaking version increment, but I'd certainly consider it if the new pixel scaling was considerably more "standard".