Skip to content

Conversation

EYHN
Copy link
Contributor

@EYHN EYHN commented Jun 26, 2025

This PR continues the work of @Susko3 in #5933, introducing comprehensive Unicode text handling improvements and colored font support. @Susko3's commits are already included in this PR, so only this PR needs to be merged.

I believe this PR is now ready for review. I've attempted to solve most of the major issues, including support for multi-codepoint emoji for flags and TextBox support for emoji. To achieve this, I introduced a new Grapheme structure to replace Rune, and generated emoji resources from noto color emoji. Those changes that I think warrant discussion, so please share your thoughts.

If you want to test the game yourself, please switch to https://github.com/EYHN/osu/tree/eyhn/emoji and use the local framework and resource from ppy/osu-resources#369


This fully emoji support feature is divided into three PRs.

Emoji rendering demonstration

Grapheme Implementation

I introduced the Grapheme struct to represent a single grapheme cluster in Unicode text, efficiently handling both simple char and complex multi-character sequences (like emoji with skin tone modifiers, flags, or characters with combining marks).

The key differences from existing types are:

  • char: Represents a single UTF-16 code unit, insufficient for complex Unicode characters
  • Rune: Represents a Unicode scalar value, but doesn't handle grapheme clusters
  • Grapheme: Represents complete user-perceived characters, including complex clusters

I optimized the Grapheme struct's memory allocation by using direct char storage for common characters and string storage only for complex graphemes, resulting in minimal heap allocations and negligible performance impact.

Performance benchmarks show that using Grapheme instead of char actually improves performance:

Using char (original):

Method Mean Error StdDev
AddCharacters 149.2 μs 1.98 μs 1.85 μs
AddCharactersWithDifferentBaselines 151.9 μs 2.26 μs 2.00 μs
RemoveLastCharacter 148.0 μs 2.20 μs 1.84 μs
RemoveLastCharacterWithDifferentBaselines 161.2 μs 3.21 μs 3.30 μs
AddText 371.1 μs 7.06 μs 8.13 μs

Using Grapheme:

Method Mean Error StdDev
AddCharacters 140.3 μs 1.11 μs 1.04 μs
AddCharactersWithDifferentBaselines 142.4 μs 1.00 μs 0.88 μs
RemoveLastCharacter 141.1 μs 0.55 μs 0.52 μs
RemoveLastCharacterWithDifferentBaselines 143.5 μs 0.56 μs 0.52 μs
AddText 340.2 μs 3.27 μs 2.90 μs

Colored Font Rendering

I added a Coloured property to ITexturedCharacterGlyph. When Coloured == true:

  • Colored font textures are created
  • SpriteText skips tinting during rendering to preserve original colors

Colored font rendering example

TextBox Emoji Support

I refactored TextBox to work with Grapheme instead of string indices. The component now maintains dual state: string text and List<Grapheme> graphemes. I changed nearly all position-based variables to use grapheme positions, ensuring proper handling of complex Unicode characters in text input.

Recording.2025-06-26.134618.mp4

Noto Color Emoji Resources

Resources: Available in ppy/osu-resources#369

Susko3 added 12 commits July 18, 2023 11:06
Only the first test fails, but the second one needs consideration when migrating to Rune.
The bmfont format supports supplementary characters, but we were using `char`
instead of the wider `int`/`Rune` for passing the values around.
The new tests now pass.
The font files were generated with the provided `.bmfc` config
using `bmfont64_1.14b_beta`, and the latest Noto Emoji available
from https://fonts.google.com/noto/specimen/Noto+Emoji.
Can't be fixed without considering the UX of typing, deleting and selecting.
@bdach
Copy link
Collaborator

bdach commented Jun 27, 2025

so is #5933 a prerequisite of this PR or not? because it's very unclear. like you've massacred the history here, it appears you squashed the entirety of that PR into e2f8661? that's not how you're supposed to do any of this

@EYHN
Copy link
Contributor Author

EYHN commented Jun 28, 2025

@bdach Yes, #5933 is already included in this PR.

When i ready for review, I will reorganize the history.

@EYHN EYHN force-pushed the eyhn/emoji branch 3 times, most recently from 28795f9 to a72fc89 Compare July 3, 2025 05:58
@EYHN EYHN marked this pull request as ready for review July 3, 2025 06:59
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 this pull request may close these issues.

3 participants