RazrFalcon / rustybuzz

A complete harfbuzz's shaping algorithm port to Rust
MIT License
498 stars 34 forks source link

In what units are GylphPositions? #33

Closed TonalidadeHidrica closed 10 months ago

TonalidadeHidrica commented 3 years ago

After shaping, we can obtain GlyphPosition for each glyph. However, I can't figure out what coordinate unit it uses. The positions are proportional to what it supposed to be, but I don't know the actual ratio and its rationale.

Also, is there a way to set the font size before the shaping process? In original HarfBuzz, we can do it via hb_font_set_ppem (as described here). Integrated with FreeType, HarfBuzz reads the font size in FreeType font struct when hb_ft_font_create-ing. But I could not find the corresponding method in rustybuzz::Face struct. set_points_per_em did not work, as it does not change the values of GlyphPositions. (Specifically, I ran example/shape.rs, but enabling or disabling the option did not affect the output.) So how can I do that? Do I have to scale the coordinates manually according to what font size I need? In such case I need the scaling factor, as I stated at first. Or am I missing something?

RazrFalcon commented 3 years ago

Values are in font units, aka units per EM (ttf_parser::Face::units_per_em). You can get the scale factor like this: font-size-in-px / units-per-em and the multiply each value by this factor.

The is no way to set font size in the moment. I will add it in the future.

TonalidadeHidrica commented 3 years ago

Thank you! Do we need to parse the binary font file once again to obtain ttf_parse::Face instance? Or is there a way to convert it from rustybuzz::Face?

RazrFalcon commented 3 years ago

Yes, for now you have to parse it again, but it's pretty cheap in case of ttf-parser.

TonalidadeHidrica commented 3 years ago

Just out of curiosity, what do set_pixels_per_em and set_points_per_em do? It seems they does not change the outcome.

laurmaedje commented 3 years ago

It's used for hinting and tracking, which not every font will support.

TonalidadeHidrica commented 3 years ago

@laurmaedje I see, thanks for your information. @RazrFalcon I tested the ratio and it worked like a charm! Thank you.

Should I close the issue or leave it open until "set font size" feature is added?

RazrFalcon commented 3 years ago

No, keep it open. I will add it later.

mainrs commented 1 year ago

Values are in font units, aka units per EM (ttf_parser::Face::units_per_em). You can get the scale factor like this: font-size-in-px / units-per-em and the multiply each value by this factor.

The is no way to set font size in the moment. I will add it in the future.

So if I want to typeset some text using Font A, I would have to parse the font and get the face I want, store the units_per_em in a variable, get the glyphs for my text, calculate the ratio by which I have to scale x_actual and y_actual and then multiply these values with the ratio. That should be my final position. These values are then in pixels, right?

I am having trouble to get the right values since I want to render the glyphs into a PDF. And that PDF takes points as its coordinates.

RazrFalcon commented 1 year ago

There are no pixels in fonts, since they are vector and not raster. All you can do is to scale them by whatever factor you want/need.

Let's say your font has units-per-em set to 2048. Those are points. If you want to render them 1:1 then you will need 2048x2048 pixels canvas. By scaling everything down you can fit it into whatever canvas you want.

As for PDF, it uses units-per-em as well. The only difference it that some values are in default PDF units (1000) and some are in font units (units-per-em).

As for rustybuzz and ttf-parser, they operate in font units. Meaning they do not scale anything.