Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS-compatible font sizing #3271

Open
bdach opened this issue Feb 16, 2020 · 3 comments · May be fixed by #5123
Open

CSS-compatible font sizing #3271

bdach opened this issue Feb 16, 2020 · 3 comments · May be fixed by #5123
Assignees
Labels

Comments

@bdach
Copy link
Collaborator

bdach commented Feb 16, 2020

Recently osu!-side there have been multiple contributions that aimed to bring visuals as close to web as possible. An issue raised during that period was that the numerically-identical font size looked smaller in the game than in web.

Right now, SpriteText & co. work in a way such that a height of 16 will yield a text sprite of the size of precisely 16. While that's what seems reasonable, it's actually not what CSS does:

image

At this point I'll quickly defer to this article explaining how CSS font-size works. Especially relevant is this picture:

which shows that for a font:

  • with a 1000-unit em-square,
  • 680-unit capital height,
  • a 1100-unit ascender,
  • and a 540-unit descender,

the effective text height in pixels of a 100px line is actually 164px.

To see how this relates to how framework handles text, I used the existing SpriteText test scene, Open Sans and FontForge. The metrics for Open Sans are:

  • em-square height: 2048 units,
  • ascender height: 2189 units,
  • descender height: 600 units,
  • capital height: 1462 units.

That means that:

  • the em-square's height is 2048 / (2189 + 600) = ~73.4% effective height of the line,
  • and a capital letter's height is 1462 / (2189 + 600) = ~52.4% effective height of the line.

The measurements in-game seem to indicate that currently the framework is sizing the entire line (ascender to descender) when size is supplied, instead of sizing the em-square:

font-sizing

126 * 52.4% comes down to just over 66 pixels. Measurement is imprecise due to antialiasing. I've only checked this one font, but seems too much of a coincidence if that turned out to be a fluke.

Font size supplied in game was 92, but measured 126 due to an ancestor DrawSizePreservingFillContainer. After adjustment the entire SpriteText should have 126 / 73.4% = ~171 height.

Now, the bad news is, as far as I can see font spacing info comes opaquely through bmfont, and all the dimensions above are font-specific, therefore we'd most likely have to modify bmfont to supply us this info, as it doesn't seem to be there. There is a base attribute in the common tag, but seems to be the ascender-to-baseline measurement, so not what we want here.

It's also not entirely clear what should be done with the ascender and descender sizings. They should be taken into account somehow. The "easiest" way I can see out of this is to make bmfont spit out the numbers needed to make the necessary adjustment (namely, the em-square and ascender + descender heights) and apply sizing adjustment game-side.

I'm aware of the scope and amount of work this could take, and for how little gain it would be. It would probably be nice to have this corrected (as this is probably the more correct, and expected in the eye of consumers, behaviour), but there's way more other important issues to deal with, therefore opening as proposal.

(Also painfully aware this could end up being a big breaking change.)

@bdach
Copy link
Collaborator Author

bdach commented Feb 16, 2020

I began to doubt all of the above, but I figured out a way to capture a better screenshot that seems to confirm my reasoning:

image

Note the following:

  • Firefox devtools applying the 73.4% height adjustment as predicted,
  • Framework size 50 text noticeably smaller than CSS,
  • Framework size 68 text pretty much on par:
    image
  • Test browser window height is 768px, which nullifies effects of the DrawSizePreservingFillContainer and makes device pixels correspond to "framework pixels" below in the hierarchy.

@peppy
Copy link
Sponsor Member

peppy commented Feb 17, 2020

If it's always a constant ratio, we can fix this by applying a scaleAdjust to the font/texture store. This can be done on a per project basis, or at the framework level if we decide that is more correct.

@frenzibyte
Copy link
Member

frenzibyte commented May 16, 2021

It is different between each font, e.g. for the "torus" font:

  • em square = 1000
  • ascender = 1000
  • descender = 200

so the ratio to apply with scaleAdjust will be 100f / 1.2f (100f default scale adjust divided by effective text height / em square), different from "Open Sans" which will have a scaleAdjust of 100f / 1.36f instead.

but that means it can still be done by separating each font family to its font store and calculate the required scale adjustment for them, in an organized way, and potentially move it to a method here in framework.

Though after doing so, all the sprite texts in osu!lazer may need to be revisited as currently the scale adjustment makes things look very off, but is to be expected:

CleanShot 2021-05-16 at 11 59 10

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants