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

Align TextBuilder characters by their baselines during addition/removal #4774

Merged
merged 8 commits into from
Sep 16, 2021

Conversation

frenzibyte
Copy link
Member

Previously characters were implicitly aligned using their YOffsets, and that works when only one font is used, but not when more than one font gets used inside one SpriteText/TextBuilder.

This PR aims to resolve the "multiple fonts" case by offsetting their DrawRectangles based on the difference between the Baseline of the new character and the previous characters.

I've worked on this initially so that font-mixed sprite texts with #3271 don't look badly misaligned (as I noticed after implementing #3271), but apparently, there are already alignment improvements osu!-side with this PR alone (although slightly unnoticable):

  • Before:
    image

  • After:
    image

(notice (TV Size) aligned correctly with the other glyphs)

I have added in-depth test coverage in TextBuilderTest which had the perfect setup for having so, with all possible scenarios I can think of.

Along with test coverage, I've also added a benchmark including the regular "no baseline adjustment" cases, and "one baseline adjustment every 10 characters" case, and the results seem reasonable.

Method Mean Error StdDev
AddCharacters 19.99 us 0.280 us 0.323 us
AddCharactersWithDifferentBaselines 31.02 us 0.219 us 0.183 us
RemoveLastCharacter 24.90 us 0.493 us 0.506 us
RemoveLastCharacterWithDifferentBaselines 38.14 us 0.570 us 0.505 us

I can see this being further optimised by offseting new characters to negative X/Ys rather than offsetting all the other previous characters in the line, but that might be a bit complicated to deal with in the SpriteText_DrawNode (especially given that TextBuilder can have multiple lines), therefore I've went with the simplest way of for looping all characters in the line for now.

Copy link
Contributor

@smoogipoo smoogipoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks solid. As I mentioned in discord, we probably want to rework TextBuilder altogether to improve performance - having everything done in-line in AddCharacter/RemoveCharacter is not good, but that goes for everything else as well.

@smoogipoo smoogipoo merged commit 051b8ef into ppy:master Sep 16, 2021
@peppy
Copy link
Member

peppy commented Sep 16, 2021

this is missing a breaking change clause for the updated method signature, will add.

@peppy
Copy link
Member

peppy commented Sep 16, 2021

Actually there's quite a few changes, just going to leave it. All mostly internal stuff so I don't think too many people will be hit by it.

@frenzibyte frenzibyte deleted the text-builder-baseline-alignment branch September 16, 2021 12:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants