-
Notifications
You must be signed in to change notification settings - Fork 411
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
Implement CSS-style font size algorithm #5123
base: master
Are you sure you want to change the base?
Conversation
Also renames the field to become `useFullGlyphHeight` to better reflect what it actually does here, also matches with `SpriteText.UseFullGlyphHeight`. If I understand this properly, when setting this to false, it should take the glyph's texture height instead so that text get properly centered, but for some reason it's still including `YOffset` which could leave an empty area at the top of the text.
This one required a bit more work as CSS usually takes the "glyph scale" of the font specified in the `font-family` as far as my manual testing went. I think it should be fine to create a `GetFont` method returning `IGlyphStore`s for that purpose, as it's also required in visual testing to visualise the baseline position in a sprite text.
947a8ff
to
b2370e5
Compare
This doesn't affect the test scene since the scaling is based on the name of the font specified for the `SpriteText`. Same for CSS as far as I've tested.
Why was this done? I think it would have sufficed to test Roboto. |
Just for the sake of adding more into the visualisation test, and also to confirm that the framework’s handling of multiple fonts in one sprite text also matches CSS. |
Co-authored-by: Bartłomiej Dach <dach.bartlomiej@gmail.com>
@@ -167,19 +168,24 @@ private void load(FrameworkConfigManager config) | |||
// note that currently this means there could be two async font load operations. | |||
Fonts.AddStore(localFonts = new FontStore(useAtlas: false)); | |||
|
|||
// Roboto and Font Awesome have different metrics for Windows and macOS. | |||
// The ones used for Windows are used here for the time being. | |||
var robotoMetrics = new FontMetrics(ascent: 1946, descent: 512, emSize: 2048); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be handy to link a guide or something to know how to obtain these. As a developer I'd probably end up here to figure how to add custom fonts, and have little idea how to make these.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have mentioned that in PR description, but I plan to write up a section in the "Fonts" wiki page about metrics and how to extract them from fonts etc.
Indeed it regressed, will look into this immediately... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rest of the code looks fine at a glance, apart from the test not working.
/// The size to draw the glyph at. | ||
/// </summary> | ||
/// <remarks> | ||
/// Note that this can differ per font on one specified <see cref="FontUsage.Size"/>, depending on each one's font metrics. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think sounds better:
For the same <see cref="FontUsage"/> size, this value can differ per-font depending on each font's metrics.
osu.Framework/Text/TextBuilder.cs
Outdated
float size = font.Size; | ||
|
||
if (font.CssScaling && fontStoreGlyph.Metrics is FontMetrics metrics) | ||
size *= metrics.GlyphScale; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be extracted to a separate method, so that it's not duplicated in two places?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you expect something like getGlyphSize(FontUsage font, FontMetrics metrics)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a getGlyphHeight()
. I think everything you need is already part of the class-level variables.
osu.Framework/Text/TextBuilder.cs
Outdated
/// <param name="useFontSizeAsHeight">True to use the provided <see cref="font"/> size as the height for each line. False if the height of each individual glyph should be used.</param> | ||
/// <param name="useFullGlyphHeight">True to use <see cref="TextBuilderGlyph.Size"/> (full glyph size) as the height for each line. False if the height of each individual glyph (<see cref="TextBuilderGlyph.YOffset"/> + <see cref="TextBuilderGlyph.Height"/>) should be used.</param> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think SpriteText
's xmldoc reads better than this one. Possible to replace?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bdach seeing that you struggled to read how this was worded initially (#5123 (comment)), what's your opinion on rewording this once again as suggested above, i.e.:
- /// <param name="useFullGlyphHeight">True to use <see cref="TextBuilderGlyph.Size"/> (full glyph size) as the height for each line. False if the height of each individual glyph (<see cref="TextBuilderGlyph.YOffset"/> + <see cref="TextBuilderGlyph.Height"/>) should be used.</param>
+ /// <param name="useFullGlyphHeight">
+ /// True if the <see cref="TextBuilder"/>'s vertical bounds should be equal to the maximum full height of the glyphs (constant per font).
+ /// False to consider the maximum texture height of each individual glyph instead.
+ /// </param>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's marginally better I guess. It still confuses me that "full height of the glyphs" is mentioned in one place and "height of each individual glyph" is in the other. The difference feels extremely subtle.
If I were to propose something then it'd probably be something along the lines of
/// <param name="useFullGlyphHeight">
/// When true, all texts that use a particular font will have a constant height, regardless of the letters used.
/// When false, the height of a given text will be cropped to only fit the letters used in that particular text,
/// and extra space above and below letters will be trimmed.
/// </param>
Apparently the test scene regressed because of 78d32b6 and I swear it wasn't broken to me the moment I tested it... That commit was changing the metrics values to use the ones which Windows respects (typo), but the text images provided were taken on macOS (hhea), therefore causing this discrepancy. The metrics provided by Windows lead to CSS scale of 1x ( |
Well this is disconcerting, are you saying this can differ per-platform somehow, too? I would hope not... |
Well, some fonts render differently on browsers in Windows and macOS, due to there existing different metrics tables (most of the time the same values will be used on all metrics, but some fonts like
It is up for the framework consumer to decide whether they want their font to be rendered correctly based on the running platform (using For osu!, I think it may be best sticking to the Typo table, but we can consider rendering per-platform correctly if we want to. Just a matter of supplying the font with the correct metric values. |
I think I'm just going to pretend I didn't ask and nod along. This is a rabbit hole the depths of which I do not dare to explore. |
For reference I found the relevant platform specific hacks that Chrome uses: https://github.com/chromium/chromium/blob/76769a9d7e911b4efa1fab3cc6e1b5df86f3d227/third_party/blink/renderer/platform/fonts/simple_font_data.cc#L88-L179 |
Adds support for CSS-style font sizing, allowing for our sprite text sizes to match 1:1 with CSS.
As a starting point, the option is disabled by default to avoid breaking every existing sprite text in all games, but as we move forward (with migrating to new designs in osu!), we'll want to make the option enabled by default, and potentially remove the option (keeping it only based on whether the font's metrics are available).
For reviewing ease, I'll recommend going commit-by-commit as the overall diff is a bit messy to read through (mainly because of the addition of
FontMetrics
, addition ofFontUsage.CssScaling
, and addition of note font for testing purposes).FontMetrics
Since the font binaries don't store metadata about the metrics (ascent, descent, em size), it is required for osu! and all consumers of the framework to manually extract them from the font and specify them in
AddFont
, similar to how it's done here:Note that different platforms use different metric tables, and I'm not entirely sure if we should use each metric based on the platform, as it turns out there can be differences. Therefore I continued with the one used by Windows.
This is still completely up to the consumer whether they want it to be platform-specific or not, but just mentioning this in regards to osu!.
I've kept the font metrics argument in
AddFont
as optional, for special fonts which don't have the concept of "font metrics" ("8-bit" fonts and the like).I will write up more about this in the fonts wiki if the
FontMetrics
concept is agreed on, mainly about how to extract them and which values should be used, etc.FontUsage.CssScaling
Going forward, osu! and all consumers should always append
css: true
to their font usages, potentially using a different static and prefixing the old non-CSS ones withOld
:It could also go the other way around, by keeping the old one as-is, and defining a
New
font withcss: true
applied instead.I've added behavioural test coverage, and also added a visual illustration in the sprite text test scene, by comparing against a picture of a CSS text element with an equal font size, in a properly aligned container:
Have also added sprite texts with CSS-style enabled, alongside the pre-existing non-CSS ones: